Browse Source

Merge branch 'master' into no-self-connect

Conflicts:
	common/Jackdmp.cpp
tags/v1.9.10
Nedko Arnaudov 15 years ago
parent
commit
e418ea102a
100 changed files with 9392 additions and 1136 deletions
  1. +150
    -12
      ChangeLog
  2. +1
    -0
      README
  3. +35
    -10
      common/JackAPI.cpp
  4. +4
    -0
      common/JackArgParser.cpp
  5. +10
    -2
      common/JackAudioAdapterInterface.cpp
  6. +2
    -1
      common/JackAudioDriver.cpp
  7. +1
    -1
      common/JackChannel.h
  8. +65
    -30
      common/JackClient.cpp
  9. +5
    -2
      common/JackClient.h
  10. +1
    -1
      common/JackClientInterface.h
  11. +3
    -2
      common/JackConstants.h
  12. +5
    -0
      common/JackControlAPI.cpp
  13. +8
    -2
      common/JackDebugClient.cpp
  14. +2
    -1
      common/JackDebugClient.h
  15. +15
    -6
      common/JackDriver.cpp
  16. +2
    -1
      common/JackDriver.h
  17. +1
    -1
      common/JackDriverLoader.cpp
  18. +36
    -25
      common/JackEngine.cpp
  19. +5
    -3
      common/JackEngine.h
  20. +2
    -0
      common/JackEngineControl.h
  21. +1
    -3
      common/JackError.cpp
  22. +0
    -2
      common/JackError.h
  23. +19
    -1
      common/JackException.h
  24. +2
    -2
      common/JackExternalClient.cpp
  25. +1
    -1
      common/JackExternalClient.h
  26. +2
    -0
      common/JackGlobals.cpp
  27. +2
    -2
      common/JackGlobals.h
  28. +28
    -8
      common/JackGraphManager.cpp
  29. +2
    -2
      common/JackInternalClientChannel.h
  30. +16
    -8
      common/JackLibAPI.cpp
  31. +2
    -2
      common/JackLibClient.cpp
  32. +1
    -1
      common/JackLibClient.h
  33. +91
    -6
      common/JackLockedEngine.h
  34. +13
    -6
      common/JackMessageBuffer.cpp
  35. +4
    -1
      common/JackMessageBuffer.h
  36. +3
    -3
      common/JackNetAdapter.cpp
  37. +21
    -11
      common/JackNetDriver.cpp
  38. +4
    -3
      common/JackNetDriver.h
  39. +6
    -1
      common/JackNetManager.cpp
  40. +1143
    -0
      common/JackNetOneDriver.cpp
  41. +96
    -0
      common/JackNetOneDriver.h
  42. +2
    -0
      common/JackNetTool.cpp
  43. +1
    -0
      common/JackNotification.h
  44. +10
    -6
      common/JackRequest.h
  45. +1
    -1
      common/JackRestartThreadedDriver.cpp
  46. +8
    -5
      common/JackServer.cpp
  47. +16
    -8
      common/JackServerAPI.cpp
  48. +1
    -1
      common/JackServerGlobals.h
  49. +9
    -2
      common/JackShmMem.cpp
  50. +14
    -12
      common/JackShmMem.h
  51. +8
    -3
      common/JackThread.h
  52. +4
    -4
      common/JackThreadedDriver.cpp
  53. +1
    -1
      common/JackThreadedDriver.h
  54. +28
    -14
      common/JackTools.cpp
  55. +7
    -2
      common/JackTools.h
  56. +2
    -1
      common/JackTransportEngine.cpp
  57. +3
    -3
      common/JackWaitThreadedDriver.cpp
  58. +103
    -84
      common/JackWeakAPI.cpp
  59. +66
    -27
      common/Jackdmp.cpp
  60. +51
    -1
      common/jack/jack.h
  61. +8
    -4
      common/jack/jslist.h
  62. +26
    -1
      common/jack/types.h
  63. +19
    -12
      common/memops.c
  64. +746
    -0
      common/netjack.c
  65. +147
    -0
      common/netjack.h
  66. +1520
    -0
      common/netjack_packet.c
  67. +165
    -0
      common/netjack_packet.h
  68. +193
    -189
      common/ringbuffer.c
  69. +2
    -2
      dbus/audio_reserve.c
  70. +2
    -2
      dbus/controller_iface_control.c
  71. +2
    -1
      dbus/controller_iface_patchbay.c
  72. +2
    -2
      dbus/sigsegv.c
  73. +757
    -0
      example-clients/alsa_in.c
  74. +755
    -0
      example-clients/alsa_out.c
  75. +16
    -5
      example-clients/bufsize.c
  76. +1
    -1
      example-clients/internal_metro.cpp
  77. +780
    -0
      example-clients/netsource.c
  78. +85
    -0
      example-clients/samplerate.c
  79. +136
    -0
      example-clients/wait.c
  80. +45
    -3
      example-clients/wscript
  81. +1
    -2
      example-clients/zombie.c
  82. +9
    -1
      linux/wscript
  83. +5
    -5
      macosx/JackMacEngineRPC.cpp
  84. +6
    -6
      macosx/JackMacLibClientRPC.cpp
  85. +2
    -2
      macosx/JackMachClientChannel.cpp
  86. +1
    -1
      macosx/JackMachClientChannel.h
  87. +3
    -3
      macosx/JackMachNotifyChannel.cpp
  88. +1
    -1
      macosx/JackMachNotifyChannel.h
  89. +11
    -5
      macosx/JackMachServerChannel.cpp
  90. +4
    -1
      macosx/JackMachServerChannel.h
  91. +1
    -1
      macosx/JackMachServerNotifyChannel.cpp
  92. +26
    -10
      macosx/JackMachThread.cpp
  93. +10
    -4
      macosx/JackMachThread.h
  94. +1527
    -492
      macosx/Jackdmp.xcodeproj/project.pbxproj
  95. +4
    -2
      macosx/RPC/JackRPCClient.defs
  96. +5
    -1
      macosx/RPC/JackRPCClient.h
  97. +196
    -18
      macosx/RPC/JackRPCClientServer.c
  98. +24
    -17
      macosx/RPC/JackRPCClientUser.c
  99. +3
    -3
      macosx/RPC/JackRPCEngine.defs
  100. +1
    -1
      macosx/RPC/JackRPCEngine.h

+ 150
- 12
ChangeLog View File

@@ -25,17 +25,155 @@ Paul Davis
Jackdmp changes log
---------------------------

2009-07-22 Stephane Letz <letz@grame.fr>
2009-11-18 Stephane Letz <letz@grame.fr>
* Sync JackCoreAudioAdapter code with JackCoreAudioDriver.

2009-11-17 Stephane Letz <letz@grame.fr>
* In JackCoreAudio driver, clock drift compensation in aggregated devices working.
* In JackCoreAudio driver, clock drift compensation semantic changed a bit : when on, does not activate if not needed (same clock domain).

2009-11-16 Stephane Letz <letz@grame.fr>
* In JackCoreAudio driver, (possibly) clock drift compensation when needed in aggregated devices.

2009-11-14 Stephane Letz <letz@grame.fr>
* Sync with JACK1 : -r parameter now used for no-realtime, realtime (-R) is now default, usable backend given vie platform.

2009-11-13 Stephane Letz <letz@grame.fr>
* Better memory allocation error checking in ringbuffer.c, weak import improvements.
* Memory allocation error checking for jack_client_new and jack_client_open (server and client side).
* Memory allocation error checking in server for RPC.
* Simplify server temporary mode : now use a JackTemporaryException.
* Lock/Unlock shared memory segments (to test...).

2009-11-12 Stephane Letz <letz@grame.fr>
* Better memory allocation error checking on client (library) side.

2009-11-11 Stephane Letz <letz@grame.fr>
* Correct JackCoreAudio driver when empty strings are given as -C, -P or -d parameter.

2009-11-10 Stephane Letz <letz@grame.fr>
* Version 1.9.4 started.
* Solaris boomer backend now working in capture or playback only mode.
* Fix control.h for proper compilation on Solaris.
* Correct JackInfoShutdownCallback prototype, two new JackClientProcessFailure and JackClientZombie JackStatus code.

2009-11-09 Stephane Letz <letz@grame.fr>
* Correct JackGraphManager::GetBuffer for the "client loop with one connection" case : buffer must be copied.

2009-11-07 Stephane Letz <letz@grame.fr>
* Fix AcquireRealTime and DropRealTime: now distinguish when called from another thread (AcquireRealTime/DropRealTime) and from the thread itself (AcquireSelfRealTime/DropSelfRealTime).
* Correct JackPosixThread::StartImp : thread priority setting now done in the RT case only.

2009-11-06 Stephane Letz <letz@grame.fr>
* Correctly save and restore RT mode state in freewheel mode.
* Correct freewheel code on client side.

2009-11-05 Stephane Letz <letz@grame.fr>
* No reason to make jack_on_shutdown deprecated, so revert the incorrect change.
* Thread AcquireRealTime and DropRealTime were (incorrectly) using fThread field. Use pthread_self()) (or GetCurrentThread() on Windows) to get the calling thread.

2009-10-30 Stephane Letz <letz@grame.fr>
* In JackCoreAudioDriver, improve management of input/output channels: -1 is now used internally to indicate a wanted max value.
* In JackCoreAudioDriver::OpenAUHAL, correct stream format setup and cleanup.
* Correct crash bug in JackAudioAdapterInterface when not input is used in adapter (temporary fix...)
* Sync JackCoreAudioAdapter code on JackCoreAudioDriver one.
* JACK_SCHED_POLICY switched to SCHED_FIFO.
* Now can aggregate device that are themselves AD.

2009-10-29 Stephane Letz <letz@grame.fr>
* In JackCoreAudioDriver::Start, wait for the audio driver to effectively start (use the MeasureCallback).

2009-10-28 Stephane Letz <letz@grame.fr>
* In JackCoreAudioDriver, force the SR value to the wanted one *before* creating aggregate device (otherwise creation will fail).
* In JackCoreAudioDriver, better cleanup of AD when intermediate open failure.

2009-10-27 Stephane Letz <letz@grame.fr>
* Dynamic system version detection in JackCoreAudioDriver to either create public or private aggregate device.

2009-10-26 Stephane Letz <letz@grame.fr>
* Implement "hog mode" (exclusive access of the audio device) in JackCoreAudioDriver.
* Fix jack_set_sample_rate_callback to have he same behavior as in JACK1.

2009-10-25 Stephane Letz <letz@grame.fr>
* Improve aggregate device management in JackCoreAudioDriver : now a "private" device only and cleanup properly.
* Aggregate device code added to JackCoreAudioAdapter.

2009-10-23 Stephane Letz <letz@grame.fr>
* Correct JackProcessSync::LockedTimedWait.
* Correct JACK_MESSAGE_SIZE value, particularly in OSX RPC code.
* Now start server channel thread only when backend has been started (so in JackServer::Start). Should solve race conditions at start time.
* jack_verbose moved to JackGlobals class.

2009-10-22 Stephane Letz <letz@grame.fr>
* Correct jackdmp.cpp (failures case were not correct..). Improve JackCoreAudioDriver code. Raise default port number to 2048.

2009-10-20 Stephane Letz <letz@grame.fr>
* Add a string parameter to server ==> client notification, add a new JackInfoShutdownCallback type.
* CoreAudio backend now issue a JackInfoShutdownCallback when an unrecoverable error is detected (sampling rate change, stream configuration changeÉ)
2009-10-17 Stephane Letz <letz@grame.fr>
* Correct server temporary mode : now set a global and quit after server/client message handling is finished.

2009-10-15 Stephane Letz <letz@grame.fr>
* Change CoreAudio notification thread setup for OSX Snow Leopard.

2009-09-18 Stephane Letz <letz@grame.fr>
* Simplify transport in NetJack2: master only can control transport.
2009-09-15 Stephane Letz <letz@grame.fr>
* Correct CPU timing in JackNetDriver, now take cycle begin time after Read.
* Fix issues in JackNetDriver::DecodeTransportData and JackNetDriver::Initialize.
2009-08-28 Stephane Letz <letz@grame.fr>
* Correct monitor port naming in JackAudioDriver and JackCoreAudioDriver.
* Big endian bug fix in memops.c (http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=5;filename=11_be24bit.patch;att=1;bug=486308)
2009-07-31 Stephane Letz <letz@grame.fr>
* Use SNDCTL_DSP_SYNCGROUP/SNDCTL_DSP_SYNCSTART API to synchronize input and output in Solaris boomer backend.
2009-07-29 Stephane Letz <letz@grame.fr>
* Add a -G parameter in CoreAudio backend (the computation value in RT thread expressed as percent of period).
2009-07-28 Stephane Letz <letz@grame.fr>
* Fix CopyAndConvertIn for Solaris backends.
2009-07-22 Stephane Letz <letz@grame.fr>
* Version 1.9.4 started.
* Solaris boomer backend now working in capture or playback only mode.
* Fix control.h for proper compilation on Solaris.
2009-07-17 Stephane Letz <letz@grame.fr>
* Loopback backend reborn as a dynamically loadable separated backend.
* Loopback backend reborn as a dynamically loadable separated backend.
* -L parameter for loopback backend activated again in jackd.

2009-07-17 Stephane Letz <letz@grame.fr>
* Big rewrite of Solaris boomer driver, seems to work in duplex mode at least.
@@ -312,12 +450,12 @@ Paul Davis
2009-01-05 Stephane Letz <letz@grame.fr>
* Synchronize jack2 public headers with jack1 ones.
* Synchronize jack2 public headers with JACK1 ones.
* Implement jack_client_real_time_priority and jack_client_max_real_time_priority API.
2008-12-18 Stephane Letz <letz@grame.fr>
* For ALSA driver, synchronize with latest jack1 memops functions.
* For ALSA driver, synchronize with latest JACK1 memops functions.
* Use memops functions in JackOSSDriver.
* Use memops functions in JackOSSAdapter.
@@ -351,13 +489,13 @@ Paul Davis
2008-11-27 Stephane Letz <letz@grame.fr>
* Add timing profiling code in JackOSSDriver.
* Report ringbuffer.c fixes from jack1.
* Report ringbuffer.c fixes from JACK1.
2008-11-21 Stephane Letz <letz@grame.fr>
* Report ringbuffer.c fixes from jack1.
* Better isolation of server and clients system resources to allow starting the server in several user account at the same time.
* Correct ressource cleanup in case of driver open failure.
* Report ringbuffer.c fixes from JACK1.
* Better isolation of server and clients system resources to allow starting the server in several user account at the same time.
* Correct ressource cleanup in case of driver open failure.
2008-11-19 Stephane Letz <letz@grame.fr>


+ 1
- 0
README View File

@@ -213,6 +213,7 @@ Note : To experiment with the -S option, jackdmp must be launched in a console.
1.9.1 : Fix jackctl_server_unload_internal. Filter SIGPIPE to avoid having client get a SIGPIPE when trying to access a died server. Libjack shutdown handler does not "deactivate" (fActive = false) the client anymore, so that jack_deactivate correctly does the job later on. Better isolation of server and clients system resources to allow starting the server in several user account at the same time. Report ringbuffer.c fixes from jack1. Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown). Use JACK_DRIVER_DIR variable in internal clients loader. For ALSA driver, synchronize with latest jack1 memops functions. Synchronize jack2 public headers with jack1 ones. Implement jack_client_real_time_priority and jack_client_max_real_time_priority API. Use up to BUFFER_SIZE_MAX frames in midi ports, fix for ticket #117. Cleanup server starting code for clients directly linked with libjackserver.so. JackMessageBuffer was using thread "Stop" scheme in destructor, now use the safer thread "Kill" way. Synchronize ALSA backend code with JACK1 one. Set default mode to 'slow' in JackNetDriver and JackNetAdapter. Simplify audio packet order verification. Fix JackNetInterface::SetNetBufferSize for socket buffer size computation and JackNetMasterInterface::DataRecv if synch packet is received, various cleanup. Better recovery of network overload situations, now "resynchronize" by skipping cycles.". Support for BIG_ENDIAN machines in NetJack2. Support for BIG_ENDIAN machines in NetJack2 for MIDI ports. Support for "-h" option in internal clients to print the parameters. In NetJack2, fix a bug when capture or playback only channels are used. Add a JACK_INTERNAL_DIR environment variable to be used for internal clients. Add a resample quality parameter in audioadapter. Now correctly return an error if JackServer::SetBufferSize could not change the buffer size (and was just restoring the current one). Use PRIu32 kind of macro in JackAlsaDriver again. Add a resample quality parameter in netadapter.
1.9.2 : Solaris version. New "profiling" tools. Rework the mutex/signal classes. Support for BIG_ENDIAN machines in NetJack2. D-BUS based device reservation to better coexist with PulseAudio on Linux. Add auto_connect parameter in netmanager and netadapter. Use Torben Hohn PI controler code for adapters. Client incorrect re-naming fixed : now done at socket and fifo level. Virtualize and allow overriding of thread creation function, to allow Wine support (from JACK1).
1.9.3 : New JackBoomerDriver class for Boomer driver on Solaris. Add mixed 32/64 bits mode (off by default). Native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver). In ALSA audio card reservation code, tries to open the card even if reservation fails. Clock source setting on Linux. Add jackctl_server_switch_master API. Fix transport callback (timebase master, sync) issue when used after jack_activate (RT thread was not running). D-Bus access for jackctl_server_add_slave/jackctl_server_remove_slave API. Cleanup "loopback" stuff in server. Torben Hohn fix for InitTime and GetMicroSeconds in JackWinTime.c. New jack_free function added in jack.h. Reworked Torben Hohn fix for server restart issue on Windows. Correct jack_set_error_function, jack_set_info_function and jack_set_thread_creator functions. Correct JackFifo::TimedWait for EINTR handling. Move DBus based audio device reservation code in ALSA backend compilation. Correct JackTransportEngine::MakeAllLocating, sync callback has to be called in this case also. NetJack2 code : better error checkout, method renaming. Tim Bechmann patch : hammerfall, only release monitor thread, if it has been created. Tim Bechmann memops.c optimization patches. In combined --dbus and --classic compilation code, use PulseAudio acquire/release code. Big rewrite of Solaris boomer driver, seems to work in duplex mode at least. Loopback backend reborn as a dynamically loadable separated backend.
1.9.4 : Solaris boomer backend now working in capture or playback only mode. Add a -G parameter in CoreAudio backend (the computation value in RT thread expressed as percent of period). Use SNDCTL_DSP_SYNCGROUP/SNDCTL_DSP_SYNCSTART API to synchronize input and output in Solaris boomer backend. Big endian bug fix in memops.c. Fix issues in JackNetDriver::DecodeTransportData and JackNetDriver::Initialize. Correct CPU timing in JackNetDriver, now take cycle begin time after Read. Simplify transport in NetJack2: master only can control transport. Change CoreAudio notification thread setup for OSX Snow Leopard. Correct server temporary mode : now set a global and quit after server/client message handling is finished. Add a string parameter to server ==> client notification, add a new JackInfoShutdownCallback type. CoreAudio backend now issue a JackInfoShutdownCallback when an unrecoverable error is detected (sampling rate change, stream configuration changeÉ). Correct jackdmp.cpp (failures case were not correct..). Improve JackCoreAudioDriver code. Raise default port number to 2048. Correct JackProcessSync::LockedTimedWait. Correct JACK_MESSAGE_SIZE value, particularly in OSX RPC code. Now start server channel thread only when backend has been started (so in JackServer::Start). Should solve race conditions at start time. jack_verbose moved to JackGlobals class. Improve aggregate device management in JackCoreAudioDriver : now a "private" device only and cleanup properly. Aggregate device code added to JackCoreAudioAdapter. Implement "hog mode" (exclusive access of the audio device) in JackCoreAudioDriver. Fix jack_set_sample_rate_callback to have he same behavior as in JACK1. Dynamic system version detection in JackCoreAudioDriver to either create public or private aggregate device. In JackCoreAudioDriver, force the SR value to the wanted one *before* creating aggregate device (otherwise creation will fail). In JackCoreAudioDriver, better cleanup of AD when intermediate open failure. In JackCoreAudioDriver::Start, wait for the audio driver to effectively start (use the MeasureCallback). In JackCoreAudioDriver, improve management of input/output channels: -1 is now used internally to indicate a wanted max value. In JackCoreAudioDriver::OpenAUHAL, correct stream format setup and cleanup. Correct crash bug in JackAudioAdapterInterface when not input is used in adapter (temporary fixÉ). Sync JackCoreAudioAdapter code on JackCoreAudioDriver one. JACK_SCHED_POLICY switched to SCHED_FIFO. Now can aggregate device that are themselves AD. No reason to make jack_on_shutdown deprecated, so revert the incorrect change. Thread AcquireRealTime and DropRealTime were (incorrectly) using fThread field. Use pthread_self()) (or GetCurrentThread() on Windows) to get the calling thread. Correctly save and restore RT mode state in freewheel mode. Correct freewheel code on client side. Fix AcquireRealTime and DropRealTime: now distinguish when called from another thread (AcquireRealTime/DropRealTime) and from the thread itself (AcquireSelfRealTime/DropSelfRealTime). Correct JackPosixThread::StartImp : thread priority setting now done in the RT case only. Correct JackGraphManager::GetBuffer for the "client loop with one connection" case : buffer must be copied. Correct JackInfoShutdownCallback prototype, two new JackClientProcessFailure and JackClientZombie JackStatus code. Correct JackCoreAudio driver when empty strings are given as -C, -P or -d parameter. Better memory allocation error checking on client (library) side. Better memory allocation error checking in ringbuffer.c, weak import improvements. Memory allocation error checking for jack_client_new and jack_client_open (server and client side). Memory allocation error checking in server for RPC. Simplify server temporary mode : now use a JackTemporaryException. Lock/Unlock shared memory segments (to test...). Sync with JACK1 : -r parameter now used for no-realtime, realtime (-R) is now default, usable backend given vie platform. In JackCoreAudio driver, (possibly) clock drift compensation when needed in aggregated devices. In JackCoreAudio driver, clock drift compensation in aggregated devices working. In JackCoreAudio driver, clock drift compensation semantic changed a bit : when on, does not activate if not needed (same clock domain). Sync JackCoreAudioAdapter code with JackCoreAudioDriver.
This is a work in progress but the implementation is now stable enough to be tested. jackdmp has been used successfully with the following applications : Ardour, Hydrogen, Jamin, Qjackctl, Jack-Rack, SooperLooper, AlsaPlayer...


+ 35
- 10
common/JackAPI.cpp View File

@@ -72,6 +72,8 @@ extern "C"
EXPORT int jack_is_realtime (jack_client_t *client);
EXPORT void jack_on_shutdown (jack_client_t *client,
JackShutdownCallback shutdown_callback, void *arg);
EXPORT void jack_on_info_shutdown (jack_client_t *client,
JackInfoShutdownCallback shutdown_callback, void *arg);
EXPORT int jack_set_process_callback (jack_client_t *client,
JackProcessCallback process_callback,
void *arg);
@@ -288,15 +290,23 @@ EXPORT void jack_set_info_function (print_function func)

EXPORT jack_client_t* jack_client_new(const char* client_name)
{
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
jack_error("jack_client_new: deprecated");
int options = JackUseExactName;
if (getenv("JACK_START_SERVER") == NULL)
options |= JackNoStartServer;
jack_client_t* res = jack_client_open_aux(client_name, (jack_options_t)options, NULL, NULL);
JackGlobals::fOpenMutex->Unlock();
return res;
try {
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
jack_error("jack_client_new: deprecated");
int options = JackUseExactName;
if (getenv("JACK_START_SERVER") == NULL)
options |= JackNoStartServer;
jack_client_t* res = jack_client_open_aux(client_name, (jack_options_t)options, NULL, NULL);
JackGlobals::fOpenMutex->Unlock();
return res;
} catch (std::bad_alloc& e) {
jack_error("Memory allocation error...");
return NULL;
} catch (...) {
jack_error("Unknown error...");
return NULL;
}
}

EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames)
@@ -819,6 +829,19 @@ EXPORT void jack_on_shutdown(jack_client_t* ext_client, JackShutdownCallback cal
}
}

EXPORT void jack_on_info_shutdown(jack_client_t* ext_client, JackInfoShutdownCallback callback, void* arg)
{
#ifdef __CLIENTDEBUG__
JackLibGlobals::CheckContext();
#endif
JackClient* client = (JackClient*)ext_client;
if (client == NULL) {
jack_error("jack_on_info_shutdown called with a NULL client");
} else {
client->OnInfoShutdown(callback, arg);
}
}

EXPORT int jack_set_process_callback(jack_client_t* ext_client, JackProcessCallback callback, void* arg)
{
#ifdef __CLIENTDEBUG__
@@ -1928,5 +1951,7 @@ jack_get_version_string()

EXPORT void jack_free(void* ptr)
{
free(ptr);
if (ptr) {
free(ptr);
}
}

+ 4
- 0
common/JackArgParser.cpp View File

@@ -128,6 +128,10 @@ namespace Jack {
return -1;
//else allocate and fill it
argv = (char**)calloc (fArgv.size(), sizeof(char*));
if (argv == NULL)
{
return -1;
}
for ( unsigned int i = 0; i < fArgv.size(); i++ )
{
argv[i] = (char*)calloc(fArgv[i].length(), sizeof(char));


+ 10
- 2
common/JackAudioAdapterInterface.cpp View File

@@ -230,10 +230,18 @@ namespace Jack
// Finer estimation of the position in the ringbuffer
int delta_frames = (fPullAndPushTime > 0) ? (int)((float(long(GetMicroSeconds() - fPullAndPushTime)) * float(fAdaptedSampleRate)) / 1000000.f) : 0;
double ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
double ratio = 1;
// TODO : done like this just to avoid crash when input only or output only...
if (fCaptureChannels > 0)
ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
else if (fPlaybackChannels > 0)
ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
#ifdef JACK_MONITOR
fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
if (fCaptureRingBuffer[0] != NULL)
fTable.Write(fCaptureRingBuffer[0]->GetError(), fCaptureRingBuffer[0]->GetError() - delta_frames, ratio, 1/ratio, fCaptureRingBuffer[0]->ReadSpace(), fCaptureRingBuffer[0]->ReadSpace());
#endif
// Push/pull from ringbuffer


+ 2
- 1
common/JackAudioDriver.cpp View File

@@ -139,12 +139,13 @@ int JackAudioDriver::Attach()
// Monitor ports
if (fWithMonitorPorts) {
jack_log("Create monitor port ");
snprintf(name, sizeof(name) - 1, "%s:%s:monitor_%u", fAliasName, fPlaybackDriverName, i + 1);
snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1);
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) {
jack_error("Cannot register monitor port for %s", name);
return -1;
} else {
port = fGraphManager->GetPort(port_index);
port->SetAlias(alias);
port->SetLatency(fEngineControl->fBufferSize);
fMonitorPortList[i] = port_index;
}


+ 1
- 1
common/JackChannel.h View File

@@ -82,7 +82,7 @@ class JackClientChannelInterface
virtual void ClientClose(int refnum, int* result)
{}

virtual void ClientActivate(int refnum, int state, int* result)
virtual void ClientActivate(int refnum, int is_real_time, int* result)
{}
virtual void ClientDeactivate(int refnum, int* result)
{}


+ 65
- 30
common/JackClient.cpp View File

@@ -49,6 +49,7 @@ JackClient::JackClient(JackSynchro* table):fThread(this)
fGraphOrder = NULL;
fXrun = NULL;
fShutdown = NULL;
fInfoShutdown = NULL;
fInit = NULL;
fBufferSize = NULL;
fClientRegistration = NULL;
@@ -63,6 +64,7 @@ JackClient::JackClient(JackSynchro* table):fThread(this)
fGraphOrderArg = NULL;
fXrunArg = NULL;
fShutdownArg = NULL;
fInfoShutdownArg = NULL;
fInitArg = NULL;
fBufferSizeArg = NULL;
fFreewheelArg = NULL;
@@ -132,12 +134,12 @@ void JackClient::SetupDriverSync(bool freewheel)
\brief Notification received from the server.
*/

int JackClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
return 0;
}

int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
int res = 0;

@@ -145,11 +147,11 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync,
switch (notify) {

case kAddClient:
res = ClientNotifyImp(refnum, name, notify, sync, value1, value2);
res = ClientNotifyImp(refnum, name, notify, sync, message, value1, value2);
break;

case kRemoveClient:
res = ClientNotifyImp(refnum, name, notify, sync, value1, value2);
res = ClientNotifyImp(refnum, name, notify, sync, message, value1, value2);
break;

case kActivateClient:
@@ -168,84 +170,107 @@ int JackClient::ClientNotify(int refnum, const char* name, int notify, int sync,

case kAddClient:
jack_log("JackClient::kAddClient fName = %s name = %s", GetClientControl()->fName, name);
if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) // Don't call the callback for the registering client itself
if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) { // Don't call the callback for the registering client itself
fClientRegistration(name, 1, fClientRegistrationArg);
}
break;

case kRemoveClient:
jack_log("JackClient::kRemoveClient fName = %s name = %s", GetClientControl()->fName, name);
if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) // Don't call the callback for the registering client itself
if (fClientRegistration && strcmp(GetClientControl()->fName, name) != 0) { // Don't call the callback for the registering client itself
fClientRegistration(name, 0, fClientRegistrationArg);
}
break;

case kBufferSizeCallback:
jack_log("JackClient::kBufferSizeCallback buffer_size = %ld", value1);
if (fBufferSize)
if (fBufferSize) {
res = fBufferSize(value1, fBufferSizeArg);
}
break;
case kSampleRateCallback:
jack_log("JackClient::kSampleRateCallback sample_rate = %ld", value1);
if (fSampleRate)
if (fSampleRate) {
res = fSampleRate(value1, fSampleRateArg);
}
break;

case kGraphOrderCallback:
jack_log("JackClient::kGraphOrderCallback");
if (fGraphOrder)
if (fGraphOrder) {
res = fGraphOrder(fGraphOrderArg);
}
break;

case kStartFreewheelCallback:
jack_log("JackClient::kStartFreewheel");
SetupDriverSync(true);
fThread.DropRealTime();
if (fFreewheel)
fThread.DropRealTime(); // Always done (JACK server in RT mode or not...)
if (fFreewheel) {
fFreewheel(1, fFreewheelArg);
}
break;

case kStopFreewheelCallback:
jack_log("JackClient::kStopFreewheel");
SetupDriverSync(false);
if (fFreewheel)
if (fFreewheel) {
fFreewheel(0, fFreewheelArg);
fThread.AcquireRealTime();
}
if (GetEngineControl()->fRealTime) {
fThread.AcquireRealTime();
}
break;

case kPortRegistrationOnCallback:
jack_log("JackClient::kPortRegistrationOn port_index = %ld", value1);
if (fPortRegistration)
if (fPortRegistration) {
fPortRegistration(value1, 1, fPortRegistrationArg);
}
break;

case kPortRegistrationOffCallback:
jack_log("JackClient::kPortRegistrationOff port_index = %ld ", value1);
if (fPortRegistration)
if (fPortRegistration) {
fPortRegistration(value1, 0, fPortRegistrationArg);
}
break;

case kPortConnectCallback:
jack_log("JackClient::kPortConnectCallback src = %ld dst = %ld", value1, value2);
if (fPortConnect)
if (fPortConnect) {
fPortConnect(value1, value2, 1, fPortConnectArg);
}
break;

case kPortDisconnectCallback:
jack_log("JackClient::kPortDisconnectCallback src = %ld dst = %ld", value1, value2);
if (fPortConnect)
if (fPortConnect) {
fPortConnect(value1, value2, 0, fPortConnectArg);
}
break;
case kPortRenameCallback:
jack_log("JackClient::kPortRenameCallback port = %ld");
if (fPortRename)
if (fPortRename) {
fPortRename(value1, GetGraphManager()->GetPort(value1)->GetName(), fPortRenameArg);
}
break;

case kXRunCallback:
jack_log("JackClient::kXRunCallback");
if (fXrun)
if (fXrun) {
res = fXrun(fXrunArg);
}
break;
case kShutDownCallback:
jack_log("JackClient::kShutDownCallback");
if (fInfoShutdown) {
fInfoShutdown((jack_status_t)value1, message, fInfoShutdownArg);
fInfoShutdown = NULL;
}
break;
}
}
@@ -444,7 +469,7 @@ inline void JackClient::End()
jack_log("JackClient::Execute end name = %s", GetClientControl()->fName);
// Hum... not sure about this, the following "close" code is called in the RT thread...
int result;
fThread.DropRealTime();
fThread.DropSelfRealTime();
GetClientControl()->fActive = false;
fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
fThread.Terminate();
@@ -455,7 +480,7 @@ inline void 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...
int result;
fThread.DropRealTime();
fThread.DropSelfRealTime();
GetClientControl()->fActive = false;
fChannel->ClientDeactivate(GetClientControl()->fRefNum, &result);
ShutDown();
@@ -582,7 +607,10 @@ void JackClient::ShutDown()
jack_log("ShutDown");
JackGlobals::fServerRunning = false;
if (fShutdown) {
if (fInfoShutdown) {
fInfoShutdown(JackFailure, "JACK server has been closed", fInfoShutdownArg);
fInfoShutdown = NULL;
} else if (fShutdown) {
fShutdown(fShutdownArg);
fShutdown = NULL;
}
@@ -772,6 +800,17 @@ void JackClient::OnShutdown(JackShutdownCallback callback, void *arg)
fShutdown = callback;
}
}
void JackClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg)
{
if (IsActive()) {
jack_error("You cannot set callbacks on an active client");
} else {
GetClientControl()->fCallback[kShutDownCallback] = (callback != NULL);
fInfoShutdownArg = arg;
fInfoShutdown = callback;
}
}

