diff --git a/ChangeLog b/ChangeLog index da6e0606..30e88c70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,10 @@ Tom Szilagyi Jackdmp changes log --------------------------- +2007-10-30 Stephane Letz + + * Fix a bug in freewheel management in async mode: drivers now receive the kStartFreewheelCallback and kStopFreewheelCallback notifications. + 2007-10-26 Stephane Letz * Add midiseq and midisine examples. diff --git a/common/JackClient.cpp b/common/JackClient.cpp index 9ab42884..f2945a14 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -94,21 +94,20 @@ pthread_t JackClient::GetThreadID() } /*! -\brief - In ASYNC mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations. + In "async" mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations. The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations. - Drivers synchro are setup in "flush" mode if server is ASYNC and NOT freewheel. + Drivers synchro are setup in "flush" mode if server is "async" and NOT freewheel. */ void JackClient::SetupDriverSync(bool freewheel) { if (!freewheel && !GetEngineControl()->fSyncMode) { JackLog("JackClient::SetupDriverSync driver sem in flush mode\n"); - fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true); + fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true); fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(true); fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(true); } else { JackLog("JackClient::SetupDriverSync driver sem in normal mode\n"); - fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(false); + fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(false); fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(false); fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(false); } diff --git a/common/JackClientControl.h b/common/JackClientControl.h index e4be0727..6a1d35c0 100644 --- a/common/JackClientControl.h +++ b/common/JackClientControl.h @@ -66,7 +66,10 @@ struct JackClientControl : public JackShmMem fCallback[kAddClient] = true; fCallback[kRemoveClient] = true; fCallback[kActivateClient] = true; - fRefNum = refnum; + // So that driver synchro are corectly setup in "flush" or "normal" mode + fCallback[kStartFreewheelCallback] = true; + fCallback[kStopFreewheelCallback] = true; + fRefNum = refnum; fTransportState = JackTransportStopped; fActive = false; } diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index 5d71be36..c8475ccb 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -76,18 +76,9 @@ int JackDriver::Open() } fClientControl->fRefNum = refnum; - fClientControl->fActive = true; - fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for sync - - /* - In ASYNC mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations. - The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations. - */ - if (!fEngineControl->fSyncMode) { - fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true); - fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(true); - fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(true); - } + fClientControl->fActive = true; + fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for "sync" mode + SetupDriverSync(fClientControl->fRefNum, false); return 0; } @@ -113,7 +104,7 @@ int JackDriver::Open(jack_nframes_t nframes, } fClientControl->fRefNum = refnum; - fClientControl->fActive = true; + fClientControl->fActive = true; fEngineControl->fBufferSize = nframes; fEngineControl->fSampleRate = samplerate; fCaptureLatency = capture_latency; @@ -130,17 +121,8 @@ int JackDriver::Open(jack_nframes_t nframes, fEngineControl->fTimeOutUsecs = (jack_time_t)(2.f * fEngineControl->fPeriodUsecs); fGraphManager->SetBufferSize(nframes); - fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for sync - - /* - In ASYNC mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations. - The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations. - */ - if (!fEngineControl->fSyncMode) { - fSynchroTable[AUDIO_DRIVER_REFNUM]->SetFlush(true); - fSynchroTable[FREEWHEEL_DRIVER_REFNUM]->SetFlush(true); - fSynchroTable[LOOPBACK_DRIVER_REFNUM]->SetFlush(true); - } + fGraphManager->DirectConnect(fClientControl->fRefNum, fClientControl->fRefNum); // Connect driver to itself for "sync" mode + SetupDriverSync(fClientControl->fRefNum, false); return 0; } @@ -152,6 +134,40 @@ int JackDriver::Close() return fEngine->ClientInternalClose(fClientControl->fRefNum, false); } +/*! + In "async" mode, the server does not synchronize itself on the output drivers, thus it would never "consume" the activations. + The synchronization primitives for drivers are setup in "flush" mode that to not keep unneeded activations. + Drivers synchro are setup in "flush" mode if server is "async" and NOT freewheel. +*/ +void JackDriver::SetupDriverSync(int ref, bool freewheel) +{ + if (!freewheel && !fEngineControl->fSyncMode) { + JackLog("JackDriver::SetupDriverSync driver sem in flush mode\n"); + fSynchroTable[ref]->SetFlush(true); + } else { + JackLog("JackDriver::SetupDriverSync driver sem in normal mode\n"); + fSynchroTable[ref]->SetFlush(false); + } +} + +int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, int value) +{ + switch (notify) { + + case kStartFreewheelCallback: + JackLog("JackDriver::kStartFreewheel\n"); + SetupDriverSync(fClientControl->fRefNum, true); + break; + + case kStopFreewheelCallback: + JackLog("JackDriver::kStopFreewheel\n"); + SetupDriverSync(fClientControl->fRefNum, false); + break; + } + + return 0; +} + bool JackDriver::IsRealTime() { return fEngineControl->fRealTime; diff --git a/common/JackDriver.h b/common/JackDriver.h index c26b772e..85e9dfd4 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -199,10 +199,9 @@ class EXPORT JackDriver : public JackDriverClient virtual bool IsRealTime(); - int ClientNotify(int refnum, const char* name, int notify, int sync, int value) - { - return 0; - } + int ClientNotify(int refnum, const char* name, int notify, int sync, int value); + + void SetupDriverSync(int ref, bool freewheel); }; diff --git a/common/JackFreewheelDriver.cpp b/common/JackFreewheelDriver.cpp index 271fa021..7e2c638c 100644 --- a/common/JackFreewheelDriver.cpp +++ b/common/JackFreewheelDriver.cpp @@ -34,7 +34,7 @@ int JackFreewheelDriver::Process() { if (fIsMaster) { JackLog("JackFreewheelDriver::Process master %lld\n", fEngineControl->fTimeOutUsecs); - fLastWaitUst = GetMicroSeconds(); + fLastWaitUst = GetMicroSeconds(); fEngine->Process(fLastWaitUst); fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); // Signal all clients if (fGraphManager->SuspendRefNum(fClientControl, fSynchroTable, 10 * 1000000) < 0) // Wait for all clients to finish for 10 sec diff --git a/common/JackServer.cpp b/common/JackServer.cpp index d5ba5a85..7e52b1af 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -257,7 +257,7 @@ int JackServer::SetFreewheel(bool onoff) fEngine->NotifyFreewheel(onoff); fFreewheelDriver->SetMaster(false); fEngineControl->InitFrameTime(); - return fAudioDriver->Start(); + return fAudioDriver->Start(); } } else { if (onoff) { @@ -267,7 +267,7 @@ int JackServer::SetFreewheel(bool onoff) fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum); fEngine->NotifyFreewheel(onoff); fFreewheelDriver->SetMaster(true); - return fFreewheelDriver->Start(); + return fFreewheelDriver->Start(); } else { return -1; } diff --git a/example-clients/freewheel.c b/example-clients/freewheel.c index cfaff7fe..9bac8fd6 100644 --- a/example-clients/freewheel.c +++ b/example-clients/freewheel.c @@ -61,7 +61,7 @@ void parse_arguments(int argc, char *argv[]) int main (int argc, char *argv[]) { - parse_arguments (argc, argv); + //parse_arguments (argc, argv); /* become a JACK client */ if ((client = jack_client_new ("freewheel1")) == 0) { @@ -69,16 +69,24 @@ main (int argc, char *argv[]) exit(1); } + /* signal (SIGQUIT, signal_handler); signal (SIGTERM, signal_handler); signal (SIGHUP, signal_handler); signal (SIGINT, signal_handler); - + */ jack_on_shutdown (client, jack_shutdown, 0); - + + /* if (jack_set_freewheel (client, onoff)) { fprintf (stderr, "failed to reset freewheel mode\n"); } + */ + + jack_set_freewheel (client, 1); + sleep(5); + jack_set_freewheel (client, 0); + sleep(5); jack_client_close(client); return 0;