diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index 19741d0f..de7616b3 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -313,6 +313,26 @@ int JackAudioDriver::ProcessGraphSync() return res; } +int JackAudioDriver::Start() +{ + int res = JackDriver::Start(); + if ((res >= 0) && fIsMaster) { + res = StartSlaves(); + } + return res; +} + +int JackAudioDriver::Stop() +{ + int res = JackDriver::Stop(); + if (fIsMaster) { + if (StopSlaves() < 0) { + res = -1; + } + } + return res; +} + void JackAudioDriver::WaitUntilNextCycle() { int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f)); diff --git a/common/JackAudioDriver.h b/common/JackAudioDriver.h index 3127f4c1..8eaca692 100644 --- a/common/JackAudioDriver.h +++ b/common/JackAudioDriver.h @@ -92,6 +92,9 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver virtual int Attach(); virtual int Detach(); + virtual int Start(); + virtual int Stop(); + virtual int Write(); virtual int SetBufferSize(jack_nframes_t buffer_size); diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index a87d1963..a3546a2a 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -826,6 +826,11 @@ EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr EXPORT bool jackctl_server_stop(jackctl_server *server_ptr) { server_ptr->engine->Stop(); + return true; +} + +EXPORT bool jackctl_server_close(jackctl_server *server_ptr) +{ server_ptr->engine->Close(); delete server_ptr->engine; @@ -853,7 +858,7 @@ EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr) } EXPORT bool -jackctl_server_start( +jackctl_server_open( jackctl_server *server_ptr, jackctl_driver *driver_ptr) { @@ -913,18 +918,8 @@ jackctl_server_start( goto fail_delete; } - rc = server_ptr->engine->Start(); - if (rc < 0) - { - jack_error("JackServer::Start() failed with %d", rc); - goto fail_close; - } - return true; -fail_close: - server_ptr->engine->Close(); - fail_delete: delete server_ptr->engine; server_ptr->engine = NULL; @@ -946,6 +941,19 @@ fail: return false; } +EXPORT bool +jackctl_server_start( + jackctl_server *server_ptr) +{ + int rc = server_ptr->engine->Start(); + bool result = rc >= 0; + if (! result) + { + jack_error("JackServer::Start() failed with %d", rc); + } + return result; +} + EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr) { return driver_ptr->desc_ptr->name; diff --git a/common/JackControlAPI.h b/common/JackControlAPI.h index d0b0cbc1..8e87d513 100644 --- a/common/JackControlAPI.h +++ b/common/JackControlAPI.h @@ -101,13 +101,21 @@ jackctl_server_get_drivers_list( jackctl_server_t * server); EXPORT bool -jackctl_server_start( +jackctl_server_open( jackctl_server_t * server, jackctl_driver_t * driver); +EXPORT bool +jackctl_server_start( + jackctl_server_t * server); + EXPORT bool jackctl_server_stop( - jackctl_server_t * server); + jackctl_server_t * server); + +EXPORT bool +jackctl_server_close( + jackctl_server_t * server); EXPORT const JSList * jackctl_server_get_parameters( diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index a2c6ccd6..b3aa0713 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -328,11 +328,41 @@ int JackDriver::Start() return 0; } +int JackDriver::StartSlaves() +{ + int res = 0; + list::const_iterator it; + for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { + JackDriverInterface* slave = *it; + if (slave->Start() < 0) { + res = -1; + + // XXX: We should attempt to stop all of the slaves that we've + // started here. + + break; + } + } + return res; +} + int JackDriver::Stop() { return 0; } +int JackDriver::StopSlaves() +{ + int res = 0; + list::const_iterator it; + for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { + JackDriverInterface* slave = *it; + if (slave->Stop() < 0) + res = -1; + } + return res; +} + bool JackDriver::IsFixedBufferSize() { return true; diff --git a/common/JackDriver.h b/common/JackDriver.h index 6f230831..3fd7b860 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -198,7 +198,9 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface virtual int Write(); virtual int Start(); + virtual int StartSlaves(); virtual int Stop(); + virtual int StopSlaves(); virtual bool IsFixedBufferSize(); virtual int SetBufferSize(jack_nframes_t buffer_size); diff --git a/common/JackServer.cpp b/common/JackServer.cpp index a35cff62..e165badc 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -87,26 +87,18 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) goto fail_close3; } - if (fFreewheelDriver->Open() < 0) { // before engine open - jack_error("Cannot open driver"); - goto fail_close4; - } - if (fAudioDriver->Attach() < 0) { jack_error("Cannot attach audio driver"); - goto fail_close5; + goto fail_close4; } fFreewheelDriver->SetMaster(false); fAudioDriver->SetMaster(true); - fAudioDriver->AddSlave(fFreewheelDriver); // After ??? + //fAudioDriver->AddSlave(fFreewheelDriver); InitTime(); SetClockSource(fEngineControl->fClockSource); return 0; -fail_close5: - fFreewheelDriver->Close(); - fail_close4: fEngine->Close(); @@ -128,7 +120,9 @@ int JackServer::Close() fChannel.Close(); fAudioDriver->Detach(); fAudioDriver->Close(); - fFreewheelDriver->Close(); + if (fFreewheel) { + fFreewheelDriver->Close(); + } fEngine->Close(); // TODO: move that in reworked JackServerGlobals::Destroy() JackMessageBuffer::Destroy(); @@ -238,6 +232,7 @@ int JackServer::SetFreewheel(bool onoff) } else { fFreewheel = false; fFreewheelDriver->Stop(); + fFreewheelDriver->Close(); fGraphManager->Restore(&fConnectionState); // Restore previous connection state fEngine->NotifyFreewheel(onoff); fFreewheelDriver->SetMaster(false); @@ -250,6 +245,10 @@ int JackServer::SetFreewheel(bool onoff) fGraphManager->Save(&fConnectionState); // Save connection state fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum); fEngine->NotifyFreewheel(onoff); + if (fFreewheelDriver->Open() < 0) { + jack_error("Cannot open freewheel driver"); + return -1; + } fFreewheelDriver->SetMaster(true); return fFreewheelDriver->Start(); } else { @@ -296,11 +295,11 @@ JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* dr if (slave == NULL) { delete info; return NULL; - } else { - slave->Attach(); - fAudioDriver->AddSlave(slave); - return info; } + slave->Attach(); + slave->SetMaster(false); + fAudioDriver->AddSlave(slave); + return info; } void JackServer::RemoveSlave(JackDriverInfo* info) @@ -322,32 +321,30 @@ int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_par JackDriverInfo* info = new JackDriverInfo(); JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); - if (master == NULL || info == NULL) { + if (master == NULL) { delete info; - delete master; return -1; - } else { + } - // Get slaves list - std::list slave_list = fAudioDriver->GetSlaves(); - std::list::const_iterator it; + // Get slaves list + std::list slave_list = fAudioDriver->GetSlaves(); + std::list::const_iterator it; - // Move slaves in new master - for (it = slave_list.begin(); it != slave_list.end(); it++) { - JackDriverInterface* slave = *it; - master->AddSlave(slave); - } + // Move slaves in new master + for (it = slave_list.begin(); it != slave_list.end(); it++) { + JackDriverInterface* slave = *it; + master->AddSlave(slave); + } - // Delete old master - delete fDriverInfo; + // Delete old master + delete fDriverInfo; - // Activate master - fAudioDriver = master; - fDriverInfo = info; - fAudioDriver->Attach(); - fAudioDriver->SetMaster(true); - return fAudioDriver->Start(); - } + // Activate master + fAudioDriver = master; + fDriverInfo = info; + fAudioDriver->Attach(); + fAudioDriver->SetMaster(true); + return fAudioDriver->Start(); } //---------------------- diff --git a/common/Jackdmp.cpp b/common/Jackdmp.cpp index 2e8a78e7..602aca31 100644 --- a/common/Jackdmp.cpp +++ b/common/Jackdmp.cpp @@ -244,6 +244,10 @@ int main(int argc, char* argv[]) std::list slaves_list; std::list::iterator it; + // Assume that we fail. + int return_value = -1; + bool notify_sent = false; + copyright(stdout); #if defined(JACK_DBUS) && defined(__linux__) server_ctl = jackctl_server_create(audio_acquire, audio_release); @@ -285,7 +289,7 @@ int main(int argc, char* argv[]) jackctl_parameter_set_value(param, &value); } else { usage(stdout); - goto fail_free1; + goto destroy_server; } } break; @@ -402,7 +406,7 @@ int main(int argc, char* argv[]) case 'h': usage(stdout); - goto fail_free1; + goto destroy_server; } } @@ -423,14 +427,14 @@ int main(int argc, char* argv[]) if (!master_driver_name) { usage(stderr); - goto fail_free1; + goto destroy_server; } // Master driver master_driver_ctl = jackctl_server_get_driver(server_ctl, master_driver_name); if (master_driver_ctl == NULL) { fprintf(stderr, "Unknown driver \"%s\"\n", master_driver_name); - goto fail_free1; + goto destroy_server; } if (optind < argc) { @@ -442,7 +446,7 @@ int main(int argc, char* argv[]) if (master_driver_nargs == 0) { fprintf(stderr, "No driver specified ... hmm. JACK won't do" " anything when run like this.\n"); - goto fail_free1; + goto destroy_server; } master_driver_args = (char **) malloc(sizeof(char *) * master_driver_nargs); @@ -453,15 +457,16 @@ int main(int argc, char* argv[]) } if (jackctl_parse_driver_params(master_driver_ctl, master_driver_nargs, master_driver_args)) { - goto fail_free1; + goto destroy_server; } - // Setup signals then start server + // Setup signals signals = jackctl_setup_signals(0); - if (!jackctl_server_start(server_ctl, master_driver_ctl)) { - fprintf(stderr, "Failed to start server\n"); - goto fail_free1; + // Open server + if (! jackctl_server_open(server_ctl, master_driver_ctl)) { + fprintf(stderr, "Failed to open server\n"); + goto destroy_server; } // Slave drivers @@ -469,7 +474,7 @@ int main(int argc, char* argv[]) jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); if (slave_driver_ctl == NULL) { fprintf(stderr, "Unknown driver \"%s\"\n", *it); - goto fail_free2; + goto close_server; } jackctl_server_add_slave(server_ctl, slave_driver_ctl); } @@ -477,6 +482,8 @@ int main(int argc, char* argv[]) // Loopback driver if (loopback > 0) { loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback"); + + // XX: What if this fails? if (loopback_driver_ctl != NULL) { const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl); param = jackctl_get_parameter(loopback_parameters, "channels"); @@ -486,6 +493,13 @@ int main(int argc, char* argv[]) } jackctl_server_add_slave(server_ctl, loopback_driver_ctl); } + + } + + // Start the server + if (!jackctl_server_start(server_ctl)) { + fprintf(stderr, "Failed to start server\n"); + goto close_server; } // Internal clients @@ -493,30 +507,28 @@ int main(int argc, char* argv[]) jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); if (internal_driver_ctl == NULL) { fprintf(stderr, "Unknown internal \"%s\"\n", *it); - goto fail_free2; + goto stop_server; } jackctl_server_load_internal(server_ctl, internal_driver_ctl); } notify_server_start(server_name); + notify_sent = true; + return_value = 0; // Waits for signal jackctl_wait_signals(signals); - if (!jackctl_server_stop(server_ctl)) + stop_server: + if (! jackctl_server_stop(server_ctl)) { fprintf(stderr, "Cannot stop server...\n"); - - jackctl_server_destroy(server_ctl); - notify_server_stop(server_name); - return 0; - -fail_free1: - jackctl_server_destroy(server_ctl); - return -1; - -fail_free2: - jackctl_server_stop(server_ctl); + } + if (notify_sent) { + notify_server_stop(server_name); + } + close_server: + jackctl_server_close(server_ctl); + destroy_server: jackctl_server_destroy(server_ctl); - notify_server_stop(server_name); - return -1; + return return_value; } diff --git a/common/jack/control.h b/common/jack/control.h index caeb931d..7ec5c521 100644 --- a/common/jack/control.h +++ b/common/jack/control.h @@ -133,7 +133,7 @@ jackctl_server_destroy( jackctl_server_t * server); /** - * Call this function to start JACK server + * Call this function to open JACK server * * @param server server object handle * @param driver driver to use @@ -141,10 +141,21 @@ jackctl_server_destroy( * @return success status: true - success, false - fail */ bool -jackctl_server_start( +jackctl_server_open( jackctl_server_t * server, jackctl_driver_t * driver); +/** + * Call this function to start JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_start( + jackctl_server_t * server); + /** * Call this function to stop JACK server * @@ -156,6 +167,17 @@ bool jackctl_server_stop( jackctl_server_t * server); +/** + * Call this function to close JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_close( + jackctl_server_t * server); + /** * Call this function to get list of available drivers. List node data * pointers is a driver object handle (::jackctl_driver_t). diff --git a/dbus/controller.c b/dbus/controller.c index 9c2bf3a5..77acef39 100644 --- a/dbus/controller.c +++ b/dbus/controller.c @@ -153,14 +153,21 @@ jack_controller_start_server( controller_ptr->xruns = 0; - if (!jackctl_server_start( + if (!jackctl_server_open( controller_ptr->server, controller_ptr->driver)) { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server"); goto fail; } + if (!jackctl_server_start( + controller_ptr->server)) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); + goto fail_close_server; + } + controller_ptr->client = jack_client_open( "dbusapi", JackNoStartServer, @@ -213,6 +220,12 @@ fail_stop_server: jack_error("failed to stop jack server"); } +fail_close_server: + if (!jackctl_server_close(controller_ptr->server)) + { + jack_error("failed to close jack server"); + } + fail: return FALSE; } @@ -250,6 +263,12 @@ jack_controller_stop_server( return FALSE; } + if (!jackctl_server_close(controller_ptr->server)) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server"); + return FALSE; + } + controller_ptr->started = false; return TRUE; diff --git a/example-clients/server_control.cpp b/example-clients/server_control.cpp index 64ec977c..44040954 100644 --- a/example-clients/server_control.cpp +++ b/example-clients/server_control.cpp @@ -207,8 +207,9 @@ int main(int argc, char *argv[]) print_internal((jackctl_internal_t *)node_ptr->data); node_ptr = jack_slist_next(node_ptr); } - - jackctl_server_start(server, jackctl_server_get_driver(server, driver_name)); + + jackctl_server_open(server, jackctl_server_get_driver(server, driver_name)); + jackctl_server_start(server); jackctl_server_load_internal(server, jackctl_server_get_internal(server, client_name)); /* diff --git a/linux/alsa/JackAlsaDriver.cpp b/linux/alsa/JackAlsaDriver.cpp index 914766ec..3d39e432 100644 --- a/linux/alsa/JackAlsaDriver.cpp +++ b/linux/alsa/JackAlsaDriver.cpp @@ -340,13 +340,23 @@ int JackAlsaDriver::Close() int JackAlsaDriver::Start() { - JackAudioDriver::Start(); - return alsa_driver_start((alsa_driver_t *)fDriver); + int res = JackAudioDriver::Start(); + if (res >= 0) { + res = alsa_driver_start((alsa_driver_t *)fDriver); + if (res < 0) { + JackAudioDriver::Stop(); + } + } + return res; } int JackAlsaDriver::Stop() { - return alsa_driver_stop((alsa_driver_t *)fDriver); + int res = alsa_driver_stop((alsa_driver_t *)fDriver); + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackAlsaDriver::Read() diff --git a/linux/firewire/JackFFADODriver.cpp b/linux/firewire/JackFFADODriver.cpp index 0966b1da..2f855f37 100644 --- a/linux/firewire/JackFFADODriver.cpp +++ b/linux/firewire/JackFFADODriver.cpp @@ -526,7 +526,7 @@ int JackFFADODriver::Attach() port = fGraphManager->GetPort(port_index); // Add one buffer more latency if "async" mode is used... - range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency + range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency; port->SetLatencyRange(JackPlaybackLatency, &range); // playback port aliases (jackd1 style port names) snprintf(buf, sizeof(buf) - 1, "%s:playback_%i", fClientControl.fName, (int) chn + 1); @@ -653,13 +653,23 @@ int JackFFADODriver::Close() int JackFFADODriver::Start() { - JackAudioDriver::Start(); - return ffado_driver_start((ffado_driver_t *)fDriver); + int res = JackAudioDriver::Start(); + if (res >= 0) { + res = ffado_driver_start((ffado_driver_t *)fDriver); + if (res < 0) { + JackAudioDriver::Stop(); + } + } + return res; } int JackFFADODriver::Stop() { - return ffado_driver_stop((ffado_driver_t *)fDriver); + int res = ffado_driver_stop((ffado_driver_t *)fDriver); + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackFFADODriver::Read() diff --git a/linux/freebob/JackFreebobDriver.cpp b/linux/freebob/JackFreebobDriver.cpp index 96131d0b..03a26893 100644 --- a/linux/freebob/JackFreebobDriver.cpp +++ b/linux/freebob/JackFreebobDriver.cpp @@ -841,13 +841,23 @@ int JackFreebobDriver::Close() int JackFreebobDriver::Start() { - JackAudioDriver::Start(); - return freebob_driver_start((freebob_driver_t *)fDriver); + int res = JackAudioDriver::Start(); + if (res >= 0) { + res = freebob_driver_start((freebob_driver_t *)fDriver); + if (res < 0) { + JackAudioDriver::Stop(); + } + } + return res; } int JackFreebobDriver::Stop() { - return freebob_driver_stop((freebob_driver_t *)fDriver); + int res = freebob_driver_stop((freebob_driver_t *)fDriver); + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackFreebobDriver::Read() diff --git a/macosx/coreaudio/JackCoreAudioDriver.cpp b/macosx/coreaudio/JackCoreAudioDriver.cpp index 0acad8a7..5cd63676 100644 --- a/macosx/coreaudio/JackCoreAudioDriver.cpp +++ b/macosx/coreaudio/JackCoreAudioDriver.cpp @@ -1680,33 +1680,38 @@ int JackCoreAudioDriver::Attach() int JackCoreAudioDriver::Start() { jack_log("JackCoreAudioDriver::Start"); - JackAudioDriver::Start(); + if (JackAudioDriver::Start() >= 0) { + OSStatus err = AudioOutputUnitStart(fAUHAL); + if (err == noErr) { - OSStatus err = AudioOutputUnitStart(fAUHAL); - if (err != noErr) - return -1; + // Waiting for Measure callback to be called (= driver has started) + fState = false; + int count = 0; + while (!fState && count++ < WAIT_COUNTER) { + usleep(100000); + jack_log("JackCoreAudioDriver::Start wait count = %d", count); + } - // Waiting for Measure callback to be called (= driver has started) - fState = false; - int count = 0; - while (!fState && count++ < WAIT_COUNTER) { - usleep(100000); - jack_log("JackCoreAudioDriver::Start wait count = %d", count); - } + if (count < WAIT_COUNTER) { + jack_info("CoreAudio driver is running..."); + return 0; + } - if (count < WAIT_COUNTER) { - jack_info("CoreAudio driver is running..."); - return 0; - } else { - jack_error("CoreAudio driver cannot start..."); - return -1; + jack_error("CoreAudio driver cannot start..."); + } + JackAudioDriver::Stop(); } + return -1; } int JackCoreAudioDriver::Stop() { jack_log("JackCoreAudioDriver::Stop"); - return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; + int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) diff --git a/windows/portaudio/JackPortAudioDriver.cpp b/windows/portaudio/JackPortAudioDriver.cpp index 1732102f..41a3deb2 100644 --- a/windows/portaudio/JackPortAudioDriver.cpp +++ b/windows/portaudio/JackPortAudioDriver.cpp @@ -191,16 +191,25 @@ error: int JackPortAudioDriver::Start() { jack_log("JackPortAudioDriver::Start"); - JackAudioDriver::Start(); - PaError err = Pa_StartStream(fStream); - return (err == paNoError) ? 0 : -1; + if (JackAudioDriver::Start() >= 0) { + PaError err = Pa_StartStream(fStream); + if (err == paNoError) { + return 0; + } + JackAudioDriver::Stop(); + } + return -1; } int JackPortAudioDriver::Stop() { jack_log("JackPortAudioDriver::Stop"); PaError err = Pa_StopStream(fStream); - return (err == paNoError) ? 0 : -1; + int res = (err == paNoError) ? 0 : -1; + if (JackAudioDriver::Stop() < 0) { + res = -1; + } + return res; } int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)