diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index 673968e2..82d8235c 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -180,7 +180,20 @@ int JackAudioDriver::Write() int JackAudioDriver::Process() { - return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); + return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync(); +} + +int JackAudioDriver::ProcessNull() +{ + JackDriver::CycleTakeTime(); + + if (!fEngine->Process(fLastWaitUst)) // fLastWaitUst is set in the "low level" layer + jack_error("JackAudioDriver::ProcessNull Process error"); + fGraphManager->ResumeRefNum(fClientControl, fSynchroTable); + if (ProcessSlaves() < 0) + jack_error("JackAudioDriver::ProcessNull ProcessSlaves error"); + + return 0; } /* diff --git a/common/JackAudioDriver.h b/common/JackAudioDriver.h index 19e93297..331f6120 100644 --- a/common/JackAudioDriver.h +++ b/common/JackAudioDriver.h @@ -61,6 +61,7 @@ class EXPORT JackAudioDriver : public JackDriver virtual ~JackAudioDriver(); virtual int Process(); + virtual int ProcessNull(); virtual int Open(jack_nframes_t nframes, jack_nframes_t samplerate, diff --git a/common/JackDriver.h b/common/JackDriver.h index 7bf6acba..6399be8e 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -75,6 +75,7 @@ class EXPORT JackDriverInterface virtual int SetSampleRate(jack_nframes_t sample_rate) = 0; virtual int Process() = 0; + virtual int ProcessNull() = 0; virtual void SetMaster(bool onoff) = 0; virtual bool GetMaster() = 0; @@ -188,6 +189,11 @@ class EXPORT JackDriver : public JackDriverClient return 0; } + virtual int ProcessNull() + { + return 0; + } + virtual int Attach() { return 0; diff --git a/common/JackDummyDriver.h b/common/JackDummyDriver.h index 2a12f7df..3b074d5b 100644 --- a/common/JackDummyDriver.h +++ b/common/JackDummyDriver.h @@ -30,7 +30,7 @@ namespace Jack \brief The dummy driver. */ -class JackDummyDriver : public JackAudioDriver +class EXPORT JackDummyDriver : public JackAudioDriver { private: diff --git a/common/JackNetDriver.cpp b/common/JackNetDriver.cpp index 4778db38..605c9d82 100644 --- a/common/JackNetDriver.cpp +++ b/common/JackNetDriver.cpp @@ -25,10 +25,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "driver_interface.h" #include "JackDriverLoader.h" #include "JackThreadedDriver.h" +#include "JackWaitThreadedDriver.h" #include "JackException.h" #include "JackExports.h" -#define DEFAULT_MULTICAST_IP "225.3.19.154" +//#define DEFAULT_MULTICAST_IP "225.3.19.154" +#define DEFAULT_MULTICAST_IP "225.3.19.155" #define DEFAULT_PORT 19000 namespace Jack @@ -85,6 +87,12 @@ namespace Jack { return 0; } + + int JackNetDriver::ProcessNull() + { + usleep(10 * 1000); + return JackAudioDriver::ProcessNull(); + } bool JackNetDriver::Init() { @@ -250,7 +258,6 @@ namespace Jack fMidiPlaybackPortList = NULL; } - int JackNetDriver::SetParams() { fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket; @@ -681,8 +688,13 @@ namespace Jack strncpy ( name, param->value.str, JACK_CLIENT_NAME_SIZE ); } } + /* Jack::JackDriverClientInterface* driver = new Jack::JackRestartThreadedDriver ( new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, midi_input_ports, midi_output_ports, name ) ); + */ + Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver ( + new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, midi_input_ports, midi_output_ports, name ) ); + if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0 ) == 0 ) return driver; diff --git a/common/JackNetDriver.h b/common/JackNetDriver.h index e79473d9..3259334e 100644 --- a/common/JackNetDriver.h +++ b/common/JackNetDriver.h @@ -56,9 +56,6 @@ namespace Jack int fAudioRxLen; int fAudioTxLen; - int Attach(); - int Detach(); - bool Init(); net_status_t GetNetMaster(); net_status_t SendMasterStartSync(); @@ -72,8 +69,7 @@ namespace Jack int Recv ( size_t size, int flags ); int Send ( size_t size, int flags ); - int Read(); - int Write(); + public: JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, const char* ip, size_t port, int midi_input_ports, int midi_output_ports, const char* master_name ); @@ -82,6 +78,14 @@ namespace Jack int Open ( jack_nframes_t frames_per_cycle, jack_nframes_t rate, bool capturing, bool playing, int inchannels, int outchannels, bool monitor, const char* capture_driver_name, const char* playback_driver_name, jack_nframes_t capture_latency, jack_nframes_t playback_latency ); + + int ProcessNull(); + + int Attach(); + int Detach(); + + int Read(); + int Write(); }; } diff --git a/common/JackThreadedDriver.cpp b/common/JackThreadedDriver.cpp index 50902bc8..e8f732d8 100644 --- a/common/JackThreadedDriver.cpp +++ b/common/JackThreadedDriver.cpp @@ -142,6 +142,6 @@ bool JackRestartThreadedDriver::Execute() return false; } } - } +} } // end of namespace diff --git a/common/JackThreadedDriver.h b/common/JackThreadedDriver.h index d1136c92..e4490294 100644 --- a/common/JackThreadedDriver.h +++ b/common/JackThreadedDriver.h @@ -73,6 +73,11 @@ class EXPORT JackThreadedDriver : public JackDriverClientInterface, public JackR { return fDriver->Process(); } + + int ProcessNull() + { + return fDriver->ProcessNull(); + } int Attach() { @@ -150,7 +155,7 @@ class EXPORT JackThreadedDriver : public JackDriverClientInterface, public JackR class EXPORT JackRestartThreadedDriver : public JackThreadedDriver { - public: + public: JackRestartThreadedDriver(JackDriverClient* driver):JackThreadedDriver(driver) {} @@ -161,7 +166,6 @@ class EXPORT JackRestartThreadedDriver : public JackThreadedDriver virtual bool Execute(); }; - } // end of namespace diff --git a/common/JackWaitThreadedDriver.cpp b/common/JackWaitThreadedDriver.cpp new file mode 100644 index 00000000..69aa2509 --- /dev/null +++ b/common/JackWaitThreadedDriver.cpp @@ -0,0 +1,85 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004-2008 Grame + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#ifdef WIN32 +#pragma warning (disable : 4786) +#endif + +#include "JackWaitThreadedDriver.h" +#include "JackGlobals.h" +#include "JackClient.h" +#include "JackEngineControl.h" +#include "JackException.h" +#include "JackError.h" + +namespace Jack +{ + +bool JackWaitThreadedDriver::Init() +{ + return (fStarter.Start() == 0); +} + +bool JackWaitThreadedDriver::Execute() +{ + try { + // Process a null cycle until NetDriver has started + while (!fStarter.fRunning && fThread.GetStatus() == JackThread::kRunning) { + fDriver->ProcessNull(); + } + + // Set RT + if (fDriver->IsRealTime()) { + jack_log("JackWaitThreadedDriver::Init IsRealTime"); + // Will do "something" on OSX only... + fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint); + if (fThread.AcquireRealTime(GetEngineControl()->fPriority) < 0) { + jack_error("AcquireRealTime error"); + } else { + set_threaded_log_function(); + } + } + + // Switch to keep running even in case of error + while (fThread.GetStatus() == JackThread::kRunning) { + fDriver->Process(); + } + return false; + } catch (JackDriverException e) { + e.PrintMessage(); + jack_log("Driver is restarted"); + fThread.DropRealTime(); + // Thread in kIniting status again... + fThread.SetStatus(JackThread::kIniting); + if (Init()) { + // Thread in kRunning status again... + fThread.SetStatus(JackThread::kRunning); + return true; + } else { + return false; + } + } +} + +} // end of namespace diff --git a/common/JackWaitThreadedDriver.h b/common/JackWaitThreadedDriver.h new file mode 100644 index 00000000..2abf27a0 --- /dev/null +++ b/common/JackWaitThreadedDriver.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004-2008 Grame + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackWaitThreadedDriver__ +#define __JackWaitThreadedDriver__ + +#include "JackThreadedDriver.h" +#include "JackAudioDriver.h" + +namespace Jack +{ + +class EXPORT JackWaitThreadedDriver : public JackThreadedDriver +{ + private: + + struct EXPORT JackDriverStarter : public JackRunnableInterface + { + + JackDriverClient* fDriver; + JackThread fThread; + bool fRunning; + + JackDriverStarter(JackDriverClient* driver) + :fDriver(driver),fThread(this),fRunning(false) + {} + + ~JackDriverStarter() + { + fThread.Kill(); + } + + int Start() + { + fRunning = false; + return fThread.Start(); + } + + // JackRunnableInterface interface + bool Execute() + { + // Blocks until driver is started... + fDriver->Init(); + fRunning = true; + return false; + } + + }; + + JackDriverStarter fStarter; + + public: + + JackWaitThreadedDriver(JackDriverClient* netdriver) + :JackThreadedDriver(netdriver),fStarter(netdriver) + {} + virtual ~JackWaitThreadedDriver() + {} + + // JackRunnableInterface interface + bool Init(); + bool Execute(); +}; + + +} // end of namespace + + +#endif diff --git a/example-clients/lsp.c b/example-clients/lsp.c index baaa9b91..db8b4543 100644 --- a/example-clients/lsp.c +++ b/example-clients/lsp.c @@ -143,6 +143,8 @@ main (int argc, char *argv[]) } ports = jack_get_ports (client, NULL, NULL, 0); + if (!ports) + goto error; for (i = 0; ports[i]; ++i) { // skip over any that don't match ALL of the strings presented at command line @@ -152,10 +154,9 @@ main (int argc, char *argv[]) skip_port = 1; } } - if(skip_port) continue; + if (skip_port) continue; printf ("%s\n", ports[i]); - port = jack_port_by_name (client, ports[i]); if (show_aliases) { @@ -218,6 +219,8 @@ main (int argc, char *argv[]) } } } + +error: jack_client_close (client); exit (0); } diff --git a/example-clients/metro.c b/example-clients/metro.c index 92375569..382a2b80 100644 --- a/example-clients/metro.c +++ b/example-clients/metro.c @@ -259,7 +259,7 @@ main (int argc, char *argv[]) } if (jack_activate (client)) { - fprintf (stderr, "cannot activate client"); + fprintf (stderr, "cannot activate client\n"); return 1; } diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index 14da101b..98eaa4fe 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -518,6 +518,8 @@ 4BAB95BB0B9E20B800A0C723 /* JackPortType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BAB95B70B9E20B800A0C723 /* JackPortType.h */; }; 4BAB95ED0B9E21A500A0C723 /* JackAudioPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */; }; 4BAB95EE0B9E21A500A0C723 /* JackAudioPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */; }; + 4BBC93BA0DF9736C002DF220 /* JackWaitThreadedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBC93B80DF9736C002DF220 /* JackWaitThreadedDriver.cpp */; }; + 4BBC93BB0DF9736C002DF220 /* JackWaitThreadedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BBC93B90DF9736C002DF220 /* JackWaitThreadedDriver.h */; }; 4BC216850A444BAD00BDA09F /* JackServerAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF8D1F50834EFB000C94B91 /* JackServerAPI.cpp */; }; 4BC216890A444BDE00BDA09F /* JackServerGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC216880A444BDE00BDA09F /* JackServerGlobals.cpp */; }; 4BC2168E0A444BED00BDA09F /* JackServerGlobals.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC2168D0A444BED00BDA09F /* JackServerGlobals.h */; }; @@ -1267,6 +1269,8 @@ 4BAB95B70B9E20B800A0C723 /* JackPortType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackPortType.h; path = ../common/JackPortType.h; sourceTree = SOURCE_ROOT; }; 4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioPort.cpp; path = ../common/JackAudioPort.cpp; sourceTree = SOURCE_ROOT; }; 4BB371D40C1AD85A0050C1E4 /* JackNotification.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackNotification.h; path = ../common/JackNotification.h; sourceTree = SOURCE_ROOT; }; + 4BBC93B80DF9736C002DF220 /* JackWaitThreadedDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWaitThreadedDriver.cpp; path = ../common/JackWaitThreadedDriver.cpp; sourceTree = SOURCE_ROOT; }; + 4BBC93B90DF9736C002DF220 /* JackWaitThreadedDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWaitThreadedDriver.h; path = ../common/JackWaitThreadedDriver.h; sourceTree = SOURCE_ROOT; }; 4BBD13CC08C71EB40079F7FF /* testSynchroServerClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroServerClient.cpp; path = ../tests/testSynchroServerClient.cpp; sourceTree = SOURCE_ROOT; }; 4BC216880A444BDE00BDA09F /* JackServerGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackServerGlobals.cpp; path = ../common/JackServerGlobals.cpp; sourceTree = SOURCE_ROOT; }; 4BC2168D0A444BED00BDA09F /* JackServerGlobals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackServerGlobals.h; path = ../common/JackServerGlobals.h; sourceTree = SOURCE_ROOT; }; @@ -2478,6 +2482,8 @@ 4BD56D8707968982006D44F9 /* Threaded */ = { isa = PBXGroup; children = ( + 4BBC93B90DF9736C002DF220 /* JackWaitThreadedDriver.h */, + 4BBC93B80DF9736C002DF220 /* JackWaitThreadedDriver.cpp */, 4BF8D1BD0834EEFC00C94B91 /* JackThreadedDriver.h */, 4BF8D1BE0834EEFC00C94B91 /* JackThreadedDriver.cpp */, 4BF8D1B90834EEF100C94B91 /* JackFreewheelDriver.h */, @@ -3017,6 +3023,7 @@ 4B9A26020DBF8584006E9FBC /* jslist.h in Headers */, 4B4F9C8D0DC20C0400706CB0 /* JackMessageBuffer.h in Headers */, 4B5F253E0DEE9B8F0041E486 /* JackLockedEngine.h in Headers */, + 4BBC93BB0DF9736C002DF220 /* JackWaitThreadedDriver.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5611,6 +5618,7 @@ 4B9A25B60DBF8330006E9FBC /* JackError.cpp in Sources */, 4B02069E0DC0BAB400319AF1 /* JackProcessSync.cpp in Sources */, 4B4F9C8C0DC20C0400706CB0 /* JackMessageBuffer.cpp in Sources */, + 4BBC93BA0DF9736C002DF220 /* JackWaitThreadedDriver.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };