Skip to content

Commit 8c2b458

Browse files
committed
Change the force feedback driver to use mach_absolute_time instead of CFAbsoluteTimeGetCurrent.
Fixes 360Controller#70
1 parent d3fef4f commit 8c2b458

File tree

5 files changed

+32
-16
lines changed

5 files changed

+32
-16
lines changed

360 Driver.xcodeproj/project.pbxproj

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,6 @@
297297
55E1C62819708E7300EC9DD8 /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = SOURCE_ROOT; };
298298
55E1C62919708E7300EC9DD8 /* clean.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = clean.sh; sourceTree = SOURCE_ROOT; };
299299
55E1C62A19708F8600EC9DD8 /* Readme.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = Readme.md; sourceTree = SOURCE_ROOT; };
300-
55E1C62B1970921E00EC9DD8 /* Readme.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = Readme.rtf; sourceTree = SOURCE_ROOT; };
301300
55FE3CA118D7B77800D69E84 /* testhaptic */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testhaptic; sourceTree = BUILT_PRODUCTS_DIR; };
302301
55FE3CAC18D7B7B600D69E84 /* SDL2.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDL2.framework; path = /Library/Frameworks/SDL2.framework; sourceTree = "<absolute>"; };
303302
/* End PBXFileReference section */
@@ -402,7 +401,6 @@
402401
isa = PBXGroup;
403402
children = (
404403
55E1C62A19708F8600EC9DD8 /* Readme.md */,
405-
55E1C62B1970921E00EC9DD8 /* Readme.rtf */,
406404
551CE004196EFD34000869B6 /* Welcome.rtf */,
407405
);
408406
path = Text;

Feedback360/Feedback360.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,27 @@
2424
*/
2525

2626
#include "Feedback360.h"
27+
#include <mach/mach.h>
28+
#include <mach/mach_time.h>
2729
using std::max;
2830
using std::min;
2931

3032
#define LoopGranularity 10000 // Microseconds
3133