int JackClient::SetProcessCallback(JackProcessCallback callback, void *arg)
{
@@ -850,6 +889,9 @@ int JackClient::SetSampleRateCallback(JackSampleRateCallback callback, void *arg
GetClientControl()->fCallback[kSampleRateCallback] = (callback != NULL);
fSampleRateArg = arg;
fSampleRate = callback;
// Now invoke it
if (callback)
callback(GetEngineControl()->fSampleRate, arg);
return 0;
}
}
@@ -946,14 +988,7 @@ char* JackClient::GetInternalClientName(int ref)
char name_res[JACK_CLIENT_NAME_SIZE + 1];
int result = -1;
fChannel->GetInternalClientName(GetClientControl()->fRefNum, ref, name_res, &result);

if (result < 0) {
return NULL;
} else {
char* name = (char*)malloc(strlen(name_res));
strcpy(name, name_res);
return name;
}
return (result < 0) ? NULL : strdup(name_res);
}

int JackClient::InternalClientHandle(const char* client_name, jack_status_t* status)


+ 5
- 2
common/JackClient.h View File

@@ -54,6 +54,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
JackGraphOrderCallback fGraphOrder;
JackXRunCallback fXrun;
JackShutdownCallback fShutdown;
JackInfoShutdownCallback fInfoShutdown;
JackThreadInitCallback fInit;
JackBufferSizeCallback fBufferSize;
JackSampleRateCallback fSampleRate;
@@ -70,6 +71,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
void* fGraphOrderArg;
void* fXrunArg;
void* fShutdownArg;
void* fInfoShutdownArg;
void* fInitArg;
void* fBufferSizeArg;
void* fSampleRateArg;
@@ -95,7 +97,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
void CallSyncCallback();
void CallTimebaseCallback();
virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value);
virtual int ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value);

inline void DummyCycle();
inline void ExecuteThread();
@@ -123,7 +125,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface
virtual JackEngineControl* GetEngineControl() const = 0;

// Notifications
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2);
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);

virtual int Activate();
virtual int Deactivate();
@@ -159,6 +161,7 @@ class JackClient : public JackClientInterface, public JackRunnableInterface

// Callbacks
virtual void OnShutdown(JackShutdownCallback callback, void *arg);
virtual void OnInfoShutdown(JackInfoShutdownCallback callback, void *arg);
virtual int SetProcessCallback(JackProcessCallback callback, void* arg);
virtual int SetXRunCallback(JackXRunCallback callback, void* arg);
virtual int SetInitCallback(JackThreadInitCallback callback, void* arg);


+ 1
- 1
common/JackClientInterface.h View File

@@ -44,7 +44,7 @@ class SERVER_EXPORT JackClientInterface
virtual int Close() = 0;

virtual int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2) = 0;
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2) = 0;

virtual JackClientControl* GetClientControl() const = 0;
};


+ 3
- 2
common/JackConstants.h View File

@@ -32,15 +32,16 @@
#define JACK_PORT_TYPE_SIZE 32

#define JACK_CLIENT_NAME_SIZE 64
#define JACK_MESSAGE_SIZE 256

#ifndef PORT_NUM
#define PORT_NUM 1024
#define PORT_NUM 2048
#endif

#define DRIVER_PORT_NUM 256

#ifndef PORT_NUM_FOR_CLIENT
#define PORT_NUM_FOR_CLIENT 512
#define PORT_NUM_FOR_CLIENT 768
#endif

#define FIRST_AVAILABLE_PORT 1


+ 5
- 0
common/JackControlAPI.cpp View File

@@ -624,6 +624,11 @@ get_realtime_priority_constraint()
//jack_info("realtime priority range is (%d,%d)", min, max);

constraint_ptr = (jack_driver_param_constraint_desc_t *)calloc(1, sizeof(jack_driver_param_value_enum_t));
if (constraint_ptr == NULL)
{
jack_error("Cannot allocate memory for jack_driver_param_constraint_desc_t structure.");
return NULL;
}
constraint_ptr->flags = JACK_CONSTRAINT_FLAG_RANGE;

constraint_ptr->constraint.range.min.i = min;


+ 8
- 2
common/JackDebugClient.cpp View File

@@ -139,10 +139,10 @@ JackEngineControl* JackDebugClient::GetEngineControl() const
\brief Notification received from the server.
*/

int JackDebugClient::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackDebugClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
CheckClient();
return fClient->ClientNotify( refnum, name, notify, sync, value1, value2);
return fClient->ClientNotify( refnum, name, notify, sync, message, value1, value2);
}

int JackDebugClient::Activate()
@@ -416,6 +416,12 @@ void JackDebugClient::OnShutdown(JackShutdownCallback callback, void *arg)
fClient->OnShutdown(callback, arg);
}

void JackDebugClient::OnInfoShutdown(JackInfoShutdownCallback callback, void *arg)
{
CheckClient();
fClient->OnInfoShutdown(callback, arg);
}
int JackDebugClient::TimeCallback(jack_nframes_t nframes, void *arg)
{
JackDebugClient* client = (JackDebugClient*)arg;


+ 2
- 1
common/JackDebugClient.h View File

@@ -75,7 +75,7 @@ class JackDebugClient : public JackClient
virtual JackEngineControl* GetEngineControl() const;

// Notifications
int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2);
int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);

int Activate();
int Deactivate();
@@ -110,6 +110,7 @@ class JackDebugClient : public JackClient

// Callbacks
void OnShutdown(JackShutdownCallback callback, void *arg);
void OnInfoShutdown(JackInfoShutdownCallback callback, void *arg);
int SetProcessCallback(JackProcessCallback callback, void* arg);
int SetXRunCallback(JackXRunCallback callback, void* arg);
int SetInitCallback(JackThreadInitCallback callback, void* arg);


+ 15
- 6
common/JackDriver.cpp View File

@@ -167,11 +167,15 @@ int JackDriver::Open(jack_nframes_t buffer_size,

int JackDriver::Close()
{
jack_log("JackDriver::Close");
fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
fClientControl.fActive = false;
fEngineControl->fDriverNum--;
return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
if (fClientControl.fRefNum > 0) {
jack_log("JackDriver::Close");
fGraphManager->DirectDisconnect(fClientControl.fRefNum, fClientControl.fRefNum); // Disconnect driver from itself for sync
fClientControl.fActive = false;
fEngineControl->fDriverNum--;
return fEngine->ClientInternalClose(fClientControl.fRefNum, false);
} else {
return -1;
}
}

/*!
@@ -190,7 +194,7 @@ void JackDriver::SetupDriverSync(int ref, bool freewheel)
}
}

int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
switch (notify) {

@@ -250,6 +254,11 @@ void JackDriver::NotifySampleRate(jack_nframes_t sample_rate)
fEngine->NotifySampleRate(sample_rate);
fEngineControl->InitFrameTime();
}
void JackDriver::NotifyFailure(int code, const char* reason)
{
fEngine->NotifyFailure(code, reason);
}

void JackDriver::SetMaster(bool onoff)
{


+ 2
- 1
common/JackDriver.h View File

@@ -140,6 +140,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface
void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs); // XRun notification sent by the driver
void NotifyBufferSize(jack_nframes_t buffer_size); // BufferSize notification sent by the driver
void NotifySampleRate(jack_nframes_t sample_rate); // SampleRate notification sent by the driver
void NotifyFailure(int code, const char* reason); // Failure notification sent by the driver
public:
@@ -199,7 +200,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface
virtual int SetBufferSize(jack_nframes_t buffer_size);
virtual int SetSampleRate(jack_nframes_t sample_rate);
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2);
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);
virtual JackClientControl* GetClientControl() const;
virtual bool IsRealTime() const;


+ 1
- 1
common/JackDriverLoader.cpp View File

@@ -62,7 +62,7 @@ SERVER_EXPORT void jack_print_driver_options (jack_driver_desc_t* desc, FILE* fi
fprintf (file, "\t-%c, --%s \t%s (default: %s)\n",
desc->params[i].character,
desc->params[i].name,
desc->params[i].short_desc,
desc->params[i].long_desc,
arg_default);
}
}


+ 36
- 25
common/JackEngine.cpp View File

@@ -121,9 +121,7 @@ void JackEngine::ReleaseRefnum(int ref)
// last client and temporay case: quit the server
jack_log("JackEngine::ReleaseRefnum server quit");
fEngineControl->fTemporary = false;
#ifndef WIN32
exit(0);
#endif
throw JackTemporaryException();
}
}
}
@@ -207,7 +205,7 @@ void JackEngine::CheckXRun(jack_time_t callback_usecs) // REVOIR les conditions
// Notifications
//---------------

void JackEngine::NotifyClient(int refnum, int event, int sync, int value1, int value2)
void JackEngine::NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2)
{
JackClientInterface* client = fClientTable[refnum];

@@ -215,20 +213,20 @@ void JackEngine::NotifyClient(int refnum, int event, int sync, int value1, int v
if (!client) {
jack_log("JackEngine::NotifyClient: client not available anymore");
} else if (client->GetClientControl()->fCallback[event]) {
if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, value1, value2) < 0)
if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
} else {
jack_log("JackEngine::NotifyClient: no callback for event = %ld", event);
}
}

void JackEngine::NotifyClients(int event, int sync, int value1, int value2)
void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2)
{
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* client = fClientTable[i];
if (client) {
if (client->GetClientControl()->fCallback[event]) {
if (client->ClientNotify(i, client->GetClientControl()->fName, event, sync, value1, value2) < 0)
if (client->ClientNotify(i, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
} else {
jack_log("JackEngine::NotifyClients: no callback for event = %ld", event);
@@ -244,11 +242,11 @@ int JackEngine::NotifyAddClient(JackClientInterface* new_client, const char* nam
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* old_client = fClientTable[i];
if (old_client) {
if (old_client->ClientNotify(refnum, name, kAddClient, true, 0, 0) < 0) {
if (old_client->ClientNotify(refnum, name, kAddClient, true, "", 0, 0) < 0) {
jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName);
return -1;
}
if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, 0, 0) < 0) {
if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) {
jack_error("NotifyAddClient new_client fails name = %s", name);
return -1;
}
@@ -264,7 +262,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum)
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* client = fClientTable[i];
if (client) {
client->ClientNotify(refnum, name, kRemoveClient, true, 0, 0);
client->ClientNotify(refnum, name, kRemoveClient, true, "",0, 0);
}
}
}
@@ -281,51 +279,64 @@ void JackEngine::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs)
void JackEngine::NotifyXRun(int refnum)
{
if (refnum == ALL_CLIENTS) {
NotifyClients(kXRunCallback, false, 0, 0);
NotifyClients(kXRunCallback, false, "", 0, 0);
} else {
NotifyClient(refnum, kXRunCallback, false, 0, 0);
NotifyClient(refnum, kXRunCallback, false, "", 0, 0);
}
}

void JackEngine::NotifyGraphReorder()
{
NotifyClients(kGraphOrderCallback, false, 0, 0);
NotifyClients(kGraphOrderCallback, false, "", 0, 0);
}

void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size)
{
NotifyClients(kBufferSizeCallback, true, buffer_size, 0);
NotifyClients(kBufferSizeCallback, true, "", buffer_size, 0);
}

void JackEngine::NotifySampleRate(jack_nframes_t sample_rate)
{
NotifyClients(kSampleRateCallback, true, sample_rate, 0);
NotifyClients(kSampleRateCallback, true, "", sample_rate, 0);
}

void JackEngine::NotifyFailure(int code, const char* reason)
{
NotifyClients(kShutDownCallback, false, reason, code, 0);
}
void JackEngine::NotifyFreewheel(bool onoff)
{
fEngineControl->fRealTime = !onoff;
NotifyClients((onoff ? kStartFreewheelCallback : kStopFreewheelCallback), true, 0, 0);
if (onoff) {
// Save RT state
fEngineControl->fSavedRealTime = fEngineControl->fRealTime;
fEngineControl->fRealTime = false;
} else {
// Restore RT state
fEngineControl->fRealTime = fEngineControl->fSavedRealTime;
fEngineControl->fSavedRealTime = false;
}
NotifyClients((onoff ? kStartFreewheelCallback : kStopFreewheelCallback), true, "", 0, 0);
}

void JackEngine::NotifyPortRegistation(jack_port_id_t port_index, bool onoff)
{
NotifyClients((onoff ? kPortRegistrationOnCallback : kPortRegistrationOffCallback), false, port_index, 0);
NotifyClients((onoff ? kPortRegistrationOnCallback : kPortRegistrationOffCallback), false, "", port_index, 0);
}

void JackEngine::NotifyPortRename(jack_port_id_t port)
{
NotifyClients(kPortRenameCallback, false, port, 0);
NotifyClients(kPortRenameCallback, false, "", port, 0);
}

void JackEngine::NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff)
{
NotifyClients((onoff ? kPortConnectCallback : kPortDisconnectCallback), false, src, dst);
NotifyClients((onoff ? kPortConnectCallback : kPortDisconnectCallback), false, "", src, dst);
}

void JackEngine::NotifyActivate(int refnum)
{
NotifyClient(refnum, kActivateClient, true, 0, 0);
NotifyClient(refnum, kActivateClient, true, "", 0, 0);
}

//----------------------------
@@ -483,7 +494,7 @@ int JackEngine::GetClientRefNum(const char* name)
// Used for external clients
int JackEngine::ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
{
jack_log("JackEngine::ClientOpen: name = %s ", name);
jack_log("JackEngine::ClientExternalOpen: name = %s ", name);

int refnum = AllocateRefnum();
if (refnum < 0) {
@@ -535,7 +546,7 @@ error:
// Used for server driver clients
int JackEngine::ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait)
{
jack_log("JackEngine::ClientInternalNew: name = %s", name);
jack_log("JackEngine::ClientInternalOpen: name = %s", name);

int refnum = AllocateRefnum();
if (refnum < 0) {
@@ -640,14 +651,14 @@ int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wai
return 0;
}

int JackEngine::ClientActivate(int refnum, bool state)
int JackEngine::ClientActivate(int refnum, bool is_real_time)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
assert(fClientTable[refnum]);

jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
if (state)
if (is_real_time)
fGraphManager->Activate(refnum);

// Wait for graph state change to be effective


+ 5
- 3
common/JackEngine.h View File

@@ -65,8 +65,9 @@ class SERVER_EXPORT JackEngine
int AllocateRefnum();
void ReleaseRefnum(int ref);

void NotifyClient(int refnum, int event, int sync, int value1, int value2);
void NotifyClients(int event, int sync, int value1, int value2);
void NotifyClient(int refnum, int event, int sync, const char* message, int value1, int value2);
void NotifyClients(int event, int sync, const char* message, int value1, int value2);
void NotifyPortRegistation(jack_port_id_t port_index, bool onoff);
void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff);
void NotifyPortRename(jack_port_id_t src);
@@ -90,7 +91,7 @@ class SERVER_EXPORT JackEngine
int ClientExternalClose(int refnum);
int ClientInternalClose(int refnum, bool wait);

int ClientActivate(int refnum, bool state);
int ClientActivate(int refnum, bool is_real_time);
int ClientDeactivate(int refnum);
int GetClientPID(const char* name);
@@ -118,6 +119,7 @@ class SERVER_EXPORT JackEngine

// Notifications
void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs);
void NotifyFailure(int code, const char* reason);
void NotifyXRun(int refnum);
void NotifyGraphReorder();
void NotifyBufferSize(jack_nframes_t buffer_size);


+ 2
- 0
common/JackEngineControl.h View File

@@ -58,6 +58,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem
float fXrunDelayedUsecs;
bool fTimeOut;
bool fRealTime;
bool fSavedRealTime; // RT state saved and restored during Freewheel mode
int fServerPriority;
int fClientPriority;
int fMaxClientPriority;
@@ -100,6 +101,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem
fTimeOut = (timeout > 0);
fTimeOutUsecs = timeout * 1000;
fRealTime = rt;
fSavedRealTime = false;
fServerPriority = priority;
fClientPriority = (rt) ? priority - 5 : 0;
fMaxClientPriority = (rt) ? priority - 1 : 0;


+ 1
- 3
common/JackError.cpp View File

@@ -25,8 +25,6 @@
#include "JackGlobals.h"
#include "JackMessageBuffer.h"

int jack_verbose = 0;

using namespace Jack;

void change_thread_log_function(jack_log_function_t log_function)
@@ -110,7 +108,7 @@ SERVER_EXPORT void jack_info(const char *fmt, ...)

SERVER_EXPORT void jack_log(const char *fmt,...)
{
if (jack_verbose) {
if (JackGlobals::fVerbose) {
va_list ap;
va_start(ap, fmt);
jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);


+ 0
- 2
common/JackError.h View File

@@ -58,8 +58,6 @@ extern "C"
void jack_log_function(int level, const char *message);
SERVER_EXPORT void set_threaded_log_function();
extern int jack_verbose;

#ifdef __cplusplus
}


+ 19
- 1
common/JackException.h View File

@@ -58,7 +58,25 @@ class SERVER_EXPORT JackException : public std::runtime_error {
};

/*!
\brief Exception possibly thrown by Net Slaves.
\brief Exception thrown by JackEngine in temporary mode.
*/

class SERVER_EXPORT JackTemporaryException : public JackException {
public:
JackTemporaryException(const std::string& msg) : JackException(msg)
{}
JackTemporaryException(char* msg) : JackException(msg)
{}
JackTemporaryException(const char* msg) : JackException(msg)
{}
JackTemporaryException() : JackException("")
{}
};
/*!
\brief Exception possibly thrown by Net slaves.
*/

class SERVER_EXPORT JackNetException : public JackException {


+ 2
- 2
common/JackExternalClient.cpp View File

@@ -33,11 +33,11 @@ JackExternalClient::JackExternalClient(): fClientControl(NULL)
JackExternalClient::~JackExternalClient()
{}

int JackExternalClient::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackExternalClient::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
int result = -1;
jack_log("JackExternalClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify);
fChannel.ClientNotify(refnum, name, notify, sync, value1, value2, &result);
fChannel.ClientNotify(refnum, name, notify, sync, message, value1, value2, &result);
return result;
}



+ 1
- 1
common/JackExternalClient.h View File

@@ -49,7 +49,7 @@ class JackExternalClient : public JackClientInterface
int Open(const char* name, int pid, int refnum, int* shared_client);
int Close();

int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2);
int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);

JackClientControl* GetClientControl() const;
};


+ 2
- 0
common/JackGlobals.cpp View File

@@ -22,6 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
namespace Jack
{

bool JackGlobals::fVerbose = 0;
jack_tls_key JackGlobals::fRealTime;
static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&JackGlobals::fRealTime);



+ 2
- 2
common/JackGlobals.h View File

@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
namespace Jack
{

// Globals used for client management on server or libray side.
// Globals used for client management on server or library side.
struct JackGlobals {

static jack_tls_key fRealTime;
@@ -34,10 +34,10 @@ struct JackGlobals {
static JackMutex* fOpenMutex;
static bool fServerRunning;
static JackClient* fClientTable[];
static bool fVerbose;
#ifndef WIN32
static jack_thread_creator_t fJackThreadCreator;
#endif

};

// Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table.


+ 28
- 8
common/JackGraphManager.cpp View File

@@ -135,8 +135,8 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff
JackConnectionManager* manager = ReadCurrentState();
JackPort* port = GetPort(port_index);

// This happens when a port has just been unregistered and is still used by the RT code
if (!port->IsUsed()) {
// This happens when a port has just been unregistered and is still used by the RT code.
jack_log("JackGraphManager::GetBuffer : port = %ld is released state", port_index);
return GetBuffer(0); // port_index 0 is not used
}
@@ -149,14 +149,29 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff
// Input port
jack_int_t len = manager->Connections(port_index);

if (len == 0) { // No connections: return a zero-filled buffer
// No connections : return a zero-filled buffer
if (len == 0) {
port->ClearBuffer(buffer_size);
return port->GetBuffer();
} else if (len == 1) { // One connection: use zero-copy mode - just pass the buffer of the connected (output) port.
assert(manager->GetPort(port_index, 0) != port_index); // Check recursion
return GetBuffer(manager->GetPort(port_index, 0), buffer_size);
} else { // Multiple connections

// One connection
} else if (len == 1) {
jack_port_id_t src_index = manager->GetPort(port_index, 0);
// Ports in same client : copy the buffer
if (GetPort(src_index)->GetRefNum() == port->GetRefNum()) {
void* buffers[1];
buffers[0] = GetBuffer(src_index, buffer_size);
port->MixBuffers(buffers, 1, buffer_size);
return port->GetBuffer();
// Otherwise, use zero-copy mode, just pass the buffer of the connected (output) port.
} else {
return GetBuffer(src_index, buffer_size);
}
// Multiple connections : mix all buffers
} else {
const jack_int_t* connections = manager->GetConnections(port_index);
void* buffers[CONNECTION_NUM_FOR_PORT];
jack_port_id_t src_index;
@@ -167,7 +182,6 @@ void* JackGraphManager::GetBuffer(jack_port_id_t port_index, jack_nframes_t buff
buffers[i] = GetBuffer(src_index, buffer_size);
}

JackPort* port = GetPort(port_index);
port->MixBuffers(buffers, i, buffer_size);
return port->GetBuffer();
}
@@ -688,6 +702,9 @@ const char** JackGraphManager::GetConnections(jack_port_id_t port_index)
{
const char** res = (const char**)malloc(sizeof(char*) * CONNECTION_NUM_FOR_PORT);
UInt16 cur_index, next_index;
if (!res)
return NULL;

do {
cur_index = GetCurrentIndex();
@@ -768,6 +785,9 @@ const char** JackGraphManager::GetPorts(const char* port_name_pattern, const cha
{
const char** res = (const char**)malloc(sizeof(char*) * PORT_NUM);
UInt16 cur_index, next_index;
if (!res)
return NULL;
do {
cur_index = GetCurrentIndex();


+ 2
- 2
common/JackInternalClientChannel.h View File

@@ -63,9 +63,9 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface
*result = fEngine->ClientInternalClose(refnum, true);
}

void ClientActivate(int refnum, int state, int* result)
void ClientActivate(int refnum, int is_real_time, int* result)
{
*result = fEngine->ClientActivate(refnum, state);
*result = fEngine->ClientActivate(refnum, is_real_time);
}
void ClientDeactivate(int refnum, int* result)
{


+ 16
- 8
common/JackLibAPI.cpp View File

@@ -111,14 +111,22 @@ EXPORT jack_client_t* jack_client_open_aux(const char* client_name, jack_options

EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
{
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
va_list ap;
va_start(ap, status);
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
va_end(ap);
JackGlobals::fOpenMutex->Unlock();
return res;
try {
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
va_list ap;
va_start(ap, status);
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
va_end(ap);
JackGlobals::fOpenMutex->Unlock();
return res;
} catch(std::bad_alloc& e) {
jack_error("Memory allocation error...");
return NULL;
} catch (...) {
jack_error("Unknown error...");
return NULL;
}
}

EXPORT int jack_client_close(jack_client_t* ext_client)


+ 2
- 2
common/JackLibClient.cpp View File

@@ -99,7 +99,7 @@ int JackLibClient::Open(const char* server_name, const char* name, jack_options_
JackLibGlobals::fGlobals->fEngineControl.SetShmIndex(shared_engine, fServerName);
JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName);
fClientControl.SetShmIndex(shared_client, fServerName);
jack_verbose = GetEngineControl()->fVerbose;
JackGlobals::fVerbose = GetEngineControl()->fVerbose;
} catch (int n) {
jack_error("Map shared memory segments exception %d", n);
goto error;
@@ -128,7 +128,7 @@ error:
// Notifications received from the server
// TODO this should be done once for all clients in the process, when a shared notification channel
// will be shared by all clients...
int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackLibClient::ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
int res = 0;



+ 1
- 1
common/JackLibClient.h View File

@@ -46,7 +46,7 @@ class JackLibClient : public JackClient

int Open(const char* server_name, const char* name, jack_options_t options, jack_status_t* status);

int ClientNotifyImp(int refnum, const char* name, int notify, int sync, int value1, int value2);
int ClientNotifyImp(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);

JackGraphManager* GetGraphManager() const;
JackEngineControl* GetEngineControl() const;


+ 91
- 6
common/JackLockedEngine.h View File

@@ -22,10 +22,35 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "JackEngine.h"
#include "JackMutex.h"
#include "JackTools.h"
#include "JackException.h"

namespace Jack
{

#define TRY_CALL \
try { \

#define CATCH_EXCEPTION_RETURN \
} catch(std::bad_alloc& e) { \
jack_error("Memory allocation error..."); \
return -1; \
} catch(JackTemporaryException& e) { \
jack_error("JackTemporaryException : now quits..."); \
JackTools::KillServer(); \
return -1; \
} catch (...) { \
jack_error("Unknown error..."); \
return -1; \
} \

#define CATCH_ENGINE_EXCEPTION \
} catch(std::bad_alloc& e) { \
jack_error("Memory allocation error..."); \
} catch (...) { \
jack_error("Unknown error..."); \
} \

/*!
\brief Locked Engine, access to methods is serialized using a mutex.
*/
@@ -47,108 +72,146 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int Open()
{
// No lock needed
TRY_CALL
return fEngine.Open();
CATCH_EXCEPTION_RETURN
}
int Close()
{
// No lock needed
TRY_CALL
return fEngine.Close();
CATCH_EXCEPTION_RETURN
}

// Client management
int ClientCheck(const char* name, char* name_res, int protocol, int options, int* status)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientCheck(name, name_res, protocol, options, status);
CATCH_EXCEPTION_RETURN
}
int ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientExternalOpen(name, pid, ref, shared_engine, shared_client, shared_graph_manager);
CATCH_EXCEPTION_RETURN
}
int ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientInternalOpen(name, ref, shared_engine, shared_manager, client, wait);
CATCH_EXCEPTION_RETURN
}

int ClientExternalClose(int refnum)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientExternalClose(refnum);
CATCH_EXCEPTION_RETURN
}
int ClientInternalClose(int refnum, bool wait)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientInternalClose(refnum, wait);
CATCH_EXCEPTION_RETURN
}

int ClientActivate(int refnum, bool state)
int ClientActivate(int refnum, bool is_real_time)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientActivate(refnum, state);
return fEngine.ClientActivate(refnum, is_real_time);
CATCH_EXCEPTION_RETURN
}
int ClientDeactivate(int refnum)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientDeactivate(refnum);
CATCH_EXCEPTION_RETURN
}

// Internal client management
int GetInternalClientName(int int_ref, char* name_res)
{
TRY_CALL
JackLock lock(this);
return fEngine.GetInternalClientName(int_ref, name_res);
CATCH_EXCEPTION_RETURN
}
int InternalClientHandle(const char* client_name, int* status, int* int_ref)
{
TRY_CALL
JackLock lock(this);
return fEngine.InternalClientHandle(client_name, status, int_ref);
CATCH_EXCEPTION_RETURN
}
int InternalClientUnload(int refnum, int* status)
{
TRY_CALL
JackLock lock(this);
return fEngine.InternalClientUnload(refnum, status);
CATCH_EXCEPTION_RETURN
}

// Port management
int PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortRegister(refnum, name, type, flags, buffer_size, port);
CATCH_EXCEPTION_RETURN
}
int PortUnRegister(int refnum, jack_port_id_t port)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortUnRegister(refnum, port);
CATCH_EXCEPTION_RETURN
}

int PortConnect(int refnum, const char* src, const char* dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortConnect(refnum, src, dst);
CATCH_EXCEPTION_RETURN
}
int PortDisconnect(int refnum, const char* src, const char* dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortDisconnect(refnum, src, dst);
CATCH_EXCEPTION_RETURN
}

int PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortConnect(refnum, src, dst);
CATCH_EXCEPTION_RETURN
}
int PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortDisconnect(refnum, src, dst);
CATCH_EXCEPTION_RETURN
}
int PortRename(int refnum, jack_port_id_t port, const char* name)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortRename(refnum, port, name);
CATCH_EXCEPTION_RETURN
}

// Graph
@@ -167,42 +230,64 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble

void NotifyXRun(int refnum)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyXRun(refnum);
CATCH_ENGINE_EXCEPTION
}
void NotifyGraphReorder()
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyGraphReorder();
CATCH_ENGINE_EXCEPTION
}
void NotifyBufferSize(jack_nframes_t buffer_size)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyBufferSize(buffer_size);
CATCH_ENGINE_EXCEPTION
}
void NotifySampleRate(jack_nframes_t sample_rate)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifySampleRate(sample_rate);
CATCH_ENGINE_EXCEPTION
}
void NotifyFreewheel(bool onoff)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyFreewheel(onoff);
CATCH_ENGINE_EXCEPTION
}

void NotifyFailure(int code, const char* reason)
{
TRY_CALL
JackLock lock(this);
fEngine.NotifyFailure(code, reason);
CATCH_ENGINE_EXCEPTION
}

int GetClientPID(const char* name)
{
TRY_CALL
JackLock lock(this);
return fEngine.GetClientPID(name);
CATCH_EXCEPTION_RETURN
}
int GetClientRefNum(const char* name)
{
TRY_CALL
JackLock lock(this);
return fEngine.GetClientRefNum(name);
CATCH_EXCEPTION_RETURN
}
};

} // end of namespace


+ 13
- 6
common/JackMessageBuffer.cpp View File

@@ -29,18 +29,24 @@ namespace Jack
JackMessageBuffer* JackMessageBuffer::fInstance = NULL;

JackMessageBuffer::JackMessageBuffer()
:fThread(this),fInBuffer(0),fOutBuffer(0),fOverruns(0)
:fThread(this),fInBuffer(0),fOutBuffer(0),fOverruns(0),fRunning(false)
{}

JackMessageBuffer::~JackMessageBuffer()
{}
void JackMessageBuffer::Start()
{
fRunning = true;
fThread.StartSync();
}

JackMessageBuffer::~JackMessageBuffer()
void JackMessageBuffer::Stop()
{
if (fOverruns > 0) {
jack_error("WARNING: %d message buffer overruns!", fOverruns);
} else {
jack_info("no message buffer overruns");
jack_log("no message buffer overruns");
}
fGuard.Lock();
fRunning = false;
@@ -49,7 +55,7 @@ JackMessageBuffer::~JackMessageBuffer()
fThread.Stop();
Flush();
}
void JackMessageBuffer::Flush()
{
while (fOutBuffer != fInBuffer) {
@@ -86,12 +92,14 @@ void JackMessageBuffer::Create()
{
if (fInstance == NULL) {
fInstance = new JackMessageBuffer();
fInstance->Start();
}
}

void JackMessageBuffer::Destroy()
{
if (fInstance != NULL) {
fInstance->Stop();
delete fInstance;
fInstance = NULL;
}
@@ -100,8 +108,7 @@ void JackMessageBuffer::Destroy()
void JackMessageBufferAdd(int level, const char *message)
{
if (Jack::JackMessageBuffer::fInstance == NULL) {
/* Unable to print message with realtime safety.
* Complain and print it anyway. */
/* Unable to print message with realtime safety. Complain and print it anyway. */
jack_log_function(LOG_LEVEL_ERROR, "messagebuffer not initialized, skip message");
} else {
Jack::JackMessageBuffer::fInstance->AddMessage(level, message);


+ 4
- 1
common/JackMessageBuffer.h View File

@@ -66,10 +66,13 @@ class JackMessageBuffer : public JackRunnableInterface
bool fRunning;

void Flush();
void Start();
void Stop();
public:
JackMessageBuffer();
JackMessageBuffer();
~JackMessageBuffer();
// JackRunnableInterface interface


+ 3
- 3
common/JackNetAdapter.cpp View File

@@ -228,8 +228,8 @@ namespace Jack
// Will do "something" on OSX only...
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) {
jack_error("AcquireRealTime error");
if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
jack_error("AcquireSelfRealTime error");
} else {
set_threaded_log_function();
}
@@ -251,7 +251,7 @@ namespace Jack
e.PrintMessage();
jack_info("NetAdapter is restarted.");
Reset();
fThread.DropRealTime();
fThread.DropSelfRealTime();
fThread.SetStatus(JackThread::kIniting);
if (Init()) {
fThread.SetStatus(JackThread::kRunning);


+ 21
- 11
common/JackNetDriver.cpp View File

@@ -53,6 +53,7 @@ namespace Jack
fMidiPlaybackPortList = NULL;
#ifdef JACK_MONITOR
fNetTimeMon = NULL;
fRcvSyncUst = 0;
#endif
}

@@ -208,7 +209,7 @@ namespace Jack
JackDriver::NotifySampleRate ( fParams.fSampleRate );

//transport engine parametering
fEngineControl->fTransport.SetNetworkSync ( true );
fEngineControl->fTransport.SetNetworkSync ( fParams.fTransportSync );
return true;
}

@@ -418,6 +419,7 @@ namespace Jack
break;

case JackTransportRolling :
//fEngineControl->fTransport.SetCommand ( TransportCommandStart );
fEngineControl->fTransport.SetState ( JackTransportRolling );
jack_info ( "Master is rolling." );
break;
@@ -427,6 +429,7 @@ namespace Jack

void JackNetDriver::EncodeTransportData()
{
/* Desactivated
//is there a timebase master change ?
int refnum;
bool conditional;
@@ -449,12 +452,14 @@ namespace Jack
}
else
fReturnTransportData.fTimebaseMaster = NO_CHANGE;

*/
//update transport state and position
fReturnTransportData.fState = fEngineControl->fTransport.Query ( &fReturnTransportData.fPosition );
//is it a new state (that the master need to know...) ?
fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) &&
fReturnTransportData.fNewState = (( fReturnTransportData.fState == JackTransportNetStarting) &&
( fReturnTransportData.fState != fLastTransportState ) &&
( fReturnTransportData.fState != fSendTransportData.fState ) );
if ( fReturnTransportData.fNewState )
jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) );
@@ -481,22 +486,27 @@ namespace Jack
if ( SyncRecv() == SOCKET_ERROR )
return 0;

//take the time at the beginning of the cycle
JackDriver::CycleTakeBeginTime();
#ifdef JACK_MONITOR
// For timing
fRcvSyncUst = GetMicroSeconds();
#endif

//decode sync
//if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified
DecodeSyncPacket();
#ifdef JACK_MONITOR
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
#endif
//audio, midi or sync if driver is late
if ( DataRecv() == SOCKET_ERROR )
return SOCKET_ERROR;

//take the time at the beginning of the cycle
JackDriver::CycleTakeBeginTime();

#ifdef JACK_MONITOR
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
#endif

return 0;
@@ -514,7 +524,7 @@ namespace Jack
fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) );

