int prTempoClock_SetTempoAtBeat(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } double tempo, beat; int err = slotDoubleVal(b, &tempo); if (err) return errFailed; if (tempo <= 0.) { error("invalid tempo %g\n", tempo); return errFailed; } err = slotDoubleVal(c, &beat); if (err) return errFailed; clock->SetTempoAtBeat(tempo, beat); return errNone; }
int prTempoClock_Sched(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double delta, beats; int err; TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } if (!SlotEq(&g->thread->clock, a)) { beats = clock->ElapsedBeats(); //post("shouldn't call TempoClock-sched from a different clock. Use schedAbs.\n"); //return errFailed; } else { err = slotDoubleVal(&g->thread->beats, &beats); if (err) return errNone; // return nil OK, just don't schedule } err = slotDoubleVal(b, &delta); if (err) return errNone; // return nil OK, just don't schedule beats += delta; if (beats == dInfinity) return errNone; // return nil OK, just don't schedule clock->Add(beats, c); return errNone; }
int mathFoldInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_fold(slotRawInt(a), slotRawInt(b), slotRawInt(c))); } else { double x, lo, hi; x = slotRawInt(a); err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_fold(x, lo, hi)); } return errNone; }
int prTempoClock_New(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 3; PyrSlot *b = g->sp - 2; PyrSlot *c = g->sp - 1; PyrSlot *d = g->sp; double tempo; int err = slotDoubleVal(b, &tempo); if (err) tempo = 1.; if (tempo <= 0.) { error("invalid tempo %g\n", tempo); SetPtr(slotRawObject(a)->slots+1, NULL); return errFailed; } double beats; err = slotDoubleVal(c, &beats); if (err) beats = 0.; double seconds; err = slotDoubleVal(d, &seconds); if (err) seconds = elapsedTime(); TempoClock* clock = new TempoClock(g, slotRawObject(a), tempo, beats, seconds); SetPtr(slotRawObject(a)->slots+1, clock); return errNone; }
int prTempoClock_SetAll(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 3; PyrSlot *b = g->sp - 2; PyrSlot *c = g->sp - 1; PyrSlot *d = g->sp; TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } double tempo, beat, secs; int err = slotDoubleVal(b, &tempo); if (err) return errFailed; err = slotDoubleVal(c, &beat); if (err) return errFailed; err = slotDoubleVal(d, &secs); if (err) return errFailed; clock->SetAll(tempo, beat, secs); return errNone; }
int mathWrapInt(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else if (IsInt(b) && IsInt(c)) { SetRaw(a, sc_mod((int)(slotRawInt(a) - slotRawInt(b)), (int)(slotRawInt(c) - slotRawInt(b) + 1)) + slotRawInt(b)); } else { double x, lo, hi; x = slotRawInt(a); err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetFloat(a, sc_mod(x - lo, hi - lo) + lo); } return errNone; }
int prSignalAddHarmonic(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c, *d; int err; float harmonic, amp; double phase, step; PyrObject *signal; float *out; a = g->sp - 3; b = g->sp - 2; c = g->sp - 1; d = g->sp; err = slotFloatVal(b, &harmonic); if (err) return errWrongType; err = slotFloatVal(c, &); if (err) return errWrongType; err = slotDoubleVal(d, &phase); if (err) return errWrongType; signal = slotRawObject(a); out = (float*)(signal->slots) - 1; step = twopi * harmonic / signal->size; UNROLL_CODE(signal->size, out, *++out += sin(phase) * amp; phase += step; );
int makeSynthBundle(big_scpacket *packet, PyrSlot *slots, int size, bool useElapsed) { double time; int err; int64 oscTime; err = slotDoubleVal(slots, &time); if (!err) { if (useElapsed) { oscTime = ElapsedTimeToOSC(time); } else { oscTime = (int64)(time * kSecondsToOSC); } } else { oscTime = 1; // immediate } packet->OpenBundle(oscTime); for (int i=1; i<size; ++i) { if (isKindOfSlot(slots+i, class_array)) { PyrObject *obj = slots[i].uo; makeSynthMsgWithTags(packet, obj->slots, obj->size); } } packet->CloseBundle(); return errNone; }
bool SC_LanguageClient::tickLocked( double * nextTime ) { if (isLibraryCompiled()) { ::runLibrary(s_tick); } return slotDoubleVal( &gMainVMGlobals->result, nextTime ) == errNone; }
int prSystemClock_Sched(struct VMGlobals *g, int numArgsPushed) { //PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double delta, seconds; int err = slotDoubleVal(b, &delta); if (err) return errNone; // return nil OK, just don't schedule err = slotDoubleVal(&g->thread->seconds, &seconds); if (err) return errNone; // return nil OK, just don't schedule seconds += delta; if (seconds == dInfinity) return errNone; // return nil OK, just don't schedule PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue); schedAdd(g, inQueue, seconds, c); return errNone; }
int prPriorityQueuePostpone(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 1; // priority queue PyrSlot *b = g->sp; // time double time; int err = slotDoubleVal(b, &time); if (err) return err; PyrObject *queueobj = slotRawObject(a); PriorityQueuePostpone(queueobj, time); return errNone; }
int prEvent_Delta(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, key, dur, stretch, delta; double fdur, fstretch; int err; a = g->sp; // dict SetSymbol(&key, s_delta); identDict_lookup(slotRawObject(a), &key, calcHash(&key), &delta); if (NotNil(&delta)) { slotCopy(a,&delta); } else { SetSymbol(&key, s_dur); identDict_lookup(slotRawObject(a), &key, calcHash(&key), &dur); err = slotDoubleVal(&dur, &fdur); if (err) { if (NotNil(&dur)) return err; SetNil(a); return errNone; } SetSymbol(&key, s_stretch); identDict_lookup(slotRawObject(a), &key, calcHash(&key), &stretch); err = slotDoubleVal(&stretch, &fstretch); if (err) { if (NotNil(&stretch)) return err; SetFloat(a, fdur); return errNone; } SetFloat(a, fdur * fstretch ); } return errNone; }
int prTempoClock_Beats(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp; double beats, seconds; if (SlotEq(&g->thread->clock, a)) { int err = slotDoubleVal(&g->thread->beats, &beats); if (err) return errWrongType; } else { TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } int err = slotDoubleVal(&g->thread->seconds, &seconds); if (err) return errWrongType; beats = clock->SecsToBeats(seconds); } SetFloat(a, beats); return errNone; }
int prPriorityQueueAdd(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; // priority queue PyrSlot *b = g->sp - 1; // time PyrSlot *c = g->sp; // item double time; int err = slotDoubleVal(b, &time); if (err) return errNone; // nil is OK, nothing gets added PriorityQueueAdd(g, slotRawObject(a), c, time); return errNone; }
int mathWrapFloat(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b, *c; double lo, hi; int err; a = g->sp - 2; b = g->sp - 1; c = g->sp; if (IsSym(b)) { *a = *b; } else if (IsSym(c)) { *a = *c; } else { err = slotDoubleVal(b, &lo); if (err) return err; err = slotDoubleVal(c, &hi); if (err) return err; SetRaw(a, sc_mod(slotRawFloat(a) - lo, hi - lo) + lo); } return errNone; }
int prSetSpeechVolume(struct VMGlobals *g, int numArgsPushed) { OSErr theErr = noErr; //PyrSlot *a = g->sp-2; PyrSlot *b = g->sp-1; PyrSlot *c = g->sp; double val; int chan; slotIntVal(b, &chan); slotDoubleVal(c, &val); Fixed newVal = (Fixed)(val * 65536.0); // if(!fCurSpeechChannel) theErr = NewSpeechChannel( NULL, &fCurSpeechChannel ); theErr = SetSpeechInfo (fCurSpeechChannel[chan], soVolume, &newVal); return errNone; }
int prSystemClock_SchedAbs(struct VMGlobals *g, int numArgsPushed) { //PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double time; int err = slotDoubleVal(b, &time) || (time == dInfinity); if (err) return errNone; // return nil OK, just don't schedule PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue); schedAdd(g, inQueue, time, c); return errNone; }
int prHIDRunEventLoop(VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 1; //class PyrSlot *b = g->sp; //num double eventtime; int err = slotDoubleVal(b, &eventtime); if (err) return err; if(gTimer) { RemoveEventLoopTimer(gTimer); gTimer = NULL; } InstallEventLoopTimer (GetCurrentEventLoop(), 0, (EventTimerInterval) eventtime, GetTimerUPP (), 0, &gTimer); //HIDSetQueueCallback(pCurrentHIDDevice, callback); return errNone; }
int prNetAddr_SendBundle(VMGlobals *g, int numArgsPushed) { PyrSlot* netAddrSlot = g->sp - numArgsPushed + 1; PyrSlot* args = netAddrSlot + 1; big_scpacket packet; double time; int err = slotDoubleVal(args, &time); if (!err) { time += g->thread->seconds.uf; SetFloat(args, time); } int numargs = numArgsPushed - 1; makeSynthBundle(&packet, args, numargs, true); //for (int i=0; i<packet.size()/4; i++) post("%d %08X\n", i, packet.buf[i]); return netAddrSend(netAddrSlot->uo, packet.size(), (char*)packet.buf); }
int prTempoClock_SecsToBeats(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 1; PyrSlot *b = g->sp; TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } double secs; int err = slotDoubleVal(b, &secs); if (err) return errFailed; SetFloat(a, clock->SecsToBeats(secs)); return errNone; }
int prTempoClock_SchedAbs(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; TempoClock *clock = (TempoClock*)slotRawPtr(&slotRawObject(a)->slots[1]); if (!clock) { error("clock is not running.\n"); return errFailed; } double beats; int err = slotDoubleVal(b, &beats) || (beats == dInfinity); if (err) return errNone; // return nil OK, just don't schedule clock->Add(beats, c); return errNone; }
int prFilePutDoubleLE(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, *b; PyrFile *pfile; FILE *file; a = g->sp - 1; b = g->sp; pfile = (PyrFile*)slotRawObject(a); file = (FILE*)slotRawPtr(&pfile->fileptr); if (file == NULL) return errFailed; double val; int err = slotDoubleVal(b, &val); if (err) return err; SC_IOStream<FILE*> scio(file); scio.writeDouble_le(val); return errNone; }
int prAsFraction(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; double mediant_num, lower_num, upper_num, temp_num; double mediant_den, lower_den, upper_den, temp_den; double x, d; int k, k1; int maxDenominator; int err; bool neg = false; err = slotDoubleVal(a, &x); if (err) return err; err = slotIntVal(b, &maxDenominator); if (err) return err; bool faster = IsTrue(c); PyrObject *obj = newPyrArray(g->gc, 2, 0, true); obj->size = 2; PyrSlot *slots = obj->slots; SetObject(a, obj); if (x < 0.0) { x = -x; neg = true; } if (x < 1.0) { upper_num = 1.0; upper_den = floor(1./x); lower_num = 1.0; lower_den = upper_den + 1.; } else { lower_num = floor(x); lower_den = 1.0; upper_num = lower_num + 1.; upper_den = 1.0; } while (true) { mediant_num = lower_num + upper_num; mediant_den = lower_den + upper_den; //post(" md %g %g %g %g %g %g\n", mediant_num, mediant_den, lower_num, lower_den, upper_num, upper_den); if (x * mediant_den > mediant_num) { d = upper_num - (x * upper_den); if (maxDenominator < mediant_den || fabs(d) < 1e-5) { if (neg) upper_num = -upper_num; SetInt(slots+0, (int)upper_num); SetInt(slots+1, (int)upper_den); return errNone; } lower_num = mediant_num; lower_den = mediant_den; if (faster) { k = (int)floor(((x * lower_den) - lower_num) / d); if (k < 10000) { k1 = k + 1; temp_num = lower_num + (k1 * upper_num); temp_den = lower_den + (k1 * upper_den); lower_num = lower_num + (k * upper_num); lower_den = lower_den + (k * upper_den); upper_num = temp_num; upper_den = temp_den; } } } else if (x * mediant_den == mediant_num) { if (maxDenominator >= mediant_den) { if (neg) mediant_num = -mediant_num; SetInt(slots+0, (int)mediant_num); SetInt(slots+1, (int)mediant_den); return errNone; } else if (lower_den < upper_den) { if (neg) lower_num = -lower_num; SetInt(slots+0, (int)lower_num); SetInt(slots+1, (int)lower_den); return errNone; } else { if (neg) upper_num = -upper_num; SetInt(slots+0, (int)upper_num); SetInt(slots+1, (int)upper_den); return errNone; } } else { d = lower_num - (x * lower_den); if (maxDenominator < mediant_den || fabs(d) < 1e-5) { if (neg) lower_num = -lower_num; SetInt(slots+0, (int)lower_num); SetInt(slots+1, (int)lower_den); return errNone; } upper_num = mediant_num; upper_den = mediant_den; if (faster) { k = (int)floor(((x * upper_den) - upper_num) / d); if (k < 10000) { k1 = k + 1; temp_num = (k1 * lower_num) + upper_num; temp_den = (k1 * lower_den) + upper_den; upper_num = (k * lower_num) + upper_num; upper_den = (k * lower_den) + upper_den; lower_num = temp_num; lower_den = temp_den; } } } } }
int prSimpleNumberSeries(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a = g->sp - 2; PyrSlot *b = g->sp - 1; PyrSlot *c = g->sp; int err, size; if (IsInt(a) && (IsInt(b) || IsNil(b)) && IsInt(c)) { int first, second, last, step; first = slotRawInt(a); last = slotRawInt(c); second = IsInt(b) ? slotRawInt(b) : (first < last ? first + 1 : first - 1); step = second - first; if ( step == 0 ) size = 1; else size = ((last - first) / step) + 1; if(size<1 || size > INT_MAX_BY_PyrSlot){ post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot); return errFailed; } PyrObject *obj = newPyrArray(g->gc, size, 0, true); obj->size = size; PyrSlot *slots = obj->slots; if(step==1){ // Faster iteration for common case if(first==0){ for (int i=0; i<size; ++i) { SetInt(slots+i, i); } }else{ for (int i=0; i<size; ++i) { SetInt(slots+i, first++); } } }else{ int val = first; for (int i=0; i<size; ++i) { SetInt(slots+i, val); val += step; } } SetObject(a, obj); } else { double first, second, last, step; err = slotDoubleVal(a, &first); if (err) return err; err = slotDoubleVal(c, &last); if (err) return err; err = slotDoubleVal(b, &second); if (err) { if (first < last) second = first + 1.; else second = first - 1.; } step = second - first; size = (int)floor((last - first) / step + 0.001) + 1; if(size<1 || size > INT_MAX_BY_PyrSlot){ post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot); return errFailed; } PyrObject *obj = newPyrArray(g->gc, size, 0, true); obj->size = size; PyrSlot *slots = obj->slots; if(first==0. && step==1.){ // Faster iteration for common case for (long i=0; i<size; ++i) { SetFloat(slots+i, i); } }else{ double val = first; for (long i=0; i<size; ++i) { val = first + step * i; SetFloat(slots+i, val); } } SetObject(a, obj); } return errNone; }
int prEvent_Delta(struct VMGlobals *g, int numArgsPushed) { PyrSlot *a, key, dur, stretch, delta; double fdur, fstretch; int err; PyrClass *restClass = getsym("Rest")->u.classobj; PyrSlot *slot; a = g->sp; // dict SetSymbol(&key, s_delta); identDict_lookup(slotRawObject(a), &key, calcHash(&key), &delta); if (NotNil(&delta)) { if (isKindOfSlot(&delta, restClass)) { slot = slotRawObject(&delta)->slots; err = slotDoubleVal(slot, &fdur); } else { err = slotDoubleVal(&delta, &fdur); } if (err) { return err; } else { SetFloat(a, fdur); return errNone; } } else { SetSymbol(&key, s_dur); identDict_lookup(slotRawObject(a), &key, calcHash(&key), &dur); err = slotDoubleVal(&dur, &fdur); if (err) { if (IsNil(&dur)) { SetNil(g->sp); return errNone; } else if (isKindOfSlot(&dur, restClass)) { slot = slotRawObject(&dur)->slots; err = slotDoubleVal(slot, &fdur); if (err) return err; } else { return errWrongType; } } SetSymbol(&key, s_stretch); identDict_lookup(slotRawObject(a), &key, calcHash(&key), &stretch); err = slotDoubleVal(&stretch, &fstretch); if (err) { if (NotNil(&stretch)) { if (isKindOfSlot(&stretch, restClass)) { slot = slotRawObject(&stretch)->slots; err = slotDoubleVal(slot, &fstretch); if (err) return err; } else { return errWrongType; } } else { SetFloat(a, fdur); return errNone; } } SetFloat(a, fdur * fstretch); } return errNone; }
static double safeRead( PyrSlot *slot ) { double val; if (slotDoubleVal(slot, &val)) return 0.0; return val; }
void* schedRunFunc(void* arg) { pthread_mutex_lock (&gLangMutex); VMGlobals *g = gMainVMGlobals; PyrObject* inQueue = slotRawObject(&g->process->sysSchedulerQueue); //dumpObject(inQueue); gRunSched = true; while (true) { assert(inQueue->size); //postfl("wait until there is something in scheduler\n"); // wait until there is something in scheduler while (inQueue->size == 1) { //postfl("wait until there is something in scheduler\n"); pthread_cond_wait (&gSchedCond, &gLangMutex); if (!gRunSched) goto leave; } //postfl("wait until an event is ready\n"); // wait until an event is ready double elapsed; do { elapsed = elapsedTime(); if (elapsed >= slotRawFloat(inQueue->slots + 1)) break; struct timespec abstime; //doubleToTimespec(inQueue->slots->uf, &abstime); ElapsedTimeToTimespec(slotRawFloat(inQueue->slots + 1), &abstime); //postfl("wait until an event is ready\n"); pthread_cond_timedwait (&gSchedCond, &gLangMutex, &abstime); if (!gRunSched) goto leave; //postfl("time diff %g\n", elapsedTime() - inQueue->slots->uf); } while (inQueue->size > 1); //postfl("perform all events that are ready %d %.9f\n", inQueue->size, elapsed); // perform all events that are ready //postfl("perform all events that are ready\n"); while ((inQueue->size > 1) && elapsed >= slotRawFloat(inQueue->slots + 1)) { double schedtime, delta; PyrSlot task; //postfl("while %.6f >= %.6f\n", elapsed, inQueue->slots->uf); getheap(g, inQueue, &schedtime, &task); if (isKindOfSlot(&task, class_thread)) { SetNil(&slotRawThread(&task)->nextBeat); } slotCopy((++g->sp), &task); SetFloat(++g->sp, schedtime); SetFloat(++g->sp, schedtime); ++g->sp; SetObject(g->sp, s_systemclock->u.classobj); runAwakeMessage(g); long err = slotDoubleVal(&g->result, &delta); if (!err) { // add delta time and reschedule double time = schedtime + delta; schedAdd(g, inQueue, time, &task); } } //postfl("loop\n"); } //postfl("exitloop\n"); leave: pthread_mutex_unlock (&gLangMutex); return 0; }
void* TempoClock::Run() { //printf("->TempoClock::Run\n"); pthread_mutex_lock (&gLangMutex); while (mRun) { assert(mQueue->size); //printf("tempo %g dur %g beats %g\n", mTempo, mBeatDur, mBeats); //printf("wait until there is something in scheduler\n"); // wait until there is something in scheduler while (mQueue->size == 1) { //printf("wait until there is something in scheduler\n"); pthread_cond_wait (&mCondition, &gLangMutex); //printf("mRun a %d\n", mRun); if (!mRun) goto leave; } //printf("wait until an event is ready\n"); // wait until an event is ready double elapsedBeats; do { elapsedBeats = ElapsedBeats(); if (elapsedBeats >= slotRawFloat(mQueue->slots)) break; struct timespec abstime; //doubleToTimespec(mQueue->slots->uf, &abstime); //printf("event ready at %g . elapsed beats %g\n", mQueue->slots->uf, elapsedBeats); double wakeTime = BeatsToSecs(slotRawFloat(mQueue->slots)); ElapsedTimeToTimespec(wakeTime, &abstime); //printf("wait until an event is ready. wake %g now %g\n", wakeTime, elapsedTime()); pthread_cond_timedwait (&mCondition, &gLangMutex, &abstime); //printf("mRun b %d\n", mRun); if (!mRun) goto leave; //printf("time diff %g\n", elapsedTime() - mQueue->slots->uf); } while (mQueue->size > 1); //printf("perform all events that are ready %d %.9f\n", mQueue->size, elapsedBeats); // perform all events that are ready //printf("perform all events that are ready\n"); while (mQueue->size > 1 && elapsedBeats >= slotRawFloat(mQueue->slots)) { double delta; PyrSlot task; //printf("while %.6f >= %.6f\n", elapsedBeats, mQueue->slots->uf); getheap(g, (PyrObject*)mQueue, &mBeats, &task); if (isKindOfSlot(&task, class_thread)) { SetNil(&slotRawThread(&task)->nextBeat); } slotCopy((++g->sp), &task); SetFloat(++g->sp, mBeats); SetFloat(++g->sp, BeatsToSecs(mBeats)); ++g->sp; SetObject(g->sp, mTempoClockObj); runAwakeMessage(g); long err = slotDoubleVal(&g->result, &delta); if (!err) { // add delta time and reschedule double beats = mBeats + delta; Add(beats, &task); } } } leave: //printf("<-TempoClock::Run\n"); pthread_mutex_unlock (&gLangMutex); return 0; }