34+
double CurrentTimeUsingMach()
35+
{
36+
mach_timebase_info_data_t info = {0};
37+
if (mach_timebase_info(&info) != KERN_SUCCESS) {
38+
//FIXME: why would this fail/set to fail more gracefully.
39+
return -1.0;
40+
}
41+
42+
uint64_t start = mach_absolute_time();
43+
44+
uint64_t nanos = start * info.numer / info.denom;
45+
return (double)nanos / NSEC_PER_SEC;
46+
}
47+
3248
static IOCFPlugInInterface functionMap360_IOCFPlugInInterface = {
3349
// Padding required for COM
3450
NULL,
@@ -186,7 +202,7 @@ HRESULT Feedback360::StartEffect(FFEffectDownloadID EffectHandle, FFEffectStartF
186202
{
187203
effectIterator->Status = FFEGES_PLAYING;
188204
effectIterator->PlayCount = Count;
189-
effectIterator->StartTime = CFAbsoluteTimeGetCurrent();
205+
effectIterator->StartTime = CurrentTimeUsingMach();
190206
Stopped = false;
191207
} else {
192208
if (Mode & FFES_SOLO) {
@@ -336,7 +352,7 @@ HRESULT Feedback360::DownloadEffect(CFUUIDRef EffectType, FFEffectDownloadID *Ef
336352
{
337353
Effect->Status = FFEGES_PLAYING;
338354
Effect->PlayCount = 1;
339-
Effect->StartTime = CFAbsoluteTimeGetCurrent();
355+
Effect->StartTime = CurrentTimeUsingMach();
340356
}
341357

342358
if( Flags & FFEP_NORESTART )
@@ -438,13 +454,13 @@ HRESULT Feedback360::SendForceFeedbackCommand(FFCommandFlag state)
438454

439455
case FFSFFC_PAUSE:
440456
Paused = true;
441-
PausedTime = CFAbsoluteTimeGetCurrent();
457+
PausedTime = CurrentTimeUsingMach();
442458
break;
443459

444460
case FFSFFC_CONTINUE:
445461
for (Feedback360EffectIterator effectIterator = EffectList.begin() ; effectIterator != EffectList.end(); ++effectIterator)
446462
{
447-
effectIterator->StartTime += ( CFAbsoluteTimeGetCurrent() - PausedTime );
463+
effectIterator->StartTime += ( CurrentTimeUsingMach() - PausedTime );
448464
}
449465
Paused = false;
450466
break;
@@ -591,7 +607,7 @@ void Feedback360::EffectProc( void *params )
591607
{
592608
for (Feedback360EffectIterator effectIterator = cThis->EffectList.begin(); effectIterator != cThis->EffectList.end(); ++effectIterator)
593609
{
594-
if((CFAbsoluteTimeGetCurrent() - cThis->LastTime*1000*1000) >= effectIterator->DiEffect.dwSamplePeriod) {
610+
if((CurrentTimeUsingMach() - cThis->LastTime*1000*1000) >= effectIterator->DiEffect.dwSamplePeriod) {
595611
CalcResult = effectIterator->Calc(&LeftLevel, &RightLevel);
596612
}
597613
}

Feedback360/Feedback360.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ class Feedback360 : IUnknown
114114
bool Stopped;
115115
bool Paused;
116116
bool Manual;
117-
CFAbsoluteTime LastTime;
118-
CFAbsoluteTime PausedTime;
117+
double LastTime;
118+
double PausedTime;
119119
CFUUIDRef FactoryID;
120120

121121
void SetForce(LONG LeftLevel, LONG RightLevel);

Feedback360/Feedback360Effect.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,13 @@ LONG Feedback360Effect::Calc(LONG *LeftLevel, LONG *RightLevel)
6565
} else {
6666
Duration = DBL_MAX;
6767
}
68-
CFAbsoluteTime BeginTime = StartTime + ( DiEffect.dwStartDelay / 1000. / 1000.);
69-
CFAbsoluteTime EndTime = DBL_MAX;
68+
double BeginTime = StartTime + ( DiEffect.dwStartDelay / 1000. / 1000.);
69+
double EndTime = DBL_MAX;
7070
if (PlayCount != -1)
7171
{
7272
EndTime = BeginTime + Duration * PlayCount;
7373
}
74-
CFAbsoluteTime CurrentTime = CFAbsoluteTimeGetCurrent();
74+
double CurrentTime = CurrentTimeUsingMach();
7575

7676
if (Status == FFEGES_PLAYING && BeginTime <= CurrentTime && CurrentTime <= EndTime)
7777
{
@@ -93,15 +93,15 @@ LONG Feedback360Effect::Calc(LONG *LeftLevel, LONG *RightLevel)
9393

9494
// CustomForce allows setting each channel separately
9595
if(CFEqual(Type, kFFEffectType_CustomForce_ID)) {
96-
if((CFAbsoluteTimeGetCurrent() - LastTime)*1000*1000 < DiCustomForce.dwSamplePeriod) {
96+
if((CurrentTimeUsingMach() - LastTime)*1000*1000 < DiCustomForce.dwSamplePeriod) {
9797
return -1;
9898
}
9999
else {
100100
WorkLeftLevel = ((DiCustomForce.rglForceData[2*Index] * NormalRate + AttackLevel + FadeLevel) / 100) * DiEffect.dwGain / 10000;
101101
WorkRightLevel = ((DiCustomForce.rglForceData[2*Index + 1] * NormalRate + AttackLevel + FadeLevel) / 100) * DiEffect.dwGain / 10000;
102102
//fprintf(stderr, "L:%d; R:%d\n", WorkLeftLevel, WorkRightLevel);
103103
Index = (Index + 1) % (DiCustomForce.cSamples/2);
104-
LastTime = CFAbsoluteTimeGetCurrent();
104+
LastTime = CurrentTimeUsingMach();
105105
}
106106
}
107107
// Regular commands treat controller as a single output (both channels are together as one)

Feedback360/Feedback360Effect.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@
5353

5454
#define SCALE_MAX (LONG)255
5555

56+
double CurrentTimeUsingMach();
57+
5658
class Feedback360Effect
5759
{
5860
public:
@@ -73,9 +75,9 @@ class Feedback360Effect
7375

7476
DWORD Status;
7577
DWORD PlayCount;
76-
CFAbsoluteTime StartTime;
78+
double StartTime;
7779

78-
CFAbsoluteTime LastTime;
80+
double LastTime;
7981
DWORD Index;
8082

8183
private:

0 commit comments

Comments
 (0)