#ifdef JACK_MONITOR
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
#endif

//sync
@@ -525,7 +535,7 @@ namespace Jack
return SOCKET_ERROR;

#ifdef JACK_MONITOR
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
#endif

//send data
@@ -533,7 +543,7 @@ namespace Jack
return SOCKET_ERROR;

#ifdef JACK_MONITOR
fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
#endif

return 0;


+ 4
- 3
common/JackNetDriver.h View File

@@ -40,15 +40,16 @@ namespace Jack
//jack data
jack_port_id_t* fMidiCapturePortList;
jack_port_id_t* fMidiPlaybackPortList;
//transport
int fLastTransportState;
int fLastTimebaseMaster;
//monitoring
#ifdef JACK_MONITOR
#ifdef JACK_MONITOR
JackGnuPlotMonitor<float>* fNetTimeMon;
#endif
jack_time_t fRcvSyncUst;
#endif

bool Initialize();
void FreeAll();


+ 6
- 1
common/JackNetManager.cpp View File

@@ -305,6 +305,7 @@ namespace Jack
else
jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
break;
case TIMEBASEMASTER :
timebase = jack_set_timebase_callback ( fJackClient, 0, SetTimebaseCallback, this );
if ( timebase < 0 )
@@ -312,6 +313,7 @@ namespace Jack
else
jack_info ( "'%s' is the new timebase master.", fParams.fName );
break;
case CONDITIONAL_TIMEBASEMASTER :
timebase = jack_set_timebase_callback ( fJackClient, 1, SetTimebaseCallback, this );
if ( timebase != EBUSY )
@@ -334,15 +336,18 @@ namespace Jack
jack_transport_stop ( fJackClient );
jack_info ( "'%s' stops transport.", fParams.fName );
break;
case JackTransportStarting :
if ( jack_transport_reposition ( fJackClient, &fReturnTransportData.fPosition ) == EINVAL )
jack_error ( "Can't set new position." );
jack_transport_start ( fJackClient );
jack_info ( "'%s' starts transport frame = %d frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
jack_info ( "'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
break;
case JackTransportNetStarting :
jack_info ( "'%s' is ready to roll..", fParams.fName );
break;
case JackTransportRolling :
jack_info ( "'%s' is rolling.", fParams.fName );
break;


+ 1143
- 0
common/JackNetOneDriver.cpp
File diff suppressed because it is too large
View File


+ 96
- 0
common/JackNetOneDriver.h View File

@@ -0,0 +1,96 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2008 Romain Moret at 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 __JackNetDriver__
#define __JackNetDriver__

#include "JackAudioDriver.h"
#include "netjack.h"
#include "netjack_packet.h"

namespace Jack
{
/**
\Brief This class describes the Net Backend
*/

class JackNetOneDriver : public JackAudioDriver
{
private:
netjack_driver_state_t netj;

void
render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats);
void
render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats );
#ifdef HAVE_CELT
void
render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes);
void
render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up);
#endif
void
render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats);
void
render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats);

public:
JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports,
int sample_rate, int period_size, int resample_factor,
const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig,
int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val );
~JackNetOneDriver();

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 Close();
int Attach();
int Detach();

int Read();
int Write();

bool Initialize();
int AllocPorts();
void FreePorts();

// BufferSize can't be changed
bool IsFixedBufferSize()
{
return true;
}

int SetBufferSize ( jack_nframes_t buffer_size )
{
return -1;
}

int SetSampleRate ( jack_nframes_t sample_rate )
{
return -1;
}

};
}

#endif

+ 2
- 0
common/JackNetTool.cpp View File

@@ -417,6 +417,7 @@ namespace Jack
dst_params->fPosition.usecs = htonl(src_params->fPosition.usecs);
dst_params->fPosition.frame_rate = htonl(src_params->fPosition.frame_rate);
dst_params->fPosition.frame = htonl(src_params->fPosition.frame);
dst_params->fPosition.valid = (jack_position_bits_t)htonl((uint32_t)src_params->fPosition.valid);
dst_params->fPosition.bar = htonl(src_params->fPosition.bar);
dst_params->fPosition.beat = htonl(src_params->fPosition.beat);
dst_params->fPosition.tick = htonl(src_params->fPosition.tick);
@@ -442,6 +443,7 @@ namespace Jack
dst_params->fPosition.usecs = ntohl(src_params->fPosition.usecs);
dst_params->fPosition.frame_rate = ntohl(src_params->fPosition.frame_rate);
dst_params->fPosition.frame = ntohl(src_params->fPosition.frame);
dst_params->fPosition.valid = (jack_position_bits_t)ntohl((uint32_t)src_params->fPosition.valid);
dst_params->fPosition.bar = ntohl(src_params->fPosition.bar);
dst_params->fPosition.beat = ntohl(src_params->fPosition.beat);
dst_params->fPosition.tick = ntohl(src_params->fPosition.tick);


+ 1
- 0
common/JackNotification.h View File

@@ -43,6 +43,7 @@ enum NotificationType {
kPortDisconnectCallback = 12,
kPortRenameCallback = 13,
kRealTimeCallback = 14,
kShutDownCallback = 15,
kMaxNotification
};



+ 10
- 6
common/JackRequest.h View File

@@ -297,25 +297,25 @@ struct JackActivateRequest : public JackRequest
{

int fRefNum;
int fState;
int fIsRealTime;

JackActivateRequest()
{}
JackActivateRequest(int refnum, int state)
: JackRequest(JackRequest::kActivateClient), fRefNum(refnum), fState(state)
JackActivateRequest(int refnum, int is_real_time)
: JackRequest(JackRequest::kActivateClient), fRefNum(refnum), fIsRealTime(is_real_time)
{}

int Read(JackChannelTransaction* trans)
{
CheckRes(trans->Read(&fRefNum, sizeof(int)));
return trans->Read(&fState, sizeof(int));
return trans->Read(&fIsRealTime, sizeof(int));
}

int Write(JackChannelTransaction* trans)
{
CheckRes(JackRequest::Write(trans));
CheckRes(trans->Write(&fRefNum, sizeof(int)));
return trans->Write(&fState, sizeof(int));
return trans->Write(&fIsRealTime, sizeof(int));
}

} POST_PACKED_STRUCTURE;
@@ -1079,13 +1079,15 @@ struct JackClientNotification
int fValue1;
int fValue2;
int fSync;
char fMessage[JACK_MESSAGE_SIZE + 1];

JackClientNotification(): fNotify(-1), fValue1(-1), fValue2(-1)
{}
JackClientNotification(const char* name, int refnum, int notify, int sync, int value1, int value2)
JackClientNotification(const char* name, int refnum, int notify, int sync, const char* message, int value1, int value2)
: fRefNum(refnum), fNotify(notify), fValue1(value1), fValue2(value2), fSync(sync)
{
snprintf(fName, sizeof(fName), "%s", name);
snprintf(fMessage, sizeof(fMessage), "%s", message);
}

int Read(JackChannelTransaction* trans)
@@ -1096,6 +1098,7 @@ struct JackClientNotification
CheckRes(trans->Read(&fValue1, sizeof(int)));
CheckRes(trans->Read(&fValue2, sizeof(int)));
CheckRes(trans->Read(&fSync, sizeof(int)));
CheckRes(trans->Read(&fMessage, JACK_MESSAGE_SIZE + 1));
return 0;
}

@@ -1107,6 +1110,7 @@ struct JackClientNotification
CheckRes(trans->Write(&fValue1, sizeof(int)));
CheckRes(trans->Write(&fValue2, sizeof(int)));
CheckRes(trans->Write(&fSync, sizeof(int)));
CheckRes(trans->Write(&fMessage, JACK_MESSAGE_SIZE + 1));
return 0;
}



+ 1
- 1
common/JackRestartThreadedDriver.cpp View File

@@ -36,7 +36,7 @@ bool JackRestartThreadedDriver::Execute()
} catch (JackNetException& e) {
e.PrintMessage();
jack_log("Driver is restarted");
fThread.DropRealTime();
fThread.DropSelfRealTime();
// Thread in kIniting status again...
fThread.SetStatus(JackThread::kIniting);
if (Init()) {


+ 8
- 5
common/JackServer.cpp View File

@@ -55,7 +55,7 @@ JackServer::JackServer(bool sync, bool temporary, long timeout, bool rt, long pr
fFreewheel = false;
JackServerGlobals::fInstance = this; // Unique instance
JackServerGlobals::fUserCount = 1; // One user
jack_verbose = verbose;
JackGlobals::fVerbose = verbose;
}

JackServer::~JackServer()
@@ -78,7 +78,7 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
goto fail_close1;
}
if (fEngine->Open() != 0) {
if (fEngine->Open() < 0) {
jack_error("Cannot open engine");
goto fail_close2;
}
@@ -88,12 +88,12 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params)
goto fail_close3;
}
if (fFreewheelDriver->Open() != 0) { // before engine open
if (fFreewheelDriver->Open() < 0) { // before engine open
jack_error("Cannot open driver");
goto fail_close4;
}
if (fAudioDriver->Attach() != 0) {
if (fAudioDriver->Attach() < 0) {
jack_error("Cannot attach audio driver");
goto fail_close5;
}
@@ -168,7 +168,10 @@ int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const
int JackServer::Start()
{
jack_log("JackServer::Start");
return fAudioDriver->Start();
if (fAudioDriver->Start() < 0) {
return -1;
}
return fChannel.Start();
}

int JackServer::Stop()


+ 16
- 8
common/JackServerAPI.cpp View File

@@ -105,14 +105,22 @@ EXPORT jack_client_t* jack_client_open_aux(const char* client_name, jack_options

EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
{
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
va_list ap;
va_start(ap, status);
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
va_end(ap);
JackGlobals::fOpenMutex->Unlock();
return res;
try {
assert(JackGlobals::fOpenMutex);
JackGlobals::fOpenMutex->Lock();
va_list ap;
va_start(ap, status);
jack_client_t* res = jack_client_open_aux(ext_client_name, options, status, ap);
va_end(ap);
JackGlobals::fOpenMutex->Unlock();
return res;
} catch(std::bad_alloc& e) {
jack_error("Memory allocation error...");
return NULL;
} catch (...) {
jack_error("Unknown error...");
return NULL;
}
}

EXPORT int jack_client_close(jack_client_t* ext_client)


+ 1
- 1
common/JackServerGlobals.h View File

@@ -46,7 +46,7 @@ struct SERVER_EXPORT JackServerGlobals

static bool Init();
static void Destroy();
static int Start (const char* server_name,
static int Start(const char* server_name,
jack_driver_desc_t* driver_desc,
JSList* driver_params,
int sync,


+ 9
- 2
common/JackShmMem.cpp View File

@@ -1,6 +1,6 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2004-2008 Grame
Copyright (C) 2004-2009 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
@@ -32,6 +32,12 @@ size_t JackMem::gSize = 0;
JackShmMem::JackShmMem()
{
JackShmMemAble::Init();
LockMemory();
}
JackShmMem::~JackShmMem()
{
UnlockMemory();
}

void JackShmMemAble::Init()
@@ -96,8 +102,9 @@ void JackShmMem::operator delete(void* p, size_t size)

void JackShmMem::operator delete(void* obj)
{
if (obj)
if (obj) {
JackShmMem::operator delete(obj, 0);
}
}

void LockMemoryImp(void* ptr, size_t size)


+ 14
- 12
common/JackShmMem.h View File

@@ -1,6 +1,6 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2004-2008 Grame
Copyright (C) 2004-2009 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
@@ -129,9 +129,8 @@ class SERVER_EXPORT JackShmMem : public JackShmMemAble
protected:
JackShmMem();
~JackShmMem()
{}
~JackShmMem();
public:
void* operator new(size_t size);
@@ -162,9 +161,9 @@ class JackShmReadWritePtr
throw - 1;
fInfo.index = index;
if (jack_attach_shm(&fInfo)) {
//jack_error("cannot attach shared memory segment", strerror(errno));
throw - 2;
}
GetShmAddress()->LockMemory();
}
}

@@ -185,9 +184,10 @@ class JackShmReadWritePtr
{
if (fInfo.index >= 0) {
jack_log("JackShmReadWritePtr::~JackShmReadWritePtr %ld", fInfo.index);
GetShmAddress()->UnlockMemory();
jack_release_shm(&fInfo);
fInfo.index = -1;
}
}
}

T* operator->() const
@@ -242,15 +242,15 @@ class JackShmReadWritePtr1
throw - 1;
fInfo.index = index;
if (jack_attach_shm(&fInfo)) {
//jack_error("cannot attach shared memory segment", strerror(errno));
throw - 2;
}
/*
nobody else needs to access this shared memory any more, so
destroy it. because we have our own attachment to it, it won't
vanish till we exit (and release it).
*/
nobody else needs to access this shared memory any more, so
destroy it. because we have our own attachment to it, it won't
vanish till we exit (and release it).
*/
jack_destroy_shm(&fInfo);
GetShmAddress()->LockMemory();
}
}

@@ -271,6 +271,7 @@ class JackShmReadWritePtr1
{
if (fInfo.index >= 0) {
jack_log("JackShmReadWritePtr1::~JackShmReadWritePtr1 %ld", fInfo.index);
GetShmAddress()->UnlockMemory();
jack_release_shm(&fInfo);
fInfo.index = -1;
}
@@ -328,9 +329,9 @@ class JackShmReadPtr
throw - 1;
fInfo.index = index;
if (jack_attach_shm_read(&fInfo)) {
//jack_error("cannot attach shared memory segment", strerror(errno));
throw - 2;
}
GetShmAddress()->LockMemory();
}
}

@@ -351,6 +352,7 @@ class JackShmReadPtr
{
if (fInfo.index >= 0) {
jack_log("JackShmPtrRead::~JackShmPtrRead %ld", fInfo.index);
GetShmAddress()->UnlockMemory();
jack_release_shm(&fInfo);
fInfo.index = -1;
}


+ 8
- 3
common/JackThread.h View File

@@ -96,9 +96,14 @@ class SERVER_EXPORT JackThreadInterface
int Stop();
void Terminate();

int AcquireRealTime();
int AcquireRealTime(int priority);
int DropRealTime();
int AcquireRealTime(); // Used when called from another thread
int AcquireSelfRealTime(); // Used when called from thread itself
int AcquireRealTime(int priority); // Used when called from another thread
int AcquireSelfRealTime(int priority); // Used when called from thread itself
int DropRealTime(); // Used when called from another thread
int DropSelfRealTime(); // Used when called from thread itself

pthread_t GetThreadID();



+ 4
- 4
common/JackThreadedDriver.cpp View File

@@ -137,9 +137,9 @@ std::list<JackDriverInterface*> JackThreadedDriver::GetSlaves()
return fDriver->GetSlaves();
}

int JackThreadedDriver::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2)
int JackThreadedDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
{
return fDriver->ClientNotify(refnum, name, notify, sync, value1, value2);
return fDriver->ClientNotify(refnum, name, notify, sync, message, value1, value2);
}

JackClientControl* JackThreadedDriver::GetClientControl() const
@@ -215,8 +215,8 @@ bool JackThreadedDriver::Init()
// Will do "something" on OSX only...
GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
if (fThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
jack_error("AcquireRealTime error");
if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
jack_error("AcquireSelfRealTime error");
} else {
set_threaded_log_function();
}


+ 1
- 1
common/JackThreadedDriver.h View File

@@ -94,7 +94,7 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi
virtual std::list<JackDriverInterface*> GetSlaves();
virtual int ProcessSlaves();
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2);
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);
virtual JackClientControl* GetClientControl() const;
virtual bool IsRealTime() const;


+ 28
- 14
common/JackTools.cpp View File

@@ -33,10 +33,24 @@ using namespace std;

