diff --git a/ChangeLog b/ChangeLog index 8c65b7ea..f86b0af0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -17,6 +17,12 @@ Tim Blechmann Jackdmp changes log --------------------------- +2008-01-31 Stephane Letz + + * Remove checking thread in CoreAudio driver, better device state change recovery strategy: the driver is stopped and restarted. + * jack_thread_wait implementation. + * Add jack_thread_wait client example. + 2008-01-30 Stephane Letz * Latest jack_lsp code from jack SVN. diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index 79126e87..817267b5 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -64,7 +64,8 @@ extern "C" EXPORT int jack_set_process_callback (jack_client_t *client, JackProcessCallback process_callback, void *arg); - EXPORT int jack_set_thread_init_callback (jack_client_t *client, + EXPORT jack_nframes_t jack_thread_wait(jack_client_t *client, int status); + EXPORT int jack_set_thread_init_callback (jack_client_t *client, JackThreadInitCallback thread_init_callback, void *arg); EXPORT int jack_set_freewheel_callback (jack_client_t *client, @@ -630,6 +631,20 @@ EXPORT int jack_set_process_callback(jack_client_t* ext_client, JackProcessCallb } } +EXPORT jack_nframes_t jack_thread_wait(jack_client_t* ext_client, int status) +{ +#ifdef __CLIENTDEBUG__ + JackLibGlobals::CheckContext(); +#endif + JackClient* client = (JackClient*)ext_client; + if (client == NULL) { + jack_error("jack_thread_wait called with a NULL client"); + return -1; + } else { + return client->Wait(status); + } +} + EXPORT int jack_set_freewheel_callback(jack_client_t* ext_client, JackFreewheelCallback freewheel_callback, void* arg) { #ifdef __CLIENTDEBUG__ diff --git a/common/JackClient.cpp b/common/JackClient.cpp index 95c85ddb..c6a29788 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -298,11 +298,13 @@ int JackClient::Deactivate() // RT thread management //---------------------- +/* bool JackClient::CallProcessCallback() { return (fProcess == NULL) ? true : (fProcess(GetEngineControl()->fBufferSize, fProcessArg) == 0); } +*/ /*! \brief Called once when the thread starts. */ @@ -342,6 +344,7 @@ int JackClient::StartThread() /*! \brief RT thread. */ +/* bool JackClient::Execute() { // Suspend itself: wait on the input synchro @@ -392,6 +395,107 @@ error: ShutDown(); return false; } +*/ +//// + +bool JackClient::Execute() +{ + if (WaitFirstSync()) + ExecuteThread(); + return false; // Never reached +} + +inline bool JackClient::WaitFirstSync() +{ + while (true) { + // Start first cycle + WaitSync(); + if (IsActive()) { + CallSyncCallback(); + // Finish first cycle + if (Wait(CallProcessCallback()) != GetEngineControl()->fBufferSize) + return false; + return true; + } else { + JackLog("Process called for an inactive client\n"); + } + SignalSync(); + } + return false; // Never reached +} + +inline void JackClient::ExecuteThread() +{ + while (true) { + if (Wait(CallProcessCallback()) != GetEngineControl()->fBufferSize) + return; + } +} + +inline int JackClient::End() +{ + JackLog("JackClient::Execute end name = %s\n", GetClientControl()->fName); + int result; + // Hum... not sure about this, the following "close" code is called in the RT thread... + fThread->DropRealTime(); + GetClientControl()->fActive = false; + fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result); + fThread->Terminate(); + return 0; // Never reached +} + +inline int JackClient::Error() +{ + jack_error("JackClient::Execute error name = %s", GetClientControl()->fName); + // Hum... not sure about this, the following "close" code is called in the RT thread... + fThread->DropRealTime(); + ShutDown(); + fThread->Terminate(); + return 0; // Never reached +} + +jack_nframes_t JackClient::Wait(int status) +{ + if (status == 0) + CallTimebaseCallback(); + SignalSync(); + if (status != 0) + goto end; + if (!WaitSync()) + goto error; + CallSyncCallback(); + return GetEngineControl()->fBufferSize; + +end: + return End(); + +error: + return Error(); +} + +inline int JackClient::CallProcessCallback() +{ + return (fProcess != NULL) ? fProcess(GetEngineControl()->fBufferSize, fProcessArg) : 0; +} + +inline bool JackClient::WaitSync() +{ + // Suspend itself: wait on the input synchro + if (GetGraphManager()->SuspendRefNum(GetClientControl(), fSynchroTable, 0x7FFFFFFF) < 0) { + jack_error("SuspendRefNum error"); + return false; + } else { + return true; + } +} + +inline void JackClient::SignalSync() +{ + // Resume: signal output clients connected to the running client + if (GetGraphManager()->ResumeRefNum(GetClientControl(), fSynchroTable) < 0) { + jack_error("ResumeRefNum error"); + } +} //----------------- // Port management diff --git a/common/JackClient.h b/common/JackClient.h index bacd72dc..a77792d8 100644 --- a/common/JackClient.h +++ b/common/JackClient.h @@ -90,12 +90,20 @@ class JackClient : public JackClientInterface, public JackRunnableInterface void SetupDriverSync(bool freewheel); bool IsActive(); - bool CallProcessCallback(); void CallSyncCallback(); void CallTimebaseCallback(); int RequestNewPos(jack_position_t* pos); virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value); + + // Fons Adriaensen thread model + inline bool WaitFirstSync(); + inline void ExecuteThread(); + inline bool WaitSync(); + inline void SignalSync(); + inline int CallProcessCallback(); + inline int End(); + inline int Error(); public: @@ -161,6 +169,9 @@ class JackClient : public JackClientInterface, public JackRunnableInterface virtual int InternalClientHandle(const char* client_name, jack_status_t* status); virtual int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va); virtual void InternalClientUnload(int ref, jack_status_t* status); + + // Fons Adriaensen thread model + virtual jack_nframes_t Wait(int status); // JackRunnableInterface interface bool Init(); diff --git a/common/JackPosixThread.cpp b/common/JackPosixThread.cpp index fc7c1dfc..529a680f 100644 --- a/common/JackPosixThread.cpp +++ b/common/JackPosixThread.cpp @@ -226,5 +226,11 @@ pthread_t JackPosixThread::GetThreadID() return fThread; } +void JackPosixThread::Terminate() +{ + JackLog("JackPosixThread::Terminate\n"); + pthread_exit(0); +} + } // end of namespace diff --git a/common/JackPosixThread.h b/common/JackPosixThread.h index f867f08b..9a2601bf 100644 --- a/common/JackPosixThread.h +++ b/common/JackPosixThread.h @@ -62,6 +62,7 @@ class JackPosixThread : public JackThread virtual int StartSync(); virtual int Kill(); virtual int Stop(); + virtual void Terminate(); virtual int AcquireRealTime(); virtual int AcquireRealTime(int priority); diff --git a/common/JackThread.h b/common/JackThread.h index 1a7aad00..54d4e7da 100644 --- a/common/JackThread.h +++ b/common/JackThread.h @@ -81,6 +81,7 @@ class JackThread virtual int StartSync() = 0; virtual int Kill() = 0; virtual int Stop() = 0; + virtual void Terminate() = 0; virtual int AcquireRealTime() = 0; virtual int AcquireRealTime(int priority) = 0; diff --git a/macosx/JackCoreAudioDriver.cpp b/macosx/JackCoreAudioDriver.cpp index 3f2ddc38..4364c60c 100644 --- a/macosx/JackCoreAudioDriver.cpp +++ b/macosx/JackCoreAudioDriver.cpp @@ -257,121 +257,65 @@ OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice, driver->NotifyXRun(GetMicroSeconds()); break; - case kAudioDevicePropertyDeviceIsRunning: { - UInt32 outSize = sizeof(UInt32); - driver->fStopTime = CFAbsoluteTimeGetCurrent(); - OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, &outSize, &driver->fRunning); - JackLog("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsRunning res = %ld\n", driver->fRunning); - if (err != noErr) { - jack_error("Cannot getkAudioDevicePropertyDeviceIsRunning"); - printError(err); - } - break; - } - case kAudioDevicePropertyStreamConfiguration: - JackLog("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyStreamConfiguration \n"); - //JackLog("GetTotalNumberChannels input = %ld\n", GetTotalNumberChannels(driver->fDeviceID, true)); - //JackLog("GetTotalNumberChannels output = %ld\n", GetTotalNumberChannels(driver->fDeviceID, false)); - break; - case kAudioDevicePropertyNominalSampleRate: { - - OSStatus err; - UInt32 outSize = sizeof(Float64); + + UInt32 outSize = sizeof(Float64); Float64 sampleRate; + int in_nChannels = 0; + int out_nChannels = 0; + char capture_driver_name[256]; + char playback_driver_name[256]; - return noErr; // for now + // Stop and restart + driver->Stop(); + driver->RemoveListeners(); + driver->CloseAUHAL(); - err = AudioOutputUnitStop(driver->fAUHAL); - if (err != noErr) - jack_error("Error calling AudioOutputUnitStop"); - - AudioStreamBasicDescription srcFormat, dstFormat; - err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); + OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate); if (err != noErr) { jack_error("Cannot get current sample rate"); printError(err); - return kAudioHardwareUnsupportedOperationError; } JackLog("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyNominalSampleRate %ld\n", long(sampleRate)); - - if (sampleRate != driver->fEngineControl->fSampleRate) { - - // To get SR change notification - /* - driver->fState = false; - err = AudioDeviceAddPropertyListener(driver->fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, driver); - if (err != noErr) { - jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate"); - printError(err); - return kAudioHardwareUnsupportedOperationError; - } - */ - - //sampleRate = driver->fEngineControl->fSampleRate; - err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate); - if (err != noErr) { - jack_error("Cannot set sample rate = %ld", sampleRate); - printError(err); - return kAudioHardwareUnsupportedOperationError; - } - - - JackLog("JackCoreAudioDriver::DeviceNotificationCallback sampleRate %ld\n", driver->fEngineControl->fSampleRate); - - /* - // Waiting for SR change notification - int count = 0; - while (!driver->fState && count++ < 100) { - usleep(100000); - JackLog("Wait count = %ld\n", count); - } - - // Remove SR change notification - AudioDeviceRemovePropertyListener(driver->fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); - */ - } - - /* - // Update SR for input - - //Float64 sampleRate = driver->fEngineControl->fSampleRate; - outSize = sizeof(AudioStreamBasicDescription); - - err = AudioUnitGetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, &outSize); - if (err != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); - printError(err); - } - - srcFormat.mSampleRate = sampleRate; - //srcFormat.mSampleRate = driver->fEngineControl->fSampleRate; - err = AudioUnitSetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, outSize); - if (err != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input"); - printError(err); - } + if (driver->SetupDevices(driver->fCaptureUID, driver->fPlaybackUID, capture_driver_name, playback_driver_name) < 0) + return -1; - // Update SR for output - err = AudioUnitGetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, &outSize); - if (err != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); - printError(err); - } - dstFormat.mSampleRate = sampleRate; - //dstFormat.mSampleRate = driver->fEngineControl->fSampleRate; - err = AudioUnitSetProperty(driver->fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, outSize); - if (err != noErr) { - jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output"); - printError(err); - } - */ + if (driver->SetupChannels(driver->fCapturing, driver->fPlaying, driver->fInChannels, driver->fOutChannels, in_nChannels, out_nChannels, false) < 0) + return -1; + + if (driver->SetupBufferSizeAndSampleRate(driver->fEngineControl->fBufferSize, sampleRate) < 0) + return -1; + + if (driver->OpenAUHAL(driver->fCapturing, + driver->fPlaying, + driver->fInChannels, + driver->fOutChannels, + in_nChannels, + out_nChannels, + driver->fEngineControl->fBufferSize, + sampleRate, + false) < 0) + goto error; + + if (driver->AddListeners() < 0) + goto error; + + driver->Start(); - err = AudioOutputUnitStart(driver->fAUHAL); - if (err != noErr) - jack_error("Error calling AudioOutputUnitStart"); + // Send notification to be used in JackPilot or JackRouter plugin + jack_error("Device restart..."); + CFStringRef ref = CFStringCreateWithCString(NULL, driver->fEngineControl->fServerName, kCFStringEncodingMacRoman); + CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), + CFSTR("com.grame.jackserver.restart"), + ref, + NULL, + kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions); + CFRelease(ref); + return noErr; + error: + driver->CloseAUHAL(); break; } } @@ -453,7 +397,7 @@ OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name) return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name); } -OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, long* channelCount, bool isInput) +OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput) { OSStatus err = noErr; UInt32 outSize; @@ -478,12 +422,11 @@ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, long* chann } JackCoreAudioDriver::JackCoreAudioDriver(const char* name, JackEngine* engine, JackSynchro** table) - : JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fState(false), fStopTime(0), fRunning(true) + : JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL), fState(false) { #ifdef DEBUG //fLogFile = new CALatencyLog("jackmp_latency", ".txt"); #endif - fThread = JackGlobals::MakeThread(this); } JackCoreAudioDriver::~JackCoreAudioDriver() @@ -491,60 +434,14 @@ JackCoreAudioDriver::~JackCoreAudioDriver() #ifdef DEBUG //delete fLogFile; #endif - fThread->Kill(); - delete fThread; } -bool JackCoreAudioDriver::Execute() -{ - while (true) { - JackLog("Check device running...\n"); - if (!fRunning && CFAbsoluteTimeGetCurrent() > fStopTime + 3.0) { - jack_error("Critical error : device not running anymore..."); - // Send notification to be used in JackPilot or JackRouter plugin - CFStringRef ref = CFStringCreateWithCString(NULL, fEngineControl->fServerName, kCFStringEncodingMacRoman); - CFNotificationCenterPostNotificationWithOptions(CFNotificationCenterGetDistributedCenter(), - CFSTR("com.grame.jackserver.stop"), - ref, - NULL, - kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions); - CFRelease(ref); - } - usleep(2000000); - } - return false; -} - -int JackCoreAudioDriver::Open(jack_nframes_t nframes, - jack_nframes_t samplerate, - bool capturing, - bool playing, - int inchannels, - int outchannels, - bool monitor, - const char* capture_driver_uid, - const char* playback_driver_uid, - jack_nframes_t capture_latency, - jack_nframes_t playback_latency) +int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid, const char* playback_driver_uid, char* capture_driver_name, char* playback_driver_name) { - OSStatus err = noErr; - ComponentResult err1; - UInt32 outSize; - UInt32 enableIO; - AudioStreamBasicDescription srcFormat, dstFormat; - Float64 sampleRate; - - long in_nChannels = 0; - long out_nChannels = 0; - char capture_driver_name[256]; - char playback_driver_name[256]; - capture_driver_name[0] = 0; + capture_driver_name[0] = 0; playback_driver_name[0] = 0; - - JackLog("JackCoreAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s\n", - nframes, inchannels, outchannels, capture_driver_uid, playback_driver_uid); - - // Duplex + + // Duplex if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) { JackLog("JackCoreAudioDriver::Open duplex \n"); if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) { @@ -598,13 +495,15 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, return -1; } } + + return 0; +} - // Generic JackAudioDriver Open - if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) { - return -1; - } - - if (capturing) { +int JackCoreAudioDriver::SetupChannels(int capturing, int playing, int& inchannels, int& outchannels, int& in_nChannels, int& out_nChannels, bool strict) +{ + OSStatus err = noErr; + + if (capturing) { err = GetTotalChannels(fDeviceID, &in_nChannels, true); if (err != noErr) { jack_error("Cannot get input channel number"); @@ -624,12 +523,14 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (inchannels > in_nChannels) { jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels); - return -1; - } + if (strict) + return -1; + } if (outchannels > out_nChannels) { jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels); - return -1; + if (strict) + return -1; } if (inchannels == 0) { @@ -641,10 +542,19 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, JackLog("Setup max out channels = %ld\n", out_nChannels); outchannels = out_nChannels; } + + return 0; +} - // Setting buffer size +int JackCoreAudioDriver::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate) +{ + OSStatus err = noErr; + UInt32 outSize; + Float64 sampleRate; + + // Setting buffer size outSize = sizeof(UInt32); - err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &fEngineControl->fBufferSize); + err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes); if (err != noErr) { jack_error("Cannot set buffer size %ld", nframes); printError(err); @@ -688,8 +598,25 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, // Remove SR change notification AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback); } + + return 0; +} - // AUHAL +int JackCoreAudioDriver::OpenAUHAL(int capturing, + int playing, + int inchannels, + int outchannels, + int in_nChannels, + int out_nChannels, + jack_nframes_t nframes, + jack_nframes_t samplerate, + bool strict) +{ + ComponentResult err1; + UInt32 enableIO; + AudioStreamBasicDescription srcFormat, dstFormat; + + // AUHAL ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0}; Component HALOutput = FindNextComponent(NULL, &cd); @@ -697,14 +624,14 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling OpenAComponent"); printError(err1); - goto error; + return -1; } err1 = AudioUnitInitialize(fAUHAL); if (err1 != noErr) { jack_error("Cannot initialize AUHAL unit"); printError(err1); - goto error; + return -1; } // Start I/O @@ -715,7 +642,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input"); printError(err1); - goto error; + if (strict) + return -1; } } @@ -725,7 +653,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output"); printError(err1); - goto error; + if (strict) + return -1; } } @@ -734,7 +663,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice"); printError(err1); - goto error; + if (strict) + return -1; } // Set buffer size @@ -743,7 +673,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); printError(err1); - goto error; + if (strict) + return -1; } } @@ -752,7 +683,8 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice"); printError(err1); - goto error; + if (strict) + return -1; } } @@ -829,7 +761,7 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1"); printError(err1); - goto error; + return -1; } } else { AURenderCallbackStruct output; @@ -839,98 +771,174 @@ int JackCoreAudioDriver::Open(jack_nframes_t nframes, if (err1 != noErr) { jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0"); printError(err1); - goto error; + return -1; } } - // Prepare buffers - if (capturing && inchannels > 0) { - fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer)); - if (fJackInputData == 0) { - jack_error("Cannot allocate memory for input buffers"); - goto error; - } - fJackInputData->mNumberBuffers = inchannels; - for (int i = 0; i < fCaptureChannels; i++) { - fJackInputData->mBuffers[i].mNumberChannels = 1; - fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float); - } - } + return 0; +} + +int JackCoreAudioDriver::SetupBuffers(int inchannels, int outchannels) +{ + // Prepare buffers + fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer)); + if (fJackInputData == 0) { + jack_error("Cannot allocate memory for input buffers"); + return -1; + } + fJackInputData->mNumberBuffers = inchannels; + for (int i = 0; i < fCaptureChannels; i++) { + fJackInputData->mBuffers[i].mNumberChannels = 1; + fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float); + } + return 0; +} + +void JackCoreAudioDriver::DisposeBuffers() +{ + if (fJackInputData) { + free(fJackInputData); + fJackInputData = 0; + } +} + +void JackCoreAudioDriver::CloseAUHAL() +{ + AudioUnitUninitialize(fAUHAL); + CloseComponent(fAUHAL); +} - // Add listeners +int JackCoreAudioDriver::AddListeners() +{ + OSStatus err = noErr; + + // Add listeners err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload"); - printError(err1); - goto error; + printError(err); + return -1; } err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices"); - printError(err1); - goto error; + printError(err); + return -1; } err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate"); - printError(err1); - goto error; + printError(err); + return -1; } err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning"); - printError(err1); - goto error; + printError(err); + return -1; } err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration"); - printError(err1); - goto error; + printError(err); + return -1; } err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this); if (err != noErr) { jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration"); - printError(err1); - goto error; + printError(err); + return -1; } - fDriverOutputData = 0; + return 0; +} +void JackCoreAudioDriver::RemoveListeners() +{ + AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback); + AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback); + AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback); + AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback); + AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback); + AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); + AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); +} + +int JackCoreAudioDriver::Open(jack_nframes_t nframes, + jack_nframes_t samplerate, + bool capturing, + bool playing, + int inchannels, + int outchannels, + bool monitor, + const char* capture_driver_uid, + const char* playback_driver_uid, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency) +{ + int in_nChannels = 0; + int out_nChannels = 0; + char capture_driver_name[256]; + char playback_driver_name[256]; + + // Keep initial state + fCapturing = capturing; + fPlaying = playing; + fInChannels = inchannels; + fOutChannels = outchannels; + fMonitor = monitor; + strcpy(fCaptureUID, capture_driver_uid); + strcpy(fPlaybackUID, playback_driver_uid); + fCaptureLatency = capture_latency; + fPlaybackLatency = playback_latency; + + if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name) < 0) + return -1; + + // Generic JackAudioDriver Open + if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) + return -1; + + if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) + return -1; + + if (SetupBufferSizeAndSampleRate(nframes, samplerate) < 0) + return -1; + + if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, nframes, samplerate, true) < 0) + goto error; + + if (capturing && inchannels > 0) + if (SetupBuffers(inchannels, outchannels) < 0) + goto error; + + if (AddListeners() < 0) + goto error; + // Core driver may have changed the in/out values fCaptureChannels = inchannels; fPlaybackChannels = outchannels; return noErr; error: - AudioUnitUninitialize(fAUHAL); - CloseComponent(fAUHAL); + Close(); return -1; } int JackCoreAudioDriver::Close() { JackLog("JackCoreAudioDriver::Close\n"); + Stop(); JackAudioDriver::Close(); - // Possibly (if MeasureCallback has not been called) - AudioDeviceStop(fDeviceID, MeasureCallback); - AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback); - AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback); - AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback); - AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback); - AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback); - AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); - AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback); - - free(fJackInputData); - AudioUnitUninitialize(fAUHAL); - CloseComponent(fAUHAL); - return 0; + RemoveListeners(); + DisposeBuffers(); + CloseAUHAL(); + return 0; } int JackCoreAudioDriver::Attach() @@ -978,7 +986,6 @@ int JackCoreAudioDriver::Attach() port = fGraphManager->GetPort(port_index); port->Rename("system:capture_%d", i + 1); port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency); - JackLog("Latency = %ld \n", port->GetLatency()); fCapturePortList[i] = port_index; } @@ -1016,7 +1023,6 @@ int JackCoreAudioDriver::Attach() port = fGraphManager->GetPort(port_index); port->Rename("system:playback_%d", i + 1); port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fPlaybackLatency); - JackLog("Latency = %ld \n", port->GetLatency()); fPlaybackPortList[i] = port_index; // Monitor ports @@ -1061,20 +1067,14 @@ int JackCoreAudioDriver::Start() return -1; } - // Start checking thread... - fRunning = true; - fThread->Start(); return 0; } int JackCoreAudioDriver::Stop() { + JackLog("JackCoreAudioDriver::Stop\n"); AudioDeviceStop(fDeviceID, MeasureCallback); AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback); - JackLog("JackCoreAudioDriver::Stop\n"); - // Kill checking thread... - fThread->Kill(); - fRunning = false; return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; } diff --git a/macosx/JackCoreAudioDriver.h b/macosx/JackCoreAudioDriver.h index a3d2fe07..ca6e7bd8 100644 --- a/macosx/JackCoreAudioDriver.h +++ b/macosx/JackCoreAudioDriver.h @@ -25,7 +25,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include "JackAudioDriver.h" #include "JackTime.h" -#include "JackThread.h" #include "/Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.h" @@ -47,7 +46,7 @@ typedef UInt8 CAAudioHardwareDeviceSectionID; \todo hardware monitoring */ -class JackCoreAudioDriver : public JackAudioDriver, public JackRunnableInterface +class JackCoreAudioDriver : public JackAudioDriver { private: @@ -67,9 +66,18 @@ class JackCoreAudioDriver : public JackAudioDriver, public JackRunnableInterfac AudioTimeStamp* fCurrentTime; bool fState; - CFAbsoluteTime fStopTime; - UInt32 fRunning; - JackThread* fThread; + + /// Intitial state + int fCapturing; + int fPlaying; + + int fInChannels; + int fOutChannels; + + char fCaptureUID[256]; + char fPlaybackUID[256]; + + bool fMonitor; static OSStatus Render(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, @@ -104,7 +112,40 @@ class JackCoreAudioDriver : public JackAudioDriver, public JackRunnableInterfac OSStatus GetDefaultInputDevice(AudioDeviceID* id); OSStatus GetDefaultOutputDevice(AudioDeviceID* id); OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name); - OSStatus GetTotalChannels(AudioDeviceID device, long* channelCount, bool isInput); + OSStatus GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput); + + // Setup + int SetupDevices(const char* capture_driver_uid, + const char* playback_driver_uid, + char* capture_driver_name, + char* playback_driver_name); + + int SetupChannels(int capturing, + int playing, + int& inchannels, + int& outchannels, + int& in_nChannels, + int& out_nChannels, + bool strict); + + int SetupBuffers(int inchannels, int outchannels); + void DisposeBuffers(); + + int SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate); + + int OpenAUHAL(int capturing, + int playing, + int inchannels, + int outchannels, + int in_nChannels, + int out_nChannels, + jack_nframes_t nframes, + jack_nframes_t samplerate, + bool strict); + void CloseAUHAL(); + + int AddListeners(); + void RemoveListeners(); public: @@ -122,8 +163,7 @@ class JackCoreAudioDriver : public JackAudioDriver, public JackRunnableInterfac const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency); - - int Close(); + int Close(); int Attach(); @@ -134,8 +174,6 @@ class JackCoreAudioDriver : public JackAudioDriver, public JackRunnableInterfac int Write(); int SetBufferSize(jack_nframes_t buffer_size); - - bool Execute(); }; } // end of namespace diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index 754d5f25..b819055b 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 4B35C6920D4733B9000DE7AE /* PBXTargetDependency */, 4B35C6940D4733B9000DE7AE /* PBXTargetDependency */, 4B35C6960D4733B9000DE7AE /* PBXTargetDependency */, + 4B0A29300D5210C4002EFF74 /* PBXTargetDependency */, 4B35C6980D4733B9000DE7AE /* PBXTargetDependency */, 4B35C69A0D4733B9000DE7AE /* PBXTargetDependency */, 4B35C69C0D4733B9000DE7AE /* PBXTargetDependency */, @@ -68,6 +69,7 @@ 4BE99D630AD7A19100C59091 /* PBXTargetDependency */, 4BA693E90CBE5BBA00EAD520 /* PBXTargetDependency */, 4BA693EB0CBE5BBA00EAD520 /* PBXTargetDependency */, + 4B0A28F40D520D11002EFF74 /* PBXTargetDependency */, 4BFA99AC0AAAF41D009E916C /* PBXTargetDependency */, 4BFA99500AAAED90009E916C /* PBXTargetDependency */, 4BFA99520AAAED90009E916C /* PBXTargetDependency */, @@ -83,6 +85,8 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 4B0A28ED0D520852002EFF74 /* tw.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0A28EC0D520852002EFF74 /* tw.c */; }; + 4B0A29260D52108E002EFF74 /* tw.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0A28EC0D520852002EFF74 /* tw.c */; }; 4B35C41E0D4731D1000DE7AE /* Jackdmp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D2250834F06A00C94B91 /* Jackdmp.cpp */; }; 4B35C4290D4731D1000DE7AE /* JackMachPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B799AD707899652003F3F15 /* JackMachPort.h */; }; 4B35C42A0D4731D1000DE7AE /* JackError.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF8D1770834EE4800C94B91 /* JackError.h */; }; @@ -596,6 +600,20 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 4B0A28F30D520D11002EFF74 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4B0A28DC0D52073D002EFF74 /* jack_thread_wait */; + remoteInfo = jack_thread_wait; + }; + 4B0A292F0D5210C4002EFF74 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4B0A29230D52108E002EFF74 /* jack_thread_wait 64 bits */; + remoteInfo = "jack_thread_wait 64 bits"; + }; 4B1C1ABF0CC61597005F551E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; @@ -986,6 +1004,9 @@ /* Begin PBXFileReference section */ 4B003A6008E2A87A0060EFDC /* JackError.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = JackError.c; path = ../common/JackError.c; sourceTree = SOURCE_ROOT; }; 4B003AB008E2B2BA0060EFDC /* ringbuffer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ringbuffer.c; path = ../common/ringbuffer.c; sourceTree = SOURCE_ROOT; }; + 4B0A28E60D52073D002EFF74 /* jack_thread_wait */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_thread_wait; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B0A28EC0D520852002EFF74 /* tw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tw.c; path = "../example-clients/tw.c"; sourceTree = SOURCE_ROOT; }; + 4B0A292D0D52108E002EFF74 /* jack_thread_wait */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_thread_wait; sourceTree = BUILT_PRODUCTS_DIR; }; 4B123D3308B3954300540632 /* JackGlobalsClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobalsClient.cpp; path = ../common/JackGlobalsClient.cpp; sourceTree = SOURCE_ROOT; }; 4B123D3608B3954A00540632 /* JackGlobalsServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobalsServer.cpp; path = ../common/JackGlobalsServer.cpp; sourceTree = SOURCE_ROOT; }; 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; }; @@ -1201,6 +1222,20 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 4B0A28E00D52073D002EFF74 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0A29270D52108E002EFF74 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B35C41F0D4731D1000DE7AE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1680,6 +1715,8 @@ 4B35C6290D4731D2000DE7AE /* jack_portaudio.so */, 4B35C6340D4731D2000DE7AE /* jack_dummy.so */, 4B35C63E0D4731D3000DE7AE /* inprocess.so */, + 4B0A28E60D52073D002EFF74 /* jack_thread_wait */, + 4B0A292D0D52108E002EFF74 /* jack_thread_wait */, ); name = Products; sourceTree = ""; @@ -1687,6 +1724,7 @@ 4B03383E0797E19900686131 /* Simple clients */ = { isa = PBXGroup; children = ( + 4B0A28EC0D520852002EFF74 /* tw.c */, 4B5A1BDC0CD1CD420005BF74 /* midisine.c */, 4B5A1BBD0CD1CC110005BF74 /* midiseq.c */, 4BA692D60CBE4CC600EAD520 /* ipunload.c */, @@ -2031,6 +2069,20 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 4B0A28DD0D52073D002EFF74 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0A29240D52108E002EFF74 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B35C41C0D4731D1000DE7AE /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2646,6 +2698,44 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 4B0A28DC0D52073D002EFF74 /* jack_thread_wait */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B0A28E20D52073D002EFF74 /* Build configuration list for PBXNativeTarget "jack_thread_wait" */; + buildPhases = ( + 4B0A28DD0D52073D002EFF74 /* Headers */, + 4B0A28DE0D52073D002EFF74 /* Sources */, + 4B0A28E00D52073D002EFF74 /* Frameworks */, + 4B0A28E10D52073D002EFF74 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = jack_thread_wait; + productInstallPath = /usr/local/bin; + productName = testSem; + productReference = 4B0A28E60D52073D002EFF74 /* jack_thread_wait */; + productType = "com.apple.product-type.tool"; + }; + 4B0A29230D52108E002EFF74 /* jack_thread_wait 64 bits */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4B0A29290D52108E002EFF74 /* Build configuration list for PBXNativeTarget "jack_thread_wait 64 bits" */; + buildPhases = ( + 4B0A29240D52108E002EFF74 /* Headers */, + 4B0A29250D52108E002EFF74 /* Sources */, + 4B0A29270D52108E002EFF74 /* Frameworks */, + 4B0A29280D52108E002EFF74 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "jack_thread_wait 64 bits"; + productInstallPath = /usr/local/bin; + productName = testSem; + productReference = 4B0A292D0D52108E002EFF74 /* jack_thread_wait */; + productType = "com.apple.product-type.tool"; + }; 4B35C41B0D4731D1000DE7AE /* jackdmp framework 64bits */ = { isa = PBXNativeTarget; buildConfigurationList = 4B35C4210D4731D1000DE7AE /* Build configuration list for PBXNativeTarget "jackdmp framework 64bits" */; @@ -3690,6 +3780,7 @@ 4BE99D260AD7A04800C59091 /* jack_cpu Universal */, 4BA692A60CBE4BC700EAD520 /* jack_load Universal */, 4BA692CA0CBE4C9000EAD520 /* jack_unload Universal */, + 4B0A28DC0D52073D002EFF74 /* jack_thread_wait */, 4B699D4F097D421600A18468 /* synchroServer Universal */, 4B699D67097D421600A18468 /* synchroClient Universal */, 4B699D7F097D421700A18468 /* synchroServerClient Universal */, @@ -3717,6 +3808,7 @@ 4B35C5B40D4731D2000DE7AE /* jack_cpu 64 bits */, 4B35C5C00D4731D2000DE7AE /* jack_load 64 bits */, 4B35C5CC0D4731D2000DE7AE /* jack_unload 64 bits */, + 4B0A29230D52108E002EFF74 /* jack_thread_wait 64 bits */, 4B35C5D80D4731D2000DE7AE /* synchroServer 64 bits */, 4B35C5EC0D4731D2000DE7AE /* synchroClient 64 bits */, 4B35C6000D4731D2000DE7AE /* synchroServerClient 64 bits */, @@ -3774,6 +3866,20 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXRezBuildPhase section */ + 4B0A28E10D52073D002EFF74 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0A29280D52108E002EFF74 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B35C4200D4731D1000DE7AE /* Rez */ = { isa = PBXRezBuildPhase; buildActionMask = 2147483647; @@ -4085,6 +4191,22 @@ /* End PBXRezBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 4B0A28DE0D52073D002EFF74 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B0A28ED0D520852002EFF74 /* tw.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4B0A29250D52108E002EFF74 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4B0A29260D52108E002EFF74 /* tw.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 4B35C41D0D4731D1000DE7AE /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -4742,6 +4864,16 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 4B0A28F40D520D11002EFF74 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4B0A28DC0D52073D002EFF74 /* jack_thread_wait */; + targetProxy = 4B0A28F30D520D11002EFF74 /* PBXContainerItemProxy */; + }; + 4B0A29300D5210C4002EFF74 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4B0A29230D52108E002EFF74 /* jack_thread_wait 64 bits */; + targetProxy = 4B0A292F0D5210C4002EFF74 /* PBXContainerItemProxy */; + }; 4B1C1AC00CC61597005F551E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 4BE50F8D0B01EE8000C05E63 /* Jackwrapper.framework Universal */; @@ -5020,6 +5152,192 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 4B0A28E30D52073D002EFF74 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_thread_wait; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + 4B0A28E40D52073D002EFF74 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_OPTIMIZATION_LEVEL = 3; + HEADER_SEARCH_PATHS = ../common; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_thread_wait; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + 4B0A28E50D52073D002EFF74 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ); + GCC_OPTIMIZATION_LEVEL = 3; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_thread_wait; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; + 4B0A292A0D52108E002EFF74 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ppc64, + x86_64, + ); + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_thread_wait; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = YES; + }; + name = Development; + }; + 4B0A292B0D52108E002EFF74 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ppc64, + x86_64, + ); + COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_OPTIMIZATION_LEVEL = 3; + HEADER_SEARCH_PATHS = ../common; + MACOSX_DEPLOYMENT_TARGET = 10.4; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_thread_wait; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + ZERO_LINK = NO; + }; + name = Deployment; + }; + 4B0A292C0D52108E002EFF74 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + ppc64, + x86_64, + ); + GCC_OPTIMIZATION_LEVEL = 3; + HEADER_SEARCH_PATHS = ../common; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ( + "-framework", + Jackmp, + ); + OTHER_REZFLAGS = ""; + PRODUCT_NAME = jack_thread_wait; + REZ_EXECUTABLE = YES; + SDKROOT = ""; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ( + "-Wmost", + "-Wno-four-char-constants", + "-Wno-unknown-pragmas", + ); + }; + name = Default; + }; 4B35C4220D4731D1000DE7AE /* Development */ = { isa = XCBuildConfiguration; buildSettings = { @@ -11193,6 +11511,26 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 4B0A28E20D52073D002EFF74 /* Build configuration list for PBXNativeTarget "jack_thread_wait" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B0A28E30D52073D002EFF74 /* Development */, + 4B0A28E40D52073D002EFF74 /* Deployment */, + 4B0A28E50D52073D002EFF74 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 4B0A29290D52108E002EFF74 /* Build configuration list for PBXNativeTarget "jack_thread_wait 64 bits" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4B0A292A0D52108E002EFF74 /* Development */, + 4B0A292B0D52108E002EFF74 /* Deployment */, + 4B0A292C0D52108E002EFF74 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; 4B35C4210D4731D1000DE7AE /* Build configuration list for PBXNativeTarget "jackdmp framework 64bits" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/windows/JackWinThread.cpp b/windows/JackWinThread.cpp index fff76f65..1128c763 100644 --- a/windows/JackWinThread.cpp +++ b/windows/JackWinThread.cpp @@ -247,5 +247,12 @@ pthread_t JackWinThread::GetThreadID() return fThread; } +void JackWinThread::Terminate() +{ + TerminateThread(fThread, 0); + WaitForSingleObject(fThread, INFINITE); + CloseHandle(fThread); +} + } // end of namespace diff --git a/windows/JackWinThread.h b/windows/JackWinThread.h index 0b1878ac..a4bafab7 100644 --- a/windows/JackWinThread.h +++ b/windows/JackWinThread.h @@ -27,8 +27,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. namespace Jack { - -typedef DWORD (WINAPI *ThreadCallback)(void *arg); + +typedef DWORD (WINAPI *ThreadCallback)(void *arg); /*! \brief Windows threads. @@ -53,6 +53,7 @@ class JackWinThread : public JackThread int StartSync(); int Kill(); int Stop(); + void Terminate(); int AcquireRealTime(); int AcquireRealTime(int priority) ; @@ -62,7 +63,7 @@ class JackWinThread : public JackThread static int AcquireRealTimeImp(pthread_t thread, int priority); static int DropRealTimeImp(pthread_t thread); - static int StartImp(pthread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg); + static int StartImp(pthread_t* thread, int priority, int realtime, ThreadCallback start_routine, void* arg); };