namespace Jack {

void JackTools::KillServer()
{
#ifdef WIN32
exit(1);
#else
kill(GetPID(), SIGINT);
#endif
}

void JackTools::ThrowJackNetException()
{
throw JackNetException();
}

#define DEFAULT_TMP_DIR "/tmp"
char* jack_tmpdir = (char*)DEFAULT_TMP_DIR;

int JackTools::GetPID()
int JackTools::GetPID()
{
#ifdef WIN32
return _getpid();
@@ -45,7 +59,7 @@ namespace Jack {
#endif
}

int JackTools::GetUID()
int JackTools::GetUID()
{
#ifdef WIN32
return _getpid();
@@ -55,7 +69,7 @@ namespace Jack {
#endif
}

const char* JackTools::DefaultServerName()
const char* JackTools::DefaultServerName()
{
const char* server_name;
if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL)
@@ -66,25 +80,25 @@ namespace Jack {
/* returns the name of the per-user subdirectory of jack_tmpdir */
#ifdef WIN32

char* JackTools::UserDir()
char* JackTools::UserDir()
{
return "";
}

char* JackTools::ServerDir(const char* server_name, char* server_dir)
char* JackTools::ServerDir(const char* server_name, char* server_dir)
{
return "";
}

void JackTools::CleanupFiles(const char* server_name) {}

int JackTools::GetTmpdir()
int JackTools::GetTmpdir()
{
return 0;
}

#else
char* JackTools::UserDir()
char* JackTools::UserDir()
{
static char user_dir[JACK_PATH_MAX + 1] = "";

@@ -101,7 +115,7 @@ namespace Jack {
}

/* returns the name of the per-server subdirectory of jack_user_dir() */
char* JackTools::ServerDir(const char* server_name, char* server_dir)
char* JackTools::ServerDir(const char* server_name, char* server_dir)
{
/* format the path name into the suppled server_dir char array,
* assuming that server_dir is at least as large as JACK_PATH_MAX + 1 */
@@ -110,7 +124,7 @@ namespace Jack {
return server_dir;
}

void JackTools::CleanupFiles(const char* server_name)
void JackTools::CleanupFiles(const char* server_name)
{
DIR* dir;
struct dirent *dirent;
@@ -169,7 +183,7 @@ namespace Jack {
}
}

int JackTools::GetTmpdir()
int JackTools::GetTmpdir()
{
FILE* in;
size_t len;
@@ -201,7 +215,7 @@ namespace Jack {
}
#endif

void JackTools::RewriteName(const char* name, char* new_name)
void JackTools::RewriteName(const char* name, char* new_name)
{
size_t i;
for (i = 0; i < strlen(name); i++) {
@@ -212,7 +226,7 @@ namespace Jack {
}
new_name[i] = '\0';
}
#ifdef WIN32

void BuildClientPath(char* path_to_so, int path_len, const char* so_name)
@@ -251,7 +265,7 @@ void PrintLoadError(const char* so_name)

#else

void PrintLoadError(const char* so_name)
void PrintLoadError(const char* so_name)
{
jack_log("error loading %s err = %s", so_name, dlerror());
}
@@ -264,7 +278,7 @@ void BuildClientPath(char* path_to_so, int path_len, const char* so_name)
internal_dir = ADDON_DIR;
}
}
snprintf(path_to_so, path_len, "%s/%s.so", internal_dir, so_name);
}



+ 7
- 2
common/JackTools.h View File

@@ -36,6 +36,7 @@
#include "driver_interface.h"
#include "JackCompilerDeps.h"
#include "JackError.h"
#include "JackException.h"

#include <string>
#include <algorithm>
@@ -55,12 +56,16 @@ namespace Jack
static int GetPID();
static int GetUID();

static void KillServer();

static char* UserDir();
static char* ServerDir ( const char* server_name, char* server_dir );
static const char* DefaultServerName();
static void CleanupFiles ( const char* server_name );
static int GetTmpdir();
static void RewriteName ( const char* name, char* new_name );
static void ThrowJackNetException();
};

/*!
@@ -201,10 +206,10 @@ namespace Jack
return 0;
}
};
void BuildClientPath(char* path_to_so, int path_len, const char* so_name);
void PrintLoadError(const char* so_name);
}

#endif

+ 2
- 1
common/JackTransportEngine.cpp View File

@@ -38,7 +38,8 @@ JackTransportEngine::JackTransportEngine(): JackAtomicArrayState<jack_position_t
{
fTransportState = JackTransportStopped;
fTransportCmd = fPreviousCmd = TransportCommandStop;
fSyncTimeout = 2000000; /* 2 second default */
fSyncTimeout = 10000000; /* 10 seconds default...
in case of big netjack1 roundtrip */
fSyncTimeLeft = 0;
fTimeBaseMaster = -1;
fWriteCounter = 0;


+ 3
- 3
common/JackWaitThreadedDriver.cpp View File

@@ -48,8 +48,8 @@ bool JackWaitThreadedDriver::Execute()
// Will do "something" on OSX only...
GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
if (fThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
jack_error("AcquireRealTime error");
if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
jack_error("AcquireSelfRealTime error");
} else {
set_threaded_log_function();
}
@@ -63,7 +63,7 @@ bool JackWaitThreadedDriver::Execute()
} catch (JackNetException& e) {
e.PrintMessage();
jack_info("Driver is restarted");
fThread.DropRealTime();
fThread.DropSelfRealTime();
// Thread in kIniting status again...
fThread.SetStatus(JackThread::kIniting);
if (Init()) {


+ 103
- 84
common/JackWeakAPI.cpp View File

@@ -21,7 +21,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Completed from Julien Pommier (PianoTeq : http://www.pianoteq.com/) code.
*/

#include "jack.h"
#include <jack/jack.h>
#include <jack/thread.h>
#include <jack/midiport.h>
#include <math.h>
#include <dlfcn.h>
#include <stdlib.h>
@@ -32,6 +34,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
(similar to what relaytool is trying to do, but more portably..)
*/

typedef void (*print_function)(const char *);
typedef void *(*thread_routine)(void*);

using std::cerr;

int libjack_is_present = 0; // public symbol, similar to what relaytool does.
@@ -40,7 +45,12 @@ static void *libjack_handle = 0;
static void __attribute__((constructor)) tryload_libjack()
{
if (getenv("SKIP_LIBJACK") == 0) { // just in case libjack is causing troubles..
#ifdef __APPLE__
libjack_handle = dlopen("libjack.0.dylib", RTLD_LAZY);
#else
libjack_handle = dlopen("libjack.so.0", RTLD_LAZY);
#endif
}
libjack_is_present = (libjack_handle != 0);
}
@@ -65,7 +75,7 @@ void *load_jack_function(const char *fn_name)
static fn_name##_ptr_t fn = 0; \
if (fn == 0) { fn = (fn_name##_ptr_t)load_jack_function(#fn_name); } \
if (fn) return (*fn)arguments; \
else return 0; \
else return (return_type)-1; \
}

#define DECL_VOID_FUNCTION(fn_name, arguments_types, arguments) \
@@ -81,7 +91,7 @@ DECL_FUNCTION(const char *, jack_get_version_string, (), ());
DECL_FUNCTION(jack_client_t *, jack_client_open, (const char *client_name, jack_options_t options, jack_status_t *status, ...),
(client_name, options, status));
DECL_FUNCTION(int, jack_client_close, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_client_new, (const char *client_name), (client_name));
DECL_FUNCTION(jack_client_t *, jack_client_new, (const char *client_name), (client_name));
DECL_FUNCTION(int, jack_client_name_size, (), ());
DECL_FUNCTION(char*, jack_get_client_name, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_internal_client_new, (const char *client_name,
@@ -89,7 +99,8 @@ DECL_FUNCTION(int, jack_internal_client_new, (const char *client_name,
const char *load_init), (client_name, load_name, load_init));
DECL_VOID_FUNCTION(jack_internal_client_close, (const char *client_name), (client_name));
DECL_FUNCTION(int, jack_is_realtime, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_on_shutdown, (jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg), (client, function, arg));
DECL_VOID_FUNCTION(jack_on_shutdown, (jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg), (client, shutdown_callback, arg));
DECL_VOID_FUNCTION(jack_on_info_shutdown, (jack_client_t* client, JackInfoShutdownCallback shutdown_callback, void* arg), (client, shutdown_callback, arg));
DECL_FUNCTION(int, jack_set_process_callback, (jack_client_t *client,
JackProcessCallback process_callback,
void *arg), (client, process_callback, arg));
@@ -97,7 +108,7 @@ DECL_FUNCTION(jack_nframes_t, jack_thread_wait, (jack_client_t *client, int stat
//
DECL_FUNCTION(jack_nframes_t, jack_cycle_wait, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_cycle_signal, (jack_client_t *client, , int status), (client, status));
DECL_VOID_FUNCTION(jack_cycle_signal, (jack_client_t *client, int status), (client, status));
DECL_FUNCTION(int, jack_set_process_thread, (jack_client_t *client,
JackThreadCallback fun,
void *arg), (client, fun, arg));
@@ -149,94 +160,102 @@ DECL_FUNCTION(int, jack_port_is_mine, (const jack_client_t *client, const jack_p
DECL_FUNCTION(int, jack_port_connected, (const jack_port_t *port), (port));
DECL_FUNCTION(int, jack_port_connected_to, (const jack_port_t *port, const char *port_name), (port, port_name));
DECL_FUNCTION(const char**, jack_port_get_connections, (const jack_port_t *port), (port));
DECL_FUNCTION(const char**, jack_port_get_all_connections, (const jack_port_t *port), (port));
DECL_FUNCTION(const char**, jack_port_get_all_connections, (const jack_client_t *client,const jack_port_t *port), (client, port));
DECL_FUNCTION(int, jack_port_tie, (jack_port_t *src, jack_port_t *dst), (src, dst));
DECL_FUNCTION(int, jack_port_untie, (jack_port_t *port), (port));
DECL_FUNCTION(jack_nframes_t, jack_port_get_latency, (jack_port_t *port));
DECL_FUNCTION(jack_nframes_t, jack_port_get_total_latency ,(jack_client_t *), (jack_port_t *port));
DECL_VOID_FUNCTION(jack_port_set_latency, (jack_port_t *), (jack_nframes_t));
DECL_FUNCTION(int, jack_recompute_total_latency, (jack_client_t*), (jack_port_t* port));
DECL_FUNCTION(int, jack_recompute_total_latencies, (jack_client_t*));
DECL_FUNCTION(int, jack_port_set_name, (jack_port_t *port), (const char *port_name));
DECL_FUNCTION(int, jack_port_set_alias, (jack_port_t *port), (const char *alias));
DECL_FUNCTION(int, jack_port_unset_alias, (jack_port_t *port), (const char *alias));
DECL_FUNCTION(int, jack_port_get_aliases, (const jack_port_t *port), (char* const aliases[2]));
DECL_FUNCTION(int, jack_port_request_monitor, (jack_port_t *port), (int onoff));
DECL_FUNCTION(int, jack_port_request_monitor_by_name, (jack_client_t *client), (const char *port_name), (int onoff));
DECL_FUNCTION(int, jack_port_ensure_monitor, (jack_port_t *port), (int onoff));
DECL_FUNCTION(int, jack_port_monitoring_input, (jack_port_t *port));
DECL_FUNCTION(int, jack_connect, (jack_client_t *), (const char *source_port), (const char *destination_port));
DECL_FUNCTION(int, jack_disconnect, (jack_client_t *), (const char *source_port), (const char *destination_port));
DECL_FUNCTION(int, jack_port_disconnect, (jack_client_t *), (jack_port_t *));
DECL_FUNCTION(int, jack_port_name_size,(void));
DECL_FUNCTION(int, jack_port_type_size,(void));
DECL_FUNCTION(jack_nframes_t, jack_port_get_latency, (jack_port_t *port), (port));
DECL_FUNCTION(jack_nframes_t, jack_port_get_total_latency ,(jack_client_t * client, jack_port_t *port), (client, port));
DECL_VOID_FUNCTION(jack_port_set_latency, (jack_port_t * port, jack_nframes_t frames), (port, frames));
DECL_FUNCTION(int, jack_recompute_total_latency, (jack_client_t* client, jack_port_t* port), (client, port));
DECL_FUNCTION(int, jack_recompute_total_latencies, (jack_client_t* client),(client));
DECL_FUNCTION(int, jack_port_set_name, (jack_port_t *port, const char *port_name), (port, port_name));
DECL_FUNCTION(int, jack_port_set_alias, (jack_port_t *port, const char *alias), (port, alias));
DECL_FUNCTION(int, jack_port_unset_alias, (jack_port_t *port, const char *alias), (port, alias));
DECL_FUNCTION(int, jack_port_get_aliases, (const jack_port_t *port, char* const aliases[2]), (port,aliases));
DECL_FUNCTION(int, jack_port_request_monitor, (jack_port_t *port, int onoff), (port, onoff));
DECL_FUNCTION(int, jack_port_request_monitor_by_name, (jack_client_t *client, const char *port_name, int onoff), (client, port_name, onoff));
DECL_FUNCTION(int, jack_port_ensure_monitor, (jack_port_t *port, int onoff), (port, onoff));
DECL_FUNCTION(int, jack_port_monitoring_input, (jack_port_t *port) ,(port));
DECL_FUNCTION(int, jack_connect, (jack_client_t * client, const char *source_port, const char *destination_port), (client, source_port, destination_port));
DECL_FUNCTION(int, jack_disconnect, (jack_client_t * client, const char *source_port, const char *destination_port), (client, source_port, destination_port));
DECL_FUNCTION(int, jack_port_disconnect, (jack_client_t * client, jack_port_t * port), (client, port));
DECL_FUNCTION(int, jack_port_name_size,(),());
DECL_FUNCTION(int, jack_port_type_size,(),());
DECL_FUNCTION(jack_nframes_t, jack_get_sample_rate, (jack_client_t *client), (client));
DECL_FUNCTION(jack_nframes_t, jack_get_buffer_size, (jack_client_t *client), (client));
DECL_FUNCTION(const char**, jack_get_ports, (jack_client_t *client, const char *port_name_pattern, const char * type_name_pattern,
unsigned long flags), (client, port_name_pattern, type_name_pattern, flags));
DECL_FUNCTION(jack_port_t *, jack_port_by_name, (jack_client_t *), (const char *port_name));
DECL_FUNCTION(jack_port_t *, jack_port_by_id, (jack_client_t *client), (jack_port_id_t port_id));

DECL_FUNCTION(int, jack_engine_takeover_timebase, (jack_client_t *));
DECL_FUNCTION(jack_nframes_t, jack_frames_since_cycle_start, (const jack_client_t *));
DECL_FUNCTION(jack_time_t, jack_get_time());
DECL_FUNCTION(jack_nframes_t, jack_time_to_frames, (const jack_client_t *client), (jack_time_t time));
DECL_FUNCTION(jack_time_t, jack_frames_to_time, (const jack_client_t *client), (jack_nframes_t frames));
DECL_FUNCTION(jack_nframes_t, jack_frame_time, (const jack_client_t *));
DECL_FUNCTION(jack_nframes_t, jack_last_frame_time, (const jack_client_t *client));
DECL_FUNCTION(float, jack_cpu_load, (jack_client_t *client));
DECL_FUNCTION(pthread_t, jack_client_thread_id, (jack_client_t *));
DECL_VOID_FUNCTION(jack_set_error_function, (print_function));
DECL_VOID_FUNCTION(jack_set_info_function, (print_function));

DECL_FUNCTION(float, jack_get_max_delayed_usecs, (jack_client_t *client));
DECL_FUNCTION(float, jack_get_xrun_delayed_usecs, (jack_client_t *client));
DECL_VOID_FUNCTION(jack_reset_max_delayed_usecs, (jack_client_t *client));

DECL_FUNCTION(int, jack_release_timebase, (jack_client_t *client));
DECL_FUNCTION(int, jack_set_sync_callback, (jack_client_t *client, (JackSyncCallback sync_callback), (void *arg));
DECL_FUNCTION(int, jack_set_sync_timeout, (jack_client_t *client), (jack_time_t timeout));
DECL_FUNCTION(int, jack_set_timebase_callback, (jack_client_t *client), (int conditional), (JackTimebaseCallback timebase_callback), (void *arg));
DECL_FUNCTION(int, jack_transport_locate, (jack_client_t *client), (jack_nframes_t frame));
DECL_FUNCTION(jack_transport_state_t, jack_transport_query, (const jack_client_t *client), (jack_position_t *pos));
DECL_FUNCTION(jack_nframes_t, jack_get_current_transport_frame, (const jack_client_t *client));
DECL_FUNCTION(int, jack_transport_reposition, (jack_client_t *client), (jack_position_t *pos));
DECL_VOID_FUNCTION(jack_transport_start, (jack_client_t *client));
DECL_VOID_FUNCTION(jack_transport_stop, (jack_client_t *client));
DECL_VOID_FUNCTION(jack_get_transport_info, (jack_client_t *client), (jack_transport_info_t *tinfo));
DECL_VOID_FUNCTION(jack_set_transport_info, (jack_client_t *client), (jack_transport_info_t *tinfo));

DECL_FUNCTION(int, jack_client_real_time_priority, (jack_client_t*));
DECL_FUNCTION(int, jack_client_max_real_time_priority, (jack_client_t*));
DECL_FUNCTION(int, jack_acquire_real_time_scheduling, (pthread_t thread), (int priority));
DECL_FUNCTION(int, jack_client_create_thread, (jack_client_t* client),
(pthread_t *thread),
(int priority),
(int realtime), // boolean
(thread_routine routine),
(void *arg));
DECL_FUNCTION(int, jack_drop_real_time_scheduling, (pthread_t thread));

DECL_FUNCTION(int, jack_client_stop_thread, (jack_client_t* client), (pthread_t thread));
DECL_FUNCTION(int, jack_client_kill_thread, (jack_client_t* client), (pthread_t thread));
DECL_FUNCTION(jack_port_t *, jack_port_by_name, (jack_client_t * client, const char *port_name), (client, port_name));
DECL_FUNCTION(jack_port_t *, jack_port_by_id, (jack_client_t *client, jack_port_id_t port_id), (client, port_id));

DECL_FUNCTION(int, jack_engine_takeover_timebase, (jack_client_t * client), (client));
DECL_FUNCTION(jack_nframes_t, jack_frames_since_cycle_start, (const jack_client_t * client), (client));
DECL_FUNCTION(jack_time_t, jack_get_time, (), ());
DECL_FUNCTION(jack_nframes_t, jack_time_to_frames, (const jack_client_t *client, jack_time_t time), (client, time));
DECL_FUNCTION(jack_time_t, jack_frames_to_time, (const jack_client_t *client, jack_nframes_t frames), (client, frames));
DECL_FUNCTION(jack_nframes_t, jack_frame_time, (const jack_client_t *client), (client));
DECL_FUNCTION(jack_nframes_t, jack_last_frame_time, (const jack_client_t *client), (client));
DECL_FUNCTION(float, jack_cpu_load, (jack_client_t *client), (client));
DECL_FUNCTION(pthread_t, jack_client_thread_id, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_set_error_function, (print_function fun), (fun));
DECL_VOID_FUNCTION(jack_set_info_function, (print_function fun), (fun));

DECL_FUNCTION(float, jack_get_max_delayed_usecs, (jack_client_t *client), (client));
DECL_FUNCTION(float, jack_get_xrun_delayed_usecs, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_reset_max_delayed_usecs, (jack_client_t *client), (client));

DECL_FUNCTION(int, jack_release_timebase, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_set_sync_callback, (jack_client_t *client, JackSyncCallback sync_callback, void *arg), (client, sync_callback, arg));
DECL_FUNCTION(int, jack_set_sync_timeout, (jack_client_t *client, jack_time_t timeout), (client, timeout));
DECL_FUNCTION(int, jack_set_timebase_callback, (jack_client_t *client,
int conditional,
JackTimebaseCallback timebase_callback,
void *arg), (client, conditional, timebase_callback, arg));
DECL_FUNCTION(int, jack_transport_locate, (jack_client_t *client, jack_nframes_t frame), (client, frame));
DECL_FUNCTION(jack_transport_state_t, jack_transport_query, (const jack_client_t *client, jack_position_t *pos), (client, pos));
DECL_FUNCTION(jack_nframes_t, jack_get_current_transport_frame, (const jack_client_t *client), (client));
DECL_FUNCTION(int, jack_transport_reposition, (jack_client_t *client, jack_position_t *pos), (client, pos));
DECL_VOID_FUNCTION(jack_transport_start, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_transport_stop, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_get_transport_info, (jack_client_t *client, jack_transport_info_t *tinfo), (client,tinfo));
DECL_VOID_FUNCTION(jack_set_transport_info, (jack_client_t *client, jack_transport_info_t *tinfo), (client,tinfo));

DECL_FUNCTION(int, jack_client_real_time_priority, (jack_client_t* client), (client));
DECL_FUNCTION(int, jack_client_max_real_time_priority, (jack_client_t* client), (client));
DECL_FUNCTION(int, jack_acquire_real_time_scheduling, (pthread_t thread, int priority), (thread, priority));
DECL_FUNCTION(int, jack_client_create_thread, (jack_client_t* client,
pthread_t *thread,
int priority,
int realtime, // boolean
thread_routine routine,
void *arg), (client, thread, priority, realtime, routine, arg));
DECL_FUNCTION(int, jack_drop_real_time_scheduling, (pthread_t thread), (thread));

DECL_FUNCTION(int, jack_client_stop_thread, (jack_client_t* client, pthread_t thread), (client, thread));
DECL_FUNCTION(int, jack_client_kill_thread, (jack_client_t* client, pthread_t thread), (client, thread));
#ifndef WIN32
DECL_VOID_FUNCTION(jack_set_thread_creator, (jack_thread_creator_t jtc));
DECL_VOID_FUNCTION(jack_set_thread_creator, (jack_thread_creator_t jtc), (jtc));
#endif
DECL_FUNCTION(char *, jack_get_internal_client_name, (jack_client_t *client, (jack_intclient_t intclient));
DECL_FUNCTION(jack_intclient_t, jack_internal_client_handle, (jack_client_t *client), (const char *client_name), (jack_status_t *status));
DECL_FUNCTION(jack_intclient_t, jack_internal_client_load, (jack_client_t *client), (const char *client_name), (jack_options_t options), (jack_status_t *status), ...));

DECL_FUNCTION(jack_status_t, jack_internal_client_unload, (jack_client_t *client), jack_intclient_t intclient));
DECL_VOID_FUNCTION(jack_free, (void* ptr));
DECL_FUNCTION(char *, jack_get_internal_client_name, (jack_client_t *client, jack_intclient_t intclient), (client, intclient));
DECL_FUNCTION(jack_intclient_t, jack_internal_client_handle, (jack_client_t *client, const char *client_name, jack_status_t *status), (client, client_name, status));
/*
DECL_FUNCTION(jack_intclient_t, jack_internal_client_load, (jack_client_t *client,
const char *client_name,
jack_options_t options,
jack_status_t *status
, ...), (client, client_name, options, status, ...));
*/
DECL_FUNCTION(jack_status_t, jack_internal_client_unload, (jack_client_t *client, jack_intclient_t intclient), (client, intclient));
DECL_VOID_FUNCTION(jack_free, (void* ptr), (ptr));

// MIDI

DECL_FUNCTION(jack_nframes_t, jack_midi_get_event_count, (void* port_buffer));
DECL_FUNCTION(int jack_midi_event_get(jack_midi_event_t* event, void* port_buffer, jack_nframes_t event_index);
DECL_VOID_FUNCTION(jack_midi_clear_buffer, (void* port_buffer));
DECL_FUNCTION(size_t, jack_midi_max_event_size, (void* port_buffer));
DECL_FUNCTION(jack_midi_data_t*, jack_midi_event_reserve, (void* port_buffer), (jack_nframes_t time), (size_t data_size));
DECL_FUNCTIO(int jack_midi_event_write, (void* port_buffer), (jack_nframes_t time), (const jack_midi_data_t* data), (size_t data_size));
DECL_FUNCTION(jack_nframes_t, jack_midi_get_lost_event_count, (void* port_buffer));
DECL_FUNCTION(jack_nframes_t, jack_midi_get_event_count, (void* port_buffer), (port_buffer));
DECL_FUNCTION(int, jack_midi_event_get, (jack_midi_event_t* event, void* port_buffer, jack_nframes_t event_index), (event, port_buffer, event_index)) ;
DECL_VOID_FUNCTION(jack_midi_clear_buffer, (void* port_buffer), (port_buffer));
DECL_FUNCTION(size_t, jack_midi_max_event_size, (void* port_buffer), (port_buffer));
DECL_FUNCTION(jack_midi_data_t*, jack_midi_event_reserve, (void* port_buffer, jack_nframes_t time, size_t data_size), (port_buffer, time, data_size));
DECL_FUNCTION(int, jack_midi_event_write, (void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, size_t data_size), (port_buffer, time, data, data_size));
DECL_FUNCTION(jack_nframes_t, jack_midi_get_lost_event_count, (void* port_buffer), (port_buffer));

+ 66
- 27
common/Jackdmp.cpp View File

@@ -94,7 +94,9 @@ static void copyright(FILE* file)
static void usage(FILE* file)
{
fprintf(file, "\n"
"usage: jackdmp [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
"usage: jackdmp [ --no-realtime OR -r ]\n"
" [ --realtime OR -R [ --realtime-priority OR -P priority ] ]\n"
" (the two previous arguments are mutually exclusive. The default is --realtime)\n"
" [ --name OR -n server-name ]\n"
" [ --timeout OR -t client-timeout-in-msecs ]\n"
" [ --loopback OR -L loopback-port-number ]\n"
@@ -103,15 +105,26 @@ static void usage(FILE* file)
#ifdef __linux__
" [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n"
#endif
" [ --replace-registry OR -r ]\n"
" [ --replace-registry ]\n"
" [ --silent OR -s ]\n"
" [ --sync OR -S ]\n"
" [ --temporary OR -T ]\n"
" [ --version OR -V ]\n"
" -d audio-driver [ ... driver args ... ]\n"
" where driver can be `alsa', `coreaudio', 'portaudio' or `dummy'\n"
" jackdmp -d driver --help\n"
" to display options for each driver\n\n");
" -d backend [ ... backend args ... ]\n"
#ifdef __APPLE__
" Available backends may include: coreaudio, dummy or net.\n\n"
#endif
#ifdef WIN32
" Available backends may include: portaudio, dummy or net.\n\n"
#endif
#ifdef __linux__
" Available backends may include: alsa, dummy, freebob, firewire, net, oss or sun.\n\n"
#endif
#if defined(__sun__) || defined(sun)
" Available backends may include: boomer, oss, dummy or net.\n\n"
#endif
" jackdmp -d backend --help\n"
" to display options for each backend\n\n");
}

// To put in the control.h interface??
@@ -163,12 +176,14 @@ int main(int argc, char* argv[])
jackctl_driver_t * audio_driver_ctl;
jackctl_driver_t * midi_driver_ctl;
jackctl_driver_t * loopback_driver_ctl;
int replace_registry = 0;
const char *options = "-d:X:P:uvshVrRL:STFl:t:mn:p:"
"a:"
#ifdef __linux__
const char *options = "-d:X:P:uvrshVRSTFl:t:mn:p:c:a:L:";
#else
const char *options = "-d:X:P:uvrshVRSTFl:t:mn:p:a:L:";
"c:"
#endif
;
struct option long_options[] = {
#ifdef __linux__
@@ -184,7 +199,8 @@ int main(int argc, char* argv[])
{ "name", 0, 0, 'n' },
{ "unlock", 0, 0, 'u' },
{ "realtime", 0, 0, 'R' },
{ "replace-registry", 0, 0, 'r' },
{ "no-realtime", 0, 0, 'r' },
{ "replace-registry", 0, &replace_registry, 0 },
{ "loopback", 0, 0, 'L' },
{ "realtime-priority", 1, 0, 'P' },
{ "timeout", 1, 0, 't' },
@@ -225,8 +241,16 @@ int main(int argc, char* argv[])
fprintf(stderr, "Failed to create server object\n");
return -1;
}
server_parameters = jackctl_server_get_parameters(server_ctl);
// Default setting
param = jackctl_get_parameter(server_parameters, "realtime");
if (param != NULL) {
value.b = true;
jackctl_parameter_set_value(param, &value);
}
opterr = 0;
while (!seen_audio_driver &&
(opt = getopt_long(argc, argv, options,
@@ -248,7 +272,7 @@ int main(int argc, char* argv[])
jackctl_parameter_set_value(param, &value);
} else {
usage(stdout);
goto fail_free;
goto fail_free1;
}
}
break;
@@ -269,7 +293,7 @@ int main(int argc, char* argv[])
jackctl_parameter_set_value(param, &value);
} else {
usage(stdout);
goto fail_free;
goto fail_free1;
}
}
break;
@@ -336,11 +360,11 @@ int main(int argc, char* argv[])
jackctl_parameter_set_value(param, &value);
}
break;
case 'r':
param = jackctl_get_parameter(server_parameters, "replace-registry");
param = jackctl_get_parameter(server_parameters, "realtime");
if (param != NULL) {
value.b = true;
value.b = false;
jackctl_parameter_set_value(param, &value);
}
break;
@@ -379,10 +403,17 @@ int main(int argc, char* argv[])

case 'h':
usage(stdout);
goto fail_free;
goto fail_free1;
}
}

// Long option with no letter so treated separately
param = jackctl_get_parameter(server_parameters, "replace-registry");
if (param != NULL) {
value.b = replace_registry;
jackctl_parameter_set_value(param, &value);
}
if (show_version) {
printf( "jackdmp version " VERSION
" tmpdir " jack_server_dir
@@ -393,14 +424,14 @@ int main(int argc, char* argv[])

if (!seen_audio_driver) {
usage(stderr);
goto fail_free;
goto fail_free1;
}

// Audio driver
audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name);
if (audio_driver_ctl == NULL) {
fprintf(stderr, "Unkown driver \"%s\"\n", audio_driver_name);
goto fail_free;
goto fail_free1;
}

if (optind < argc) {
@@ -412,7 +443,7 @@ int main(int argc, char* argv[])
if (audio_driver_nargs == 0) {
fprintf(stderr, "No driver specified ... hmm. JACK won't do"
" anything when run like this.\n");
goto fail_free;
goto fail_free1;
}

audio_driver_args = (char **) malloc(sizeof(char *) * audio_driver_nargs);
@@ -423,13 +454,13 @@ int main(int argc, char* argv[])
}

if (jackctl_parse_driver_params(audio_driver_ctl, audio_driver_nargs, audio_driver_args)) {
goto fail_free;
goto fail_free1;
}

// Start server
if (!jackctl_server_start(server_ctl, audio_driver_ctl)) {
fprintf(stderr, "Failed to start server\n");
goto fail_free;
goto fail_free1;
}

// MIDI driver
@@ -438,7 +469,7 @@ int main(int argc, char* argv[])
midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name);
if (midi_driver_ctl == NULL) {
fprintf(stderr, "Unkown driver \"%s\"\n", midi_driver_name);
goto fail_free;
goto fail_free2;
}

jackctl_server_add_slave(server_ctl, midi_driver_ctl);
@@ -466,10 +497,18 @@ int main(int argc, char* argv[])

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_free:

fail_free1:
jackctl_server_destroy(server_ctl);
return -1;
fail_free2:
jackctl_server_stop(server_ctl);
jackctl_server_destroy(server_ctl);
notify_server_stop(server_name);
return 1;
return -1;
}

+ 51
- 1
common/jack/jack.h View File

@@ -34,6 +34,25 @@ extern "C"
* Note: More documentation can be found in jack/types.h.
*/
/*************************************************************
* NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function
* added to the JACK API after the 0.116.2 release.
*************************************************************/

#ifndef JACK_WEAK_EXPORT
#ifdef __GNUC__
/* JACK_WEAK_EXPORT needs to be a macro which
expands into a compiler directive. If non-null, the directive
must tell the compiler to arrange for weak linkage of
the symbol it used with. For this to work full may
require linker arguments in the client as well.
*/
#define JACK_WEAK_EXPORT __attribute__((weak))
#else
/* Add other things here for non-gcc platforms */
#endif
#endif

/**
* @defgroup ClientFunctions Creating & manipulating clients
* @{
@@ -294,10 +313,41 @@ int jack_set_thread_init_callback (jack_client_t *client,
* NOTE: clients do not need to call this. It exists only
* to help more complex clients understand what is going
* on. It should be called before jack_client_activate().
*
* NOTE: if a client calls this AND jack_on_info_shutdown(), then
* the event of a client thread shutdown, the callback
* passed to this function will not be called, and the one passed to
* jack_on_info_shutdown() will.
*/
void jack_on_shutdown (jack_client_t *client,
JackShutdownCallback shutdown_callback, void *arg);
JackShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT;

/**
* @param client pointer to JACK client structure.
* @param function The jack_info_shutdown function pointer.
* @param arg The arguments for the jack_info_shutdown function.
*
* Register a function (and argument) to be called if and when the
* JACK server shuts down the client thread. The function must
* be written as if it were an asynchonrous POSIX signal
* handler --- use only async-safe functions, and remember that it
* is executed from another thread. A typical function might
* set a flag or write to a pipe so that the rest of the
* application knows that the JACK client thread has shut
* down.
*
* NOTE: clients do not need to call this. It exists only
* to help more complex clients understand what is going
* on. It should be called before jack_client_activate().
*
* NOTE: if a client calls this AND jack_on_info_shutdown(), then
* the event of a client thread shutdown, the callback
* passed to this function will not be called, and the one passed to
* jack_on_info_shutdown() will.
*/
void jack_on_info_shutdown (jack_client_t *client,
JackInfoShutdownCallback shutdown_callback, void *arg);
/**
* Tell the Jack server to call @a process_callback whenever there is
* work be done, passing @a arg as the second argument.


+ 8
- 4
common/jack/jslist.h View File

@@ -48,8 +48,10 @@ jack_slist_alloc (void)
JSList *new_list;

new_list = (JSList*)malloc(sizeof(JSList));
new_list->data = NULL;
new_list->next = NULL;
if (new_list) {
new_list->data = NULL;
new_list->next = NULL;
}

return new_list;
}
@@ -61,8 +63,10 @@ jack_slist_prepend (JSList* list, void* data)
JSList *new_list;

new_list = (JSList*)malloc(sizeof(JSList));
new_list->data = data;
new_list->next = list;
if (new_list) {
new_list->data = data;
new_list->next = list;
}

return new_list;
}


+ 26
- 1
common/jack/types.h View File

@@ -419,7 +419,17 @@ enum JackStatus {
/**
* Client's protocol version does not match
*/
JackVersionError = 0x400
JackVersionError = 0x400,
/**
* Backend error
*/
JackBackendError = 0x800,
/**
* Client zombified failure
*/
JackClientZombie = 0x1000
};

/**
@@ -644,4 +654,19 @@ typedef struct {

} jack_transport_info_t;

/**
* Prototype for the client supplied function that is called
* whenever jackd is shutdown. Note that after server shutdown,
* the client pointer is *not* deallocated by libjack,
* the application is responsible to properly use jack_client_close()
* to release client ressources. Warning: jack_client_close() cannot be
* safely used inside the shutdown callback and has to be called outside of
* the callback context.
* @param code a status word, formed by OR-ing together the relevant @ref JackStatus bits.
* @param reason a string describing the shutdown reason (backend failure, server crash... etc...)
* @param arg pointer to a client supplied structure
*/
typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg);

#endif /* __jack_types_h__ */

+ 19
- 12
common/memops.c View File

@@ -37,6 +37,9 @@

#if defined (__SSE2__) && !defined (__sun__)
#include <emmintrin.h>
#ifdef __SSE4_1__
#include <smmintrin.h>
#endif
#endif

/* Notes about these *_SCALING values.
@@ -285,6 +288,12 @@ void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigne
__m128i y = _mm_cvttps_epi32(clipped);
__m128i shifted = _mm_slli_epi32(y, 8);

#ifdef __SSE4_1__
*(int32_t*)dst = _mm_extract_epi32(shifted, 0);
*(int32_t*)(dst+dst_skip) = _mm_extract_epi32(shifted, 1);
*(int32_t*)(dst+2*dst_skip) = _mm_extract_epi32(shifted, 2);
*(int32_t*)(dst+3*dst_skip) = _mm_extract_epi32(shifted, 3);
#else
__m128i shuffled1 = _mm_shuffle_epi32(shifted, _MM_SHUFFLE(0, 3, 2, 1));
__m128i shuffled2 = _mm_shuffle_epi32(shifted, _MM_SHUFFLE(1, 0, 3, 2));
__m128i shuffled3 = _mm_shuffle_epi32(shifted, _MM_SHUFFLE(2, 1, 0, 3));
@@ -294,6 +303,7 @@ void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigne
_mm_store_ss((float*)(dst+dst_skip), (__m128)shuffled1);
_mm_store_ss((float*)(dst+2*dst_skip), (__m128)shuffled2);
_mm_store_ss((float*)(dst+3*dst_skip), (__m128)shuffled3);
#endif
dst += 4*dst_skip;

src+= 4;
@@ -421,6 +431,12 @@ void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned l
__m128 samples = _mm_loadu_ps(src);
__m128i converted = float_24_sse(samples);

#ifdef __SSE4_1__
z[0] = _mm_extract_epi32(converted, 0);
z[1] = _mm_extract_epi32(converted, 1);
z[2] = _mm_extract_epi32(converted, 2);
z[3] = _mm_extract_epi32(converted, 3);
#else
__m128i shuffled1 = _mm_shuffle_epi32(converted, _MM_SHUFFLE(0, 3, 2, 1));
__m128i shuffled2 = _mm_shuffle_epi32(converted, _MM_SHUFFLE(1, 0, 3, 2));
__m128i shuffled3 = _mm_shuffle_epi32(converted, _MM_SHUFFLE(2, 1, 0, 3));
@@ -431,13 +447,11 @@ void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned l
_mm_store_ss((float*)z+3, (__m128)shuffled3);

for (i = 0; i != 4; ++i) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy (dst, z+i, 3);
#elif __BYTE_ORDER == __BIG_ENDIAN
memcpy (dst, (float*)((char *)&z + 1)+i, 3);
#endif
dst += dst_skip;
}
#endif

nsamples -= 4;
src += 4;
}
@@ -481,7 +495,7 @@ void sample_move_dS_s24s (jack_default_audio_sample_t *dst, char *src, unsigned
x <<= 8;
x |= (unsigned char)(src[0]);
/* correct sign bit and the rest of the top byte */
if (src[0] & 0x80) {
if (src[2] & 0x80) {
x |= 0xff << 24;
}
#endif
@@ -500,17 +514,10 @@ void sample_move_dS_s24 (jack_default_audio_sample_t *dst, char *src, unsigned l
while (nsamples >= 4) {
int x0, x1, x2, x3;

#if __BYTE_ORDER == __LITTLE_ENDIAN
memcpy((char*)&x0 + 1, src, 3);
memcpy((char*)&x1 + 1, src+src_skip, 3);
memcpy((char*)&x2 + 1, src+2*src_skip, 3);
memcpy((char*)&x3 + 1, src+3*src_skip, 3);
#elif __BYTE_ORDER == __BIG_ENDIAN
memcpy(&x0, src, 3);
memcpy(&x1, src+src_skip, 3);
memcpy(&x2, src+2*src_skip, 3);
memcpy(&x3, src+3*src_skip, 3);
#endif
src += 4 * src_skip;

const __m128i block_i = _mm_set_epi32(x3, x2, x1, x0);


+ 746
- 0
common/netjack.c View File

@@ -0,0 +1,746 @@

/* -*- mode: c; c-file-style: "linux"; -*- */
/*
NetJack Abstraction.

Copyright (C) 2008 Pieter Palmers <pieterpalmers@users.sourceforge.net>
Copyright (C) 2006 Torben Hohn <torbenh@gmx.de>
Copyright (C) 2003 Robert Ham <rah@bash.sh>
Copyright (C) 2001 Paul Davis

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.

$Id: net_driver.c,v 1.17 2006/04/16 20:16:10 torbenh Exp $
*/


#include <math.h>
#include <stdio.h>
#include <memory.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>

#include <jack/types.h>
#include "jack/jslist.h"

#include <sys/types.h>

#ifdef WIN32
#include <winsock.h>
#include <malloc.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif

#include "netjack.h"

//#include "config.h"

#if HAVE_SAMPLERATE
#include <samplerate.h>
#endif

#if HAVE_CELT
#include <celt/celt.h>
#endif

#include "netjack.h"
#include "netjack_packet.h"

// JACK2
#include "jack/control.h"

#define MIN(x,y) ((x)<(y) ? (x) : (y))

static int sync_state = 1;
static jack_transport_state_t last_transport_state;

static int
net_driver_sync_cb(jack_transport_state_t state, jack_position_t *pos, void *data)
{
int retval = sync_state;

if (state == JackTransportStarting && last_transport_state != JackTransportStarting) {
retval = 0;
}
// if (state == JackTransportStarting)
// jack_info("Starting sync_state = %d", sync_state);
last_transport_state = state;
return retval;
}

int netjack_wait( netjack_driver_state_t *netj )
{
int we_have_the_expected_frame = 0;
jack_nframes_t next_frame_avail;
jack_time_t packet_recv_time_stamp;
jacknet_packet_header *pkthdr;

if( !netj->next_deadline_valid ) {
netj->next_deadline = jack_get_time() + netj->deadline_offset;
netj->next_deadline_valid = 1;
}

// Increment expected frame here.

if( netj->expected_framecnt_valid ) {
netj->expected_framecnt += 1;
} else {
// starting up.... lets look into the packetcache, and fetch the highest packet.
packet_cache_drain_socket( global_packcache, netj->sockfd );
if( packet_cache_get_highest_available_framecnt( global_packcache, &next_frame_avail ) ) {
netj->expected_framecnt = next_frame_avail;
netj->expected_framecnt_valid = 1;
} else {
// no packets there... start normally.
netj->expected_framecnt = 0;
netj->expected_framecnt_valid = 1;
}

}

//jack_log( "expect %d", netj->expected_framecnt );
// Now check if required packet is already in the cache.
// then poll (have deadline calculated)
// then drain socket, rinse and repeat.
while(1) {
if( packet_cache_get_next_available_framecnt( global_packcache, netj->expected_framecnt, &next_frame_avail) ) {
if( next_frame_avail == netj->expected_framecnt ) {
we_have_the_expected_frame = 1;
if( !netj->always_deadline )
break;
}
}
if( ! netjack_poll_deadline( netj->sockfd, netj->next_deadline ) ) {
break;
}

packet_cache_drain_socket( global_packcache, netj->sockfd );
}

// check if we know who to send our packets too.
if (!netj->srcaddress_valid)
if( global_packcache->master_address_valid ) {
memcpy (&(netj->syncsource_address), &(global_packcache->master_address), sizeof( struct sockaddr_in ) );
netj->srcaddress_valid = 1;
}

// XXX: switching mode unconditionally is stupid.
// if we were running free perhaps we like to behave differently
// ie. fastforward one packet etc.
// well... this is the first packet we see. hmm.... dunno ;S
// it works... so...
netj->running_free = 0;

//if( !we_have_the_expected_frame )
// jack_error( "netxrun... %d", netj->expected_framecnt );

if( we_have_the_expected_frame ) {

jack_time_t now = jack_get_time();
if( now < netj->next_deadline )
netj->time_to_deadline = netj->next_deadline - now;
else
netj->time_to_deadline = 0;

packet_cache_retreive_packet_pointer( global_packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize , &packet_recv_time_stamp);
pkthdr = (jacknet_packet_header *) netj->rx_buf;
packet_header_ntoh(pkthdr);
netj->deadline_goodness = (int)pkthdr->sync_state;
netj->packet_data_valid = 1;

int want_deadline;
if( netj->jitter_val != 0 )
want_deadline = netj->jitter_val;
else if( netj->latency < 4 )
want_deadline = -netj->period_usecs/2;
else
want_deadline = (netj->period_usecs/4+10*(int)netj->period_usecs*netj->latency/100);

if( netj->deadline_goodness != MASTER_FREEWHEELS ) {
if( netj->deadline_goodness < want_deadline ) {
netj->deadline_offset -= netj->period_usecs/100;
//jack_log( "goodness: %d, Adjust deadline: --- %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 );
}
if( netj->deadline_goodness > want_deadline ) {
netj->deadline_offset += netj->period_usecs/100;
//jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 );
}
}
if( netj->deadline_offset < (netj->period_usecs*70/100) ) {
jack_error( "master is forcing deadline_offset to below 70%% of period_usecs... increase latency setting on master" );
netj->deadline_offset = (netj->period_usecs*90/100);
}

netj->next_deadline = jack_get_time() + netj->deadline_offset;
} else {
netj->time_to_deadline = 0;
netj->next_deadline = jack_get_time() + netj->deadline_offset;
// bah... the packet is not there.
// either
// - it got lost.
// - its late
// - sync source is not sending anymore.

// lets check if we have the next packets, we will just run a cycle without data.
// in that case.

if( packet_cache_get_next_available_framecnt( global_packcache, netj->expected_framecnt, &next_frame_avail) )
{
jack_nframes_t offset = next_frame_avail - netj->expected_framecnt;

//XXX: hmm... i need to remember why resync_threshold wasnt right.
//if( offset < netj->resync_threshold )
if( offset < 10 ) {
// ok. dont do nothing. we will run without data.
// this seems to be one or 2 lost packets.
//
// this can also be reordered packet jitter.
// (maybe this is not happening in real live)
// but it happens in netem.

netj->packet_data_valid = 0;

// I also found this happening, when the packet queue, is too full.
// but wtf ? use a smaller latency. this link can handle that ;S
if( packet_cache_get_fill( global_packcache, netj->expected_framecnt ) > 80.0 )
netj->next_deadline -= netj->period_usecs/2;


} else {
// the diff is too high. but we have a packet in the future.
// lets resync.
netj->expected_framecnt = next_frame_avail;
packet_cache_retreive_packet_pointer( global_packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL );
pkthdr = (jacknet_packet_header *) netj->rx_buf;
packet_header_ntoh(pkthdr);
//netj->deadline_goodness = 0;
netj->deadline_goodness = (int)pkthdr->sync_state - (int)netj->period_usecs * offset;
netj->next_deadline_valid = 0;
netj->packet_data_valid = 1;
}

} else {
// no packets in buffer.
netj->packet_data_valid = 0;

//printf( "frame %d No Packet in queue. num_lost_packets = %d \n", netj->expected_framecnt, netj->num_lost_packets );
if( netj->num_lost_packets < 5 ) {
// ok. No Packet in queue. The packet was either lost,
// or we are running too fast.
//
// Adjusting the deadline unconditionally resulted in
// too many xruns on master.
// But we need to adjust for the case we are running too fast.
// So lets check if the last packet is there now.
//
// It would not be in the queue anymore, if it had been
// retrieved. This might break for redundancy, but
// i will make the packet cache drop redundant packets,
// that have already been retreived.
//
if( packet_cache_get_highest_available_framecnt( global_packcache, &next_frame_avail) ) {
if( next_frame_avail == (netj->expected_framecnt - 1) ) {
// Ok. the last packet is there now.
// and it had not been retrieved.
//
// TODO: We are still dropping 2 packets.
// perhaps we can adjust the deadline
// when (num_packets lost == 0)

// This might still be too much.
netj->next_deadline += netj->period_usecs;
}
}
} else if( (netj->num_lost_packets <= 100) ) {
// lets try adjusting the deadline harder, for some packets, we might have just ran 2 fast.
netj->next_deadline += netj->period_usecs*netj->latency/8;
} else {

// But now we can check for any new frame available.
//
if( packet_cache_get_highest_available_framecnt( global_packcache, &next_frame_avail) ) {
netj->expected_framecnt = next_frame_avail;
packet_cache_retreive_packet_pointer( global_packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL );
pkthdr = (jacknet_packet_header *) netj->rx_buf;
packet_header_ntoh(pkthdr);
netj->deadline_goodness = pkthdr->sync_state;
netj->next_deadline_valid = 0;
netj->packet_data_valid = 1;
netj->running_free = 0;
jack_info( "resync after freerun... %d", netj->expected_framecnt );
} else {
if( netj->num_lost_packets == 101 ) {
jack_info( "master seems gone... entering freerun mode", netj->expected_framecnt );
}

netj->running_free = 1;

// when we really dont see packets.
// reset source address. and open possibility for new master.
// maybe dsl reconnect. Also restart of netsource without fix
// reply address changes port.
if (netj->num_lost_packets > 200 ) {
netj->srcaddress_valid = 0;
packet_cache_reset_master_address( global_packcache );
}
}
}
}
}

int retval = 0;

if( !netj->packet_data_valid ) {
netj->num_lost_packets += 1;
if( netj->num_lost_packets == 1 )
retval = netj->period_usecs;
} else {
if( (netj->num_lost_packets>1) && !netj->running_free )
retval = (netj->num_lost_packets-1) * netj->period_usecs;

netj->num_lost_packets = 0;
}

return retval;
}

void netjack_send_silence( netjack_driver_state_t *netj, int syncstate )
{
int tx_size = get_sample_size(netj->bitdepth) * netj->playback_channels * netj->net_period_up + sizeof(jacknet_packet_header);
unsigned int *packet_buf, *packet_bufX;

packet_buf = alloca( tx_size);
jacknet_packet_header *tx_pkthdr = (jacknet_packet_header *)packet_buf;
jacknet_packet_header *rx_pkthdr = (jacknet_packet_header *)netj->rx_buf;

//framecnt = rx_pkthdr->framecnt;

netj->reply_port = rx_pkthdr->reply_port;

// offset packet_bufX by the packetheader.
packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);

tx_pkthdr->sync_state = syncstate;
tx_pkthdr->framecnt = netj->expected_framecnt;

// memset 0 the payload.
int payload_size = get_sample_size(netj->bitdepth) * netj->playback_channels * netj->net_period_up;
memset(packet_bufX, 0, payload_size);

packet_header_hton(tx_pkthdr);
if (netj->srcaddress_valid)
{
int r;
if (netj->reply_port)
netj->syncsource_address.sin_port = htons(netj->reply_port);

for( r=0; r<netj->redundancy; r++ )
netjack_sendto(netj->outsockfd, (char *)packet_buf, tx_size,
0, (struct sockaddr*)&(netj->syncsource_address), sizeof(struct sockaddr_in), netj->mtu);
}
}


void netjack_attach( netjack_driver_state_t *netj )
{
//puts ("net_driver_attach");
jack_port_t * port;
char buf[32];
unsigned int chn;
int port_flags;


if (netj->handle_transport_sync)
jack_set_sync_callback(netj->client, (JackSyncCallback) net_driver_sync_cb, NULL);

port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;

for (chn = 0; chn < netj->capture_channels_audio; chn++) {
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1);

port = jack_port_register (netj->client, buf,
JACK_DEFAULT_AUDIO_TYPE,
port_flags, 0);
if (!port) {
jack_error ("NET: cannot register port for %s", buf);
break;
}

netj->capture_ports =
jack_slist_append (netj->capture_ports, port);

if( netj->bitdepth == CELT_MODE ) {
#if HAVE_CELT
#if HAVE_CELT_API_0_7
celt_int32 lookahead;
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL );
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) );
#else
celt_int32_t lookahead;
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL );
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( celt_mode ) );
#endif
celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead );
netj->codec_latency = 2*lookahead;
#endif
} else {
#if HAVE_SAMPLERATE
netj->capture_srcs = jack_slist_append(netj->capture_srcs, src_new(SRC_LINEAR, 1, NULL));
#endif
}
}
for (chn = netj->capture_channels_audio; chn < netj->capture_channels; chn++) {
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn + 1);

port = jack_port_register (netj->client, buf,
JACK_DEFAULT_MIDI_TYPE,
port_flags, 0);
if (!port) {
jack_error ("NET: cannot register port for %s", buf);
break;
}

netj->capture_ports =
jack_slist_append (netj->capture_ports, port);
}

port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;

for (chn = 0; chn < netj->playback_channels_audio; chn++) {
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1);

port = jack_port_register (netj->client, buf,
JACK_DEFAULT_AUDIO_TYPE,
port_flags, 0);

if (!port) {
jack_error ("NET: cannot register port for %s", buf);
break;
}

netj->playback_ports =
jack_slist_append (netj->playback_ports, port);
if( netj->bitdepth == CELT_MODE ) {
#if HAVE_CELT
#if HAVE_CELT_API_0_7
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL );
netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) );
#else
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL );
netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode ) );
#endif
#endif
} else {
#if HAVE_SAMPLERATE
netj->playback_srcs = jack_slist_append(netj->playback_srcs, src_new(SRC_LINEAR, 1, NULL));
#endif
}
}
for (chn = netj->playback_channels_audio; chn < netj->playback_channels; chn++) {
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1);

port = jack_port_register (netj->client, buf,
JACK_DEFAULT_MIDI_TYPE,
port_flags, 0);

if (!port) {
jack_error ("NET: cannot register port for %s", buf);
break;
}

netj->playback_ports =
jack_slist_append (netj->playback_ports, port);
}

jack_activate (netj->client);
}


void netjack_detach( netjack_driver_state_t *netj )
{
JSList * node;


for (node = netj->capture_ports; node; node = jack_slist_next (node))
jack_port_unregister (netj->client,
((jack_port_t *) node->data));

jack_slist_free (netj->capture_ports);
netj->capture_ports = NULL;

for (node = netj->playback_ports; node; node = jack_slist_next (node))
jack_port_unregister (netj->client,
((jack_port_t *) node->data));

jack_slist_free (netj->playback_ports);
netj->playback_ports = NULL;
}


netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj,
jack_client_t * client,
const char *name,
unsigned int capture_ports,
unsigned int playback_ports,
unsigned int capture_ports_midi,
unsigned int playback_ports_midi,
jack_nframes_t sample_rate,
jack_nframes_t period_size,
unsigned int listen_port,
unsigned int transport_sync,
unsigned int resample_factor,
unsigned int resample_factor_up,
unsigned int bitdepth,
unsigned int use_autoconfig,
unsigned int latency,
unsigned int redundancy,
int dont_htonl_floats,
int always_deadline,
int jitter_val )
{

// Fill in netj values.
// might be subject to autoconfig...
// so dont calculate anything with them...


netj->sample_rate = sample_rate;
netj->period_size = period_size;
netj->dont_htonl_floats = dont_htonl_floats;

netj->listen_port = listen_port;

netj->capture_channels = capture_ports + capture_ports_midi;
netj->capture_channels_audio = capture_ports;
netj->capture_channels_midi = capture_ports_midi;
netj->capture_ports = NULL;
netj->playback_channels = playback_ports + playback_ports_midi;
netj->playback_channels_audio = playback_ports;
netj->playback_channels_midi = playback_ports_midi;
netj->playback_ports = NULL;
netj->codec_latency = 0;

netj->handle_transport_sync = transport_sync;
netj->mtu = 1400;
netj->latency = latency;
netj->redundancy = redundancy;
netj->use_autoconfig = use_autoconfig;
netj->always_deadline = always_deadline;


netj->client = client;


if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE))
{
jack_info ("Invalid bitdepth: %d (8, 16 or 0 for float) !!!", bitdepth);
return NULL;
}
netj->bitdepth = bitdepth;


if (resample_factor_up == 0)
resample_factor_up = resample_factor;

netj->resample_factor = resample_factor;
netj->resample_factor_up = resample_factor_up;


return netj;
}

void netjack_release( netjack_driver_state_t *netj )
{
close( netj->sockfd );
close( netj->outsockfd );

packet_cache_free( global_packcache );
global_packcache = NULL;
}

int
netjack_startup( netjack_driver_state_t *netj )
{
int first_pack_len;
struct sockaddr_in address;
// Now open the socket, and wait for the first packet to arrive...
netj->sockfd = socket (AF_INET, SOCK_DGRAM, 0);
#ifdef WIN32
if (netj->sockfd == INVALID_SOCKET)
#else
if (netj->sockfd == -1)
#endif
{
jack_info ("socket error");
return -1;
}
address.sin_family = AF_INET;
address.sin_port = htons(netj->listen_port);
address.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind (netj->sockfd, (struct sockaddr *) &address, sizeof (address)) < 0)
{
jack_info("bind error");
return -1;
}

netj->outsockfd = socket (AF_INET, SOCK_DGRAM, 0);
#ifdef WIN32
if (netj->outsockfd == INVALID_SOCKET)
#else
if (netj->outsockfd == -1)
#endif
{
jack_info ("socket error");
return -1;
}
netj->srcaddress_valid = 0;
if (netj->use_autoconfig)
{
jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header));
#ifdef WIN32
int address_size = sizeof( struct sockaddr_in );
#else
socklen_t address_size = sizeof (struct sockaddr_in);
#endif
//jack_info ("Waiting for an incoming packet !!!");
//jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!");

while(1) {
first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size);
#ifdef WIN32
if( first_pack_len == -1 ) {
first_pack_len = sizeof(jacknet_packet_header);
break;
}
#else
if (first_pack_len == sizeof (jacknet_packet_header))
break;
#endif
}
netj->srcaddress_valid = 1;

if (first_pack_len == sizeof (jacknet_packet_header))
{
packet_header_ntoh (first_packet);

jack_info ("AutoConfig Override !!!");
if (netj->sample_rate != first_packet->sample_rate)
{
jack_info ("AutoConfig Override: Master JACK sample rate = %d", first_packet->sample_rate);
netj->sample_rate = first_packet->sample_rate;
}

if (netj->period_size != first_packet->period_size)
{
jack_info ("AutoConfig Override: Master JACK period size is %d", first_packet->period_size);
netj->period_size = first_packet->period_size;
}
if (netj->capture_channels_audio != first_packet->capture_channels_audio)
{
jack_info ("AutoConfig Override: capture_channels_audio = %d", first_packet->capture_channels_audio);
netj->capture_channels_audio = first_packet->capture_channels_audio;
}
if (netj->capture_channels_midi != first_packet->capture_channels_midi)
{
jack_info ("AutoConfig Override: capture_channels_midi = %d", first_packet->capture_channels_midi);
netj->capture_channels_midi = first_packet->capture_channels_midi;
}
if (netj->playback_channels_audio != first_packet->playback_channels_audio)
{
jack_info ("AutoConfig Override: playback_channels_audio = %d", first_packet->playback_channels_audio);
netj->playback_channels_audio = first_packet->playback_channels_audio;
}
if (netj->playback_channels_midi != first_packet->playback_channels_midi)
{
jack_info ("AutoConfig Override: playback_channels_midi = %d", first_packet->playback_channels_midi);
netj->playback_channels_midi = first_packet->playback_channels_midi;
}

netj->mtu = first_packet->mtu;
jack_info ("MTU is set to %d bytes", first_packet->mtu);
netj->latency = first_packet->latency;
}
}
netj->capture_channels = netj->capture_channels_audio + netj->capture_channels_midi;
netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi;

if( (netj->capture_channels * netj->period_size * netj->latency * 4) > 100000000 ) {
jack_error( "autoconfig requests more than 100MB packet cache... bailing out" );
exit(1);
}

if( netj->playback_channels > 1000 ) {
jack_error( "autoconfig requests more than 1000 playback channels... bailing out" );
exit(1);
}


if( netj->mtu < (2*sizeof( jacknet_packet_header )) ) {
jack_error( "bullshit mtu requested by autoconfig" );
exit(1);
}

if( netj->sample_rate == 0 ) {
jack_error( "sample_rate 0 requested by autoconfig" );
exit(1);
}

// After possible Autoconfig: do all calculations...
netj->period_usecs =
(jack_time_t) floor ((((float) netj->period_size) / (float)netj->sample_rate)
* 1000000.0f);
if( netj->latency == 0 )
netj->deadline_offset = 50*netj->period_usecs;
else
netj->deadline_offset = netj->period_usecs + 10*netj->latency*netj->period_usecs/100;

if( netj->bitdepth == CELT_MODE ) {
// celt mode.
// TODO: this is a hack. But i dont want to change the packet header.
netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8)&(~1);
netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8)&(~1);
netj->net_period_down = netj->resample_factor;
netj->net_period_up = netj->resample_factor_up;
} else {
netj->net_period_down = (float) netj->period_size / (float) netj->resample_factor;
netj->net_period_up = (float) netj->period_size / (float) netj->resample_factor_up;
}

netj->rx_bufsize = sizeof (jacknet_packet_header) + netj->net_period_down * netj->capture_channels * get_sample_size (netj->bitdepth);
netj->pkt_buf = malloc (netj->rx_bufsize);
global_packcache = packet_cache_new (netj->latency + 50, netj->rx_bufsize, netj->mtu);

netj->expected_framecnt_valid = 0;
netj->num_lost_packets = 0;
netj->next_deadline_valid = 0;
netj->deadline_goodness = 0;
netj->time_to_deadline = 0;

// Special handling for latency=0
if( netj->latency == 0 )
netj->resync_threshold = 0;
else
netj->resync_threshold = MIN( 15, netj->latency-1 );

netj->running_free = 0;

return 0;
}

+ 147
- 0
common/netjack.h View File

@@ -0,0 +1,147 @@

/*
Copyright (C) 2003 Robert Ham <rah@bash.sh>
Copyright (C) 2005 Torben Hohn <torbenh@gmx.de>

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 __NETJACK_H__
#define __NETJACK_H__

#include <unistd.h>

#include <jack/types.h>
//#include <jack/driver.h>
#include <jack/jack.h>
#include <jack/transport.h>

#include "jack/jslist.h"

//#include <netinet/in.h>

#ifdef __cplusplus
extern "C"
{
#endif

typedef struct _netjack_driver_state netjack_driver_state_t;

struct _netjack_driver_state {
jack_nframes_t net_period_up;
jack_nframes_t net_period_down;

jack_nframes_t sample_rate;
jack_nframes_t bitdepth;
jack_nframes_t period_size;
jack_time_t period_usecs;
int dont_htonl_floats;
int always_deadline;

jack_nframes_t codec_latency;

unsigned int listen_port;

unsigned int capture_channels;
unsigned int playback_channels;
unsigned int capture_channels_audio;
unsigned int playback_channels_audio;
unsigned int capture_channels_midi;
unsigned int playback_channels_midi;

JSList *capture_ports;
JSList *playback_ports;
JSList *playback_srcs;
JSList *capture_srcs;

jack_client_t *client;

#ifdef WIN32
SOCKET sockfd;
SOCKET outsockfd;
#else
int sockfd;
int outsockfd;
#endif

struct sockaddr_in syncsource_address;

int reply_port;
int srcaddress_valid;

int sync_state;
unsigned int handle_transport_sync;

unsigned int *rx_buf;
unsigned int *pkt_buf;
unsigned int rx_bufsize;
//unsigned int tx_bufsize;
unsigned int mtu;
unsigned int latency;
unsigned int redundancy;

jack_nframes_t expected_framecnt;
int expected_framecnt_valid;
unsigned int num_lost_packets;
jack_time_t next_deadline;
jack_time_t deadline_offset;
int next_deadline_valid;
int packet_data_valid;
int resync_threshold;
int running_free;
int deadline_goodness;
jack_time_t time_to_deadline;
unsigned int use_autoconfig;
unsigned int resample_factor;
unsigned int resample_factor_up;
int jitter_val;
};

int netjack_wait( netjack_driver_state_t *netj );
void netjack_send_silence( netjack_driver_state_t *netj, int syncstate );
void netjack_read( netjack_driver_state_t *netj, jack_nframes_t nframes ) ;
void netjack_write( netjack_driver_state_t *netj, jack_nframes_t nframes, int syncstate );
void netjack_attach( netjack_driver_state_t *netj );
void netjack_detach( netjack_driver_state_t *netj );

netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj,
jack_client_t * client,
const char *name,
unsigned int capture_ports,
unsigned int playback_ports,
unsigned int capture_ports_midi,
unsigned int playback_ports_midi,
jack_nframes_t sample_rate,
jack_nframes_t period_size,
unsigned int listen_port,
unsigned int transport_sync,
unsigned int resample_factor,
unsigned int resample_factor_up,
unsigned int bitdepth,
unsigned int use_autoconfig,
unsigned int latency,
unsigned int redundancy,
int dont_htonl_floats,
int always_deadline,
int jitter_val );

void netjack_release( netjack_driver_state_t *netj );
int netjack_startup( netjack_driver_state_t *netj );

#ifdef __cplusplus
}
#endif

#endif

+ 1520
- 0
common/netjack_packet.c
File diff suppressed because it is too large
View File


+ 165
- 0
common/netjack_packet.h View File

@@ -0,0 +1,165 @@

/*
* NetJack - Packet Handling functions
*
* used by the driver and the jacknet_client
*
* Copyright (C) 2006 Torben Hohn <torbenh@gmx.de>
*
* 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.
*
* $Id: net_driver.c,v 1.16 2006/03/20 19:41:37 torbenh Exp $
*
*/

#ifndef __JACK_NET_PACKET_H__
#define __JACK_NET_PACKET_H__

#ifdef __cplusplus
extern "C"
{
#endif

#include <jack/jack.h>
#include <jack/types.h>
//#include <jack/engine.h>
#include <jack/jslist.h>

#include <jack/midiport.h>

//#include <netinet/in.h>
// The Packet Header.

#define CELT_MODE 1000 // Magic bitdepth value that indicates CELT compression
#define MASTER_FREEWHEELS 0x80000000

typedef struct _jacknet_packet_header jacknet_packet_header;

struct _jacknet_packet_header
{
// General AutoConf Data
jack_nframes_t capture_channels_audio;
jack_nframes_t playback_channels_audio;
jack_nframes_t capture_channels_midi;
jack_nframes_t playback_channels_midi;
jack_nframes_t period_size;
jack_nframes_t sample_rate;

// Transport Sync
jack_nframes_t sync_state;
jack_nframes_t transport_frame;
jack_nframes_t transport_state;

// Packet loss Detection, and latency reduction
jack_nframes_t framecnt;
jack_nframes_t latency;

jack_nframes_t reply_port;
jack_nframes_t mtu;
jack_nframes_t fragment_nr;
};

typedef union _int_float int_float_t;

union _int_float
{
uint32_t i;
float f;
};

// fragment reorder cache.
typedef struct _cache_packet cache_packet;

struct _cache_packet
{
int valid;
int num_fragments;
int packet_size;
int mtu;
jack_time_t recv_timestamp;
jack_nframes_t framecnt;
char * fragment_array;
char * packet_buf;
};

typedef struct _packet_cache packet_cache;

struct _packet_cache
{
int size;
cache_packet *packets;
int mtu;
struct sockaddr_in master_address;
int master_address_valid;
jack_nframes_t last_framecnt_retreived;
int last_framecnt_retreived_valid;
};

extern packet_cache *global_packcache;

// fragment cache function prototypes
// XXX: Some of these are private.
packet_cache *packet_cache_new(int num_packets, int pkt_size, int mtu);
void packet_cache_free(packet_cache *pkt_cache);

cache_packet *packet_cache_get_packet(packet_cache *pkt_cache, jack_nframes_t framecnt);
cache_packet *packet_cache_get_oldest_packet(packet_cache *pkt_cache);
cache_packet *packet_cache_get_free_packet(packet_cache *pkt_cache);

void cache_packet_reset(cache_packet *pack);
void cache_packet_set_framecnt(cache_packet *pack, jack_nframes_t framecnt);
void cache_packet_add_fragment(cache_packet *pack, char *packet_buf, int rcv_len);
int cache_packet_is_complete(cache_packet *pack);

void packet_cache_drain_socket( packet_cache *pcache, int sockfd );
void packet_cache_reset_master_address( packet_cache *pcache );
float packet_cache_get_fill( packet_cache *pcache, jack_nframes_t expected_framecnt );
int packet_cache_retreive_packet_pointer( packet_cache *pcache, jack_nframes_t framecnt, char **packet_buf, int pkt_size, jack_time_t *timestamp );
int packet_cache_release_packet( packet_cache *pcache, jack_nframes_t framecnt );
int packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt );
int packet_cache_get_highest_available_framecnt( packet_cache *pcache, jack_nframes_t *framecnt );
int packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt );
// Function Prototypes

int netjack_poll_deadline (int sockfd, jack_time_t deadline);

void netjack_sendto(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, int addr_size, int mtu);


int get_sample_size(int bitdepth);
void packet_header_hton(jacknet_packet_header *pkthdr);

void packet_header_ntoh(jacknet_packet_header *pkthdr);

void render_payload_to_jack_ports(int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats );

void render_jack_ports_to_payload(int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats );


// XXX: This is sort of deprecated:
// This one waits forever. an is not using ppoll
int netjack_poll(int sockfd, int timeout);

// TODO: these are deprecated.
//int netjack_recvfrom(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, socklen_t *addr_size, int mtu);
//int netjack_recv(int sockfd, char *packet_buf, int pkt_size, int flags, int mtu);

void decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf);
void encode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf);
#ifdef __cplusplus
}
#endif
#endif


+ 193
- 189
common/ringbuffer.c View File

@@ -67,23 +67,27 @@ size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);
EXPORT jack_ringbuffer_t *
jack_ringbuffer_create (size_t sz)
{
int power_of_two;
jack_ringbuffer_t *rb;

rb = (jack_ringbuffer_t*)malloc (sizeof (jack_ringbuffer_t));

for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++);

rb->size = 1 << power_of_two;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->write_ptr = 0;
rb->read_ptr = 0;
rb->buf = (char*)malloc (rb->size);
memset(rb->buf, 0, rb->size);
rb->mlocked = 0;

return rb;
int power_of_two;
jack_ringbuffer_t *rb;
if ((rb = malloc (sizeof (jack_ringbuffer_t))) == NULL) {
return NULL;
}
for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++);
rb->size = 1 << power_of_two;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->write_ptr = 0;
rb->read_ptr = 0;
if ((rb->buf = malloc (rb->size)) == NULL) {
free (rb);
return NULL;
}
rb->mlocked = 0;
return rb;
}

/* Free all data associated with the ringbuffer `rb'. */
@@ -92,12 +96,12 @@ EXPORT void
jack_ringbuffer_free (jack_ringbuffer_t * rb)
{
#ifdef USE_MLOCK
if (rb->mlocked) {
munlock (rb->buf, rb->size);
}
if (rb->mlocked) {
munlock (rb->buf, rb->size);
}
#endif /* USE_MLOCK */
free (rb->buf);
free (rb);
free (rb->buf);
free (rb);
}

/* Lock the data block of `rb' using the system call 'mlock'. */
@@ -106,12 +110,12 @@ EXPORT int
jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
{
#ifdef USE_MLOCK
if (mlock (rb->buf, rb->size)) {
return -1;
}
if (mlock (rb->buf, rb->size)) {
return -1;
}
#endif /* USE_MLOCK */
rb->mlocked = 1;
return 0;
rb->mlocked = 1;
return 0;
}

/* Reset the read and write pointers to zero. This is not thread
@@ -120,8 +124,8 @@ jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
EXPORT void
jack_ringbuffer_reset (jack_ringbuffer_t * rb)
{
rb->read_ptr = 0;
rb->write_ptr = 0;
rb->read_ptr = 0;
rb->write_ptr = 0;
}

/* Reset the read and write pointers to zero. This is not thread
@@ -130,11 +134,11 @@ jack_ringbuffer_reset (jack_ringbuffer_t * rb)
EXPORT void
jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz)
{
rb->size = sz;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->read_ptr = 0;
rb->write_ptr = 0;
rb->size = sz;
rb->size_mask = rb->size;
rb->size_mask -= 1;
rb->read_ptr = 0;
rb->write_ptr = 0;
}

/* Return the number of bytes available for reading. This is the
@@ -144,16 +148,16 @@ jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz)
EXPORT size_t
jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)
{
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return w - r;
} else {
return (w - r + rb->size) & rb->size_mask;
}
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return w - r;
} else {
return (w - r + rb->size) & rb->size_mask;
}
}

/* Return the number of bytes available for writing. This is the
@@ -163,18 +167,18 @@ jack_ringbuffer_read_space (const jack_ringbuffer_t * rb)
EXPORT size_t
jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
{
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
return (r - w) - 1;
} else {
return rb->size - 1;
}
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
return ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
return (r - w) - 1;
} else {
return rb->size - 1;
}
}

/* The copying data reader. Copy at most `cnt' bytes from `rb' to
@@ -183,77 +187,77 @@ jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
EXPORT size_t
jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)
{
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;

if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}

to_read = cnt > free_cnt ? free_cnt : cnt;
to_read = cnt > free_cnt ? free_cnt : cnt;

cnt2 = rb->read_ptr + to_read;
cnt2 = rb->read_ptr + to_read;

if (cnt2 > rb->size) {
n1 = rb->size - rb->read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}
if (cnt2 > rb->size) {
n1 = rb->size - rb->read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}

memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;

if (n2) {
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
}
if (n2) {
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
}

return to_read;
return to_read;
}

/* The copying data reader w/o read pointer advance. Copy at most
`cnt' bytes from `rb' to `dest'. Returns the actual number of bytes
copied. */
/* The copying data reader w/o read pointer advance. Copy at most
`cnt' bytes from `rb' to `dest'. Returns the actual number of bytes
copied. */

EXPORT size_t
jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
{
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
size_t tmp_read_ptr;
size_t free_cnt;
size_t cnt2;
size_t to_read;
size_t n1, n2;
size_t tmp_read_ptr;

tmp_read_ptr = rb->read_ptr;
tmp_read_ptr = rb->read_ptr;

if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}
if ((free_cnt = jack_ringbuffer_read_space (rb)) == 0) {
return 0;
}

to_read = cnt > free_cnt ? free_cnt : cnt;
to_read = cnt > free_cnt ? free_cnt : cnt;

cnt2 = tmp_read_ptr + to_read;
cnt2 = tmp_read_ptr + to_read;

if (cnt2 > rb->size) {
n1 = rb->size - tmp_read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}
if (cnt2 > rb->size) {
n1 = rb->size - tmp_read_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_read;
n2 = 0;
}

memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;

if (n2) {
memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
}
if (n2) {
memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
}

return to_read;
return to_read;
}

/* The copying data writer. Copy at most `cnt' bytes to `rb' from
@@ -262,36 +266,36 @@ jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
EXPORT size_t
jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
{
size_t free_cnt;
size_t cnt2;
size_t to_write;
size_t n1, n2;
size_t free_cnt;
size_t cnt2;
size_t to_write;
size_t n1, n2;

if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
return 0;
}
if ((free_cnt = jack_ringbuffer_write_space (rb)) == 0) {
return 0;
}

to_write = cnt > free_cnt ? free_cnt : cnt;
to_write = cnt > free_cnt ? free_cnt : cnt;

cnt2 = rb->write_ptr + to_write;
cnt2 = rb->write_ptr + to_write;

if (cnt2 > rb->size) {
n1 = rb->size - rb->write_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_write;
n2 = 0;
}
if (cnt2 > rb->size) {
n1 = rb->size - rb->write_ptr;
n2 = cnt2 & rb->size_mask;
} else {
n1 = to_write;
n2 = 0;
}

memcpy (&(rb->buf[rb->write_ptr]), src, n1);
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
memcpy (&(rb->buf[rb->write_ptr]), src, n1);
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;

if (n2) {
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
}
if (n2) {
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
}

return to_write;
return to_write;
}

/* Advance the read pointer `cnt' places. */
@@ -299,8 +303,8 @@ jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
EXPORT void
jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
{
size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
rb->read_ptr = tmp;
size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
rb->read_ptr = tmp;
}

/* Advance the write pointer `cnt' places. */
@@ -308,8 +312,8 @@ jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
EXPORT void
jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
{
size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
rb->write_ptr = tmp;
size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
rb->write_ptr = tmp;
}

/* The non-copying data reader. `vec' is an array of two places. Set
@@ -321,39 +325,39 @@ EXPORT void
jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,
jack_ringbuffer_data_t * vec)
{
size_t free_cnt;
size_t cnt2;
size_t w, r;
size_t free_cnt;
size_t cnt2;
size_t w, r;

w = rb->write_ptr;
r = rb->read_ptr;
w = rb->write_ptr;
r = rb->read_ptr;

if (w > r) {
free_cnt = w - r;
} else {
free_cnt = (w - r + rb->size) & rb->size_mask;
}
if (w > r) {
free_cnt = w - r;
} else {
free_cnt = (w - r + rb->size) & rb->size_mask;
}

cnt2 = r + free_cnt;
cnt2 = r + free_cnt;

if (cnt2 > rb->size) {
if (cnt2 > rb->size) {

/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */
/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */

vec[0].buf = &(rb->buf[r]);
vec[0].len = rb->size - r;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;
vec[0].buf = &(rb->buf[r]);
vec[0].len = rb->size - r;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;

} else {
} else {

/* Single part vector: just the rest of the buffer */
/* Single part vector: just the rest of the buffer */

vec[0].buf = &(rb->buf[r]);
vec[0].len = free_cnt;
vec[1].len = 0;
}
vec[0].buf = &(rb->buf[r]);
vec[0].len = free_cnt;
vec[1].len = 0;
}
}

/* The non-copying data writer. `vec' is an array of two places. Set
@@ -365,35 +369,35 @@ EXPORT void
jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb,
jack_ringbuffer_data_t * vec)
{
size_t free_cnt;
size_t cnt2;
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
free_cnt = ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
free_cnt = (r - w) - 1;
} else {
free_cnt = rb->size - 1;
}
cnt2 = w + free_cnt;
if (cnt2 > rb->size) {
/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */
vec[0].buf = &(rb->buf[w]);
vec[0].len = rb->size - w;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;
} else {
vec[0].buf = &(rb->buf[w]);
vec[0].len = free_cnt;
vec[1].len = 0;
}
}
size_t free_cnt;
size_t cnt2;
size_t w, r;
w = rb->write_ptr;
r = rb->read_ptr;
if (w > r) {
free_cnt = ((r - w + rb->size) & rb->size_mask) - 1;
} else if (w < r) {
free_cnt = (r - w) - 1;
} else {
free_cnt = rb->size - 1;
}
cnt2 = w + free_cnt;
if (cnt2 > rb->size) {
/* Two part vector: the rest of the buffer after the current write
ptr, plus some from the start of the buffer. */
vec[0].buf = &(rb->buf[w]);
vec[0].len = rb->size - w;
vec[1].buf = rb->buf;
vec[1].len = cnt2 & rb->size_mask;
} else {
vec[0].buf = &(rb->buf[w]);
vec[0].len = free_cnt;
vec[1].len = 0;
}
}

+ 2
- 2
dbus/audio_reserve.c View File

@@ -106,10 +106,10 @@ SERVER_EXPORT void audio_release(const char * device_name)
}
if (i < DEVICE_MAX) {
jack_info("Released audio card %s", device_name);
jack_info("Released audio card %s", device_name);
rd_release(gReservedDevice[i].reserved_device);
} else {
jack_error("Audio card %s not found!!", device_name);
jack_error("Audio card %s not found!!", device_name);
}

// Close DBus connection last time


+ 2
- 2
dbus/controller_iface_control.c View File

@@ -340,7 +340,7 @@ JACK_DBUS_METHOD_ARGUMENTS_BEGIN(LoadInternal)
JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
JACK_DBUS_METHOD_ARGUMENTS_END

JACK_DBUS_METHOD_ARGUMENTS_BEGIN(UnlooadInternal)
JACK_DBUS_METHOD_ARGUMENTS_BEGIN(UnloadInternal)
JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
JACK_DBUS_METHOD_ARGUMENTS_END

@@ -366,7 +366,7 @@ JACK_DBUS_METHODS_BEGIN
JACK_DBUS_METHOD_DESCRIBE(IsRealtime, NULL)
JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL)
JACK_DBUS_METHOD_DESCRIBE(LoadInternal, NULL)
JACK_DBUS_METHOD_DESCRIBE(UnlooadInternal, NULL)
JACK_DBUS_METHOD_DESCRIBE(UnloadInternal, NULL)
JACK_DBUS_METHOD_DESCRIBE(AddSlave, NULL)
JACK_DBUS_METHOD_DESCRIBE(RemoveSlave, NULL)
JACK_DBUS_METHODS_END


+ 2
- 1
dbus/controller_iface_patchbay.c View File

@@ -1763,7 +1763,8 @@ JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID)
JACK_DBUS_METHOD_ARGUMENTS_END

JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID)
JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_INT64_AS_STRING, false)
JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING, false)
JACK_DBUS_METHOD_ARGUMENT("process_id", DBUS_TYPE_INT64_AS_STRING, true)
JACK_DBUS_METHOD_ARGUMENTS_END

JACK_DBUS_METHODS_BEGIN


+ 2
- 2
dbus/sigsegv.c View File

@@ -26,12 +26,10 @@
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <ucontext.h>
#include <dlfcn.h>
#include <execinfo.h>
#include <errno.h>
#ifndef NO_CPP_DEMANGLE
//#include <cxxabi.h>
char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status);
#endif

@@ -56,6 +54,8 @@ static void signal_segv(int signum, siginfo_t* info, void*ptr)

#else

#include <ucontext.h>

static void signal_segv(int signum, siginfo_t* info, void*ptr) {
static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"};



+ 757
- 0
example-clients/alsa_in.c View File

@@ -0,0 +1,757 @@
/** @file simple_client.c
*
* @brief This simple client demonstrates the basic features of JACK
* as they would be used by many applications.
*/

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <alloca.h>
#include <math.h>

#include <jack/jack.h>
#include <jack/jslist.h>
#include <memops.h>

#include "alsa/asoundlib.h"

#include <samplerate.h>

// Here are the lists of the jack ports...

JSList *capture_ports = NULL;
JSList *capture_srcs = NULL;
JSList *playback_ports = NULL;
JSList *playback_srcs = NULL;
jack_client_t *client;

snd_pcm_t *alsa_handle;

int jack_sample_rate;
int jack_buffer_size;

int quit = 0;
double resample_mean = 1.0;
double static_resample_factor = 1.0;

double *offset_array;
double *window_array;
int offset_differential_index = 0;

double offset_integral = 0;

// ------------------------------------------------------ commandline parameters

int sample_rate = 0; /* stream rate */
int num_channels = 2; /* count of channels */
int period_size = 1024;
int num_periods = 2;

int target_delay = 0; /* the delay which the program should try to approach. */
int max_diff = 0; /* the diff value, when a hard readpointer skip should occur */
int catch_factor = 100000;
int catch_factor2 = 10000;
double pclamp = 15.0;
double controlquant = 10000.0;
int smooth_size = 256;
int good_window=0;
int verbose = 0;
int instrument = 0;
int samplerate_quality = 2;

// Debug stuff:

volatile float output_resampling_factor = 1.0;
volatile int output_new_delay = 0;
volatile float output_offset = 0.0;
volatile float output_integral = 0.0;
volatile float output_diff = 0.0;

snd_pcm_uframes_t real_buffer_size;
snd_pcm_uframes_t real_period_size;

// format selection, and corresponding functions from memops in a nice set of structs.

typedef struct alsa_format {
snd_pcm_format_t format_id;
size_t sample_size;
void (*jack_to_soundcard) (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state);
void (*soundcard_to_jack) (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip);
const char *name;
} alsa_format_t;

alsa_format_t formats[] = {
{ SND_PCM_FORMAT_FLOAT_LE, 4, sample_move_dS_floatLE, sample_move_floatLE_sSs, "float" },
{ SND_PCM_FORMAT_S32, 4, sample_move_d32u24_sS, sample_move_dS_s32u24, "32bit" },
{ SND_PCM_FORMAT_S24_3LE, 3, sample_move_d24_sS, sample_move_dS_s24, "24bit - real" },
{ SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" },
{ SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" }
};
#define NUMFORMATS (sizeof(formats)/sizeof(formats[0]))
int format=0;

// Alsa stuff... i dont want to touch this bullshit in the next years.... please...

static int xrun_recovery(snd_pcm_t *handle, int err) {
// printf( "xrun !!!.... %d\n", err );
if (err == -EPIPE) { /* under-run */
err = snd_pcm_prepare(handle);
if (err < 0)
printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
return 0;
} else if (err == -EAGAIN) {
while ((err = snd_pcm_resume(handle)) == -EAGAIN)
usleep(100); /* wait until the suspend flag is released */
if (err < 0) {
err = snd_pcm_prepare(handle);
if (err < 0)
printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
}
return 0;
}
return err;
}

static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params )
{
int i;
int err;

for( i=0; i<NUMFORMATS; i++ ) {
/* set the sample format */
err = snd_pcm_hw_params_set_format(handle, params, formats[i].format_id);
if (err == 0) {
format = i;
return 0;
}
}

return err;
}

static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) {
int err, dir=0;
unsigned int buffer_time;
unsigned int period_time;
unsigned int rrate;
unsigned int rchannels;

/* choose all parameters */
err = snd_pcm_hw_params_any(handle, params);
if (err < 0) {
printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
return err;
}
/* set the interleaved read/write format */
err = snd_pcm_hw_params_set_access(handle, params, access);
if (err < 0) {
printf("Access type not available for playback: %s\n", snd_strerror(err));
return err;
}

/* set the sample format */
err = set_hwformat(handle, params);
if (err < 0) {
printf("Sample format not available for playback: %s\n", snd_strerror(err));
return err;
}
/* set the count of channels */
rchannels = channels;
err = snd_pcm_hw_params_set_channels_near(handle, params, &rchannels);
if (err < 0) {
printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err));
return err;
}
if (rchannels != channels) {
printf("WARNING: chennel count does not match (requested %d got %d)\n", channels, rchannels);
num_channels = rchannels;
}
/* set the stream rate */
rrate = rate;
err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
if (err < 0) {
printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
return err;
}
if (rrate != rate) {
printf("WARNING: Rate doesn't match (requested %iHz, get %iHz)\n", rate, rrate);
sample_rate = rrate;
}
/* set the buffer time */

buffer_time = 1000000*period*nperiods/rate;
err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
if (err < 0) {
printf("Unable to set buffer time %i for playback: %s\n", 1000000*period*nperiods/rate, snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_get_buffer_size( params, &real_buffer_size );
if (err < 0) {
printf("Unable to get buffer size back: %s\n", snd_strerror(err));
return err;
}
if( real_buffer_size != nperiods * period ) {
printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) real_buffer_size );
}
/* set the period time */
period_time = 1000000*period/rate;
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
if (err < 0) {
printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_get_period_size(params, &real_period_size, NULL );
if (err < 0) {
printf("Unable to get period size back: %s\n", snd_strerror(err));
return err;
}
if( real_period_size != period ) {
printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, (int)real_period_size );
}
/* write the parameters to device */
err = snd_pcm_hw_params(handle, params);
if (err < 0) {
printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
return err;
}
return 0;
}

static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period) {
int err;

/* get the current swparams */
err = snd_pcm_sw_params_current(handle, swparams);
if (err < 0) {
printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err));
return err;
}
/* start the transfer when the buffer is full */
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period );
if (err < 0) {
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 );
if (err < 0) {
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
return err;
}
/* allow the transfer when at least period_size samples can be processed */
err = snd_pcm_sw_params_set_avail_min(handle, swparams, 2*period );
if (err < 0) {
printf("Unable to set avail min for capture: %s\n", snd_strerror(err));
return err;
}
/* align all transfers to 1 sample */
err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
if (err < 0) {
printf("Unable to set transfer align for capture: %s\n", snd_strerror(err));
return err;
}
/* write the parameters to the playback device */
err = snd_pcm_sw_params(handle, swparams);
if (err < 0) {
printf("Unable to set sw params for capture: %s\n", snd_strerror(err));
return err;
}
return 0;
}

// ok... i only need this function to communicate with the alsa bloat api...

static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) {
int err;
snd_pcm_t *handle;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;

snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_sw_params_alloca(&swparams);

if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) {
printf("Capture open error: %s\n", snd_strerror(err));
return NULL;
}

if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) {
printf("Setting of hwparams failed: %s\n", snd_strerror(err));
return NULL;
}
if ((err = set_swparams(handle, swparams, period)) < 0) {
printf("Setting of swparams failed: %s\n", snd_strerror(err));
return NULL;
}

snd_pcm_start( handle );
snd_pcm_wait( handle, 200 );

return handle;
}

double hann( double x )
{
return 0.5 * (1.0 - cos( 2*M_PI * x ) );
}

/**
* The process callback for this JACK application.
* It is called by JACK at the appropriate times.
*/
int process (jack_nframes_t nframes, void *arg) {

char *outbuf;
float *resampbuf;
int rlen;
int err;
snd_pcm_sframes_t delay = target_delay;
int put_back_samples=0;
int i;

delay = snd_pcm_avail( alsa_handle );

delay -= jack_frames_since_cycle_start( client );
// Do it the hard way.
// this is for compensating xruns etc...

if( delay > (target_delay+max_diff) ) {
char *tmp = alloca( (delay-target_delay) * formats[format].sample_size * num_channels );
snd_pcm_readi( alsa_handle, tmp, delay-target_delay );
output_new_delay = (int) delay;

delay = target_delay;

// Set the resample_rate... we need to adjust the offset integral, to do this.
// first look at the PI controller, this code is just a special case, which should never execute once
// everything is swung in.
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
// Also clear the array. we are beginning a new control cycle.
for( i=0; i<smooth_size; i++ )
offset_array[i] = 0.0;
}
if( delay < (target_delay-max_diff) ) {
snd_pcm_rewind( alsa_handle, target_delay - delay );
output_new_delay = (int) delay;
delay = target_delay;

// Set the resample_rate... we need to adjust the offset integral, to do this.
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
// Also clear the array. we are beginning a new control cycle.
for( i=0; i<smooth_size; i++ )
offset_array[i] = 0.0;
}
/* ok... now we should have target_delay +- max_diff on the alsa side.
*
* calculate the number of frames, we want to get.
*/

double offset = delay - target_delay;

// Save offset.
offset_array[(offset_differential_index++)% smooth_size ] = offset;

// Build the mean of the windowed offset array
// basically fir lowpassing.
double smooth_offset = 0.0;
for( i=0; i<smooth_size; i++ )
smooth_offset +=
offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i];
smooth_offset /= (double) smooth_size;

// this is the integral of the smoothed_offset
offset_integral += smooth_offset;

// Clamp offset.
// the smooth offset still contains unwanted noise
// which would go straigth onto the resample coeff.
// it only used in the P component and the I component is used for the fine tuning anyways.
if( fabs( smooth_offset ) < pclamp )
smooth_offset = 0.0;

// ok. now this is the PI controller.
// u(t) = K * ( e(t) + 1/T \int e(t') dt' )
// K = 1/catch_factor and T = catch_factor2
double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2;

// now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean;

// Output "instrumentatio" gonna change that to real instrumentation in a few.
output_resampling_factor = (float) current_resample_factor;
output_diff = (float) smooth_offset;
output_integral = (float) offset_integral;
output_offset = (float) offset;

// Clamp a bit.
if( current_resample_factor < 0.25 ) current_resample_factor = 0.25;
if( current_resample_factor > 4 ) current_resample_factor = 4;

// Now Calculate how many samples we need.
rlen = ceil( ((double)nframes) / current_resample_factor )+2;
assert( rlen > 2 );

// Calculate resample_mean so we can init ourselves to saner values.
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
/*
* now this should do it...
*/

outbuf = alloca( rlen * formats[format].sample_size * num_channels );

resampbuf = alloca( rlen * sizeof( float ) );

// get the data...
again:
err = snd_pcm_readi(alsa_handle, outbuf, rlen);
if( err < 0 ) {
printf( "err = %d\n", err );
if (xrun_recovery(alsa_handle, err) < 0) {
//printf("Write error: %s\n", snd_strerror(err));
//exit(EXIT_FAILURE);
}
goto again;
}
if( err != rlen ) {
//printf( "read = %d\n", rlen );
}

/*
* render jack ports to the outbuf...
*/

int chn = 0;
JSList *node = capture_ports;
JSList *src_node = capture_srcs;
SRC_DATA src;

while ( node != NULL)
{
jack_port_t *port = (jack_port_t *) node->data;
float *buf = jack_port_get_buffer (port, nframes);

SRC_STATE *src_state = src_node->data;

formats[format].soundcard_to_jack( resampbuf, outbuf + format[formats].sample_size * chn, rlen, num_channels*format[formats].sample_size );

src.data_in = resampbuf;
src.input_frames = rlen;

src.data_out = buf;
src.output_frames = nframes;
src.end_of_input = 0;

src.src_ratio = current_resample_factor;

src_process( src_state, &src );

put_back_samples = rlen-src.input_frames_used;

src_node = jack_slist_next (src_node);
node = jack_slist_next (node);
chn++;
}

// Put back the samples libsamplerate did not consume.
//printf( "putback = %d\n", put_back_samples );
snd_pcm_rewind( alsa_handle, put_back_samples );

return 0;
}


/**
* Allocate the necessary jack ports...
*/

void alloc_ports( int n_capture, int n_playback ) {

int port_flags = JackPortIsOutput;
int chn;
jack_port_t *port;
char buf[32];

capture_ports = NULL;
for (chn = 0; chn < n_capture; chn++)
{
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);

port = jack_port_register (client, buf,
JACK_DEFAULT_AUDIO_TYPE,
port_flags, 0);

if (!port)
{
printf( "jacknet_client: cannot register port for %s", buf);
break;
}

capture_srcs = jack_slist_append( capture_srcs, src_new( 4-samplerate_quality, 1, NULL ) );
capture_ports = jack_slist_append (capture_ports, port);
}

port_flags = JackPortIsInput;

playback_ports = NULL;
for (chn = 0; chn < n_playback; chn++)
{
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);

port = jack_port_register (client, buf,
JACK_DEFAULT_AUDIO_TYPE,
port_flags, 0);

if (!port)
{
printf( "jacknet_client: cannot register port for %s", buf);
break;
}

playback_srcs = jack_slist_append( playback_srcs, src_new( 4-samplerate_quality, 1, NULL ) );
playback_ports = jack_slist_append (playback_ports, port);
}
}

/**
* This is the shutdown callback for this JACK application.
* It is called by JACK if the server ever shuts down or
* decides to disconnect the client.
*/

void jack_shutdown (void *arg) {

exit (1);
}

/**
* be user friendly.
* be user friendly.
* be user friendly.
*/

void printUsage() {
fprintf(stderr, "usage: alsa_out [options]\n"
"\n"
" -j <jack name> - client name\n"
" -d <alsa_device> \n"
" -c <channels> \n"
" -p <period_size> \n"
" -n <num_period> \n"
" -r <sample_rate> \n"
" -q <sample_rate quality [0..4]\n"
" -m <max_diff> \n"
" -t <target_delay> \n"
" -i turns on instrumentation\n"
" -v turns on printouts\n"
"\n");
}


/**
* the main function....
*/

void
sigterm_handler( int signal )
{
quit = 1;
}


int main (int argc, char *argv[]) {
char jack_name[30] = "alsa_in";
char alsa_device[30] = "hw:0";

extern char *optarg;
extern int optind, optopt;
int errflg=0;
int c;

while ((c = getopt(argc, argv, "ivj:r:c:p:n:d:q:m:t:f:F:C:Q:s:")) != -1) {
switch(c) {
case 'j':
strcpy(jack_name,optarg);
break;
case 'r':
sample_rate = atoi(optarg);
break;
case 'c':
num_channels = atoi(optarg);
break;
case 'p':
period_size = atoi(optarg);
break;
case 'n':
num_periods = atoi(optarg);
break;
case 'd':
strcpy(alsa_device,optarg);
break;
case 't':
target_delay = atoi(optarg);
break;
case 'q':
samplerate_quality = atoi(optarg);
break;
case 'm':
max_diff = atoi(optarg);
break;
case 'f':
catch_factor = atoi(optarg);
break;
case 'F':
catch_factor2 = atoi(optarg);
break;
case 'C':
pclamp = (double) atoi(optarg);
break;
case 'Q':
controlquant = (double) atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'i':
instrument = 1;
break;
case 's':
smooth_size = atoi(optarg);
break;
case ':':
fprintf(stderr,
"Option -%c requires an operand\n", optopt);
errflg++;
break;
case '?':
fprintf(stderr,
"Unrecognized option: -%c\n", optopt);
errflg++;
}
}
if (errflg) {
printUsage();
exit(2);
}

if( (samplerate_quality < 0) || (samplerate_quality > 4) ) {
fprintf (stderr, "invalid samplerate quality\n");
return 1;
}
if ((client = jack_client_open (jack_name, 0, NULL)) == 0) {
fprintf (stderr, "jack server not running?\n");
return 1;
}

/* tell the JACK server to call `process()' whenever
there is work to be done.
*/

jack_set_process_callback (client, process, 0);

/* tell the JACK server to call `jack_shutdown()' if
it ever shuts down, either entirely, or if it
just decides to stop calling us.
*/

jack_on_shutdown (client, jack_shutdown, 0);


// get jack sample_rate
jack_sample_rate = jack_get_sample_rate( client );

if( !sample_rate )
sample_rate = jack_sample_rate;

// now open the alsa fd...
alsa_handle = open_audiofd( alsa_device, 1, sample_rate, num_channels, period_size, num_periods);
if( alsa_handle == 0 )
exit(20);

printf( "selected sample format: %s\n", formats[format].name );

static_resample_factor = (double) jack_sample_rate / (double) sample_rate;
resample_mean = static_resample_factor;

offset_array = malloc( sizeof(double) * smooth_size );
if( offset_array == NULL ) {
fprintf( stderr, "no memory for offset_array !!!\n" );
exit(20);
}
window_array = malloc( sizeof(double) * smooth_size );
if( window_array == NULL ) {
fprintf( stderr, "no memory for window_array !!!\n" );
exit(20);
}
int i;
for( i=0; i<smooth_size; i++ ) {
offset_array[i] = 0.0;
window_array[i] = hann( (double) i / ((double) smooth_size - 1.0) );
}

jack_buffer_size = jack_get_buffer_size( client );
// Setup target delay and max_diff for the normal user, who does not play with them...
if( !target_delay )
target_delay = (num_periods*period_size / 2) + jack_buffer_size/2;

if( !max_diff )
max_diff = num_periods*period_size - target_delay ;

if( max_diff > target_delay ) {
fprintf( stderr, "target_delay (%d) cant be smaller than max_diff(%d)\n", target_delay, max_diff );
exit(20);
}
if( (target_delay+max_diff) > (num_periods*period_size) ) {
fprintf( stderr, "target_delay+max_diff (%d) cant be bigger than buffersize(%d)\n", target_delay+max_diff, num_periods*period_size );
exit(20);
}
// alloc input ports, which are blasted out to alsa...
alloc_ports( num_channels, 0 );


/* tell the JACK server that we are ready to roll */

if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
return 1;
}

signal( SIGTERM, sigterm_handler );
signal( SIGINT, sigterm_handler );

if( verbose ) {
while(!quit) {
usleep(500000);
if( output_new_delay ) {
printf( "delay = %d\n", output_new_delay );
output_new_delay = 0;
}
printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset );
}
} else if( instrument ) {
printf( "# n\tresamp\tdiff\toffseti\tintegral\n");
int n=0;
while(!quit) {
usleep(1000);
printf( "%d\t%f\t%f\t%f\t%f\n", n++, output_resampling_factor, output_diff, output_offset, output_integral );
}
} else {
while(!quit)
{
usleep(500000);
if( output_new_delay ) {
printf( "delay = %d\n", output_new_delay );
output_new_delay = 0;
}
}
}

jack_deactivate( client );
jack_client_close (client);
exit (0);
}


+ 755
- 0
example-clients/alsa_out.c View File

@@ -0,0 +1,755 @@
/** @file simple_client.c
*
* @brief This simple client demonstrates the basic features of JACK
* as they would be used by many applications.
*/

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include <alloca.h>
#include <math.h>

#include <jack/jack.h>
#include <jack/jslist.h>
#include <memops.h>

#include "alsa/asoundlib.h"

#include <samplerate.h>

// Here are the lists of the jack ports...

JSList *capture_ports = NULL;
JSList *capture_srcs = NULL;
JSList *playback_ports = NULL;
JSList *playback_srcs = NULL;
jack_client_t *client;

snd_pcm_t *alsa_handle;

int jack_sample_rate;
int jack_buffer_size;

double resample_mean = 1.0;
double static_resample_factor = 1.0;

double *offset_array;
double *window_array;
int offset_differential_index = 0;

double offset_integral = 0;
int quit = 0;

// ------------------------------------------------------ commandline parameters

int sample_rate = 0; /* stream rate */
int num_channels = 2; /* count of channels */
int period_size = 1024;
int num_periods = 2;

int target_delay = 0; /* the delay which the program should try to approach. */
int max_diff = 0; /* the diff value, when a hard readpointer skip should occur */
int catch_factor = 100000;
int catch_factor2 = 10000;
double pclamp = 15.0;
double controlquant = 10000.0;
int smooth_size = 256;
int good_window=0;
int verbose = 0;
int instrument = 0;
int samplerate_quality = 2;

// Debug stuff:

volatile float output_resampling_factor = 1.0;
volatile int output_new_delay = 0;
volatile float output_offset = 0.0;
volatile float output_integral = 0.0;
volatile float output_diff = 0.0;

snd_pcm_uframes_t real_buffer_size;
snd_pcm_uframes_t real_period_size;

// format selection, and corresponding functions from memops in a nice set of structs.

typedef struct alsa_format {
snd_pcm_format_t format_id;
size_t sample_size;
void (*jack_to_soundcard) (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state);
void (*soundcard_to_jack) (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip);
const char *name;
} alsa_format_t;

alsa_format_t formats[] = {
{ SND_PCM_FORMAT_FLOAT_LE, 4, sample_move_dS_floatLE, sample_move_floatLE_sSs, "float" },
{ SND_PCM_FORMAT_S32, 4, sample_move_d32u24_sS, sample_move_dS_s32u24, "32bit" },
{ SND_PCM_FORMAT_S24, 4, sample_move_d24_sS, sample_move_dS_s24, "24bit" },
{ SND_PCM_FORMAT_S16, 2, sample_move_d16_sS, sample_move_dS_s16, "16bit" }
};
#define NUMFORMATS (sizeof(formats)/sizeof(formats[0]))
int format=0;

// Alsa stuff... i dont want to touch this bullshit in the next years.... please...

static int xrun_recovery(snd_pcm_t *handle, int err) {
// printf( "xrun !!!.... %d\n", err );
if (err == -EPIPE) { /* under-run */
err = snd_pcm_prepare(handle);
if (err < 0)
printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
return 0;
} else if (err == -EAGAIN) {
while ((err = snd_pcm_resume(handle)) == -EAGAIN)
usleep(100); /* wait until the suspend flag is released */
if (err < 0) {
err = snd_pcm_prepare(handle);
if (err < 0)
printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
}
return 0;
}
return err;
}

static int set_hwformat( snd_pcm_t *handle, snd_pcm_hw_params_t *params )
{
int i;
int err;

for( i=0; i<NUMFORMATS; i++ ) {
/* set the sample format */
err = snd_pcm_hw_params_set_format(handle, params, formats[i].format_id);
if (err == 0) {
format = i;
return 0;
}
}

return err;
}

static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access, int rate, int channels, int period, int nperiods ) {
int err, dir=0;
unsigned int buffer_time;
unsigned int period_time;
unsigned int rrate;
unsigned int rchannels;

/* choose all parameters */
err = snd_pcm_hw_params_any(handle, params);
if (err < 0) {
printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
return err;
}
/* set the interleaved read/write format */
err = snd_pcm_hw_params_set_access(handle, params, access);
if (err < 0) {
printf("Access type not available for playback: %s\n", snd_strerror(err));
return err;
}

/* set the sample format */
err = set_hwformat(handle, params);
if (err < 0) {
printf("Sample format not available for playback: %s\n", snd_strerror(err));
return err;
}
/* set the count of channels */
rchannels = channels;
err = snd_pcm_hw_params_set_channels_near(handle, params, &rchannels);
if (err < 0) {
printf("Channels count (%i) not available for record: %s\n", channels, snd_strerror(err));
return err;
}
if (rchannels != channels) {
printf("WARNING: chennel count does not match (requested %d got %d)\n", channels, rchannels);
num_channels = rchannels;
}
/* set the stream rate */
rrate = rate;
err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
if (err < 0) {
printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
return err;
}
if (rrate != rate) {
printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, rrate);
return -EINVAL;
}
/* set the buffer time */

buffer_time = 1000000*period*nperiods/rate;
err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, &dir);
if (err < 0) {
printf("Unable to set buffer time %i for playback: %s\n", 1000000*period*nperiods/rate, snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_get_buffer_size( params, &real_buffer_size );
if (err < 0) {
printf("Unable to get buffer size back: %s\n", snd_strerror(err));
return err;
}
if( real_buffer_size != nperiods * period ) {
printf( "WARNING: buffer size does not match: (requested %d, got %d)\n", nperiods * period, (int) real_buffer_size );
}
/* set the period time */
period_time = 1000000*period/rate;
err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, &dir);
if (err < 0) {
printf("Unable to set period time %i for playback: %s\n", 1000000*period/rate, snd_strerror(err));
return err;
}
err = snd_pcm_hw_params_get_period_size(params, &real_period_size, NULL );
if (err < 0) {
printf("Unable to get period size back: %s\n", snd_strerror(err));
return err;
}
if( real_period_size != period ) {
printf( "WARNING: period size does not match: (requested %i, got %i)\n", period, (int)real_period_size );
}
/* write the parameters to device */
err = snd_pcm_hw_params(handle, params);
if (err < 0) {
printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
return err;
}
return 0;
}

static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams, int period, int nperiods) {
int err;

/* get the current swparams */
err = snd_pcm_sw_params_current(handle, swparams);
if (err < 0) {
printf("Unable to determine current swparams for capture: %s\n", snd_strerror(err));
return err;
}
/* start the transfer when the buffer is full */
err = snd_pcm_sw_params_set_start_threshold(handle, swparams, period );
if (err < 0) {
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
return err;
}
err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, -1 );
if (err < 0) {
printf("Unable to set start threshold mode for capture: %s\n", snd_strerror(err));
return err;
}
/* allow the transfer when at least period_size samples can be processed */
err = snd_pcm_sw_params_set_avail_min(handle, swparams, 1 );
if (err < 0) {
printf("Unable to set avail min for capture: %s\n", snd_strerror(err));
return err;
}
/* align all transfers to 1 sample */
err = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1);
if (err < 0) {
printf("Unable to set transfer align for capture: %s\n", snd_strerror(err));
return err;
}
/* write the parameters to the playback device */
err = snd_pcm_sw_params(handle, swparams);
if (err < 0) {
printf("Unable to set sw params for capture: %s\n", snd_strerror(err));
return err;
}
return 0;
}

// ok... i only need this function to communicate with the alsa bloat api...

static snd_pcm_t *open_audiofd( char *device_name, int capture, int rate, int channels, int period, int nperiods ) {
int err;
snd_pcm_t *handle;
snd_pcm_hw_params_t *hwparams;
snd_pcm_sw_params_t *swparams;

snd_pcm_hw_params_alloca(&hwparams);
snd_pcm_sw_params_alloca(&swparams);

if ((err = snd_pcm_open(&(handle), device_name, capture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK )) < 0) {
printf("Capture open error: %s\n", snd_strerror(err));
return NULL;
}

if ((err = set_hwparams(handle, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED, rate, channels, period, nperiods )) < 0) {
printf("Setting of hwparams failed: %s\n", snd_strerror(err));
return NULL;
}
if ((err = set_swparams(handle, swparams, period, nperiods)) < 0) {
printf("Setting of swparams failed: %s\n", snd_strerror(err));
return NULL;
}

//snd_pcm_start( handle );
//snd_pcm_wait( handle, 200 );
int num_null_samples = nperiods * period * channels;
char *tmp = alloca( num_null_samples * formats[format].sample_size );
memset( tmp, 0, num_null_samples * formats[format].sample_size );
snd_pcm_writei( handle, tmp, num_null_samples );

return handle;
}

double hann( double x )
{
return 0.5 * (1.0 - cos( 2*M_PI * x ) );
}

/**
* The process callback for this JACK application.
* It is called by JACK at the appropriate times.
*/
int process (jack_nframes_t nframes, void *arg) {

char *outbuf;
float *resampbuf;
int rlen;
int err;
snd_pcm_sframes_t delay = target_delay;
int i;

delay = (num_periods*period_size)-snd_pcm_avail( alsa_handle ) ;

delay -= jack_frames_since_cycle_start( client );
delay += jack_get_buffer_size( client ) / 2;
// Do it the hard way.
// this is for compensating xruns etc...

if( delay > (target_delay+max_diff) ) {
snd_pcm_rewind( alsa_handle, delay - target_delay );
output_new_delay = (int) delay;

delay = target_delay;

// Set the resample_rate... we need to adjust the offset integral, to do this.
// first look at the PI controller, this code is just a special case, which should never execute once
// everything is swung in.
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
// Also clear the array. we are beginning a new control cycle.
for( i=0; i<smooth_size; i++ )
offset_array[i] = 0.0;
}
if( delay < (target_delay-max_diff) ) {
char *tmp = alloca( (target_delay-delay) * formats[format].sample_size * num_channels );
memset( tmp, 0, formats[format].sample_size * num_channels * (target_delay-delay) );
snd_pcm_writei( alsa_handle, tmp, target_delay-delay );

output_new_delay = (int) delay;

delay = target_delay;

// Set the resample_rate... we need to adjust the offset integral, to do this.
offset_integral = - (resample_mean - static_resample_factor) * catch_factor * catch_factor2;
// Also clear the array. we are beginning a new control cycle.
for( i=0; i<smooth_size; i++ )
offset_array[i] = 0.0;
}
/* ok... now we should have target_delay +- max_diff on the alsa side.
*
* calculate the number of frames, we want to get.
*/

double offset = delay - target_delay;

// Save offset.
offset_array[(offset_differential_index++)% smooth_size ] = offset;

// Build the mean of the windowed offset array
// basically fir lowpassing.
double smooth_offset = 0.0;
for( i=0; i<smooth_size; i++ )
smooth_offset +=
offset_array[ (i + offset_differential_index-1) % smooth_size] * window_array[i];
smooth_offset /= (double) smooth_size;

// this is the integral of the smoothed_offset
offset_integral += smooth_offset;

// Clamp offset.
// the smooth offset still contains unwanted noise
// which would go straigth onto the resample coeff.
// it only used in the P component and the I component is used for the fine tuning anyways.
if( fabs( smooth_offset ) < pclamp )
smooth_offset = 0.0;

// ok. now this is the PI controller.
// u(t) = K * ( e(t) + 1/T \int e(t') dt' )
// K = 1/catch_factor and T = catch_factor2
double current_resample_factor = static_resample_factor - smooth_offset / (double) catch_factor - offset_integral / (double) catch_factor / (double)catch_factor2;

// now quantize this value around resample_mean, so that the noise which is in the integral component doesnt hurt.
current_resample_factor = floor( (current_resample_factor - resample_mean) * controlquant + 0.5 ) / controlquant + resample_mean;

// Output "instrumentatio" gonna change that to real instrumentation in a few.
output_resampling_factor = (float) current_resample_factor;
output_diff = (float) smooth_offset;
output_integral = (float) offset_integral;
output_offset = (float) offset;

// Clamp a bit.
if( current_resample_factor < 0.25 ) current_resample_factor = 0.25;
if( current_resample_factor > 4 ) current_resample_factor = 4;

// Now Calculate how many samples we need.
rlen = ceil( ((double)nframes) * current_resample_factor )+2;
assert( rlen > 2 );

// Calculate resample_mean so we can init ourselves to saner values.
resample_mean = 0.9999 * resample_mean + 0.0001 * current_resample_factor;
/*
* now this should do it...
*/

outbuf = alloca( rlen * formats[format].sample_size * num_channels );

resampbuf = alloca( rlen * sizeof( float ) );
/*
* render jack ports to the outbuf...
*/

int chn = 0;
JSList *node = playback_ports;
JSList *src_node = playback_srcs;
SRC_DATA src;

while ( node != NULL)
{
jack_port_t *port = (jack_port_t *) node->data;
float *buf = jack_port_get_buffer (port, nframes);

SRC_STATE *src_state = src_node->data;

src.data_in = buf;
src.input_frames = nframes;

src.data_out = resampbuf;
src.output_frames = rlen;
src.end_of_input = 0;

src.src_ratio = current_resample_factor;

src_process( src_state, &src );

formats[format].jack_to_soundcard( outbuf + format[formats].sample_size * chn, resampbuf, src.output_frames_gen, num_channels*format[formats].sample_size, NULL);

src_node = jack_slist_next (src_node);
node = jack_slist_next (node);
chn++;
}

// now write the output...
again:
err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
//err = snd_pcm_writei(alsa_handle, outbuf, src.output_frames_gen);
if( err < 0 ) {
printf( "err = %d\n", err );
if (xrun_recovery(alsa_handle, err) < 0) {
printf("Write error: %s\n", snd_strerror(err));
exit(EXIT_FAILURE);
}
goto again;
}

return 0;
}


/**
* Allocate the necessary jack ports...
*/

void alloc_ports( int n_capture, int n_playback ) {

int port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
int chn;
jack_port_t *port;
char buf[32];

capture_ports = NULL;
for (chn = 0; chn < n_capture; chn++)
{
snprintf (buf, sizeof(buf) - 1, "capture_%u", chn+1);

port = jack_port_register (client, buf,
JACK_DEFAULT_AUDIO_TYPE,
port_flags, 0);

if (!port)
{
printf( "jacknet_client: cannot register port for %s", buf);
break;
}

capture_srcs = jack_slist_append( capture_srcs, src_new( 4-samplerate_quality, 1, NULL ) );
capture_ports = jack_slist_append (capture_ports, port);
}

port_flags = JackPortIsInput;

playback_ports = NULL;
for (chn = 0; chn < n_playback; chn++)
{
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn+1);

port = jack_port_register (client, buf,
JACK_DEFAULT_AUDIO_TYPE,
port_flags, 0);

if (!port)
{
printf( "jacknet_client: cannot register port for %s", buf);
break;
}

playback_srcs = jack_slist_append( playback_srcs, src_new( 4-samplerate_quality, 1, NULL ) );
playback_ports = jack_slist_append (playback_ports, port);
}
}

/**
* This is the shutdown callback for this JACK application.
* It is called by JACK if the server ever shuts down or
* decides to disconnect the client.
*/

void jack_shutdown (void *arg) {

exit (1);
}

/**
* be user friendly.
* be user friendly.
* be user friendly.
*/

void printUsage() {
fprintf(stderr, "usage: alsa_out [options]\n"
"\n"
" -j <jack name> - client name\n"
" -d <alsa_device> \n"
" -c <channels> \n"
" -p <period_size> \n"
" -n <num_period> \n"
" -r <sample_rate> \n"
" -q <sample_rate quality [0..4]\n"
" -m <max_diff> \n"
" -t <target_delay> \n"
" -i turns on instrumentation\n"
" -v turns on printouts\n"
"\n");
}


/**
* the main function....
*/

void
sigterm_handler( int signal )
{
quit = 1;
}


int main (int argc, char *argv[]) {
char jack_name[30] = "alsa_out";
char alsa_device[30] = "hw:0";

extern char *optarg;
extern int optind, optopt;
int errflg=0;
int c;

while ((c = getopt(argc, argv, "ivj:r:c:p:n:d:q:m:t:f:F:C:Q:s:")) != -1) {
switch(c) {
case 'j':
strcpy(jack_name,optarg);
break;
case 'r':
sample_rate = atoi(optarg);
break;
case 'c':
num_channels = atoi(optarg);
break;
case 'p':
period_size = atoi(optarg);
break;
case 'n':
num_periods = atoi(optarg);
break;
case 'd':
strcpy(alsa_device,optarg);
break;
case 't':
target_delay = atoi(optarg);
break;
case 'q':
samplerate_quality = atoi(optarg);
break;
case 'm':
max_diff = atoi(optarg);
break;
case 'f':
catch_factor = atoi(optarg);
break;
case 'F':
catch_factor2 = atoi(optarg);
break;
case 'C':
pclamp = (double) atoi(optarg);
break;
case 'Q':
controlquant = (double) atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'i':
instrument = 1;
break;
case 's':
smooth_size = atoi(optarg);
break;
case ':':
fprintf(stderr,
"Option -%c requires an operand\n", optopt);
errflg++;
break;
case '?':
fprintf(stderr,
"Unrecognized option: -%c\n", optopt);
errflg++;
}
}
if (errflg) {
printUsage();
exit(2);
}

if( (samplerate_quality < 0) || (samplerate_quality > 4) ) {
fprintf (stderr, "invalid samplerate quality\n");
return 1;
}
if ((client = jack_client_open (jack_name, 0, NULL)) == 0) {
fprintf (stderr, "jack server not running?\n");
return 1;
}

/* tell the JACK server to call `process()' whenever
there is work to be done.
*/

jack_set_process_callback (client, process, 0);

/* tell the JACK server to call `jack_shutdown()' if
it ever shuts down, either entirely, or if it
just decides to stop calling us.
*/

jack_on_shutdown (client, jack_shutdown, 0);


// get jack sample_rate
jack_sample_rate = jack_get_sample_rate( client );

if( !sample_rate )
sample_rate = jack_sample_rate;

static_resample_factor = (double) sample_rate / (double) jack_sample_rate;
resample_mean = static_resample_factor;

offset_array = malloc( sizeof(double) * smooth_size );
if( offset_array == NULL ) {
fprintf( stderr, "no memory for offset_array !!!\n" );
exit(20);
}
window_array = malloc( sizeof(double) * smooth_size );
if( window_array == NULL ) {
fprintf( stderr, "no memory for window_array !!!\n" );
exit(20);
}
int i;
for( i=0; i<smooth_size; i++ ) {
offset_array[i] = 0.0;
window_array[i] = hann( (double) i / ((double) smooth_size - 1.0) );
}

jack_buffer_size = jack_get_buffer_size( client );
// Setup target delay and max_diff for the normal user, who does not play with them...
if( !target_delay )
target_delay = (num_periods*period_size / 2) - jack_buffer_size/2;

if( !max_diff )
max_diff = target_delay;

if( max_diff > target_delay ) {
fprintf( stderr, "target_delay (%d) cant be smaller than max_diff(%d)\n", target_delay, max_diff );
exit(20);
}
if( (target_delay+max_diff) > (num_periods*period_size) ) {
fprintf( stderr, "target_delay+max_diff (%d) cant be bigger than buffersize(%d)\n", target_delay+max_diff, num_periods*period_size );
exit(20);
}
// now open the alsa fd...
alsa_handle = open_audiofd( alsa_device, 0, sample_rate, num_channels, period_size, num_periods);
if( alsa_handle == 0 )
exit(20);

printf( "selected sample format: %s\n", formats[format].name );

// alloc input ports, which are blasted out to alsa...
alloc_ports( 0, num_channels );


/* tell the JACK server that we are ready to roll */

if (jack_activate (client)) {
fprintf (stderr, "cannot activate client");
return 1;
}

signal( SIGTERM, sigterm_handler );
signal( SIGINT, sigterm_handler );

if( verbose ) {
while(!quit) {
usleep(500000);
if( output_new_delay ) {
printf( "delay = %d\n", output_new_delay );
output_new_delay = 0;
}
printf( "res: %f, \tdiff = %f, \toffset = %f \n", output_resampling_factor, output_diff, output_offset );
}
} else if( instrument ) {
printf( "# n\tresamp\tdiff\toffseti\tintegral\n");
int n=0;
while(!quit) {
usleep(1000);
printf( "%d\t%f\t%f\t%f\t%f\n", n++, output_resampling_factor, output_diff, output_offset, output_integral );
}
} else {
while(!quit)
{
usleep(500000);
if( output_new_delay ) {
printf( "delay = %d\n", output_new_delay );
output_new_delay = 0;
}
}
}

jack_deactivate( client );
jack_client_close (client);
exit (0);
}


+ 16
- 5
example-clients/bufsize.c View File

@@ -30,6 +30,7 @@
char *package; /* program name */
jack_client_t *client;
jack_nframes_t nframes;
int just_print_bufsize=0;

void jack_shutdown(void *arg)
{
@@ -54,6 +55,10 @@ void parse_arguments(int argc, char *argv[])
else
package++;

if (argc==1) {
just_print_bufsize = 1;
return;
}
if (argc < 2) {
fprintf(stderr, "usage: %s <bufsize>\n", package);
exit(9);
@@ -74,7 +79,7 @@ int main(int argc, char *argv[])
parse_arguments(argc, argv);

/* become a JACK client */
if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) {
if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) {
fprintf(stderr, "JACK server not running?\n");
exit(1);
}
@@ -86,10 +91,16 @@ int main(int argc, char *argv[])

jack_on_shutdown(client, jack_shutdown, 0);

rc = jack_set_buffer_size(client, nframes);
if (rc)
fprintf(stderr, "jack_set_buffer_size(): %s\n", strerror(rc));
if (just_print_bufsize) {
fprintf(stdout, "%d\n", jack_get_buffer_size( client ) );
rc=0;
}
else
{
rc = jack_set_buffer_size(client, nframes);
if (rc)
fprintf(stderr, "jack_set_buffer_size(): %s\n", strerror(rc));
}
jack_client_close(client);

return rc;


+ 1
- 1
example-clients/internal_metro.cpp View File

@@ -57,7 +57,7 @@ InternalMetro::InternalMetro(int freq, double max_amp, int dur_arg, int bpm, cha
client_name = (char *) malloc (9 * sizeof (char));
strcpy (client_name, "metro");
}
if ((client = jack_client_new (client_name)) == 0) {
if ((client = jack_client_open (client_name, JackNullOption, NULL)) == 0) {
fprintf (stderr, "jack server not running?\n");
return ;
}


+ 780
- 0
example-clients/netsource.c View File

@@ -0,0 +1,780 @@
/*
NetJack Client

Copyright (C) 2008 Marc-Olivier Barre <marco@marcochapeau.org>
Copyright (C) 2008 Pieter Palmers <pieterpalmers@users.sourceforge.net>
Copyright (C) 2006 Torben Hohn <torbenh@gmx.de>

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.

*/

/** @file netsource.c
*
* @brief This client connects a remote slave JACK to a local JACK server assumed to be the master
*/


#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#ifdef WIN32
#include <winsock2.h>
#include <malloc.h>
#else
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#endif

/* These two required by FreeBSD. */
#include <sys/types.h>


#include <jack/jack.h>

//#include <net_driver.h>
#include <netjack_packet.h>
#if HAVE_SAMPLERATE
#include <samplerate.h>
#endif

#if HAVE_CELT
#include <celt/celt.h>
#endif

#include <math.h>

JSList *capture_ports = NULL;
JSList *capture_srcs = NULL;
int capture_channels = 0;
int capture_channels_audio = 2;
int capture_channels_midi = 1;
JSList *playback_ports = NULL;
JSList *playback_srcs = NULL;
int playback_channels = 0;
int playback_channels_audio = 2;
int playback_channels_midi = 1;
int dont_htonl_floats = 0;

int latency = 5;
jack_nframes_t factor = 1;
int bitdepth = 0;
int mtu = 1400;
int reply_port = 0;
int bind_port = 0;
int redundancy = 1;
jack_client_t *client;

int state_connected = 0;
int state_latency = 0;
int state_netxruns = 0;
int state_currentframe = 0;
int state_recv_packet_queue_time = 0;

int quit=0;


int outsockfd;
int insockfd;
#ifdef WIN32
struct sockaddr_in destaddr;
struct sockaddr_in bindaddr;
#else
struct sockaddr destaddr;
struct sockaddr bindaddr;
#endif

int sync_state;
jack_transport_state_t last_transport_state;

int framecnt = 0;

int cont_miss = 0;

int freewheeling = 0;

/**
* This Function allocates all the I/O Ports which are added the lists.
*/
void
alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int n_playback_midi)
{

int port_flags = JackPortIsOutput;
int chn;
jack_port_t *port;
char buf[32];

capture_ports = NULL;
/* Allocate audio capture channels */
for (chn = 0; chn < n_capture_audio; chn++)
{
snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1);
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
if (!port)
{
printf( "jack_netsource: cannot register %s port\n", buf);
break;
}
if( bitdepth == 1000 ) {
#if HAVE_CELT
#if HAVE_CELT_API_0_7
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL );
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) );
#else
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL );
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) );
#endif
#endif
} else {
#if HAVE_SAMPLERATE
capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL));
#endif
}
capture_ports = jack_slist_append (capture_ports, port);
}

/* Allocate midi capture channels */
for (chn = n_capture_audio; chn < n_capture_midi + n_capture_audio; chn++)
{
snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1);
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0);
if (!port)
{
printf ("jack_netsource: cannot register %s port\n", buf);
break;
}
capture_ports = jack_slist_append(capture_ports, port);
}

/* Allocate audio playback channels */
port_flags = JackPortIsInput;
playback_ports = NULL;
for (chn = 0; chn < n_playback_audio; chn++)
{
snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1);
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0);
if (!port)
{
printf ("jack_netsource: cannot register %s port\n", buf);
break;
}
if( bitdepth == 1000 ) {
#if HAVE_CELT
#if HAVE_CELT_API_0_7
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL );
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) );
#else
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL );
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) );
#endif
#endif
} else {
#if HAVE_SAMPLERATE
playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL));
#endif
}
playback_ports = jack_slist_append (playback_ports, port);
}

/* Allocate midi playback channels */
for (chn = n_playback_audio; chn < n_playback_midi + n_playback_audio; chn++)
{
snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1);
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0);
if (!port)
{
printf ("jack_netsource: cannot register %s port\n", buf);
break;
}
playback_ports = jack_slist_append (playback_ports, port);
}
}

/**
* The Sync callback... sync state is set elsewhere...
* we will see if this is working correctly.
* i dont really believe in it yet.
*/
int
sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg)
{
static int latency_count = 0;
int retval = sync_state;

if (latency_count) {
latency_count--;
retval = 0;
}

else if (state == JackTransportStarting && last_transport_state != JackTransportStarting)
{
retval = 0;
latency_count = latency - 1;
}

last_transport_state = state;
return retval;
}

void
freewheel_cb (int starting, void *arg)
{
freewheeling = starting;
}

int deadline_goodness=0;
/**
* The process callback for this JACK application.
* It is called by JACK at the appropriate times.
*/
int
process (jack_nframes_t nframes, void *arg)
{
jack_nframes_t net_period;
int rx_bufsize, tx_bufsize;

jack_default_audio_sample_t *buf;
jack_port_t *port;
JSList *node;
int chn;
int size, i;
const char *porttype;
int input_fd;

jack_position_t local_trans_pos;

uint32_t *packet_buf, *packet_bufX;
uint32_t *rx_packet_ptr;
jack_time_t packet_recv_timestamp;

if( bitdepth == 1000 )
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ;
else
net_period = (float) nframes / (float) factor;

rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header);


/* Allocate a buffer where both In and Out Buffer will fit */
packet_buf = alloca ((rx_bufsize > tx_bufsize) ? rx_bufsize : tx_bufsize);

jacknet_packet_header *pkthdr = (jacknet_packet_header *) packet_buf;

/*
* for latency==0 we need to send out the packet before we wait on the reply.
* but this introduces a cycle of latency, when netsource is connected to itself.
* so we send out before read only in zero latency mode.
*
*/

if( latency == 0 ) {
/* reset packet_bufX... */
packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

/* ---------- Send ---------- */
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
packet_bufX, net_period, dont_htonl_floats);

/* fill in packet hdr */
pkthdr->transport_state = jack_transport_query (client, &local_trans_pos);
pkthdr->transport_frame = local_trans_pos.frame;
pkthdr->framecnt = framecnt;
pkthdr->latency = latency;
pkthdr->reply_port = reply_port;
pkthdr->sample_rate = jack_get_sample_rate (client);
pkthdr->period_size = nframes;

/* playback for us is capture on the other side */
pkthdr->capture_channels_audio = playback_channels_audio;
pkthdr->playback_channels_audio = capture_channels_audio;
pkthdr->capture_channels_midi = playback_channels_midi;
pkthdr->playback_channels_midi = capture_channels_midi;
pkthdr->mtu = mtu;
if( freewheeling!= 0 )
pkthdr->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
else
pkthdr->sync_state = (jack_nframes_t)deadline_goodness;
//printf("goodness=%d\n", deadline_goodness );

packet_header_hton (pkthdr);
if (cont_miss < 3*latency+5) {
int r;
for( r=0; r<redundancy; r++ )
netjack_sendto (outsockfd, (char *) packet_buf, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
}
else if (cont_miss > 50+5*latency)
{
state_connected = 0;
packet_cache_reset_master_address( global_packcache );
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
cont_miss = 0;
}
}

/*
* ok... now the RECEIVE code.
*
*/

/* reset packet_bufX... */
packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

if( reply_port )
input_fd = insockfd;
else
input_fd = outsockfd;

// for latency == 0 we can poll.
if( (latency == 0) || (freewheeling!=0) ) {
jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client)/jack_get_sample_rate(client);
// Now loop until we get the right packet.
while(1) {
jack_nframes_t got_frame;
if ( ! netjack_poll_deadline( input_fd, deadline ) )
break;

packet_cache_drain_socket(global_packcache, input_fd);

if (packet_cache_get_next_available_framecnt( global_packcache, framecnt - latency, &got_frame ))
if( got_frame == (framecnt - latency) )
break;
}
} else {
// normally:
// only drain socket.
packet_cache_drain_socket(global_packcache, input_fd);
}

size = packet_cache_retreive_packet_pointer( global_packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp );
/* First alternative : we received what we expected. Render the data
* to the JACK ports so it can be played. */
if (size == rx_bufsize)
{
packet_buf = rx_packet_ptr;
pkthdr = (jacknet_packet_header *) packet_buf;
packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
// calculate how much time there would have been, if this packet was sent at the deadline.

int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp);
packet_header_ntoh (pkthdr);
deadline_goodness = recv_time_offset - (int)pkthdr->latency;
//printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset );

if (cont_miss)
{
//printf("Frame %d \tRecovered from dropouts\n", framecnt);
cont_miss = 0;
}
render_payload_to_jack_ports (bitdepth, packet_bufX, net_period,
capture_ports, capture_srcs, nframes, dont_htonl_floats);

state_currentframe = framecnt;
state_recv_packet_queue_time = recv_time_offset;
state_connected = 1;
sync_state = pkthdr->sync_state;
packet_cache_release_packet( global_packcache, framecnt - latency );
}
/* Second alternative : we've received something that's not
* as big as expected or we missed a packet. We render silence
* to the ouput ports */
else
{
jack_nframes_t latency_estimate;
if( packet_cache_find_latency( global_packcache, framecnt, &latency_estimate ) )
//if( (state_latency == 0) || (latency_estimate < state_latency) )
state_latency = latency_estimate;

// Set the counters up.
state_currentframe = framecnt;
//state_latency = framecnt - pkthdr->framecnt;
state_netxruns += 1;

//printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size);
//printf ("Frame %d \tPacket missed or incomplete\n", framecnt);
cont_miss += 1;
chn = 0;
node = capture_ports;
while (node != NULL)
{
port = (jack_port_t *) node->data;
buf = jack_port_get_buffer (port, nframes);
porttype = jack_port_type (port);
if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0)
for (i = 0; i < nframes; i++)
buf[i] = 0.0;
else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0)
jack_midi_clear_buffer (buf);
node = jack_slist_next (node);
chn++;
}
}
if( latency != 0 ) {
/* reset packet_bufX... */
packet_bufX = packet_buf + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);

/* ---------- Send ---------- */
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
packet_bufX, net_period, dont_htonl_floats);

/* fill in packet hdr */
pkthdr->transport_state = jack_transport_query (client, &local_trans_pos);
pkthdr->transport_frame = local_trans_pos.frame;
pkthdr->framecnt = framecnt;
pkthdr->latency = latency;
pkthdr->reply_port = reply_port;
pkthdr->sample_rate = jack_get_sample_rate (client);
pkthdr->period_size = nframes;

/* playback for us is capture on the other side */
pkthdr->capture_channels_audio = playback_channels_audio;
pkthdr->playback_channels_audio = capture_channels_audio;
pkthdr->capture_channels_midi = playback_channels_midi;
pkthdr->playback_channels_midi = capture_channels_midi;
pkthdr->mtu = mtu;
if( freewheeling!= 0 )
pkthdr->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
else
pkthdr->sync_state = (jack_nframes_t)deadline_goodness;
//printf("goodness=%d\n", deadline_goodness );

packet_header_hton (pkthdr);
if (cont_miss < 3*latency+5) {
int r;
for( r=0; r<redundancy; r++ )
netjack_sendto (outsockfd, (char *) packet_buf, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
}
else if (cont_miss > 50+5*latency)
{
state_connected = 0;
packet_cache_reset_master_address( global_packcache );
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
cont_miss = 0;
}
}

framecnt++;
return 0;
}

/**
* This is the shutdown callback for this JACK application.
* It is called by JACK if the server ever shuts down or
* decides to disconnect the client.
*/

void
jack_shutdown (void *arg)
{
exit (1);
}

void
init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t port)
{
name->sin_family = AF_INET ;
name->sin_port = htons (port);
if (hostname)
{
struct hostent *hostinfo = gethostbyname (hostname);
if (hostinfo == NULL) {
fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname);
fflush( stderr );
}
#ifdef WIN32
name->sin_addr.s_addr = inet_addr( hostname );
#else
name->sin_addr = *(struct in_addr *) hostinfo->h_addr ;
#endif
}
else
name->sin_addr.s_addr = htonl (INADDR_ANY) ;

}

void
printUsage ()
{
fprintf (stderr, "usage: jack_netsource [options]\n"
"\n"
" -h this help text\n"
" -H <slave host> - Host name of the slave JACK\n"
" -o <num channels> - Number of audio playback channels\n"
" -i <num channels> - Number of audio capture channels\n"
" -O <num channels> - Number of midi playback channels\n"
" -I <num channels> - Number of midi capture channels\n"
" -n <periods> - Network latency in JACK periods\n"
" -p <port> - UDP port that the slave is listening on\n"
" -r <reply port> - UDP port that we are listening on\n"
" -B <bind port> - reply port, for use in NAT environments\n"
" -b <bitdepth> - Set transport to use 16bit or 8bit\n"
" -c <kbits> - Use CELT encoding with <kbits> kbits per channel\n"
" -m <mtu> - Assume this mtu for the link\n"
" -R <N> - Redundancy: send out packets N times.\n"
" -e - skip host-to-network endianness conversion\n"
" -N <jack name> - Reports a different name to jack\n"
" -s <server name> - The name of the local jack server\n"
"\n");
}

void
sigterm_handler( int signal )
{
quit = 1;
}

int
main (int argc, char *argv[])
{
/* Some startup related basics */
char *client_name, *server_name = NULL, *peer_ip;
int peer_port = 3000;
jack_options_t options = JackNullOption;
jack_status_t status;
#ifdef WIN32
WSADATA wsa;
int rc = WSAStartup(MAKEWORD(2,0),&wsa);
#endif
/* Torben's famous state variables, aka "the reporting API" ! */
/* heh ? these are only the copies of them ;) */
int statecopy_connected, statecopy_latency, statecopy_netxruns;
jack_nframes_t net_period;
/* Argument parsing stuff */
extern char *optarg;
extern int optind, optopt;
int errflg=0, c;

if (argc < 3)
{
printUsage ();
return 1;
}

client_name = (char *) malloc (sizeof (char) * 10);
peer_ip = (char *) malloc (sizeof (char) * 10);
sprintf(client_name, "netjack");
sprintf(peer_ip, "localhost");

while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:")) != -1)
{
switch (c)
{
case 'h':
printUsage();
exit (0);
break;
case 'H':
free(peer_ip);
peer_ip = (char *) malloc (sizeof (char) * strlen (optarg)+1);
strcpy (peer_ip, optarg);
break;
case 'o':
playback_channels_audio = atoi (optarg);
break;
case 'i':
capture_channels_audio = atoi (optarg);
break;
case 'O':
playback_channels_midi = atoi (optarg);
break;
case 'I':
capture_channels_midi = atoi (optarg);
break;
case 'n':
latency = atoi (optarg);
break;
case 'p':
peer_port = atoi (optarg);
break;
case 'r':
reply_port = atoi (optarg);
break;
case 'B':
bind_port = atoi (optarg);
break;
case 'f':
factor = atoi (optarg);
printf("This feature is deprecated and will be removed in future netjack versions. CELT offers a superiour way to conserve bandwidth");
break;
case 'b':
bitdepth = atoi (optarg);
break;
case 'c':
#if HAVE_CELT
bitdepth = 1000;
factor = atoi (optarg);
#else
printf( "not built with celt supprt\n" );
exit(10);
#endif
break;
case 'm':
mtu = atoi (optarg);
break;
case 'R':
redundancy = atoi (optarg);
break;
case 'e':
dont_htonl_floats = 1;
break;
case 'N':
free(client_name);
client_name = (char *) malloc (sizeof (char) * strlen (optarg)+1);
strcpy (client_name, optarg);
break;
case 's':
server_name = (char *) malloc (sizeof (char) * strlen (optarg)+1);
strcpy (server_name, optarg);
options |= JackServerName;
break;
case ':':
fprintf (stderr, "Option -%c requires an operand\n", optopt);
errflg++;
break;
case '?':
fprintf (stderr, "Unrecognized option: -%c\n", optopt);
errflg++;
}
}
if (errflg)
{
printUsage ();
exit (2);
}

capture_channels = capture_channels_audio + capture_channels_midi;
playback_channels = playback_channels_audio + playback_channels_midi;

outsockfd = socket (AF_INET, SOCK_DGRAM, 0);
insockfd = socket (AF_INET, SOCK_DGRAM, 0);

if( (outsockfd == -1) || (insockfd == -1) ) {
fprintf (stderr, "cant open sockets\n" );
return 1;
}

init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_port);
if(bind_port) {
init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, bind_port);
if( bind (outsockfd, &bindaddr, sizeof (bindaddr)) ) {
fprintf (stderr, "bind failure\n" );
}
}
if(reply_port)
{
init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port);
if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) {
fprintf (stderr, "bind failure\n" );
}
}

/* try to become a client of the JACK server */
client = jack_client_open (client_name, options, &status, server_name);
if (client == NULL)
{
fprintf (stderr, "jack_client_open() failed, status = 0x%2.0x\n"
"Is the JACK server running ?\n", status);
return 1;
}

/* Set up jack callbacks */
jack_set_process_callback (client, process, 0);
jack_set_sync_callback (client, sync_cb, 0);
jack_set_freewheel_callback (client, freewheel_cb, 0);
jack_on_shutdown (client, jack_shutdown, 0);

alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi);

if( bitdepth == 1000 )
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ;
else
net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor);

int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
global_packcache = packet_cache_new (latency + 50, rx_bufsize, mtu);

/* tell the JACK server that we are ready to roll */
if (jack_activate (client))
{
fprintf (stderr, "Cannot activate client");
return 1;
}

/* Now sleep forever... and evaluate the state_ vars */

signal( SIGTERM, sigterm_handler );
signal( SIGINT, sigterm_handler );

statecopy_connected = 2; // make it report unconnected on start.
statecopy_latency = state_latency;
statecopy_netxruns = state_netxruns;

while ( !quit )
{
#ifdef WIN32
Sleep (1000);
#else
sleep(1);
#endif
if (statecopy_connected != state_connected)
{
statecopy_connected = state_connected;
if (statecopy_connected)
{
state_netxruns = 1; // We want to reset the netxrun count on each new connection
printf ("Connected :-)\n");
}
else
printf ("Not Connected\n");

fflush(stdout);
}

if (statecopy_connected)
{
if (statecopy_netxruns != state_netxruns) {
statecopy_netxruns = state_netxruns;
printf ("%s: at frame %06d -> total netxruns %d (%d%%) queue time= %d\n",
client_name,
state_currentframe,
statecopy_netxruns,
100*statecopy_netxruns/state_currentframe,
state_recv_packet_queue_time);

fflush(stdout);
}
}
else
{
if (statecopy_latency != state_latency)
{
statecopy_latency = state_latency;
if (statecopy_latency > 1)
printf ("current latency %d\n", statecopy_latency);
fflush(stdout);
}
}
}

jack_client_close (client);
packet_cache_free (global_packcache);
exit (0);
}

+ 85
- 0
example-clients/samplerate.c View File

@@ -0,0 +1,85 @@
/*
* smaplerate.c -- get current samplerate
*
* Copyright (C) 2003 Jack O'Quin.
*
* 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.
*/

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <jack/jack.h>
#include <jack/transport.h>

char *package; /* program name */
jack_client_t *client;

void jack_shutdown(void *arg)
{
fprintf(stderr, "JACK shut down, exiting ...\n");
exit(1);
}

void signal_handler(int sig)
{
jack_client_close(client);
fprintf(stderr, "signal received, exiting ...\n");
exit(0);
}

void parse_arguments(int argc, char *argv[])
{

/* basename $0 */
package = strrchr(argv[0], '/');
if (package == 0)
package = argv[0];
else
package++;

if (argc==1) {
return;
}
fprintf(stderr, "usage: %s [bufsize]\n", package);
exit(9);
}

int main(int argc, char *argv[])
{
parse_arguments(argc, argv);

/* become a JACK client */
if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) {
fprintf(stderr, "JACK server not running?\n");
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);

fprintf(stdout, "%d\n", jack_get_sample_rate( client ) );

jack_client_close(client);

return 0;
}

+ 136
- 0
example-clients/wait.c View File

@@ -0,0 +1,136 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>

#include <time.h>

#include <jack/jack.h>

char * my_name;

void
show_usage (void)
{
fprintf (stderr, "\nUsage: %s [options]\n", my_name);
fprintf (stderr, "Check for jack existence, or wait, until it either quits, or gets started\n");
fprintf (stderr, "options:\n");
fprintf (stderr, " -s, --server <name> Connect to the jack server named <name>\n");
fprintf (stderr, " -w, --wait Wait for server to become available\n");
fprintf (stderr, " -q, --quit Wait until server is quit\n");
fprintf (stderr, " -c, --check Check wether server is running\n");
fprintf (stderr, " -t, --timeout Wait timeout in seconds\n");
fprintf (stderr, " -h, --help Display this help message\n");
fprintf (stderr, "For more information see http://jackaudio.org/\n");
}

int
main (int argc, char *argv[])
{
jack_client_t *client;
jack_status_t status;
jack_options_t options = JackNoStartServer;
int c;
int option_index;
char *server_name = NULL;
int wait_for_start = 0;
int wait_for_quit = 0;
int just_check = 0;
int wait_timeout = 0;
time_t start_timestamp;

struct option long_options[] = {
{ "server", 1, 0, 's' },
{ "wait", 0, 0, 'w' },
{ "quit", 0, 0, 'q' },
{ "check", 0, 0, 'c' },
{ "timeout", 1, 0, 't' },
{ "help", 0, 0, 'h' },
{ 0, 0, 0, 0 }
};

my_name = strrchr(argv[0], '/');
if (my_name == 0) {
my_name = argv[0];
} else {
my_name ++;
}

while ((c = getopt_long (argc, argv, "s:wqct:hv", long_options, &option_index)) >= 0) {
switch (c) {
case 's':
server_name = (char *) malloc (sizeof (char) * strlen(optarg));
strcpy (server_name, optarg);
options |= JackServerName;
break;
case 'w':
wait_for_start = 1;
break;
case 'q':
wait_for_quit = 1;
break;
case 'c':
just_check = 1;
break;
case 't':
wait_timeout = atoi(optarg);
break;
case 'h':
show_usage ();
return 1;
break;
default:
show_usage ();
return 1;
break;
}
}

/* try to open server in a loop. breaking under certein conditions */

start_timestamp = time( NULL );

while(1) {
client = jack_client_open ("wait", options, &status, server_name);
/* check for some real error and bail out */
if( (client == NULL) && !(status & JackServerFailed) ) {
fprintf (stderr, "jack_client_open() failed, "
"status = 0x%2.0x\n", status);
return 1;
}

if( client == NULL ) {
if( wait_for_quit ) {
fprintf( stdout, "server is gone\n" );
break;
}
if( just_check ) {
fprintf( stdout, "not running\n" );
break;
}
} else {
jack_client_close( client );
if( wait_for_start ) {
fprintf( stdout, "server is available\n" );
break;
}
if( just_check ) {
fprintf( stdout, "running\n" );
break;
}
}
if( wait_timeout ) {
if( (time( NULL ) - start_timestamp) > wait_timeout ) {
fprintf( stdout, "timeout\n" );
break;
}
}

// Wait a second, and repeat
sleep(1);
}

exit (0);
}

+ 45
- 3
example-clients/wscript View File

@@ -16,6 +16,8 @@ example_programs = {
'jack_showtime' : 'showtime.c',
'jack_alias' : 'alias.c',
'jack_bufsize' : 'bufsize.c',
'jack_wait' : 'wait.c',
'jack_samplerate' : 'samplerate.c',
'jack_evmon' : 'evmon.c',
'jack_monitor_client' : 'monitor_client.c',
'jack_thru' : 'thru_client.c',
@@ -30,9 +32,16 @@ example_libs = {
def configure(conf):
e = conf.check_cc(header_name='sndfile.h', define_name="HAVE_SNDFILE")
conf.check_cc(header_name='samplerate.h', define_name="HAVE_SAMPLERATE")
if conf.is_defined('HAVE_SAMPLERATE'):
conf.env['LIB_SAMPLERATE'] = ['samplerate']

if conf.is_defined('HAVE_SNDFILE'):
conf.env['LIB_SNDFILE'] = ['sndfile']

conf.check_cfg(package='celt', atleast_version='0.5.0', args='--cflags --libs')

e = conf.check_cc(header_name='ncurses.h', define_name="HAVE_NCURSES")

if conf.is_defined('HAVE_NCURSES'):
@@ -47,6 +56,8 @@ def configure(conf):

conf.env['BUILD_EXAMPLE_CLIENT_REC'] = conf.is_defined('HAVE_SNDFILE')

conf.env['BUILD_EXAMPLE_ALSA_IO'] = conf.is_defined('HAVE_SAMPLERATE')

def build(bld):
if bld.env['IS_LINUX']:
os_incdir = ['../linux', '../posix']
@@ -73,8 +84,7 @@ def build(bld):
prog.uselib_local = 'clientlib'
prog.target = example_program
#if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT']
if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT'] == True:
if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT']:
prog = bld.new_task_gen('cc', 'program')
prog.includes = os_incdir + ['../common/jack', '../common']
prog.source = 'transport.c'
@@ -89,7 +99,7 @@ def build(bld):
prog.uselib_local = 'clientlib'
prog.target = 'jack_transport'

if bld.env['BUILD_EXAMPLE_CLIENT_REC'] == True:
if bld.env['BUILD_EXAMPLE_CLIENT_REC']:
prog = bld.new_task_gen('cc', 'program')
prog.includes = os_incdir + ['../common/jack', '../common']
prog.source = 'capture_client.c'
@@ -105,6 +115,38 @@ def build(bld):
prog.uselib_local = 'clientlib'
prog.target = 'jack_rec'

if bld.env['IS_LINUX'] or bld.env['IS_MACOSX']:
prog = bld.new_task_gen('cc', 'program')
prog.includes = os_incdir + ['../common/jack', '../common']
prog.source = ['netsource.c', '../common/netjack_packet.c']
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR")
# Seems uneeded here...
#if bld.env['HAVE_CELT']:
#if bld.env['HAVE_CELT_API_0_5']:
# prog.defines = ['HAVE_CELT', 'HAVE_CELT_API_0_5']
#elif bld.env['HAVE_CELT_API_0_7']:
# prog.defines = ['HAVE_CELT', 'HAVE_CELT_API_0_7']
prog.uselib = 'CELT SAMPLERATE'
prog.uselib_local = 'clientlib'
prog.target = 'jack_netsource'

if bld.env['IS_LINUX'] and bld.env['BUILD_EXAMPLE_ALSA_IO']:
prog = bld.new_task_gen('cc', 'program')
prog.includes = os_incdir + ['../common/jack', '../common']
prog.source = ['alsa_in.c', '../common/memops.c']
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR")
prog.uselib = 'ALSA SAMPLERATE'
prog.uselib_local = 'clientlib'
prog.target = 'alsa_in'

prog = bld.new_task_gen('cc', 'program')
prog.includes = os_incdir + ['../common/jack', '../common']
prog.source = ['alsa_out.c', '../common/memops.c']
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR")
prog.uselib = 'ALSA SAMPLERATE'
prog.uselib_local = 'clientlib'
prog.target = 'alsa_out'

for example_lib, example_lib_source in example_libs.items():
lib = bld.new_task_gen('cc', 'shlib')
lib.env['shlib_PATTERN'] = '%s.so'


+ 1
- 2
example-clients/zombie.c View File

@@ -52,9 +52,8 @@ int
main (int argc, char *argv[])
{
jack_client_t* client = NULL;
/* try to become a client of the JACK server */
if ((client = jack_client_new ("zombie")) == 0) {
if ((client = jack_client_open ("zombie", JackNullOption, NULL)) == 0) {
fprintf (stderr, "jack server not running?\n");
goto error;
}


+ 9
- 1
linux/wscript View File

@@ -11,11 +11,14 @@ def configure(conf):
conf. check_cfg(package='libffado', atleast_version='1.999.17', args='--cflags --libs')
conf.env['BUILD_DRIVER_FFADO'] = conf.is_defined('HAVE_LIBFFADO')

conf.define('HAVE_PPOLL', 1 )


def create_jack_driver_obj(bld, target, sources, uselib = None):
driver = bld.new_task_gen('cxx', 'shlib')
driver.features.append('cc')
driver.env['shlib_PATTERN'] = 'jack_%s.so'
driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE']
driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL']
driver.includes = ['.', '../linux', '../posix', '../common', '../common/jack', '../dbus']
driver.target = target
driver.source = sources
@@ -64,3 +67,8 @@ def build(bld):
create_jack_driver_obj(bld, 'net', '../common/JackNetDriver.cpp')

create_jack_driver_obj(bld, 'loopback', '../common/JackLoopbackDriver.cpp')

create_jack_driver_obj(bld, 'netone', [ '../common/JackNetOneDriver.cpp',
'../common/netjack.c',
'../common/netjack_packet.c' ], "SAMPLERATE CELT" )


+ 5
- 5
macosx/JackMacEngineRPC.cpp View File

@@ -59,12 +59,12 @@ rpc_type server_rpc_jack_client_close(mach_port_t private_port, int refnum, int*
return KERN_SUCCESS;
}

rpc_type server_rpc_jack_client_activate(mach_port_t private_port, int refnum, int state, int* result)
rpc_type server_rpc_jack_client_activate(mach_port_t private_port, int refnum, int is_real_time, int* result)
{
jack_log("rpc_jack_client_activate");
JackMachServerChannel* channel = JackMachServerChannel::fPortTable[private_port];
assert(channel);
*result = channel->GetEngine()->ClientActivate(refnum, state);
*result = channel->GetEngine()->ClientActivate(refnum, is_real_time);
return KERN_SUCCESS;
}

@@ -83,7 +83,7 @@ rpc_type server_rpc_jack_client_deactivate(mach_port_t private_port, int refnum,

rpc_type server_rpc_jack_port_register(mach_port_t private_port, int refnum, client_port_name_t name, client_port_type_t type, unsigned int flags, unsigned int buffer_size, unsigned int* port_index, int* result)
{
jack_log("rpc_jack_port_register ref = %ld name = %s", refnum, name);
jack_log("rpc_jack_port_register ref = %d name = %s", refnum, name);
JackMachServerChannel* channel = JackMachServerChannel::fPortTable[private_port];
assert(channel);
*result = channel->GetEngine()->PortRegister(refnum, name, type, flags, buffer_size, port_index);
@@ -92,7 +92,7 @@ rpc_type server_rpc_jack_port_register(mach_port_t private_port, int refnum, cli

rpc_type server_rpc_jack_port_unregister(mach_port_t private_port, int refnum, int port, int* result)
{
jack_log("rpc_jack_port_unregister ref = %ld port = %ld ", refnum, port);
jack_log("rpc_jack_port_unregister ref = %d port = %d ", refnum, port);
JackMachServerChannel* channel = JackMachServerChannel::fPortTable[private_port];
assert(channel);
*result = channel->GetEngine()->PortUnRegister(refnum, port);
@@ -234,7 +234,7 @@ rpc_type server_rpc_jack_internal_clientunload(mach_port_t private_port, int ref

rpc_type server_rpc_jack_client_rt_notify(mach_port_t server_port, int refnum, int notify, int value)
{
jack_log("rpc_jack_client_rt_notify ref = %ld notify = %ld value = %ld", refnum, notify, value);
jack_log("rpc_jack_client_rt_notify ref = %d notify = %d value = %d", refnum, notify, value);
JackMachServerChannel* channel = JackMachServerChannel::fPortTable[server_port];
assert(channel);
assert(channel->GetServer());


+ 6
- 6
macosx/JackMacLibClientRPC.cpp View File

@@ -27,21 +27,21 @@ using namespace Jack;

#define rpc_type kern_return_t // for astyle

rpc_type rpc_jack_client_sync_notify(mach_port_t client_port, int refnum, client_name_t name, int notify, int value1, int value2, int* result)
rpc_type rpc_jack_client_sync_notify(mach_port_t client_port, int refnum, client_name_t name, int notify, message_t message, int value1, int value2, int* result)
{
jack_log("rpc_jack_client_sync_notify ref = %ld name = %s notify = %ld val1 = %ld val2 = %ld", refnum, name, notify, value1, value2);
jack_log("rpc_jack_client_sync_notify ref = %ld name = %s notify = %ld message %s val1 = %ld val2 = %ld", refnum, name, notify, message, value1, value2);
JackClient* client = gClientTable[client_port];
assert(client);
*result = client->ClientNotify(refnum, name, notify, true, value1, value2);
*result = client->ClientNotify(refnum, name, notify, true, message, value1, value2);
return KERN_SUCCESS;
}

rpc_type rpc_jack_client_async_notify(mach_port_t client_port, int refnum, client_name_t name, int notify, int value1, int value2)
rpc_type rpc_jack_client_async_notify(mach_port_t client_port, int refnum, client_name_t name, int notify, message_t message, int value1, int value2)
{
jack_log("rpc_jack_client_async_notify ref = %ld name = %s notify = %ld val1 = %ld val2 = %ld", refnum, name, notify, value1, value2);
jack_log("rpc_jack_client_async_notify ref = %ld name = %s notify = %ld message %s val1 = %ld val2 = %ld", refnum, name, notify, message, value1, value2);
JackClient* client = gClientTable[client_port];
assert(client);
client->ClientNotify(refnum, name, notify, false, value1, value2);
client->ClientNotify(refnum, name, notify, false, message, value1, value2);
return KERN_SUCCESS;
}


+ 2
- 2
macosx/JackMachClientChannel.cpp View File

@@ -154,9 +154,9 @@ void JackMachClientChannel::ClientClose(int refnum, int* result)
}
}

void JackMachClientChannel::ClientActivate(int refnum, int state, int* result)
void JackMachClientChannel::ClientActivate(int refnum, int is_real_time, int* result)
{
kern_return_t res = rpc_jack_client_activate(fPrivatePort, refnum, state, result);
kern_return_t res = rpc_jack_client_activate(fPrivatePort, refnum, is_real_time, result);
if (res != KERN_SUCCESS) {
*result = -1;
jack_error("JackMachClientChannel::ClientActivate err = %s", mach_error_string(res));


+ 1
- 1
macosx/JackMachClientChannel.h View File

@@ -61,7 +61,7 @@ class JackMachClientChannel : public detail::JackClientChannelInterface, public
{}
void ClientClose(int refnum, int* result);

void ClientActivate(int refnum, int state, int* result);
void ClientActivate(int refnum, int is_real_time, int* result);
void ClientDeactivate(int refnum, int* result);

void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index, int* result);


+ 3
- 3
macosx/JackMachNotifyChannel.cpp View File

@@ -49,11 +49,11 @@ void JackMachNotifyChannel::Close()
fClientPort.DisconnectPort();
}

void JackMachNotifyChannel::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2, int* result)
void JackMachNotifyChannel::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2, int* result)
{
kern_return_t res = (sync)
? rpc_jack_client_sync_notify(fClientPort.GetPort(), refnum, (char*)name, notify, value1, value2, result)
: rpc_jack_client_async_notify(fClientPort.GetPort(), refnum, (char*)name, notify, value1, value2);
? rpc_jack_client_sync_notify(fClientPort.GetPort(), refnum, (char*)name, notify, (char*)message, value1, value2, result)
: rpc_jack_client_async_notify(fClientPort.GetPort(), refnum, (char*)name, notify, (char*)message, value1, value2);
if (res == KERN_SUCCESS) {
*result = 0;
} else {


+ 1
- 1
macosx/JackMachNotifyChannel.h View File

@@ -44,7 +44,7 @@ class JackMachNotifyChannel
int Open(const char* name); // Open the Server/Client connection
void Close(); // Close the Server/Client connection

void ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2, int* result);
void ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2, int* result);
};

} // end of namespace


+ 11
- 5
macosx/JackMachServerChannel.cpp View File

@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "JackServer.h"
#include "JackLockedEngine.h"
#include "JackNotification.h"
#include "JackServerGlobals.h"

using namespace std;

@@ -49,11 +50,6 @@ int JackMachServerChannel::Open(const char* server_name, JackServer* server)
return -1;
}

if (fThread.Start() != 0) {
jack_error("Cannot start Jack server listener");
return -1;
}

fServer = server;
fPortTable[fServerPort.GetPort()] = this;
return 0;
@@ -65,6 +61,16 @@ void JackMachServerChannel::Close()
fThread.Kill();
fServerPort.DestroyPort();
}
int JackMachServerChannel::Start()
{
if (fThread.Start() != 0) {
jack_error("Cannot start Jack server listener");
return -1;
}
return 0;
}

JackLockedEngine* JackMachServerChannel::GetEngine()
{


+ 4
- 1
macosx/JackMachServerChannel.h View File

@@ -53,7 +53,9 @@ class JackMachServerChannel : public JackRunnableInterface

int Open(const char* server_name, JackServer* server); // Open the Server/Client connection
void Close(); // Close the Server/Client connection

int Start();
JackLockedEngine* GetEngine();
JackServer* GetServer();

@@ -64,6 +66,7 @@ class JackMachServerChannel : public JackRunnableInterface

bool Execute();

// Has to be public..
static std::map<mach_port_t, JackMachServerChannel*> fPortTable;
};



+ 1
- 1
macosx/JackMachServerNotifyChannel.cpp View File

@@ -50,7 +50,7 @@ void JackMachServerNotifyChannel::Notify(int refnum, int notify, int value)
{
kern_return_t res = rpc_jack_client_rt_notify(fClientPort.GetPort(), refnum, notify, value, 0);
if (res != KERN_SUCCESS) {
jack_error("Could not write request ref = %ld notify = %ld err = %s", refnum, notify, mach_error_string(res));
jack_error("Could not write request ref = %d notify = %d err = %s", refnum, notify, mach_error_string(res));
}
}



+ 26
- 10
macosx/JackMachThread.cpp View File

@@ -118,13 +118,13 @@ UInt32 JackMachThread::GetThreadPriority(pthread_t thread, int inWhichPriority)
return 0;
}

int JackMachThread::GetParams(UInt64* period, UInt64* computation, UInt64* constraint)
int JackMachThread::GetParams(pthread_t thread, UInt64* period, UInt64* computation, UInt64* constraint)
{
thread_time_constraint_policy_data_t theTCPolicy;
mach_msg_type_number_t count = THREAD_TIME_CONSTRAINT_POLICY_COUNT;
boolean_t get_default = false;

kern_return_t res = thread_policy_get(pthread_mach_thread_np(pthread_self()),
kern_return_t res = thread_policy_get(pthread_mach_thread_np(thread),
THREAD_TIME_CONSTRAINT_POLICY,
(thread_policy_t) & theTCPolicy,
&count,
@@ -145,9 +145,11 @@ int JackMachThread::Kill()
// pthread_cancel still not yet implemented in Darwin (TO CHECK ON TIGER)
jack_log("JackMachThread::Kill");
if (fThread) { // If thread has been started
if (fThread != (pthread_t)NULL) { // If thread has been started
mach_port_t machThread = pthread_mach_thread_np(fThread);
return (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1;
int res = (thread_terminate(machThread) == KERN_SUCCESS) ? 0 : -1;
fThread = (pthread_t)NULL;
return res;
} else {
return -1;
}
@@ -157,7 +159,14 @@ int JackMachThread::AcquireRealTime()
{
jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
return (fThread) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1;
return (fThread != (pthread_t)NULL) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1;
}

int JackMachThread::AcquireSelfRealTime()
{
jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint);
}

int JackMachThread::AcquireRealTime(int priority)
@@ -166,19 +175,26 @@ int JackMachThread::AcquireRealTime(int priority)
return AcquireRealTime();
}

int JackMachThread::AcquireSelfRealTime(int priority)
{
fPriority = priority;
return AcquireSelfRealTime();
}

int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint)
{
SetThreadToPriority(thread, 96, true, period, computation, constraint);
UInt64 int_period;
UInt64 int_computation;
UInt64 int_constraint;
GetParams(&int_period, &int_computation, &int_constraint);
return 0;
}

int JackMachThread::DropRealTime()
{
return (fThread) ? DropRealTimeImp(fThread) : -1;
return (fThread != (pthread_t)NULL) ? DropRealTimeImp(fThread) : -1;
}

int JackMachThread::DropSelfRealTime()
{
return DropRealTimeImp(pthread_self());
}

int JackMachThread::DropRealTimeImp(pthread_t thread)


+ 10
- 4
macosx/JackMachThread.h View File

@@ -103,11 +103,17 @@ class SERVER_EXPORT JackMachThread : public JackPosixThread

int Kill();

int AcquireRealTime();
int AcquireRealTime(int priority);
int DropRealTime();
int AcquireRealTime(); // Used when called from another thread
int AcquireSelfRealTime(); // Used when called from thread itself
int AcquireRealTime(int priority); // Used when called from another thread
int AcquireSelfRealTime(int priority); // Used when called from thread itself
int DropRealTime(); // Used when called from another thread
int DropSelfRealTime(); // Used when called from thread itself
void SetParams(UInt64 period, UInt64 computation, UInt64 constraint);
static int GetParams(UInt64* period, UInt64* computation, UInt64* constraint);
static int GetParams(pthread_t thread, UInt64* period, UInt64* computation, UInt64* constraint);
static int SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint);

static int AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint);


+ 1527
- 492
macosx/Jackdmp.xcodeproj/project.pbxproj
File diff suppressed because it is too large
View File


+ 4
- 2
macosx/RPC/JackRPCClient.defs View File

@@ -24,14 +24,15 @@ subsystem JackRPCClient 1000;
import "Jackdefs.h";
waittime 5000;

type client_name_t = c_string[128];
type client_port_name_t = c_string[128];
type client_name_t = c_string[64];
type message_t = c_string[256];

routine rpc_jack_client_sync_notify(
client_port : mach_port_t;
refnum : int;
client_name : client_name_t;
notify : int;
message : message_t;
value1 : int;
value2 : int;
out result : int);
@@ -41,5 +42,6 @@ simpleroutine rpc_jack_client_async_notify(
refnum : int;
client_name : client_name_t;
notify : int;
message : message_t;
value1 : int;
value2 : int);

+ 5
- 1
macosx/RPC/JackRPCClient.h View File

@@ -21,7 +21,7 @@ typedef struct {
char *name;
function_ptr_t function;
} function_table_entry;
typedef function_table_entry *function_table_t;
typedef function_table_entry *function_table_t;
#endif /* FUNCTION_PTR_T */
#endif /* AUTOTEST */

@@ -55,6 +55,7 @@ kern_return_t rpc_jack_client_sync_notify
int refnum,
client_name_t client_name,
int notify,
message_t message,
int value1,
int value2,
int *result
@@ -72,6 +73,7 @@ kern_return_t rpc_jack_client_async_notify
int refnum,
client_name_t client_name,
int notify,
message_t message,
int value1,
int value2
);
@@ -103,6 +105,7 @@ __END_DECLS
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
} __Request__rpc_jack_client_sync_notify_t;
@@ -119,6 +122,7 @@ __END_DECLS
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
} __Request__rpc_jack_client_async_notify_t;


+ 196
- 18
macosx/RPC/JackRPCClientServer.c View File

@@ -1,7 +1,7 @@
/*
* IDENTIFICATION:
* stub generated Mon Sep 1 17:42:27 2008
* with a MiG generated Tue Feb 19 02:01:43 PST 2008 by root@b75.local
* stub generated Fri Oct 23 10:35:08 2009
* with a MiG generated Mon May 18 09:59:33 PDT 2009 by root@sulitlana.apple.com
* OPTIONS:
*/

@@ -113,6 +113,7 @@
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
} __Request__rpc_jack_client_sync_notify_t;
@@ -129,6 +130,7 @@
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
} __Request__rpc_jack_client_async_notify_t;
@@ -224,11 +226,11 @@ mig_internal novalue _Xrpc_jack_client_async_notify
#elif defined(__NDR_convert__int_rep__JackRPCClient__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__client_name(a, f) \
__NDR_convert__int_rep__JackRPCClient__string(a, f, 128)
__NDR_convert__int_rep__JackRPCClient__string(a, f, 64)
#elif defined(__NDR_convert__int_rep__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__client_name(a, f) \
__NDR_convert__int_rep__string(a, f, 128)
__NDR_convert__int_rep__string(a, f, 64)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined */

@@ -252,6 +254,26 @@ mig_internal novalue _Xrpc_jack_client_async_notify
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__notify__defined */

#ifndef __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#if defined(__NDR_convert__int_rep__JackRPCClient__message_t__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__int_rep__JackRPCClient__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__int_rep__message_t__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__int_rep__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__int_rep__JackRPCClient__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__int_rep__JackRPCClient__string(a, f, 256)
#elif defined(__NDR_convert__int_rep__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__int_rep__string(a, f, 256)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined */

#ifndef __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value1__defined
#if defined(__NDR_convert__int_rep__JackRPCClient__int__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value1__defined
@@ -324,11 +346,11 @@ mig_internal novalue _Xrpc_jack_client_async_notify
#elif defined(__NDR_convert__char_rep__JackRPCClient__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__client_name(a, f) \
__NDR_convert__char_rep__JackRPCClient__string(a, f, 128)
__NDR_convert__char_rep__JackRPCClient__string(a, f, 64)
#elif defined(__NDR_convert__char_rep__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__client_name(a, f) \
__NDR_convert__char_rep__string(a, f, 128)
__NDR_convert__char_rep__string(a, f, 64)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined */

@@ -352,6 +374,26 @@ mig_internal novalue _Xrpc_jack_client_async_notify
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__notify__defined */

#ifndef __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#if defined(__NDR_convert__char_rep__JackRPCClient__message_t__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__char_rep__JackRPCClient__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__char_rep__message_t__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__char_rep__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__char_rep__JackRPCClient__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__char_rep__JackRPCClient__string(a, f, 256)
#elif defined(__NDR_convert__char_rep__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__char_rep__string(a, f, 256)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined */

#ifndef __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value1__defined
#if defined(__NDR_convert__char_rep__JackRPCClient__int__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value1__defined
@@ -424,11 +466,11 @@ mig_internal novalue _Xrpc_jack_client_async_notify
#elif defined(__NDR_convert__float_rep__JackRPCClient__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__client_name(a, f) \
__NDR_convert__float_rep__JackRPCClient__string(a, f, 128)
__NDR_convert__float_rep__JackRPCClient__string(a, f, 64)
#elif defined(__NDR_convert__float_rep__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__client_name(a, f) \
__NDR_convert__float_rep__string(a, f, 128)
__NDR_convert__float_rep__string(a, f, 64)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined */

@@ -452,6 +494,26 @@ mig_internal novalue _Xrpc_jack_client_async_notify
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__notify__defined */

#ifndef __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#if defined(__NDR_convert__float_rep__JackRPCClient__message_t__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__float_rep__JackRPCClient__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__float_rep__message_t__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__float_rep__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__float_rep__JackRPCClient__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__float_rep__JackRPCClient__string(a, f, 256)
#elif defined(__NDR_convert__float_rep__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message(a, f) \
__NDR_convert__float_rep__string(a, f, 256)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined */

#ifndef __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value1__defined
#if defined(__NDR_convert__float_rep__JackRPCClient__int__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value1__defined
@@ -503,9 +565,24 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_sync_notify_t(_
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */

#if __MigTypeCheck
{
char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;
size_t memchr_limit;

memchr_limit = min((msg_limit - In0P->client_name), 64);
if (( memchr(In0P->client_name, '\0', memchr_limit) == NULL ))
return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!
memchr_limit = min((msg_limit - In0P->message), 256);
if (( memchr(In0P->message, '\0', memchr_limit) == NULL ))
return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!
}
#endif /* __MigTypeCheck */

#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__refnum__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__notify__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value1__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value2__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep) {
@@ -518,6 +595,9 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_sync_notify_t(_
#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__notify__defined)
__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__notify(&In0P->notify, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__notify__defined */
#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined)
__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message(&In0P->message, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__message__defined */
#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value1__defined)
__NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value1(&In0P->value1, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_sync_notify_t__value1__defined */
@@ -530,6 +610,7 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_sync_notify_t(_
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__refnum__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__notify__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value1__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value2__defined)
if (In0P->NDR.char_rep != NDR_record.char_rep) {
@@ -542,6 +623,9 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_sync_notify_t(_
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__notify__defined)
__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__notify(&In0P->notify, In0P->NDR.char_rep);
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__notify__defined */
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined)
__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message(&In0P->message, In0P->NDR.char_rep);
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__message__defined */
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value1__defined)
__NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value1(&In0P->value1, In0P->NDR.char_rep);
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_sync_notify_t__value1__defined */
@@ -554,6 +638,7 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_sync_notify_t(_
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__refnum__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__client_name__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__notify__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value1__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value2__defined)
if (In0P->NDR.float_rep != NDR_record.float_rep) {
@@ -566,6 +651,9 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_sync_notify_t(_
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__notify__defined)
__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__notify(&In0P->notify, In0P->NDR.float_rep);
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__notify__defined */
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined)
__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message(&In0P->message, In0P->NDR.float_rep);
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__message__defined */
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value1__defined)
__NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value1(&In0P->value1, In0P->NDR.float_rep);
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_sync_notify_t__value1__defined */
@@ -594,6 +682,7 @@ kern_return_t rpc_jack_client_sync_notify
int refnum,
client_name_t client_name,
int notify,
message_t message,
int value1,
int value2,
int *result
@@ -613,6 +702,7 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
mach_msg_trailer_t trailer;
@@ -646,7 +736,7 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__rpc_jack_client_sync_notify_t__defined) */

OutP->RetCode = rpc_jack_client_sync_notify(In0P->Head.msgh_request_port, In0P->refnum, In0P->client_name, In0P->notify, In0P->value1, In0P->value2, &OutP->result);
OutP->RetCode = rpc_jack_client_sync_notify(In0P->Head.msgh_request_port, In0P->refnum, In0P->client_name, In0P->notify, In0P->message, In0P->value1, In0P->value2, &OutP->result);
if (OutP->RetCode != KERN_SUCCESS) {
MIG_RETURN_ERROR(OutP, OutP->RetCode);
}
@@ -694,11 +784,11 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
#elif defined(__NDR_convert__int_rep__JackRPCClient__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__client_name__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__client_name(a, f) \
__NDR_convert__int_rep__JackRPCClient__string(a, f, 128)
__NDR_convert__int_rep__JackRPCClient__string(a, f, 64)
#elif defined(__NDR_convert__int_rep__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__client_name__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__client_name(a, f) \
__NDR_convert__int_rep__string(a, f, 128)
__NDR_convert__int_rep__string(a, f, 64)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__client_name__defined */

@@ -722,6 +812,26 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__notify__defined */

#ifndef __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined
#if defined(__NDR_convert__int_rep__JackRPCClient__message_t__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__int_rep__JackRPCClient__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__int_rep__message_t__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__int_rep__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__int_rep__JackRPCClient__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__int_rep__JackRPCClient__string(a, f, 256)
#elif defined(__NDR_convert__int_rep__string__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__int_rep__string(a, f, 256)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined */

#ifndef __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value1__defined
#if defined(__NDR_convert__int_rep__JackRPCClient__int__defined)
#define __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value1__defined
@@ -794,11 +904,11 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
#elif defined(__NDR_convert__char_rep__JackRPCClient__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__client_name__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__client_name(a, f) \
__NDR_convert__char_rep__JackRPCClient__string(a, f, 128)
__NDR_convert__char_rep__JackRPCClient__string(a, f, 64)
#elif defined(__NDR_convert__char_rep__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__client_name__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__client_name(a, f) \
__NDR_convert__char_rep__string(a, f, 128)
__NDR_convert__char_rep__string(a, f, 64)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__client_name__defined */

@@ -822,6 +932,26 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__notify__defined */

#ifndef __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined
#if defined(__NDR_convert__char_rep__JackRPCClient__message_t__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__char_rep__JackRPCClient__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__char_rep__message_t__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__char_rep__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__char_rep__JackRPCClient__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__char_rep__JackRPCClient__string(a, f, 256)
#elif defined(__NDR_convert__char_rep__string__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__char_rep__string(a, f, 256)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined */

#ifndef __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value1__defined
#if defined(__NDR_convert__char_rep__JackRPCClient__int__defined)
#define __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value1__defined
@@ -894,11 +1024,11 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
#elif defined(__NDR_convert__float_rep__JackRPCClient__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__client_name__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__client_name(a, f) \
__NDR_convert__float_rep__JackRPCClient__string(a, f, 128)
__NDR_convert__float_rep__JackRPCClient__string(a, f, 64)
#elif defined(__NDR_convert__float_rep__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__client_name__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__client_name(a, f) \
__NDR_convert__float_rep__string(a, f, 128)
__NDR_convert__float_rep__string(a, f, 64)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__client_name__defined */

@@ -922,6 +1052,26 @@ mig_internal novalue _Xrpc_jack_client_sync_notify
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__notify__defined */

#ifndef __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined
#if defined(__NDR_convert__float_rep__JackRPCClient__message_t__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__float_rep__JackRPCClient__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__float_rep__message_t__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__float_rep__message_t((message_t *)(a), f)
#elif defined(__NDR_convert__float_rep__JackRPCClient__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__float_rep__JackRPCClient__string(a, f, 256)
#elif defined(__NDR_convert__float_rep__string__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message(a, f) \
__NDR_convert__float_rep__string(a, f, 256)
#endif /* defined(__NDR_convert__*__defined) */
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined */

#ifndef __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value1__defined
#if defined(__NDR_convert__float_rep__JackRPCClient__int__defined)
#define __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value1__defined
@@ -973,9 +1123,24 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_async_notify_t(
return MIG_BAD_ARGUMENTS;
#endif /* __MigTypeCheck */

#if __MigTypeCheck
{
char * msg_limit = ((char *) In0P) + In0P->Head.msgh_size;
size_t memchr_limit;

memchr_limit = min((msg_limit - In0P->client_name), 64);
if (( memchr(In0P->client_name, '\0', memchr_limit) == NULL ))
return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!
memchr_limit = min((msg_limit - In0P->message), 256);
if (( memchr(In0P->message, '\0', memchr_limit) == NULL ))
return MIG_BAD_ARGUMENTS; // string length exceeds buffer length!
}
#endif /* __MigTypeCheck */

#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__refnum__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__client_name__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__notify__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value1__defined) || \
defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value2__defined)
if (In0P->NDR.int_rep != NDR_record.int_rep) {
@@ -988,6 +1153,9 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_async_notify_t(
#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__notify__defined)
__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__notify(&In0P->notify, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__notify__defined */
#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined)
__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message(&In0P->message, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__message__defined */
#if defined(__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value1__defined)
__NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value1(&In0P->value1, In0P->NDR.int_rep);
#endif /* __NDR_convert__int_rep__Request__rpc_jack_client_async_notify_t__value1__defined */
@@ -1000,6 +1168,7 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_async_notify_t(
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__refnum__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__client_name__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__notify__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value1__defined) || \
defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value2__defined)
if (In0P->NDR.char_rep != NDR_record.char_rep) {
@@ -1012,6 +1181,9 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_async_notify_t(
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__notify__defined)
__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__notify(&In0P->notify, In0P->NDR.char_rep);
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__notify__defined */
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined)
__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message(&In0P->message, In0P->NDR.char_rep);
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__message__defined */
#if defined(__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value1__defined)
__NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value1(&In0P->value1, In0P->NDR.char_rep);
#endif /* __NDR_convert__char_rep__Request__rpc_jack_client_async_notify_t__value1__defined */
@@ -1024,6 +1196,7 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_async_notify_t(
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__refnum__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__client_name__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__notify__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value1__defined) || \
defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value2__defined)
if (In0P->NDR.float_rep != NDR_record.float_rep) {
@@ -1036,6 +1209,9 @@ mig_internal kern_return_t __MIG_check__Request__rpc_jack_client_async_notify_t(
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__notify__defined)
__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__notify(&In0P->notify, In0P->NDR.float_rep);
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__notify__defined */
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined)
__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message(&In0P->message, In0P->NDR.float_rep);
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__message__defined */
#if defined(__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value1__defined)
__NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value1(&In0P->value1, In0P->NDR.float_rep);
#endif /* __NDR_convert__float_rep__Request__rpc_jack_client_async_notify_t__value1__defined */
@@ -1064,6 +1240,7 @@ kern_return_t rpc_jack_client_async_notify
int refnum,
client_name_t client_name,
int notify,
message_t message,
int value1,
int value2
);
@@ -1082,6 +1259,7 @@ mig_internal novalue _Xrpc_jack_client_async_notify
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
mach_msg_trailer_t trailer;
@@ -1115,7 +1293,7 @@ mig_internal novalue _Xrpc_jack_client_async_notify
{ MIG_RETURN_ERROR(OutP, check_result); }
#endif /* defined(__MIG_check__Request__rpc_jack_client_async_notify_t__defined) */

OutP->RetCode = rpc_jack_client_async_notify(In0P->Head.msgh_request_port, In0P->refnum, In0P->client_name, In0P->notify, In0P->value1, In0P->value2);
OutP->RetCode = rpc_jack_client_async_notify(In0P->Head.msgh_request_port, In0P->refnum, In0P->client_name, In0P->notify, In0P->message, In0P->value1, In0P->value2);
__AfterRcvSimple(1001, "rpc_jack_client_async_notify")
}

@@ -1145,9 +1323,9 @@ const struct JackRPCClient_subsystem {
(vm_address_t)0,
{
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xrpc_jack_client_sync_notify, 7, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__rpc_jack_client_sync_notify_t)},
(mig_stub_routine_t) _Xrpc_jack_client_sync_notify, 8, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__rpc_jack_client_sync_notify_t)},
{ (mig_impl_routine_t) 0,
(mig_stub_routine_t) _Xrpc_jack_client_async_notify, 6, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__rpc_jack_client_async_notify_t)},
(mig_stub_routine_t) _Xrpc_jack_client_async_notify, 7, 0, (routine_arg_descriptor_t)0, (mach_msg_size_t)sizeof(__Reply__rpc_jack_client_async_notify_t)},
}
};



+ 24
- 17
macosx/RPC/JackRPCClientUser.c View File

@@ -1,7 +1,7 @@
/*
* IDENTIFICATION:
* stub generated Mon Sep 1 17:42:27 2008
* with a MiG generated Tue Feb 19 02:01:43 PST 2008 by root@b75.local
* stub generated Fri Oct 23 10:35:08 2009
* with a MiG generated Mon May 18 09:59:33 PDT 2009 by root@sulitlana.apple.com
* OPTIONS:
*/
#define __MIG_check__Reply__JackRPCClient_subsystem__ 1
@@ -50,15 +50,15 @@
#ifndef __MachMsgErrorWithTimeout
#define __MachMsgErrorWithTimeout(_R_) { \
switch (_R_) { \
case MACH_SEND_INVALID_REPLY: \
case MACH_RCV_INVALID_NAME: \
case MACH_RCV_PORT_DIED: \
case MACH_RCV_PORT_CHANGED: \
case MACH_RCV_TIMED_OUT: \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
case MACH_SEND_INVALID_DATA: \
case MACH_SEND_INVALID_DEST: \
case MACH_SEND_INVALID_HEADER: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
break; \
case MACH_SEND_TIMED_OUT: \
case MACH_RCV_TIMED_OUT: \
default: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
} \
}
#endif /* __MachMsgErrorWithTimeout */
@@ -66,14 +66,13 @@
#ifndef __MachMsgErrorWithoutTimeout
#define __MachMsgErrorWithoutTimeout(_R_) { \
switch (_R_) { \
case MACH_SEND_INVALID_REPLY: \
case MACH_RCV_INVALID_NAME: \
case MACH_RCV_PORT_DIED: \
case MACH_RCV_PORT_CHANGED: \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
case MACH_SEND_INVALID_DATA: \
case MACH_SEND_INVALID_DEST: \
case MACH_SEND_INVALID_HEADER: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
break; \
default: \
mig_put_reply_port(InP->Head.msgh_reply_port); \
mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
} \
}
#endif /* __MachMsgErrorWithoutTimeout */
@@ -265,6 +264,7 @@ mig_external kern_return_t rpc_jack_client_sync_notify
int refnum,
client_name_t client_name,
int notify,
message_t message,
int value1,
int value2,
int *result
@@ -280,6 +280,7 @@ mig_external kern_return_t rpc_jack_client_sync_notify
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
} Request;
@@ -341,10 +342,12 @@ mig_external kern_return_t rpc_jack_client_sync_notify

InP->refnum = refnum;

(void) mig_strncpy(InP->client_name, client_name, 128);
(void) mig_strncpy(InP->client_name, client_name, 64);

InP->notify = notify;

(void) mig_strncpy(InP->message, message, 256);

InP->value1 = value1;

InP->value2 = value2;
@@ -387,6 +390,7 @@ mig_external kern_return_t rpc_jack_client_async_notify
int refnum,
client_name_t client_name,
int notify,
message_t message,
int value1,
int value2
)
@@ -401,6 +405,7 @@ mig_external kern_return_t rpc_jack_client_async_notify
int refnum;
client_name_t client_name;
int notify;
message_t message;
int value1;
int value2;
} Request;
@@ -433,10 +438,12 @@ mig_external kern_return_t rpc_jack_client_async_notify

InP->refnum = refnum;

(void) mig_strncpy(InP->client_name, client_name, 128);
(void) mig_strncpy(InP->client_name, client_name, 64);

InP->notify = notify;

(void) mig_strncpy(InP->message, message, 256);

InP->value1 = value1;

InP->value2 = value2;


+ 3
- 3
macosx/RPC/JackRPCEngine.defs View File

@@ -25,11 +25,11 @@ import "Jackdefs.h";

ServerPrefix server_;

type client_name_t = c_string[128];
type client_name_t = c_string[64];
type client_port_name_t = c_string[128];
type client_port_type_t = c_string[128];
type so_name_t = c_string[1024];
type objet_data_t = c_string[1024];
type so_name_t = c_string[256];
type objet_data_t = c_string[256];

routine rpc_jack_client_open(
server_port : mach_port_t;


+ 1
- 1
macosx/RPC/JackRPCEngine.h View File

@@ -21,7 +21,7 @@ typedef struct {
char *name;
function_ptr_t function;
} function_table_entry;
typedef function_table_entry *function_table_t;
typedef function_table_entry *function_table_t;
#endif /* FUNCTION_PTR_T */
#endif /* AUTOTEST */



Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save