[SCM] jackd2/master: Sync to upstream VCS r4627 (1.9.8-preview)
adiknoth-guest at users.alioth.debian.org
adiknoth-guest at users.alioth.debian.org
Mon Dec 5 16:59:18 UTC 2011
The following commit has been merged in the master branch:
commit c40d7771c8b07c469825104af64bda94dba9be96
Author: Adrian Knoth <adi at drcomp.erfurt.thur.de>
Date: Mon Dec 5 16:51:59 2011 +0100
Sync to upstream VCS r4627 (1.9.8-preview)
diff --git a/debian/patches/0000_sync_upstream.patch b/debian/patches/0000_sync_upstream.patch
new file mode 100644
index 0000000..83ad623
--- /dev/null
+++ b/debian/patches/0000_sync_upstream.patch
@@ -0,0 +1,71727 @@
+From: Adrian Knoth <adi at drcomp.erfurt.thur.de>
+Description: Sync to upstream VCS r4627
+Origin: http://repo.or.cz/w/jack2.git
+Last-Update: 2011-12-05
+--- a/ChangeLog
++++ b/ChangeLog
+@@ -1,39 +1,254 @@
+----------------------------
+- Contributors
+----------------------------
+-
+-Dmitry Baikov
+-Gabriel M. Beddingfield
+-Steven Chamberlain
+-Thom Johansen
+-Thibault LeMeur
+-Tom Szilagyi
+-Andrzej Szombierski
+-Kjetil S.Matheussen
+-Pieter Palmers
+-Tim Blechmann
+-Marc-Olivier Barre
+-Nedko Arnaudov
+-Fernando Lopez-Lezcano
+-Romain Moret
+-Florian Faber
+-Michael Voigt
+-Torben Hohn
+-Paul Davis
+-Peter L Jones
+-Devin Anderson
+-Josh Green
+-Mario Lang
++---------------------------
++ Contributors
++---------------------------
++
++Dmitry Baikov
++Gabriel M. Beddingfield
++Steven Chamberlain
++Thom Johansen
++Thibault LeMeur
++Tom Szilagyi
++Andrzej Szombierski
++Kjetil S.Matheussen
++Pieter Palmers
++Tim Blechmann
++Marc-Olivier Barre
++Nedko Arnaudov
++Fernando Lopez-Lezcano
++Romain Moret
++Florian Faber
++Michael Voigt
++Torben Hohn
++Paul Davis
++Peter L Jones
++Devin Anderson
++Josh Green
++Mario Lang
+ Arnold Krille
+ Jan Engelhardt
+ Adrian Knoth
+ David Garcia Garzon
+ Valerio Pilo
++Chris Caudle
++John Emmas
+
+ ---------------------------
+ Jackdmp changes log
+ ---------------------------
+
++2011-11-25 Stephane Letz <letz at grame.fr>
++
++ * More robust dynamic port management in JACK/CoreMidi bridge.
++ * Correct jack_port_name_size API.
++
++2011-11-24 Stephane Letz <letz at grame.fr>
++
++ * Dynamic port management in JACK/CoreMidi bridge.
++ * Correct jack_client_create_thread (when realtime in on).
++
++2011-11-21 Stephane Letz <letz at grame.fr>
++
++ * John Emmas third auto-launch server on Windows patch.
++
++2011-11-07 Stephane Letz <letz at grame.fr>
++
++ * John Emmas first auto-launch server on Windows patch.
++ * John Emmas second auto-launch server on Windows patch.
++
++2011-11-06 Stephane Letz <letz at grame.fr>
++
++ * Enable local access in NetJack2 code.
++
++2011-11-04 Stephane Letz <letz at grame.fr>
++
++ * Fix jack_set_port_name API.
++
++2011-11-03 Stephane Letz <letz at grame.fr>
++
++ * Add missing jack_client_get_uuid API.
++ * John Emmas Windows server launching patch (1).
++
++2011-10-28 Stephane Letz <letz at grame.fr>
++
++ * John Emmas POST_PACKED_STRUCTURE patch.
++
++2011-10-27 Stephane Letz <letz at grame.fr>
++
++ * Gabriel Beddingfield patch (r4541) reverted.
++
++2011-10-10 Stephane Letz <letz at grame.fr>
++
++ * John Emmas patch for DSP CPU computation.
++
++2011-09-27 Stephane Letz <letz at grame.fr>
++
++ * Gabriel Beddingfield patch for ALSA driver: error when source is non-native byte-order float.
++
++2011-08-31 Stephane Letz <letz at grame.fr>
++
++ * Correct Start/Stop for Control API.
++
++2011-08-30 Stephane Letz <letz at grame.fr>
++
++ * Check driver type in jackdmp.cpp.
++
++2011-08-28 Stephane Letz <letz at grame.fr>
++
++ * Correct JackBasePosixMutex::Trylock.
++ * Correct JackMessageBuffer::Execute.
++
++2011-08-26 Stephane Letz <letz at grame.fr>
++
++ * More robust code in synchronization primitives and in JackMessageBuffer.
++ * Non blocking notifications in JackEngine::NotifyAddClient and JackEngine::NotifyRemoveClient.
++ * More robust Control API implementation.
++ * Add jackctl_driver_get_type in Control API.
++ * Singleton behaviour for JackCoreMidiDriver and JackWinMMEDriver.
++
++2011-07-29 Stephane Letz <letz at grame.fr>
++
++ * New JackTimedDriver class to be used by JackDummyDriver, JackNetDriver and JackNetOneDriver classes.
++
++2011-07-28 Stephane Letz <letz at grame.fr>
++
++ * Enable explicit channel mapping in CoreAudio driver.
++
++2011-07-25 Stephane Letz <letz at grame.fr>
++
++ * NetJack2: no more timeout, correct JackWaitThreadedDriver::Execute.
++
++2011-07-25 Stephane Letz <letz at grame.fr>
++
++ * NetJack2: improve latency management, cleanup.
++
++2011-07-23 Stephane Letz <letz at grame.fr>
++
++ * Possible fix for http://trac.jackaudio.org/ticket/193.
++
++2011-07-22 Stephane Letz <letz at grame.fr>
++
++ * NetJack2: improve error reporting.
++
++2011-07-16 Stephane Letz <letz at grame.fr>
++
++ * Error in JackActivationCount::Signal now uses jack_log instead of jack_error.
++ * EXPORT macro renamed to LIB_EXPORT.
++
++2011-07-12 Stephane Letz <letz at grame.fr>
++
++ * NetJack2 now only send data on network only is ports are connected both sides.
++
++2011-07-11 Stephane Letz <letz at grame.fr>
++
++ * Add JACK_NETJACK_PORT and JACK_NETJACK_MULTICAST environment variables for NetJack2.
++
++2011-07-08 Stephane Letz <letz at grame.fr>
++
++ * NetJack2 now only send data on network for connected ports.
++
++2011-07-03 Stephane Letz <letz at grame.fr>
++
++ * More debug code in JackMMCSS class.
++
++2011-07-03 Stephane Letz <letz at grame.fr>
++
++ * -l in JackCoreAudioDriver now display devices names and then quit.
++
++2011-07-01 Stephane Letz <letz at grame.fr>
++
++ * Fix bugs in JackNetAdapter.
++
++2011-06-29 Stephane Letz <letz at grame.fr>
++
++ * Special CATCH_CLOSE_EXCEPTION_RETURN to handle Close API calls.
++
++2011-06-28 Stephane Letz <letz at grame.fr>
++
++ * Another round of code improvements to handle completely buggy Digidesign CoreAudio user-land driver.
++
++2011-06-20 Stephane Letz <letz at grame.fr>
++
++ * Correct Dummy driver.
++
++2011-06-17 Stephane Letz <letz at grame.fr>
++
++ * NetJack2: connection error handling.
++
++2011-06-16 Stephane Letz <letz at grame.fr>
++
++ * Changes in NetJack2 connection management: no more timeout, any transmission error considered as fatal.
++ * NetJack2: timeout again...
++
++2011-06-11 Stephane Letz <letz at grame.fr>
++
++ * Special version of jack_attach_shm/jack_release_shm on client side for POSIX shared memory, to solve a memory leak issue.
++
++2011-06-10 Stephane Letz <letz at grame.fr>
++
++ * SaveConnections/RestoreConnections in NetDriver.
++ * SaveConnections/RestoreConnections moved in JackAudioDriver.
++
++2011-06-09 Stephane Letz <letz at grame.fr>
++
++ * Correct NetJack2 connection handling.
++
++2011-05-27 Stephane Letz <letz at grame.fr>
++
++ * Correct rd_acquire in dbus code.
++
++2011-05-16 Stephane Letz <letz at grame.fr>
++
++ * Correct OSX real-time thread setup.
++
++2011-05-11 Stephane Letz <letz at grame.fr>
++
++ * Correct MIDI in NetJack2.
++
++2011-05-05 Stephane Letz <letz at grame.fr>
++
++ * Libjacknet in progress.
++
++2011-05-02 Stephane Letz <letz at grame.fr>
++
++ * Merge branch switch-master-port-registration-notifications: correct driver port registration.
++
++2011-04-21 Stephane Letz <letz at grame.fr>
++
++ * CELT code for NetJack2.
++
++2011-04-20 Stephane Letz <letz at grame.fr>
++
++ * Add XRun detection in PortAudio driver.
++
++2011-04-18 Stephane Letz <letz at grame.fr>
++
++ * JackWeakAPI.cpp renamed in JackWeakAPI.c.
++
++2011-04-04 Stephane Letz <letz at grame.fr>
++
++ * Correct driver lifetime management.
++
++2011-04-03 Stephane Letz <letz at grame.fr>
++
++ * Fix in JackCoreAudioDriver::Read when there is no inputs.
++
++2011-04-02 Stephane Letz <letz at grame.fr>
++
++ * NetDriver can now ask for in/out values from the master (in progress).
++ * Correct drivers parameter settings.
++
++2011-04-01 Stephane Letz <letz at grame.fr>
++
++ * Merge newer-midi branch (Devin Anderson redesign of the MIDI drivers: alsarawmidi, ffado, coremidi and winmme).
++ * Cleanup JackThreadedDriver::Stop.
++ * Correct JackNetOneDriver::Close.
++ * Correction in jackdmp.cpp: notify_server_stop should be done after server destruction.
++ * Improve error management in JackNetDriver.
++
++2011-03-30 Stephane Letz <letz at grame.fr>
++
++ * Version 1.9.8 started.
++
+ 2011-03-29 Stephane Letz <letz at grame.fr>
+
+ * Synchronize JackWeakAPI.cpp with new APIs.
+@@ -117,7 +332,7 @@
+
+ 2010-11-17 Stephane Letz <letz at grame.fr>
+
+- * ALSA backend : suspend/resume handling (jack1 r4075).
++ * ALSA backend: suspend/resume handling (jack1 r4075).
+ * Correct dummy driver.
+
+ 2010-11-05 Stephane Letz <letz at grame.fr>
+@@ -169,7 +384,7 @@
+
+ 2010-06-13 Stephane Letz <letz at grame.fr>
+
+- * Fix JackPosixSemaphore::TimedWait : same behavior as JackPosixSemaphore::Wait regarding EINTR.
++ * Fix JackPosixSemaphore::TimedWait: same behavior as JackPosixSemaphore::Wait regarding EINTR.
+
+ 2010-05-31 Stephane Letz <letz at grame.fr>
+
+@@ -216,7 +431,7 @@
+
+ 2010-03-04 Stephane Letz <letz at grame.fr>
+
+- * Correct JackMachServerChannel::Execute : keep running even in error cases.
++ * Correct JackMachServerChannel::Execute: keep running even in error cases.
+ * Raise JACK_PROTOCOL_VERSION number.
+
+ 2010-03-03 Stephane Letz <letz at grame.fr>
+@@ -225,7 +440,7 @@
+
+ 2010-03-02 Stephane Letz <letz at grame.fr>
+
+- * Improve JackCoreAudioDriver and JackCoreAudioAdapter : when no devices are described, takes default input and output and aggregate them.
++ * Improve JackCoreAudioDriver and JackCoreAudioAdapter: when no devices are described, takes default input and output and aggregate them.
+
+ 2010-02-15 Stephane Letz <letz at grame.fr>
+
+@@ -267,7 +482,7 @@
+
+ 2009-12-01 Stephane Letz <letz at grame.fr>
+
+- * Fix port_rename callback : now both old name and new name are given as parameters.
++ * Fix port_rename callback: now both old name and new name are given as parameters.
+
+ 2009-11-30 Stephane Letz <letz at grame.fr>
+
+@@ -297,7 +512,7 @@
+ 2009-11-17 Stephane Letz <letz at 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).
++ * 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 at grame.fr>
+
+@@ -305,14 +520,14 @@
+
+ 2009-11-14 Stephane Letz <letz at grame.fr>
+
+- * Sync with JACK1 : -r parameter now used for no-realtime, realtime (-R) is now default, usable backend given vie platform.
++ * 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 at 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.
++ * Simplify server temporary mode: now use a JackTemporaryException.
+ * Lock/Unlock shared memory segments (to test...).
+
+ 2009-11-12 Stephane Letz <letz at grame.fr>
+@@ -329,12 +544,12 @@
+
+ 2009-11-09 Stephane Letz <letz at grame.fr>
+
+- * Correct JackGraphManager::GetBuffer for the "client loop with one connection" case : buffer must be copied.
++ * Correct JackGraphManager::GetBuffer for the "client loop with one connection" case: buffer must be copied.
+
+ 2009-11-07 Stephane Letz <letz at 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.
++ * Correct JackPosixThread::StartImp: thread priority setting now done in the RT case only.
+
+ 2009-11-06 Stephane Letz <letz at grame.fr>
+
+@@ -375,7 +590,7 @@
+
+ 2009-10-25 Stephane Letz <letz at grame.fr>
+
+- * Improve aggregate device management in JackCoreAudioDriver : now a "private" device only and cleanup properly.
++ * 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 at grame.fr>
+@@ -396,7 +611,7 @@
+
+ 2009-10-17 Stephane Letz <letz at grame.fr>
+
+- * Correct server temporary mode : now set a global and quit after server/client message handling is finished.
++ * Correct server temporary mode: now set a global and quit after server/client message handling is finished.
+
+ 2009-10-15 Stephane Letz <letz at grame.fr>
+
+@@ -477,12 +692,12 @@
+
+ 2009-06-30 Stephane Letz <letz at grame.fr>
+
+- * Tim Bechmann patch : hammerfall, only release monitor thread, if it has been created.
++ * Tim Bechmann patch: hammerfall, only release monitor thread, if it has been created.
+
+ 2009-06-19 Stephane Letz <letz at grame.fr>
+
+ * Correct JackTransportEngine::MakeAllLocating, sync callback has to be called in this case also.
+- * NetJack2 code : better error checkout, method renaming.
++ * NetJack2 code: better error checkout, method renaming.
+
+ 2009-06-17 Stephane Letz <letz at grame.fr>
+
+@@ -582,7 +797,7 @@
+
+ 2009-03-11 Stephane Letz <letz at grame.fr>
+
+- * Client incorrect re-naming fixed : now done at socket level also.
++ * Client incorrect re-naming fixed: now done at socket level also.
+
+ 2009-03-10 Stephane Letz <letz at grame.fr>
+
+@@ -797,7 +1012,7 @@
+
+ 2008-10-08 Stephane Letz <letz at grame.fr>
+
+- * Fix a SMP related bug introduced in rev 2957 : remove the __SMP__ flag and define LOCK for SMP in all cases.
++ * Fix a SMP related bug introduced in rev 2957: remove the __SMP__ flag and define LOCK for SMP in all cases.
+
+ 2008-10-02 Stephane Letz <letz at grame.fr>
+
+@@ -812,7 +1027,7 @@
+
+ 2008-10-10 Stephane Letz <letz at grame.fr>
+
+- * Improve OSS backend : SNDCTL_DSP_SETFRAGMENT must be done before, use of AFMT_S16_LE kind of values.
++ * Improve OSS backend: SNDCTL_DSP_SETFRAGMENT must be done before, use of AFMT_S16_LE kind of values.
+
+ 2008-10-09 Stephane Letz <letz at grame.fr>
+
+@@ -821,7 +1036,7 @@
+
+ 2008-10-08 Stephane Letz <letz at grame.fr>
+
+- * Fix a SMP related bug introduced in rev 2957 : remove the __SMP__ flag and define LOCK for SMP in all cases.
++ * Fix a SMP related bug introduced in rev 2957: remove the __SMP__ flag and define LOCK for SMP in all cases.
+
+ 2008-10-03 Stephane Letz <letz at grame.fr>
+
+@@ -938,7 +1153,7 @@
+ 2008-07-08 Stephane Letz <letz at grame.fr>
+
+ * Add jack_get_descriptor in internal clients API.
+- * Fix JackFreewheelDriver::Process() in case if client time-out : continue processing until a better recovery strategy is chosen.
++ * Fix JackFreewheelDriver::Process() in case if client time-out: continue processing until a better recovery strategy is chosen.
+
+ 2008-07-08 Stephane Letz <letz at grame.fr>
+
+@@ -1011,7 +1226,7 @@
+
+ 2008-06-02 Stephane Letz <letz at grame.fr>
+
+- * Tim Blechmann patch to remove unnecessary virtual methods : choice of the appropriate platform version is now done at compilation time.
++ * Tim Blechmann patch to remove unnecessary virtual methods: choice of the appropriate platform version is now done at compilation time.
+
+ 2008-06-02 Stephane Letz <letz at grame.fr>
+
+@@ -1038,12 +1253,12 @@
+
+ 2008-05-27 Stephane Letz <letz at grame.fr>
+
+- * Correct timing in drivers : frame time has to be incremented before Read.
++ * Correct timing in drivers: frame time has to be incremented before Read.
+
+ 2008-05-26 Stephane Letz <letz at grame.fr>
+
+ * Merge control branch.
+- * Cleanup example clients : use jack_client_open and install a proper 'quit' signal handler.
++ * Cleanup example clients: use jack_client_open and install a proper 'quit' signal handler.
+
+ 2008-05-24 Stephane Letz <letz at grame.fr>
+
+@@ -1064,7 +1279,7 @@
+
+ * Correct JackEngine::PortUnRegister, JackEngine::ClientCloseAux and JackEngine::ClientDeactivate to correctly send notifications.
+ * New jack_get_client_pid API, implemented on server side.
+- * Better handling of graph state read functions : never wait when used in the real-time thread, current state is used.
++ * Better handling of graph state read functions: never wait when used in the real-time thread, current state is used.
+
+ 2008-05-20 Stephane Letz <letz at grame.fr>
+
+@@ -1074,7 +1289,7 @@
+ 2008-05-19 Stephane Letz <letz at grame.fr>
+
+ * Use of placement new for dynamic port allocation is possibly not safe... so avoid that until a definitive answer is found.
+- * JackAudioDriver::ProcessAsync and JackAudioDriver::ProcessSync were broken at some point : 0 has to be returned in all cases.
++ * JackAudioDriver::ProcessAsync and JackAudioDriver::ProcessSync were broken at some point: 0 has to be returned in all cases.
+
+ 2008-05-16 Stephane Letz <letz at grame.fr>
+
+@@ -1103,7 +1318,7 @@
+
+ 2008-05-05 Stephane Letz <letz at grame.fr>
+
+- * Fix JackClient::Close : notification channel is stopped first to avoid receiving notifications while closing and Close is again a synchronous call.
++ * Fix JackClient::Close: notification channel is stopped first to avoid receiving notifications while closing and Close is again a synchronous call.
+ * No more remaining client close in JackEngine::Close().
+
+ 2008-05-01 Stephane Letz <letz at grame.fr>
+@@ -1144,7 +1359,7 @@
+ 2008-03-29 Stephane Letz <letz at grame.fr>
+
+ * Correct a missing parameter in the usage message of jack_midiseq.
+- * Add a client counter in wrapper layer : library is unloaded only when all clients have been closed.
++ * Add a client counter in wrapper layer: library is unloaded only when all clients have been closed.
+
+ 2008-03-28 Stephane Letz <letz at grame.fr>
+
+@@ -1334,7 +1549,7 @@
+
+ 2008-01-03 Stephane Letz <letz at grame.fr>
+
+- * Dmitry Baikov MIDI patch : alsa_seqmidi and alsa_rammidi drivers.
++ * Dmitry Baikov MIDI patch: alsa_seqmidi and alsa_rammidi drivers.
+
+ 2008-01-03 Stephane Letz <letz at grame.fr>
+
+@@ -1741,4 +1956,4 @@
+
+ 2006-09-03 Stephane Letz <letz at grame.fr>
+
+- * First import of version 0.58 base code
++ * First import of version 0.58 base code
+--- a/common/driver_interface.h
++++ b/common/driver_interface.h
+@@ -41,78 +41,110 @@
+ #define JACK_CONSTRAINT_FLAG_STRICT ((uint32_t)2) /**< if set, constraint is strict, i.e. supplying non-matching value will not work */
+ #define JACK_CONSTRAINT_FLAG_FAKE_VALUE ((uint32_t)4) /**< if set, values have no user meaningful meaning */
+
+- /** Driver parameter types */
+- typedef enum
+- {
+- JackDriverParamInt = 1,
+- JackDriverParamUInt,
+- JackDriverParamChar,
+- JackDriverParamString,
+- JackDriverParamBool
+- } jack_driver_param_type_t;
+-
+- /** Driver parameter value */
+- typedef union
+- {
+- uint32_t ui;
+- int32_t i;
+- char c;
+- char str[JACK_DRIVER_PARAM_STRING_MAX + 1];
+- } jack_driver_param_value_t;
+-
+- typedef struct {
+- jack_driver_param_value_t value;
+- char short_desc[64]; /**< A short (~30 chars) description for the user */
+- } jack_driver_param_value_enum_t;
+-
+- typedef struct {
+- uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */
+-
+- union {
+- struct {
+- jack_driver_param_value_t min;
+- jack_driver_param_value_t max;
+- } range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */
+-
+- struct {
+- uint32_t count;
+- jack_driver_param_value_enum_t * possible_values_array;
+- } enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */
+- } constraint;
+- } jack_driver_param_constraint_desc_t;
+-
+- /** A driver parameter descriptor */
+- typedef struct {
+- char name[JACK_DRIVER_NAME_MAX + 1]; /**< The parameter's name */
+- char character; /**< The parameter's character (for getopt, etc) */
+- jack_driver_param_type_t type; /**< The parameter's type */
+- jack_driver_param_value_t value; /**< The parameter's (default) value */
+- jack_driver_param_constraint_desc_t * constraint; /**< Pointer to parameter constraint descriptor. NULL if there is no constraint */
+- char short_desc[64]; /**< A short (~30 chars) description for the user */
+- char long_desc[1024]; /**< A longer description for the user */
+- }
+- jack_driver_param_desc_t;
+-
+- /** A driver parameter */
+- typedef struct {
+- char character;
+- jack_driver_param_value_t value;
+- }
+- jack_driver_param_t;
+-
+-
+- /** A struct for describing a jack driver */
+- typedef struct {
+- char name[JACK_DRIVER_NAME_MAX + 1]; /**< The driver's canonical name */
+- char desc[JACK_DRIVER_PARAM_DESC + 1]; /**< The driver's extended description */
+- char file[JACK_PATH_MAX + 1]; /**< The filename of the driver's shared object file */
+- uint32_t nparams; /**< The number of parameters the driver has */
+- jack_driver_param_desc_t * params; /**< An array of parameter descriptors */
+- }
+- jack_driver_desc_t;
++/** Driver parameter types */
++typedef enum
++{
++ JackDriverParamInt = 1,
++ JackDriverParamUInt,
++ JackDriverParamChar,
++ JackDriverParamString,
++ JackDriverParamBool
++} jack_driver_param_type_t;
++
++/** Driver types */
++typedef enum
++{
++ JackDriverMaster = 1,
++ JackDriverSlave,
++ JackDriverNone,
++} jack_driver_type_t;
++
++/** Driver parameter value */
++typedef union
++{
++ uint32_t ui;
++ int32_t i;
++ char c;
++ char str[JACK_DRIVER_PARAM_STRING_MAX + 1];
++} jack_driver_param_value_t;
++
++typedef struct {
++ jack_driver_param_value_t value;
++ char short_desc[64]; /**< A short (~30 chars) description for the user */
++} jack_driver_param_value_enum_t;
++
++typedef struct {
++ uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */
++
++ union {
++ struct {
++ jack_driver_param_value_t min;
++ jack_driver_param_value_t max;
++ } range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */
++
++ struct {
++ uint32_t count;
++ jack_driver_param_value_enum_t * possible_values_array;
++ } enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */
++ } constraint;
++} jack_driver_param_constraint_desc_t;
++
++/** A driver parameter descriptor */
++typedef struct {
++ char name[JACK_DRIVER_NAME_MAX + 1]; /**< The parameter's name */
++ char character; /**< The parameter's character (for getopt, etc) */
++ jack_driver_param_type_t type; /**< The parameter's type */
++ jack_driver_param_value_t value; /**< The parameter's (default) value */
++ jack_driver_param_constraint_desc_t * constraint; /**< Pointer to parameter constraint descriptor. NULL if there is no constraint */
++ char short_desc[64]; /**< A short (~30 chars) description for the user */
++ char long_desc[1024]; /**< A longer description for the user */
++}
++jack_driver_param_desc_t;
++
++/** A driver parameter */
++typedef struct {
++ char character;
++ jack_driver_param_value_t value;
++}
++jack_driver_param_t;
++
++/** A struct for describing a jack driver */
++typedef struct {
++ char name[JACK_DRIVER_NAME_MAX + 1]; /**< The driver's canonical name */
++ jack_driver_type_t type; /**< The driver's type */
++ char desc[JACK_DRIVER_PARAM_DESC + 1]; /**< The driver's extended description */
++ char file[JACK_PATH_MAX + 1]; /**< The filename of the driver's shared object file */
++ uint32_t nparams; /**< The number of parameters the driver has */
++ jack_driver_param_desc_t * params; /**< An array of parameter descriptors */
++}
++jack_driver_desc_t;
++
++typedef struct {
++ uint32_t size; /* size of the param array, in elements */
++}
++jack_driver_desc_filler_t;
+
++SERVER_EXPORT int jack_parse_driver_params(jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr);
+
+-SERVER_EXPORT int jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr);
++SERVER_EXPORT jack_driver_desc_t * /* newlly allocated driver descriptor, NULL on failure */
++jack_driver_descriptor_construct(
++ const char * name, /* driver name */
++ jack_driver_type_t type, /* driver type */
++ const char * description, /* driver description */
++ jack_driver_desc_filler_t * filler); /* Pointer to stack var to be supplied to jack_driver_descriptor_add_parameter() as well.
++ Can be NULL for drivers that have no parameters. */
++
++SERVER_EXPORT int /* 0 on failure */
++jack_driver_descriptor_add_parameter(
++ jack_driver_desc_t * driver_descr, /* pointer to driver descriptor as returned by jack_driver_descriptor_construct() */
++ jack_driver_desc_filler_t * filler, /* Pointer to the stack var that was supplied to jack_driver_descriptor_add_parameter(). */
++ const char * name, /* parameter's name */
++ char character, /* parameter's character (for getopt, etc) */
++ jack_driver_param_type_t type, /* The parameter's type */
++ const jack_driver_param_value_t * value_ptr, /* Pointer to parameter's (default) value */
++ jack_driver_param_constraint_desc_t * constraint, /* Pointer to parameter constraint descriptor. NULL if there is no constraint */
++ const char * short_desc, /* A short (~30 chars) description for the user */
++ const char * long_desc); /* A longer description for the user, if NULL short_desc will be used */
+
+ #ifdef __cplusplus
+ }
+--- a/common/JackActivationCount.cpp
++++ b/common/JackActivationCount.cpp
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -30,7 +30,7 @@
+ {
+ if (fValue == 0) {
+ // Transfer activation to next clients
+- jack_error("JackActivationCount::Signal value = 0 ref = %ld", control->fRefNum);
++ jack_log("JackActivationCount::Signal value = 0 ref = %ld", control->fRefNum);
+ return synchro->Signal();
+ } else if (DEC_ATOMIC(&fValue) == 1) {
+ return synchro->Signal();
+--- a/common/JackActivationCount.h
++++ b/common/JackActivationCount.h
+@@ -33,6 +33,7 @@
+ \brief Client activation counter.
+ */
+
++PRE_PACKED_STRUCTURE
+ class JackActivationCount
+ {
+
+--- a/common/JackAPI.cpp
++++ b/common/JackAPI.cpp
+@@ -44,7 +44,7 @@
+ typedef void (*print_function)(const char*);
+ typedef void *(*thread_routine)(void*);
+
+- EXPORT
++ LIB_EXPORT
+ void
+ jack_get_version(
+ int *major_ptr,
+@@ -52,219 +52,220 @@
+ int *micro_ptr,
+ int *proto_ptr);
+
+- EXPORT
++ LIB_EXPORT
+ const char*
+ jack_get_version_string();
+
+ jack_client_t * jack_client_new_aux(const char* client_name,
+ jack_options_t options,
+ jack_status_t *status);
+- EXPORT jack_client_t * jack_client_open(const char* client_name,
++ LIB_EXPORT jack_client_t * jack_client_open(const char* client_name,
+ jack_options_t options,
+ jack_status_t *status, ...);
+- EXPORT jack_client_t * jack_client_new(const char* client_name);
+- EXPORT int jack_client_name_size(void);
+- EXPORT char* jack_get_client_name(jack_client_t *client);
+- EXPORT int jack_internal_client_new(const char* client_name,
++ LIB_EXPORT jack_client_t * jack_client_new(const char* client_name);
++ LIB_EXPORT int jack_client_name_size(void);
++ LIB_EXPORT char* jack_get_client_name(jack_client_t *client);
++ LIB_EXPORT int jack_internal_client_new(const char* client_name,
+ const char* load_name,
+ const char* load_init);
+- EXPORT void jack_internal_client_close(const char* client_name);
+- EXPORT int jack_is_realtime(jack_client_t *client);
+- EXPORT void jack_on_shutdown(jack_client_t *client,
++ LIB_EXPORT void jack_internal_client_close(const char* client_name);
++ LIB_EXPORT int jack_is_realtime(jack_client_t *client);
++ LIB_EXPORT void jack_on_shutdown(jack_client_t *client,
+ JackShutdownCallback shutdown_callback, void *arg);
+- EXPORT void jack_on_info_shutdown(jack_client_t *client,
++ LIB_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,
++ LIB_EXPORT int jack_set_process_callback(jack_client_t *client,
+ JackProcessCallback process_callback,
+ void *arg);
+- EXPORT jack_nframes_t jack_thread_wait(jack_client_t *client, int status);
++ LIB_EXPORT jack_nframes_t jack_thread_wait(jack_client_t *client, int status);
+
+ // new
+- EXPORT jack_nframes_t jack_cycle_wait(jack_client_t*);
+- EXPORT void jack_cycle_signal(jack_client_t*, int status);
+- EXPORT int jack_set_process_thread(jack_client_t* client, JackThreadCallback fun, void *arg);
++ LIB_EXPORT jack_nframes_t jack_cycle_wait(jack_client_t*);
++ LIB_EXPORT void jack_cycle_signal(jack_client_t*, int status);
++ LIB_EXPORT int jack_set_process_thread(jack_client_t* client, JackThreadCallback fun, void *arg);
+
+- EXPORT int jack_set_thread_init_callback(jack_client_t *client,
++ LIB_EXPORT int jack_set_thread_init_callback(jack_client_t *client,
+ JackThreadInitCallback thread_init_callback,
+ void *arg);
+- EXPORT int jack_set_freewheel_callback(jack_client_t *client,
++ LIB_EXPORT int jack_set_freewheel_callback(jack_client_t *client,
+ JackFreewheelCallback freewheel_callback,
+ void *arg);
+- EXPORT int jack_set_freewheel(jack_client_t* client, int onoff);
+- EXPORT int jack_set_buffer_size(jack_client_t *client, jack_nframes_t nframes);
+- EXPORT int jack_set_buffer_size_callback(jack_client_t *client,
++ LIB_EXPORT int jack_set_freewheel(jack_client_t* client, int onoff);
++ LIB_EXPORT int jack_set_buffer_size(jack_client_t *client, jack_nframes_t nframes);
++ LIB_EXPORT int jack_set_buffer_size_callback(jack_client_t *client,
+ JackBufferSizeCallback bufsize_callback,
+ void *arg);
+- EXPORT int jack_set_sample_rate_callback(jack_client_t *client,
++ LIB_EXPORT int jack_set_sample_rate_callback(jack_client_t *client,
+ JackSampleRateCallback srate_callback,
+ void *arg);
+- EXPORT int jack_set_client_registration_callback(jack_client_t *,
++ LIB_EXPORT int jack_set_client_registration_callback(jack_client_t *,
+ JackClientRegistrationCallback
+ registration_callback, void *arg);
+- EXPORT int jack_set_port_registration_callback(jack_client_t *,
++ LIB_EXPORT int jack_set_port_registration_callback(jack_client_t *,
+ JackPortRegistrationCallback
+ registration_callback, void *arg);
+- EXPORT int jack_set_port_connect_callback(jack_client_t *,
++ LIB_EXPORT int jack_set_port_connect_callback(jack_client_t *,
+ JackPortConnectCallback
+ connect_callback, void *arg);
+- EXPORT int jack_set_port_rename_callback(jack_client_t *,
++ LIB_EXPORT int jack_set_port_rename_callback(jack_client_t *,
+ JackPortRenameCallback
+ rename_callback, void *arg);
+- EXPORT int jack_set_graph_order_callback(jack_client_t *,
++ LIB_EXPORT int jack_set_graph_order_callback(jack_client_t *,
+ JackGraphOrderCallback graph_callback,
+ void *);
+- EXPORT int jack_set_xrun_callback(jack_client_t *,
++ LIB_EXPORT int jack_set_xrun_callback(jack_client_t *,
+ JackXRunCallback xrun_callback, void *arg);
+- EXPORT int jack_set_latency_callback(jack_client_t *client,
++ LIB_EXPORT int jack_set_latency_callback(jack_client_t *client,
+ JackLatencyCallback latency_callback, void *arg);
+
+- EXPORT int jack_activate(jack_client_t *client);
+- EXPORT int jack_deactivate(jack_client_t *client);
+- EXPORT jack_port_t * jack_port_register(jack_client_t *client,
++ LIB_EXPORT int jack_activate(jack_client_t *client);
++ LIB_EXPORT int jack_deactivate(jack_client_t *client);
++ LIB_EXPORT jack_port_t * jack_port_register(jack_client_t *client,
+ const char* port_name,
+ const char* port_type,
+ unsigned long flags,
+ unsigned long buffer_size);
+- EXPORT int jack_port_unregister(jack_client_t *, jack_port_t *);
+- EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t);
+- EXPORT const char* jack_port_name(const jack_port_t *port);
+- EXPORT const char* jack_port_short_name(const jack_port_t *port);
+- EXPORT int jack_port_flags(const jack_port_t *port);
+- EXPORT const char* jack_port_type(const jack_port_t *port);
+- EXPORT jack_port_type_id_t jack_port_type_id(const jack_port_t *port);
+- EXPORT int jack_port_is_mine(const jack_client_t *, const jack_port_t *port);
+- EXPORT int jack_port_connected(const jack_port_t *port);
+- EXPORT int jack_port_connected_to(const jack_port_t *port,
++ LIB_EXPORT int jack_port_unregister(jack_client_t *, jack_port_t *);
++ LIB_EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t);
++ LIB_EXPORT const char* jack_port_name(const jack_port_t *port);
++ LIB_EXPORT const char* jack_port_short_name(const jack_port_t *port);
++ LIB_EXPORT int jack_port_flags(const jack_port_t *port);
++ LIB_EXPORT const char* jack_port_type(const jack_port_t *port);
++ LIB_EXPORT jack_port_type_id_t jack_port_type_id(const jack_port_t *port);
++ LIB_EXPORT int jack_port_is_mine(const jack_client_t *, const jack_port_t *port);
++ LIB_EXPORT int jack_port_connected(const jack_port_t *port);
++ LIB_EXPORT int jack_port_connected_to(const jack_port_t *port,
+ const char* port_name);
+- EXPORT const char* * jack_port_get_connections(const jack_port_t *port);
+- EXPORT const char* * jack_port_get_all_connections(const jack_client_t *client,
++ LIB_EXPORT const char* * jack_port_get_connections(const jack_port_t *port);
++ LIB_EXPORT const char* * jack_port_get_all_connections(const jack_client_t *client,
+ const jack_port_t *port);
+- EXPORT int jack_port_tie(jack_port_t *src, jack_port_t *dst);
+- EXPORT int jack_port_untie(jack_port_t *port);
++ LIB_EXPORT int jack_port_tie(jack_port_t *src, jack_port_t *dst);
++ LIB_EXPORT int jack_port_untie(jack_port_t *port);
+
+ // Old latency API
+- EXPORT jack_nframes_t jack_port_get_latency(jack_port_t *port);
+- EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t *,
++ LIB_EXPORT jack_nframes_t jack_port_get_latency(jack_port_t *port);
++ LIB_EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t *,
+ jack_port_t *port);
+- EXPORT void jack_port_set_latency(jack_port_t *, jack_nframes_t);
+- EXPORT int jack_recompute_total_latency(jack_client_t*, jack_port_t* port);
++ LIB_EXPORT void jack_port_set_latency(jack_port_t *, jack_nframes_t);
++ LIB_EXPORT int jack_recompute_total_latency(jack_client_t*, jack_port_t* port);
+
+ // New latency API
+- EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range);
+- EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range);
+- EXPORT int jack_recompute_total_latencies(jack_client_t*);
+-
+- EXPORT int jack_port_set_name(jack_port_t *port, const char* port_name);
+- EXPORT int jack_port_set_alias(jack_port_t *port, const char* alias);
+- EXPORT int jack_port_unset_alias(jack_port_t *port, const char* alias);
+- EXPORT int jack_port_get_aliases(const jack_port_t *port, char* const aliases[2]);
+- EXPORT int jack_port_request_monitor(jack_port_t *port, int onoff);
+- EXPORT int jack_port_request_monitor_by_name(jack_client_t *client,
++ LIB_EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range);
++ LIB_EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range);
++ LIB_EXPORT int jack_recompute_total_latencies(jack_client_t*);
++
++ LIB_EXPORT int jack_port_set_name(jack_port_t *port, const char* port_name);
++ LIB_EXPORT int jack_port_set_alias(jack_port_t *port, const char* alias);
++ LIB_EXPORT int jack_port_unset_alias(jack_port_t *port, const char* alias);
++ LIB_EXPORT int jack_port_get_aliases(const jack_port_t *port, char* const aliases[2]);
++ LIB_EXPORT int jack_port_request_monitor(jack_port_t *port, int onoff);
++ LIB_EXPORT int jack_port_request_monitor_by_name(jack_client_t *client,
+ const char* port_name, int onoff);
+- EXPORT int jack_port_ensure_monitor(jack_port_t *port, int onoff);
+- EXPORT int jack_port_monitoring_input(jack_port_t *port);
+- EXPORT int jack_connect(jack_client_t *,
++ LIB_EXPORT int jack_port_ensure_monitor(jack_port_t *port, int onoff);
++ LIB_EXPORT int jack_port_monitoring_input(jack_port_t *port);
++ LIB_EXPORT int jack_connect(jack_client_t *,
+ const char* source_port,
+ const char* destination_port);
+- EXPORT int jack_disconnect(jack_client_t *,
++ LIB_EXPORT int jack_disconnect(jack_client_t *,
+ const char* source_port,
+ const char* destination_port);
+- EXPORT int jack_port_disconnect(jack_client_t *, jack_port_t *);
+- EXPORT int jack_port_name_size(void);
+- EXPORT int jack_port_type_size(void);
+- EXPORT size_t jack_port_type_get_buffer_size(jack_client_t *client, const char* port_type);
+- EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *);
+- EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *);
+- EXPORT const char* * jack_get_ports(jack_client_t *,
++ LIB_EXPORT int jack_port_disconnect(jack_client_t *, jack_port_t *);
++ LIB_EXPORT int jack_port_name_size(void);
++ LIB_EXPORT int jack_port_type_size(void);
++ LIB_EXPORT size_t jack_port_type_get_buffer_size(jack_client_t *client, const char* port_type);
++ LIB_EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *);
++ LIB_EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *);
++ LIB_EXPORT const char* * jack_get_ports(jack_client_t *,
+ const char* port_name_pattern,
+ const char* type_name_pattern,
+ unsigned long flags);
+- EXPORT jack_port_t * jack_port_by_name(jack_client_t *, const char* port_name);
+- EXPORT jack_port_t * jack_port_by_id(jack_client_t *client,
++ LIB_EXPORT jack_port_t * jack_port_by_name(jack_client_t *, const char* port_name);
++ LIB_EXPORT jack_port_t * jack_port_by_id(jack_client_t *client,
+ jack_port_id_t port_id);
+- EXPORT int jack_engine_takeover_timebase(jack_client_t *);
+- EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t *);
+- EXPORT jack_time_t jack_get_time();
+- EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t time);
+- EXPORT jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t frames);
+- EXPORT jack_nframes_t jack_frame_time(const jack_client_t *);
+- EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t *client);
+- EXPORT float jack_cpu_load(jack_client_t *client);
+- EXPORT jack_native_thread_t jack_client_thread_id(jack_client_t *);
+- EXPORT void jack_set_error_function(print_function);
+- EXPORT void jack_set_info_function(print_function);
+-
+- EXPORT float jack_get_max_delayed_usecs(jack_client_t *client);
+- EXPORT float jack_get_xrun_delayed_usecs(jack_client_t *client);
+- EXPORT void jack_reset_max_delayed_usecs(jack_client_t *client);
++ LIB_EXPORT int jack_engine_takeover_timebase(jack_client_t *);
++ LIB_EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t *);
++ LIB_EXPORT jack_time_t jack_get_time();
++ LIB_EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t time);
++ LIB_EXPORT jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t frames);
++ LIB_EXPORT jack_nframes_t jack_frame_time(const jack_client_t *);
++ LIB_EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t *client);
++ LIB_EXPORT float jack_cpu_load(jack_client_t *client);
++ LIB_EXPORT jack_native_thread_t jack_client_thread_id(jack_client_t *);
++ LIB_EXPORT void jack_set_error_function(print_function);
++ LIB_EXPORT void jack_set_info_function(print_function);
++
++ LIB_EXPORT float jack_get_max_delayed_usecs(jack_client_t *client);
++ LIB_EXPORT float jack_get_xrun_delayed_usecs(jack_client_t *client);
++ LIB_EXPORT void jack_reset_max_delayed_usecs(jack_client_t *client);
+
+- EXPORT int jack_release_timebase(jack_client_t *client);
+- EXPORT int jack_set_sync_callback(jack_client_t *client,
++ LIB_EXPORT int jack_release_timebase(jack_client_t *client);
++ LIB_EXPORT int jack_set_sync_callback(jack_client_t *client,
+ JackSyncCallback sync_callback,
+ void *arg);
+- EXPORT int jack_set_sync_timeout(jack_client_t *client,
++ LIB_EXPORT int jack_set_sync_timeout(jack_client_t *client,
+ jack_time_t timeout);
+- EXPORT int jack_set_timebase_callback(jack_client_t *client,
++ LIB_EXPORT int jack_set_timebase_callback(jack_client_t *client,
+ int conditional,
+ JackTimebaseCallback timebase_callback,
+ void *arg);
+- EXPORT int jack_transport_locate(jack_client_t *client,
++ LIB_EXPORT int jack_transport_locate(jack_client_t *client,
+ jack_nframes_t frame);
+- EXPORT jack_transport_state_t jack_transport_query(const jack_client_t *client,
++ LIB_EXPORT jack_transport_state_t jack_transport_query(const jack_client_t *client,
+ jack_position_t *pos);
+- EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t *client);
+- EXPORT int jack_transport_reposition(jack_client_t *client,
+- jack_position_t *pos);
+- EXPORT void jack_transport_start(jack_client_t *client);
+- EXPORT void jack_transport_stop(jack_client_t *client);
+- EXPORT void jack_get_transport_info(jack_client_t *client,
++ LIB_EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t *client);
++ LIB_EXPORT int jack_transport_reposition(jack_client_t *client,
++ const jack_position_t *pos);
++ LIB_EXPORT void jack_transport_start(jack_client_t *client);
++ LIB_EXPORT void jack_transport_stop(jack_client_t *client);
++ LIB_EXPORT void jack_get_transport_info(jack_client_t *client,
+ jack_transport_info_t *tinfo);
+- EXPORT void jack_set_transport_info(jack_client_t *client,
++ LIB_EXPORT void jack_set_transport_info(jack_client_t *client,
+ jack_transport_info_t *tinfo);
+
+- EXPORT int jack_client_real_time_priority(jack_client_t*);
+- EXPORT int jack_client_max_real_time_priority(jack_client_t*);
+- EXPORT int jack_acquire_real_time_scheduling(jack_native_thread_t thread, int priority);
+- EXPORT int jack_client_create_thread(jack_client_t* client,
++ LIB_EXPORT int jack_client_real_time_priority(jack_client_t*);
++ LIB_EXPORT int jack_client_max_real_time_priority(jack_client_t*);
++ LIB_EXPORT int jack_acquire_real_time_scheduling(jack_native_thread_t thread, int priority);
++ LIB_EXPORT int jack_client_create_thread(jack_client_t* client,
+ jack_native_thread_t *thread,
+ int priority,
+ int realtime, // boolean
+ thread_routine routine,
+ void *arg);
+- EXPORT int jack_drop_real_time_scheduling(jack_native_thread_t thread);
++ LIB_EXPORT int jack_drop_real_time_scheduling(jack_native_thread_t thread);
+
+- EXPORT int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread);
+- EXPORT int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread);
++ LIB_EXPORT int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread);
++ LIB_EXPORT int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread);
+ #ifndef WIN32
+- EXPORT void jack_set_thread_creator(jack_thread_creator_t jtc);
++ LIB_EXPORT void jack_set_thread_creator(jack_thread_creator_t jtc);
+ #endif
+- EXPORT char * jack_get_internal_client_name(jack_client_t *client,
++ LIB_EXPORT char * jack_get_internal_client_name(jack_client_t *client,
+ jack_intclient_t intclient);
+- EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t *client,
++ LIB_EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t *client,
+ const char* client_name,
+ jack_status_t *status);
+- EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client,
++ LIB_EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client,
+ const char* client_name,
+ jack_options_t options,
+ jack_status_t *status, ...);
+- EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t *client,
++ LIB_EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t *client,
+ const char* client_name,
+ jack_options_t options,
+ jack_status_t *status, va_list ap);
+
+- EXPORT jack_status_t jack_internal_client_unload(jack_client_t *client,
++ LIB_EXPORT jack_status_t jack_internal_client_unload(jack_client_t *client,
+ jack_intclient_t intclient);
+- EXPORT void jack_free(void* ptr);
++ LIB_EXPORT void jack_free(void* ptr);
+
+- EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallback session_callback, void* arg);
+- EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path);
+- EXPORT int jack_session_reply(jack_client_t* ext_client, jack_session_event_t *event);
+- EXPORT void jack_session_event_free(jack_session_event_t* ev);
+- EXPORT char* jack_get_uuid_for_client_name(jack_client_t* ext_client, const char* client_name);
+- EXPORT char* jack_get_client_name_by_uuid(jack_client_t* ext_client, const char* client_uuid);
+- EXPORT int jack_reserve_client_name(jack_client_t* ext_client, const char* name, const char* uuid);
+- EXPORT void jack_session_commands_free(jack_session_command_t *cmds);
+- EXPORT int jack_client_has_session_callback(jack_client_t *client, const char* client_name);
++ LIB_EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallback session_callback, void* arg);
++ LIB_EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path);
++ LIB_EXPORT int jack_session_reply(jack_client_t* ext_client, jack_session_event_t *event);
++ LIB_EXPORT void jack_session_event_free(jack_session_event_t* ev);
++ LIB_EXPORT char* jack_client_get_uuid (jack_client_t *client);
++ LIB_EXPORT char* jack_get_uuid_for_client_name(jack_client_t* ext_client, const char* client_name);
++ LIB_EXPORT char* jack_get_client_name_by_uuid(jack_client_t* ext_client, const char* client_uuid);
++ LIB_EXPORT int jack_reserve_client_name(jack_client_t* ext_client, const char* name, const char* uuid);
++ LIB_EXPORT void jack_session_commands_free(jack_session_command_t *cmds);
++ LIB_EXPORT int jack_client_has_session_callback(jack_client_t *client, const char* client_name);
+
+ #ifdef __cplusplus
+ }
+@@ -299,17 +300,17 @@
+ }
+ }
+
+-EXPORT void jack_set_error_function(print_function func)
++LIB_EXPORT void jack_set_error_function(print_function func)
+ {
+ jack_error_callback = (func == NULL) ? &default_jack_error_callback : func;
+ }
+
+-EXPORT void jack_set_info_function(print_function func)
++LIB_EXPORT void jack_set_info_function(print_function func)
+ {
+ jack_info_callback = (func == NULL) ? &default_jack_info_callback : func;
+ }
+
+-EXPORT jack_client_t* jack_client_new(const char* client_name)
++LIB_EXPORT jack_client_t* jack_client_new(const char* client_name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_new");
+@@ -333,7 +334,7 @@
+ }
+ }
+
+-EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames)
++LIB_EXPORT void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t frames)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_buffer");
+@@ -349,7 +350,7 @@
+ }
+ }
+
+-EXPORT const char* jack_port_name(const jack_port_t* port)
++LIB_EXPORT const char* jack_port_name(const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_name");
+@@ -365,7 +366,7 @@
+ }
+ }
+
+-EXPORT const char* jack_port_short_name(const jack_port_t* port)
++LIB_EXPORT const char* jack_port_short_name(const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_short_name");
+@@ -381,7 +382,7 @@
+ }
+ }
+
+-EXPORT int jack_port_flags(const jack_port_t* port)
++LIB_EXPORT int jack_port_flags(const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_flags");
+@@ -397,7 +398,7 @@
+ }
+ }
+
+-EXPORT const char* jack_port_type(const jack_port_t* port)
++LIB_EXPORT const char* jack_port_type(const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_type");
+@@ -413,7 +414,7 @@
+ }
+ }
+
+-EXPORT jack_port_type_id_t jack_port_type_id(const jack_port_t *port)
++LIB_EXPORT jack_port_type_id_t jack_port_type_id(const jack_port_t *port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_type_id");
+@@ -429,7 +430,7 @@
+ }
+ }
+
+-EXPORT int jack_port_connected(const jack_port_t* port)
++LIB_EXPORT int jack_port_connected(const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_connected");
+@@ -446,7 +447,7 @@
+ }
+ }
+
+-EXPORT int jack_port_connected_to(const jack_port_t* port, const char* port_name)
++LIB_EXPORT int jack_port_connected_to(const jack_port_t* port, const char* port_name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_connected_to");
+@@ -472,7 +473,7 @@
+ }
+ }
+
+-EXPORT int jack_port_tie(jack_port_t* src, jack_port_t* dst)
++LIB_EXPORT int jack_port_tie(jack_port_t* src, jack_port_t* dst)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_tie");
+@@ -498,7 +499,7 @@
+ }
+ }
+
+-EXPORT int jack_port_untie(jack_port_t* port)
++LIB_EXPORT int jack_port_untie(jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_untie");
+@@ -514,7 +515,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_port_get_latency(jack_port_t* port)
++LIB_EXPORT jack_nframes_t jack_port_get_latency(jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_latency");
+@@ -531,7 +532,7 @@
+ }
+ }
+
+-EXPORT void jack_port_set_latency(jack_port_t* port, jack_nframes_t frames)
++LIB_EXPORT void jack_port_set_latency(jack_port_t* port, jack_nframes_t frames)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_set_latency");
+@@ -547,7 +548,7 @@
+ }
+ }
+
+-EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
++LIB_EXPORT void jack_port_get_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_latency_range");
+@@ -564,7 +565,7 @@
+ }
+ }
+
+-EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
++LIB_EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_set_latency_range");
+@@ -581,7 +582,7 @@
+ }
+ }
+
+-EXPORT int jack_recompute_total_latency(jack_client_t* ext_client, jack_port_t* port)
++LIB_EXPORT int jack_recompute_total_latency(jack_client_t* ext_client, jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_recompute_total_latency");
+@@ -603,7 +604,7 @@
+ }
+ }
+
+-EXPORT int jack_recompute_total_latencies(jack_client_t* ext_client)
++LIB_EXPORT int jack_recompute_total_latencies(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_recompute_total_latencies");
+@@ -618,11 +619,7 @@
+ }
+ }
+
+-/*
+-This is unsafe if case of concurrent access, and should be "serialized" doing a server call.
+-*/
+-
+-EXPORT int jack_port_set_name(jack_port_t* port, const char* name)
++LIB_EXPORT int jack_port_set_name(jack_port_t* port, const char* name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_set_name");
+@@ -636,19 +633,18 @@
+ jack_error("jack_port_set_name called with a NULL port name");
+ return -1;
+ } else {
+- JackGraphManager* manager = GetGraphManager();
+- int refnum;
+- if (manager && ((refnum = manager->GetPort(myport)->GetRefNum()) > 0)) {
+- JackClient* client = JackGlobals::fClientTable[refnum];
+- assert(client);
+- return client->PortRename(myport, name);
+- } else {
+- return -1;
++ JackClient* client = NULL;
++ for (int i = 0; i < CLIENT_NUM; i++) {
++ // Find a valid client
++ if ((client = JackGlobals::fClientTable[i])) {
++ break;
++ }
+ }
++ return (client) ? client->PortRename(myport, name) : -1;
+ }
+ }
+
+-EXPORT int jack_port_set_alias(jack_port_t* port, const char* name)
++LIB_EXPORT int jack_port_set_alias(jack_port_t* port, const char* name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_set_alias");
+@@ -667,7 +663,7 @@
+ }
+ }
+
+-EXPORT int jack_port_unset_alias(jack_port_t* port, const char* name)
++LIB_EXPORT int jack_port_unset_alias(jack_port_t* port, const char* name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_unset_alias");
+@@ -686,7 +682,7 @@
+ }
+ }
+
+-EXPORT int jack_port_get_aliases(const jack_port_t* port, char* const aliases[2])
++LIB_EXPORT int jack_port_get_aliases(const jack_port_t* port, char* const aliases[2])
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_aliases");
+@@ -702,7 +698,7 @@
+ }
+ }
+
+-EXPORT int jack_port_request_monitor(jack_port_t* port, int onoff)
++LIB_EXPORT int jack_port_request_monitor(jack_port_t* port, int onoff)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_request_monitor");
+@@ -718,7 +714,7 @@
+ }
+ }
+
+-EXPORT int jack_port_request_monitor_by_name(jack_client_t* ext_client, const char* port_name, int onoff)
++LIB_EXPORT int jack_port_request_monitor_by_name(jack_client_t* ext_client, const char* port_name, int onoff)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_request_monitor_by_name");
+@@ -741,7 +737,7 @@
+ }
+ }
+
+-EXPORT int jack_port_ensure_monitor(jack_port_t* port, int onoff)
++LIB_EXPORT int jack_port_ensure_monitor(jack_port_t* port, int onoff)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_ensure_monitor");
+@@ -757,7 +753,7 @@
+ }
+ }
+
+-EXPORT int jack_port_monitoring_input(jack_port_t* port)
++LIB_EXPORT int jack_port_monitoring_input(jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_monitoring_input");
+@@ -773,7 +769,7 @@
+ }
+ }
+
+-EXPORT int jack_is_realtime(jack_client_t* ext_client)
++LIB_EXPORT int jack_is_realtime(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_is_realtime");
+@@ -788,7 +784,7 @@
+ }
+ }
+
+-EXPORT void jack_on_shutdown(jack_client_t* ext_client, JackShutdownCallback callback, void* arg)
++LIB_EXPORT void jack_on_shutdown(jack_client_t* ext_client, JackShutdownCallback callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_on_shutdown");
+@@ -801,7 +797,7 @@
+ }
+ }
+
+-EXPORT void jack_on_info_shutdown(jack_client_t* ext_client, JackInfoShutdownCallback callback, void* arg)
++LIB_EXPORT void jack_on_info_shutdown(jack_client_t* ext_client, JackInfoShutdownCallback callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_on_info_shutdown");
+@@ -814,7 +810,7 @@
+ }
+ }
+
+-EXPORT int jack_set_process_callback(jack_client_t* ext_client, JackProcessCallback callback, void* arg)
++LIB_EXPORT int jack_set_process_callback(jack_client_t* ext_client, JackProcessCallback callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_process_callback");
+@@ -828,7 +824,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_thread_wait(jack_client_t* ext_client, int status)
++LIB_EXPORT jack_nframes_t jack_thread_wait(jack_client_t* ext_client, int status)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_thread_wait");
+@@ -843,7 +839,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_cycle_wait(jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_cycle_wait(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_cycle_wait");
+@@ -857,7 +853,7 @@
+ }
+ }
+
+-EXPORT void jack_cycle_signal(jack_client_t* ext_client, int status)
++LIB_EXPORT void jack_cycle_signal(jack_client_t* ext_client, int status)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_cycle_signal");
+@@ -870,7 +866,7 @@
+ }
+ }
+
+-EXPORT int jack_set_process_thread(jack_client_t* ext_client, JackThreadCallback fun, void *arg)
++LIB_EXPORT int jack_set_process_thread(jack_client_t* ext_client, JackThreadCallback fun, void *arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_process_thread");
+@@ -884,7 +880,7 @@
+ }
+ }
+
+-EXPORT int jack_set_freewheel_callback(jack_client_t* ext_client, JackFreewheelCallback freewheel_callback, void* arg)
++LIB_EXPORT int jack_set_freewheel_callback(jack_client_t* ext_client, JackFreewheelCallback freewheel_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_freewheel_callback");
+@@ -898,7 +894,7 @@
+ }
+ }
+
+-EXPORT int jack_set_freewheel(jack_client_t* ext_client, int onoff)
++LIB_EXPORT int jack_set_freewheel(jack_client_t* ext_client, int onoff)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_freewheel");
+@@ -912,7 +908,7 @@
+ }
+ }
+
+-EXPORT int jack_set_buffer_size(jack_client_t* ext_client, jack_nframes_t buffer_size)
++LIB_EXPORT int jack_set_buffer_size(jack_client_t* ext_client, jack_nframes_t buffer_size)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_buffer_size");
+@@ -928,7 +924,7 @@
+ }
+ }
+
+-EXPORT int jack_set_buffer_size_callback(jack_client_t* ext_client, JackBufferSizeCallback bufsize_callback, void* arg)
++LIB_EXPORT int jack_set_buffer_size_callback(jack_client_t* ext_client, JackBufferSizeCallback bufsize_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_buffer_size_callback");
+@@ -942,7 +938,7 @@
+ }
+ }
+
+-EXPORT int jack_set_sample_rate_callback(jack_client_t* ext_client, JackSampleRateCallback srate_callback, void* arg)
++LIB_EXPORT int jack_set_sample_rate_callback(jack_client_t* ext_client, JackSampleRateCallback srate_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_sample_rate_callback");
+@@ -956,7 +952,7 @@
+ }
+ }
+
+-EXPORT int jack_set_client_registration_callback(jack_client_t* ext_client, JackClientRegistrationCallback registration_callback, void* arg)
++LIB_EXPORT int jack_set_client_registration_callback(jack_client_t* ext_client, JackClientRegistrationCallback registration_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_client_registration_callback");
+@@ -970,7 +966,7 @@
+ }
+ }
+
+-EXPORT int jack_set_port_registration_callback(jack_client_t* ext_client, JackPortRegistrationCallback registration_callback, void* arg)
++LIB_EXPORT int jack_set_port_registration_callback(jack_client_t* ext_client, JackPortRegistrationCallback registration_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_port_registration_callback");
+@@ -984,7 +980,7 @@
+ }
+ }
+
+-EXPORT int jack_set_port_connect_callback(jack_client_t* ext_client, JackPortConnectCallback portconnect_callback, void* arg)
++LIB_EXPORT int jack_set_port_connect_callback(jack_client_t* ext_client, JackPortConnectCallback portconnect_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_port_connect_callback");
+@@ -998,7 +994,7 @@
+ }
+ }
+
+-EXPORT int jack_set_port_rename_callback(jack_client_t* ext_client, JackPortRenameCallback rename_callback, void* arg)
++LIB_EXPORT int jack_set_port_rename_callback(jack_client_t* ext_client, JackPortRenameCallback rename_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_port_rename_callback");
+@@ -1012,7 +1008,7 @@
+ }
+ }
+
+-EXPORT int jack_set_graph_order_callback(jack_client_t* ext_client, JackGraphOrderCallback graph_callback, void* arg)
++LIB_EXPORT int jack_set_graph_order_callback(jack_client_t* ext_client, JackGraphOrderCallback graph_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_graph_order_callback");
+@@ -1027,7 +1023,7 @@
+ }
+ }
+
+-EXPORT int jack_set_xrun_callback(jack_client_t* ext_client, JackXRunCallback xrun_callback, void* arg)
++LIB_EXPORT int jack_set_xrun_callback(jack_client_t* ext_client, JackXRunCallback xrun_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_xrun_callback");
+@@ -1041,7 +1037,7 @@
+ }
+ }
+
+-EXPORT int jack_set_latency_callback(jack_client_t* ext_client, JackLatencyCallback latency_callback, void *arg)
++LIB_EXPORT int jack_set_latency_callback(jack_client_t* ext_client, JackLatencyCallback latency_callback, void *arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_latency_callback");
+@@ -1055,7 +1051,7 @@
+ }
+ }
+
+-EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg)
++LIB_EXPORT int jack_set_thread_init_callback(jack_client_t* ext_client, JackThreadInitCallback init_callback, void *arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_thread_init_callback");
+@@ -1070,7 +1066,7 @@
+ }
+ }
+
+-EXPORT int jack_activate(jack_client_t* ext_client)
++LIB_EXPORT int jack_activate(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_activate");
+@@ -1084,7 +1080,7 @@
+ }
+ }
+
+-EXPORT int jack_deactivate(jack_client_t* ext_client)
++LIB_EXPORT int jack_deactivate(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_deactivate");
+@@ -1098,7 +1094,7 @@
+ }
+ }
+
+-EXPORT jack_port_t* jack_port_register(jack_client_t* ext_client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
++LIB_EXPORT jack_port_t* jack_port_register(jack_client_t* ext_client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_register");
+@@ -1115,7 +1111,7 @@
+ }
+ }
+
+-EXPORT int jack_port_unregister(jack_client_t* ext_client, jack_port_t* port)
++LIB_EXPORT int jack_port_unregister(jack_client_t* ext_client, jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_unregister");
+@@ -1134,7 +1130,7 @@
+ return client->PortUnRegister(myport);
+ }
+
+-EXPORT int jack_port_is_mine(const jack_client_t* ext_client, const jack_port_t* port)
++LIB_EXPORT int jack_port_is_mine(const jack_client_t* ext_client, const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_is_mine");
+@@ -1153,7 +1149,7 @@
+ return client->PortIsMine(myport);
+ }
+
+-EXPORT const char** jack_port_get_connections(const jack_port_t* port)
++LIB_EXPORT const char** jack_port_get_connections(const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_connections");
+@@ -1171,7 +1167,7 @@
+ }
+
+ // Calling client does not need to "own" the port
+-EXPORT const char** jack_port_get_all_connections(const jack_client_t* ext_client, const jack_port_t* port)
++LIB_EXPORT const char** jack_port_get_all_connections(const jack_client_t* ext_client, const jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_all_connections");
+@@ -1194,7 +1190,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t* ext_client, jack_port_t* port)
++LIB_EXPORT jack_nframes_t jack_port_get_total_latency(jack_client_t* ext_client, jack_port_t* port)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_get_total_latency");
+@@ -1222,7 +1218,7 @@
+ }
+ }
+
+-EXPORT int jack_connect(jack_client_t* ext_client, const char* src, const char* dst)
++LIB_EXPORT int jack_connect(jack_client_t* ext_client, const char* src, const char* dst)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_connect");
+@@ -1239,7 +1235,7 @@
+ }
+ }
+
+-EXPORT int jack_disconnect(jack_client_t* ext_client, const char* src, const char* dst)
++LIB_EXPORT int jack_disconnect(jack_client_t* ext_client, const char* src, const char* dst)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_disconnect");
+@@ -1256,7 +1252,7 @@
+ }
+ }
+
+-EXPORT int jack_port_disconnect(jack_client_t* ext_client, jack_port_t* src)
++LIB_EXPORT int jack_port_disconnect(jack_client_t* ext_client, jack_port_t* src)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_disconnect");
+@@ -1275,7 +1271,7 @@
+ return client->PortDisconnect(myport);
+ }
+
+-EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_sample_rate");
+@@ -1290,7 +1286,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_buffer_size");
+@@ -1305,7 +1301,7 @@
+ }
+ }
+
+-EXPORT const char** jack_get_ports(jack_client_t* ext_client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
++LIB_EXPORT const char** jack_get_ports(jack_client_t* ext_client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_ports");
+@@ -1319,7 +1315,7 @@
+ return (manager ? manager->GetPorts(port_name_pattern, type_name_pattern, flags) : NULL);
+ }
+
+-EXPORT jack_port_t* jack_port_by_name(jack_client_t* ext_client, const char* portname)
++LIB_EXPORT jack_port_t* jack_port_by_name(jack_client_t* ext_client, const char* portname)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_by_name");
+@@ -1342,7 +1338,7 @@
+ }
+ }
+
+-EXPORT jack_port_t* jack_port_by_id(jack_client_t* ext_client, jack_port_id_t id)
++LIB_EXPORT jack_port_t* jack_port_by_id(jack_client_t* ext_client, jack_port_id_t id)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_by_id");
+@@ -1351,7 +1347,7 @@
+ return (jack_port_t*)((uintptr_t)id);
+ }
+
+-EXPORT int jack_engine_takeover_timebase(jack_client_t* ext_client)
++LIB_EXPORT int jack_engine_takeover_timebase(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_engine_takeover_timebase");
+@@ -1366,7 +1362,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_frames_since_cycle_start(const jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_frames_since_cycle_start");
+@@ -1381,7 +1377,7 @@
+ }
+ }
+
+-EXPORT jack_time_t jack_get_time()
++LIB_EXPORT jack_time_t jack_get_time()
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_time");
+@@ -1389,7 +1385,7 @@
+ return GetMicroSeconds();
+ }
+
+-EXPORT jack_time_t jack_frames_to_time(const jack_client_t* ext_client, jack_nframes_t frames)
++LIB_EXPORT jack_time_t jack_frames_to_time(const jack_client_t* ext_client, jack_nframes_t frames)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_frames_to_time");
+@@ -1410,7 +1406,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t* ext_client, jack_time_t time)
++LIB_EXPORT jack_nframes_t jack_time_to_frames(const jack_client_t* ext_client, jack_time_t time)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_time_to_frames");
+@@ -1431,7 +1427,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_frame_time(const jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_frame_time(const jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_frame_time");
+@@ -1439,7 +1435,7 @@
+ return jack_time_to_frames(ext_client, GetMicroSeconds());
+ }
+
+-EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_last_frame_time(const jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_last_frame_time");
+@@ -1448,7 +1444,7 @@
+ return (control) ? control->fFrameTimer.ReadCurrentState()->CurFrame() : 0;
+ }
+
+-EXPORT float jack_cpu_load(jack_client_t* ext_client)
++LIB_EXPORT float jack_cpu_load(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_cpu_load");
+@@ -1463,7 +1459,7 @@
+ }
+ }
+
+-EXPORT jack_native_thread_t jack_client_thread_id(jack_client_t* ext_client)
++LIB_EXPORT jack_native_thread_t jack_client_thread_id(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_thread_id");
+@@ -1477,7 +1473,7 @@
+ }
+ }
+
+-EXPORT char* jack_get_client_name(jack_client_t* ext_client)
++LIB_EXPORT char* jack_get_client_name(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_client_name");
+@@ -1491,22 +1487,22 @@
+ }
+ }
+
+-EXPORT int jack_client_name_size(void)
++LIB_EXPORT int jack_client_name_size(void)
+ {
+ return JACK_CLIENT_NAME_SIZE;
+ }
+
+-EXPORT int jack_port_name_size(void)
++LIB_EXPORT int jack_port_name_size(void)
+ {
+- return JACK_PORT_NAME_SIZE;
++ return REAL_JACK_PORT_NAME_SIZE;
+ }
+
+-EXPORT int jack_port_type_size(void)
++LIB_EXPORT int jack_port_type_size(void)
+ {
+ return JACK_PORT_TYPE_SIZE;
+ }
+
+-EXPORT size_t jack_port_type_get_buffer_size(jack_client_t* ext_client, const char* port_type)
++LIB_EXPORT size_t jack_port_type_get_buffer_size(jack_client_t* ext_client, const char* port_type)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_port_type_get_buffer_size");
+@@ -1527,7 +1523,7 @@
+ }
+
+ // transport.h
+-EXPORT int jack_release_timebase(jack_client_t* ext_client)
++LIB_EXPORT int jack_release_timebase(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_release_timebase");
+@@ -1541,7 +1537,7 @@
+ }
+ }
+
+-EXPORT int jack_set_sync_callback(jack_client_t* ext_client, JackSyncCallback sync_callback, void *arg)
++LIB_EXPORT int jack_set_sync_callback(jack_client_t* ext_client, JackSyncCallback sync_callback, void *arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_sync_callback");
+@@ -1555,7 +1551,7 @@
+ }
+ }
+
+-EXPORT int jack_set_sync_timeout(jack_client_t* ext_client, jack_time_t timeout)
++LIB_EXPORT int jack_set_sync_timeout(jack_client_t* ext_client, jack_time_t timeout)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_sync_timeout");
+@@ -1569,7 +1565,7 @@
+ }
+ }
+
+-EXPORT int jack_set_timebase_callback(jack_client_t* ext_client, int conditional, JackTimebaseCallback timebase_callback, void* arg)
++LIB_EXPORT int jack_set_timebase_callback(jack_client_t* ext_client, int conditional, JackTimebaseCallback timebase_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_timebase_callback");
+@@ -1583,7 +1579,7 @@
+ }
+ }
+
+-EXPORT int jack_transport_locate(jack_client_t* ext_client, jack_nframes_t frame)
++LIB_EXPORT int jack_transport_locate(jack_client_t* ext_client, jack_nframes_t frame)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_transport_locate");
+@@ -1598,7 +1594,7 @@
+ }
+ }
+
+-EXPORT jack_transport_state_t jack_transport_query(const jack_client_t* ext_client, jack_position_t* pos)
++LIB_EXPORT jack_transport_state_t jack_transport_query(const jack_client_t* ext_client, jack_position_t* pos)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_transport_query");
+@@ -1612,7 +1608,7 @@
+ }
+ }
+
+-EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t* ext_client)
++LIB_EXPORT jack_nframes_t jack_get_current_transport_frame(const jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_current_transport_frame");
+@@ -1626,7 +1622,7 @@
+ }
+ }
+
+-EXPORT int jack_transport_reposition(jack_client_t* ext_client, jack_position_t* pos)
++LIB_EXPORT int jack_transport_reposition(jack_client_t* ext_client, const jack_position_t* pos)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_transport_reposition");
+@@ -1641,7 +1637,7 @@
+ }
+ }
+
+-EXPORT void jack_transport_start(jack_client_t* ext_client)
++LIB_EXPORT void jack_transport_start(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_transport_start");
+@@ -1654,7 +1650,7 @@
+ }
+ }
+
+-EXPORT void jack_transport_stop(jack_client_t* ext_client)
++LIB_EXPORT void jack_transport_stop(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_transport_stop");
+@@ -1668,7 +1664,7 @@
+ }
+
+ // deprecated
+-EXPORT void jack_get_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
++LIB_EXPORT void jack_get_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_transport_info");
+@@ -1678,7 +1674,7 @@
+ memset(tinfo, 0, sizeof(jack_transport_info_t));
+ }
+
+-EXPORT void jack_set_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
++LIB_EXPORT void jack_set_transport_info(jack_client_t* ext_client, jack_transport_info_t* tinfo)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_transport_info");
+@@ -1689,7 +1685,7 @@
+ }
+
+ // statistics.h
+-EXPORT float jack_get_max_delayed_usecs(jack_client_t* ext_client)
++LIB_EXPORT float jack_get_max_delayed_usecs(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_max_delayed_usecs");
+@@ -1704,7 +1700,7 @@
+ }
+ }
+
+-EXPORT float jack_get_xrun_delayed_usecs(jack_client_t* ext_client)
++LIB_EXPORT float jack_get_xrun_delayed_usecs(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_xrun_delayed_usecs");
+@@ -1719,7 +1715,7 @@
+ }
+ }
+
+-EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client)
++LIB_EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_reset_max_delayed_usecs");
+@@ -1734,7 +1730,7 @@
+ }
+
+ // thread.h
+-EXPORT int jack_client_real_time_priority(jack_client_t* ext_client)
++LIB_EXPORT int jack_client_real_time_priority(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_real_time_priority");
+@@ -1749,7 +1745,7 @@
+ }
+ }
+
+-EXPORT int jack_client_max_real_time_priority(jack_client_t* ext_client)
++LIB_EXPORT int jack_client_max_real_time_priority(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_max_real_time_priority");
+@@ -1760,17 +1756,19 @@
+ return -1;
+ } else {
+ JackEngineControl* control = GetEngineControl();
+- return (control->fRealTime) ? control->fMaxClientPriority : -1;
++ return (control->fRealTime) ? control->fMaxClientPriority : -1;
+ }
+ }
+
+-EXPORT int jack_acquire_real_time_scheduling(jack_native_thread_t thread, int priority)
++LIB_EXPORT int jack_acquire_real_time_scheduling(jack_native_thread_t thread, int priority)
+ {
+ JackEngineControl* control = GetEngineControl();
+- return (control ? JackThread::AcquireRealTimeImp(thread, priority, GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint) : -1);
++ return (control
++ ? JackThread::AcquireRealTimeImp(thread, priority, control->fPeriod, control->fComputation, control->fConstraint)
++ : -1);
+ }
+
+-EXPORT int jack_client_create_thread(jack_client_t* client,
++LIB_EXPORT int jack_client_create_thread(jack_client_t* client,
+ jack_native_thread_t *thread,
+ int priority,
+ int realtime, /* boolean */
+@@ -1780,15 +1778,19 @@
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_create_thread");
+ #endif
+- return JackThread::StartImp(thread, priority, realtime, routine, arg);
++ JackEngineControl* control = GetEngineControl();
++ int res = JackThread::StartImp(thread, priority, realtime, routine, arg);
++ return (res == 0)
++ ? ((realtime ? JackThread::AcquireRealTimeImp(*thread, priority, control->fPeriod, control->fComputation, control->fConstraint) : res))
++ : res;
+ }
+
+-EXPORT int jack_drop_real_time_scheduling(jack_native_thread_t thread)
++LIB_EXPORT int jack_drop_real_time_scheduling(jack_native_thread_t thread)
+ {
+ return JackThread::DropRealTimeImp(thread);
+ }
+
+-EXPORT int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread)
++LIB_EXPORT int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_stop_thread");
+@@ -1796,7 +1798,7 @@
+ return JackThread::StopImp(thread);
+ }
+
+-EXPORT int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread)
++LIB_EXPORT int jack_client_kill_thread(jack_client_t* client, jack_native_thread_t thread)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_kill_thread");
+@@ -1805,27 +1807,33 @@
+ }
+
+ #ifndef WIN32
+-EXPORT void jack_set_thread_creator (jack_thread_creator_t jtc)
++LIB_EXPORT void jack_set_thread_creator (jack_thread_creator_t jtc)
+ {
+ JackGlobals::fJackThreadCreator = (jtc == NULL) ? pthread_create : jtc;
+ }
+ #endif
+
+ // intclient.h
+-EXPORT int jack_internal_client_new (const char* client_name,
++LIB_EXPORT int jack_internal_client_new (const char* client_name,
+ const char* load_name,
+ const char* load_init)
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_internal_client_new");
++#endif
+ jack_error("jack_internal_client_new: deprecated");
+ return -1;
+ }
+
+-EXPORT void jack_internal_client_close (const char* client_name)
++LIB_EXPORT void jack_internal_client_close (const char* client_name)
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_internal_client_close");
++#endif
+ jack_error("jack_internal_client_close: deprecated");
+ }
+
+-EXPORT char* jack_get_internal_client_name(jack_client_t* ext_client, jack_intclient_t intclient)
++LIB_EXPORT char* jack_get_internal_client_name(jack_client_t* ext_client, jack_intclient_t intclient)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_internal_client_name");
+@@ -1842,7 +1850,7 @@
+ }
+ }
+
+-EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t* ext_client, const char* client_name, jack_status_t* status)
++LIB_EXPORT jack_intclient_t jack_internal_client_handle(jack_client_t* ext_client, const char* client_name, jack_status_t* status)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_internal_client_handle");
+@@ -1860,7 +1868,7 @@
+ }
+ }
+
+-EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t* ext_client, const char* client_name, jack_options_t options, jack_status_t* status, va_list ap)
++LIB_EXPORT jack_intclient_t jack_internal_client_load_aux(jack_client_t* ext_client, const char* client_name, jack_options_t options, jack_status_t* status, va_list ap)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_internal_client_load_aux");
+@@ -1873,7 +1881,7 @@
+ jack_varargs_t va;
+ jack_status_t my_status;
+
+- if (status == NULL) /* no status from caller? */
++ if (status == NULL) /* no status from caller? */
+ status = &my_status; /* use local status word */
+ *status = (jack_status_t)0;
+
+@@ -1890,8 +1898,11 @@
+ }
+ }
+
+-EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client, const char* client_name, jack_options_t options, jack_status_t *status, ...)
++LIB_EXPORT jack_intclient_t jack_internal_client_load(jack_client_t *client, const char* client_name, jack_options_t options, jack_status_t *status, ...)
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_internal_client_load");
++#endif
+ va_list ap;
+ va_start(ap, status);
+ jack_intclient_t res = jack_internal_client_load_aux(client, client_name, options, status, ap);
+@@ -1899,7 +1910,7 @@
+ return res;
+ }
+
+-EXPORT jack_status_t jack_internal_client_unload(jack_client_t* ext_client, jack_intclient_t intclient)
++LIB_EXPORT jack_status_t jack_internal_client_unload(jack_client_t* ext_client, jack_intclient_t intclient)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_internal_client_load");
+@@ -1918,14 +1929,14 @@
+ }
+ }
+
+-EXPORT
+-void
+-jack_get_version(
+- int *major_ptr,
+- int *minor_ptr,
+- int *micro_ptr,
+- int *proto_ptr)
++LIB_EXPORT void jack_get_version(int *major_ptr,
++ int *minor_ptr,
++ int *micro_ptr,
++ int *proto_ptr)
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_get_version");
++#endif
+ // FIXME: We need these comming from build system
+ *major_ptr = 0;
+ *minor_ptr = 0;
+@@ -1933,22 +1944,26 @@
+ *proto_ptr = 0;
+ }
+
+-EXPORT
+-const char*
+-jack_get_version_string()
++LIB_EXPORT const char* jack_get_version_string()
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_get_version_string");
++#endif
+ return VERSION;
+ }
+
+-EXPORT void jack_free(void* ptr)
++LIB_EXPORT void jack_free(void* ptr)
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_free");
++#endif
+ if (ptr) {
+ free(ptr);
+ }
+ }
+
+ // session.h
+-EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallback session_callback, void* arg)
++LIB_EXPORT int jack_set_session_callback(jack_client_t* ext_client, JackSessionCallback session_callback, void* arg)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_set_session_callback");
+@@ -1963,7 +1978,7 @@
+ }
+ }
+
+-EXPORT jack_session_command_t *jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path)
++LIB_EXPORT jack_session_command_t* jack_session_notify(jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_session_notify");
+@@ -1978,7 +1993,7 @@
+ }
+ }
+
+-EXPORT int jack_session_reply(jack_client_t* ext_client, jack_session_event_t *event)
++LIB_EXPORT int jack_session_reply(jack_client_t* ext_client, jack_session_event_t *event)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_session_reply");
+@@ -1993,8 +2008,11 @@
+ }
+ }
+
+-EXPORT void jack_session_event_free(jack_session_event_t* ev)
++LIB_EXPORT void jack_session_event_free(jack_session_event_t* ev)
+ {
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_session_event_free");
++#endif
+ if (ev) {
+ if (ev->session_dir)
+ free((void *)ev->session_dir);
+@@ -2006,7 +2024,23 @@
+ }
+ }
+
+-EXPORT char *jack_get_uuid_for_client_name(jack_client_t* ext_client, const char* client_name)
++LIB_EXPORT char *jack_client_get_uuid(jack_client_t* ext_client)
++{
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_client_get_uuid");
++#endif
++ JackClient* client = (JackClient*)ext_client;
++ if (client == NULL) {
++ jack_error("jack_client_get_uuid called with a NULL client");
++ return NULL;
++ } else {
++ char retval[16];
++ snprintf(retval, sizeof(retval), "%d", client->GetClientControl()->fSessionID);
++ return strdup(retval);
++ }
++}
++
++LIB_EXPORT char* jack_get_uuid_for_client_name(jack_client_t* ext_client, const char* client_name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_uuid_for_client_name");
+@@ -2021,7 +2055,7 @@
+ }
+ }
+
+-EXPORT char *jack_get_client_name_by_uuid(jack_client_t* ext_client, const char* client_uuid)
++LIB_EXPORT char* jack_get_client_name_by_uuid(jack_client_t* ext_client, const char* client_uuid)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_get_client_name_by_uuid");
+@@ -2036,7 +2070,7 @@
+ }
+ }
+
+-EXPORT int jack_reserve_client_name(jack_client_t* ext_client, const char* client_name, const char* uuid)
++LIB_EXPORT int jack_reserve_client_name(jack_client_t* ext_client, const char* client_name, const char* uuid)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_reserve_client_name");
+@@ -2051,21 +2085,29 @@
+ }
+ }
+
+-EXPORT void jack_session_commands_free(jack_session_command_t *cmds)
++LIB_EXPORT void jack_session_commands_free(jack_session_command_t *cmds)
+ {
+- if (!cmds)
++#ifdef __CLIENTDEBUG__
++ JackGlobals::CheckContext("jack_session_commands_free");
++#endif
++
++ if (!cmds) {
+ return;
++ }
+
+ int i = 0;
+ while (1) {
+- if (cmds[i].client_name)
++ if (cmds[i].client_name) {
+ free ((char *)cmds[i].client_name);
+- if (cmds[i].command)
++ }
++ if (cmds[i].command) {
+ free ((char *)cmds[i].command);
+- if (cmds[i].uuid)
++ }
++ if (cmds[i].uuid) {
+ free ((char *)cmds[i].uuid);
+- else
++ } else {
+ break;
++ }
+
+ i += 1;
+ }
+@@ -2073,7 +2115,7 @@
+ free(cmds);
+ }
+
+-EXPORT int jack_client_has_session_callback(jack_client_t* ext_client, const char* client_name)
++LIB_EXPORT int jack_client_has_session_callback(jack_client_t* ext_client, const char* client_name)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_has_session_callback");
+--- a/common/JackAtomicArrayState.h
++++ b/common/JackAtomicArrayState.h
+@@ -30,7 +30,7 @@
+ /*!
+ \brief Counter for CAS
+ */
+-
++PRE_PACKED_STRUCTURE
+ struct AtomicArrayCounter
+ {
+ union {
+@@ -109,6 +109,7 @@
+
+ // CHECK livelock
+
++PRE_PACKED_STRUCTURE
+ template <class T>
+ class JackAtomicArrayState
+ {
+--- a/common/JackAtomicState.h
++++ b/common/JackAtomicState.h
+@@ -31,6 +31,7 @@
+ \brief Counter for CAS
+ */
+
++PRE_PACKED_STRUCTURE
+ struct AtomicCounter
+ {
+ union {
+@@ -84,6 +85,7 @@
+
+ // CHECK livelock
+
++PRE_PACKED_STRUCTURE
+ template <class T>
+ class JackAtomicState
+ {
+--- a/common/JackAudioAdapter.cpp
++++ b/common/JackAudioAdapter.cpp
+@@ -32,158 +32,188 @@
+ namespace Jack
+ {
+
+-//static methods ***********************************************************
+- int JackAudioAdapter::Process (jack_nframes_t frames, void* arg)
+- {
+- JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
+- jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()];
+- jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
+-
+- // Always clear output
+- for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
+- inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames);
+- memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t));
+- }
+-
+- for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
+- outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
+- }
++int JackAudioAdapter::Process(jack_nframes_t frames, void* arg)
++{
++ JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
++ jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()];
++ jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()];
+
+- adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
+- return 0;
++ // Always clear output
++ for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
++ inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames);
++ memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t));
+ }
+
+- int JackAudioAdapter::BufferSize ( jack_nframes_t buffer_size, void* arg )
+- {
+- JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg );
+- adapter->Reset();
+- adapter->fAudioAdapter->SetHostBufferSize ( buffer_size );
+- return 0;
++ for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
++ outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames);
+ }
+
+- int JackAudioAdapter::SampleRate ( jack_nframes_t sample_rate, void* arg )
+- {
+- JackAudioAdapter* adapter = static_cast<JackAudioAdapter*> ( arg );
+- adapter->Reset();
+- adapter->fAudioAdapter->SetHostSampleRate ( sample_rate );
+- return 0;
+- }
++ adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames);
++ return 0;
++}
++
++int JackAudioAdapter::BufferSize(jack_nframes_t buffer_size, void* arg)
++{
++ JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
++ adapter->Reset();
++ adapter->fAudioAdapter->SetHostBufferSize(buffer_size);
++ return 0;
++}
+
+-//JackAudioAdapter *********************************************************
++int JackAudioAdapter::SampleRate(jack_nframes_t sample_rate, void* arg)
++{
++ JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
++ adapter->Reset();
++ adapter->fAudioAdapter->SetHostSampleRate(sample_rate);
++ return 0;
++}
+
+- JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system)
+- :fJackClient(jack_client), fAudioAdapter(audio_io)
+- {
+- const JSList* node;
+- const jack_driver_param_t* param;
+- fAutoConnect = false;
++void JackAudioAdapter::Latency(jack_latency_callback_mode_t mode, void* arg)
++{
++ JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg);
+
+- for (node = params; node; node = jack_slist_next(node)) {
+- param = (const jack_driver_param_t*) node->data;
+- switch (param->character) {
+- case 'c':
+- fAutoConnect = true;
+- break;
+- }
++ if (mode == JackCaptureLatency) {
++ for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) {
++ jack_latency_range_t range;
++ range.min = range.max = adapter->fAudioAdapter->GetInputLatency(i);
++ jack_port_set_latency_range(adapter->fCapturePortList[i], JackCaptureLatency, &range);
+ }
+- }
+
+- JackAudioAdapter::~JackAudioAdapter()
+- {
+- // When called, Close has already been used for the client, thus ports are already unregistered.
+- delete fAudioAdapter;
++ } else {
++ for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) {
++ jack_latency_range_t range;
++ range.min = range.max = adapter->fAudioAdapter->GetOutputLatency(i);
++ jack_port_set_latency_range(adapter->fPlaybackPortList[i], JackPlaybackLatency, &range);
++ }
+ }
++}
+
+- void JackAudioAdapter::FreePorts()
+- {
+- for (int i = 0; i < fAudioAdapter->GetInputs(); i++ )
+- if ( fCapturePortList[i] )
+- jack_port_unregister ( fJackClient, fCapturePortList[i] );
+- for (int i = 0; i < fAudioAdapter->GetOutputs(); i++ )
+- if ( fPlaybackPortList[i] )
+- jack_port_unregister ( fJackClient, fPlaybackPortList[i] );
++JackAudioAdapter::JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params)
++ :fClient(client), fAudioAdapter(audio_io)
++{
++ const JSList* node;
++ const jack_driver_param_t* param;
++ fAutoConnect = false;
+
+- delete[] fCapturePortList;
+- delete[] fPlaybackPortList;
++ for (node = params; node; node = jack_slist_next(node)) {
++ param = (const jack_driver_param_t*)node->data;
++ switch (param->character) {
++ case 'c':
++ fAutoConnect = true;
++ break;
++ }
+ }
++}
+
+- void JackAudioAdapter::ConnectPorts()
+- {
+- const char **ports;
+-
+- ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
+- if (ports != NULL) {
+- for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) {
+- jack_connect(fJackClient,jack_port_name(fCapturePortList[i]), ports[i]);
+- }
+- free(ports);
+- }
++JackAudioAdapter::~JackAudioAdapter()
++{
++ // When called, Close has already been used for the client, thus ports are already unregistered.
++ delete fAudioAdapter;
++}
+
+- ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
+- if (ports != NULL) {
+- for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) {
+- jack_connect(fJackClient, ports[i], jack_port_name(fPlaybackPortList[i]));
+- }
+- free(ports);
++void JackAudioAdapter::FreePorts()
++{
++ for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
++ if (fCapturePortList[i]) {
++ jack_port_unregister(fClient, fCapturePortList[i]);
+ }
+ }
+-
+- void JackAudioAdapter::Reset()
+- {
+- fAudioAdapter->Reset();
++ for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
++ if (fPlaybackPortList[i]) {
++ jack_port_unregister(fClient, fPlaybackPortList[i]);
++ }
+ }
+
+- int JackAudioAdapter::Open()
+- {
+- char name[32];
+- jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs());
+- fAudioAdapter->Create();
++ delete[] fCapturePortList;
++ delete[] fPlaybackPortList;
++}
+
+- //jack ports
+- fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()];
+- fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()];
++void JackAudioAdapter::ConnectPorts()
++{
++ const char** ports;
+
+- for (int i = 0; i < fAudioAdapter->GetInputs(); i++)
+- {
+- sprintf(name, "capture_%d", i + 1);
+- if ((fCapturePortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0)) == NULL)
+- goto fail;
++ ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
++ if (ports != NULL) {
++ for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) {
++ jack_connect(fClient, jack_port_name(fCapturePortList[i]), ports[i]);
+ }
++ jack_free(ports);
++ }
+
+- for (int i = 0; i < fAudioAdapter->GetOutputs(); i++)
+- {
+- sprintf(name, "playback_%d", i + 1);
+- if ((fPlaybackPortList[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 )) == NULL)
+- goto fail;
++ ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
++ if (ports != NULL) {
++ for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) {
++ jack_connect(fClient, ports[i], jack_port_name(fPlaybackPortList[i]));
+ }
++ jack_free(ports);
++ }
++}
+
+- //callbacks and activation
+- if ( jack_set_process_callback ( fJackClient, Process, this ) < 0 )
+- goto fail;
+- if ( jack_set_buffer_size_callback ( fJackClient, BufferSize, this ) < 0 )
+- goto fail;
+- if ( jack_set_sample_rate_callback ( fJackClient, SampleRate, this ) < 0 )
+- goto fail;
+- if ( jack_activate ( fJackClient ) < 0 )
++void JackAudioAdapter::Reset()
++{
++ fAudioAdapter->Reset();
++}
++
++int JackAudioAdapter::Open()
++{
++ char name[32];
++ jack_log("JackAudioAdapter::Open fCaptureChannels %d fPlaybackChannels %d", fAudioAdapter->GetInputs(), fAudioAdapter->GetOutputs());
++ fAudioAdapter->Create();
++
++ //jack ports
++ fCapturePortList = new jack_port_t*[fAudioAdapter->GetInputs()];
++ fPlaybackPortList = new jack_port_t*[fAudioAdapter->GetOutputs()];
++
++ for (int i = 0; i < fAudioAdapter->GetInputs(); i++) {
++ snprintf(name, sizeof(name), "capture_%d", i + 1);
++ if ((fCapturePortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, 0)) == NULL) {
+ goto fail;
++ }
++ }
+
+- if (fAutoConnect)
+- ConnectPorts();
++ for (int i = 0; i < fAudioAdapter->GetOutputs(); i++) {
++ snprintf(name, sizeof(name), "playback_%d", i + 1);
++ if ((fPlaybackPortList[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, 0)) == NULL) {
++ goto fail;
++ }
++ }
+
+- // Ring buffer are now allocated..
+- return fAudioAdapter->Open();
++ //callbacks and activation
++ if (jack_set_process_callback(fClient, Process, this) < 0) {
++ goto fail;
++ }
++ if (jack_set_buffer_size_callback(fClient, BufferSize, this) < 0) {
++ goto fail;
++ }
++ if (jack_set_sample_rate_callback(fClient, SampleRate, this) < 0) {
++ goto fail;
++ }
++ if (jack_set_latency_callback(fClient, Latency, this) < 0) {
++ goto fail;
++ }
++ if (jack_activate(fClient) < 0) {
++ goto fail;
++ }
+
+- fail:
+- FreePorts();
+- fAudioAdapter->Destroy();
+- return -1;
+- }
+-
+- int JackAudioAdapter::Close()
+- {
+- fAudioAdapter->Close();
+- fAudioAdapter->Destroy();
+- return 0;
++ if (fAutoConnect) {
++ ConnectPorts();
+ }
+
++ // Ring buffers are now allocated...
++ return fAudioAdapter->Open();
++ return 0;
++
++fail:
++ FreePorts();
++ fAudioAdapter->Destroy();
++ return -1;
++}
++
++int JackAudioAdapter::Close()
++{
++ fAudioAdapter->Close();
++ fAudioAdapter->Destroy();
++ return 0;
++}
++
+ } //namespace
+--- a/common/JackAudioAdapterFactory.cpp
++++ b/common/JackAudioAdapterFactory.cpp
+@@ -53,7 +53,7 @@
+ Jack::JackAudioAdapter* adapter;
+ jack_nframes_t buffer_size = jack_get_buffer_size(jack_client);
+ jack_nframes_t sample_rate = jack_get_sample_rate(jack_client);
+-
++
+ try {
+
+ #ifdef __linux__
+@@ -71,17 +71,16 @@
+ #if defined(__sun__) || defined(sun)
+ adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackOSSAdapter(buffer_size, sample_rate, params));
+ #endif
+-
+- assert(adapter);
+-
+- if (adapter->Open() == 0)
++
++ assert(adapter);
++
++ if (adapter->Open() == 0) {
+ return 0;
+- else
+- {
++ } else {
+ delete adapter;
+ return 1;
+ }
+-
++
+ } catch (...) {
+ return 1;
+ }
+@@ -94,13 +93,14 @@
+ int res = 1;
+ jack_driver_desc_t* desc = jack_get_descriptor();
+
+- Jack::JackArgParser parser ( load_init );
+- if ( parser.GetArgc() > 0 )
+- parse_params = parser.ParseParams ( desc, ¶ms );
++ Jack::JackArgParser parser(load_init);
++ if (parser.GetArgc() > 0) {
++ parse_params = parser.ParseParams(desc, ¶ms);
++ }
+
+ if (parse_params) {
+- res = jack_internal_initialize ( jack_client, params );
+- parser.FreeParams ( params );
++ res = jack_internal_initialize(jack_client, params);
++ parser.FreeParams(params);
+ }
+ return res;
+ }
+--- a/common/JackAudioAdapter.h
++++ b/common/JackAudioAdapter.h
+@@ -34,14 +34,15 @@
+ {
+ private:
+
+- static int Process ( jack_nframes_t, void* arg );
+- static int BufferSize ( jack_nframes_t buffer_size, void *arg );
+- static int SampleRate ( jack_nframes_t sample_rate, void *arg );
++ static int Process(jack_nframes_t, void* arg);
++ static int BufferSize(jack_nframes_t buffer_size, void* arg);
++ static int SampleRate(jack_nframes_t sample_rate, void* arg);
++ static void Latency(jack_latency_callback_mode_t mode, void* arg);
+
+ jack_port_t** fCapturePortList;
+ jack_port_t** fPlaybackPortList;
+
+- jack_client_t* fJackClient;
++ jack_client_t* fClient;
+ JackAudioAdapterInterface* fAudioAdapter;
+ bool fAutoConnect;
+
+@@ -51,7 +52,7 @@
+
+ public:
+
+- JackAudioAdapter(jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params = NULL, bool system = false);
++ JackAudioAdapter(jack_client_t* client, JackAudioAdapterInterface* audio_io, const JSList* params = NULL);
+ ~JackAudioAdapter();
+
+ int Open();
+@@ -60,4 +61,7 @@
+
+ }
+
++#define CaptureDriverFlags static_cast<JackPortFlags>(JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal)
++#define PlaybackDriverFlags static_cast<JackPortFlags>(JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal)
++
+ #endif
+--- a/common/JackAudioAdapterInterface.cpp
++++ b/common/JackAudioAdapterInterface.cpp
+@@ -17,9 +17,15 @@
+
+ */
+
++#ifdef __APPLE__
++#include <TargetConditionals.h>
++#endif
++
+ #include "JackAudioAdapter.h"
++#ifndef MY_TARGET_OS_IPHONE
+ #include "JackLibSampleRateResampler.h"
+-#include "JackTime.h"
++#endif
++#include "JackTime.h"
+ #include <stdio.h>
+
+ namespace Jack
+@@ -40,12 +46,10 @@
+
+ void MeasureTable::Save(unsigned int fHostBufferSize, unsigned int fHostSampleRate, unsigned int fAdaptedSampleRate, unsigned int fAdaptedBufferSize)
+ {
+- char buffer[1024];
+ FILE* file = fopen("JackAudioAdapter.log", "w");
+
+ int max = (fCount) % TABLE_MAX - 1;
+- for (int i = 1; i < max; i++)
+- {
++ for (int i = 1; i < max; i++) {
+ fprintf(file, "%d \t %d \t %d \t %f \t %f \t %d \t %d \n",
+ fTable[i].delta, fTable[i].time1, fTable[i].time2,
+ fTable[i].r1, fTable[i].r2, fTable[i].pos1, fTable[i].pos2);
+@@ -62,15 +66,13 @@
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+ fprintf(file, "set ylabel \"frames\"\n");
+ fprintf(file, "plot ");
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
+- fprintf(file, buffer);
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
+- fprintf(file, buffer);
+-
+- fprintf(file, "\n unset multiplot\n");
++ fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Ringbuffer error\" with lines,");
++ fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Ringbuffer error with timing correction\" with lines");
++
++ fprintf(file, "\n unset multiplot\n");
+ fprintf(file, "set output 'AdapterTiming1.svg\n");
+ fprintf(file, "set terminal svg\n");
+-
++
+ fprintf(file, "set multiplot\n");
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
+@@ -78,15 +80,13 @@
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+ fprintf(file, "set ylabel \"frames\"\n");
+ fprintf(file, "plot ");
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
+- fprintf(file, buffer);
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines\n");
+- fprintf(file, buffer);
++ fprintf(file, "\"JackAudioAdapter.log\" using 2 title \"Consumer interrupt period\" with lines,");
++ fprintf(file, "\"JackAudioAdapter.log\" using 3 title \"Producer interrupt period\" with lines\n");
+ fprintf(file, "unset multiplot\n");
+ fprintf(file, "unset output\n");
+-
++
+ fclose(file);
+-
++
+ // Adapter timing 2
+ file = fopen("AdapterTiming2.plot", "w");
+ fprintf(file, "set multiplot\n");
+@@ -96,15 +96,13 @@
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+ fprintf(file, "set ylabel \"resampling ratio\"\n");
+ fprintf(file, "plot ");
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
+- fprintf(file, buffer);
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
+- fprintf(file, buffer);
+-
+- fprintf(file, "\n unset multiplot\n");
++ fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
++ fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines");
++
++ fprintf(file, "\n unset multiplot\n");
+ fprintf(file, "set output 'AdapterTiming2.svg\n");
+ fprintf(file, "set terminal svg\n");
+-
++
+ fprintf(file, "set multiplot\n");
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
+@@ -112,13 +110,11 @@
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+ fprintf(file, "set ylabel \"resampling ratio\"\n");
+ fprintf(file, "plot ");
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
+- fprintf(file, buffer);
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
+- fprintf(file, buffer);
++ fprintf(file, "\"JackAudioAdapter.log\" using 4 title \"Ratio 1\" with lines,");
++ fprintf(file, "\"JackAudioAdapter.log\" using 5 title \"Ratio 2\" with lines\n");
+ fprintf(file, "unset multiplot\n");
+ fprintf(file, "unset output\n");
+-
++
+ fclose(file);
+
+ // Adapter timing 3
+@@ -130,15 +126,13 @@
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+ fprintf(file, "set ylabel \"frames\"\n");
+ fprintf(file, "plot ");
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
+- fprintf(file, buffer);
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
+- fprintf(file, buffer);
+-
+- fprintf(file, "\n unset multiplot\n");
++ fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
++ fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines");
++
++ fprintf(file, "\n unset multiplot\n");
+ fprintf(file, "set output 'AdapterTiming3.svg\n");
+ fprintf(file, "set terminal svg\n");
+-
++
+ fprintf(file, "set multiplot\n");
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"Audio adapter timing: host [rate = %.1f kHz buffer = %d frames] adapter [rate = %.1f kHz buffer = %d frames] \"\n"
+@@ -146,13 +140,11 @@
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+ fprintf(file, "set ylabel \"frames\"\n");
+ fprintf(file, "plot ");
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
+- fprintf(file, buffer);
+- sprintf(buffer, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
+- fprintf(file, buffer);
++ fprintf(file, "\"JackAudioAdapter.log\" using 6 title \"Frames position in consumer ringbuffer\" with lines,");
++ fprintf(file, "\"JackAudioAdapter.log\" using 7 title \"Frames position in producer ringbuffer\" with lines\n");
+ fprintf(file, "unset multiplot\n");
+ fprintf(file, "unset output\n");
+-
++
+ fclose(file);
+ }
+
+@@ -162,47 +154,56 @@
+ {
+ fRingbufferCurSize *= 2;
+ }
+-
++
+ void JackAudioAdapterInterface::AdaptRingBufferSize()
+ {
+- if (fHostBufferSize > fAdaptedBufferSize)
++ if (fHostBufferSize > fAdaptedBufferSize) {
+ fRingbufferCurSize = 4 * fHostBufferSize;
+- else
++ } else {
+ fRingbufferCurSize = 4 * fAdaptedBufferSize;
++ }
+ }
+-
++
+ void JackAudioAdapterInterface::ResetRingBuffers()
+ {
+- if (fRingbufferCurSize > DEFAULT_RB_SIZE)
++ if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
+ fRingbufferCurSize = DEFAULT_RB_SIZE;
+-
+- for (int i = 0; i < fCaptureChannels; i++)
++ }
++
++ for (int i = 0; i < fCaptureChannels; i++) {
+ fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
+- for (int i = 0; i < fPlaybackChannels; i++)
++ }
++ for (int i = 0; i < fPlaybackChannels; i++) {
+ fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
++ }
+ }
+-
++
+ void JackAudioAdapterInterface::Reset()
+ {
+ ResetRingBuffers();
+ fRunning = false;
+ }
+
++#ifdef MY_TARGET_OS_IPHONE
++ void JackAudioAdapterInterface::Create()
++ {}
++#else
+ void JackAudioAdapterInterface::Create()
+ {
+ //ringbuffers
+ fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
+ fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
+-
++
+ if (fAdaptative) {
+ AdaptRingBufferSize();
+ jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
+ } else {
+- if (fRingbufferCurSize > DEFAULT_RB_SIZE)
++ if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
+ fRingbufferCurSize = DEFAULT_RB_SIZE;
++ }
+ jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
+ }
+-
++
+ for (int i = 0; i < fCaptureChannels; i++ ) {
+ fCaptureRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
+ fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
+@@ -211,56 +212,68 @@
+ fPlaybackRingBuffer[i] = new JackLibSampleRateResampler(fQuality);
+ fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
+ }
+-
+- if (fCaptureChannels > 0)
++
++ if (fCaptureChannels > 0) {
+ jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
+- if (fPlaybackChannels > 0)
++ }
++ if (fPlaybackChannels > 0) {
+ jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
++ }
+ }
++#endif
+
+ void JackAudioAdapterInterface::Destroy()
+ {
+- for (int i = 0; i < fCaptureChannels; i++ )
+- delete ( fCaptureRingBuffer[i] );
+- for (int i = 0; i < fPlaybackChannels; i++ )
+- delete ( fPlaybackRingBuffer[i] );
++ for (int i = 0; i < fCaptureChannels; i++) {
++ delete(fCaptureRingBuffer[i]);
++ }
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ delete (fPlaybackRingBuffer[i]);
++ }
+
+ delete[] fCaptureRingBuffer;
+ delete[] fPlaybackRingBuffer;
+ }
+-
++
+ int JackAudioAdapterInterface::PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames)
+ {
+ bool failure = false;
+ fRunning = true;
+-
++
+ // 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 = 1;
+-
++
+ // TODO : done like this just to avoid crash when input only or output only...
+- if (fCaptureChannels > 0)
++ if (fCaptureChannels > 0) {
+ ratio = fPIControler.GetRatio(fCaptureRingBuffer[0]->GetError() - delta_frames);
+- else if (fPlaybackChannels > 0)
++ } else if (fPlaybackChannels > 0) {
+ ratio = fPIControler.GetRatio(fPlaybackRingBuffer[0]->GetError() - delta_frames);
+-
++ }
++
+ #ifdef JACK_MONITOR
+- if (fCaptureRingBuffer[0] != NULL)
++ if (fCaptureRingBuffer && 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
+ for (int i = 0; i < fCaptureChannels; i++) {
+ fCaptureRingBuffer[i]->SetRatio(ratio);
+- if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames)
+- failure = true;
++ if (inputBuffer[i]) {
++ if (fCaptureRingBuffer[i]->WriteResample(inputBuffer[i], frames) < frames) {
++ failure = true;
++ }
++ }
+ }
+
+ for (int i = 0; i < fPlaybackChannels; i++) {
+ fPlaybackRingBuffer[i]->SetRatio(1/ratio);
+- if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames)
+- failure = true;
++ if (outputBuffer[i]) {
++ if (fPlaybackRingBuffer[i]->ReadResample(outputBuffer[i], frames) < frames) {
++ failure = true;
++ }
++ }
+ }
+ // Reset all ringbuffers in case of failure
+ if (failure) {
+@@ -276,26 +289,32 @@
+ }
+ }
+
+- int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
++ int JackAudioAdapterInterface::PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames)
+ {
+ fPullAndPushTime = GetMicroSeconds();
+ if (!fRunning)
+ return 0;
+
+ int res = 0;
+-
++
+ // Push/pull from ringbuffer
+ for (int i = 0; i < fCaptureChannels; i++) {
+- if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames)
+- res = -1;
++ if (inputBuffer[i]) {
++ if (fCaptureRingBuffer[i]->Read(inputBuffer[i], frames) < frames) {
++ res = -1;
++ }
++ }
+ }
+
+ for (int i = 0; i < fPlaybackChannels; i++) {
+- if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames)
+- res = -1;
++ if (outputBuffer[i]) {
++ if (fPlaybackRingBuffer[i]->Write(outputBuffer[i], frames) < frames) {
++ res = -1;
++ }
++ }
+ }
+-
++
+ return res;
+ }
+-
++
+ } // namespace
+--- a/common/JackAudioAdapterInterface.h
++++ b/common/JackAudioAdapterInterface.h
+@@ -49,7 +49,7 @@
+ Measure fTable[TABLE_MAX];
+ int fCount;
+
+- MeasureTable() :fCount ( 0 )
++ MeasureTable() :fCount(0)
+ {}
+
+ void Write(int time1, int time2, float r1, float r2, int pos1, int pos2);
+@@ -102,17 +102,35 @@
+
+ public:
+
+- JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate ):
+- fCaptureChannels ( 0 ),
+- fPlaybackChannels ( 0 ),
+- fHostBufferSize ( buffer_size ),
+- fHostSampleRate ( sample_rate ),
+- fAdaptedBufferSize ( buffer_size),
+- fAdaptedSampleRate ( sample_rate ),
++ JackAudioAdapterInterface(jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE):
++ fCaptureChannels(0),
++ fPlaybackChannels(0),
++ fHostBufferSize(buffer_size),
++ fHostSampleRate(sample_rate),
++ fAdaptedBufferSize(buffer_size),
++ fAdaptedSampleRate(sample_rate),
+ fPIControler(sample_rate / sample_rate, 256),
+ fCaptureRingBuffer(NULL), fPlaybackRingBuffer(NULL),
+ fQuality(0),
+- fRingbufferCurSize(DEFAULT_ADAPTATIVE_SIZE),
++ fRingbufferCurSize(ring_buffer_size),
++ fPullAndPushTime(0),
++ fRunning(false),
++ fAdaptative(true)
++ {}
++ JackAudioAdapterInterface(jack_nframes_t host_buffer_size,
++ jack_nframes_t host_sample_rate,
++ jack_nframes_t adapted_buffer_size,
++ jack_nframes_t adapted_sample_rate,
++ jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE) :
++ fCaptureChannels(0),
++ fPlaybackChannels(0),
++ fHostBufferSize(host_buffer_size),
++ fHostSampleRate(host_sample_rate),
++ fAdaptedBufferSize(adapted_buffer_size),
++ fAdaptedSampleRate(adapted_sample_rate),
++ fPIControler(host_sample_rate / host_sample_rate, 256),
++ fQuality(0),
++ fRingbufferCurSize(ring_buffer_size),
+ fPullAndPushTime(0),
+ fRunning(false),
+ fAdaptative(true)
+@@ -123,8 +141,8 @@
+
+ virtual void Reset();
+
+- void Create();
+- void Destroy();
++ virtual void Create();
++ virtual void Destroy();
+
+ virtual int Open()
+ {
+@@ -136,76 +154,81 @@
+ return 0;
+ }
+
+- virtual int SetHostBufferSize ( jack_nframes_t buffer_size )
++ virtual int SetHostBufferSize(jack_nframes_t buffer_size)
+ {
+ fHostBufferSize = buffer_size;
+- if (fAdaptative)
++ if (fAdaptative) {
+ AdaptRingBufferSize();
++ }
+ return 0;
+ }
+
+- virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size )
++ virtual int SetAdaptedBufferSize(jack_nframes_t buffer_size)
+ {
+ fAdaptedBufferSize = buffer_size;
+- if (fAdaptative)
++ if (fAdaptative) {
+ AdaptRingBufferSize();
++ }
+ return 0;
+ }
+
+- virtual int SetBufferSize ( jack_nframes_t buffer_size )
++ virtual int SetBufferSize(jack_nframes_t buffer_size)
+ {
+- SetHostBufferSize ( buffer_size );
+- SetAdaptedBufferSize ( buffer_size );
++ SetHostBufferSize(buffer_size);
++ SetAdaptedBufferSize(buffer_size);
+ return 0;
+ }
+
+- virtual int SetHostSampleRate ( jack_nframes_t sample_rate )
++ virtual int SetHostSampleRate(jack_nframes_t sample_rate)
+ {
+ fHostSampleRate = sample_rate;
+ fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
+ return 0;
+ }
+
+- virtual int SetAdaptedSampleRate ( jack_nframes_t sample_rate )
++ virtual int SetAdaptedSampleRate(jack_nframes_t sample_rate)
+ {
+ fAdaptedSampleRate = sample_rate;
+ fPIControler.Init(double(fHostSampleRate) / double(fAdaptedSampleRate));
+ return 0;
+ }
+
+- virtual int SetSampleRate ( jack_nframes_t sample_rate )
++ virtual int SetSampleRate(jack_nframes_t sample_rate)
+ {
+- SetHostSampleRate ( sample_rate );
+- SetAdaptedSampleRate ( sample_rate );
++ SetHostSampleRate(sample_rate);
++ SetAdaptedSampleRate(sample_rate);
+ return 0;
+ }
+
+- void SetInputs ( int inputs )
++ void SetInputs(int inputs)
+ {
+- jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs );
++ jack_log("JackAudioAdapterInterface::SetInputs %d", inputs);
+ fCaptureChannels = inputs;
+ }
+
+- void SetOutputs ( int outputs )
++ void SetOutputs(int outputs)
+ {
+- jack_log ( "JackAudioAdapterInterface::SetOutputs %d", outputs );
++ jack_log("JackAudioAdapterInterface::SetOutputs %d", outputs);
+ fPlaybackChannels = outputs;
+ }
+
+ int GetInputs()
+ {
+- jack_log ( "JackAudioAdapterInterface::GetInputs %d", fCaptureChannels );
++ //jack_log("JackAudioAdapterInterface::GetInputs %d", fCaptureChannels);
+ return fCaptureChannels;
+ }
+
+ int GetOutputs()
+ {
+- jack_log ( "JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels );
++ //jack_log ("JackAudioAdapterInterface::GetOutputs %d", fPlaybackChannels);
+ return fPlaybackChannels;
+ }
+
+- int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames);
+- int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int inNumberFrames);
++ virtual int GetInputLatency(int port_index) { return 0; }
++ virtual int GetOutputLatency(int port_index) { return 0; }
++
++ int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames);
++ int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames);
+
+ };
+
+--- a/common/JackAudioDriver.cpp
++++ b/common/JackAudioDriver.cpp
+@@ -29,14 +29,13 @@
+ #include "JackException.h"
+ #include <assert.h>
+
++using namespace std;
++
+ namespace Jack
+ {
+
+ JackAudioDriver::JackAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+- : JackDriver(name, alias, engine, table),
+- fCaptureChannels(0),
+- fPlaybackChannels(0),
+- fWithMonitorPorts(false)
++ : JackDriver(name, alias, engine, table)
+ {}
+
+ JackAudioDriver::~JackAudioDriver()
+@@ -44,21 +43,29 @@
+
+ int JackAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
+ {
++ // Update engine and graph manager state
+ fEngineControl->fBufferSize = buffer_size;
+ fGraphManager->SetBufferSize(buffer_size);
+ fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
+- if (!fEngineControl->fTimeOut)
++ if (!fEngineControl->fTimeOut) {
+ fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
+- return 0;
++ }
++
++ UpdateLatencies();
++
++ // Redirect on slaves drivers...
++ return JackDriver::SetBufferSize(buffer_size);
+ }
+
+ int JackAudioDriver::SetSampleRate(jack_nframes_t sample_rate)
+ {
+ fEngineControl->fSampleRate = sample_rate;
+ fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
+- if (!fEngineControl->fTimeOut)
++ if (!fEngineControl->fTimeOut) {
+ fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
+- return 0;
++ }
++
++ return JackDriver::SetSampleRate(sample_rate);
+ }
+
+ int JackAudioDriver::Open(jack_nframes_t buffer_size,
+@@ -76,7 +83,11 @@
+ fCaptureChannels = inchannels;
+ fPlaybackChannels = outchannels;
+ fWithMonitorPorts = monitor;
+- return JackDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
++ memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
++ memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
++ memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
++ return JackDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels,
++ monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
+ }
+
+ int JackAudioDriver::Open(bool capturing,
+@@ -92,66 +103,88 @@
+ fCaptureChannels = inchannels;
+ fPlaybackChannels = outchannels;
+ fWithMonitorPorts = monitor;
+- return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
++ memset(fCapturePortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
++ memset(fPlaybackPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
++ memset(fMonitorPortList, 0, sizeof(jack_port_id_t) * DRIVER_PORT_NUM);
++ return JackDriver::Open(capturing, playing, inchannels, outchannels,
++ monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
++}
++
++void JackAudioDriver::UpdateLatencies()
++{
++ jack_latency_range_t input_range;
++ jack_latency_range_t output_range;
++ jack_latency_range_t monitor_range;
++
++ for (int i = 0; i < fCaptureChannels; i++) {
++ input_range.max = input_range.min = fEngineControl->fBufferSize + fCaptureLatency;
++ fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
++ }
++
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ output_range.max = output_range.min = fPlaybackLatency;
++ if (fEngineControl->fSyncMode) {
++ output_range.max = output_range.min += fEngineControl->fBufferSize;
++ } else {
++ output_range.max = output_range.min += fEngineControl->fBufferSize * 2;
++ }
++ fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
++ if (fWithMonitorPorts) {
++ monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
++ fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
++ }
++ }
+ }
+
+ int JackAudioDriver::Attach()
+ {
+ JackPort* port;
+ jack_port_id_t port_index;
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- jack_latency_range_t range;
++ char name[REAL_JACK_PORT_NAME_SIZE];
++ char alias[REAL_JACK_PORT_NAME_SIZE];
+ int i;
+
+ jack_log("JackAudioDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
+
+ for (i = 0; i < fCaptureChannels; i++) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
+- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
++ snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+ port = fGraphManager->GetPort(port_index);
+ port->SetAlias(alias);
+- range.min = range.max = fEngineControl->fBufferSize + fCaptureLatency;
+- port->SetLatencyRange(JackCaptureLatency, &range);
+ fCapturePortList[i] = port_index;
+ jack_log("JackAudioDriver::Attach fCapturePortList[i] port_index = %ld", port_index);
+ }
+
+ for (i = 0; i < fPlaybackChannels; i++) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
+- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
++ snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+ port = fGraphManager->GetPort(port_index);
+ port->SetAlias(alias);
+- // Add more latency if "async" mode is used...
+- range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + fPlaybackLatency;
+- port->SetLatencyRange(JackPlaybackLatency, &range);
+ fPlaybackPortList[i] = port_index;
+ jack_log("JackAudioDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index);
+
+ // Monitor ports
+ if (fWithMonitorPorts) {
+ jack_log("Create monitor port");
+- 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) {
++ snprintf(name, sizeof(name), "%s:monitor_%u", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("Cannot register monitor port for %s", name);
+ return -1;
+ } else {
+- port = fGraphManager->GetPort(port_index);
+- range.min = range.max = fEngineControl->fBufferSize;
+- port->SetLatencyRange(JackCaptureLatency, &range);
+- fMonitorPortList[i] = port_index;
++ fMonitorPortList[i] = port_index;
+ }
+ }
+ }
+
++ UpdateLatencies();
+ return 0;
+ }
+
+@@ -161,13 +194,14 @@
+ jack_log("JackAudioDriver::Detach");
+
+ for (i = 0; i < fCaptureChannels; i++) {
+- fGraphManager->ReleasePort(fClientControl.fRefNum, fCapturePortList[i]);
++ fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[i]);
+ }
+
+ for (i = 0; i < fPlaybackChannels; i++) {
+- fGraphManager->ReleasePort(fClientControl.fRefNum, fPlaybackPortList[i]);
+- if (fWithMonitorPorts)
+- fGraphManager->ReleasePort(fClientControl.fRefNum, fMonitorPortList[i]);
++ fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[i]);
++ if (fWithMonitorPorts) {
++ fEngine->PortUnRegister(fClientControl.fRefNum, fMonitorPortList[i]);
++ }
+ }
+
+ return 0;
+@@ -187,26 +221,19 @@
+ return 0;
+ }
+
+-int JackAudioDriver::ProcessNull()
++int JackAudioDriver::Process()
+ {
+- // Keep begin cycle time
+- JackDriver::CycleTakeBeginTime();
+-
+- if (fEngineControl->fSyncMode) {
+- ProcessGraphSync();
+- } else {
+- ProcessGraphAsync();
+- }
+-
+- // Keep end cycle time
+- JackDriver::CycleTakeEndTime();
+- WaitUntilNextCycle();
+- return 0;
++ return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
+ }
+
+-int JackAudioDriver::Process()
++void JackAudioDriver::ProcessGraphAsync()
+ {
+- return (fEngineControl->fSyncMode) ? ProcessSync() : ProcessAsync();
++ // Process graph
++ if (fIsMaster) {
++ ProcessGraphAsyncMaster();
++ } else {
++ ProcessGraphAsyncSlave();
++ }
+ }
+
+ /*
+@@ -229,17 +256,30 @@
+ }
+
+ // Process graph
+- if (fIsMaster) {
+- ProcessGraphAsync();
+- } else {
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
+- }
++ ProcessGraphAsync();
+
+ // Keep end cycle time
+ JackDriver::CycleTakeEndTime();
+ return 0;
+ }
+
++void JackAudioDriver::ProcessGraphSync()
++{
++ // Process graph
++ if (fIsMaster) {
++ if (ProcessGraphSyncMaster() < 0) {
++ //jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
++ //goto end;
++ }
++ } else {
++ if (ProcessGraphSyncSlave() < 0) {
++ //jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
++ //goto end;
++ }
++ }
++}
++
++
+ /*
+ The driver SYNC mode: the server does synchronize to the end of client graph execution,
+ if graph process succeed, output buffers computed at the *current cycle* are used.
+@@ -254,17 +294,7 @@
+ }
+
+ // Process graph
+- if (fIsMaster) {
+- if (ProcessGraphSync() < 0) {
+- jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
+- goto end;
+- }
+- } else {
+- if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
+- jack_error("JackAudioDriver::ProcessSync: process error, skip cycle...");
+- goto end;
+- }
+- }
++ ProcessGraphSync();
+
+ // Write output buffers from the current cycle
+ if (Write() < 0) {
+@@ -272,34 +302,55 @@
+ return -1;
+ }
+
+-end:
+-
+ // Keep end cycle time
+ JackDriver::CycleTakeEndTime();
+ return 0;
+ }
+
+-void JackAudioDriver::ProcessGraphAsync()
++void JackAudioDriver::ProcessGraphAsyncMaster()
+ {
+ // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle
+ if (!fEngine->Process(fBeginDateUst, fEndDateUst))
+- jack_error("JackAudioDriver::ProcessGraphAsync: Process error");
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
+- if (ProcessSlaves() < 0)
+- jack_error("JackAudioDriver::ProcessGraphAsync: ProcessSlaves error");
++ jack_error("JackAudioDriver::ProcessGraphAsyncMaster: Process error");
++
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0)
++ jack_error("JackAudioDriver::ProcessGraphAsyncMaster: ResumeRefNum error");
++
++ if (ProcessReadSlaves() < 0)
++ jack_error("JackAudioDriver::ProcessGraphAsyncMaster: ProcessReadSlaves error");
++
++ if (ProcessWriteSlaves() < 0)
++ jack_error("JackAudioDriver::ProcessGraphAsyncMaster: ProcessWriteSlaves error");
+ }
+
+-int JackAudioDriver::ProcessGraphSync()
++void JackAudioDriver::ProcessGraphAsyncSlave()
++{
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0)
++ jack_error("JackAudioDriver::ProcessGraphAsyncSlave: ResumeRefNum error");
++}
++
++int JackAudioDriver::ProcessGraphSyncMaster()
+ {
+ int res = 0;
+
+ // fBeginDateUst is set in the "low level" layer, fEndDateUst is from previous cycle
+ if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
+- if (ProcessSlaves() < 0) {
+- jack_error("JackAudioDriver::ProcessGraphSync: ProcessSlaves error, engine may now behave abnormally!!");
++
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
++ jack_error("JackAudioDriver::ProcessGraphSyncMaster: ResumeRefNum error");
++ res = -1;
++ }
++
++ if (ProcessReadSlaves() < 0) {
++ jack_error("JackAudioDriver::ProcessGraphSync: ProcessReadSlaves error, engine may now behave abnormally!!");
++ res = -1;
++ }
++
++ if (ProcessWriteSlaves() < 0) {
++ jack_error("JackAudioDriver::ProcessGraphSync: ProcessWriteSlaves error, engine may now behave abnormally!!");
+ res = -1;
+ }
++
+ if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
+ jack_error("JackAudioDriver::ProcessGraphSync: SuspendRefNum error, engine may now behave abnormally!!");
+ res = -1;
+@@ -312,6 +363,11 @@
+ return res;
+ }
+
++int JackAudioDriver::ProcessGraphSyncSlave()
++{
++ return fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
++}
++
+ int JackAudioDriver::Start()
+ {
+ int res = JackDriver::Start();
+@@ -332,30 +388,25 @@
+ return res;
+ }
+
+-void JackAudioDriver::WaitUntilNextCycle()
+-{
+- int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f));
+- wait_time_usec = int(wait_time_usec - (GetMicroSeconds() - fBeginDateUst));
+- if (wait_time_usec > 0)
+- JackSleep(wait_time_usec);
+-}
+-
+ jack_default_audio_sample_t* JackAudioDriver::GetInputBuffer(int port_index)
+ {
+- assert(fCapturePortList[port_index]);
+- return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize);
++ return fCapturePortList[port_index]
++ ? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fCapturePortList[port_index], fEngineControl->fBufferSize)
++ : NULL;
+ }
+
+ jack_default_audio_sample_t* JackAudioDriver::GetOutputBuffer(int port_index)
+ {
+- assert(fPlaybackPortList[port_index]);
+- return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize);
++ return fPlaybackPortList[port_index]
++ ? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fPlaybackPortList[port_index], fEngineControl->fBufferSize)
++ : NULL;
+ }
+
+ jack_default_audio_sample_t* JackAudioDriver::GetMonitorBuffer(int port_index)
+ {
+- assert(fPlaybackPortList[port_index]);
+- return (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize);
++ return fPlaybackPortList[port_index]
++ ? (jack_default_audio_sample_t*)fGraphManager->GetBuffer(fMonitorPortList[port_index], fEngineControl->fBufferSize)
++ : NULL;
+ }
+
+ int JackAudioDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
+--- a/common/JackAudioDriver.h
++++ b/common/JackAudioDriver.h
+@@ -35,29 +35,22 @@
+
+ protected:
+
+- void ProcessGraphAsync();
+- int ProcessGraphSync();
+- void WaitUntilNextCycle();
+-
+- virtual int ProcessAsync();
+- virtual int ProcessSync();
+-
+- int fCaptureChannels;
+- int fPlaybackChannels;
+-
+- // Static tables since the actual number of ports may be changed by the real driver
+- // thus dynamic allocation is more difficult to handle
+- jack_port_id_t fCapturePortList[DRIVER_PORT_NUM];
+- jack_port_id_t fPlaybackPortList[DRIVER_PORT_NUM];
+- jack_port_id_t fMonitorPortList[DRIVER_PORT_NUM];
+-
+- bool fWithMonitorPorts;
+-
+ jack_default_audio_sample_t* GetInputBuffer(int port_index);
+ jack_default_audio_sample_t* GetOutputBuffer(int port_index);
+ jack_default_audio_sample_t* GetMonitorBuffer(int port_index);
+
+ void HandleLatencyCallback(int status);
++ virtual void UpdateLatencies();
++
++ int ProcessAsync();
++ void ProcessGraphAsync();
++ void ProcessGraphAsyncMaster();
++ void ProcessGraphAsyncSlave();
++
++ int ProcessSync();
++ void ProcessGraphSync();
++ int ProcessGraphSyncMaster();
++ int ProcessGraphSyncSlave();
+
+ public:
+
+@@ -87,7 +80,6 @@
+ jack_nframes_t playback_latency);
+
+ virtual int Process();
+- virtual int ProcessNull();
+
+ virtual int Attach();
+ virtual int Detach();
+--- a/common/JackChannel.h
++++ b/common/JackChannel.h
+@@ -20,7 +20,8 @@
+ #ifndef __JackChannel__
+ #define __JackChannel__
+
+-#include "session.h"
++#include "types.h"
++#include "JackSession.h"
+
+ namespace Jack
+ {
+@@ -73,7 +74,7 @@
+ return -1;
+ }
+
+- virtual void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result)
++ virtual void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open)
+ {}
+ virtual void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result)
+ {}
+--- a/common/JackClientControl.h
++++ b/common/JackClientControl.h
+@@ -25,7 +25,7 @@
+ #include "JackPort.h"
+ #include "JackSynchro.h"
+ #include "JackNotification.h"
+-#include "session.h"
++#include "JackSession.h"
+
+ namespace Jack
+ {
+@@ -34,6 +34,7 @@
+ \brief Client control possibly in shared memory.
+ */
+
++PRE_PACKED_STRUCTURE
+ struct JackClientControl : public JackShmMemAble
+ {
+ char fName[JACK_CLIENT_NAME_SIZE + 1];
+--- a/common/JackClient.cpp
++++ b/common/JackClient.cpp
+@@ -81,6 +81,8 @@
+ fThreadFunArg = NULL;
+ fSessionArg = NULL;
+ fLatencyArg = NULL;
++
++ fSessionReply = kPendingSessionReply;
+ }
+
+ JackClient::~JackClient()
+@@ -149,6 +151,8 @@
+ {
+ int res = 0;
+
++ jack_log("JackClient::ClientNotify ref = %ld name = %s notify = %ld", refnum, name, notify);
++
+ // Done all time: redirected on subclass implementation JackLibClient and JackInternalClient
+ switch (notify) {
+
+@@ -284,17 +288,18 @@
+ case kSessionCallback:
+ jack_log("JackClient::kSessionCallback");
+ if (fSession) {
+- jack_session_event_t *event = (jack_session_event_t *) malloc( sizeof(jack_session_event_t) );
++ jack_session_event_t* event = (jack_session_event_t*)malloc( sizeof(jack_session_event_t));
+ char uuid_buf[JACK_UUID_SIZE];
+- event->type = (jack_session_event_type_t) value1;
+- event->session_dir = strdup( message );
++ event->type = (jack_session_event_type_t)value1;
++ event->session_dir = strdup(message);
+ event->command_line = NULL;
+- event->flags = (jack_session_flags_t) 0;
+- snprintf( uuid_buf, sizeof(uuid_buf), "%d", GetClientControl()->fSessionID );
+- event->client_uuid = strdup( uuid_buf );
+- fImmediateSessionReply = false;
++ event->flags = (jack_session_flags_t)0;
++ snprintf(uuid_buf, sizeof(uuid_buf), "%d", GetClientControl()->fSessionID);
++ event->client_uuid = strdup(uuid_buf);
++ fSessionReply = kPendingSessionReply;
++ // Session callback may change fSessionReply by directly using jack_session_reply
+ fSession(event, fSessionArg);
+- res = (fImmediateSessionReply) ? 1 : 2;
++ res = fSessionReply;
+ }
+ break;
+
+@@ -642,7 +647,7 @@
+
+ // Check port name length
+ string name = string(GetClientControl()->fName) + string(":") + port_name_str;
+- if (name.size() >= JACK_PORT_NAME_SIZE) {
++ if (name.size() >= REAL_JACK_PORT_NAME_SIZE) {
+ jack_error("\"%s:%s\" is too long to be used as a JACK port name.\n"
+ "Please use %lu characters or less",
+ GetClientControl()->fName,
+@@ -843,14 +848,14 @@
+ GetEngineControl()->fTransport.RequestNewPos(&pos);
+ }
+
+-int JackClient::TransportReposition(jack_position_t* pos)
++int JackClient::TransportReposition(const jack_position_t* pos)
+ {
+ jack_position_t tmp = *pos;
+ jack_log("JackClient::TransportReposition pos = %ld", pos->frame);
+ if (tmp.valid & ~JACK_POSITION_MASK) {
+ return EINVAL;
+ } else {
+- GetEngineControl()->fTransport.RequestNewPos(pos);
++ GetEngineControl()->fTransport.RequestNewPos(&tmp);
+ return 0;
+ }
+ }
+@@ -1232,8 +1237,9 @@
+
+ jack_log("JackClient::SessionReply... we are here");
+ if (fChannel->IsChannelThread()) {
+- jack_log( "JackClient::SessionReply... in callback reply");
+- fImmediateSessionReply = true;
++ jack_log("JackClient::SessionReply... in callback reply");
++ // OK, immediate reply...
++ fSessionReply = kImmediateSessionReply;
+ return 0;
+ }
+
+--- a/common/JackClient.h
++++ b/common/JackClient.h
+@@ -27,7 +27,6 @@
+ #include "JackSynchro.h"
+ #include "JackPlatformPlug.h"
+ #include "JackChannel.h"
+-#include "session.h"
+ #include "varargs.h"
+ #include <list>
+
+@@ -94,7 +93,7 @@
+ JackSynchro* fSynchroTable;
+ std::list<jack_port_id_t> fPortList;
+
+- bool fImmediateSessionReply;
++ JackSessionReply fSessionReply;
+
+ int StartThread();
+ void SetupDriverSync(bool freewheel);
+@@ -165,7 +164,7 @@
+ virtual void TransportLocate(jack_nframes_t frame);
+ virtual jack_transport_state_t TransportQuery(jack_position_t* pos);
+ virtual jack_nframes_t GetCurrentTransportFrame();
+- virtual int TransportReposition(jack_position_t* pos);
++ virtual int TransportReposition(const jack_position_t* pos);
+ virtual void TransportStart();
+ virtual void TransportStop();
+
+--- a/common/JackConnectionManager.h
++++ b/common/JackConnectionManager.h
+@@ -36,6 +36,7 @@
+ \brief Utility class.
+ */
+
++PRE_PACKED_STRUCTURE
+ template <int SIZE>
+ class JackFixedArray
+ {
+@@ -122,6 +123,7 @@
+ \brief Utility class.
+ */
+
++PRE_PACKED_STRUCTURE
+ template <int SIZE>
+ class JackFixedArray1 : public JackFixedArray<SIZE>
+ {
+@@ -158,6 +160,7 @@
+ \brief Utility class.
+ */
+
++PRE_PACKED_STRUCTURE
+ template <int SIZE>
+ class JackFixedMatrix
+ {
+@@ -253,6 +256,7 @@
+ \brief Utility class.
+ */
+
++PRE_PACKED_STRUCTURE
+ template <int SIZE>
+ class JackLoopFeedback
+ {
+@@ -366,6 +370,7 @@
+ \brief For client timing measurements.
+ */
+
++PRE_PACKED_STRUCTURE
+ struct JackClientTiming
+ {
+ jack_time_t fSignaledAt;
+@@ -402,6 +407,7 @@
+ </UL>
+ */
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackConnectionManager
+ {
+
+--- a/common/JackConstants.h
++++ b/common/JackConstants.h
+@@ -24,7 +24,7 @@
+ #include "config.h"
+ #endif
+
+-#define VERSION "1.9.7"
++#define VERSION "1.9.8"
+
+ #define BUFFER_SIZE_MAX 8192
+
+@@ -36,6 +36,8 @@
+ #define JACK_UUID_SIZE 32
+ #define JACK_SESSION_COMMAND_SIZE 256
+
++#define REAL_JACK_PORT_NAME_SIZE JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE
++
+ #ifndef PORT_NUM
+ #define PORT_NUM 2048
+ #endif
+@@ -71,7 +73,7 @@
+ #define SOCKET_TIME_OUT 5 // in sec
+ #define DRIVER_OPEN_TIMEOUT 5 // in sec
+ #define FREEWHEEL_DRIVER_TIMEOUT 10 // in sec
+-#define DRIVER_TIMEOUT_FACTOR 10
++#define DRIVER_TIMEOUT_FACTOR 10
+
+
+ #define NO_PORT 0xFFFE
+--- a/common/JackControlAPI.cpp
++++ b/common/JackControlAPI.cpp
+@@ -101,7 +101,7 @@
+ jack_driver_desc_t * desc_ptr;
+ JSList * parameters;
+ JSList * set_parameters;
+- JackDriverInfo* info;
++ JSList * infos;
+ };
+
+ struct jackctl_internal
+@@ -215,7 +215,8 @@
+ jackctl_add_driver_parameters(
+ struct jackctl_driver * driver_ptr)
+ {
+- uint32_t i;
++ unsigned int i;
++
+ union jackctl_parameter_value jackctl_value;
+ jackctl_param_type_t jackctl_type;
+ struct jackctl_parameter * parameter_ptr;
+@@ -308,6 +309,7 @@
+ driver_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
+ driver_ptr->parameters = NULL;
+ driver_ptr->set_parameters = NULL;
++ driver_ptr->infos = NULL;
+
+ if (!jackctl_add_driver_parameters(driver_ptr))
+ {
+@@ -377,6 +379,7 @@
+ internal_ptr->desc_ptr = (jack_driver_desc_t *)descriptor_node_ptr->data;
+ internal_ptr->parameters = NULL;
+ internal_ptr->set_parameters = NULL;
++ internal_ptr->refnum = -1;
+
+ if (!jackctl_add_driver_parameters((struct jackctl_driver *)internal_ptr))
+ {
+@@ -483,7 +486,7 @@
+ snprintf (buf, sizeof(buf), "received signal %d during shutdown (ignored)\n", sig);
+ }
+
+-EXPORT sigset_t
++SERVER_EXPORT sigset_t
+ jackctl_setup_signals(
+ unsigned int flags)
+ {
+@@ -561,7 +564,7 @@
+ return signals;
+ }
+
+-EXPORT void
++SERVER_EXPORT void
+ jackctl_wait_signals(sigset_t signals)
+ {
+ int sig;
+@@ -628,7 +631,7 @@
+ return constraint_ptr;
+ }
+
+-EXPORT jackctl_server_t * jackctl_server_create(
++SERVER_EXPORT jackctl_server_t * jackctl_server_create(
+ bool (* on_device_acquire)(const char * device_name),
+ void (* on_device_release)(const char * device_name))
+ {
+@@ -661,7 +664,7 @@
+ goto fail_free_parameters;
+ }
+
+- value.b = false;
++ value.b = true;
+ if (jackctl_add_parameter(
+ &server_ptr->parameters,
+ "realtime",
+@@ -810,115 +813,134 @@
+ return NULL;
+ }
+
+-EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
++SERVER_EXPORT void jackctl_server_destroy(jackctl_server *server_ptr)
+ {
+- jackctl_server_free_drivers(server_ptr);
+- jackctl_server_free_internals(server_ptr);
+- jackctl_server_free_parameters(server_ptr);
+- free(server_ptr);
++ if (server_ptr) {
++ jackctl_server_free_drivers(server_ptr);
++ jackctl_server_free_internals(server_ptr);
++ jackctl_server_free_parameters(server_ptr);
++ free(server_ptr);
++ }
+ }
+
+-EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
++SERVER_EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr)
+ {
+- return server_ptr->drivers;
++ return (server_ptr) ? server_ptr->drivers : NULL;
+ }
+
+-EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
++SERVER_EXPORT bool jackctl_server_stop(jackctl_server *server_ptr)
+ {
+- server_ptr->engine->Stop();
+- return true;
++ if (server_ptr) {
++ server_ptr->engine->Stop();
++ return true;
++ } else {
++ return false;
++ }
+ }
+
+-EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
++SERVER_EXPORT bool jackctl_server_close(jackctl_server *server_ptr)
+ {
+- server_ptr->engine->Close();
+- delete server_ptr->engine;
++ if (server_ptr) {
++ server_ptr->engine->Close();
++ delete server_ptr->engine;
+
+- /* clean up shared memory and files from this server instance */
+- jack_log("cleaning up shared memory");
++ /* clean up shared memory and files from this server instance */
++ jack_log("cleaning up shared memory");
+
+- jack_cleanup_shm();
++ jack_cleanup_shm();
+
+- jack_log("cleaning up files");
++ jack_log("cleaning up files");
+
+- JackTools::CleanupFiles(server_ptr->name.str);
++ JackTools::CleanupFiles(server_ptr->name.str);
+
+- jack_log("unregistering server `%s'", server_ptr->name.str);
++ jack_log("unregistering server `%s'", server_ptr->name.str);
+
+- jack_unregister_server(server_ptr->name.str);
++ jack_unregister_server(server_ptr->name.str);
+
+- server_ptr->engine = NULL;
++ server_ptr->engine = NULL;
+
+- return true;
++ return true;
++ } else {
++ return false;
++ }
+ }
+
+-EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
++SERVER_EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr)
+ {
+- return server_ptr->parameters;
++ return (server_ptr) ? server_ptr->parameters : NULL;
+ }
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_open(
+ jackctl_server *server_ptr,
+ jackctl_driver *driver_ptr)
+ {
+- int rc;
++ try {
+
+- rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
+- switch (rc)
+- {
+- case EEXIST:
+- jack_error("`%s' server already active", server_ptr->name.str);
+- goto fail;
+- case ENOSPC:
+- jack_error("too many servers already active");
+- goto fail;
+- case ENOMEM:
+- jack_error("no access to shm registry");
+- goto fail;
+- }
++ if (!server_ptr || !driver_ptr) {
++ return false;
++ }
+
+- jack_log("server `%s' registered", server_ptr->name.str);
++ int rc = jack_register_server(server_ptr->name.str, server_ptr->replace_registry.b);
++ switch (rc)
++ {
++ case EEXIST:
++ jack_error("`%s' server already active", server_ptr->name.str);
++ goto fail;
++ case ENOSPC:
++ jack_error("too many servers already active");
++ goto fail;
++ case ENOMEM:
++ jack_error("no access to shm registry");
++ goto fail;
++ }
+
+- /* clean up shared memory and files from any previous
+- * instance of this server name */
+- jack_cleanup_shm();
+- JackTools::CleanupFiles(server_ptr->name.str);
++ jack_log("server `%s' registered", server_ptr->name.str);
+
+- if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0)
+- server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */
++ /* clean up shared memory and files from any previous
++ * instance of this server name */
++ jack_cleanup_shm();
++ JackTools::CleanupFiles(server_ptr->name.str);
+
+- /* check port max value before allocating server */
+- if (server_ptr->port_max.ui > PORT_NUM_MAX) {
+- jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX);
+- goto fail;
+- }
++ if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) {
++ server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */
++ }
+
+- /* get the engine/driver started */
+- server_ptr->engine = new JackServer(
+- server_ptr->sync.b,
+- server_ptr->temporary.b,
+- server_ptr->client_timeout.i,
+- server_ptr->realtime.b,
+- server_ptr->realtime_priority.i,
+- server_ptr->port_max.ui,
+- server_ptr->verbose.b,
+- (jack_timer_type_t)server_ptr->clock_source.ui,
+- server_ptr->name.str);
+- if (server_ptr->engine == NULL)
+- {
+- jack_error("Failed to create new JackServer object");
+- goto fail_unregister;
+- }
++ /* check port max value before allocating server */
++ if (server_ptr->port_max.ui > PORT_NUM_MAX) {
++ jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX);
++ goto fail;
++ }
+
+- rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
+- if (rc < 0)
+- {
+- jack_error("JackServer::Open() failed with %d", rc);
+- goto fail_delete;
+- }
++ /* get the engine/driver started */
++ server_ptr->engine = new JackServer(
++ server_ptr->sync.b,
++ server_ptr->temporary.b,
++ server_ptr->client_timeout.i,
++ server_ptr->realtime.b,
++ server_ptr->realtime_priority.i,
++ server_ptr->port_max.ui,
++ server_ptr->verbose.b,
++ (jack_timer_type_t)server_ptr->clock_source.ui,
++ server_ptr->name.str);
++ if (server_ptr->engine == NULL)
++ {
++ jack_error("Failed to create new JackServer object");
++ goto fail_unregister;
++ }
+
+- return true;
++ rc = server_ptr->engine->Open(driver_ptr->desc_ptr, driver_ptr->set_parameters);
++ if (rc < 0)
++ {
++ jack_error("JackServer::Open() failed with %d", rc);
++ goto fail_delete;
++ }
++
++ return true;
++
++ } catch (std::exception e) {
++ jack_error("jackctl_server_open error...");
++ }
+
+ fail_delete:
+ delete server_ptr->engine;
+@@ -941,74 +963,92 @@
+ return false;
+ }
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_start(
+ jackctl_server *server_ptr)
+ {
+- int rc = server_ptr->engine->Start();
+- bool result = rc >= 0;
+- if (! result)
+- {
+- jack_error("JackServer::Start() failed with %d", rc);
++ if (!server_ptr) {
++ return false;
++ } else {
++ int rc = server_ptr->engine->Start();
++ bool result = rc >= 0;
++ if (! result)
++ {
++ jack_error("JackServer::Start() failed with %d", rc);
++ }
++ return result;
+ }
+- return result;
+ }
+
+-EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
++SERVER_EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr)
+ {
+- return driver_ptr->desc_ptr->name;
++ return (driver_ptr) ? driver_ptr->desc_ptr->name : NULL;
+ }
+
+-EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
++SERVER_EXPORT jackctl_driver_type_t jackctl_driver_get_type(jackctl_driver *driver_ptr)
+ {
+- return driver_ptr->parameters;
++ return (driver_ptr) ? (jackctl_driver_type_t)driver_ptr->desc_ptr->type : (jackctl_driver_type_t)0;
+ }
+
+-EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
++SERVER_EXPORT const JSList * jackctl_driver_get_parameters(jackctl_driver *driver_ptr)
+ {
+- return driver_ptr->desc_ptr;
++ return (driver_ptr) ? driver_ptr->parameters : NULL;
+ }
+
+-EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver *driver_ptr)
+ {
+- return parameter_ptr->name;
++ return (driver_ptr) ? driver_ptr->desc_ptr : NULL;
+ }
+
+-EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT const char * jackctl_parameter_get_name(jackctl_parameter *parameter_ptr)
+ {
+- return parameter_ptr->short_description;
++ return (parameter_ptr) ? parameter_ptr->name : NULL;
+ }
+
+-EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT const char * jackctl_parameter_get_short_description(jackctl_parameter *parameter_ptr)
+ {
+- return parameter_ptr->long_description;
++ return (parameter_ptr) ? parameter_ptr->short_description : NULL;
+ }
+
+-EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT const char * jackctl_parameter_get_long_description(jackctl_parameter *parameter_ptr)
+ {
+- return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0;
++ return (parameter_ptr) ? parameter_ptr->long_description : NULL;
+ }
+
+-EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT bool jackctl_parameter_has_range_constraint(jackctl_parameter *parameter_ptr)
+ {
+- return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0;
++ return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) != 0) : false;
+ }
+
+-EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT bool jackctl_parameter_has_enum_constraint(jackctl_parameter *parameter_ptr)
+ {
++ return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_RANGE) == 0): false;
++}
++
++SERVER_EXPORT uint32_t jackctl_parameter_get_enum_constraints_count(jackctl_parameter *parameter_ptr)
++{
++ if (!parameter_ptr) {
++ return NULL;
++ }
++
+ if (!jackctl_parameter_has_enum_constraint(parameter_ptr))
+ {
+ return 0;
+ }
+
+ return parameter_ptr->constraint_ptr->constraint.enumeration.count;
+-}
++ }
+
+-EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
++SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_enum_constraint_value(jackctl_parameter *parameter_ptr, uint32_t index)
+ {
+ jack_driver_param_value_t * value_ptr;
+ union jackctl_parameter_value jackctl_value;
+
++ if (!parameter_ptr) {
++ memset(&jackctl_value, 0, sizeof(jackctl_value));
++ return jackctl_value;
++ }
++
+ value_ptr = ¶meter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].value;
+
+ switch (parameter_ptr->type)
+@@ -1033,13 +1073,17 @@
+ return jackctl_value;
+ }
+
+-EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
++SERVER_EXPORT const char * jackctl_parameter_get_enum_constraint_description(jackctl_parameter *parameter_ptr, uint32_t index)
+ {
+- return parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc;
++ return (parameter_ptr) ? parameter_ptr->constraint_ptr->constraint.enumeration.possible_values_array[index].short_desc : NULL;
+ }
+
+-EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
++SERVER_EXPORT void jackctl_parameter_get_range_constraint(jackctl_parameter *parameter_ptr, union jackctl_parameter_value * min_ptr, union jackctl_parameter_value * max_ptr)
+ {
++ if (!parameter_ptr || !min_ptr || !max_ptr) {
++ return;
++ }
++
+ switch (parameter_ptr->type)
+ {
+ case JackParamInt:
+@@ -1056,38 +1100,48 @@
+ }
+ }
+
+-EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr)
++SERVER_EXPORT bool jackctl_parameter_constraint_is_strict(jackctl_parameter_t * parameter_ptr)
+ {
+- return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
++ return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_STRICT) != 0) : false;
+ }
+
+-EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr)
++SERVER_EXPORT bool jackctl_parameter_constraint_is_fake_value(jackctl_parameter_t * parameter_ptr)
+ {
+- return parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
++ return (parameter_ptr) ? (parameter_ptr->constraint_ptr != NULL && (parameter_ptr->constraint_ptr->flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0) : false;
+ }
+
+-EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT jackctl_param_type_t jackctl_parameter_get_type(jackctl_parameter *parameter_ptr)
+ {
+- return parameter_ptr->type;
++ return (parameter_ptr) ? parameter_ptr->type : (jackctl_param_type_t)0;
+ }
+
+-EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
++SERVER_EXPORT char jackctl_parameter_get_id(jackctl_parameter_t * parameter_ptr)
+ {
+- return parameter_ptr->id;
++ return (parameter_ptr) ? parameter_ptr->id : 0;
+ }
+
+-EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT bool jackctl_parameter_is_set(jackctl_parameter *parameter_ptr)
+ {
+- return parameter_ptr->is_set;
++ return (parameter_ptr) ? parameter_ptr->is_set : false;
+ }
+
+-EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_value(jackctl_parameter *parameter_ptr)
+ {
+- return *parameter_ptr->value_ptr;
++ if (parameter_ptr) {
++ return *parameter_ptr->value_ptr;
++ } else {
++ union jackctl_parameter_value jackctl_value;
++ memset(&jackctl_value, 0, sizeof(jackctl_value));
++ return jackctl_value;
++ }
+ }
+
+-EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT bool jackctl_parameter_reset(jackctl_parameter *parameter_ptr)
+ {
++ if (!parameter_ptr) {
++ return NULL;
++ }
++
+ if (!parameter_ptr->is_set)
+ {
+ return true;
+@@ -1100,8 +1154,12 @@
+ return true;
+ }
+
+-EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
++SERVER_EXPORT bool jackctl_parameter_set_value(jackctl_parameter *parameter_ptr, const union jackctl_parameter_value * value_ptr)
+ {
++ if (!parameter_ptr || !value_ptr) {
++ return NULL;
++ }
++
+ bool new_driver_parameter;
+
+ /* for driver parameters, set the parameter by adding jack_driver_param_t in the set_parameters list */
+@@ -1159,32 +1217,42 @@
+ return true;
+ }
+
+-EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
++SERVER_EXPORT union jackctl_parameter_value jackctl_parameter_get_default_value(jackctl_parameter *parameter_ptr)
+ {
+- return *parameter_ptr->default_value_ptr;
++ if (parameter_ptr) {
++ return *parameter_ptr->default_value_ptr;
++ } else {
++ union jackctl_parameter_value jackctl_value;
++ memset(&jackctl_value, 0, sizeof(jackctl_value));
++ return jackctl_value;
++ }
+ }
+
+ // Internals clients
+
+-EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
++SERVER_EXPORT const JSList * jackctl_server_get_internals_list(jackctl_server *server_ptr)
+ {
+- return server_ptr->internals;
++ return (server_ptr) ? server_ptr->internals : NULL;
+ }
+
+-EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
++SERVER_EXPORT const char * jackctl_internal_get_name(jackctl_internal *internal_ptr)
+ {
+- return internal_ptr->desc_ptr->name;
++ return (internal_ptr) ? internal_ptr->desc_ptr->name : NULL;
+ }
+
+-EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
++SERVER_EXPORT const JSList * jackctl_internal_get_parameters(jackctl_internal *internal_ptr)
+ {
+- return internal_ptr->parameters;
++ return (internal_ptr) ? internal_ptr->parameters : NULL;
+ }
+
+-EXPORT bool jackctl_server_load_internal(
++SERVER_EXPORT bool jackctl_server_load_internal(
+ jackctl_server * server_ptr,
+ jackctl_internal * internal)
+ {
++ if (!server_ptr || !internal) {
++ return false;
++ }
++
+ int status;
+ if (server_ptr->engine != NULL) {
+ server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status);
+@@ -1194,56 +1262,73 @@
+ }
+ }
+
+-EXPORT bool jackctl_server_unload_internal(
++SERVER_EXPORT bool jackctl_server_unload_internal(
+ jackctl_server * server_ptr,
+ jackctl_internal * internal)
+ {
++ if (!server_ptr || !internal) {
++ return false;
++ }
++
+ int status;
+ if (server_ptr->engine != NULL && internal->refnum > 0) {
+- // Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload
++ // Client object is internally kept in JackEngine, and will be deallocated in InternalClientUnload
+ return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0);
+ } else {
+ return false;
+ }
+ }
+
+-EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
++SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
+ {
+- if (server_ptr->engine != NULL) {
++ if (server_ptr && server_ptr->engine) {
+ if (server_ptr->engine->IsRunning()) {
+ jack_error("cannot add a slave in a running server");
+ return false;
+ } else {
+- driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
+- return (driver_ptr->info != 0);
++ JackDriverInfo* info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters);
++ if (info) {
++ driver_ptr->infos = jack_slist_append(driver_ptr->infos, info);
++ return true;
++ } else {
++ return false;
++ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+-EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
++SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
+ {
+- if (server_ptr->engine != NULL) {
++ if (server_ptr && server_ptr->engine) {
+ if (server_ptr->engine->IsRunning()) {
+ jack_error("cannot remove a slave from a running server");
+ return false;
+ } else {
+- server_ptr->engine->RemoveSlave(driver_ptr->info);
+- delete driver_ptr->info;
+- return true;
++ if (driver_ptr->infos) {
++ JackDriverInfo* info = (JackDriverInfo*)driver_ptr->infos->data;
++ assert(info);
++ driver_ptr->infos = jack_slist_remove(driver_ptr->infos, info);
++ server_ptr->engine->RemoveSlave(info);
++ delete info;
++ return true;
++ } else {
++ return false;
++ }
+ }
+ } else {
+ return false;
+ }
+ }
+
+-EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
++SERVER_EXPORT bool jackctl_server_switch_master(jackctl_server * server_ptr, jackctl_driver * driver_ptr)
+ {
+- if (server_ptr->engine != NULL) {
++ if (server_ptr && server_ptr->engine) {
+ return (server_ptr->engine->SwitchMaster(driver_ptr->desc_ptr, driver_ptr->set_parameters) == 0);
+ } else {
+ return false;
+ }
+ }
+
++
+--- a/common/JackControlAPI.h
++++ b/common/JackControlAPI.h
+@@ -28,6 +28,7 @@
+ #ifdef WIN32
+ #ifdef __MINGW32__
+ #include <sys/types.h>
++typedef _sigset_t sigset_t;
+ #else
+ typedef HANDLE sigset_t;
+ #endif
+@@ -43,6 +44,13 @@
+ JackParamBool, /**< @brief value type is a boolean */
+ } jackctl_param_type_t;
+
++/** Driver types, intentionally similar to jack_driver_type_t */
++typedef enum
++{
++ JackMaster = 1, /**< @brief master driver */
++ JackSlave, /**< @brief slave driver */
++} jackctl_driver_type_t;
++
+ /** @brief Max value that jackctl_param_type_t type can have */
+ #define JACK_PARAM_MAX (JackParamBool + 1)
+
+@@ -79,164 +87,168 @@
+ } /* Adjust editor indent */
+ #endif
+
+-EXPORT sigset_t
++SERVER_EXPORT sigset_t
+ jackctl_setup_signals(
+ unsigned int flags);
+
+-EXPORT void
++SERVER_EXPORT void
+ jackctl_wait_signals(
+ sigset_t signals);
+
+-EXPORT jackctl_server_t *
++SERVER_EXPORT jackctl_server_t *
+ jackctl_server_create(
+ bool (* on_device_acquire)(const char * device_name),
+ void (* on_device_release)(const char * device_name));
+
+-EXPORT void
++SERVER_EXPORT void
+ jackctl_server_destroy(
+ jackctl_server_t * server);
+
+-EXPORT const JSList *
++SERVER_EXPORT const JSList *
+ jackctl_server_get_drivers_list(
+ jackctl_server_t * server);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_open(
+ jackctl_server_t * server,
+ jackctl_driver_t * driver);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_start(
+ jackctl_server_t * server);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_stop(
+ jackctl_server_t * server);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_close(
+ jackctl_server_t * server);
+
+-EXPORT const JSList *
++SERVER_EXPORT const JSList *
+ jackctl_server_get_parameters(
+ jackctl_server_t * server);
+
+-EXPORT const char *
++SERVER_EXPORT const char *
+ jackctl_driver_get_name(
+ jackctl_driver_t * driver);
+
+-EXPORT const JSList *
++SERVER_EXPORT jackctl_driver_type_t
++jackctl_driver_get_type(
++ jackctl_driver_t * driver);
++
++SERVER_EXPORT const JSList *
+ jackctl_driver_get_parameters(
+ jackctl_driver_t * driver);
+
+-EXPORT const char *
++SERVER_EXPORT const char *
+ jackctl_parameter_get_name(
+ jackctl_parameter_t * parameter);
+
+-EXPORT const char *
++SERVER_EXPORT const char *
+ jackctl_parameter_get_short_description(
+ jackctl_parameter_t * parameter);
+
+-EXPORT const char *
++SERVER_EXPORT const char *
+ jackctl_parameter_get_long_description(
+ jackctl_parameter_t * parameter);
+
+-EXPORT jackctl_param_type_t
++SERVER_EXPORT jackctl_param_type_t
+ jackctl_parameter_get_type(
+ jackctl_parameter_t * parameter);
+
+-EXPORT char
++SERVER_EXPORT char
+ jackctl_parameter_get_id(
+ jackctl_parameter_t * parameter);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_parameter_is_set(
+ jackctl_parameter_t * parameter);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_parameter_reset(
+ jackctl_parameter_t * parameter);
+
+-EXPORT union jackctl_parameter_value
++SERVER_EXPORT union jackctl_parameter_value
+ jackctl_parameter_get_value(
+ jackctl_parameter_t * parameter);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_parameter_set_value(
+ jackctl_parameter_t * parameter,
+ const union jackctl_parameter_value * value_ptr);
+
+-EXPORT union jackctl_parameter_value
++SERVER_EXPORT union jackctl_parameter_value
+ jackctl_parameter_get_default_value(
+ jackctl_parameter_t * parameter);
+-
+-EXPORT union jackctl_parameter_value
++
++SERVER_EXPORT union jackctl_parameter_value
+ jackctl_parameter_get_default_value(
+ jackctl_parameter *parameter_ptr);
+-
+-EXPORT bool
++
++SERVER_EXPORT bool
+ jackctl_parameter_has_range_constraint(
+ jackctl_parameter_t * parameter_ptr);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_parameter_has_enum_constraint(
+ jackctl_parameter_t * parameter_ptr);
+
+-EXPORT uint32_t
++SERVER_EXPORT uint32_t
+ jackctl_parameter_get_enum_constraints_count(
+ jackctl_parameter_t * parameter_ptr);
+
+-EXPORT union jackctl_parameter_value
++SERVER_EXPORT union jackctl_parameter_value
+ jackctl_parameter_get_enum_constraint_value(
+ jackctl_parameter_t * parameter_ptr,
+ uint32_t index);
+
+-EXPORT const char *
++SERVER_EXPORT const char *
+ jackctl_parameter_get_enum_constraint_description(
+ jackctl_parameter_t * parameter_ptr,
+ uint32_t index);
+
+-EXPORT void
++SERVER_EXPORT void
+ jackctl_parameter_get_range_constraint(
+ jackctl_parameter_t * parameter_ptr,
+ union jackctl_parameter_value * min_ptr,
+ union jackctl_parameter_value * max_ptr);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_parameter_constraint_is_strict(
+ jackctl_parameter_t * parameter_ptr);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_parameter_constraint_is_fake_value(
+ jackctl_parameter_t * parameter_ptr);
+
+-EXPORT const JSList *
++SERVER_EXPORT const JSList *
+ jackctl_server_get_internals_list(
+ jackctl_server *server_ptr);
+-
+-EXPORT const char *
++
++SERVER_EXPORT const char *
+ jackctl_internal_get_name(
+ jackctl_internal *internal_ptr);
+-
+-EXPORT const JSList *
++
++SERVER_EXPORT const JSList *
+ jackctl_internal_get_parameters(
+ jackctl_internal *internal_ptr);
+-
+-EXPORT bool jackctl_server_load_internal(
++
++SERVER_EXPORT bool jackctl_server_load_internal(
+ jackctl_server * server,
+ jackctl_internal * internal);
+-
+-EXPORT bool jackctl_server_unload_internal(
++
++SERVER_EXPORT bool jackctl_server_unload_internal(
+ jackctl_server * server,
+ jackctl_internal * internal);
+-
+-EXPORT bool jackctl_server_add_slave(jackctl_server_t * server,
++
++SERVER_EXPORT bool jackctl_server_add_slave(jackctl_server_t * server,
+ jackctl_driver_t * driver);
+
+-EXPORT bool jackctl_server_remove_slave(jackctl_server_t * server,
++SERVER_EXPORT bool jackctl_server_remove_slave(jackctl_server_t * server,
+ jackctl_driver_t * driver);
+
+-EXPORT bool
++SERVER_EXPORT bool
+ jackctl_server_switch_master(jackctl_server_t * server,
+ jackctl_driver_t * driver);
+
+@@ -248,3 +260,4 @@
+ #endif
+
+ #endif
++
+--- a/common/jack/control.h
++++ b/common/jack/control.h
+@@ -45,6 +45,13 @@
+ JackParamBool, /**< @brief value type is a boolean */
+ } jackctl_param_type_t;
+
++/** Driver types */
++typedef enum
++{
++ JackMaster = 1, /**< @brief master driver */
++ JackSlave /**< @brief slave driver */
++} jackctl_driver_type_t;
++
+ /** @brief Max value that jackctl_param_type_t type can have */
+ #define JACK_PARAM_MAX (JackParamBool + 1)
+
+@@ -82,7 +89,7 @@
+ #endif
+
+ /**
+- * @defgroup ServerControl Controling the server
++ * @defgroup ControlAPI The API for starting and controlling a JACK server
+ * @{
+ */
+
+@@ -299,6 +306,18 @@
+ jackctl_driver_t * driver);
+
+ /**
++ * Call this function to get type of driver.
++ *
++ * @param driver driver object handle to get name of
++ *
++ * @return driver type. Must not be modified. Always same for same
++ * driver object.
++ */
++jackctl_driver_type_t
++jackctl_driver_get_type(
++ jackctl_driver_t * driver);
++
++/**
+ * Call this function to get list of driver parameters. List node data
+ * pointers is a parameter object handle (::jackctl_parameter_t).
+ *
+--- a/common/JackDebugClient.cpp
++++ b/common/JackDebugClient.cpp
+@@ -90,7 +90,7 @@
+ /* Convert it to local time representation. */
+ loctime = localtime (&curtime);
+ strftime (buffer, 256, "%I-%M", loctime);
+- sprintf(provstr, "JackClientDebug-%s-%s.log", name, buffer);
++ snprintf(provstr, sizeof(provstr), "JackClientDebug-%s-%s.log", name, buffer);
+ fStream = new ofstream(provstr, ios_base::ate);
+ if (fStream->is_open()) {
+ if (res == -1) {
+@@ -333,7 +333,7 @@
+ *fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = ON while FW is already ON " << endl;
+ if (!onoff && !fFreewheel)
+ *fStream << "!!! ERROR !!! : Freewheel setup seems incorrect : set = OFF while FW is already OFF " << endl;
+- fFreewheel = onoff;
++ fFreewheel = onoff ? true : false;
+ return fClient->SetFreeWheel(onoff);
+ }
+
+--- a/common/JackDebugClient.h
++++ b/common/JackDebugClient.h
+@@ -46,7 +46,7 @@
+ \brief A "decorator" debug client to validate API use.
+ */
+
+-class SERVER_EXPORT JackDebugClient : public JackClient
++class LIB_EXPORT JackDebugClient : public JackClient
+ {
+ protected:
+
+--- a/common/Jackdmp.cpp
++++ b/common/Jackdmp.cpp
+@@ -115,13 +115,13 @@
+ " [ --version OR -V ]\n"
+ " -d master-backend-name [ ... master-backend args ... ]\n"
+ #ifdef __APPLE__
+- " Available master backends may include: coreaudio, dummy or net.\n\n"
++ " Available master backends may include: coreaudio, dummy, net or netone.\n\n"
+ #endif
+ #ifdef WIN32
+- " Available master backends may include: portaudio, dummy or net.\n\n"
++ " Available master backends may include: portaudio, dummy, net or netone.\n\n"
+ #endif
+ #ifdef __linux__
+- " Available master backends may include: alsa, dummy, freebob, firewire or net\n\n"
++ " Available master backends may include: alsa, dummy, freebob, firewire, net or netone.\n\n"
+ #endif
+ #if defined(__sun__) || defined(sun)
+ " Available master backends may include: boomer, oss, dummy or net.\n\n"
+@@ -185,13 +185,13 @@
+ return NULL;
+ }
+
+-int main(int argc, char* argv[])
++int main(int argc, char** argv)
+ {
+ jackctl_server_t * server_ctl;
+ const JSList * server_parameters;
+ const char* server_name = "default";
+ jackctl_driver_t * master_driver_ctl;
+- jackctl_driver_t * loopback_driver_ctl;
++ jackctl_driver_t * loopback_driver_ctl = NULL;
+ int replace_registry = 0;
+
+ const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:"
+@@ -261,13 +261,6 @@
+
+ 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 (!master_driver_name &&
+ (opt = getopt_long(argc, argv, options,
+@@ -437,6 +430,11 @@
+ goto destroy_server;
+ }
+
++ if (jackctl_driver_get_type(master_driver_ctl) != JackMaster) {
++ fprintf(stderr, "Driver \"%s\" is not a master \n", master_driver_name);
++ goto destroy_server;
++ }
++
+ if (optind < argc) {
+ master_driver_nargs = 1 + argc - optind;
+ } else {
+@@ -476,14 +474,20 @@
+ fprintf(stderr, "Unknown driver \"%s\"\n", *it);
+ goto close_server;
+ }
+- jackctl_server_add_slave(server_ctl, slave_driver_ctl);
++ if (jackctl_driver_get_type(slave_driver_ctl) != JackSlave) {
++ fprintf(stderr, "Driver \"%s\" is not a slave \n", *it);
++ goto close_server;
++ }
++ if (!jackctl_server_add_slave(server_ctl, slave_driver_ctl)) {
++ fprintf(stderr, "Driver \"%s\" cannot be loaded\n", *it);
++ goto close_server;
++ }
+ }
+
+ // Loopback driver
+ if (loopback > 0) {
+ loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback");
+
+- // XX: What if this fails?
+ if (loopback_driver_ctl != NULL) {
+ const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl);
+ param = jackctl_get_parameter(loopback_parameters, "channels");
+@@ -491,9 +495,14 @@
+ value.ui = loopback;
+ jackctl_parameter_set_value(param, &value);
+ }
+- jackctl_server_add_slave(server_ctl, loopback_driver_ctl);
++ if (!jackctl_server_add_slave(server_ctl, loopback_driver_ctl)) {
++ fprintf(stderr, "Driver \"loopback\" cannot be loaded\n");
++ goto close_server;
++ }
++ } else {
++ fprintf(stderr, "Driver \"loopback\" not found\n");
++ goto close_server;
+ }
+-
+ }
+
+ // Start the server
+@@ -509,7 +518,10 @@
+ fprintf(stderr, "Unknown internal \"%s\"\n", *it);
+ goto stop_server;
+ }
+- jackctl_server_load_internal(server_ctl, internal_driver_ctl);
++ if (!jackctl_server_load_internal(server_ctl, internal_driver_ctl)) {
++ fprintf(stderr, "Internal client \"%s\" cannot be loaded\n", *it);
++ goto stop_server;
++ }
+ }
+
+ notify_server_start(server_name);
+@@ -520,15 +532,33 @@
+ jackctl_wait_signals(signals);
+
+ stop_server:
+- if (! jackctl_server_stop(server_ctl)) {
++ if (!jackctl_server_stop(server_ctl)) {
+ fprintf(stderr, "Cannot stop server...\n");
+ }
+- if (notify_sent) {
+- notify_server_stop(server_name);
+- }
++
+ close_server:
++ if (loopback > 0 && loopback_driver_ctl) {
++ jackctl_server_remove_slave(server_ctl, loopback_driver_ctl);
++ }
++ // Slave drivers
++ for (it = slaves_list.begin(); it != slaves_list.end(); it++) {
++ jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it);
++ if (slave_driver_ctl)
++ jackctl_server_remove_slave(server_ctl, slave_driver_ctl);
++ }
++
++ // Internal clients
++ for (it = internals_list.begin(); it != internals_list.end(); it++) {
++ jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it);
++ if (internal_driver_ctl)
++ jackctl_server_unload_internal(server_ctl, internal_driver_ctl);
++ }
+ jackctl_server_close(server_ctl);
++
+ destroy_server:
+ jackctl_server_destroy(server_ctl);
++ if (notify_sent) {
++ notify_server_stop(server_name);
++ }
+ return return_value;
+ }
+--- a/common/JackDriver.cpp
++++ b/common/JackDriver.cpp
+@@ -37,7 +37,10 @@
+ {
+
+ JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+- :fClientControl(name)
++ :fClientControl(name),
++ fCaptureChannels(0),
++ fPlaybackChannels(0),
++ fWithMonitorPorts(false)
+ {
+ assert(strlen(name) < JACK_CLIENT_NAME_SIZE);
+ fSynchroTable = table;
+@@ -56,8 +59,12 @@
+ fEngine = NULL;
+ fGraphManager = NULL;
+ fBeginDateUst = 0;
++ fDelayedUsecs = 0.f;
+ fIsMaster = true;
+ fIsRunning = false;
++ fCaptureChannels = 0;
++ fPlaybackChannels = 0;
++ fWithMonitorPorts = false;
+ }
+
+ JackDriver::~JackDriver()
+@@ -123,8 +130,9 @@
+ strcpy(fPlaybackDriverName, playback_driver_name);
+
+ fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
+- if (!fEngineControl->fTimeOut)
++ if (!fEngineControl->fTimeOut) {
+ fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
++ }
+
+ fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
+ SetupDriverSync(fClientControl.fRefNum, false);
+@@ -176,8 +184,9 @@
+ strcpy(fPlaybackDriverName, playback_driver_name);
+
+ fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize); // in microsec
+- if (!fEngineControl->fTimeOut)
++ if (!fEngineControl->fTimeOut) {
+ fEngineControl->fTimeOutUsecs = jack_time_t(2.f * fEngineControl->fPeriodUsecs);
++ }
+
+ fGraphManager->SetBufferSize(buffer_size);
+ fGraphManager->DirectConnect(fClientControl.fRefNum, fClientControl.fRefNum); // Connect driver to itself for "sync" mode
+@@ -216,6 +225,8 @@
+
+ int JackDriver::ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2)
+ {
++ jack_log("JackDriver::ClientNotify ref = %ld driver = %s name = %s notify = %ld", refnum, fClientControl.fName, name, notify);
++
+ switch (notify) {
+
+ case kStartFreewheelCallback:
+@@ -227,7 +238,7 @@
+ jack_log("JackDriver::kStopFreewheel");
+ SetupDriverSync(fClientControl.fRefNum, false);
+ break;
+- }
++ }
+
+ return 0;
+ }
+@@ -300,25 +311,47 @@
+ fSlaveList.remove(slave);
+ }
+
+-int JackDriver::ProcessSlaves()
++int JackDriver::ProcessReadSlaves()
+ {
+ int res = 0;
+ list<JackDriverInterface*>::const_iterator it;
+ for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
+ JackDriverInterface* slave = *it;
+- if (slave->Process() < 0)
+- res = -1;
++ if (slave->IsRunning()) {
++ if (slave->ProcessRead() < 0) {
++ res = -1;
++ }
++ }
++ }
++ return res;
++}
+
++int JackDriver::ProcessWriteSlaves()
++{
++ int res = 0;
++ list<JackDriverInterface*>::const_iterator it;
++ for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
++ JackDriverInterface* slave = *it;
++ if (slave->IsRunning()) {
++ if (slave->ProcessWrite() < 0) {
++ res = -1;
++ }
++ }
+ }
+ return res;
+ }
+
+-int JackDriver::Process()
++int JackDriver::ProcessRead()
+ {
+ return 0;
+ }
+
+-int JackDriver::ProcessNull()
++int JackDriver::ProcessWrite()
++{
++ return 0;
++}
++
++int JackDriver::Process()
+ {
+ return 0;
+ }
+@@ -352,6 +385,12 @@
+ return 0;
+ }
+
++int JackDriver::Stop()
++{
++ fIsRunning = false;
++ return 0;
++}
++
+ int JackDriver::StartSlaves()
+ {
+ int res = 0;
+@@ -360,30 +399,23 @@
+ JackDriverInterface* slave = *it;
+ if (slave->Start() < 0) {
+ res = -1;
+-
+ // XXX: We should attempt to stop all of the slaves that we've
+ // started here.
+-
+ break;
+ }
+ }
+ return res;
+ }
+
+-int JackDriver::Stop()
+-{
+- fIsRunning = false;
+- return 0;
+-}
+-
+ int JackDriver::StopSlaves()
+ {
+ int res = 0;
+ list<JackDriverInterface*>::const_iterator it;
+ for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
+ JackDriverInterface* slave = *it;
+- if (slave->Stop() < 0)
++ if (slave->Stop() < 0) {
+ res = -1;
++ }
+ }
+ return res;
+ }
+@@ -395,12 +427,28 @@
+
+ int JackDriver::SetBufferSize(jack_nframes_t buffer_size)
+ {
+- return 0;
++ int res = 0;
++ list<JackDriverInterface*>::const_iterator it;
++ for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
++ JackDriverInterface* slave = *it;
++ if (slave->SetBufferSize(buffer_size) < 0) {
++ res = -1;
++ }
++ }
++ return res;
+ }
+
+ int JackDriver::SetSampleRate(jack_nframes_t sample_rate)
+ {
+- return 0;
++ int res = 0;
++ list<JackDriverInterface*>::const_iterator it;
++ for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) {
++ JackDriverInterface* slave = *it;
++ if (slave->SetSampleRate(sample_rate) < 0) {
++ res = -1;
++ }
++ }
++ return res;
+ }
+
+ bool JackDriver::Initialize()
+@@ -409,4 +457,57 @@
+ }
+
+
++void JackDriver::SaveConnections()
++{
++ const char** connections;
++ fConnections.clear();
++ char alias1[REAL_JACK_PORT_NAME_SIZE];
++ char alias2[REAL_JACK_PORT_NAME_SIZE];
++ char* aliases[2];
++
++ aliases[0] = alias1;
++ aliases[1] = alias2;
++
++ for (int i = 0; i < fCaptureChannels; ++i) {
++ if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fCapturePortList[i])) != 0) {
++ for (int j = 0; connections[j]; j++) {
++ /*
++ fGraphManager->GetPort(fCapturePortList[i])->GetAliases(aliases);
++ fConnections.push_back(make_pair(aliases[0], connections[j]));
++ jack_info("Save connection: %s %s", aliases[0], connections[j]);
++ */
++ fConnections.push_back(make_pair(fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]));
++ jack_info("Save connection: %s %s", fGraphManager->GetPort(fCapturePortList[i])->GetName(), connections[j]);
++ }
++ free(connections);
++ }
++ }
++
++ for (int i = 0; i < fPlaybackChannels; ++i) {
++ if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fPlaybackPortList[i])) != 0) {
++ for (int j = 0; connections[j]; j++) {
++ /*
++ fGraphManager->GetPort(fPlaybackPortList[i])->GetAliases(aliases);
++ fConnections.push_back(make_pair(connections[j], aliases[0]));
++ jack_info("Save connection: %s %s", connections[j], aliases[0]);
++ */
++ fConnections.push_back(make_pair(connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName()));
++ jack_info("Save connection: %s %s", connections[j], fGraphManager->GetPort(fPlaybackPortList[i])->GetName());
++ }
++ free(connections);
++ }
++ }
++}
++
++void JackDriver::RestoreConnections()
++{
++ list<pair<string, string> >::const_iterator it;
++
++ for (it = fConnections.begin(); it != fConnections.end(); it++) {
++ pair<string, string> connection = *it;
++ jack_info("Restore connection: %s %s", connection.first.c_str(), connection.second.c_str());
++ fEngine->PortConnect(fClientControl.fRefNum, connection.first.c_str(), connection.second.c_str());
++ }
++}
++
+ } // end of namespace
+--- a/common/JackDriver.h
++++ b/common/JackDriver.h
+@@ -34,6 +34,7 @@
+ class JackLockedEngine;
+ class JackGraphManager;
+ struct JackEngineControl;
++class JackSlaveDriverInterface;
+
+ /*!
+ \brief The base interface for drivers.
+@@ -52,14 +53,14 @@
+ virtual int Open() = 0;
+
+ virtual int Open (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) = 0;
++ 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) = 0;
+
+ virtual int Open(jack_nframes_t buffer_size,
+ jack_nframes_t samplerate,
+@@ -87,14 +88,20 @@
+ virtual int SetSampleRate(jack_nframes_t sample_rate) = 0;
+
+ virtual int Process() = 0;
+- virtual int ProcessNull() = 0;
+
+ virtual void SetMaster(bool onoff) = 0;
+ virtual bool GetMaster() = 0;
++
+ virtual void AddSlave(JackDriverInterface* slave) = 0;
+ virtual void RemoveSlave(JackDriverInterface* slave) = 0;
++
+ virtual std::list<JackDriverInterface*> GetSlaves() = 0;
+- virtual int ProcessSlaves() = 0;
++
++ virtual int ProcessReadSlaves() = 0;
++ virtual int ProcessWriteSlaves() = 0;
++
++ virtual int ProcessRead() = 0;
++ virtual int ProcessWrite() = 0;
+
+ virtual bool IsRealTime() const = 0;
+ virtual bool IsRunning() const = 0;
+@@ -122,12 +129,16 @@
+
+ char fCaptureDriverName[JACK_CLIENT_NAME_SIZE + 1];
+ char fPlaybackDriverName[JACK_CLIENT_NAME_SIZE + 1];
++
+ char fAliasName[JACK_CLIENT_NAME_SIZE + 1];
++
+ jack_nframes_t fCaptureLatency;
+ jack_nframes_t fPlaybackLatency;
++
+ jack_time_t fBeginDateUst;
+ jack_time_t fEndDateUst;
+ float fDelayedUsecs;
++
+ JackLockedEngine* fEngine;
+ JackGraphManager* fGraphManager;
+ JackSynchro* fSynchroTable;
+@@ -137,6 +148,19 @@
+ bool fIsMaster;
+ bool fIsRunning;
+
++ int fCaptureChannels;
++ int fPlaybackChannels;
++
++ // Static tables since the actual number of ports may be changed by the real driver
++ // thus dynamic allocation is more difficult to handle
++ jack_port_id_t fCapturePortList[DRIVER_PORT_NUM];
++ jack_port_id_t fPlaybackPortList[DRIVER_PORT_NUM];
++ jack_port_id_t fMonitorPortList[DRIVER_PORT_NUM];
++
++ bool fWithMonitorPorts;
++
++ std::list<std::pair<std::string, std::string> > fConnections; // Connections list
++
+ void CycleIncTime();
+ void CycleTakeBeginTime();
+ void CycleTakeEndTime();
+@@ -159,23 +183,23 @@
+
+ void AddSlave(JackDriverInterface* slave);
+ void RemoveSlave(JackDriverInterface* slave);
++
+ std::list<JackDriverInterface*> GetSlaves()
+ {
+ return fSlaveList;
+ }
+- int ProcessSlaves();
+
+ virtual int Open();
+
+ virtual int Open (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);
++ 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);
+
+ virtual int Open(jack_nframes_t buffer_size,
+ jack_nframes_t samplerate,
+@@ -191,7 +215,6 @@
+ virtual int Close();
+
+ virtual int Process();
+- virtual int ProcessNull();
+
+ virtual int Attach();
+ virtual int Detach();
+@@ -200,10 +223,20 @@
+ virtual int Write();
+
+ virtual int Start();
+- virtual int StartSlaves();
+ virtual int Stop();
++
++ virtual int StartSlaves();
+ virtual int StopSlaves();
+
++ int ProcessReadSlaves();
++ int ProcessWriteSlaves();
++
++ int ProcessRead();
++ int ProcessWrite();
++
++ virtual void SaveConnections();
++ virtual void RestoreConnections();
++
+ virtual bool IsFixedBufferSize();
+ virtual int SetBufferSize(jack_nframes_t buffer_size);
+ virtual int SetSampleRate(jack_nframes_t sample_rate);
+--- a/common/JackDriverLoader.cpp
++++ b/common/JackDriverLoader.cpp
+@@ -25,14 +25,15 @@
+ #include <getopt.h>
+ #include <stdio.h>
+ #include <errno.h>
++#include <string.h>
+
+ #ifndef WIN32
+ #include <dirent.h>
+ #endif
+
+-jack_driver_desc_t * jackctl_driver_get_desc(jackctl_driver_t * driver);
++jack_driver_desc_t* jackctl_driver_get_desc(jackctl_driver_t * driver);
+
+-EXPORT void jack_print_driver_options (jack_driver_desc_t* desc, FILE* file)
++SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file)
+ {
+ unsigned long i;
+ char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1];
+@@ -49,17 +50,18 @@
+ sprintf (arg_default, "%c", desc->params[i].value.c);
+ break;
+ case JackDriverParamString:
+- if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0)
++ if (desc->params[i].value.str && strcmp (desc->params[i].value.str, "") != 0) {
+ sprintf (arg_default, "%s", desc->params[i].value.str);
+- else
++ } else {
+ sprintf (arg_default, "none");
++ }
+ break;
+ case JackDriverParamBool:
+ sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false");
+ break;
+ }
+
+- fprintf (file, "\t-%c, --%s \t%s (default: %s)\n",
++ fprintf(file, "\t-%c, --%s \t%s (default: %s)\n",
+ desc->params[i].character,
+ desc->params[i].name,
+ desc->params[i].long_desc,
+@@ -68,17 +70,17 @@
+ }
+
+ static void
+-jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file)
++jack_print_driver_param_usage (jack_driver_desc_t* desc, unsigned long param, FILE *file)
+ {
+ fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n",
+ desc->params[param].name, desc->name);
+ fprintf (file, "%s\n", desc->params[param].long_desc);
+ }
+
+-EXPORT void jack_free_driver_params(JSList * driver_params)
++SERVER_EXPORT void jack_free_driver_params(JSList * driver_params)
+ {
+- JSList *node_ptr = driver_params;
+- JSList *next_node_ptr;
++ JSList*node_ptr = driver_params;
++ JSList*next_node_ptr;
+
+ while (node_ptr) {
+ next_node_ptr = node_ptr->next;
+@@ -88,15 +90,15 @@
+ }
+ }
+
+-int
+-jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSList ** param_ptr)
++SERVER_EXPORT int
++jack_parse_driver_params(jack_driver_desc_t* desc, int argc, char* argv[], JSList** param_ptr)
+ {
+ struct option * long_options;
+- char * options, * options_ptr;
++ char* options, * options_ptr;
+ unsigned long i;
+ int opt;
+ unsigned int param_index;
+- JSList * params = NULL;
++ JSList* params = NULL;
+ jack_driver_param_t * driver_param;
+
+ if (argc <= 1) {
+@@ -173,10 +175,10 @@
+ if (optarg) {
+ switch (desc->params[param_index].type) {
+ case JackDriverParamInt:
+- driver_param->value.i = atoi (optarg);
++ driver_param->value.i = atoi(optarg);
+ break;
+ case JackDriverParamUInt:
+- driver_param->value.ui = strtoul (optarg, NULL, 10);
++ driver_param->value.ui = strtoul(optarg, NULL, 10);
+ break;
+ case JackDriverParamChar:
+ driver_param->value.c = optarg[0];
+@@ -185,26 +187,14 @@
+ strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
+ break;
+ case JackDriverParamBool:
+-
+- /*
+- if (strcasecmp ("false", optarg) == 0 ||
+- strcasecmp ("off", optarg) == 0 ||
+- strcasecmp ("no", optarg) == 0 ||
+- strcasecmp ("0", optarg) == 0 ||
+- strcasecmp ("(null)", optarg) == 0 ) {
+- */
+- // steph
+- if (strcmp ("false", optarg) == 0 ||
+- strcmp ("off", optarg) == 0 ||
+- strcmp ("no", optarg) == 0 ||
+- strcmp ("0", optarg) == 0 ||
+- strcmp ("(null)", optarg) == 0 ) {
++ if (strcasecmp("false", optarg) == 0 ||
++ strcasecmp("off", optarg) == 0 ||
++ strcasecmp("no", optarg) == 0 ||
++ strcasecmp("0", optarg) == 0 ||
++ strcasecmp("(null)", optarg) == 0 ) {
+ driver_param->value.i = false;
+-
+ } else {
+-
+ driver_param->value.i = true;
+-
+ }
+ break;
+ }
+@@ -222,31 +212,33 @@
+ free (options);
+ free (long_options);
+
+- if (param_ptr)
++ if (param_ptr) {
+ *param_ptr = params;
+-
++ }
+ return 0;
+ }
+
+-EXPORT int
+-jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[])
++SERVER_EXPORT int
++jackctl_parse_driver_params(jackctl_driver *driver_ptr, int argc, char* argv[])
+ {
+- struct option * long_options;
+- char * options, * options_ptr;
++ struct option* long_options;
++ char* options, * options_ptr;
+ unsigned long i;
+ int opt;
+- JSList * node_ptr;
++ JSList* node_ptr;
+ jackctl_parameter_t * param = NULL;
+ union jackctl_parameter_value value;
+
+- if (argc <= 1)
++ if (argc <= 1) {
+ return 0;
++ }
+
+- const JSList * driver_params = jackctl_driver_get_parameters(driver_ptr);
+- if (driver_params == NULL)
++ const JSList* driver_params = jackctl_driver_get_parameters(driver_ptr);
++ if (driver_params == NULL) {
+ return 1;
++ }
+
+- jack_driver_desc_t * desc = jackctl_driver_get_desc(driver_ptr);
++ jack_driver_desc_t* desc = jackctl_driver_get_desc(driver_ptr);
+
+ /* check for help */
+ if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) {
+@@ -274,7 +266,7 @@
+
+ options_ptr = options;
+ for (i = 0; i < desc->nparams; i++) {
+- sprintf (options_ptr, "%c::", desc->params[i].character);
++ sprintf(options_ptr, "%c::", desc->params[i].character);
+ options_ptr += 3;
+ long_options[i].name = desc->params[i].name;
+ long_options[i].flag = NULL;
+@@ -317,11 +309,11 @@
+ if (optarg) {
+ switch (jackctl_parameter_get_type(param)) {
+ case JackDriverParamInt:
+- value.i = atoi (optarg);
++ value.i = atoi(optarg);
+ jackctl_parameter_set_value(param, &value);
+ break;
+ case JackDriverParamUInt:
+- value.ui = strtoul (optarg, NULL, 10);
++ value.ui = strtoul(optarg, NULL, 10);
+ jackctl_parameter_set_value(param, &value);
+ break;
+ case JackDriverParamChar:
+@@ -329,23 +321,15 @@
+ jackctl_parameter_set_value(param, &value);
+ break;
+ case JackDriverParamString:
+- strncpy (value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
++ strncpy(value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX);
+ jackctl_parameter_set_value(param, &value);
+ break;
+ case JackDriverParamBool:
+- /*
+- if (strcasecmp ("false", optarg) == 0 ||
+- strcasecmp ("off", optarg) == 0 ||
+- strcasecmp ("no", optarg) == 0 ||
+- strcasecmp ("0", optarg) == 0 ||
+- strcasecmp ("(null)", optarg) == 0 ) {
+- */
+- // steph
+- if (strcmp ("false", optarg) == 0 ||
+- strcmp ("off", optarg) == 0 ||
+- strcmp ("no", optarg) == 0 ||
+- strcmp ("0", optarg) == 0 ||
+- strcmp ("(null)", optarg) == 0 ) {
++ if (strcasecmp("false", optarg) == 0 ||
++ strcasecmp("off", optarg) == 0 ||
++ strcasecmp("no", optarg) == 0 ||
++ strcasecmp("0", optarg) == 0 ||
++ strcasecmp("(null)", optarg) == 0 ) {
+ value.i = false;
+ } else {
+ value.i = true;
+@@ -368,14 +352,14 @@
+ return 0;
+ }
+
+-jack_driver_desc_t *
+-jack_find_driver_descriptor (JSList * drivers, const char * name)
++jack_driver_desc_t*
++jack_find_driver_descriptor (JSList * drivers, const char* name)
+ {
+- jack_driver_desc_t * desc = 0;
+- JSList * node;
++ jack_driver_desc_t* desc = 0;
++ JSList* node;
+
+ for (node = drivers; node; node = jack_slist_next (node)) {
+- desc = (jack_driver_desc_t *) node->data;
++ desc = (jack_driver_desc_t*) node->data;
+
+ if (strcmp (desc->name, name) != 0) {
+ desc = NULL;
+@@ -387,18 +371,18 @@
+ return desc;
+ }
+
+-static jack_driver_desc_t *
+-jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol)
++static jack_driver_desc_t*
++jack_get_descriptor (JSList * drivers, const char* sofile, const char* symbol)
+ {
+- jack_driver_desc_t * descriptor, * other_descriptor;
++ jack_driver_desc_t* descriptor, * other_descriptor;
+ JackDriverDescFunction so_get_descriptor = NULL;
+- JSList * node;
++ JSList* node;
+ void * dlhandle;
+- char * filename;
++ char* filename;
+ #ifdef WIN32
+ int dlerr;
+ #else
+- const char * dlerr;
++ const char* dlerr;
+ #endif
+
+ int err;
+@@ -410,7 +394,15 @@
+ #ifdef WIN32
+ char temp_driver_dir1[512];
+ char temp_driver_dir2[512];
+- GetCurrentDirectory(512, temp_driver_dir1);
++ if (3 < GetModuleFileName(NULL, temp_driver_dir1, 512)) {
++ char *p = strrchr(temp_driver_dir1, '\\');
++ if (p && (p != temp_driver_dir1))
++ *p = 0;
++ else
++ GetCurrentDirectory(512, temp_driver_dir1);
++ } else {
++ GetCurrentDirectory(512, temp_driver_dir1);
++ }
+ sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
+ driver_dir = temp_driver_dir2;
+ #else
+@@ -418,8 +410,9 @@
+ #endif
+ }
+
+- filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
+- sprintf (filename, "%s/%s", driver_dir, sofile);
++ int len = strlen(driver_dir) + 1 + strlen(sofile) + 1;
++ filename = (char*)malloc(len);
++ snprintf(filename, len, "%s/%s", driver_dir, sofile);
+
+ if ((dlhandle = LoadDriverModule(filename)) == NULL) {
+ #ifdef WIN32
+@@ -466,7 +459,7 @@
+
+ /* check it doesn't exist already */
+ for (node = drivers; node; node = jack_slist_next (node)) {
+- other_descriptor = (jack_driver_desc_t *) node->data;
++ other_descriptor = (jack_driver_desc_t*) node->data;
+
+ if (strcmp(descriptor->name, other_descriptor->name) == 0) {
+ jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first",
+@@ -494,16 +487,25 @@
+ #ifdef WIN32
+ char temp_driver_dir1[512];
+ char temp_driver_dir2[512];
+- GetCurrentDirectory(512, temp_driver_dir1);
+- sprintf(temp_driver_dir2, "%s/%s", temp_driver_dir1, ADDON_DIR);
++ if (3 < GetModuleFileName(NULL, temp_driver_dir1, 512)) {
++ char *p = strrchr(temp_driver_dir1, '\\');
++ if (p && (p != temp_driver_dir1))
++ *p = 0;
++ else
++ GetCurrentDirectory(512, temp_driver_dir1);
++ } else {
++ GetCurrentDirectory(512, temp_driver_dir1);
++ }
++ snprintf(temp_driver_dir2, sizeof(temp_driver_dir2), "%s/%s", temp_driver_dir1, ADDON_DIR);
+ driver_dir = temp_driver_dir2;
+ #else
+ driver_dir = ADDON_DIR;
+ #endif
+ }
+
+- char* filename = (char *)malloc(strlen (driver_dir) + 1 + strlen(sofile) + 1);
+- sprintf (filename, "%s/%s", driver_dir, sofile);
++ int len = strlen(driver_dir) + 1 + strlen(sofile) + 1;
++ char* filename = (char*)malloc(len);
++ snprintf(filename, len, "%s/%s", driver_dir, sofile);
+
+ if ((dlhandle = LoadDriverModule(filename)) == NULL) {
+ #ifdef WIN32
+@@ -524,24 +526,32 @@
+
+ JSList *
+ jack_drivers_load (JSList * drivers) {
+- char * driver_dir;
++ char* driver_dir;
+ char driver_dir_storage[512];
+ char dll_filename[512];
+ WIN32_FIND_DATA filedata;
+ HANDLE file;
+- const char * ptr = NULL;
+- JSList * driver_list = NULL;
+- jack_driver_desc_t * desc;
++ const char* ptr = NULL;
++ JSList* driver_list = NULL;
++ jack_driver_desc_t* desc = NULL;
+
+ if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
+ // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
+- GetCurrentDirectory(512, driver_dir_storage);
++ if (3 < GetModuleFileName(NULL, driver_dir_storage, 512)) {
++ char *p = strrchr(driver_dir_storage, '\\');
++ if (p && (p != driver_dir_storage))
++ *p = 0;
++ else
++ GetCurrentDirectory(512, driver_dir_storage);
++ } else {
++ GetCurrentDirectory(512, driver_dir_storage);
++ }
+ strcat(driver_dir_storage, "/");
+ strcat(driver_dir_storage, ADDON_DIR);
+ driver_dir = driver_dir_storage;
+ }
+
+- sprintf(dll_filename, "%s/*.dll", driver_dir);
++ snprintf(dll_filename, sizeof(dll_filename), "%s/*.dll", driver_dir);
+
+ file = (HANDLE )FindFirstFile(dll_filename, &filedata);
+
+@@ -551,6 +561,11 @@
+ }
+
+ do {
++ /* check the filename is of the right format */
++ if (strncmp ("jack_", filedata.cFileName, 5) != 0) {
++ continue;
++ }
++
+ ptr = strrchr (filedata.cFileName, '.');
+ if (!ptr) {
+ continue;
+@@ -560,6 +575,11 @@
+ continue;
+ }
+
++ /* check if dll is an internal client */
++ if (check_symbol(filedata.cFileName, "jack_internal_initialize")) {
++ continue;
++ }
++
+ desc = jack_get_descriptor (drivers, filedata.cFileName, "driver_get_descriptor");
+ if (desc) {
+ driver_list = jack_slist_append (driver_list, desc);
+@@ -583,10 +603,10 @@
+ jack_drivers_load (JSList * drivers) {
+ struct dirent * dir_entry;
+ DIR * dir_stream;
+- const char * ptr;
++ const char* ptr;
+ int err;
+- JSList * driver_list = NULL;
+- jack_driver_desc_t * desc;
++ JSList* driver_list = NULL;
++ jack_driver_desc_t* desc = NULL;
+
+ const char* driver_dir;
+ if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
+@@ -618,8 +638,12 @@
+ continue;
+ }
+
+- desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor");
++ /* check if dll is an internal client */
++ if (check_symbol(dir_entry->d_name, "jack_internal_initialize")) {
++ continue;
++ }
+
++ desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor");
+ if (desc) {
+ driver_list = jack_slist_append (driver_list, desc);
+ } else {
+@@ -647,29 +671,37 @@
+
+ JSList *
+ jack_internals_load (JSList * internals) {
+- char * driver_dir;
++ char* driver_dir;
+ char driver_dir_storage[512];
+ char dll_filename[512];
+ WIN32_FIND_DATA filedata;
+ HANDLE file;
+- const char * ptr = NULL;
+- JSList * driver_list = NULL;
+- jack_driver_desc_t * desc;
++ const char* ptr = NULL;
++ JSList* driver_list = NULL;
++ jack_driver_desc_t* desc;
+
+ if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
+ // for WIN32 ADDON_DIR is defined in JackConstants.h as relative path
+- GetCurrentDirectory(512, driver_dir_storage);
++ if (3 < GetModuleFileName(NULL, driver_dir_storage, 512)) {
++ char *p = strrchr(driver_dir_storage, '\\');
++ if (p && (p != driver_dir_storage))
++ *p = 0;
++ else
++ GetCurrentDirectory(512, driver_dir_storage);
++ } else {
++ GetCurrentDirectory(512, driver_dir_storage);
++ }
+ strcat(driver_dir_storage, "/");
+ strcat(driver_dir_storage, ADDON_DIR);
+ driver_dir = driver_dir_storage;
+ }
+
+- sprintf(dll_filename, "%s/*.dll", driver_dir);
++ snprintf(dll_filename, sizeof(dll_filename), "%s/*.dll", driver_dir);
+
+ file = (HANDLE )FindFirstFile(dll_filename, &filedata);
+
+ if (file == INVALID_HANDLE_VALUE) {
+- jack_error("error");
++ jack_error("could not open driver directory %s", driver_dir);
+ return NULL;
+ }
+
+@@ -712,10 +744,10 @@
+ jack_internals_load (JSList * internals) {
+ struct dirent * dir_entry;
+ DIR * dir_stream;
+- const char * ptr;
++ const char* ptr;
+ int err;
+- JSList * driver_list = NULL;
+- jack_driver_desc_t * desc;
++ JSList* driver_list = NULL;
++ jack_driver_desc_t* desc;
+
+ const char* driver_dir;
+ if ((driver_dir = getenv("JACK_DRIVER_DIR")) == 0) {
+@@ -779,7 +811,7 @@
+ #ifdef WIN32
+ int errstr;
+ #else
+- const char * errstr;
++ const char* errstr;
+ #endif
+
+ fHandle = LoadDriverModule (driver_desc->file);
+@@ -820,3 +852,106 @@
+ if (fHandle)
+ UnloadDriverModule(fHandle);
+ }
++
++SERVER_EXPORT
++jack_driver_desc_t*
++jack_driver_descriptor_construct(
++ const char * name,
++ jack_driver_type_t type,
++ const char * description,
++ jack_driver_desc_filler_t * filler_ptr)
++{
++ size_t name_len;
++ size_t description_len;
++ jack_driver_desc_t* desc_ptr;
++
++ name_len = strlen(name);
++ description_len = strlen(description);
++
++ if (name_len > sizeof(desc_ptr->name) - 1 ||
++ description_len > sizeof(desc_ptr->desc) - 1) {
++ assert(false);
++ return 0;
++ }
++
++ desc_ptr = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
++ if (desc_ptr == NULL) {
++ jack_error("calloc() failed to allocate memory for driver descriptor struct");
++ return 0;
++ }
++
++ memcpy(desc_ptr->name, name, name_len + 1);
++ memcpy(desc_ptr->desc, description, description_len + 1);
++
++ desc_ptr->nparams = 0;
++ desc_ptr->type = type;
++
++ if (filler_ptr != NULL) {
++ filler_ptr->size = 0;
++ }
++
++ return desc_ptr;
++}
++
++SERVER_EXPORT
++int
++jack_driver_descriptor_add_parameter(
++ jack_driver_desc_t* desc_ptr,
++ jack_driver_desc_filler_t * filler_ptr,
++ const char* name,
++ char character,
++ jack_driver_param_type_t type,
++ const jack_driver_param_value_t * value_ptr,
++ jack_driver_param_constraint_desc_t * constraint,
++ const char* short_desc,
++ const char* long_desc)
++{
++ size_t name_len;
++ size_t short_desc_len;
++ size_t long_desc_len;
++ jack_driver_param_desc_t * param_ptr;
++ size_t newsize;
++
++ name_len = strlen(name);
++ short_desc_len = strlen(short_desc);
++
++ if (long_desc != NULL) {
++ long_desc_len = strlen(long_desc);
++ } else {
++ long_desc = short_desc;
++ long_desc_len = short_desc_len;
++ }
++
++ if (name_len > sizeof(param_ptr->name) - 1 ||
++ short_desc_len > sizeof(param_ptr->short_desc) - 1 ||
++ long_desc_len > sizeof(param_ptr->long_desc) - 1) {
++ assert(false);
++ return 0;
++ }
++
++ if (desc_ptr->nparams == filler_ptr->size) {
++ newsize = filler_ptr->size + 20; // most drivers have less than 20 parameters
++ param_ptr = (jack_driver_param_desc_t*)realloc (desc_ptr->params, newsize * sizeof (jack_driver_param_desc_t));
++ if (param_ptr == NULL) {
++ jack_error("realloc() failed for parameter array of %zu elements", newsize);
++ return false;
++ }
++ filler_ptr->size = newsize;
++ desc_ptr->params = param_ptr;
++ }
++
++ assert(desc_ptr->nparams < filler_ptr->size);
++ param_ptr = desc_ptr->params + desc_ptr->nparams;
++
++ memcpy(param_ptr->name, name, name_len + 1);
++ param_ptr->character = character;
++ param_ptr->type = type;
++ param_ptr->value = *value_ptr;
++ param_ptr->constraint = constraint;
++ memcpy(param_ptr->short_desc, short_desc, short_desc_len + 1);
++ memcpy(param_ptr->long_desc, long_desc, long_desc_len + 1);
++
++ desc_ptr->nparams++;
++
++ return true;
++}
+--- a/common/JackDriverLoader.h
++++ b/common/JackDriverLoader.h
+@@ -27,10 +27,10 @@
+ #include "JackDriver.h"
+ #include "JackSystemDeps.h"
+
+-typedef jack_driver_desc_t * (*JackDriverDescFunction) ();
++typedef jack_driver_desc_t* (*JackDriverDescFunction) ();
+ typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*);
+
+-class JackDriverInfo
++class SERVER_EXPORT JackDriverInfo
+ {
+
+ private:
+@@ -54,14 +54,23 @@
+
+ };
+
+-jack_driver_desc_t * jack_find_driver_descriptor(JSList * drivers, const char * name);
++jack_driver_desc_t* jack_find_driver_descriptor(JSList* drivers, const char* name);
+
+-JSList * jack_drivers_load(JSList * drivers);
+-JSList * jack_internals_load(JSList * internals);
++JSList* jack_drivers_load(JSList* drivers);
++JSList* jack_internals_load(JSList* internals);
+
+-EXPORT int jackctl_parse_driver_params (jackctl_driver * driver_ptr, int argc, char* argv[]);
+-EXPORT void jack_free_driver_params(JSList * param_ptr);
+-EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file);
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++
++SERVER_EXPORT int jackctl_parse_driver_params (jackctl_driver * driver_ptr, int argc, char* argv[]);
++SERVER_EXPORT void jack_free_driver_params(JSList * param_ptr);
++SERVER_EXPORT void jack_print_driver_options(jack_driver_desc_t* desc, FILE* file);
++
++#ifdef __cplusplus
++}
++#endif
+
+ #endif
+
+--- a/common/JackDummyDriver.cpp
++++ b/common/JackDummyDriver.cpp
+@@ -19,71 +19,13 @@
+ */
+
+ #include "JackDummyDriver.h"
+-#include "JackEngineControl.h"
+-#include "JackGraphManager.h"
+ #include "JackDriverLoader.h"
+ #include "JackThreadedDriver.h"
+ #include "JackCompilerDeps.h"
+ #include <iostream>
+ #include <unistd.h>
++#include <math.h>
+
+-namespace Jack
+-{
+-
+-int JackDummyDriver::Open(jack_nframes_t buffer_size,
+- jack_nframes_t samplerate,
+- 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)
+-{
+- if (JackAudioDriver::Open(buffer_size,
+- samplerate,
+- capturing,
+- playing,
+- inchannels,
+- outchannels,
+- monitor,
+- capture_driver_name,
+- playback_driver_name,
+- capture_latency,
+- playback_latency) == 0) {
+- fEngineControl->fPeriod = 0;
+- fEngineControl->fComputation = 500 * 1000;
+- fEngineControl->fConstraint = 500 * 1000;
+- int buffer_size = int((fWaitTime * fEngineControl->fSampleRate) / 1000000.0f);
+- if (buffer_size > BUFFER_SIZE_MAX) {
+- buffer_size = BUFFER_SIZE_MAX;
+- jack_error("Buffer size set to %d ", BUFFER_SIZE_MAX);
+- }
+- SetBufferSize(buffer_size);
+- return 0;
+- } else {
+- return -1;
+- }
+-}
+-
+-int JackDummyDriver::Process()
+-{
+- JackDriver::CycleTakeBeginTime();
+- JackAudioDriver::Process();
+- JackSleep(std::max(0L, long(fWaitTime - (GetMicroSeconds() - fBeginDateUst))));
+- return 0;
+-}
+-
+-int JackDummyDriver::SetBufferSize(jack_nframes_t buffer_size)
+-{
+- JackAudioDriver::SetBufferSize(buffer_size);
+- fWaitTime = (unsigned long)((((float)buffer_size) / ((float)fEngineControl->fSampleRate)) * 1000000.0f);
+- return 0;
+-}
+-
+-} // end of namespace
+
+ #ifdef __cplusplus
+ extern "C"
+@@ -92,73 +34,36 @@
+
+ SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor () {
+ jack_driver_desc_t * desc;
+- unsigned int i;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("dummy", JackDriverMaster, "Timer based backend", &filler);
++
++ value.ui = 2U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamUInt, &value, NULL, "Number of capture ports", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamUInt, &value, NULL, "Number of playback ports", NULL);
++
++ value.ui = 48000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
+
+- desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
+- strcpy(desc->name, "dummy"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Timer based backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 6;
+- desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 2U;
+- strcpy(desc->params[i].short_desc, "Number of capture ports");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[1].value.ui = 2U;
+- strcpy(desc->params[i].short_desc, "Number of playback ports");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 48000U;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "monitor");
+- desc->params[i].character = 'm';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 1024U;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "wait");
+- desc->params[i].character = 'w';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 21333U;
+- strcpy(desc->params[i].short_desc,
+- "Number of usecs to wait between engine processes");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
++
++ value.ui = 1024U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = 21333U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "wait", 'w', JackDriverParamUInt, &value, NULL, "Number of usecs to wait between engine processes", NULL);
+
+ return desc;
+ }
+
+ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) {
+ jack_nframes_t sample_rate = 48000;
+- jack_nframes_t period_size = 1024;
++ jack_nframes_t buffer_size = 1024;
+ unsigned int capture_ports = 2;
+ unsigned int playback_ports = 2;
+- unsigned long wait_time = 0;
++ int wait_time = 0;
+ const JSList * node;
+ const jack_driver_param_t * param;
+ bool monitor = false;
+@@ -181,7 +86,7 @@
+ break;
+
+ case 'p':
+- period_size = param->value.ui;
++ buffer_size = param->value.ui;
+ break;
+
+ case 'w':
+@@ -194,11 +99,16 @@
+ }
+ }
+
+- if (wait_time == 0) // Not set
+- wait_time = (unsigned long)((((float)period_size) / ((float)sample_rate)) * 1000000.0f);
++ if (wait_time > 0) {
++ buffer_size = lroundf((wait_time * sample_rate) / 1000000.0f);
++ if (buffer_size > BUFFER_SIZE_MAX) {
++ buffer_size = BUFFER_SIZE_MAX;
++ jack_error("Buffer size set to %d", BUFFER_SIZE_MAX);
++ }
++ }
+
+- Jack::JackDriverClientInterface* driver = new Jack::JackThreadedDriver(new Jack::JackDummyDriver("system", "dummy_pcm", engine, table, wait_time));
+- if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports, monitor, "dummy", "dummy", 0, 0) == 0) {
++ Jack::JackDriverClientInterface* driver = new Jack::JackThreadedDriver(new Jack::JackDummyDriver("system", "dummy_pcm", engine, table));
++ if (driver->Open(buffer_size, sample_rate, 1, 1, capture_ports, playback_ports, monitor, "dummy", "dummy", 0, 0) == 0) {
+ return driver;
+ } else {
+ delete driver;
+--- a/common/JackDummyDriver.h
++++ b/common/JackDummyDriver.h
+@@ -21,7 +21,7 @@
+ #ifndef __JackDummyDriver__
+ #define __JackDummyDriver__
+
+-#include "JackAudioDriver.h"
++#include "JackTimedDriver.h"
+
+ namespace Jack
+ {
+@@ -30,41 +30,28 @@
+ \brief The dummy driver.
+ */
+
+-class JackDummyDriver : public JackAudioDriver
++class JackDummyDriver : public JackTimedDriver
+ {
+- private:
+-
+- long fWaitTime;
+
+ public:
+
+- JackDummyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, unsigned long wait_time)
+- : JackAudioDriver(name, alias, engine, table), fWaitTime(wait_time)
++ JackDummyDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
++ : JackTimedDriver(name, alias, engine, table)
+ {}
+ virtual ~JackDummyDriver()
+ {}
+
+- int Open(jack_nframes_t buffersize,
+- jack_nframes_t samplerate,
+- bool capturing,
+- bool playing,
+- int chan_in,
+- int chan_out,
+- bool monitor,
+- const char* capture_driver_name,
+- const char* playback_driver_name,
+- jack_nframes_t capture_latency,
+- jack_nframes_t playback_latency);
+-
+- int Process();
+-
+- // BufferSize can be changed
+- bool IsFixedBufferSize()
++ virtual int Process()
+ {
+- return false;
+- }
++ JackDriver::CycleTakeBeginTime();
+
+- int SetBufferSize(jack_nframes_t buffer_size);
++ if (JackAudioDriver::Process() < 0) {
++ return -1;
++ } else {
++ ProcessWait();
++ return 0;
++ }
++ }
+
+ };
+
+--- a/common/JackEngineControl.cpp
++++ b/common/JackEngineControl.cpp
+@@ -53,23 +53,37 @@
+ }
+
+ // Store the execution time for later averaging
+- fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime;
++ if (last_cycle_end > 0)
++ fRollingClientUsecs[fRollingClientUsecsIndex++] = last_cycle_end - fPrevCycleTime;
+ if (fRollingClientUsecsIndex >= JACK_ENGINE_ROLLING_COUNT)
+ fRollingClientUsecsIndex = 0;
+
+- // Every so often, recompute the current maximum use over the
+- // last JACK_ENGINE_ROLLING_COUNT client iterations.
+-
+- if (++fRollingClientUsecsCnt % fRollingInterval == 0) {
+-
++ // Each time we have a full set of iterations, recompute the current
++ // usage from the latest JACK_ENGINE_ROLLING_COUNT client entries.
++ if (fRollingClientUsecsCnt && (fRollingClientUsecsIndex == 0)) {
++ jack_time_t avg_usecs = 0;
+ jack_time_t max_usecs = 0;
+- for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++)
++
++ for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) {
++ avg_usecs += fRollingClientUsecs[i]; // This is really a running
++ // total to be averaged later
+ max_usecs = JACK_MAX(fRollingClientUsecs[i], max_usecs);
++ }
+
+ fMaxUsecs = JACK_MAX(fMaxUsecs, max_usecs);
+- fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0);
++
++ if (max_usecs < ((fPeriodUsecs * 95) / 100)) {
++ // Average the values from our JACK_ENGINE_ROLLING_COUNT array
++ fSpareUsecs = (jack_time_t)(fPeriodUsecs - (avg_usecs / JACK_ENGINE_ROLLING_COUNT));
++ } else {
++ // Use the 'worst case' value (or zero if we exceeded 'fPeriodUsecs')
++ fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0);
++ }
++
+ fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f));
+ }
++
++ fRollingClientUsecsCnt++;
+ }
+
+ void JackEngineControl::ResetRollingUsecs()
+--- a/common/JackEngineControl.h
++++ b/common/JackEngineControl.h
+@@ -45,6 +45,7 @@
+ \brief Engine control in shared memory.
+ */
+
++PRE_PACKED_STRUCTURE
+ struct SERVER_EXPORT JackEngineControl : public JackShmMem
+ {
+ // Shared state
+@@ -69,12 +70,12 @@
+ bool fVerbose;
+
+ // CPU Load
+- jack_time_t fPrevCycleTime;
+- jack_time_t fCurCycleTime;
+- jack_time_t fSpareUsecs;
+- jack_time_t fMaxUsecs;
+- jack_time_t fRollingClientUsecs[JACK_ENGINE_ROLLING_COUNT];
+- int fRollingClientUsecsCnt;
++ jack_time_t fPrevCycleTime;
++ jack_time_t fCurCycleTime;
++ jack_time_t fSpareUsecs;
++ jack_time_t fMaxUsecs;
++ jack_time_t fRollingClientUsecs[JACK_ENGINE_ROLLING_COUNT];
++ unsigned int fRollingClientUsecsCnt;
+ int fRollingClientUsecsIndex;
+ int fRollingInterval;
+ float fCPULoad;
+--- a/common/JackEngine.cpp
++++ b/common/JackEngine.cpp
+@@ -140,7 +140,6 @@
+ fLastSwitchUsecs = cur_cycle_begin;
+ if (fGraphManager->RunNextGraph()) { // True if the graph actually switched to a new state
+ fChannel.Notify(ALL_CLIENTS, kGraphOrderCallback, 0);
+- //NotifyGraphReorder();
+ }
+ fSignal.Signal(); // Signal for threads waiting for next cycle
+ }
+@@ -198,13 +197,11 @@
+ if (status != NotTriggered && status != Finished) {
+ jack_error("JackEngine::XRun: client = %s was not run: state = %ld", client->GetClientControl()->fName, status);
+ fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients
+- //NotifyXRun(ALL_CLIENTS);
+ }
+
+ if (status == Finished && (long)(finished_date - callback_usecs) > 0) {
+ jack_error("JackEngine::XRun: client %s finished after current callback", client->GetClientControl()->fName);
+ fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0); // Notify all clients
+- //NotifyXRun(ALL_CLIENTS);
+ }
+ }
+ }
+@@ -250,11 +247,11 @@
+ /*
+ Important for internal clients : unlock before calling the notification callbacks.
+ */
+- bool res = fMutex.Unlock();
++ bool res = Unlock();
+ 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);
+ if (res)
+- fMutex.Lock();
++ Lock();
+
+ } else {
+ jack_log("JackEngine::NotifyClient: no callback for event = %ld", event);
+@@ -275,10 +272,10 @@
+ // Notify existing clients of the new client and new client of existing clients.
+ 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 && old_client != new_client) {
++ if (old_client->ClientNotify(refnum, name, kAddClient, false, "", 0, 0) < 0) {
+ jack_error("NotifyAddClient old_client fails name = %s", old_client->GetClientControl()->fName);
+- return -1;
++ // Not considered as a failure...
+ }
+ if (new_client->ClientNotify(i, old_client->GetClientControl()->fName, kAddClient, true, "", 0, 0) < 0) {
+ jack_error("NotifyAddClient new_client fails name = %s", name);
+@@ -296,7 +293,7 @@
+ 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, false, "", 0, 0);
+ }
+ }
+ }
+@@ -307,7 +304,6 @@
+ // Use the audio thread => request thread communication channel
+ fEngineControl->NotifyXRun(callback_usecs, delayed_usecs);
+ fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
+- //NotifyXRun(ALL_CLIENTS);
+ }
+
+ void JackEngine::NotifyXRun(int refnum)
+@@ -427,7 +423,7 @@
+ *status = 0;
+ strcpy(name_res, name);
+
+- jack_log("Check protocol client %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);
++ jack_log("Check protocol client = %ld server = %ld", protocol, JACK_PROTOCOL_VERSION);
+
+ if (protocol != JACK_PROTOCOL_VERSION) {
+ *status |= (JackFailure | JackVersionError);
+@@ -563,7 +559,6 @@
+ } else {
+ strncpy(real_name, name, JACK_CLIENT_NAME_SIZE);
+ }
+-
+ EnsureUUID(uuid);
+ }
+
+@@ -686,12 +681,12 @@
+ int i;
+
+ fGraphManager->GetInputPorts(refnum, ports);
+- for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) {
++ for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) {
+ PortUnRegister(refnum, ports[i]);
+ }
+
+ fGraphManager->GetOutputPorts(refnum, ports);
+- for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY) ; i++) {
++ for (i = 0; (i < PORT_NUM_FOR_CLIENT) && (ports[i] != EMPTY); i++) {
+ PortUnRegister(refnum, ports[i]);
+ }
+
+@@ -804,6 +799,7 @@
+ return -1;
+ }
+
++ // buffer_size is actually ignored...
+ *port_index = fGraphManager->AllocatePort(refnum, name, type, (JackPortFlags)flags, fEngineControl->fBufferSize);
+ if (*port_index != NO_PORT) {
+ if (client->GetClientControl()->fActive)
+@@ -925,7 +921,7 @@
+
+ int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name)
+ {
+- char old_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
++ char old_name[REAL_JACK_PORT_NAME_SIZE];
+ strcpy(old_name, fGraphManager->GetPort(port)->GetName());
+ fGraphManager->GetPort(port)->SetName(name);
+ NotifyPortRename(port, old_name);
+@@ -936,12 +932,15 @@
+ // Session management
+ //--------------------
+
+-void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket)
++void JackEngine::SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result)
+ {
+ if (fSessionPendingReplies != 0) {
+ JackSessionNotifyResult res(-1);
+ res.Write(socket);
+ jack_log("JackEngine::SessionNotify ... busy");
++ if (result != NULL) {
++ *result = NULL;
++ }
+ return;
+ }
+
+@@ -965,30 +964,36 @@
+ }
+
+ char path_buf[JACK_PORT_NAME_SIZE];
+- snprintf( path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR );
++ snprintf(path_buf, sizeof(path_buf), "%s%s%c", path, client->GetClientControl()->fName, DIR_SEPARATOR);
+
+ int res = JackTools::MkDir(path_buf);
+ if (res)
+- jack_error( "JackEngine::SessionNotify: can not create session directory '%s'", path_buf );
++ jack_error("JackEngine::SessionNotify: can not create session directory '%s'", path_buf);
+
+- int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int) type, 0);
++ int result = client->ClientNotify(i, client->GetClientControl()->fName, kSessionCallback, true, path_buf, (int)type, 0);
+
+- if (result == 2) {
++ if (result == kPendingSessionReply) {
+ fSessionPendingReplies += 1;
+- } else if (result == 1) {
++ } else if (result == kImmediateSessionReply) {
+ char uuid_buf[JACK_UUID_SIZE];
+- snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID );
+- fSessionResult->fCommandList.push_back( JackSessionCommand( uuid_buf,
+- client->GetClientControl()->fName,
+- client->GetClientControl()->fSessionCommand,
+- client->GetClientControl()->fSessionFlags ));
++ snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID);
++ fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf,
++ client->GetClientControl()->fName,
++ client->GetClientControl()->fSessionCommand,
++ client->GetClientControl()->fSessionFlags));
+ }
+ }
+ }
+
++ if (result != NULL) {
++ *result = fSessionResult;
++ }
++
+ if (fSessionPendingReplies == 0) {
+ fSessionResult->Write(socket);
+- delete fSessionResult;
++ if (result == NULL) {
++ delete fSessionResult;
++ }
+ fSessionResult = NULL;
+ } else {
+ fSessionTransaction = socket;
+@@ -999,7 +1004,7 @@
+ {
+ JackClientInterface* client = fClientTable[refnum];
+ char uuid_buf[JACK_UUID_SIZE];
+- snprintf( uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID);
++ snprintf(uuid_buf, sizeof(uuid_buf), "%d", client->GetClientControl()->fSessionID);
+ fSessionResult->fCommandList.push_back(JackSessionCommand(uuid_buf,
+ client->GetClientControl()->fName,
+ client->GetClientControl()->fSessionCommand,
+@@ -1008,7 +1013,10 @@
+
+ if (fSessionPendingReplies == 0) {
+ fSessionResult->Write(fSessionTransaction);
+- delete fSessionResult;
++ if (fSessionTransaction != NULL)
++ {
++ delete fSessionResult;
++ }
+ fSessionResult = NULL;
+ }
+ }
+@@ -1064,11 +1072,11 @@
+ *result = 0;
+ }
+
+-void JackEngine::ClientHasSessionCallbackRequest(const char *name, int *result)
++void JackEngine::ClientHasSessionCallback(const char *name, int *result)
+ {
+ JackClientInterface* client = NULL;
+ for (int i = 0; i < CLIENT_NUM; i++) {
+- JackClientInterface* client = fClientTable[i];
++ client = fClientTable[i];
+ if (client && (strcmp(client->GetClientControl()->fName, name) == 0))
+ break;
+ }
+--- a/common/JackEngine.h
++++ b/common/JackEngine.h
+@@ -54,8 +54,8 @@
+ jack_time_t fLastSwitchUsecs;
+
+ int fSessionPendingReplies;
+- JackChannelTransaction *fSessionTransaction;
+- JackSessionNotifyResult *fSessionResult;
++ JackChannelTransaction* fSessionTransaction;
++ JackSessionNotifyResult* fSessionResult;
+ std::map<int,std::string> fReservationMap;
+ int fMaxUUID;
+
+@@ -145,13 +145,13 @@
+ void NotifyQuit();
+
+ // Session management
+- void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket);
++ void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result);
+ void SessionReply(int refnum);
+
+ void GetUUIDForClientName(const char *client_name, char *uuid_res, int *result);
+ void GetClientNameForUUID(const char *uuid, char *name_res, int *result);
+ void ReserveClientName(const char *name, const char *uuid, int *result);
+- void ClientHasSessionCallbackRequest(const char *name, int *result);
++ void ClientHasSessionCallback(const char *name, int *result);
+ };
+
+
+--- a/common/JackEngineProfiling.cpp
++++ b/common/JackEngineProfiling.cpp
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -34,7 +34,7 @@
+ JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0)
+ {
+ jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024));
+-
++
+ // Force memory page in
+ memset(fProfileTable, 0, sizeof(fProfileTable));
+ }
+@@ -47,32 +47,32 @@
+ if (!fStream.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file");
+ } else {
+-
++
+ // For each measured point
+ for (int i = 2; i < TIME_POINTS; i++) {
+-
++
+ // Driver timing values
+ long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin);
+ long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin);
+-
++
+ if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0)
+ continue; // Skip non valid cycles
+-
++
+ // Print driver delta and end cycle
+ fStream << d1 << "\t" << d2 << "\t";
+-
++
+ // For each measured client
+- for (unsigned int j = 0; j < fMeasuredClient; j++) {
+-
++ for (unsigned int j = 0; j < fMeasuredClient; j++) {
++
+ int ref = fIntervalTable[j].fRefNum;
+-
+- // Is valid client cycle
+- if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
+-
++
++ // Is valid client cycle
++ if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) {
++
+ long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin);
+ long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin);
+ long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin);
+-
++
+ fStream << ref << "\t" ;
+ fStream << ((d5 > 0) ? d5 : 0) << "\t";
+ fStream << ((d6 > 0) ? d6 : 0) << "\t" ;
+@@ -80,57 +80,57 @@
+ fStream << ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0) << "\t" ;
+ fStream << ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0) << "\t" ;
+ fStream << fProfileTable[i].fClientTable[ref].fStatus << "\t" ;;
+-
++
+ } else { // Print tabs
+ fStream << "\t \t \t \t \t \t \t";
+ }
+ }
+-
++
+ // Terminate line
+ fStream << std::endl;
+ }
+ }
+-
++
+ // Driver period
+ std::ofstream fStream1("Timing1.plot", std::ios_base::ate);
+-
++
+ if (!fStream1.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open Timing1.plot file");
+ } else {
+-
++
+ fStream1 << "set grid\n";
+ fStream1 << "set title \"Audio driver timing\"\n";
+ fStream1 << "set xlabel \"audio cycles\"\n";
+ fStream1 << "set ylabel \"usec\"\n";
+ fStream1 << "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n";
+-
++
+ fStream1 << "set output 'Timing1.svg\n";
+ fStream1 << "set terminal svg\n";
+-
++
+ fStream1 << "set grid\n";
+ fStream1 << "set title \"Audio driver timing\"\n";
+ fStream1 << "set xlabel \"audio cycles\"\n";
+ fStream1 << "set ylabel \"usec\"\n";
+ fStream1 << "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n";
+- fStream1 << "unset output\n";
++ fStream1 << "unset output\n";
+ }
+-
++
+ // Driver end date
+ std::ofstream fStream2("Timing2.plot", std::ios_base::ate);
+-
++
+ if (!fStream2.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open Timing2.plot file");
+ } else {
+-
++
+ fStream2 << "set grid\n";
+ fStream2 << "set title \"Driver end date\"\n";
+ fStream2 << "set xlabel \"audio cycles\"\n";
+ fStream2 << "set ylabel \"usec\"\n";
+ fStream2 << "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n";
+-
++
+ fStream2 << "set output 'Timing2.svg\n";
+ fStream2 << "set terminal svg\n";
+-
++
+ fStream2 << "set grid\n";
+ fStream2 << "set title \"Driver end date\"\n";
+ fStream2 << "set xlabel \"audio cycles\"\n";
+@@ -138,15 +138,15 @@
+ fStream2 << "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n";
+ fStream2 << "unset output\n";
+ }
+-
++
+ // Clients end date
+ if (fMeasuredClient > 0) {
+ std::ofstream fStream3("Timing3.plot", std::ios_base::ate);
+-
++
+ if (!fStream3.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open Timing3.plot file");
+ } else {
+-
++
+ fStream3 << "set multiplot\n";
+ fStream3 << "set grid\n";
+ fStream3 << "set title \"Clients end date\"\n";
+@@ -170,11 +170,11 @@
+ fStream3 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) - 1 << " title \"" << fIntervalTable[i].fName << "\" with lines,";
+ }
+ }
+-
+- fStream3 << "\n unset multiplot\n";
++
++ fStream3 << "\n unset multiplot\n";
+ fStream3 << "set output 'Timing3.svg\n";
+ fStream3 << "set terminal svg\n";
+-
++
+ fStream3 << "set multiplot\n";
+ fStream3 << "set grid\n";
+ fStream3 << "set title \"Clients end date\"\n";
+@@ -206,11 +206,11 @@
+ // Clients scheduling
+ if (fMeasuredClient > 0) {
+ std::ofstream fStream4("Timing4.plot", std::ios_base::ate);
+-
++
+ if (!fStream4.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open Timing4.plot file");
+ } else {
+-
++
+ fStream4 << "set multiplot\n";
+ fStream4 << "set grid\n";
+ fStream4 << "set title \"Clients scheduling latency\"\n";
+@@ -224,11 +224,11 @@
+ fStream4 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) << " title \"" << fIntervalTable[i].fName << "\" with lines,";
+ }
+ }
+-
+- fStream4 << "\n unset multiplot\n";
++
++ fStream4 << "\n unset multiplot\n";
+ fStream4 << "set output 'Timing4.svg\n";
+ fStream4 << "set terminal svg\n";
+-
++
+ fStream4 << "set multiplot\n";
+ fStream4 << "set grid\n";
+ fStream4 << "set title \"Clients scheduling latency\"\n";
+@@ -246,7 +246,7 @@
+ fStream4 << "unset output\n";
+ }
+ }
+-
++
+ // Clients duration
+ if (fMeasuredClient > 0) {
+ std::ofstream fStream5("Timing5.plot", std::ios_base::ate);
+@@ -254,7 +254,7 @@
+ if (!fStream5.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open Timing5.plot file");
+ } else {
+-
++
+ fStream5 << "set multiplot\n";
+ fStream5 << "set grid\n";
+ fStream5 << "set title \"Clients duration\"\n";
+@@ -268,11 +268,11 @@
+ fStream5 << "\"JackEngineProfiling.log\" using " << ((i + 1) * 7) + 1 << " title \"" << fIntervalTable[i].fName << "\" with lines,";
+ }
+ }
+-
+- fStream5 << "\n unset multiplot\n";
++
++ fStream5 << "\n unset multiplot\n";
+ fStream5 << "set output 'Timing5.svg\n";
+ fStream5 << "set terminal svg\n";
+-
++
+ fStream5 << "set multiplot\n";
+ fStream5 << "set grid\n";
+ fStream5 << "set title \"Clients duration\"\n";
+@@ -290,7 +290,7 @@
+ fStream5 << "unset output\n";
+ }
+ }
+-
++
+ std::ofstream fStream6("Timings.html", std::ios_base::ate);
+ if (!fStream6.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open Timings.html file");
+@@ -315,8 +315,8 @@
+ fStream6 << " <div class='center'><object class='center' type='image/svg+xml' data='Timing5.svg'>Timing5</object></div>";
+ fStream6 << " </body>\n";
+ fStream6 << "</html>\n";
+- }
+-
++ }
++
+ std::ofstream fStream7("generate_timings", std::ios_base::ate);
+ if (!fStream7.is_open()) {
+ jack_error("JackEngineProfiling::Save cannot open generate_timings file");
+@@ -326,7 +326,7 @@
+ fStream7 << "gnuplot -persist Timing3.plot\n";
+ fStream7 << "gnuplot -persist Timing4.plot\n";
+ fStream7 << "gnuplot -persist Timing5.plot\n";
+- }
++ }
+ }
+
+ bool JackEngineProfiling::CheckClient(const char* name, int cur_point)
+@@ -340,14 +340,14 @@
+ return false;
+ }
+
+-void JackEngineProfiling::Profile(JackClientInterface** table,
+- JackGraphManager* manager,
++void JackEngineProfiling::Profile(JackClientInterface** table,
++ JackGraphManager* manager,
+ jack_time_t period_usecs,
+- jack_time_t cur_cycle_begin,
++ jack_time_t cur_cycle_begin,
+ jack_time_t prev_cycle_end)
+ {
+ fAudioCycle = (fAudioCycle + 1) % TIME_POINTS;
+-
++
+ // Keeps cycle data
+ fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs;
+ fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin;
+@@ -358,7 +358,7 @@
+ JackClientInterface* client = table[i];
+ JackClientTiming* timing = manager->GetClientTiming(i);
+ if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) {
+-
++
+ if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) {
+ // Keep new measured client
+ fIntervalTable[fMeasuredClient].fRefNum = i;
+@@ -380,5 +380,5 @@
+ {
+ return &fProfileTable[fAudioCycle];
+ }
+-
++
+ } // end of namespace
+--- a/common/JackEngineProfiling.h
++++ b/common/JackEngineProfiling.h
+@@ -37,6 +37,7 @@
+ \brief Timing stucture for a client.
+ */
+
++PRE_PACKED_STRUCTURE
+ struct JackTimingMeasureClient
+ {
+ int fRefNum;
+@@ -59,6 +60,7 @@
+ \brief Timing interval in the global table for a given client
+ */
+
++PRE_PACKED_STRUCTURE
+ struct JackTimingClientInterval
+ {
+ int fRefNum;
+@@ -78,6 +80,7 @@
+ \brief Timing stucture for a table of clients.
+ */
+
++PRE_PACKED_STRUCTURE
+ struct JackTimingMeasure
+ {
+ unsigned int fAudioCycle;
+@@ -102,6 +105,7 @@
+ class JackClientInterface;
+ class JackGraphManager;
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackEngineProfiling
+ {
+
+--- a/common/JackError.cpp
++++ b/common/JackError.cpp
+@@ -33,7 +33,7 @@
+ && jack_tls_set(JackGlobals::fKeyLogFunction, (void*)log_function));
+ }
+
+-EXPORT int set_threaded_log_function()
++SERVER_EXPORT int set_threaded_log_function()
+ {
+ return change_thread_log_function(JackMessageBufferAdd);
+ }
+@@ -88,7 +88,7 @@
+ log_function(level, buffer);
+ }
+
+-EXPORT void jack_error(const char *fmt, ...)
++SERVER_EXPORT void jack_error(const char *fmt, ...)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+@@ -96,7 +96,7 @@
+ va_end(ap);
+ }
+
+-EXPORT void jack_info(const char *fmt, ...)
++SERVER_EXPORT void jack_info(const char *fmt, ...)
+ {
+ va_list ap;
+ va_start(ap, fmt);
+@@ -104,7 +104,7 @@
+ va_end(ap);
+ }
+
+-EXPORT void jack_log(const char *fmt,...)
++SERVER_EXPORT void jack_log(const char *fmt,...)
+ {
+ if (JackGlobals::fVerbose) {
+ va_list ap;
+@@ -114,23 +114,23 @@
+ }
+ }
+
+-EXPORT void default_jack_error_callback(const char *desc)
++SERVER_EXPORT void default_jack_error_callback(const char *desc)
+ {
+ fprintf(stderr, "%s\n", desc);
+ fflush(stderr);
+ }
+
+-EXPORT void default_jack_info_callback(const char *desc)
++SERVER_EXPORT void default_jack_info_callback(const char *desc)
+ {
+ fprintf(stdout, "%s\n", desc);
+ fflush(stdout);
+ }
+
+-EXPORT void silent_jack_error_callback(const char *desc)
++SERVER_EXPORT void silent_jack_error_callback(const char *desc)
+ {}
+
+-EXPORT void silent_jack_info_callback(const char *desc)
++SERVER_EXPORT void silent_jack_info_callback(const char *desc)
+ {}
+
+-EXPORT void (*jack_error_callback)(const char *desc) = &default_jack_error_callback;
+-EXPORT void (*jack_info_callback)(const char *desc) = &default_jack_info_callback;
++SERVER_EXPORT void (*jack_error_callback)(const char *desc) = &default_jack_error_callback;
++SERVER_EXPORT void (*jack_info_callback)(const char *desc) = &default_jack_info_callback;
+--- a/common/JackError.h
++++ b/common/JackError.h
+@@ -34,27 +34,27 @@
+ #define LOG_LEVEL_INFO 1
+ #define LOG_LEVEL_ERROR 2
+
+- EXPORT void jack_error(const char *fmt, ...);
++ SERVER_EXPORT void jack_error(const char *fmt, ...);
+
+- EXPORT void jack_info(const char *fmt, ...);
++ SERVER_EXPORT void jack_info(const char *fmt, ...);
+
+ // like jack_info() but only if verbose mode is enabled
+- EXPORT void jack_log(const char *fmt, ...);
++ SERVER_EXPORT void jack_log(const char *fmt, ...);
+
+- EXPORT extern void (*jack_error_callback)(const char *desc);
+- EXPORT extern void (*jack_info_callback)(const char *desc);
++ SERVER_EXPORT extern void (*jack_error_callback)(const char *desc);
++ SERVER_EXPORT extern void (*jack_info_callback)(const char *desc);
+
+- EXPORT extern void default_jack_error_callback(const char *desc);
+- EXPORT extern void default_jack_info_callback(const char *desc);
++ SERVER_EXPORT extern void default_jack_error_callback(const char *desc);
++ SERVER_EXPORT extern void default_jack_info_callback(const char *desc);
+
+- EXPORT extern void silent_jack_error_callback(const char *desc);
+- EXPORT extern void silent_jack_info_callback(const char *desc);
++ SERVER_EXPORT extern void silent_jack_error_callback(const char *desc);
++ SERVER_EXPORT extern void silent_jack_info_callback(const char *desc);
+
+ typedef void (* jack_log_function_t)(int level, const char *message);
+
+ void jack_log_function(int level, const char *message);
+
+- EXPORT int set_threaded_log_function();
++ SERVER_EXPORT int set_threaded_log_function();
+
+ #ifdef __cplusplus
+ }
+--- a/common/JackException.h
++++ b/common/JackException.h
+@@ -29,6 +29,13 @@
+ namespace Jack
+ {
+
++#define ThrowIf(inCondition, inException) \
++ if(inCondition) \
++ { \
++ throw(inException); \
++ }
++
++
+ /*!
+ \brief Exception base class.
+ */
+@@ -52,8 +59,9 @@
+ void PrintMessage()
+ {
+ std::string str = what();
+- if (str != "")
++ if (str != "") {
+ jack_info(str.c_str());
++ }
+ }
+ };
+
+@@ -62,9 +70,9 @@
+ */
+
+ class SERVER_EXPORT JackTemporaryException : public JackException {
+-
++
+ public:
+-
++
+ JackTemporaryException(const std::string& msg) : JackException(msg)
+ {}
+ JackTemporaryException(char* msg) : JackException(msg)
+@@ -74,15 +82,15 @@
+ JackTemporaryException() : JackException("")
+ {}
+ };
+-
++
+ /*!
+- \brief
++ \brief
+ */
+
+ class SERVER_EXPORT JackQuitException : public JackException {
+-
++
+ public:
+-
++
+ JackQuitException(const std::string& msg) : JackException(msg)
+ {}
+ JackQuitException(char* msg) : JackException(msg)
+@@ -92,7 +100,7 @@
+ JackQuitException() : JackException("")
+ {}
+ };
+-
++
+ /*!
+ \brief Exception possibly thrown by Net slaves.
+ */
+--- a/common/JackExternalClient.cpp
++++ b/common/JackExternalClient.cpp
+@@ -36,7 +36,7 @@
+ 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);
++ jack_log("JackExternalClient::ClientNotify ref = %ld client = %s name = %s notify = %ld", refnum, fClientControl->fName, name, notify);
+ fChannel.ClientNotify(refnum, name, notify, sync, message, value1, value2, &result);
+ return result;
+ }
+@@ -49,17 +49,17 @@
+ jack_error("Cannot connect to client name = %s\n", name);
+ return -1;
+ }
+-
++
+ // Use "placement new" to allocate object in shared memory
+ JackShmMemAble* shared_mem = static_cast<JackShmMemAble*>(JackShmMem::operator new(sizeof(JackClientControl)));
+ shared_mem->Init();
+ fClientControl = new(shared_mem) JackClientControl(name, pid, refnum, uuid);
+-
++
+ if (!fClientControl) {
+ jack_error("Cannot allocate client shared memory segment");
+ return -1;
+ }
+-
++
+ *shared_client = shared_mem->GetShmIndex();
+ jack_log("JackExternalClient::Open name = %s index = %ld base = %x", name, shared_mem->GetShmIndex(), shared_mem->GetShmAddress());
+ return 0;
+@@ -71,6 +71,7 @@
+
+ int JackExternalClient::Close()
+ {
++ jack_log("JackExternalClient::Close");
+ fChannel.Close();
+ if (fClientControl) {
+ fClientControl->~JackClientControl();
+--- a/common/JackExternalClient.h
++++ b/common/JackExternalClient.h
+@@ -38,8 +38,8 @@
+
+ private:
+
+- JackNotifyChannel fChannel; /*! Server/client communication channel */
+- JackClientControl* fClientControl; /*! Client control in shared memory */
++ JackNotifyChannel fChannel; /*! Server/client communication channel */
++ JackClientControl* fClientControl; /*! Client control in shared memory */
+
+ public:
+
+--- a/common/JackFilters.h
++++ b/common/JackFilters.h
+@@ -20,33 +20,42 @@
+ #ifndef __JackFilters__
+ #define __JackFilters__
+
++#ifdef __APPLE__
++#include <TargetConditionals.h>
++#endif
++
+ #include "jack.h"
++#ifndef MY_TARGET_OS_IPHONE
+ #include "JackAtomicState.h"
++#endif
+ #include <math.h>
+ #include <stdlib.h>
+
+ namespace Jack
+ {
+
++#ifndef TARGET_OS_IPHONE
++
+ #define MAX_SIZE 64
+-
+- struct JackFilter
++
++ PRE_PACKED_STRUCTURE
++ struct JackFilter
+ {
+-
++
+ jack_time_t fTable[MAX_SIZE];
+-
++
+ JackFilter()
+ {
+ for (int i = 0; i < MAX_SIZE; i++)
+ fTable[i] = 0;
+ }
+-
++
+ void AddValue(jack_time_t val)
+ {
+ memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
+ fTable[0] = val;
+ }
+-
++
+ jack_time_t GetVal()
+ {
+ jack_time_t mean = 0;
+@@ -54,14 +63,15 @@
+ mean += fTable[i];
+ return mean / MAX_SIZE;
+ }
+-
++
+ } POST_PACKED_STRUCTURE;
+-
++
++ PRE_PACKED_STRUCTURE
+ class JackDelayLockedLoop
+ {
+-
++
+ private:
+-
++
+ jack_nframes_t fFrames;
+ jack_time_t fCurrentWakeup;
+ jack_time_t fCurrentCallback;
+@@ -72,17 +82,17 @@
+ jack_time_t fPeriodUsecs;
+ float fFilterCoefficient; /* set once, never altered */
+ bool fUpdating;
+-
++
+ public:
+-
++
+ JackDelayLockedLoop()
+ {}
+-
++
+ JackDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
+ {
+ Init(buffer_size, sample_rate);
+ }
+-
++
+ void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
+ {
+ fFrames = 0;
+@@ -95,7 +105,7 @@
+ fSampleRate = sample_rate;
+ fPeriodUsecs = jack_time_t(1000000.f / fSampleRate * fBufferSize); // in microsec
+ }
+-
++
+ void Init(jack_time_t callback_usecs)
+ {
+ fFrames = 0;
+@@ -104,7 +114,7 @@
+ fCurrentCallback = callback_usecs;
+ fNextWakeUp = callback_usecs + fPeriodUsecs;
+ }
+-
++
+ void IncFrame(jack_time_t callback_usecs)
+ {
+ float delta = (int64_t)callback_usecs - (int64_t)fNextWakeUp;
+@@ -114,41 +124,42 @@
+ fSecondOrderIntegrator += 0.5f * fFilterCoefficient * delta;
+ fNextWakeUp = fCurrentWakeup + fPeriodUsecs + (int64_t) floorf((fFilterCoefficient * (delta + fSecondOrderIntegrator)));
+ }
+-
++
+ jack_nframes_t Time2Frames(jack_time_t time)
+ {
+ long delta = (long) rint(((double) ((long long)(time - fCurrentWakeup)) / ((long long)(fNextWakeUp - fCurrentWakeup))) * fBufferSize);
+ return (delta < 0) ? ((fFrames > 0) ? fFrames : 1) : (fFrames + delta);
+ }
+-
++
+ jack_time_t Frames2Time(jack_nframes_t frames)
+ {
+ long delta = (long) rint(((double) ((long long)(frames - fFrames)) * ((long long)(fNextWakeUp - fCurrentWakeup))) / fBufferSize);
+ return (delta < 0) ? ((fCurrentWakeup > 0) ? fCurrentWakeup : 1) : (fCurrentWakeup + delta);
+ }
+-
++
+ jack_nframes_t CurFrame()
+ {
+ return fFrames;
+ }
+-
++
+ jack_time_t CurTime()
+ {
+ return fCurrentWakeup;
+ }
+-
++
+ } POST_PACKED_STRUCTURE;
+-
++
++ PRE_PACKED_STRUCTURE
+ class JackAtomicDelayLockedLoop : public JackAtomicState<JackDelayLockedLoop>
+ {
+ public:
+-
++
+ JackAtomicDelayLockedLoop(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
+ {
+ fState[0].Init(buffer_size, sample_rate);
+ fState[1].Init(buffer_size, sample_rate);
+ }
+-
++
+ void Init(jack_time_t callback_usecs)
+ {
+ JackDelayLockedLoop* dll = WriteNextStateStart();
+@@ -156,7 +167,7 @@
+ WriteNextStateStop();
+ TrySwitchState(); // always succeed since there is only one writer
+ }
+-
++
+ void Init(jack_nframes_t buffer_size, jack_nframes_t sample_rate)
+ {
+ JackDelayLockedLoop* dll = WriteNextStateStart();
+@@ -164,7 +175,7 @@
+ WriteNextStateStop();
+ TrySwitchState(); // always succeed since there is only one writer
+ }
+-
++
+ void IncFrame(jack_time_t callback_usecs)
+ {
+ JackDelayLockedLoop* dll = WriteNextStateStart();
+@@ -172,44 +183,46 @@
+ WriteNextStateStop();
+ TrySwitchState(); // always succeed since there is only one writer
+ }
+-
++
+ jack_nframes_t Time2Frames(jack_time_t time)
+ {
+ UInt16 next_index = GetCurrentIndex();
+ UInt16 cur_index;
+ jack_nframes_t res;
+-
++
+ do {
+ cur_index = next_index;
+ res = ReadCurrentState()->Time2Frames(time);
+ next_index = GetCurrentIndex();
+ } while (cur_index != next_index); // Until a coherent state has been read
+-
++
+ return res;
+ }
+-
++
+ jack_time_t Frames2Time(jack_nframes_t frames)
+ {
+ UInt16 next_index = GetCurrentIndex();
+ UInt16 cur_index;
+ jack_time_t res;
+-
++
+ do {
+ cur_index = next_index;
+ res = ReadCurrentState()->Frames2Time(frames);
+ next_index = GetCurrentIndex();
+ } while (cur_index != next_index); // Until a coherent state has been read
+-
++
+ return res;
+ }
+ } POST_PACKED_STRUCTURE;
+-
++
++#endif
++
+ /*
+ Torben Hohn PI controler from JACK1
+ */
+-
++
+ struct JackPIControler {
+-
++
+ double resample_mean;
+ double static_resample_factor;
+
+@@ -224,12 +237,12 @@
+ double pclamp;
+ double controlquant;
+ int smooth_size;
+-
++
+ double hann(double x)
+ {
+ return 0.5 * (1.0 - cos(2 * M_PI * x));
+ }
+-
++
+ JackPIControler(double resample_factor, int fir_size)
+ {
+ resample_mean = resample_factor;
+@@ -239,7 +252,7 @@
+ offset_differential_index = 0;
+ offset_integral = 0.0;
+ smooth_size = fir_size;
+-
++
+ for (int i = 0; i < fir_size; i++) {
+ offset_array[i] = 0.0;
+ window_array[i] = hann(double(i) / (double(fir_size) - 1.0));
+@@ -251,19 +264,19 @@
+ pclamp = 15.0;
+ controlquant = 10000.0;
+ }
+-
++
+ ~JackPIControler()
+ {
+ delete[] offset_array;
+ delete[] window_array;
+ }
+-
++
+ void Init(double resample_factor)
+ {
+ resample_mean = resample_factor;
+ static_resample_factor = resample_factor;
+ }
+-
++
+ /*
+ double GetRatio(int fill_level)
+ {
+@@ -271,14 +284,14 @@
+
+ // 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 (int 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;
+
+@@ -286,13 +299,13 @@
+ // 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.
++
++ // Ok, now this is the PI controller.
+ // u(t) = K * (e(t) + 1/T \int e(t') dt')
+- // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
+- double current_resample_factor
++ // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
++ double current_resample_factor
+ = static_resample_factor - smooth_offset / catch_factor - offset_integral / catch_factor / 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;
+
+@@ -309,25 +322,25 @@
+ // This is the integral of the smoothed_offset
+ offset_integral += smooth_offset;
+
+- // Ok, now this is the PI controller.
++ // Ok, now this is the PI controller.
+ // u(t) = K * (e(t) + 1/T \int e(t') dt')
+- // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
++ // Kp = 1/catch_factor and T = catch_factor2 Ki = Kp/T
+ return static_resample_factor - smooth_offset/catch_factor - offset_integral/catch_factor/catch_factor2;
+ }
+-
++
+ void OurOfBounds()
+ {
+ int i;
+ // 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.
++ // 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;
+ }
+ }
+-
++
+ };
+
+ }
+--- a/common/JackFrameTimer.cpp
++++ b/common/JackFrameTimer.cpp
+@@ -13,7 +13,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+--- a/common/JackFrameTimer.h
++++ b/common/JackFrameTimer.h
+@@ -32,6 +32,7 @@
+ \brief A structure used for time management.
+ */
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackTimer
+ {
+
+@@ -73,6 +74,7 @@
+ \brief A class using the JackAtomicState to manage jack time.
+ */
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackFrameTimer : public JackAtomicState<JackTimer>
+ {
+
+--- a/common/JackFreewheelDriver.cpp
++++ b/common/JackFreewheelDriver.cpp
+@@ -28,26 +28,72 @@
+
+ int JackFreewheelDriver::Process()
+ {
+- if (fIsMaster) {
+- jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs);
+- JackDriver::CycleTakeBeginTime();
+- fEngine->Process(fBeginDateUst, fEndDateUst);
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); // Signal all clients
++ int res = 0;
++
++ jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs);
++ JackDriver::CycleTakeBeginTime();
++
++ if (fEngine->Process(fBeginDateUst, fEndDateUst)) {
++
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable)) { // Signal all clients
++ jack_error("JackFreewheelDriver::Process: ResumeRefNum error");
++ res = -1;
++ }
++
+ if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, FREEWHEEL_DRIVER_TIMEOUT * 1000000) < 0) { // Wait for all clients to finish for 10 sec
+- jack_error("JackFreewheelDriver::ProcessSync SuspendRefNum error");
++ jack_error("JackFreewheelDriver::ProcessSync: SuspendRefNum error");
+ /* We have a client time-out error, but still continue to process, until a better recovery strategy is chosen */
+ return 0;
+ }
+- } else {
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); // Signal all clients
+- if (fEngineControl->fSyncMode) {
+- if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
+- jack_error("JackFreewheelDriver::ProcessSync SuspendRefNum error");
+- return -1;
+- }
+- }
++
++ } else { // Graph not finished: do not activate it
++ jack_error("JackFreewheelDriver::Process: Process error");
++ res = -1;
++ }
++
++ return res;
++}
++
++int JackFreewheelDriver::ProcessRead()
++{
++ return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
++}
++
++int JackFreewheelDriver::ProcessWrite()
++{
++ return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
++}
++
++int JackFreewheelDriver::ProcessReadSync()
++{
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) { // Signal all clients
++ jack_error("JackFreewheelDriver::ProcessReadSync: ResumeRefNum error");
++ return -1;
++ }
++ return 0;
++}
++
++int JackFreewheelDriver::ProcessWriteSync()
++{
++ if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
++ jack_error("JackFreewheelDriver::ProcessSync SuspendRefNum error");
++ return -1;
+ }
+ return 0;
+ }
+
++int JackFreewheelDriver::ProcessReadAsync()
++{
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) { // Signal all clients
++ jack_error("JackFreewheelDriver::ProcessReadAsync: ResumeRefNum error");
++ return -1;
++ }
++ return 0;
++}
++
++int JackFreewheelDriver::ProcessWriteAsync()
++{
++ return 0;
++}
++
+ } // end of namespace
+--- a/common/JackFreewheelDriver.h
++++ b/common/JackFreewheelDriver.h
+@@ -46,6 +46,16 @@
+ }
+
+ int Process();
++
++ int ProcessRead();
++ int ProcessWrite();
++
++ int ProcessReadSync();
++ int ProcessWriteSync();
++
++ int ProcessReadAsync();
++ int ProcessWriteAsync();
++
+ };
+
+ } // end of namespace
+--- a/common/JackGlobals.cpp
++++ b/common/JackGlobals.cpp
+@@ -23,7 +23,7 @@
+ {
+
+ bool JackGlobals::fVerbose = 0;
+-
++
+ jack_tls_key JackGlobals::fRealTime;
+ static bool gKeyRealtimeInitialized = jack_tls_allocate_key(&JackGlobals::fRealTime);
+
+@@ -31,13 +31,13 @@
+ static bool fKeyLogFunctionInitialized = jack_tls_allocate_key(&JackGlobals::fKeyLogFunction);
+
+ JackMutex* JackGlobals::fOpenMutex = new JackMutex();
+-bool JackGlobals::fServerRunning = false;
++volatile bool JackGlobals::fServerRunning = false;
+ JackClient* JackGlobals::fClientTable[CLIENT_NUM] = {};
+
+ #ifndef WIN32
+ jack_thread_creator_t JackGlobals::fJackThreadCreator = pthread_create;
+ #endif
+-
++
+ #ifdef __CLIENTDEBUG__
+ std::ofstream* JackGlobals::fStream = NULL;
+
+@@ -52,13 +52,13 @@
+ curtime = time (NULL);
+ /* Convert it to local time representation. */
+ loctime = localtime (&curtime);
+- strftime (buffer, 256, "%I-%M", loctime);
+- sprintf(provstr, "JackAPICall-%s.log", buffer);
++ strftime(buffer, 256, "%I-%M", loctime);
++ snprintf(provstr, sizeof(provstr), "JackAPICall-%s.log", buffer);
+ JackGlobals::fStream = new std::ofstream(provstr, std::ios_base::ate);
+ JackGlobals::fStream->is_open();
+ }
+ (*fStream) << "JACK API call : " << name << ", calling thread : " << pthread_self() << std::endl;
+ }
+-#endif
++#endif
+
+ } // end of namespace
+--- a/common/JackGlobals.h
++++ b/common/JackGlobals.h
+@@ -21,14 +21,15 @@
+ #define __JackGlobals__
+
+ #include "JackPlatformPlug.h"
++#include "JackSystemDeps.h"
+ #include "JackConstants.h"
+
+-#ifdef __CLIENTDEBUG__
++#ifdef __CLIENTDEBUG__
+ #include <iostream>
+ #include <fstream>
+ #include <string>
+ #include <time.h>
+-#endif
++#endif
+
+ namespace Jack
+ {
+@@ -39,13 +40,13 @@
+ static jack_tls_key fRealTime;
+ static jack_tls_key fKeyLogFunction;
+ static JackMutex* fOpenMutex;
+- static bool fServerRunning;
++ static volatile bool fServerRunning;
+ static JackClient* fClientTable[];
+ static bool fVerbose;
+ #ifndef WIN32
+ static jack_thread_creator_t fJackThreadCreator;
+ #endif
+-
++
+ #ifdef __CLIENTDEBUG__
+ static std::ofstream* fStream;
+ static void CheckContext(const char* name);
+@@ -53,9 +54,9 @@
+ };
+
+ // Each "side" server and client will implement this to get the shared graph manager, engine control and inter-process synchro table.
+-extern EXPORT JackGraphManager* GetGraphManager();
+-extern EXPORT JackEngineControl* GetEngineControl();
+-extern EXPORT JackSynchro* GetSynchroTable();
++extern SERVER_EXPORT JackGraphManager* GetGraphManager();
++extern SERVER_EXPORT JackEngineControl* GetEngineControl();
++extern SERVER_EXPORT JackSynchro* GetSynchroTable();
+
+ } // end of namespace
+
+--- a/common/JackGraphManager.cpp
++++ b/common/JackGraphManager.cpp
+@@ -180,14 +180,13 @@
+ return GetBuffer(0); // port_index 0 is not used
+ }
+
++ jack_int_t len = manager->Connections(port_index);
++
+ // Output port
+ if (port->fFlags & JackPortIsOutput) {
+ return (port->fTied != NO_PORT) ? GetBuffer(port->fTied, buffer_size) : GetBuffer(port_index);
+ }
+
+- // Input port
+- jack_int_t len = manager->Connections(port_index);
+-
+ // No connections : return a zero-filled buffer
+ if (len == 0) {
+ port->ClearBuffer(buffer_size);
+@@ -742,8 +741,9 @@
+ {
+ for (unsigned int i = 0; i < fPortMax; i++) {
+ JackPort* port = GetPort(i);
+- if (port->IsUsed() && port->NameEquals(name))
++ if (port->IsUsed() && port->NameEquals(name)) {
+ return i;
++ }
+ }
+ return NO_PORT;
+ }
+@@ -791,9 +791,9 @@
+ next_index = GetCurrentIndex();
+ } while (cur_index != next_index); // Until a coherent state has been read
+
+- if (res[0]) { // at least one connection
++ if (res[0]) { // At least one connection
+ return res;
+- } else { // empty array, should return NULL
++ } else { // Empty array, should return NULL
+ free(res);
+ return NULL;
+ }
+@@ -874,10 +874,10 @@
+ next_index = GetCurrentIndex();
+ } while (cur_index != next_index); // Until a coherent state has been read
+
+- if (res[0]) { // at least one port
++ if (res[0]) { // At least one port
+ return res;
+ } else {
+- free(res); // empty array, should return NULL
++ free(res); // Empty array, should return NULL
+ return NULL;
+ }
+ }
+--- a/common/JackGraphManager.h
++++ b/common/JackGraphManager.h
+@@ -36,6 +36,7 @@
+ \brief Graph manager: contains the connection manager and the port array.
+ */
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState<JackConnectionManager>
+ {
+
+--- a/common/JackInternalClientChannel.h
++++ b/common/JackInternalClientChannel.h
+@@ -50,7 +50,7 @@
+ return 0;
+ }
+
+- void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result)
++ void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open)
+ {
+ *result = fEngine->ClientCheck(name, uuid, name_res, protocol, options, status);
+ }
+@@ -146,7 +146,42 @@
+
+ void SessionNotify(int refnum, const char *target, jack_session_event_type_t type, const char *path, jack_session_command_t** result)
+ {
+- *result = NULL;
++ JackSessionNotifyResult* res;
++ fEngine->SessionNotify(refnum, target, type, path, NULL, &res);
++ if (res == NULL)
++ {
++ *result = NULL;
++ return;
++ }
++
++ *result = res->GetCommands();
++ delete(res);
++ }
++
++ void SessionReply(int refnum, int* result)
++ {
++ fEngine->SessionReply(refnum);
++ *result = 0;
++ }
++
++ void GetUUIDForClientName(int refnum, const char* client_name, char* uuid_res, int* result)
++ {
++ fEngine->GetUUIDForClientName(client_name, uuid_res, result);
++ }
++
++ void GetClientNameForUUID(int refnum, const char* uuid, char* name_res, int* result)
++ {
++ fEngine->GetClientNameForUUID(uuid, name_res, result);
++ }
++
++ void ReserveClientName(int refnum, const char* client_name, const char *uuid, int* result)
++ {
++ fEngine->ReserveClientName(client_name, uuid, result);
++ }
++
++ void ClientHasSessionCallback(const char* client_name, int* result)
++ {
++ fEngine->ClientHasSessionCallback(client_name, result);
+ }
+
+
+--- a/common/JackInternalClient.cpp
++++ b/common/JackInternalClient.cpp
+@@ -38,17 +38,17 @@
+ JackEngineControl* JackInternalClient::fEngineControl = NULL;
+
+ // Used for external C API (JackAPI.cpp)
+-EXPORT JackGraphManager* GetGraphManager()
++SERVER_EXPORT JackGraphManager* GetGraphManager()
+ {
+ return JackServerGlobals::fInstance->GetGraphManager();
+ }
+
+-EXPORT JackEngineControl* GetEngineControl()
++SERVER_EXPORT JackEngineControl* GetEngineControl()
+ {
+ return JackServerGlobals::fInstance->GetEngineControl();
+ }
+
+-EXPORT JackSynchro* GetSynchroTable()
++SERVER_EXPORT JackSynchro* GetSynchroTable()
+ {
+ return JackServerGlobals::fInstance->GetSynchroTable();
+ }
+@@ -71,13 +71,14 @@
+
+ strncpy(fServerName, server_name, sizeof(fServerName));
+
+- fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
++ fChannel->ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, false);
+ if (result < 0) {
+ int status1 = *status;
+- if (status1 & JackVersionError)
++ if (status1 & JackVersionError) {
+ jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
+- else
++ } else {
+ jack_error("Client name = %s conflits with another running client", name);
++ }
+ goto error;
+ }
+
+--- a/common/jack/jack.h
++++ b/common/jack/jack.h
+@@ -233,7 +233,7 @@
+ *
+ * @return the number of frames of data to process
+ */
+- jack_nframes_t jack_cycle_wait (jack_client_t* client) JACK_OPTIONAL_WEAK_EXPORT;
++jack_nframes_t jack_cycle_wait (jack_client_t* client) JACK_OPTIONAL_WEAK_EXPORT;
+
+ /**
+ * Signal next clients in the graph.
+@@ -310,7 +310,7 @@
+ * jack_on_info_shutdown() will.
+ */
+ void jack_on_shutdown (jack_client_t *client,
+- JackShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT;
++ JackShutdownCallback shutdown_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT;
+
+ /**
+ * @param client pointer to JACK client structure.
+@@ -336,7 +336,7 @@
+ * jack_on_info_shutdown() will.
+ */
+ void jack_on_info_shutdown (jack_client_t *client,
+- JackInfoShutdownCallback shutdown_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT;
++ JackInfoShutdownCallback shutdown_callback, void *arg) JACK_WEAK_EXPORT;
+
+ /**
+ * Tell the Jack server to call @a process_callback whenever there is
+--- a/common/JackLibAPI.cpp
++++ b/common/JackLibAPI.cpp
+@@ -13,7 +13,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -42,11 +42,12 @@
+ jack_client_t * jack_client_open_aux (const char *client_name,
+ jack_options_t options,
+ jack_status_t *status, va_list ap);
+- EXPORT jack_client_t * jack_client_open (const char *client_name,
++
++ LIB_EXPORT jack_client_t * jack_client_open (const char *client_name,
+ jack_options_t options,
+ jack_status_t *status, ...);
+- EXPORT int jack_client_close (jack_client_t *client);
+- EXPORT int jack_get_client_pid (const char *name);
++ LIB_EXPORT int jack_client_close (jack_client_t *client);
++ LIB_EXPORT int jack_get_client_pid (const char *name);
+
+ #ifdef __cplusplus
+ }
+@@ -60,14 +61,14 @@
+ jack_varargs_t va; /* variable arguments */
+ jack_status_t my_status;
+ JackClient* client;
+-
++
+ if (client_name == NULL) {
+ jack_error("jack_client_new called with a NULL client_name");
+ return NULL;
+ }
+
+ jack_log("jack_client_new %s", client_name);
+-
++
+ if (status == NULL) /* no status from caller? */
+ status = &my_status; /* use local status word */
+ *status = (jack_status_t)0;
+@@ -81,7 +82,7 @@
+
+ /* parse variable arguments */
+ jack_varargs_init(&va);
+-
++
+ JackLibGlobals::Init(); // jack library initialisation
+
+ if (try_start_server(&va, options, status)) {
+@@ -113,14 +114,14 @@
+ jack_varargs_t va; /* variable arguments */
+ jack_status_t my_status;
+ JackClient* client;
+-
++
+ if (client_name == NULL) {
+ jack_error("jack_client_open called with a NULL client_name");
+ return NULL;
+ }
+
+ jack_log("jack_client_open %s", client_name);
+-
++
+ if (status == NULL) /* no status from caller? */
+ status = &my_status; /* use local status word */
+ *status = (jack_status_t)0;
+@@ -134,7 +135,7 @@
+
+ /* parse variable arguments */
+ jack_varargs_parse(options, ap, &va);
+-
++
+ JackLibGlobals::Init(); // jack library initialisation
+
+ if (try_start_server(&va, options, status)) {
+@@ -161,7 +162,7 @@
+ }
+ }
+
+-EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
++LIB_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_open");
+@@ -184,7 +185,7 @@
+ }
+ }
+
+-EXPORT int jack_client_close(jack_client_t* ext_client)
++LIB_EXPORT int jack_client_close(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_close");
+@@ -206,7 +207,7 @@
+ return res;
+ }
+
+-EXPORT int jack_get_client_pid(const char *name)
++LIB_EXPORT int jack_get_client_pid(const char *name)
+ {
+ jack_error("jack_get_client_pid : not implemented on library side");
+ return 0;
+--- a/common/JackLibClient.cpp
++++ b/common/JackLibClient.cpp
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -100,22 +100,19 @@
+ JackLibGlobals::fGlobals->fGraphManager.SetShmIndex(shared_graph, fServerName);
+ fClientControl.SetShmIndex(shared_client, fServerName);
+ JackGlobals::fVerbose = GetEngineControl()->fVerbose;
+- } catch (int n) {
+- jack_error("Map shared memory segments exception %d", n);
+- goto error;
+ } catch (...) {
+- jack_error("Unknown error...");
++ jack_error("Map shared memory segments exception");
+ goto error;
+ }
+
+ SetupDriverSync(false);
+-
++
+ // Connect shared synchro : the synchro must be usable in I/O mode when several clients live in the same process
+ if (!fSynchroTable[GetClientControl()->fRefNum].Connect(name_res, fServerName)) {
+ jack_error("Cannot ConnectSemaphore %s client", name_res);
+ goto error;
+ }
+-
++
+ JackGlobals::fClientTable[GetClientControl()->fRefNum] = this;
+ JackGlobals::fServerRunning = true;
+ SetClockSource(GetEngineControl()->fClockSource);
+@@ -146,7 +143,7 @@
+
+ case kRemoveClient:
+ jack_log("JackClient::RemoveClient name = %s, ref = %ld ", name, refnum);
+- if (strcmp(GetClientControl()->fName, name) != 0)
++ if (GetClientControl() && strcmp(GetClientControl()->fName, name) != 0)
+ res = fSynchroTable[refnum].Disconnect() ? 0 : -1;
+ break;
+ }
+--- a/common/JackLibClient.h
++++ b/common/JackLibClient.h
+@@ -32,7 +32,7 @@
+ \brief Client on the library side.
+ */
+
+-class SERVER_EXPORT JackLibClient : public JackClient
++class LIB_EXPORT JackLibClient : public JackClient
+ {
+
+ private:
+--- a/common/JackLibGlobals.h
++++ b/common/JackLibGlobals.h
+@@ -32,6 +32,14 @@
+ #include <assert.h>
+ #include <signal.h>
+
++#ifdef WIN32
++#ifdef __MINGW32__
++#include <sys/types.h>
++typedef _sigset_t sigset_t;
++#else
++typedef HANDLE sigset_t;
++#endif
++#endif
+
+ namespace Jack
+ {
+@@ -42,7 +50,7 @@
+ \brief Global library static structure: singleton kind of pattern.
+ */
+
+-struct SERVER_EXPORT JackLibGlobals
++struct LIB_EXPORT JackLibGlobals
+ {
+ JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */
+ JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable
+--- a/common/JackLibSampleRateResampler.cpp
++++ b/common/JackLibSampleRateResampler.cpp
+@@ -58,8 +58,9 @@
+
+ int error;
+ fResampler = src_new(quality, 1, &error);
+- if (error != 0)
++ if (error != 0) {
+ jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error));
++ }
+ }
+
+ JackLibSampleRateResampler::~JackLibSampleRateResampler()
+@@ -148,7 +149,7 @@
+
+ res = src_process(fResampler, &src_data);
+ if (res != 0) {
+- jack_error("JackLibSampleRateResampler::ReadResample ratio = %f err = %s", fRatio, src_strerror(res));
++ jack_error("JackLibSampleRateResampler::WriteResample ratio = %f err = %s", fRatio, src_strerror(res));
+ return 0;
+ }
+
+@@ -167,7 +168,7 @@
+
+ if (read_frames < frames) {
+ jack_error("Input available = %ld", available_frames);
+- jack_error("JackLibSampleRateResampler::ReadResample error read_frames = %ld", read_frames);
++ jack_error("JackLibSampleRateResampler::WriteResample error read_frames = %ld", read_frames);
+ }
+
+ return read_frames;
+--- a/common/JackLockedEngine.h
++++ b/common/JackLockedEngine.h
+@@ -44,14 +44,23 @@
+ } catch(std::bad_alloc& e) { \
+ jack_error("Memory allocation error..."); \
+ return -1; \
++ } catch (...) { \
++ jack_error("Unknown error..."); \
++ throw; \
++ } \
++
++#define CATCH_CLOSE_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; \
++ return 0; \
+ } catch (...) { \
+ jack_error("Unknown error..."); \
+ throw; \
+- } \
++ }
+
+ #define CATCH_EXCEPTION \
+ } catch(std::bad_alloc& e) { \
+@@ -122,15 +131,15 @@
+ {
+ TRY_CALL
+ JackLock lock(&fEngine);
+- return (fEngine.CheckClient(refnum)) ? fEngine.ClientExternalClose(refnum) : - 1;
+- CATCH_EXCEPTION_RETURN
++ return (fEngine.CheckClient(refnum)) ? fEngine.ClientExternalClose(refnum) : -1;
++ CATCH_CLOSE_EXCEPTION_RETURN
+ }
+ int ClientInternalClose(int refnum, bool wait)
+ {
+ TRY_CALL
+ JackLock lock(&fEngine);
+ return (fEngine.CheckClient(refnum)) ? fEngine.ClientInternalClose(refnum, wait) : -1;
+- CATCH_EXCEPTION_RETURN
++ CATCH_CLOSE_EXCEPTION_RETURN
+ }
+
+ int ClientActivate(int refnum, bool is_real_time)
+@@ -261,6 +270,7 @@
+ fEngine.NotifyGraphReorder();
+ CATCH_EXCEPTION
+ }
++
+ void NotifyBufferSize(jack_nframes_t buffer_size)
+ {
+ TRY_CALL
+@@ -315,11 +325,11 @@
+ CATCH_EXCEPTION
+ }
+
+- void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket)
++ void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, JackChannelTransaction *socket, JackSessionNotifyResult** result)
+ {
+ TRY_CALL
+ JackLock lock(&fEngine);
+- fEngine.SessionNotify(refnum, target, type, path, socket);
++ fEngine.SessionNotify(refnum, target, type, path, socket, result);
+ CATCH_EXCEPTION
+ }
+
+@@ -353,11 +363,11 @@
+ CATCH_EXCEPTION
+ }
+
+- void ClientHasSessionCallbackRequest(const char *name, int *result)
++ void ClientHasSessionCallback(const char *name, int *result)
+ {
+ TRY_CALL
+ JackLock lock(&fEngine);
+- fEngine.ClientHasSessionCallbackRequest(name, result);
++ fEngine.ClientHasSessionCallback(name, result);
+ CATCH_EXCEPTION
+ }
+ };
+--- a/common/JackLoopbackDriver.cpp
++++ b/common/JackLoopbackDriver.cpp
+@@ -30,20 +30,61 @@
+ namespace Jack
+ {
+
+-int JackLoopbackDriver::Process()
++int JackLoopbackDriver::ProcessRead()
+ {
++ return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
++}
++
++int JackLoopbackDriver::ProcessWrite()
++{
++ return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
++}
++
++int JackLoopbackDriver::ProcessReadSync()
++{
++ int res = 0;
++
++ // Loopback copy
++ for (int i = 0; i < fCaptureChannels; i++) {
++ memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
++ }
++
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
++ jack_error("JackLoopbackDriver::ProcessReadSync - ResumeRefNum error");
++ res = -1;
++ }
++
++ return res;
++}
++
++int JackLoopbackDriver::ProcessWriteSync()
++{
++ if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
++ jack_error("JackLoopbackDriver::ProcessWriteSync SuspendRefNum error");
++ return -1;
++ }
++ return 0;
++}
++
++int JackLoopbackDriver::ProcessReadAsync()
++{
++ int res = 0;
++
+ // Loopback copy
+ for (int i = 0; i < fCaptureChannels; i++) {
+ memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
+ }
+
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); // Signal all clients
+- if (fEngineControl->fSyncMode) {
+- if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, DRIVER_TIMEOUT_FACTOR * fEngineControl->fTimeOutUsecs) < 0) {
+- jack_error("JackLoopbackDriver::ProcessSync SuspendRefNum error");
+- return -1;
+- }
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
++ jack_error("JackLoopbackDriver::ProcessReadAsync - ResumeRefNum error");
++ res = -1;
+ }
++
++ return res;
++}
++
++int JackLoopbackDriver::ProcessWriteAsync()
++{
+ return 0;
+ }
+
+@@ -57,22 +98,13 @@
+ SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
+ {
+ jack_driver_desc_t * desc;
+- unsigned int i;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("loopback", JackDriverSlave, "Loopback backend", &filler);
+
+- desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
+- strcpy(desc->name, "loopback"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Loopback backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 1;
+- desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "channels");
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Maximum number of loopback ports");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of loopback ports", NULL);
+
+ return desc;
+ }
+--- a/common/JackLoopbackDriver.h
++++ b/common/JackLoopbackDriver.h
+@@ -33,15 +33,24 @@
+ class JackLoopbackDriver : public JackAudioDriver
+ {
+
++ private:
++
++ virtual int ProcessReadSync();
++ virtual int ProcessWriteSync();
++
++ virtual int ProcessReadAsync();
++ virtual int ProcessWriteAsync();
++
+ public:
+
+ JackLoopbackDriver(JackLockedEngine* engine, JackSynchro* table)
+- : JackAudioDriver("loopback", "", engine, table)
++ : JackAudioDriver("loopback", "loopback", engine, table)
+ {}
+ virtual ~JackLoopbackDriver()
+ {}
+
+- int Process();
++ virtual int ProcessRead();
++ virtual int ProcessWrite();
+ };
+
+ } // end of namespace
+--- a/common/JackMessageBuffer.cpp
++++ b/common/JackMessageBuffer.cpp
+@@ -48,11 +48,16 @@
+ } else {
+ jack_log("no message buffer overruns");
+ }
+- fGuard.Lock();
+- fRunning = false;
+- fGuard.Signal();
+- fGuard.Unlock();
+- fThread.Stop();
++
++ if (fGuard.Lock()) {
++ fRunning = false;
++ fGuard.Signal();
++ fGuard.Unlock();
++ fThread.Stop();
++ } else {
++ fThread.Kill();
++ }
++
+ Flush();
+ }
+
+@@ -79,21 +84,29 @@
+
+ bool JackMessageBuffer::Execute()
+ {
+- while (fRunning) {
+- fGuard.Lock();
+- fGuard.Wait();
+- /* the client asked for all threads to run a thread
+- initialization callback, which includes us.
+- */
+- if (fInit) {
+- fInit(fInitArg);
+- fInit = NULL;
+- /* and we're done */
+- fGuard.Signal();
++ if (fGuard.Lock()) {
++ while (fRunning) {
++ fGuard.Wait();
++ /* the client asked for all threads to run a thread
++ initialization callback, which includes us.
++ */
++ if (fInit) {
++ fInit(fInitArg);
++ fInit = NULL;
++ /* and we're done */
++ fGuard.Signal();
++ }
++
++ /* releasing the mutex reduces contention */
++ fGuard.Unlock();
++ Flush();
++ fGuard.Lock();
+ }
+- Flush();
+ fGuard.Unlock();
++ } else {
++ jack_error("JackMessageBuffer::Execute lock cannot be taken");
+ }
++
+ return false;
+ }
+
+@@ -126,16 +139,19 @@
+
+ void JackMessageBuffer::SetInitCallback(JackThreadInitCallback callback, void *arg)
+ {
+- fGuard.Lock();
+- /* set up the callback */
+- fInitArg = arg;
+- fInit = callback;
+- /* wake msg buffer thread */
+- fGuard.Signal();
+- /* wait for it to be done */
+- fGuard.Wait();
+- /* and we're done */
+- fGuard.Unlock();
++ if (fGuard.Lock()) {
++ /* set up the callback */
++ fInitArg = arg;
++ fInit = callback;
++ /* wake msg buffer thread */
++ fGuard.Signal();
++ /* wait for it to be done */
++ fGuard.Wait();
++ /* and we're done */
++ fGuard.Unlock();
++ } else {
++ jack_error("JackMessageBuffer::SetInitCallback lock cannot be taken");
++ }
+ }
+
+ };
+--- a/common/JackMessageBuffer.h
++++ b/common/JackMessageBuffer.h
+@@ -10,19 +10,19 @@
+ * Copyright (C) 2004 Rui Nuno Capela, Steve Harris
+ * Copyright (C) 2008 Nedko Arnaudov
+ * Copyright (C) 2008 Grame
+- *
++ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+- *
++ *
+ * You should have received a copy of the GNU Lesser General Public License
+- * along with this program; if not, write to the Free Software
++ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+@@ -56,7 +56,7 @@
+ {
+
+ private:
+-
++
+ JackThreadInitCallback fInit;
+ void* fInitArg;
+ JackMessage fBuffers[MB_BUFFERS];
+@@ -68,15 +68,15 @@
+ bool fRunning;
+
+ void Flush();
+-
++
+ void Start();
+ void Stop();
+-
++
+ public:
+-
+- JackMessageBuffer();
++
++ JackMessageBuffer();
+ ~JackMessageBuffer();
+-
++
+ // JackRunnableInterface interface
+ bool Execute();
+
+@@ -90,16 +90,16 @@
+ };
+
+ #ifdef __cplusplus
+-extern "C"
++extern "C"
+ {
+ #endif
+
+ void JackMessageBufferAdd(int level, const char *message);
+
+ #ifdef __cplusplus
+-}
++}
+ #endif
+
+ };
+
+-#endif
++#endif
+--- a/common/JackMidiAPI.cpp
++++ b/common/JackMidiAPI.cpp
+@@ -13,7 +13,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -30,22 +30,22 @@
+ {
+ #endif
+
+- EXPORT jack_nframes_t jack_midi_get_event_count(void* port_buffer);
++ LIB_EXPORT uint32_t jack_midi_get_event_count(void* port_buffer);
+
+- EXPORT int jack_midi_event_get(jack_midi_event_t* event,
+- void* port_buffer, jack_nframes_t event_index);
++ LIB_EXPORT int jack_midi_event_get(jack_midi_event_t* event,
++ void* port_buffer, uint32_t event_index);
+
+- EXPORT void jack_midi_clear_buffer(void* port_buffer);
++ LIB_EXPORT void jack_midi_clear_buffer(void* port_buffer);
+
+- EXPORT size_t jack_midi_max_event_size(void* port_buffer);
++ LIB_EXPORT size_t jack_midi_max_event_size(void* port_buffer);
+
+- EXPORT jack_midi_data_t* jack_midi_event_reserve(void* port_buffer,
++ LIB_EXPORT jack_midi_data_t* jack_midi_event_reserve(void* port_buffer,
+ jack_nframes_t time, size_t data_size);
+
+- EXPORT int jack_midi_event_write(void* port_buffer,
++ LIB_EXPORT int jack_midi_event_write(void* port_buffer,
+ jack_nframes_t time, const jack_midi_data_t* data, size_t data_size);
+
+- EXPORT jack_nframes_t jack_midi_get_lost_event_count(void* port_buffer);
++ LIB_EXPORT jack_nframes_t jack_midi_get_lost_event_count(void* port_buffer);
+
+ #ifdef __cplusplus
+ }
+@@ -53,23 +53,26 @@
+
+ using namespace Jack;
+
+-EXPORT
+-jack_nframes_t jack_midi_get_event_count(void* port_buffer)
++LIB_EXPORT
++uint32_t jack_midi_get_event_count(void* port_buffer)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+- if (!buf || !buf->IsValid())
++ if (!buf || !buf->IsValid()) {
+ return 0;
++ }
+ return buf->event_count;
+ }
+
+-EXPORT
+-int jack_midi_event_get(jack_midi_event_t *event, void* port_buffer, jack_nframes_t event_index)
++LIB_EXPORT
++int jack_midi_event_get(jack_midi_event_t *event, void* port_buffer, uint32_t event_index)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+- if (!buf || !buf->IsValid())
++ if (!buf || !buf->IsValid()) {
+ return -EINVAL;
+- if (event_index >= buf->event_count)
++ }
++ if (event_index >= buf->event_count) {
+ return -ENOBUFS;
++ }
+ JackMidiEvent* ev = &buf->events[event_index];
+ event->time = ev->time;
+ event->size = ev->size;
+@@ -77,15 +80,16 @@
+ return 0;
+ }
+
+-EXPORT
++LIB_EXPORT
+ void jack_midi_clear_buffer(void* port_buffer)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+- if (buf && buf->IsValid())
++ if (buf && buf->IsValid()) {
+ buf->Reset(buf->nframes);
++ }
+ }
+
+-EXPORT
++LIB_EXPORT
+ size_t jack_midi_max_event_size(void* port_buffer)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+@@ -94,35 +98,52 @@
+ return 0;
+ }
+
+-EXPORT
++LIB_EXPORT
+ jack_midi_data_t* jack_midi_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+- if (!buf && !buf->IsValid())
++ if (! buf) {
++ jack_error("jack_midi_event_reserve: port buffer is set to NULL");
++ return 0;
++ }
++ if (! buf->IsValid()) {
++ jack_error("jack_midi_event_reserve: port buffer is invalid");
++ return 0;
++ }
++ if (time >= buf->nframes) {
++ jack_error("jack_midi_event_reserve: time parameter is out of range "
++ "(%lu >= %lu)", time, buf->nframes);
+ return 0;
+- if (time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time))
++ }
++ if (buf->event_count && (buf->events[buf->event_count - 1].time > time)) {
++ jack_error("jack_midi_event_reserve: time parameter is earlier than "
++ "last reserved event");
+ return 0;
++ }
+ return buf->ReserveEvent(time, data_size);
+ }
+
+-EXPORT
++LIB_EXPORT
+ int jack_midi_event_write(void* port_buffer,
+ jack_nframes_t time, const jack_midi_data_t* data, size_t data_size)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+- if (!buf && !buf->IsValid())
++ if (!buf && !buf->IsValid()) {
+ return -EINVAL;
+- if (time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time))
++ }
++ if (time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time)) {
+ return -EINVAL;
++ }
+ jack_midi_data_t* dest = buf->ReserveEvent(time, data_size);
+- if (!dest)
++ if (!dest) {
+ return -ENOBUFS;
++ }
+ memcpy(dest, data, data_size);
+ return 0;
+ }
+
+-EXPORT
+-jack_nframes_t jack_midi_get_lost_event_count(void* port_buffer)
++LIB_EXPORT
++uint32_t jack_midi_get_lost_event_count(void* port_buffer)
+ {
+ JackMidiBuffer *buf = (JackMidiBuffer*)port_buffer;
+ if (buf && buf->IsValid())
+--- /dev/null
++++ b/common/JackMidiAsyncQueue.cpp
+@@ -0,0 +1,96 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <new>
++
++#include "JackMidiAsyncQueue.h"
++
++using Jack::JackMidiAsyncQueue;
++
++JackMidiAsyncQueue::JackMidiAsyncQueue(size_t max_bytes, size_t max_messages)
++{
++ data_buffer = new jack_midi_data_t[max_bytes];
++ byte_ring = jack_ringbuffer_create((max_bytes * sizeof(jack_midi_data_t)) +
++ 1);
++ if (byte_ring) {
++ info_ring = jack_ringbuffer_create((max_messages * INFO_SIZE) + 1);
++ if (info_ring) {
++ jack_ringbuffer_mlock(byte_ring);
++ jack_ringbuffer_mlock(info_ring);
++ this->max_bytes = max_bytes;
++ return;
++ }
++ jack_ringbuffer_free(byte_ring);
++ }
++ delete data_buffer;
++ throw std::bad_alloc();
++}
++
++JackMidiAsyncQueue::~JackMidiAsyncQueue()
++{
++ jack_ringbuffer_free(byte_ring);
++ jack_ringbuffer_free(info_ring);
++ delete[] data_buffer;
++}
++
++jack_midi_event_t *
++JackMidiAsyncQueue::DequeueEvent()
++{
++ jack_midi_event_t *event = 0;
++ if (jack_ringbuffer_read_space(info_ring) >= INFO_SIZE) {
++ size_t size;
++ event = &dequeue_event;
++ jack_ringbuffer_read(info_ring, (char *) &(event->time),
++ sizeof(jack_nframes_t));
++ jack_ringbuffer_read(info_ring, (char *) &size,
++ sizeof(size_t));
++ jack_ringbuffer_read(byte_ring, (char *) data_buffer,
++ size * sizeof(jack_midi_data_t));
++ event->buffer = data_buffer;
++ event->size = size;
++ }
++ return event;
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackMidiAsyncQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ if (size > max_bytes) {
++ return BUFFER_TOO_SMALL;
++ }
++ if (! ((jack_ringbuffer_write_space(info_ring) >= INFO_SIZE) &&
++ (jack_ringbuffer_write_space(byte_ring) >=
++ (size * sizeof(jack_midi_data_t))))) {
++ return BUFFER_FULL;
++ }
++ jack_ringbuffer_write(byte_ring, (const char *) buffer,
++ size * sizeof(jack_midi_data_t));
++ jack_ringbuffer_write(info_ring, (const char *) (&time),
++ sizeof(jack_nframes_t));
++ jack_ringbuffer_write(info_ring, (const char *) (&size), sizeof(size_t));
++ return OK;
++}
++
++size_t
++JackMidiAsyncQueue::GetAvailableSpace()
++{
++ return jack_ringbuffer_write_space(info_ring) < INFO_SIZE ? 0 :
++ max_bytes - jack_ringbuffer_read_space(byte_ring);
++}
+--- /dev/null
++++ b/common/JackMidiAsyncQueue.h
+@@ -0,0 +1,98 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiAsyncQueue__
++#define __JackMidiAsyncQueue__
++
++#include "JackMidiPort.h"
++#include "JackMidiReadQueue.h"
++#include "JackMidiWriteQueue.h"
++#include "ringbuffer.h"
++
++namespace Jack {
++
++ /**
++ * This is a MIDI message queue designed to allow one thread to pass MIDI
++ * messages to another thread (though it can also be used to buffer events
++ * internally). This is especially useful if the MIDI API you're
++ * attempting to interface with doesn't provide the ability to schedule
++ * MIDI events ahead of time and/or has blocking send/receive calls, as it
++ * allows a separate thread to handle input/output while the JACK process
++ * thread copies events from a MIDI buffer to this queue, or vice versa.
++ */
++
++ class SERVER_EXPORT JackMidiAsyncQueue:
++ public JackMidiReadQueue, public JackMidiWriteQueue {
++
++ private:
++
++ static const size_t INFO_SIZE =
++ sizeof(jack_nframes_t) + sizeof(size_t);
++
++ jack_ringbuffer_t *byte_ring;
++ jack_midi_data_t *data_buffer;
++ jack_midi_event_t dequeue_event;
++ jack_ringbuffer_t *info_ring;
++ size_t max_bytes;
++
++ public:
++
++ using JackMidiWriteQueue::EnqueueEvent;
++
++ /**
++ * Creates a new asynchronous MIDI message queue. The queue can store
++ * up to `max_messages` MIDI messages and up to `max_bytes` of MIDI
++ * data before it starts rejecting messages.
++ */
++
++ JackMidiAsyncQueue(size_t max_bytes=4096, size_t max_messages=1024);
++
++ virtual
++ ~JackMidiAsyncQueue();
++
++ /**
++ * Dequeues and returns a MIDI event. Returns '0' if there are no MIDI
++ * events available. This method may be overridden.
++ */
++
++ virtual jack_midi_event_t *
++ DequeueEvent();
++
++ /**
++ * Enqueues the MIDI event specified by the arguments. The return
++ * value indiciates whether or not the event was successfully enqueued.
++ * This method may be overridden.
++ */
++
++ virtual EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ /**
++ * Returns the maximum size event that can be enqueued right *now*.
++ */
++
++ size_t
++ GetAvailableSpace();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiAsyncWaitQueue.cpp
+@@ -0,0 +1,85 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <new>
++
++#include "JackMidiAsyncWaitQueue.h"
++#include "JackMidiUtil.h"
++#include "JackTime.h"
++
++using Jack::JackMidiAsyncWaitQueue;
++
++JackMidiAsyncWaitQueue::JackMidiAsyncWaitQueue(size_t max_bytes,
++ size_t max_messages):
++ JackMidiAsyncQueue(max_bytes, max_messages)
++{
++ if (semaphore.Allocate("JackMidiAsyncWaitQueue", "midi-thread", 0)) {
++ throw std::bad_alloc();
++ }
++}
++
++JackMidiAsyncWaitQueue::~JackMidiAsyncWaitQueue()
++{
++ semaphore.Destroy();
++}
++
++jack_midi_event_t *
++JackMidiAsyncWaitQueue::DequeueEvent()
++{
++ return DequeueEvent((long) 0);
++}
++
++jack_midi_event_t *
++JackMidiAsyncWaitQueue::DequeueEvent(jack_nframes_t frame)
++{
++
++ // XXX: I worry about timer resolution on Solaris and Windows. When the
++ // resolution for the `JackSynchro` object is milliseconds, the worst-case
++ // scenario for processor objects is that the wait time becomes less than a
++ // millisecond, and the processor object continually calls this method,
++ // expecting to wait a certain amount of microseconds, and ends up not
++ // waiting at all each time, essentially busy-waiting until the current
++ // frame is reached. Perhaps there should be a #define that indicates the
++ // wait time resolution for `JackSynchro` objects so that we can wait a
++ // little longer if necessary.
++
++ jack_time_t frame_time = GetTimeFromFrames(frame);
++ jack_time_t current_time = GetMicroSeconds();
++ return DequeueEvent((frame_time < current_time) ? 0 :
++ (long) (frame_time - current_time));
++}
++
++jack_midi_event_t *
++JackMidiAsyncWaitQueue::DequeueEvent(long usec)
++{
++ return ((usec < 0) ? semaphore.Wait() : semaphore.TimedWait(usec)) ?
++ JackMidiAsyncQueue::DequeueEvent() : 0;
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackMidiAsyncWaitQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ EnqueueResult result = JackMidiAsyncQueue::EnqueueEvent(time, size,
++ buffer);
++ if (result == OK) {
++ semaphore.Signal();
++ }
++ return result;
++}
+--- /dev/null
++++ b/common/JackMidiAsyncWaitQueue.h
+@@ -0,0 +1,99 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiAsyncWaitQueue__
++#define __JackMidiAsyncWaitQueue__
++
++#include "JackMidiAsyncQueue.h"
++
++namespace Jack {
++
++ /**
++ * This is an asynchronous wait queue that allows a thread to wait for a
++ * message, either indefinitely or for a specified time. This is one
++ * example of a way that the `JackMidiAsyncQueue` class can be extended so
++ * that process threads can interact with non-process threads to send MIDI
++ * events.
++ *
++ * XXX: As of right now, this code hasn't been tested. Also, note the
++ * warning in the JackMidiAsyncWaitQueue.cpp about semaphore wait
++ * resolution.
++ */
++
++ class SERVER_EXPORT JackMidiAsyncWaitQueue: public JackMidiAsyncQueue {
++
++ private:
++
++ JackSynchro semaphore;
++
++ public:
++
++ using JackMidiAsyncQueue::EnqueueEvent;
++
++ /**
++ * Creates a new asynchronous MIDI wait message queue. The queue can
++ * store up to `max_messages` MIDI messages and up to `max_bytes` of
++ * MIDI data before it starts rejecting messages.
++ */
++
++ JackMidiAsyncWaitQueue(size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackMidiAsyncWaitQueue();
++
++ /**
++ * Dequeues and returns a MIDI event. Returns '0' if there are no MIDI
++ * events available right now.
++ */
++
++ jack_midi_event_t *
++ DequeueEvent();
++
++ /**
++ * Waits a specified time for a MIDI event to be available, or
++ * indefinitely if the time is negative. Returns the MIDI event, or
++ * '0' if time runs out and no MIDI event is available.
++ */
++
++ jack_midi_event_t *
++ DequeueEvent(long usecs);
++
++ /**
++ * Waits until the specified frame for a MIDI event to be available.
++ * Returns the MIDI event, or '0' if time runs out and no MIDI event is
++ * available.
++ */
++
++ jack_midi_event_t *
++ DequeueEvent(jack_nframes_t frame);
++
++ /**
++ * Enqueues the MIDI event specified by the arguments. The return
++ * value indiciates whether or not the event was successfully enqueued.
++ */
++
++ EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiBufferReadQueue.cpp
+@@ -0,0 +1,67 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackMidiBufferReadQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackMidiBufferReadQueue;
++
++JackMidiBufferReadQueue::JackMidiBufferReadQueue()
++{
++ event_count = 0;
++ index = 0;
++}
++
++jack_midi_event_t *
++JackMidiBufferReadQueue::DequeueEvent()
++{
++ jack_midi_event_t *e = 0;
++ if (index < event_count) {
++ JackMidiEvent *event = &(buffer->events[index]);
++ midi_event.buffer = event->GetData(buffer);
++ midi_event.size = event->size;
++ midi_event.time = last_frame_time + event->time;
++ e = &midi_event;
++ index++;
++ }
++ return e;
++}
++
++void
++JackMidiBufferReadQueue::ResetMidiBuffer(JackMidiBuffer *buffer)
++{
++ event_count = 0;
++ index = 0;
++ if (! buffer) {
++ jack_error("JackMidiBufferReadQueue::ResetMidiBuffer - buffer reset "
++ "to NULL");
++ } else if (! buffer->IsValid()) {
++ jack_error("JackMidiBufferReadQueue::ResetMidiBuffer - buffer reset "
++ "to invalid buffer");
++ } else {
++ uint32_t lost_events = buffer->lost_events;
++ if (lost_events) {
++ jack_error("JackMidiBufferReadQueue::ResetMidiBuffer - %d events "
++ "lost during mixdown", lost_events);
++ }
++ this->buffer = buffer;
++ event_count = buffer->event_count;
++ last_frame_time = GetLastFrame();
++ }
++}
+--- /dev/null
++++ b/common/JackMidiBufferReadQueue.h
+@@ -0,0 +1,60 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiBufferReadQueue__
++#define __JackMidiBufferReadQueue__
++
++#include "JackMidiReadQueue.h"
++
++namespace Jack {
++
++ /**
++ * Wrapper class to present a JackMidiBuffer in a read queue interface.
++ */
++
++ class SERVER_EXPORT JackMidiBufferReadQueue: public JackMidiReadQueue {
++
++ private:
++
++ JackMidiBuffer *buffer;
++ jack_nframes_t event_count;
++ jack_nframes_t index;
++ jack_nframes_t last_frame_time;
++ jack_midi_event_t midi_event;
++
++ public:
++
++ JackMidiBufferReadQueue();
++
++ jack_midi_event_t *
++ DequeueEvent();
++
++ /**
++ * This method must be called each period to reset the MIDI buffer for
++ * processing.
++ */
++
++ void
++ ResetMidiBuffer(JackMidiBuffer *buffer);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiBufferWriteQueue.cpp
+@@ -0,0 +1,65 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackMidiBufferWriteQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackMidiBufferWriteQueue;
++
++JackMidiBufferWriteQueue::JackMidiBufferWriteQueue()
++{
++ // Empty
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackMidiBufferWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *data)
++{
++ if (time >= next_frame_time) {
++ return EVENT_EARLY;
++ }
++ if (time < last_frame_time) {
++ time = last_frame_time;
++ }
++ jack_midi_data_t *dst = buffer->ReserveEvent(time - last_frame_time, size);
++ if (! dst) {
++ return size > max_bytes ? BUFFER_TOO_SMALL : BUFFER_FULL;
++ }
++ memcpy(dst, data, size);
++ return OK;
++}
++
++void
++JackMidiBufferWriteQueue::ResetMidiBuffer(JackMidiBuffer *buffer,
++ jack_nframes_t frames)
++{
++ if (! buffer) {
++ jack_error("JackMidiBufferWriteQueue::ResetMidiBuffer - buffer reset "
++ "to NULL");
++ } else if (! buffer->IsValid()) {
++ jack_error("JackMidiBufferWriteQueue::ResetMidiBuffer - buffer reset "
++ "to invalid buffer");
++ } else {
++ this->buffer = buffer;
++ buffer->Reset(frames);
++ last_frame_time = GetLastFrame();
++ max_bytes = buffer->MaxEventSize();
++ next_frame_time = last_frame_time + frames;
++ }
++}
+--- /dev/null
++++ b/common/JackMidiBufferWriteQueue.h
+@@ -0,0 +1,62 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiBufferWriteQueue__
++#define __JackMidiBufferWriteQueue__
++
++#include "JackMidiWriteQueue.h"
++
++namespace Jack {
++
++ /**
++ * Wrapper class to present a JackMidiBuffer in a write queue interface.
++ */
++
++ class SERVER_EXPORT JackMidiBufferWriteQueue: public JackMidiWriteQueue {
++
++ private:
++
++ JackMidiBuffer *buffer;
++ jack_nframes_t last_frame_time;
++ size_t max_bytes;
++ jack_nframes_t next_frame_time;
++
++ public:
++
++ using JackMidiWriteQueue::EnqueueEvent;
++
++ JackMidiBufferWriteQueue();
++
++ EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ /**
++ * This method must be called each period to reset the MIDI buffer for
++ * processing.
++ */
++
++ void
++ ResetMidiBuffer(JackMidiBuffer *buffer, jack_nframes_t frames);
++
++ };
++
++}
++
++#endif
+--- a/common/JackMidiDriver.cpp
++++ b/common/JackMidiDriver.cpp
+@@ -27,26 +27,17 @@
+ #include "JackException.h"
+ #include <assert.h>
+
++using namespace std;
++
+ namespace Jack
+ {
+
+ JackMidiDriver::JackMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+- : JackDriver(name, alias, engine, table),
+- fCaptureChannels(0),
+- fPlaybackChannels(0)
+-{
+- for (int i = 0; i < DRIVER_PORT_NUM; i++) {
+- fRingBuffer[i] = NULL;
+- }
+-}
++ : JackDriver(name, alias, engine, table)
++{}
+
+ JackMidiDriver::~JackMidiDriver()
+-{
+- for (int i = 0; i < fCaptureChannels; i++) {
+- if (fRingBuffer[i])
+- jack_ringbuffer_free(fRingBuffer[i]);
+- }
+-}
++{}
+
+ int JackMidiDriver::Open(bool capturing,
+ bool playing,
+@@ -60,11 +51,6 @@
+ {
+ fCaptureChannels = inchannels;
+ fPlaybackChannels = outchannels;
+-
+- for (int i = 0; i < fCaptureChannels; i++) {
+- fRingBuffer[i] = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * BUFFER_SIZE_MAX);
+- }
+-
+ return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
+ }
+
+@@ -72,16 +58,16 @@
+ {
+ JackPort* port;
+ jack_port_id_t port_index;
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
++ char name[REAL_JACK_PORT_NAME_SIZE];
++ char alias[REAL_JACK_PORT_NAME_SIZE];
+ int i;
+
+ jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
+
+ for (i = 0; i < fCaptureChannels; i++) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
+- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
++ snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+@@ -92,9 +78,9 @@
+ }
+
+ for (i = 0; i < fPlaybackChannels; i++) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
+- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
++ snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+@@ -104,6 +90,7 @@
+ jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index);
+ }
+
++ UpdateLatencies();
+ return 0;
+ }
+
+@@ -113,53 +100,113 @@
+ jack_log("JackMidiDriver::Detach");
+
+ for (i = 0; i < fCaptureChannels; i++) {
+- fGraphManager->ReleasePort(fClientControl.fRefNum, fCapturePortList[i]);
++ fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[i]);
+ }
+
+ for (i = 0; i < fPlaybackChannels; i++) {
+- fGraphManager->ReleasePort(fClientControl.fRefNum, fPlaybackPortList[i]);
++ fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[i]);
+ }
+
+ return 0;
+ }
+
+-int JackMidiDriver::Read()
++void JackMidiDriver::UpdateLatencies()
+ {
+- return 0;
++ jack_latency_range_t range;
++
++ for (int i = 0; i < fCaptureChannels; i++) {
++ range.max = range.min = fEngineControl->fBufferSize;
++ fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range);
++ }
++
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ if (! fEngineControl->fSyncMode) {
++ range.max = range.min = fEngineControl->fBufferSize * 2;
++ }
++ fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range);
++ }
+ }
+
+-int JackMidiDriver::Write()
++int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size)
+ {
++ UpdateLatencies();
+ return 0;
+ }
+
+-int JackMidiDriver::ProcessNull()
++int JackMidiDriver::ProcessRead()
+ {
+- return 0;
++ return (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
++}
++
++int JackMidiDriver::ProcessWrite()
++{
++ return (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
+ }
+
+-int JackMidiDriver::Process()
++int JackMidiDriver::ProcessReadSync()
+ {
++ int res = 0;
++
+ // Read input buffers for the current cycle
+ if (Read() < 0) {
+- jack_error("JackMidiDriver::Process: read error, skip cycle");
+- return 0; // Skip cycle, but continue processing...
++ jack_error("JackMidiDriver::ProcessReadSync: read error");
++ res = -1;
+ }
+
+- fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
+- if (fEngineControl->fSyncMode) {
+- if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, fEngineControl->fTimeOutUsecs) < 0) {
+- jack_error("JackFreewheelDriver::ProcessSync SuspendRefNum error");
+- return -1;
+- }
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
++ jack_error("JackMidiDriver::ProcessReadSync: ResumeRefNum error");
++ res = -1;
++ }
++
++ return res;
++}
++
++int JackMidiDriver::ProcessWriteSync()
++{
++ int res = 0;
++
++ if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable,
++ DRIVER_TIMEOUT_FACTOR *
++ fEngineControl->fTimeOutUsecs) < 0) {
++ jack_error("JackMidiDriver::ProcessWriteSync: SuspendRefNum error");
++ res = -1;
++ }
++
++ // Write output buffers from the current cycle
++ if (Write() < 0) {
++ jack_error("JackMidiDriver::ProcessWriteSync: write error");
++ res = -1;
++ }
++
++ return res;
++}
++
++int JackMidiDriver::ProcessReadAsync()
++{
++ int res = 0;
++
++ // Read input buffers for the current cycle
++ if (Read() < 0) {
++ jack_error("JackMidiDriver::ProcessReadAsync: read error");
++ res = -1;
+ }
+
+- // Write output buffers for the current cycle
++ // Write output buffers from the previous cycle
+ if (Write() < 0) {
+- jack_error("JackMidiDriver::Process: write error, skip cycle");
+- return 0; // Skip cycle, but continue processing...
++ jack_error("JackMidiDriver::ProcessReadAsync: write error");
++ res = -1;
++ }
++
++ if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable) < 0) {
++ jack_error("JackMidiDriver::ProcessReadAsync: ResumeRefNum error");
++ res = -1;
+ }
+
++ return res;
++}
++
++int JackMidiDriver::ProcessWriteAsync()
++{
+ return 0;
+ }
+
+--- a/common/JackMidiDriver.h
++++ b/common/JackMidiDriver.h
+@@ -37,17 +37,17 @@
+
+ protected:
+
+- int fCaptureChannels;
+- int fPlaybackChannels;
+-
+- jack_ringbuffer_t* fRingBuffer[DRIVER_PORT_NUM];
+-
+- jack_port_id_t fCapturePortList[DRIVER_PORT_NUM];
+- jack_port_id_t fPlaybackPortList[DRIVER_PORT_NUM];
+-
+ JackMidiBuffer* GetInputBuffer(int port_index);
+ JackMidiBuffer* GetOutputBuffer(int port_index);
+-
++
++ virtual int ProcessReadSync();
++ virtual int ProcessWriteSync();
++
++ virtual int ProcessReadAsync();
++ virtual int ProcessWriteAsync();
++
++ virtual void UpdateLatencies();
++
+ public:
+
+ JackMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table);
+@@ -62,16 +62,15 @@
+ const char* playback_driver_name,
+ jack_nframes_t capture_latency,
+ jack_nframes_t playback_latency);
+-
+- virtual int Process();
+- virtual int ProcessNull();
++
++ virtual int SetBufferSize(jack_nframes_t buffer_size);
++
++ virtual int ProcessRead();
++ virtual int ProcessWrite();
+
+ virtual int Attach();
+ virtual int Detach();
+-
+- virtual int Read();
+- virtual int Write();
+-
++
+ };
+
+ } // end of namespace
+--- a/common/JackMidiPort.cpp
++++ b/common/JackMidiPort.cpp
+@@ -52,10 +52,11 @@
+ {
+ jack_shmsize_t space = MaxEventSize();
+ if (space == 0 || size > space) {
++ jack_error("JackMidiBuffer::ReserveEvent - the buffer does not have "
++ "enough room to enqueue a %lu byte event", size);
+ lost_events++;
+ return 0;
+ }
+-
+ JackMidiEvent* event = &events[event_count++];
+ event->time = time;
+ event->size = size;
+@@ -90,7 +91,7 @@
+ {
+ JackMidiBuffer* mix = static_cast<JackMidiBuffer*>(mixbuffer);
+ if (!mix->IsValid()) {
+- jack_error("MIDI: invalid mix buffer");
++ jack_error("Jack::MidiBufferMixdown - invalid mix buffer");
+ return;
+ }
+ mix->Reset(nframes);
+@@ -98,8 +99,10 @@
+ int event_count = 0;
+ for (int i = 0; i < src_count; ++i) {
+ JackMidiBuffer* buf = static_cast<JackMidiBuffer*>(src_buffers[i]);
+- if (!buf->IsValid())
++ if (!buf->IsValid()) {
++ jack_error("Jack::MidiBufferMixdown - invalid source buffer");
+ return;
++ }
+ buf->mix_index = 0;
+ event_count += buf->event_count;
+ mix->lost_events += buf->lost_events;
+--- a/common/jack/midiport.h
++++ b/common/jack/midiport.h
+@@ -53,7 +53,7 @@
+ * @param port_buffer Port buffer from which to retrieve event.
+ * @return number of events inside @a port_buffer
+ */
+-jack_nframes_t
++uint32_t
+ jack_midi_get_event_count(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT;
+
+
+@@ -70,8 +70,8 @@
+ */
+ int
+ jack_midi_event_get(jack_midi_event_t *event,
+- void *port_buffer,
+- jack_nframes_t event_index) JACK_OPTIONAL_WEAK_EXPORT;
++ void *port_buffer,
++ uint32_t event_index) JACK_OPTIONAL_WEAK_EXPORT;
+
+
+ /** Clear an event buffer.
+@@ -158,7 +158,7 @@
+ * @param port_buffer Port to receive count for.
+ * @returns Number of events that could not be written to @a port_buffer.
+ */
+-jack_nframes_t
++uint32_t
+ jack_midi_get_lost_event_count(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT;
+
+ /*@}*/
+--- /dev/null
++++ b/common/JackMidiRawInputWriteQueue.cpp
+@@ -0,0 +1,299 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <cassert>
++#include <memory>
++#include <new>
++
++#include "JackMidiRawInputWriteQueue.h"
++
++using Jack::JackMidiRawInputWriteQueue;
++
++JackMidiRawInputWriteQueue::
++JackMidiRawInputWriteQueue(JackMidiWriteQueue *write_queue,
++ size_t max_packet_data, size_t max_packets)
++{
++ packet_queue = new JackMidiAsyncQueue(max_packet_data, max_packets);
++ std::auto_ptr<JackMidiAsyncQueue> packet_queue_ptr(packet_queue);
++ input_buffer = new jack_midi_data_t[max_packet_data];
++ Clear();
++ expected_bytes = 0;
++ event_pending = false;
++ input_buffer_size = max_packet_data;
++ packet = 0;
++ status_byte = 0;
++ this->write_queue = write_queue;
++ packet_queue_ptr.release();
++}
++
++JackMidiRawInputWriteQueue::~JackMidiRawInputWriteQueue()
++{
++ delete[] input_buffer;
++ delete packet_queue;
++}
++
++void
++JackMidiRawInputWriteQueue::Clear()
++{
++ total_bytes = 0;
++ unbuffered_bytes = 0;
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackMidiRawInputWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ return packet_queue->EnqueueEvent(time, size, buffer);
++}
++
++size_t
++JackMidiRawInputWriteQueue::GetAvailableSpace()
++{
++ return packet_queue->GetAvailableSpace();
++}
++
++void
++JackMidiRawInputWriteQueue::HandleBufferFailure(size_t unbuffered_bytes,
++ size_t total_bytes)
++{
++ jack_error("JackMidiRawInputWriteQueue::HandleBufferFailure - %d MIDI "
++ "byte(s) of a %d byte message could not be buffered. The "
++ "message has been dropped.", unbuffered_bytes, total_bytes);
++}
++
++void
++JackMidiRawInputWriteQueue::HandleEventLoss(jack_midi_event_t *event)
++{
++ jack_error("JackMidiRawInputWriteQueue::HandleEventLoss - A %d byte MIDI "
++ "event scheduled for frame '%d' could not be processed because "
++ "the write queue cannot accomodate an event of that size. The "
++ "event has been discarded.", event->size, event->time);
++}
++
++void
++JackMidiRawInputWriteQueue::HandleIncompleteMessage(size_t total_bytes)
++{
++ jack_error("JackMidiRawInputWriteQueue::HandleIncompleteMessage - "
++ "Discarding %d MIDI byte(s) of an incomplete message. The "
++ "MIDI cable may have been unplugged.", total_bytes);
++}
++
++void
++JackMidiRawInputWriteQueue::HandleInvalidStatusByte(jack_midi_data_t byte)
++{
++ jack_error("JackMidiRawInputWriteQueue::HandleInvalidStatusByte - "
++ "Dropping invalid MIDI status byte '%x'.", (unsigned int) byte);
++}
++
++void
++JackMidiRawInputWriteQueue::HandleUnexpectedSysexEnd(size_t total_bytes)
++{
++ jack_error("JackMidiRawInputWriteQueue::HandleUnexpectedSysexEnd - "
++ "Received a sysex end byte without first receiving a sysex "
++ "start byte. Discarding %d MIDI byte(s). The cable may have "
++ "been unplugged.", total_bytes);
++}
++
++bool
++JackMidiRawInputWriteQueue::PrepareBufferedEvent(jack_nframes_t time)
++{
++ bool result = ! unbuffered_bytes;
++ if (! result) {
++ HandleBufferFailure(unbuffered_bytes, total_bytes);
++ } else {
++ PrepareEvent(time, total_bytes, input_buffer);
++ }
++ Clear();
++ if (status_byte >= 0xf0) {
++ expected_bytes = 0;
++ status_byte = 0;
++ }
++ return result;
++}
++
++bool
++JackMidiRawInputWriteQueue::PrepareByteEvent(jack_nframes_t time,
++ jack_midi_data_t byte)
++{
++ event_byte = byte;
++ PrepareEvent(time, 1, &event_byte);
++ return true;
++}
++
++void
++JackMidiRawInputWriteQueue::PrepareEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ event.buffer = buffer;
++ event.size = size;
++ event.time = time;
++ event_pending = true;
++}
++
++jack_nframes_t
++JackMidiRawInputWriteQueue::Process(jack_nframes_t boundary_frame)
++{
++ if (event_pending) {
++ if (! WriteEvent(boundary_frame)) {
++ return event.time;
++ }
++ }
++ if (! packet) {
++ packet = packet_queue->DequeueEvent();
++ }
++ for (; packet; packet = packet_queue->DequeueEvent()) {
++ for (; packet->size; (packet->buffer)++, (packet->size)--) {
++ if (ProcessByte(packet->time, *(packet->buffer))) {
++ if (! WriteEvent(boundary_frame)) {
++ (packet->buffer)++;
++ (packet->size)--;
++ return event.time;
++ }
++ }
++ }
++ }
++ return 0;
++}
++
++bool
++JackMidiRawInputWriteQueue::ProcessByte(jack_nframes_t time,
++ jack_midi_data_t byte)
++{
++ if (byte >= 0xf8) {
++ // Realtime
++ if (byte == 0xfd) {
++ HandleInvalidStatusByte(byte);
++ return false;
++ }
++ return PrepareByteEvent(time, byte);
++ }
++ if (byte == 0xf7) {
++ // Sysex end
++ if (status_byte == 0xf0) {
++ RecordByte(byte);
++ return PrepareBufferedEvent(time);
++ }
++ HandleUnexpectedSysexEnd(total_bytes);
++ Clear();
++ expected_bytes = 0;
++ status_byte = 0;
++ return false;
++ }
++ if (byte >= 0x80) {
++ // Non-realtime status byte
++ if (total_bytes) {
++ HandleIncompleteMessage(total_bytes);
++ Clear();
++ }
++ status_byte = byte;
++ switch (byte & 0xf0) {
++ case 0x80:
++ case 0x90:
++ case 0xa0:
++ case 0xb0:
++ case 0xe0:
++ // Note On, Note Off, Aftertouch, Control Change, Pitch Wheel
++ expected_bytes = 3;
++ break;
++ case 0xc0:
++ case 0xd0:
++ // Program Change, Channel Pressure
++ expected_bytes = 2;
++ break;
++ case 0xf0:
++ switch (byte) {
++ case 0xf0:
++ // Sysex
++ expected_bytes = 0;
++ break;
++ case 0xf1:
++ case 0xf3:
++ // MTC Quarter Frame, Song Select
++ expected_bytes = 2;
++ break;
++ case 0xf2:
++ // Song Position
++ expected_bytes = 3;
++ break;
++ case 0xf4:
++ case 0xf5:
++ // Undefined
++ HandleInvalidStatusByte(byte);
++ expected_bytes = 0;
++ status_byte = 0;
++ return false;
++ case 0xf6:
++ // Tune Request
++ bool result = PrepareByteEvent(time, byte);
++ if (result) {
++ expected_bytes = 0;
++ status_byte = 0;
++ }
++ return result;
++ }
++ }
++ RecordByte(byte);
++ return false;
++ }
++ // Data byte
++ if (! status_byte) {
++ // Data bytes without a status will be discarded.
++ total_bytes++;
++ unbuffered_bytes++;
++ return false;
++ }
++ if (! total_bytes) {
++ // Apply running status.
++ RecordByte(status_byte);
++ }
++ RecordByte(byte);
++ return (total_bytes == expected_bytes) ? PrepareBufferedEvent(time) :
++ false;
++}
++
++void
++JackMidiRawInputWriteQueue::RecordByte(jack_midi_data_t byte)
++{
++ if (total_bytes < input_buffer_size) {
++ input_buffer[total_bytes] = byte;
++ } else {
++ unbuffered_bytes++;
++ }
++ total_bytes++;
++}
++
++bool
++JackMidiRawInputWriteQueue::WriteEvent(jack_nframes_t boundary_frame)
++{
++ if ((! boundary_frame) || (event.time < boundary_frame)) {
++ switch (write_queue->EnqueueEvent(&event)) {
++ case BUFFER_TOO_SMALL:
++ HandleEventLoss(&event);
++ // Fallthrough on purpose
++ case OK:
++ event_pending = false;
++ return true;
++ default:
++ // This is here to stop compilers from warning us about not
++ // handling enumeration values.
++ ;
++ }
++ }
++ return false;
++}
+--- /dev/null
++++ b/common/JackMidiRawInputWriteQueue.h
+@@ -0,0 +1,177 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiRawInputWriteQueue__
++#define __JackMidiRawInputWriteQueue__
++
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiWriteQueue.h"
++
++namespace Jack {
++
++ /**
++ * This queue enqueues raw, unparsed MIDI packets, and outputs complete
++ * MIDI messages to a write queue.
++ *
++ * Use this queue if the MIDI API you're interfacing with gives you raw
++ * MIDI bytes that must be parsed.
++ */
++
++ class SERVER_EXPORT JackMidiRawInputWriteQueue: public JackMidiWriteQueue {
++
++ private:
++
++ jack_midi_event_t event;
++ jack_midi_data_t event_byte;
++ bool event_pending;
++ size_t expected_bytes;
++ jack_midi_data_t *input_buffer;
++ size_t input_buffer_size;
++ jack_midi_event_t *packet;
++ JackMidiAsyncQueue *packet_queue;
++ jack_midi_data_t status_byte;
++ size_t total_bytes;
++ size_t unbuffered_bytes;
++ JackMidiWriteQueue *write_queue;
++
++ void
++ Clear();
++
++ bool
++ PrepareBufferedEvent(jack_nframes_t time);
++
++ bool
++ PrepareByteEvent(jack_nframes_t time, jack_midi_data_t byte);
++
++ void
++ PrepareEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ bool
++ ProcessByte(jack_nframes_t time, jack_midi_data_t byte);
++
++ void
++ RecordByte(jack_midi_data_t byte);
++
++ bool
++ WriteEvent(jack_nframes_t boundary_frame);
++
++ protected:
++
++ /**
++ * Override this method to specify what happens when there isn't enough
++ * room in the ringbuffer to contain a parsed event. The default
++ * method outputs an error message.
++ */
++
++ virtual void
++ HandleBufferFailure(size_t unbuffered_bytes, size_t total_bytes);
++
++ /**
++ * Override this method to specify what happens when a parsed event
++ * can't be written to the write queue because the event's size exceeds
++ * the total possible space in the write queue. The default method
++ * outputs an error message.
++ */
++
++ virtual void
++ HandleEventLoss(jack_midi_event_t *event);
++
++ /**
++ * Override this method to specify what happens when an incomplete MIDI
++ * message is parsed. The default method outputs an error message.
++ */
++
++ virtual void
++ HandleIncompleteMessage(size_t total_bytes);
++
++ /**
++ * Override this method to specify what happens when an invalid MIDI
++ * status byte is parsed. The default method outputs an error message.
++ */
++
++ virtual void
++ HandleInvalidStatusByte(jack_midi_data_t byte);
++
++ /**
++ * Override this method to specify what happens when a sysex end byte
++ * is parsed without first parsing a sysex begin byte. The default
++ * method outputs an error message.
++ */
++
++ virtual void
++ HandleUnexpectedSysexEnd(size_t total_bytes);
++
++ public:
++
++ using JackMidiWriteQueue::EnqueueEvent;
++
++ /**
++ * Called to create a new raw input write queue. The `write_queue`
++ * argument is the queue to write parsed messages to. The optional
++ * `max_packets` argument specifies the number of packets that can be
++ * enqueued in the internal queue. The optional `max_packet_data`
++ * argument specifies the total number of MIDI bytes that can be put in
++ * the internal queue, AND the maximum size for an event that can be
++ * written to the write queue.
++ */
++
++ JackMidiRawInputWriteQueue(JackMidiWriteQueue *write_queue,
++ size_t max_packet_data=4096,
++ size_t max_packets=1024);
++
++ ~JackMidiRawInputWriteQueue();
++
++ EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ /**
++ * Returns the maximum size event that can be enqueued right *now*.
++ */
++
++ size_t
++ GetAvailableSpace();
++
++ /**
++ * The `Process()` method should be called each time the
++ * `EnqueueEvent()` method returns `OK`. The `Process()` method will
++ * return the next frame at which an event should be sent. The return
++ * value from `Process()` depends upon the result of writing bytes to
++ * the write queue:
++ *
++ * -If the return value is '0', then all *complete* events have been
++ * sent successfully to the write queue. Don't call `Process()` again
++ * until another event has been enqueued.
++ *
++ * -If the return value is a non-zero value, then it specifies the
++ * frame that a pending event is scheduled to sent at. If the frame is
++ * in the future, then `Process()` should be called again at that time;
++ * otherwise, `Process()` should be called as soon as the write queue
++ * will accept events again.
++ */
++
++ jack_nframes_t
++ Process(jack_nframes_t boundary_frame=0);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiRawOutputWriteQueue.cpp
+@@ -0,0 +1,158 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <memory>
++#include <new>
++
++#include "JackError.h"
++#include "JackMidiRawOutputWriteQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackMidiRawOutputWriteQueue;
++
++#define STILL_TIME(c, b) ((! (b)) || ((c) < (b)))
++
++JackMidiRawOutputWriteQueue::
++JackMidiRawOutputWriteQueue(JackMidiSendQueue *send_queue, size_t non_rt_size,
++ size_t max_non_rt_messages, size_t max_rt_messages)
++{
++ non_rt_queue = new JackMidiAsyncQueue(non_rt_size, max_non_rt_messages);
++ std::auto_ptr<JackMidiAsyncQueue> non_rt_ptr(non_rt_queue);
++ rt_queue = new JackMidiAsyncQueue(max_rt_messages, max_rt_messages);
++ std::auto_ptr<JackMidiAsyncQueue> rt_ptr(rt_queue);
++ non_rt_event = 0;
++ rt_event = 0;
++ running_status = 0;
++ this->send_queue = send_queue;
++ rt_ptr.release();
++ non_rt_ptr.release();
++}
++
++JackMidiRawOutputWriteQueue::~JackMidiRawOutputWriteQueue()
++{
++ delete non_rt_queue;
++ delete rt_queue;
++}
++
++void
++JackMidiRawOutputWriteQueue::DequeueNonRealtimeEvent()
++{
++ non_rt_event = non_rt_queue->DequeueEvent();
++ if (non_rt_event) {
++ non_rt_event_time = non_rt_event->time;
++ running_status = ApplyRunningStatus(non_rt_event, running_status);
++ }
++}
++
++void
++JackMidiRawOutputWriteQueue::DequeueRealtimeEvent()
++{
++ rt_event = rt_queue->DequeueEvent();
++ if (rt_event) {
++ rt_event_time = rt_event->time;
++ }
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackMidiRawOutputWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ JackMidiAsyncQueue *queue = (size == 1) && (*buffer >= 0xf8) ? rt_queue :
++ non_rt_queue;
++ return queue->EnqueueEvent(time, size, buffer);
++}
++
++void
++JackMidiRawOutputWriteQueue::HandleWriteQueueBug(jack_nframes_t time,
++ jack_midi_data_t byte)
++{
++ jack_error("JackMidiRawOutputWriteQueue::HandleWriteQueueBug - **BUG** "
++ "The write queue told us that it couldn't enqueue a 1-byte "
++ "MIDI event scheduled for frame '%d'. This is probably a bug "
++ "in the write queue implementation.", time);
++}
++
++jack_nframes_t
++JackMidiRawOutputWriteQueue::Process(jack_nframes_t boundary_frame)
++{
++ if (! non_rt_event) {
++ DequeueNonRealtimeEvent();
++ }
++ if (! rt_event) {
++ DequeueRealtimeEvent();
++ }
++ while (rt_event) {
++ jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
++ if ((rt_event_time > current_frame) && non_rt_event &&
++ (non_rt_event_time < rt_event_time)) {
++ if (! SendNonRTBytes(rt_event_time < boundary_frame ?
++ rt_event_time : boundary_frame)) {
++ return non_rt_event_time;
++ }
++ current_frame = send_queue->GetNextScheduleFrame();
++ }
++ if (! STILL_TIME(current_frame, boundary_frame)) {
++ return (! non_rt_event) ? rt_event_time :
++ non_rt_event_time < rt_event_time ? non_rt_event_time :
++ rt_event_time;
++ }
++ if (! SendByte(rt_event_time, *(rt_event->buffer))) {
++ return rt_event_time;
++ }
++ DequeueRealtimeEvent();
++ }
++ SendNonRTBytes(boundary_frame);
++ return non_rt_event ? non_rt_event_time : 0;
++}
++
++bool
++JackMidiRawOutputWriteQueue::SendByte(jack_nframes_t time,
++ jack_midi_data_t byte)
++{
++ switch (send_queue->EnqueueEvent(time, 1, &byte)) {
++ case BUFFER_TOO_SMALL:
++ HandleWriteQueueBug(time, byte);
++ case OK:
++ return true;
++ default:
++ // This is here to stop compilers from warning us about not handling
++ // enumeration values.
++ ;
++ }
++ return false;
++}
++
++bool
++JackMidiRawOutputWriteQueue::SendNonRTBytes(jack_nframes_t boundary_frame)
++{
++ while (non_rt_event) {
++ for (; non_rt_event->size;
++ (non_rt_event->size)--, (non_rt_event->buffer)++) {
++ jack_nframes_t current_frame = send_queue->GetNextScheduleFrame();
++ if (! STILL_TIME(current_frame, boundary_frame)) {
++ return true;
++ }
++ if (! SendByte(non_rt_event_time, *(non_rt_event->buffer))) {
++ return false;
++ }
++ }
++ DequeueNonRealtimeEvent();
++ }
++ return true;
++}
+--- /dev/null
++++ b/common/JackMidiRawOutputWriteQueue.h
+@@ -0,0 +1,139 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiRawOutputWriteQueue__
++#define __JackMidiRawOutputWriteQueue__
++
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiSendQueue.h"
++
++namespace Jack {
++
++ /**
++ * This queue enqueues valid MIDI events and modifies them for raw output
++ * to a write queue. It has a couple of advantages over straight MIDI
++ * event copying:
++ *
++ * -Running status: Status bytes can be omitted when the status byte of the
++ * current MIDI message is the same as the status byte of the last sent
++ * MIDI message.
++ *
++ * -Realtime messages: Realtime messages are given priority over
++ * non-realtime messages. Realtime bytes are interspersed with
++ * non-realtime bytes so that realtime messages can be sent as close as
++ * possible to the time they're scheduled for sending.
++ *
++ * Use this queue if the MIDI API you're interfacing with allows you to
++ * send raw MIDI bytes.
++ */
++
++ class SERVER_EXPORT JackMidiRawOutputWriteQueue:
++ public JackMidiWriteQueue {
++
++ private:
++
++ jack_midi_event_t *non_rt_event;
++ jack_nframes_t non_rt_event_time;
++ JackMidiAsyncQueue *non_rt_queue;
++ jack_midi_event_t *rt_event;
++ jack_nframes_t rt_event_time;
++ JackMidiAsyncQueue *rt_queue;
++ jack_midi_data_t running_status;
++ JackMidiSendQueue *send_queue;
++
++ void
++ DequeueNonRealtimeEvent();
++
++ void
++ DequeueRealtimeEvent();
++
++ bool
++ SendByte(jack_nframes_t time, jack_midi_data_t byte);
++
++ bool
++ SendNonRTBytes(jack_nframes_t boundary_frame);
++
++ protected:
++
++ /**
++ * Override this method to specify what happens when the write queue
++ * says that a 1-byte event is too large for its buffer. Basically,
++ * this should never happen.
++ */
++
++ virtual void
++ HandleWriteQueueBug(jack_nframes_t time, jack_midi_data_t byte);
++
++ public:
++
++ using JackMidiWriteQueue::EnqueueEvent;
++
++ /**
++ * Called to create a new raw write queue. The `send_queue` argument
++ * is the queue to write raw bytes to. The optional `max_rt_messages`
++ * argument specifies the number of messages that can be enqueued in
++ * the internal realtime queue. The optional `max_non_rt_messages`
++ * argument specifies the number of messages that can be enqueued in
++ * the internal non-realtime queue. The optional `non_rt_size`
++ * argument specifies the total number of MIDI bytes that can be put in
++ * the non-realtime queue.
++ */
++
++ JackMidiRawOutputWriteQueue(JackMidiSendQueue *send_queue,
++ size_t non_rt_size=4096,
++ size_t max_non_rt_messages=1024,
++ size_t max_rt_messages=128);
++
++ ~JackMidiRawOutputWriteQueue();
++
++ EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ /**
++ * The `Process()` method should be called each time the
++ * `EnqueueEvent()` method returns 'OK'. The `Process()` method will
++ * return the next frame at which an event should be sent. The return
++ * value from `Process()` depends upon the result of writing bytes to
++ * the write queue:
++ *
++ * -If the return value is '0', then all events that have been enqueued
++ * in this queue have been sent successfully to the write queue. Don't
++ * call `Process()` again until another event has been enqueued.
++ *
++ * -If the return value is an earlier frame or the current frame, it
++ * means that the write queue returned 'BUFFER_FULL', 'ERROR', or
++ * 'EVENT_EARLY' when this queue attempted to send the next byte, and
++ * that the byte should have already been sent, or is scheduled to be
++ * sent *now*. `Process()` should be called again when the write queue
++ * can enqueue events again successfully. How to determine when this
++ * will happen is left up to the caller.
++ *
++ * -If the return value is in the future, then `Process()` should be
++ * called again at that time, or after another event is enqueued.
++ */
++
++ jack_nframes_t
++ Process(jack_nframes_t boundary_frame=0);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiReadQueue.cpp
+@@ -0,0 +1,27 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackMidiReadQueue.h"
++
++using Jack::JackMidiReadQueue;
++
++JackMidiReadQueue::~JackMidiReadQueue()
++{
++ // Empty
++}
+--- /dev/null
++++ b/common/JackMidiReadQueue.h
+@@ -0,0 +1,55 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiReadQueue__
++#define __JackMidiReadQueue__
++
++#include "JackMidiPort.h"
++
++namespace Jack {
++
++ /**
++ * Interface for objects that MIDI events can be read from.
++ */
++
++ class SERVER_EXPORT JackMidiReadQueue {
++
++ public:
++
++ virtual
++ ~JackMidiReadQueue();
++
++ /**
++ * Dequeues an event from the queue. Returns the event, or 0 if no
++ * events are available for reading.
++ *
++ * An event dequeued from the read queue is guaranteed to be valid up
++ * until another event is dequeued, at which all bets are off. Make
++ * sure that you handle each event you dequeue before dequeueing the
++ * next event.
++ */
++
++ virtual jack_midi_event_t *
++ DequeueEvent() = 0;
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiReceiveQueue.cpp
+@@ -0,0 +1,27 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackMidiReceiveQueue.h"
++
++using Jack::JackMidiReceiveQueue;
++
++JackMidiReceiveQueue::~JackMidiReceiveQueue()
++{
++ // Empty
++}
+--- /dev/null
++++ b/common/JackMidiReceiveQueue.h
+@@ -0,0 +1,42 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiReceiveQueue__
++#define __JackMidiReceiveQueue__
++
++#include "JackMidiReadQueue.h"
++
++namespace Jack {
++
++ /**
++ * Implemented by MIDI input connections.
++ */
++
++ class SERVER_EXPORT JackMidiReceiveQueue: public JackMidiReadQueue {
++
++ public:
++
++ virtual
++ ~JackMidiReceiveQueue();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiSendQueue.cpp
+@@ -0,0 +1,34 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackMidiSendQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackMidiSendQueue;
++
++JackMidiSendQueue::~JackMidiSendQueue()
++{
++ // Empty
++}
++
++jack_nframes_t
++JackMidiSendQueue::GetNextScheduleFrame()
++{
++ return GetCurrentFrame();
++}
+--- /dev/null
++++ b/common/JackMidiSendQueue.h
+@@ -0,0 +1,52 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiSendQueue__
++#define __JackMidiSendQueue__
++
++#include "JackMidiWriteQueue.h"
++
++namespace Jack {
++
++ /**
++ * Implemented by MIDI output connections.
++ */
++
++ class SERVER_EXPORT JackMidiSendQueue: public JackMidiWriteQueue {
++
++ public:
++
++ using JackMidiWriteQueue::EnqueueEvent;
++
++ virtual
++ ~JackMidiSendQueue();
++
++ /**
++ * Returns the next frame that a MIDI message can be sent at. The
++ * default method returns the current frame.
++ */
++
++ virtual jack_nframes_t
++ GetNextScheduleFrame();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/common/JackMidiUtil.cpp
+@@ -0,0 +1,121 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackEngineControl.h"
++#include "JackFrameTimer.h"
++#include "JackGlobals.h"
++#include "JackMidiUtil.h"
++#include "JackTime.h"
++
++jack_midi_data_t
++Jack::ApplyRunningStatus(size_t *size, jack_midi_data_t **buffer,
++ jack_midi_data_t running_status)
++{
++
++ // Stolen and modified from alsa/midi_pack.h
++
++ jack_midi_data_t status = **buffer;
++ if ((status >= 0x80) && (status < 0xf0)) {
++ if (status == running_status) {
++ (*buffer)++;
++ (*size)--;
++ } else {
++ running_status = status;
++ }
++ } else if (status < 0xf8) {
++ running_status = 0;
++ }
++ return running_status;
++}
++
++jack_midi_data_t
++Jack::ApplyRunningStatus(jack_midi_event_t *event,
++ jack_midi_data_t running_status)
++{
++ return ApplyRunningStatus(&(event->size), &(event->buffer),
++ running_status);
++}
++
++jack_nframes_t
++Jack::GetCurrentFrame()
++{
++ jack_time_t time = GetMicroSeconds();
++ JackEngineControl *control = GetEngineControl();
++ JackTimer timer;
++ control->ReadFrameTime(&timer);
++ return timer.Time2Frames(time, control->fBufferSize);
++}
++
++jack_nframes_t
++Jack::GetFramesFromTime(jack_time_t time)
++{
++ JackEngineControl* control = GetEngineControl();
++ JackTimer timer;
++ control->ReadFrameTime(&timer);
++ return timer.Time2Frames(time, control->fBufferSize);
++}
++
++jack_nframes_t
++Jack::GetLastFrame()
++{
++ return GetEngineControl()->fFrameTimer.ReadCurrentState()->CurFrame();
++}
++
++int
++Jack::GetMessageLength(jack_midi_data_t status_byte)
++{
++ switch (status_byte & 0xf0) {
++ case 0x80:
++ case 0x90:
++ case 0xa0:
++ case 0xb0:
++ case 0xe0:
++ return 3;
++ case 0xc0:
++ case 0xd0:
++ return 2;
++ case 0xf0:
++ switch (status_byte) {
++ case 0xf0:
++ return 0;
++ case 0xf1:
++ case 0xf3:
++ return 2;
++ case 0xf2:
++ return 3;
++ case 0xf4:
++ case 0xf5:
++ case 0xf7:
++ case 0xfd:
++ break;
++ default:
++ return 1;
++ }
++ }
++ return -1;
++}
++
++jack_time_t
++Jack::GetTimeFromFrames(jack_nframes_t frames)
++{
++ JackEngineControl* control = GetEngineControl();
++ JackTimer timer;
++ control->ReadFrameTime(&timer);
++ return timer.Frames2Time(frames, control->fBufferSize);
++}
+--- /dev/null
++++ b/common/JackMidiUtil.h
+@@ -0,0 +1,102 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiUtil__
++#define __JackMidiUtil__
++
++#include "JackMidiPort.h"
++
++namespace Jack {
++
++ /**
++ * Use this function to optimize MIDI output by omitting unnecessary status
++ * bytes. This can't be used with all MIDI APIs, so before using this
++ * function, make sure that your MIDI API doesn't require complete MIDI
++ * messages to be sent.
++ *
++ * To start using this function, call this method with pointers to the
++ * `size` and `buffer` arguments of the MIDI message you want to send, and
++ * set the `running_status` argument to '0'. For each subsequent MIDI
++ * message, call this method with pointers to its `size` and `buffer`
++ * arguments, and set the `running_status` argument to the return value of
++ * the previous call to this function.
++ *
++ * Note: This function will alter the `size` and `buffer` of your MIDI
++ * message for each message that can be optimized.
++ */
++
++ SERVER_EXPORT jack_midi_data_t
++ ApplyRunningStatus(size_t *size, jack_midi_data_t **buffer,
++ jack_midi_data_t running_status=0);
++
++ /**
++ * A wrapper function for the above `ApplyRunningStatus` function.
++ */
++
++ SERVER_EXPORT jack_midi_data_t
++ ApplyRunningStatus(jack_midi_event_t *event,
++ jack_midi_data_t running_status);
++
++ /**
++ * Gets the estimated current time in frames. This function has the same
++ * functionality as the JACK client API function `jack_frame_time`.
++ */
++
++ SERVER_EXPORT jack_nframes_t
++ GetCurrentFrame();
++
++ /**
++ * Gets the estimated frame that will be occurring at the given time. This
++ * function has the same functionality as the JACK client API function
++ * `jack_time_to_frames`.
++ */
++
++ SERVER_EXPORT jack_nframes_t
++ GetFramesFromTime(jack_time_t time);
++
++ /**
++ * Gets the precise time at the start of the current process cycle. This
++ * function has the same functionality as the JACK client API function
++ * `jack_last_frame_time`.
++ */
++
++ SERVER_EXPORT jack_nframes_t
++ GetLastFrame();
++
++ /**
++ * Returns the expected message length for the status byte. Returns 0 if
++ * the status byte is a system exclusive status byte, or -1 if the status
++ * byte is invalid.
++ */
++
++ SERVER_EXPORT int
++ GetMessageLength(jack_midi_data_t status_byte);
++
++ /**
++ * Gets the estimated time at which the given frame will occur. This
++ * function has the same functionality as the JACK client API function
++ * `jack_frames_to_time`.
++ */
++
++ SERVER_EXPORT jack_time_t
++ GetTimeFromFrames(jack_nframes_t frames);
++
++};
++
++#endif
+--- /dev/null
++++ b/common/JackMidiWriteQueue.cpp
+@@ -0,0 +1,27 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackMidiWriteQueue.h"
++
++using Jack::JackMidiWriteQueue;
++
++JackMidiWriteQueue::~JackMidiWriteQueue()
++{
++ // Empty
++}
+--- /dev/null
++++ b/common/JackMidiWriteQueue.h
+@@ -0,0 +1,82 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackMidiWriteQueue__
++#define __JackMidiWriteQueue__
++
++#include "JackMidiPort.h"
++
++namespace Jack {
++
++ /**
++ * Interface for classes that act as write queues for MIDI messages. Write
++ * queues are used by processors to transfer data to the next processor.
++ */
++
++ class SERVER_EXPORT JackMidiWriteQueue {
++
++ public:
++
++ enum EnqueueResult {
++ BUFFER_FULL,
++ BUFFER_TOO_SMALL,
++ EVENT_EARLY,
++ EN_ERROR,
++ OK
++ };
++
++ virtual ~JackMidiWriteQueue();
++
++ /**
++ * Enqueues a data packet in the write queue of `size` bytes contained
++ * in `buffer` that will be sent the absolute time specified by `time`.
++ * This method should not block unless 1.) this write queue represents
++ * the actual outbound MIDI connection, 2.) the MIDI event is being
++ * sent *now*, meaning that `time` is less than or equal to *now*, and
++ * 3.) the method is *not* being called in the process thread. The
++ * method should return `OK` if the event was enqueued, `BUFFER_FULL`
++ * if the write queue isn't able to accept the event right now,
++ * `BUFFER_TOO_SMALL` if this write queue will never be able to accept
++ * the event because the event is too large, `EVENT_EARLY` if this
++ * queue cannot schedule events ahead of time, and `EN_ERROR` if an error
++ * occurs that cannot be specified by another return code.
++ */
++
++ virtual EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer) = 0;
++
++ /**
++ * A wrapper method for the `EnqueueEvent` method above. The optional
++ * 'frame_offset' argument is an amount of frames to add to the event's
++ * time.
++ */
++
++ inline EnqueueResult
++ EnqueueEvent(jack_midi_event_t *event, jack_nframes_t frame_offset=0)
++ {
++ return EnqueueEvent(event->time + frame_offset, event->size,
++ event->buffer);
++ }
++
++ };
++
++}
++
++#endif
+--- a/common/JackMutex.h
++++ b/common/JackMutex.h
+@@ -37,7 +37,7 @@
+ {
+
+ protected:
+-
++
+ JackMutex fMutex;
+
+ JackLockAble()
+@@ -46,10 +46,10 @@
+ {}
+
+ public:
+-
+- void Lock()
++
++ bool Lock()
+ {
+- fMutex.Lock();
++ return fMutex.Lock();
+ }
+
+ bool Trylock()
+@@ -57,9 +57,9 @@
+ return fMutex.Trylock();
+ }
+
+- void Unlock()
++ bool Unlock()
+ {
+- fMutex.Unlock();
++ return fMutex.Unlock();
+ }
+
+ };
+--- a/common/JackNetAdapter.cpp
++++ b/common/JackNetAdapter.cpp
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -25,72 +25,89 @@
+
+ namespace Jack
+ {
+- JackNetAdapter::JackNetAdapter ( jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
+- : JackAudioAdapterInterface ( buffer_size, sample_rate ), JackNetSlaveInterface(), fThread ( this )
++ JackNetAdapter::JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
++ : JackAudioAdapterInterface(buffer_size, sample_rate), JackNetSlaveInterface(), fThread(this)
+ {
+- jack_log ( "JackNetAdapter::JackNetAdapter" );
++ jack_log("JackNetAdapter::JackNetAdapter");
+
+- //global parametering
+- //we can't call JackNetSlaveInterface constructor with some parameters before
+- //because we don't have full parametering right now
+- //parameters will be parsed from the param list, and then JackNetSlaveInterface will be filled with proper values
+- strcpy ( fMulticastIP, DEFAULT_MULTICAST_IP );
+- uint port = DEFAULT_PORT;
+- GetHostName ( fParams.fName, JACK_CLIENT_NAME_SIZE );
+- fSocket.GetName ( fParams.fSlaveNetName );
++ /*
++ Global parameter setting : we can't call JackNetSlaveInterface constructor with some parameters before,
++ because we don't have full parametering right now, parameters will be parsed from the param list,
++ and then JackNetSlaveInterface will be filled with proper values.
++ */
++ char multicast_ip[32];
++ uint udp_port;
++ GetHostName(fParams.fName, JACK_CLIENT_NAME_SIZE);
++ fSocket.GetName(fParams.fSlaveNetName);
+ fParams.fMtu = DEFAULT_MTU;
++ // Desactivated for now...
+ fParams.fTransportSync = 0;
+- fParams.fSendAudioChannels = 2;
+- fParams.fReturnAudioChannels = 2;
++ int send_audio = -1;
++ int return_audio = -1;
+ fParams.fSendMidiChannels = 0;
+ fParams.fReturnMidiChannels = 0;
+ fParams.fSampleRate = sample_rate;
+ fParams.fPeriodSize = buffer_size;
+ fParams.fSlaveSyncMode = 1;
+- fParams.fNetworkMode = 's';
+- fJackClient = jack_client;
++ fParams.fNetworkLatency = 2;
++ fParams.fSampleEncoder = JackFloatEncoder;
++ fClient = jack_client;
++
++ // Possibly use env variable
++ const char* default_udp_port = getenv("JACK_NETJACK_PORT");
++ udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
++
++ const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
++ if (default_multicast_ip) {
++ strcpy(multicast_ip, default_multicast_ip);
++ } else {
++ strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
++ }
+
+ //options parsing
+ const JSList* node;
+ const jack_driver_param_t* param;
+- for ( node = params; node; node = jack_slist_next ( node ) )
++ for (node = params; node; node = jack_slist_next(node))
+ {
+- param = ( const jack_driver_param_t* ) node->data;
+- switch ( param->character )
+- {
++ param = (const jack_driver_param_t*) node->data;
++
++ switch (param->character) {
+ case 'a' :
+- if (strlen (param->value.str) < 32)
+- strcpy(fMulticastIP, param->value.str);
+- else
+- jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
++ assert(strlen(param->value.str) < 32);
++ strcpy(multicast_ip, param->value.str);
+ break;
+ case 'p' :
+- fSocket.SetPort ( param->value.ui );
++ udp_port = param->value.ui;
+ break;
+ case 'M' :
+ fParams.fMtu = param->value.i;
+ break;
+ case 'C' :
+- fParams.fSendAudioChannels = param->value.i;
++ send_audio = param->value.i;
+ break;
+ case 'P' :
+- fParams.fReturnAudioChannels = param->value.i;
++ return_audio = param->value.i;
+ break;
+ case 'n' :
+- strncpy ( fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE );
++ strncpy(fParams.fName, param->value.str, JACK_CLIENT_NAME_SIZE);
+ break;
+ case 't' :
+- //fParams.fTransportSync = param->value.ui;
++ fParams.fTransportSync = param->value.ui;
+ break;
+- case 'm' :
+- if ( strcmp ( param->value.str, "normal" ) == 0 )
+- fParams.fNetworkMode = 'n';
+- else if ( strcmp ( param->value.str, "slow" ) == 0 )
+- fParams.fNetworkMode = 's';
+- else if ( strcmp ( param->value.str, "fast" ) == 0 )
+- fParams.fNetworkMode = 'f';
+- else
+- jack_error ( "Unknown network mode, using 'normal' mode." );
++ #if HAVE_CELT
++ case 'c':
++ if (param->value.i > 0) {
++ fParams.fSampleEncoder = JackCeltEncoder;
++ fParams.fKBps = param->value.i;
++ }
++ break;
++ #endif
++ case 'l' :
++ fParams.fNetworkLatency = param->value.i;
++ if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
++ jack_error("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
++ throw std::bad_alloc();
++ }
+ break;
+ case 'q':
+ fQuality = param->value.ui;
+@@ -102,34 +119,41 @@
+ }
+ }
+
+- //set the socket parameters
+- fSocket.SetPort ( port );
+- fSocket.SetAddress ( fMulticastIP, port );
+-
+- //set the audio adapter interface channel values
+- SetInputs ( fParams.fSendAudioChannels );
+- SetOutputs ( fParams.fReturnAudioChannels );
++ strcpy(fMulticastIP, multicast_ip);
++
++ // Set the socket parameters
++ fSocket.SetPort(udp_port);
++ fSocket.SetAddress(fMulticastIP, udp_port);
+
+- //soft buffers will be allocated later (once network initialization done)
++ // If not set, takes default
++ fParams.fSendAudioChannels = (send_audio == -1) ? 2 : send_audio;
++
++ // If not set, takes default
++ fParams.fReturnAudioChannels = (return_audio == -1) ? 2 : return_audio;
++
++ // Set the audio adapter interface channel values
++ SetInputs(fParams.fSendAudioChannels);
++ SetOutputs(fParams.fReturnAudioChannels);
++
++ // Soft buffers will be allocated later (once network initialization done)
+ fSoftCaptureBuffer = NULL;
+ fSoftPlaybackBuffer = NULL;
+ }
+
+ JackNetAdapter::~JackNetAdapter()
+ {
+- jack_log ( "JackNetAdapter::~JackNetAdapter" );
++ jack_log("JackNetAdapter::~JackNetAdapter");
+
+- int port_index;
+- if ( fSoftCaptureBuffer )
+- {
+- for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
++ if (fSoftCaptureBuffer) {
++ for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
+ delete[] fSoftCaptureBuffer[port_index];
++ }
+ delete[] fSoftCaptureBuffer;
+ }
+- if ( fSoftPlaybackBuffer )
+- {
+- for ( port_index = 0; port_index < fPlaybackChannels; port_index++ )
++ if (fSoftPlaybackBuffer) {
++ for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
+ delete[] fSoftPlaybackBuffer[port_index];
++ }
+ delete[] fSoftPlaybackBuffer;
+ }
+ }
+@@ -137,14 +161,11 @@
+ //open/close--------------------------------------------------------------------------
+ int JackNetAdapter::Open()
+ {
+- jack_log ( "JackNetAdapter::Open" );
+-
+- jack_info ( "NetAdapter started in %s mode %s Master's transport sync.",
+- ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
++ jack_info("NetAdapter started in %s mode %s Master's transport sync.",
++ (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
+
+- if ( fThread.StartSync() < 0 )
+- {
+- jack_error ( "Cannot start netadapter thread" );
++ if (fThread.StartSync() < 0) {
++ jack_error("Cannot start netadapter thread");
+ return -1;
+ }
+
+@@ -153,89 +174,79 @@
+
+ int JackNetAdapter::Close()
+ {
+- jack_log ( "JackNetAdapter::Close" );
++ int res = 0;
++ jack_log("JackNetAdapter::Close");
+
+ #ifdef JACK_MONITOR
+ fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
+ #endif
+
+- switch ( fThread.GetStatus() )
+- {
+- // Kill the thread in Init phase
+- case JackThread::kStarting:
+- case JackThread::kIniting:
+- if ( fThread.Kill() < 0 )
+- {
+- jack_error ( "Cannot kill thread" );
+- return -1;
+- }
+- break;
+- // Stop when the thread cycle is finished
+-
+- case JackThread::kRunning:
+- if ( fThread.Stop() < 0 )
+- {
+- jack_error ( "Cannot stop thread" );
+- return -1;
+- }
+- break;
+-
+- default:
+- break;
++ if (fThread.Kill() < 0) {
++ jack_error("Cannot kill thread");
++ res = -1;
+ }
++
+ fSocket.Close();
+- return 0;
+- }
++ return res;
++ }
+
+- int JackNetAdapter::SetBufferSize ( jack_nframes_t buffer_size )
++ int JackNetAdapter::SetBufferSize(jack_nframes_t buffer_size)
+ {
+- JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
++ JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
+ return 0;
+ }
+
+ //thread------------------------------------------------------------------------------
++ // TODO : if failure, thread exist... need to restart ?
++
+ bool JackNetAdapter::Init()
+ {
+- jack_log ( "JackNetAdapter::Init" );
+-
+- int port_index;
++ jack_log("JackNetAdapter::Init");
+
+ //init network connection
+- if ( !JackNetSlaveInterface::Init() )
++ if (!JackNetSlaveInterface::Init()) {
++ jack_error("JackNetSlaveInterface::Init() error...");
+ return false;
++ }
+
+ //then set global parameters
+- SetParams();
++ if (!SetParams()) {
++ jack_error("SetParams error...");
++ return false;
++ }
+
+ //set buffers
+- fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
+- for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
+- {
+- fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
+- fNetAudioCaptureBuffer->SetBuffer ( port_index, fSoftCaptureBuffer[port_index] );
++ if (fCaptureChannels > 0) {
++ fSoftCaptureBuffer = new sample_t*[fCaptureChannels];
++ for (int port_index = 0; port_index < fCaptureChannels; port_index++) {
++ fSoftCaptureBuffer[port_index] = new sample_t[fParams.fPeriodSize];
++ fNetAudioCaptureBuffer->SetBuffer(port_index, fSoftCaptureBuffer[port_index]);
++ }
+ }
+- fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
+- for ( port_index = 0; port_index < fCaptureChannels; port_index++ )
+- {
+- fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
+- fNetAudioPlaybackBuffer->SetBuffer ( port_index, fSoftPlaybackBuffer[port_index] );
++
++ if (fPlaybackChannels > 0) {
++ fSoftPlaybackBuffer = new sample_t*[fPlaybackChannels];
++ for (int port_index = 0; port_index < fPlaybackChannels; port_index++) {
++ fSoftPlaybackBuffer[port_index] = new sample_t[fParams.fPeriodSize];
++ fNetAudioPlaybackBuffer->SetBuffer(port_index, fSoftPlaybackBuffer[port_index]);
++ }
+ }
+
+ //set audio adapter parameters
+- SetAdaptedBufferSize ( fParams.fPeriodSize );
+- SetAdaptedSampleRate ( fParams.fSampleRate );
+-
++ SetAdaptedBufferSize(fParams.fPeriodSize);
++ SetAdaptedSampleRate(fParams.fSampleRate);
++
+ // Will do "something" on OSX only...
+ fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
+-
++
+ if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) {
+ jack_error("AcquireSelfRealTime error");
+ } else {
+ set_threaded_log_function();
+ }
+-
++
+ //init done, display parameters
+- SessionParamsDisplay ( &fParams );
++ SessionParamsDisplay(&fParams);
+ return true;
+ }
+
+@@ -244,12 +255,13 @@
+ try {
+ // Keep running even in case of error
+ while (fThread.GetStatus() == JackThread::kRunning)
+- if (Process() == SOCKET_ERROR)
++ if (Process() == SOCKET_ERROR) {
+ return false;
++ }
+ return false;
+ } catch (JackNetException& e) {
+ e.PrintMessage();
+- jack_info("NetAdapter is restarted.");
++ jack_info("NetAdapter is restarted");
+ Reset();
+ fThread.DropSelfRealTime();
+ fThread.SetStatus(JackThread::kIniting);
+@@ -268,26 +280,25 @@
+ //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver)
+
+ //is there a new transport state ?
+- if ( fSendTransportData.fNewState && ( fSendTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
+- {
+- switch ( fSendTransportData.fState )
++ if (fSendTransportData.fNewState &&(fSendTransportData.fState != jack_transport_query(fClient, NULL))) {
++ switch (fSendTransportData.fState)
+ {
+ case JackTransportStopped :
+- jack_transport_stop ( fJackClient );
+- jack_info ( "NetMaster : transport stops." );
++ jack_transport_stop(fClient);
++ jack_info("NetMaster : transport stops");
+ break;
+-
++
+ case JackTransportStarting :
+- jack_transport_reposition ( fJackClient, &fSendTransportData.fPosition );
+- jack_transport_start ( fJackClient );
+- jack_info ( "NetMaster : transport starts." );
++ jack_transport_reposition(fClient, &fSendTransportData.fPosition);
++ jack_transport_start(fClient);
++ jack_info("NetMaster : transport starts");
+ break;
+-
++
+ case JackTransportRolling :
+- //TODO , we need to :
++ // TODO, we need to :
+ // - find a way to call TransportEngine->SetNetworkSync()
+ // - turn the transport state to JackTransportRolling
+- jack_info ( "NetMaster : transport rolls." );
++ jack_info("NetMaster : transport rolls");
+ break;
+ }
+ }
+@@ -299,33 +310,30 @@
+ int refnum = -1;
+ bool conditional = 0;
+ //TODO : get the actual timebase master
+- if ( refnum != fLastTimebaseMaster )
+- {
++ if (refnum != fLastTimebaseMaster) {
+ //timebase master has released its function
+- if ( refnum == -1 )
+- {
++ if (refnum == -1) {
+ fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
+- jack_info ( "Sending a timebase master release request." );
+- }
+- //there is a new timebase master
+- else
+- {
+- fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
+- jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" );
++ jack_info("Sending a timebase master release request.");
++ } else {
++ //there is a new timebase master
++ fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
++ jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
+ }
+ fLastTimebaseMaster = refnum;
+- }
+- else
++ } else {
+ fReturnTransportData.fTimebaseMaster = NO_CHANGE;
++ }
+
+ //update transport state and position
+- fReturnTransportData.fState = jack_transport_query ( fJackClient, &fReturnTransportData.fPosition );
++ fReturnTransportData.fState = jack_transport_query(fClient, &fReturnTransportData.fPosition);
+
+ //is it a new state (that the master need to know...) ?
+- fReturnTransportData.fNewState = ( ( fReturnTransportData.fState != fLastTransportState ) &&
+- ( fReturnTransportData.fState != fSendTransportData.fState ) );
+- if ( fReturnTransportData.fNewState )
+- jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) );
++ fReturnTransportData.fNewState = ((fReturnTransportData.fState != fLastTransportState) &&
++ (fReturnTransportData.fState != fSendTransportData.fState));
++ if (fReturnTransportData.fNewState) {
++ jack_info("Sending transport state '%s'.", GetTransportState(fReturnTransportData.fState));
++ }
+ fLastTransportState = fReturnTransportData.fState;
+ }
+
+@@ -334,8 +342,9 @@
+ {
+ //don't return -1 in case of sync recv failure
+ //we need the process to continue for network error detection
+- if ( SyncRecv() == SOCKET_ERROR )
++ if (SyncRecv() == SOCKET_ERROR) {
+ return 0;
++ }
+
+ DecodeSyncPacket();
+ return DataRecv();
+@@ -344,9 +353,10 @@
+ int JackNetAdapter::Write()
+ {
+ EncodeSyncPacket();
+-
+- if ( SyncSend() == SOCKET_ERROR )
++
++ if (SyncSend() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ return DataSend();
+ }
+@@ -356,19 +366,21 @@
+ {
+ //read data from the network
+ //in case of fatal network error, stop the process
+- if (Read() == SOCKET_ERROR)
++ if (Read() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
+-
++ }
++
+ PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize);
+
+ //then write data to network
+ //in case of failure, stop process
+- if (Write() == SOCKET_ERROR)
++ if (Write() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ return 0;
+ }
+-
++
+ } // namespace Jack
+
+ //loader------------------------------------------------------------------------------
+@@ -384,155 +396,102 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
+-
+- strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 11;
+- desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
+-
+- int i = 0;
+- strcpy ( desc->params[i].name, "multicast_ip" );
+- desc->params[i].character = 'a';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
+- strcpy ( desc->params[i].short_desc, "Multicast Address" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "udp_net_port" );
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = DEFAULT_PORT;
+- strcpy ( desc->params[i].short_desc, "UDP port" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "mtu" );
+- desc->params[i].character = 'M';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = DEFAULT_MTU;
+- strcpy ( desc->params[i].short_desc, "MTU to the master" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "input-ports" );
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = 2;
+- strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "output-ports" );
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = 2;
+- strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "client-name" );
+- desc->params[i].character = 'n';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "'hostname'" );
+- strcpy ( desc->params[i].short_desc, "Name of the jack client" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "transport-sync" );
+- desc->params[i].character = 't';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 1U;
+- strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "mode" );
+- desc->params[i].character = 'm';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "slow" );
+- strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy(desc->params[i].name, "quality");
+- desc->params[i].character = 'q';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ring-buffer");
+- desc->params[i].character = 'g';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 32768;
+- strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
+- strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
+-
+- i++;
+- strcpy ( desc->params[i].name, "auto-connect" );
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("netadapter", JackDriverNone, "netjack net <==> audio backend adapter", &filler);
++
++ strcpy(value.str, DEFAULT_MULTICAST_IP);
++ jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
++
++ value.i = DEFAULT_PORT;
++ jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
++
++ value.i = DEFAULT_MTU;
++ jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
++
++ value.i = 2;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio output ports", NULL);
++
++ #if HAVE_CELT
++ value.i = -1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
++ #endif
++
++ strcpy(value.str, "'hostname'");
++ jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
++
++ value.ui = 0U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
++
++ value.ui = 5U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
++
++ value.i = 32768;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", "");
++
+ return desc;
+ }
+
+- SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
++ SERVER_EXPORT int jack_internal_initialize(jack_client_t* client, const JSList* params)
+ {
+- jack_log ( "Loading netadapter" );
++ jack_log("Loading netadapter");
+
+ Jack::JackAudioAdapter* adapter;
+- jack_nframes_t buffer_size = jack_get_buffer_size ( jack_client );
+- jack_nframes_t sample_rate = jack_get_sample_rate ( jack_client );
+-
++ jack_nframes_t buffer_size = jack_get_buffer_size(client);
++ jack_nframes_t sample_rate = jack_get_sample_rate(client);
++
+ try {
+-
+- adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false);
+- assert ( adapter );
+
+- if ( adapter->Open() == 0 )
++ adapter = new Jack::JackAudioAdapter(client, new Jack::JackNetAdapter(client, buffer_size, sample_rate, params), params);
++ assert(adapter);
++
++ if (adapter->Open() == 0) {
+ return 0;
+- else
+- {
++ } else {
+ delete adapter;
+ return 1;
+ }
+-
++
+ } catch (...) {
++ jack_info("NetAdapter allocation error");
+ return 1;
+ }
+ }
+
+- SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
++ SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
+ {
+ JSList* params = NULL;
+ bool parse_params = true;
+ int res = 1;
+ jack_driver_desc_t* desc = jack_get_descriptor();
+
+- Jack::JackArgParser parser ( load_init );
+- if ( parser.GetArgc() > 0 )
+- parse_params = parser.ParseParams ( desc, ¶ms );
++ Jack::JackArgParser parser(load_init);
++ if (parser.GetArgc() > 0) {
++ parse_params = parser.ParseParams(desc, ¶ms);
++ }
+
+ if (parse_params) {
+- res = jack_internal_initialize ( jack_client, params );
+- parser.FreeParams ( params );
++ res = jack_internal_initialize(jack_client, params);
++ parser.FreeParams(params);
+ }
+ return res;
+ }
+
+- SERVER_EXPORT void jack_finish ( void* arg )
++ SERVER_EXPORT void jack_finish(void* arg)
+ {
+- Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*> ( arg );
++ Jack::JackAudioAdapter* adapter = static_cast<Jack::JackAudioAdapter*>(arg);
+
+ if (adapter) {
+- jack_log ( "Unloading netadapter" );
++ jack_log("Unloading netadapter");
+ adapter->Close();
+ delete adapter;
+ }
+--- a/common/JackNetAdapter.h
++++ b/common/JackNetAdapter.h
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -30,44 +30,48 @@
+ \brief Net adapter.
+ */
+
+- class JackNetAdapter : public JackAudioAdapterInterface, public JackNetSlaveInterface, public JackRunnableInterface
++ class JackNetAdapter : public JackAudioAdapterInterface,
++ public JackNetSlaveInterface,
++ public JackRunnableInterface
+ {
+- private:
+- //jack data
+- jack_client_t* fJackClient;
+
+- //transport data
+- int fLastTransportState;
+- int fLastTimebaseMaster;
+-
+- //sample buffers
+- sample_t** fSoftCaptureBuffer;
+- sample_t** fSoftPlaybackBuffer;
++ private:
+
+- //adapter thread
+- JackThread fThread;
++ //jack data
++ jack_client_t* fClient;
+
+- //transport
+- void EncodeTransportData();
+- void DecodeTransportData();
++ //transport data
++ int fLastTransportState;
++ int fLastTimebaseMaster;
+
+- public:
++ //sample buffers
++ sample_t** fSoftCaptureBuffer;
++ sample_t** fSoftPlaybackBuffer;
+
+- JackNetAdapter ( jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params );
+- ~JackNetAdapter();
++ //adapter thread
++ JackThread fThread;
+
+- int Open();
+- int Close();
++ //transport
++ void EncodeTransportData();
++ void DecodeTransportData();
+
+- int SetBufferSize ( jack_nframes_t buffer_size );
++ public:
+
+- bool Init();
+- bool Execute();
++ JackNetAdapter(jack_client_t* jack_client, jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
++ ~JackNetAdapter();
+
+- int Read();
+- int Write();
++ int Open();
++ int Close();
+
+- int Process();
++ int SetBufferSize(jack_nframes_t buffer_size);
++
++ bool Init();
++ bool Execute();
++
++ int Read();
++ int Write();
++
++ int Process();
+ };
+ }
+
+--- /dev/null
++++ b/common/JackNetAPI.cpp
+@@ -0,0 +1,1045 @@
++/*
++Copyright (C) 2009-2011 Grame
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <assert.h>
++#include <stdarg.h>
++#include "JackNetInterface.h"
++#include "JackPlatformPlug.h"
++#include "JackError.h"
++#include "JackTime.h"
++#include "JackException.h"
++#include "JackAudioAdapterInterface.h"
++
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++
++ // NetJack common API
++
++ #define MASTER_NAME_SIZE 256
++
++ enum JackNetEncoder {
++
++ JackFloatEncoder = 0,
++ JackIntEncoder = 1,
++ JackCeltEncoder = 2,
++ JackMaxEncoder = 3
++ };
++
++ typedef struct {
++
++ int audio_input;
++ int audio_output;
++ int midi_input;
++ int midi_output;
++ int mtu;
++ int time_out; // in millisecond, -1 means in infinite
++ int encoder; // one of JackNetEncoder
++ int kbps; // KB per second for CELT encoder
++ int latency; // network cycles
++
++ } jack_slave_t;
++
++ typedef struct {
++
++ int audio_input;
++ int audio_output;
++ int midi_input;
++ int midi_output;
++ jack_nframes_t buffer_size;
++ jack_nframes_t sample_rate;
++ char master_name[MASTER_NAME_SIZE];
++
++ } jack_master_t;
++
++ // NetJack slave API
++
++ typedef struct _jack_net_slave jack_net_slave_t;
++
++ typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size,
++ int audio_input,
++ float** audio_input_buffer,
++ int midi_input,
++ void** midi_input_buffer,
++ int audio_output,
++ float** audio_output_buffer,
++ int midi_output,
++ void** midi_output_buffer,
++ void* data);
++
++ typedef int (*JackNetSlaveBufferSizeCallback) (jack_nframes_t nframes, void *arg);
++ typedef int (*JackNetSlaveSampleRateCallback) (jack_nframes_t nframes, void *arg);
++ typedef void (*JackNetSlaveShutdownCallback) (void* data);
++
++ SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result);
++ SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net);
++
++ SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net);
++ SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net);
++
++ SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg);
++ SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t* net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg);
++ SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t* net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg);
++ SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t* net, JackNetSlaveShutdownCallback shutdown_callback, void *arg);
++
++ // NetJack master API
++
++ typedef struct _jack_net_master jack_net_master_t;
++
++ SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result);
++ SERVER_EXPORT int jack_net_master_close(jack_net_master_t* net);
++
++ SERVER_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer);
++ SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer);
++
++ // NetJack adapter API
++
++ typedef struct _jack_adapter jack_adapter_t;
++
++ SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
++ jack_nframes_t host_buffer_size,
++ jack_nframes_t host_sample_rate,
++ jack_nframes_t adapted_buffer_size,
++ jack_nframes_t adapted_sample_rate);
++ SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter);
++ SERVER_EXPORT void jack_flush_adapter(jack_adapter_t* adapter);
++
++ SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
++ SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
++
++#ifdef __cplusplus
++}
++#endif
++
++namespace Jack
++{
++
++struct JackNetExtMaster : public JackNetMasterInterface {
++
++ // Data buffers
++ float** fAudioCaptureBuffer;
++ float** fAudioPlaybackBuffer;
++
++ JackMidiBuffer** fMidiCaptureBuffer;
++ JackMidiBuffer** fMidiPlaybackBuffer;
++
++ jack_master_t fRequest;
++
++ JackNetExtMaster(const char* ip,
++ int port,
++ const char* name,
++ jack_master_t* request)
++ {
++ fRunning = true;
++ assert(strlen(ip) < 32);
++ strcpy(fMulticastIP, ip);
++ fSocket.SetPort(port);
++ fRequest.buffer_size = request->buffer_size;
++ fRequest.sample_rate = request->sample_rate;
++ fAudioCaptureBuffer = NULL;
++ fAudioPlaybackBuffer = NULL;
++ fMidiCaptureBuffer = NULL;
++ fMidiPlaybackBuffer = NULL;
++ }
++
++ virtual ~JackNetExtMaster()
++ {}
++
++ int Open(jack_slave_t* result)
++ {
++ // Init socket API (win32)
++ if (SocketAPIInit() < 0) {
++ jack_error("Can't init Socket API, exiting...");
++ return -1;
++ }
++
++ // Request socket
++ if (fSocket.NewSocket() == SOCKET_ERROR) {
++ jack_error("Can't create the network management input socket : %s", StrError(NET_ERROR_CODE));
++ return -1;
++ }
++
++ // Bind the socket to the local port
++ if (fSocket.Bind() == SOCKET_ERROR) {
++ jack_error("Can't bind the network manager socket : %s", StrError(NET_ERROR_CODE));
++ fSocket.Close();
++ return -1;
++ }
++
++ // Join multicast group
++ if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
++ jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
++ }
++
++ // Local loop
++ if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
++ jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
++ }
++
++ // Set a timeout on the multicast receive (the thread can now be cancelled)
++ if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
++ jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
++ }
++
++ // Main loop, wait for data, deal with it and wait again
++ int attempt = 0;
++ int rx_bytes = 0;
++
++ do
++ {
++ session_params_t net_params;
++ rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
++ SessionParamsNToH(&net_params, &fParams);
++
++ if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
++ jack_error("Error in receive : %s", StrError(NET_ERROR_CODE));
++ if (++attempt == 10) {
++ jack_error("Can't receive on the socket, exiting net manager" );
++ goto error;
++ }
++ }
++
++ if (rx_bytes == sizeof(session_params_t )) {
++
++ switch (GetPacketType(&fParams)) {
++
++ case SLAVE_AVAILABLE:
++ if (MasterInit() == 0) {
++ SessionParamsDisplay(&fParams);
++ fRunning = false;
++ } else {
++ jack_error("Can't init new net master...");
++ goto error;
++ }
++ jack_info("Waiting for a slave...");
++ break;
++
++ case KILL_MASTER:
++ break;
++
++ default:
++ break;
++ }
++ }
++ }
++ while (fRunning);
++
++ // Set result paramaters
++ result->audio_input = fParams.fSendAudioChannels;
++ result->audio_output = fParams.fReturnAudioChannels;
++ result->midi_input = fParams.fSendMidiChannels;
++ result->midi_output = fParams.fReturnMidiChannels;
++ result->mtu = fParams.fMtu;
++ result->latency = fParams.fNetworkLatency;
++ return 0;
++
++ error:
++ fSocket.Close();
++ return -1;
++ }
++
++ int MasterInit()
++ {
++ // Check MASTER <==> SLAVE network protocol coherency
++ if (fParams.fProtocolVersion != MASTER_PROTOCOL) {
++ jack_error("Error : slave is running with a different protocol %s", fParams.fName);
++ return -1;
++ }
++
++ // Settings
++ fSocket.GetName(fParams.fMasterNetName);
++ fParams.fID = 1;
++ fParams.fSampleEncoder = JackFloatEncoder;
++ fParams.fPeriodSize = fRequest.buffer_size;
++ fParams.fSampleRate = fRequest.sample_rate;
++
++ // Close request socket
++ fSocket.Close();
++
++ // Network slave init
++ if (!JackNetMasterInterface::Init()) {
++ return -1;
++ }
++
++ // Set global parameters
++ if (!SetParams()) {
++ return -1;
++ }
++
++ AllocPorts();
++ return 0;
++ }
++
++ int Close()
++ {
++ fSocket.Close();
++ FreePorts();
++ return 0;
++ }
++
++ void AllocPorts()
++ {
++ // Set buffers
++ if (fParams.fSendAudioChannels > 0) {
++ fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels];
++ for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
++ fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize];
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]);
++ }
++ }
++
++ if (fParams.fSendMidiChannels > 0) {
++ fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels];
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
++ fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]);
++ }
++ }
++
++ if (fParams.fReturnAudioChannels > 0) {
++ fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels];
++ for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
++ fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize];
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]);
++ }
++ }
++
++ if (fParams.fReturnMidiChannels > 0) {
++ fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels];
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
++ fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]);
++ }
++ }
++ }
++
++ void FreePorts()
++ {
++ if (fAudioPlaybackBuffer) {
++ for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++)
++ delete[] fAudioPlaybackBuffer[audio_port_index];
++ delete[] fAudioPlaybackBuffer;
++ fAudioPlaybackBuffer = NULL;
++ }
++
++ if (fMidiPlaybackBuffer) {
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++)
++ delete[] (fMidiPlaybackBuffer[midi_port_index]);
++ delete[] fMidiPlaybackBuffer;
++ fMidiPlaybackBuffer = NULL;
++ }
++
++ if (fAudioCaptureBuffer) {
++ for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++)
++ delete[] fAudioCaptureBuffer[audio_port_index];
++ delete[] fAudioCaptureBuffer;
++ fAudioCaptureBuffer = NULL;
++ }
++
++ if (fMidiCaptureBuffer) {
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++)
++ delete[] fMidiCaptureBuffer[midi_port_index];
++ delete[] fMidiCaptureBuffer;
++ fMidiCaptureBuffer = NULL;
++ }
++ }
++
++ int Read(int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer)
++ {
++ try {
++ assert(audio_input == fParams.fReturnAudioChannels);
++
++ for (int audio_port_index = 0; audio_port_index < audio_input; audio_port_index++) {
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, audio_input_buffer[audio_port_index]);
++ }
++
++ for (int midi_port_index = 0; midi_port_index < midi_input; midi_port_index++) {
++ fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_input_buffer)[midi_port_index]);
++ }
++
++ if (SyncRecv() == SOCKET_ERROR) {
++ return 0;
++ }
++
++ DecodeSyncPacket();
++ return DataRecv();
++
++ } catch (JackNetException& e) {
++ jack_error("Connection lost.");
++ return -1;
++ }
++ }
++
++ int Write(int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer)
++ {
++ try {
++ assert(audio_output == fParams.fSendAudioChannels);
++
++ for (int audio_port_index = 0; audio_port_index < audio_output; audio_port_index++) {
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, audio_output_buffer[audio_port_index]);
++ }
++
++ for (int midi_port_index = 0; midi_port_index < midi_output; midi_port_index++) {
++ fNetMidiCaptureBuffer->SetBuffer(midi_port_index, ((JackMidiBuffer**)midi_output_buffer)[midi_port_index]);
++ }
++
++ EncodeSyncPacket();
++
++ if (SyncSend() == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++
++ return DataSend();
++
++ } catch (JackNetException& e) {
++ jack_error("Connection lost.");
++ return -1;
++ }
++ }
++
++ // Transport
++ void EncodeTransportData()
++ {}
++
++ void DecodeTransportData()
++ {}
++
++};
++
++struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterface {
++
++ JackThread fThread;
++
++ JackNetSlaveProcessCallback fProcessCallback;
++ void* fProcessArg;
++
++ JackNetSlaveShutdownCallback fShutdownCallback;
++ void* fShutdownArg;
++
++ JackNetSlaveBufferSizeCallback fBufferSizeCallback;
++ void* fBufferSizeArg;
++
++ JackNetSlaveSampleRateCallback fSampleRateCallback;
++ void* fSampleRateArg;
++
++ //sample buffers
++ float** fAudioCaptureBuffer;
++ float** fAudioPlaybackBuffer;
++
++ JackMidiBuffer** fMidiCaptureBuffer;
++ JackMidiBuffer** fMidiPlaybackBuffer;
++
++ int fConnectTimeOut;
++
++ JackNetExtSlave(const char* ip,
++ int port,
++ const char* name,
++ jack_slave_t* request)
++ :fThread(this),
++ fProcessCallback(NULL),fProcessArg(NULL),
++ fShutdownCallback(NULL), fShutdownArg(NULL),
++ fBufferSizeCallback(NULL), fBufferSizeArg(NULL),
++ fSampleRateCallback(NULL), fSampleRateArg(NULL),
++ fAudioCaptureBuffer(NULL), fAudioPlaybackBuffer(NULL),
++ fMidiCaptureBuffer(NULL), fMidiPlaybackBuffer(NULL)
++ {
++ char host_name[JACK_CLIENT_NAME_SIZE];
++
++ // Request parameters
++ assert(strlen(ip) < 32);
++ strcpy(fMulticastIP, ip);
++ fParams.fMtu = request->mtu;
++ fParams.fTransportSync = 0;
++ fParams.fSendAudioChannels = request->audio_input;
++ fParams.fReturnAudioChannels = request->audio_output;
++ fParams.fSendMidiChannels = request->midi_input;
++ fParams.fReturnMidiChannels = request->midi_output;
++ fParams.fNetworkLatency = request->latency;
++ fParams.fSampleEncoder = request->encoder;
++ fParams.fKBps = request->kbps;
++ fParams.fSlaveSyncMode = 1;
++ fConnectTimeOut = request->time_out;
++
++ // Create name with hostname and client name
++ GetHostName(host_name, JACK_CLIENT_NAME_SIZE);
++ snprintf(fParams.fName, JACK_CLIENT_NAME_SIZE, "%s_%s", host_name, name);
++ fSocket.GetName(fParams.fSlaveNetName);
++
++ // Set the socket parameters
++ fSocket.SetPort(port);
++ fSocket.SetAddress(fMulticastIP, port);
++ }
++
++ virtual ~JackNetExtSlave()
++ {}
++
++ int Open(jack_master_t* result)
++ {
++ if (fParams.fNetworkLatency > NETWORK_MAX_LATENCY) {
++ jack_error("Error : network latency is limited to %d", NETWORK_MAX_LATENCY);
++ return -1;
++ }
++
++ // Init network connection
++ if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
++ jack_error("Initing network fails...");
++ return -1;
++ }
++
++ // Finish connection...
++ if (!JackNetSlaveInterface::InitRendering()) {
++ jack_error("Starting network fails...");
++ return -1;
++ }
++
++ // Then set global parameters
++ if (!SetParams()) {
++ jack_error("SetParams error...");
++ return -1;
++ }
++
++ // Set result
++ if (result != NULL) {
++ result->buffer_size = fParams.fPeriodSize;
++ result->sample_rate = fParams.fSampleRate;
++ result->audio_input = fParams.fSendAudioChannels;
++ result->audio_output = fParams.fReturnAudioChannels;
++ result->midi_input = fParams.fSendMidiChannels;
++ result->midi_output = fParams.fReturnMidiChannels;
++ strcpy(result->master_name, fParams.fMasterNetName);
++ }
++
++ AllocPorts();
++ return 0;
++ }
++
++ int Restart()
++ {
++ // If shutdown cb is set, then call it
++ if (fShutdownCallback) {
++ fShutdownCallback(fShutdownArg);
++ }
++
++ // Init network connection
++ if (!JackNetSlaveInterface::InitConnection(fConnectTimeOut)) {
++ jack_error("Initing network fails...");
++ return -1;
++ }
++
++ // Finish connection...
++ if (!JackNetSlaveInterface::InitRendering()) {
++ jack_error("Starting network fails...");
++ return -1;
++ }
++
++ // Then set global parameters
++ if (!SetParams()) {
++ jack_error("SetParams error...");
++ return -1;
++ }
++
++ // We need to notify possibly new buffer size and sample rate (see Execute)
++ if (fBufferSizeCallback) {
++ fBufferSizeCallback(fParams.fPeriodSize, fBufferSizeArg);
++ }
++
++ if (fSampleRateCallback) {
++ fSampleRateCallback(fParams.fSampleRate, fSampleRateArg);
++ }
++
++ AllocPorts();
++ return 0;
++ }
++
++ int Close()
++ {
++ fSocket.Close();
++ FreePorts();
++ return 0;
++ }
++
++ void AllocPorts()
++ {
++ // Set buffers
++ fAudioCaptureBuffer = new float*[fParams.fSendAudioChannels];
++ for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
++ fAudioCaptureBuffer[audio_port_index] = new float[fParams.fPeriodSize];
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, fAudioCaptureBuffer[audio_port_index]);
++ }
++
++ fMidiCaptureBuffer = new JackMidiBuffer*[fParams.fSendMidiChannels];
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ fMidiCaptureBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
++ fNetMidiCaptureBuffer->SetBuffer(midi_port_index, fMidiCaptureBuffer[midi_port_index]);
++ }
++
++ fAudioPlaybackBuffer = new float*[fParams.fReturnAudioChannels];
++ for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
++ fAudioPlaybackBuffer[audio_port_index] = new float[fParams.fPeriodSize];
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, fAudioPlaybackBuffer[audio_port_index]);
++ }
++
++ fMidiPlaybackBuffer = new JackMidiBuffer*[fParams.fReturnMidiChannels];
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ fMidiPlaybackBuffer[midi_port_index] = (JackMidiBuffer*)new float[fParams.fPeriodSize];
++ fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, fMidiPlaybackBuffer[midi_port_index]);
++ }
++ }
++
++ void FreePorts()
++ {
++ if (fAudioCaptureBuffer) {
++ for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++)
++ delete[] fAudioCaptureBuffer[audio_port_index];
++ delete[] fAudioCaptureBuffer;
++ fAudioCaptureBuffer = NULL;
++ }
++
++ if (fMidiCaptureBuffer) {
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++)
++ delete[] (fMidiCaptureBuffer[midi_port_index]);
++ delete[] fMidiCaptureBuffer;
++ fMidiCaptureBuffer = NULL;
++ }
++
++ if (fAudioPlaybackBuffer) {
++ for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++)
++ delete[] fAudioPlaybackBuffer[audio_port_index];
++ delete[] fAudioPlaybackBuffer;
++ fAudioPlaybackBuffer = NULL;
++ }
++
++ if (fMidiPlaybackBuffer) {
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++)
++ delete[] fMidiPlaybackBuffer[midi_port_index];
++ delete[] fMidiPlaybackBuffer;
++ fMidiPlaybackBuffer = NULL;
++ }
++ }
++
++ // Transport
++ void EncodeTransportData()
++ {}
++
++ void DecodeTransportData()
++ {}
++
++ bool Init()
++ {
++ // Will do "something" on OSX only...
++ UInt64 period, constraint;
++ period = constraint = UInt64(1000000000.f * (float(fParams.fPeriodSize) / float(fParams.fSampleRate)));
++ UInt64 computation = JackTools::ComputationMicroSec(fParams.fPeriodSize) * 1000;
++ fThread.SetParams(period, computation, constraint);
++
++ return (fThread.AcquireSelfRealTime(80) == 0); // TODO: get a value from the server
++ }
++
++ bool Execute()
++ {
++ try {
++ // Keep running even in case of error
++ while (fThread.GetStatus() == JackThread::kRunning) {
++ if (Process() == SOCKET_ERROR) {
++ return false;
++ }
++ }
++ return false;
++ } catch (JackNetException& e) {
++
++ // Otherwise just restart...
++ e.PrintMessage();
++ fThread.DropRealTime();
++ fThread.SetStatus(JackThread::kIniting);
++ FreePorts();
++ if (Restart() == 0 && Init()) {
++ fThread.SetStatus(JackThread::kRunning);
++ return true;
++ } else {
++ return false;
++ }
++ }
++ }
++
++ int Read()
++ {
++ //receive sync (launch the cycle)
++ if (SyncRecv() == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++
++ DecodeSyncPacket();
++ return DataRecv();
++ }
++
++ int Write()
++ {
++ EncodeSyncPacket();
++
++ if (SyncSend() == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++
++ return DataSend();
++ }
++
++ int Process()
++ {
++ // Read data from the network, throw JackNetException in case of network error...
++ if (Read() == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++
++ fProcessCallback(fParams.fPeriodSize,
++ fParams.fSendAudioChannels,
++ fAudioCaptureBuffer,
++ fParams.fSendMidiChannels,
++ (void**)fMidiCaptureBuffer,
++ fParams.fReturnAudioChannels,
++ fAudioPlaybackBuffer,
++ fParams.fReturnMidiChannels,
++ (void**)fMidiPlaybackBuffer,
++ fProcessArg);
++
++ // Then write data to network, throw JackNetException in case of network error...
++ if (Write() == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++
++ return 0;
++ }
++
++ int Start()
++ {
++ return (fProcessCallback == 0) ? -1 : fThread.StartSync();
++ }
++
++ int Stop()
++ {
++ return (fProcessCallback == 0) ? -1 : fThread.Kill();
++ }
++
++ // Callback
++ int SetProcessCallback(JackNetSlaveProcessCallback net_callback, void *arg)
++ {
++ if (fThread.GetStatus() == JackThread::kRunning) {
++ return -1;
++ } else {
++ fProcessCallback = net_callback;
++ fProcessArg = arg;
++ return 0;
++ }
++ }
++
++ int SetShutdownCallback(JackNetSlaveShutdownCallback shutdown_callback, void *arg)
++ {
++ if (fThread.GetStatus() == JackThread::kRunning) {
++ return -1;
++ } else {
++ fShutdownCallback = shutdown_callback;
++ fShutdownArg = arg;
++ return 0;
++ }
++ }
++
++ int SetBufferSizeCallback(JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
++ {
++ if (fThread.GetStatus() == JackThread::kRunning) {
++ return -1;
++ } else {
++ fBufferSizeCallback = bufsize_callback;
++ fBufferSizeArg = arg;
++ return 0;
++ }
++ }
++
++ int SetSampleRateCallback(JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
++ {
++ if (fThread.GetStatus() == JackThread::kRunning) {
++ return -1;
++ } else {
++ fSampleRateCallback = samplerate_callback;
++ fSampleRateArg = arg;
++ return 0;
++ }
++ }
++
++};
++
++struct JackNetAdapter : public JackAudioAdapterInterface {
++
++ JackNetAdapter(int input, int output,
++ jack_nframes_t host_buffer_size,
++ jack_nframes_t host_sample_rate,
++ jack_nframes_t adapted_buffer_size,
++ jack_nframes_t adapted_sample_rate)
++ :JackAudioAdapterInterface(host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate)
++ {
++ fCaptureChannels = input;
++ fPlaybackChannels = output;
++ Create();
++ }
++
++ void Create()
++ {
++ //ringbuffers
++
++ if (fCaptureChannels > 0) {
++ fCaptureRingBuffer = new JackResampler*[fCaptureChannels];
++ }
++ if (fPlaybackChannels > 0) {
++ fPlaybackRingBuffer = new JackResampler*[fPlaybackChannels];
++ }
++
++ if (fAdaptative) {
++ AdaptRingBufferSize();
++ jack_info("Ringbuffer automatic adaptative mode size = %d frames", fRingbufferCurSize);
++ } else {
++ if (fRingbufferCurSize > DEFAULT_RB_SIZE) {
++ fRingbufferCurSize = DEFAULT_RB_SIZE;
++ }
++ jack_info("Fixed ringbuffer size = %d frames", fRingbufferCurSize);
++ }
++
++ for (int i = 0; i < fCaptureChannels; i++ ) {
++ fCaptureRingBuffer[i] = new JackResampler();
++ fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
++ }
++ for (int i = 0; i < fPlaybackChannels; i++ ) {
++ fPlaybackRingBuffer[i] = new JackResampler();
++ fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
++ }
++
++ if (fCaptureChannels > 0) {
++ jack_log("ReadSpace = %ld", fCaptureRingBuffer[0]->ReadSpace());
++ }
++ if (fPlaybackChannels > 0) {
++ jack_log("WriteSpace = %ld", fPlaybackRingBuffer[0]->WriteSpace());
++ }
++ }
++
++ virtual ~JackNetAdapter()
++ {
++ Destroy();
++ }
++
++ void Flush()
++ {
++ for (int i = 0; i < fCaptureChannels; i++ ) {
++ fCaptureRingBuffer[i]->Reset(fRingbufferCurSize);
++ }
++ for (int i = 0; i < fPlaybackChannels; i++ ) {
++ fPlaybackRingBuffer[i]->Reset(fRingbufferCurSize);
++ }
++ }
++
++};
++
++
++} // end of namespace
++
++using namespace Jack;
++
++SERVER_EXPORT jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result)
++{
++ JackNetExtSlave* slave = new JackNetExtSlave(ip, port, name, request);
++ if (slave->Open(result) == 0) {
++ return (jack_net_slave_t*)slave;
++ } else {
++ delete slave;
++ return NULL;
++ }
++}
++
++SERVER_EXPORT int jack_net_slave_close(jack_net_slave_t* net)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ slave->Close();
++ delete slave;
++ return 0;
++}
++
++SERVER_EXPORT int jack_set_net_slave_process_callback(jack_net_slave_t* net, JackNetSlaveProcessCallback net_callback, void *arg)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ return slave->SetProcessCallback(net_callback, arg);
++}
++
++SERVER_EXPORT int jack_net_slave_activate(jack_net_slave_t* net)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ return slave->Start();
++}
++
++SERVER_EXPORT int jack_net_slave_deactivate(jack_net_slave_t* net)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ return slave->Stop();
++}
++
++SERVER_EXPORT int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ return slave->SetBufferSizeCallback(bufsize_callback, arg);
++}
++
++SERVER_EXPORT int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ return slave->SetSampleRateCallback(samplerate_callback, arg);
++}
++
++SERVER_EXPORT int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg)
++{
++ JackNetExtSlave* slave = (JackNetExtSlave*)net;
++ return slave->SetShutdownCallback(shutdown_callback, arg);
++}
++
++// Master API
++
++SERVER_EXPORT jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result)
++{
++ JackNetExtMaster* master = new JackNetExtMaster(ip, port, name, request);
++ if (master->Open(result) == 0) {
++ return (jack_net_master_t*)master;
++ } else {
++ delete master;
++ return NULL;
++ }
++}
++
++SERVER_EXPORT int jack_net_master_close(jack_net_master_t* net)
++{
++ JackNetExtMaster* master = (JackNetExtMaster*)net;
++ master->Close();
++ delete master;
++ return 0;
++}
++SERVER_EXPORT int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer)
++{
++ JackNetExtMaster* master = (JackNetExtMaster*)net;
++ return master->Read(audio_input, audio_input_buffer, midi_input, midi_input_buffer);
++}
++
++SERVER_EXPORT int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer)
++{
++ JackNetExtMaster* master = (JackNetExtMaster*)net;
++ return master->Write(audio_output, audio_output_buffer, midi_output, midi_output_buffer);
++}
++
++// Adapter API
++
++SERVER_EXPORT jack_adapter_t* jack_create_adapter(int input, int output,
++ jack_nframes_t host_buffer_size,
++ jack_nframes_t host_sample_rate,
++ jack_nframes_t adapted_buffer_size,
++ jack_nframes_t adapted_sample_rate)
++{
++ try {
++ return (jack_adapter_t*)new JackNetAdapter(input, output, host_buffer_size, host_sample_rate, adapted_buffer_size, adapted_sample_rate);
++ } catch (...) {
++ return NULL;
++ }
++}
++
++SERVER_EXPORT int jack_destroy_adapter(jack_adapter_t* adapter)
++{
++ delete((JackNetAdapter*)adapter);
++ return 0;
++}
++
++SERVER_EXPORT void jack_flush_adapter(jack_adapter_t* adapter)
++{
++ JackNetAdapter* slave = (JackNetAdapter*)adapter;
++ slave->Flush();
++}
++
++SERVER_EXPORT int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
++{
++ JackNetAdapter* slave = (JackNetAdapter*)adapter;
++ return slave->PushAndPull(input, output, frames);
++}
++
++SERVER_EXPORT int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames)
++{
++ JackNetAdapter* slave = (JackNetAdapter*)adapter;
++ return slave->PullAndPush(input, output, frames);
++}
++
++
++//#ifdef MY_TARGET_OS_IPHONE
++#if 1
++
++static void jack_format_and_log(int level, const char *prefix, const char *fmt, va_list ap)
++{
++ char buffer[300];
++ size_t len;
++
++ if (prefix != NULL) {
++ len = strlen(prefix);
++ memcpy(buffer, prefix, len);
++ } else {
++ len = 0;
++ }
++
++ vsnprintf(buffer + len, sizeof(buffer) - len, fmt, ap);
++ printf("%s", buffer);
++ printf("\n");
++}
++
++SERVER_EXPORT void jack_error(const char *fmt, ...)
++{
++ va_list ap;
++ va_start(ap, fmt);
++ jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
++ va_end(ap);
++}
++
++SERVER_EXPORT void jack_info(const char *fmt, ...)
++{
++ va_list ap;
++ va_start(ap, fmt);
++ jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
++ va_end(ap);
++}
++
++SERVER_EXPORT void jack_log(const char *fmt, ...)
++{
++ va_list ap;
++ va_start(ap, fmt);
++ jack_format_and_log(LOG_LEVEL_INFO, "Jack: ", fmt, ap);
++ va_end(ap);
++}
++
++#else
++
++// Empty code for now..
++
++SERVER_EXPORT void jack_error(const char *fmt, ...)
++{}
++
++SERVER_EXPORT void jack_info(const char *fmt, ...)
++{}
++
++SERVER_EXPORT void jack_log(const char *fmt, ...)
++{}
++
++#endif
++
+--- a/common/JackNetDriver.cpp
++++ b/common/JackNetDriver.cpp
+@@ -1,6 +1,5 @@
+ /*
+-Copyright (C) 2001 Paul Davis
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -19,32 +18,40 @@
+
+ #include "JackNetDriver.h"
+ #include "JackEngineControl.h"
++#include "JackLockedEngine.h"
+ #include "JackGraphManager.h"
+ #include "JackWaitThreadedDriver.h"
+
+-
+ using namespace std;
+
+ namespace Jack
+ {
+- JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
+- const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
+- char* net_name, uint transport_sync, char network_mode )
+- : JackAudioDriver ( name, alias, engine, table ), JackNetSlaveInterface ( ip, port )
++ JackNetDriver::JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
++ const char* ip, int udp_port, int mtu, int midi_input_ports, int midi_output_ports,
++ char* net_name, uint transport_sync, int network_latency, int celt_encoding)
++ : JackWaiterDriver(name, alias, engine, table), JackNetSlaveInterface(ip, udp_port)
+ {
+- jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port );
++ jack_log("JackNetDriver::JackNetDriver ip %s, port %d", ip, udp_port);
+
+ // Use the hostname if no name parameter was given
+- if ( strcmp ( net_name, "" ) == 0 )
+- GetHostName ( net_name, JACK_CLIENT_NAME_SIZE );
++ if (strcmp(net_name, "") == 0) {
++ GetHostName(net_name, JACK_CLIENT_NAME_SIZE);
++ }
+
+ fParams.fMtu = mtu;
+ fParams.fSendMidiChannels = midi_input_ports;
+ fParams.fReturnMidiChannels = midi_output_ports;
+- strcpy ( fParams.fName, net_name );
+- fSocket.GetName ( fParams.fSlaveNetName );
++ if (celt_encoding > 0) {
++ fParams.fSampleEncoder = JackCeltEncoder;
++ fParams.fKBps = celt_encoding;
++ } else {
++ fParams.fSampleEncoder = JackFloatEncoder;
++ //fParams.fSampleEncoder = JackIntEncoder;
++ }
++ strcpy(fParams.fName, net_name);
++ fSocket.GetName(fParams.fSlaveNetName);
+ fParams.fTransportSync = transport_sync;
+- fParams.fNetworkMode = network_mode;
++ fParams.fNetworkLatency = network_latency;
+ fSendTransportData.fState = -1;
+ fReturnTransportData.fState = -1;
+ fLastTransportState = -1;
+@@ -67,42 +74,16 @@
+ }
+
+ //open, close, attach and detach------------------------------------------------------
+- int JackNetDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, 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 )
+- {
+- if ( JackAudioDriver::Open ( buffer_size,
+- samplerate,
+- capturing,
+- playing,
+- inchannels,
+- outchannels,
+- monitor,
+- capture_driver_name,
+- playback_driver_name,
+- capture_latency,
+- playback_latency ) == 0 )
+- {
+- fEngineControl->fPeriod = 0;
+- fEngineControl->fComputation = 500 * 1000;
+- fEngineControl->fConstraint = 500 * 1000;
+- return 0;
+- }
+- else
+- {
+- return -1;
+- }
+- }
+
+ int JackNetDriver::Close()
+ {
+ #ifdef JACK_MONITOR
+- if ( fNetTimeMon )
++ if (fNetTimeMon) {
+ fNetTimeMon->Save();
++ }
+ #endif
+ FreeAll();
+- return JackDriver::Close();
++ return JackWaiterDriver::Close();
+ }
+
+ // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init)
+@@ -124,92 +105,99 @@
+
+ bool JackNetDriver::Initialize()
+ {
+- jack_log("JackNetDriver::Initialize()");
++ jack_log("JackNetDriver::Initialize");
++ SaveConnections();
++ FreePorts();
+
+- //new loading, but existing socket, restart the driver
++ // New loading, but existing socket, restart the driver
+ if (fSocket.IsSocket()) {
+ jack_info("Restarting driver...");
+ FreeAll();
+ }
+
+- //set the parameters to send
++ // Set the parameters to send
+ fParams.fSendAudioChannels = fCaptureChannels;
+ fParams.fReturnAudioChannels = fPlaybackChannels;
+ fParams.fSlaveSyncMode = fEngineControl->fSyncMode;
+
+- //display some additional infos
+- jack_info ( "NetDriver started in %s mode %s Master's transport sync.",
+- ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
++ // Display some additional infos
++ jack_info("NetDriver started in %s mode %s Master's transport sync.",
++ (fParams.fSlaveSyncMode) ? "sync" : "async", (fParams.fTransportSync) ? "with" : "without");
++
++ // Init network
++ if (!JackNetSlaveInterface::Init()) {
++ jack_error("Starting network fails...");
++ return false;
++ }
+
+- //init network
+- if ( !JackNetSlaveInterface::Init() )
++ // Set global parameters
++ if (!SetParams()) {
++ jack_error("SetParams error...");
+ return false;
++ }
+
+- //set global parameters
+- SetParams();
++ // If -1 at connection time, in/out channels count is sent by the master
++ fCaptureChannels = fParams.fSendAudioChannels;
++ fPlaybackChannels = fParams.fReturnAudioChannels;
+
+- //allocate midi ports lists
++ // Allocate midi ports lists
+ fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels];
+ fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels];
+- assert ( fMidiCapturePortList );
+- assert ( fMidiPlaybackPortList );
+
+- //register jack ports
+- if ( AllocPorts() != 0 )
+- {
+- jack_error ( "Can't allocate ports." );
++ assert(fMidiCapturePortList);
++ assert(fMidiPlaybackPortList);
++
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ fMidiCapturePortList[midi_port_index] = 0;
++ }
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ fMidiPlaybackPortList[midi_port_index] = 0;
++ }
++
++ // Register jack ports
++ if (AllocPorts() != 0) {
++ jack_error("Can't allocate ports.");
+ return false;
+ }
+
+- //init done, display parameters
+- SessionParamsDisplay ( &fParams );
++ // Init done, display parameters
++ SessionParamsDisplay(&fParams);
+
+- //monitor
++ // Monitor
+ #ifdef JACK_MONITOR
+ string plot_name;
+- //NetTimeMon
+- plot_name = string ( fParams.fName );
+- plot_name += string ( "_slave" );
+- plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" );
+- switch ( fParams.fNetworkMode )
+- {
+- case 's' :
+- plot_name += string ( "_slow" );
+- break;
+-
+- case 'n' :
+- plot_name += string ( "_normal" );
+- break;
+-
+- case 'f' :
+- plot_name += string ( "_fast" );
+- break;
+- }
+- fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 5, plot_name );
++ // NetTimeMon
++ plot_name = string(fParams.fName);
++ plot_name += string("_slave");
++ plot_name += (fEngineControl->fSyncMode) ? string("_sync") : string("_async");
++ plot_name += string("_latency");
++ fNetTimeMon = new JackGnuPlotMonitor<float>(128, 5, plot_name);
+ string net_time_mon_fields[] =
+ {
+- string ( "sync decoded" ),
+- string ( "end of read" ),
+- string ( "start of write" ),
+- string ( "sync send" ),
+- string ( "end of write" )
++ string("sync decoded"),
++ string("end of read"),
++ string("start of write"),
++ string("sync send"),
++ string("end of write")
+ };
+ string net_time_mon_options[] =
+ {
+- string ( "set xlabel \"audio cycles\"" ),
+- string ( "set ylabel \"% of audio cycle\"" )
++ string("set xlabel \"audio cycles\""),
++ string("set ylabel \"% of audio cycle\"")
+ };
+- fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 5 );
++ fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 5);
+ #endif
+- //driver parametering
+- JackAudioDriver::SetBufferSize ( fParams.fPeriodSize );
+- JackAudioDriver::SetSampleRate ( fParams.fSampleRate );
++ // Driver parametering
++ JackTimedDriver::SetBufferSize(fParams.fPeriodSize);
++ JackTimedDriver::SetSampleRate(fParams.fSampleRate);
++
++ JackDriver::NotifyBufferSize(fParams.fPeriodSize);
++ JackDriver::NotifySampleRate(fParams.fSampleRate);
+
+- JackDriver::NotifyBufferSize ( fParams.fPeriodSize );
+- JackDriver::NotifySampleRate ( fParams.fSampleRate );
++ // Transport engine parametering
++ fEngineControl->fTransport.SetNetworkSync(fParams.fTransportSync);
+
+- //transport engine parametering
+- fEngineControl->fTransport.SetNetworkSync ( fParams.fTransportSync );
++ RestoreConnections();
+ return true;
+ }
+
+@@ -244,115 +232,95 @@
+ //jack ports and buffers--------------------------------------------------------------
+ int JackNetDriver::AllocPorts()
+ {
+- jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate );
++ jack_log("JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
++
++ /*
++ fNetAudioCaptureBuffer fNetAudioPlaybackBuffer
++ fSendAudioChannels fReturnAudioChannels
++
++ fCapturePortList fPlaybackPortList
++ fCaptureChannels ==> SLAVE ==> fPlaybackChannels
++ "capture_" "playback_"
++ */
+
+ JackPort* port;
+- jack_port_id_t port_id;
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- unsigned long port_flags;
++ jack_port_id_t port_index;
++ char name[REAL_JACK_PORT_NAME_SIZE];
++ char alias[REAL_JACK_PORT_NAME_SIZE];
+ int audio_port_index;
+- uint midi_port_index;
++ int midi_port_index;
+ jack_latency_range_t range;
+
+ //audio
+- port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
+- for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
+- {
+- snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1 );
+- snprintf ( name, sizeof ( name ) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1 );
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
+- static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", name );
++ for (audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) {
++ snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1);
++ snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, audio_port_index + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
++ CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+- port = fGraphManager->GetPort ( port_id );
+- port->SetAlias ( alias );
++
+ //port latency
++ port = fGraphManager->GetPort(port_index);
++ port->SetAlias(alias);
+ range.min = range.max = fEngineControl->fBufferSize;
+ port->SetLatencyRange(JackCaptureLatency, &range);
+- fCapturePortList[audio_port_index] = port_id;
+- jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
++ fCapturePortList[audio_port_index] = port_index;
++ jack_log("JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency());
+ }
+- port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
+- for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
+- {
+- snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1 );
+- snprintf ( name, sizeof ( name ) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1 );
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
+- static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", name );
++
++ for (audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
++ snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1);
++ snprintf(name, sizeof(name), "%s:playback_%d",fClientControl.fName, audio_port_index + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
++ PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+- port = fGraphManager->GetPort ( port_id );
+- port->SetAlias ( alias );
++
+ //port latency
+- switch ( fParams.fNetworkMode )
+- {
+- case 'f' :
+- range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
+- break;
+- case 'n' :
+- range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
+- break;
+- case 's' :
+- range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
+- break;
+- }
++ port = fGraphManager->GetPort(port_index);
++ port->SetAlias(alias);
++ range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
+ port->SetLatencyRange(JackPlaybackLatency, &range);
+- fPlaybackPortList[audio_port_index] = port_id;
+- jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
++ fPlaybackPortList[audio_port_index] = port_index;
++ jack_log("JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_index, port->GetLatency());
+ }
++
+ //midi
+- port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
+- for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
+- {
+- snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1 );
+- snprintf ( name, sizeof ( name ) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1 );
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
+- static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", name );
++ for (midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1);
++ snprintf(name, sizeof (name), "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
++ CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+- port = fGraphManager->GetPort ( port_id );
++
+ //port latency
++ port = fGraphManager->GetPort(port_index);
+ range.min = range.max = fEngineControl->fBufferSize;
+ port->SetLatencyRange(JackCaptureLatency, &range);
+- fMidiCapturePortList[midi_port_index] = port_id;
+- jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
++ fMidiCapturePortList[midi_port_index] = port_index;
++ jack_log("JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency());
+ }
+
+- port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
+- for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
+- {
+- snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1 );
+- snprintf ( name, sizeof ( name ) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1 );
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
+- static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", name );
++ for (midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1);
++ snprintf(name, sizeof(name), "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
++ PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+- port = fGraphManager->GetPort ( port_id );
++
+ //port latency
+- switch ( fParams.fNetworkMode )
+- {
+- case 'f' :
+- range.min = range.max = (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize;
+- break;
+- case 'n' :
+- range.min = range.max = (fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
+- break;
+- case 's' :
+- range.min = range.max = (2 * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
+- break;
+- }
++ port = fGraphManager->GetPort(port_index);
++ range.min = range.max = (fParams.fNetworkLatency * fEngineControl->fBufferSize + (fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize);
+ port->SetLatencyRange(JackPlaybackLatency, &range);
+- fMidiPlaybackPortList[midi_port_index] = port_id;
+- jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
++ fMidiPlaybackPortList[midi_port_index] = port_index;
++ jack_log("JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_index, port->GetLatency());
+ }
+
+ return 0;
+@@ -360,33 +328,72 @@
+
+ int JackNetDriver::FreePorts()
+ {
+- jack_log ( "JackNetDriver::FreePorts" );
++ jack_log("JackNetDriver::FreePorts");
+
+- int audio_port_index;
+- uint midi_port_index;
+- for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
+- if (fCapturePortList[audio_port_index] > 0)
+- fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index] );
+- for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
+- if (fPlaybackPortList[audio_port_index] > 0)
+- fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index] );
+- for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
+- if (fMidiCapturePortList[midi_port_index] > 0)
+- fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index] );
+- for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
+- if (fMidiPlaybackPortList[midi_port_index] > 0)
+- fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index] );
++ for (int audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) {
++ if (fCapturePortList[audio_port_index] > 0) {
++ fEngine->PortUnRegister(fClientControl.fRefNum, fCapturePortList[audio_port_index]);
++ fCapturePortList[audio_port_index] = 0;
++ }
++ }
++
++ for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
++ if (fPlaybackPortList[audio_port_index] > 0) {
++ fEngine->PortUnRegister(fClientControl.fRefNum, fPlaybackPortList[audio_port_index]);
++ fPlaybackPortList[audio_port_index] = 0;
++ }
++ }
++
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ if (fMidiCapturePortList && fMidiCapturePortList[midi_port_index] > 0) {
++ fGraphManager->ReleasePort(fClientControl.fRefNum, fMidiCapturePortList[midi_port_index]);
++ fMidiCapturePortList[midi_port_index] = 0;
++ }
++ }
++
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ if (fMidiPlaybackPortList && fMidiPlaybackPortList[midi_port_index] > 0) {
++ fEngine->PortUnRegister(fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index]);
++ fMidiPlaybackPortList[midi_port_index] = 0;
++ }
++ }
+ return 0;
+ }
+
+- JackMidiBuffer* JackNetDriver::GetMidiInputBuffer ( int port_index )
++ void JackNetDriver::SaveConnections()
+ {
+- return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiCapturePortList[port_index], fEngineControl->fBufferSize ) );
++ const char** connections;
++ fConnections.clear();
++
++ JackTimedDriver::SaveConnections();
++
++ for (int i = 0; i < fParams.fSendMidiChannels; ++i) {
++ if (fCapturePortList[i] && (connections = fGraphManager->GetConnections(fMidiCapturePortList[i])) != 0) {
++ for (int j = 0; connections[j]; j++) {
++ fConnections.push_back(make_pair(fGraphManager->GetPort(fMidiCapturePortList[i])->GetName(), connections[j]));
++ }
++ free(connections);
++ }
++ }
++
++ for (int i = 0; i < fParams.fReturnMidiChannels; ++i) {
++ if (fPlaybackPortList[i] && (connections = fGraphManager->GetConnections(fMidiPlaybackPortList[i])) != 0) {
++ for (int j = 0; connections[j]; j++) {
++ fConnections.push_back(make_pair(connections[j], fGraphManager->GetPort(fMidiPlaybackPortList[i])->GetName()));
++ }
++ free(connections);
++ }
++ }
+ }
+
+- JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer ( int port_index )
++ JackMidiBuffer* JackNetDriver::GetMidiInputBuffer(int port_index)
+ {
+- return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
++ return static_cast<JackMidiBuffer*>(fGraphManager->GetBuffer(fMidiCapturePortList[port_index], fEngineControl->fBufferSize));
++ }
++
++ JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer(int port_index)
++ {
++ return static_cast<JackMidiBuffer*>(fGraphManager->GetBuffer(fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize));
+ }
+
+ //transport---------------------------------------------------------------------------
+@@ -398,35 +405,34 @@
+ // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master
+ int refnum;
+ bool conditional;
+- if ( fSendTransportData.fTimebaseMaster == TIMEBASEMASTER )
+- {
+- fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
+- if ( refnum != -1 )
+- fEngineControl->fTransport.ResetTimebase ( refnum );
+- jack_info ( "The NetMaster is now the new timebase master." );
++ if (fSendTransportData.fTimebaseMaster == TIMEBASEMASTER) {
++ fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional);
++ if (refnum != -1) {
++ fEngineControl->fTransport.ResetTimebase(refnum);
++ }
++ jack_info("The NetMaster is now the new timebase master.");
+ }
+
+ //is there a transport state change to handle ?
+- if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) )
+- {
++ if (fSendTransportData.fNewState &&(fSendTransportData.fState != fEngineControl->fTransport.GetState())) {
+
+- switch ( fSendTransportData.fState )
++ switch (fSendTransportData.fState)
+ {
+ case JackTransportStopped :
+- fEngineControl->fTransport.SetCommand ( TransportCommandStop );
+- jack_info ( "Master stops transport." );
++ fEngineControl->fTransport.SetCommand(TransportCommandStop);
++ jack_info("Master stops transport.");
+ break;
+
+ case JackTransportStarting :
+- fEngineControl->fTransport.RequestNewPos ( &fSendTransportData.fPosition );
+- fEngineControl->fTransport.SetCommand ( TransportCommandStart );
+- jack_info ( "Master starts transport frame = %d", fSendTransportData.fPosition.frame);
++ fEngineControl->fTransport.RequestNewPos(&fSendTransportData.fPosition);
++ fEngineControl->fTransport.SetCommand(TransportCommandStart);
++ jack_info("Master starts transport frame = %d", fSendTransportData.fPosition.frame);
+ break;
+
+ case JackTransportRolling :
+- //fEngineControl->fTransport.SetCommand ( TransportCommandStart );
+- fEngineControl->fTransport.SetState ( JackTransportRolling );
+- jack_info ( "Master is rolling." );
++ //fEngineControl->fTransport.SetCommand(TransportCommandStart);
++ fEngineControl->fTransport.SetState(JackTransportRolling);
++ jack_info("Master is rolling.");
+ break;
+ }
+ }
+@@ -434,62 +440,67 @@
+
+ void JackNetDriver::EncodeTransportData()
+ {
+- /* Desactivated
+ //is there a timebase master change ?
+ int refnum;
+ bool conditional;
+- fEngineControl->fTransport.GetTimebaseMaster ( refnum, conditional );
+- if ( refnum != fLastTimebaseMaster )
+- {
++ fEngineControl->fTransport.GetTimebaseMaster(refnum, conditional);
++ if (refnum != fLastTimebaseMaster) {
+ //timebase master has released its function
+- if ( refnum == -1 )
+- {
++ if (refnum == -1) {
+ fReturnTransportData.fTimebaseMaster = RELEASE_TIMEBASEMASTER;
+- jack_info ( "Sending a timebase master release request." );
+- }
+- //there is a new timebase master
+- else
+- {
+- fReturnTransportData.fTimebaseMaster = ( conditional ) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
+- jack_info ( "Sending a %s timebase master request.", ( conditional ) ? "conditional" : "non-conditional" );
++ jack_info("Sending a timebase master release request.");
++ } else {
++ //there is a new timebase master
++ fReturnTransportData.fTimebaseMaster = (conditional) ? CONDITIONAL_TIMEBASEMASTER : TIMEBASEMASTER;
++ jack_info("Sending a %s timebase master request.", (conditional) ? "conditional" : "non-conditional");
+ }
+ fLastTimebaseMaster = refnum;
+- }
+- else
++ } else {
+ fReturnTransportData.fTimebaseMaster = NO_CHANGE;
+- */
++ }
+
+ //update transport state and position
+- fReturnTransportData.fState = fEngineControl->fTransport.Query ( &fReturnTransportData.fPosition );
++ fReturnTransportData.fState = fEngineControl->fTransport.Query(&fReturnTransportData.fPosition);
+
+ //is it a new state (that the master need to know...) ?
+- fReturnTransportData.fNewState = (( fReturnTransportData.fState == JackTransportNetStarting) &&
+- ( fReturnTransportData.fState != fLastTransportState ) &&
+- ( fReturnTransportData.fState != fSendTransportData.fState ) );
+- if ( fReturnTransportData.fNewState )
+- jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) );
++ fReturnTransportData.fNewState = ((fReturnTransportData.fState == JackTransportNetStarting) &&
++ (fReturnTransportData.fState != fLastTransportState) &&
++ (fReturnTransportData.fState != fSendTransportData.fState));
++ if (fReturnTransportData.fNewState) {
++ jack_info("Sending '%s'.", GetTransportState(fReturnTransportData.fState));
++ }
+ fLastTransportState = fReturnTransportData.fState;
+ }
+
+ //driver processes--------------------------------------------------------------------
++
+ int JackNetDriver::Read()
+ {
+- uint midi_port_index;
+- uint audio_port_index;
+-
+ //buffers
+- for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
+- fNetMidiCaptureBuffer->SetBuffer ( midi_port_index, GetMidiInputBuffer ( midi_port_index ) );
+- for ( audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++ )
+- fNetAudioCaptureBuffer->SetBuffer ( audio_port_index, GetInputBuffer ( audio_port_index ) );
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ fNetMidiCaptureBuffer->SetBuffer(midi_port_index, GetMidiInputBuffer(midi_port_index));
++ }
++
++ for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
++ #ifdef OPTIMIZED_PROTOCOL
++ if (fGraphManager->GetConnectionsNum(fCapturePortList[audio_port_index]) > 0) {
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index));
++ } else {
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL);
++ }
++ #else
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, GetInputBuffer(audio_port_index));
++ #endif
++ }
+
+ #ifdef JACK_MONITOR
+ fNetTimeMon->New();
+ #endif
+
+ //receive sync (launch the cycle)
+- if ( SyncRecv() == SOCKET_ERROR )
+- return 0;
++ if (SyncRecv() == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
+
+ #ifdef JACK_MONITOR
+ // For timing
+@@ -501,17 +512,22 @@
+ DecodeSyncPacket();
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( 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 )
++ int res = DataRecv();
++ if (res == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ } else if (res == NET_PACKET_ERROR) {
++ jack_time_t cur_time = GetMicroSeconds();
++ NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
++ }
+
+ //take the time at the beginning of the cycle
+ JackDriver::CycleTakeBeginTime();
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
++ fNetTimeMon->Add((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f);
+ #endif
+
+ return 0;
+@@ -519,36 +535,51 @@
+
+ int JackNetDriver::Write()
+ {
+- uint midi_port_index;
+- int audio_port_index;
+-
+ //buffers
+- for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
+- fNetMidiPlaybackBuffer->SetBuffer ( midi_port_index, GetMidiOutputBuffer ( midi_port_index ) );
+- for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
+- fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) );
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ fNetMidiPlaybackBuffer->SetBuffer(midi_port_index, GetMidiOutputBuffer(midi_port_index));
++ }
++
++ for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) {
++ #ifdef OPTIMIZED_PROTOCOL
++ // Port is connected on other side...
++ if (fNetAudioPlaybackBuffer->GetConnected(audio_port_index)) {
++ if (fGraphManager->GetConnectionsNum(fPlaybackPortList[audio_port_index]) > 0) {
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index));
++ } else {
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL);
++ }
++ } else {
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, NULL);
++ }
++ #else
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, GetOutputBuffer(audio_port_index));
++ #endif
++ }
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
++ fNetTimeMon->AddLast((float(GetMicroSeconds() - fRcvSyncUst) / float(fEngineControl->fPeriodUsecs) * 100.f);
+ #endif
+
+ //sync
+ EncodeSyncPacket();
+
+ //send sync
+- if ( SyncSend() == SOCKET_ERROR )
++ if (SyncSend() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
++ fNetTimeMon->Add(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f);
+ #endif
+
+ //send data
+- if ( DataSend() == SOCKET_ERROR )
++ if (DataSend() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - fRcvSyncUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
++ fNetTimeMon->AddLast(((float)(GetMicroSeconds() - fRcvSyncUst) / (float)fEngineControl->fPeriodUsecs) * 100.f);
+ #endif
+
+ return 0;
+@@ -560,127 +591,87 @@
+ extern "C"
+ {
+ #endif
+- SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
++ SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
+ {
+- jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("net", JackDriverMaster, "netjack slave backend component", &filler);
++
++ strcpy(value.str, DEFAULT_MULTICAST_IP);
++ jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
++
++ value.i = DEFAULT_PORT;
++ jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
+
+- strcpy ( desc->name, "net" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy ( desc->desc, "netjack slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
++ value.i = DEFAULT_MTU;
++ jack_driver_descriptor_add_parameter(desc, &filler, "mtu", 'M', JackDriverParamInt, &value, NULL, "MTU to the master", NULL);
+
+- desc->nparams = 10;
+- desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
++ value.i = -1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-ports", 'C', JackDriverParamInt, &value, NULL, "Number of audio input ports", "Number of audio input ports. If -1, audio physical input from the master");
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-ports", 'P', JackDriverParamInt, &value, NULL, "Number of audio output ports", "Number of audio output ports. If -1, audio physical output from the master");
+
+- int i = 0;
+- strcpy ( desc->params[i].name, "multicast_ip" );
+- desc->params[i].character = 'a';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
+- strcpy ( desc->params[i].short_desc, "Multicast Address" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "udp_net_port" );
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = DEFAULT_PORT;
+- strcpy ( desc->params[i].short_desc, "UDP port" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "mtu" );
+- desc->params[i].character = 'M';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = DEFAULT_MTU;
+- strcpy ( desc->params[i].short_desc, "MTU to the master" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "input_ports" );
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = 2;
+- strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "output_ports" );
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = 2;
+- strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "midi_in_ports" );
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = 0;
+- strcpy ( desc->params[i].short_desc, "Number of midi input ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "midi_out_ports" );
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy ( desc->params[i].short_desc, "Number of midi output ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "client_name" );
+- desc->params[i].character = 'n';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "'hostname'" );
+- strcpy ( desc->params[i].short_desc, "Name of the jack client" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "transport_sync" );
+- desc->params[i].character = 't';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 1U;
+- strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "mode" );
+- desc->params[i].character = 'm';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "slow" );
+- strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "midi-in-ports", 'i', JackDriverParamInt, &value, NULL, "Number of midi input ports", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "midi-out-ports", 'o', JackDriverParamInt, &value, NULL, "Number of midi output ports", NULL);
++
++#if HAVE_CELT
++ value.i = -1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamInt, &value, NULL, "Set CELT encoding and number of kBits per channel", NULL);
++#endif
++ strcpy(value.str, "'hostname'");
++ jack_driver_descriptor_add_parameter(desc, &filler, "client-name", 'n', JackDriverParamString, &value, NULL, "Name of the jack client", NULL);
++
++ value.ui = 0U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamUInt, &value, NULL, "Sync transport with master's", NULL);
++
++ value.ui = 5U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "latency", 'l', JackDriverParamUInt, &value, NULL, "Network latency", NULL);
+
+ return desc;
+ }
+
+- SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
++ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
+ {
+- char multicast_ip[16];
+- strcpy ( multicast_ip, DEFAULT_MULTICAST_IP );
++ char multicast_ip[32];
+ char net_name[JACK_CLIENT_NAME_SIZE + 1];
+- int udp_port = DEFAULT_PORT;
++ int udp_port;
+ int mtu = DEFAULT_MTU;
+- uint transport_sync = 1;
+- jack_nframes_t period_size = 128;
++ // Desactivated for now...
++ uint transport_sync = 0;
++ jack_nframes_t period_size = 1024;
+ jack_nframes_t sample_rate = 48000;
+- int audio_capture_ports = 2;
+- int audio_playback_ports = 2;
++ int audio_capture_ports = -1;
++ int audio_playback_ports = -1;
+ int midi_input_ports = 0;
+ int midi_output_ports = 0;
++ int celt_encoding = -1;
+ bool monitor = false;
+- char network_mode = 's';
++ int network_latency = 5;
+ const JSList* node;
+ const jack_driver_param_t* param;
+
+ net_name[0] = 0;
+
+- for ( node = params; node; node = jack_slist_next ( node ) )
+- {
+- param = ( const jack_driver_param_t* ) node->data;
+- switch ( param->character )
++ // Possibly use env variable
++ const char* default_udp_port = getenv("JACK_NETJACK_PORT");
++ udp_port = (default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT;
++
++ const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
++ if (default_multicast_ip) {
++ strcpy(multicast_ip, default_multicast_ip);
++ } else {
++ strcpy(multicast_ip, DEFAULT_MULTICAST_IP);
++ }
++
++ for (node = params; node; node = jack_slist_next(node)) {
++ param = (const jack_driver_param_t*) node->data;
++ switch (param->character)
+ {
+ case 'a' :
+- strncpy ( multicast_ip, param->value.str, 15 );
++ assert(strlen(param->value.str) < 32);
++ strcpy(multicast_ip, param->value.str);
+ break;
+ case 'p':
+ udp_port = param->value.ui;
+@@ -700,46 +691,42 @@
+ case 'o':
+ midi_output_ports = param->value.i;
+ break;
++ #if HAVE_CELT
++ case 'c':
++ celt_encoding = param->value.i;
++ break;
++ #endif
+ case 'n' :
+- strncpy ( net_name, param->value.str, JACK_CLIENT_NAME_SIZE );
++ strncpy(net_name, param->value.str, JACK_CLIENT_NAME_SIZE);
+ break;
+ case 't' :
+ transport_sync = param->value.ui;
+ break;
+- case 'm' :
+- if ( strcmp ( param->value.str, "normal" ) == 0 )
+- network_mode = 'n';
+- else if ( strcmp ( param->value.str, "slow" ) == 0 )
+- network_mode = 's';
+- else if ( strcmp ( param->value.str, "fast" ) == 0 )
+- network_mode = 'f';
+- else
+- jack_error ( "Unknown network mode, using 'normal' mode." );
++ case 'l' :
++ network_latency = param->value.ui;
++ if (network_latency > NETWORK_MAX_LATENCY) {
++ printf("Error : network latency is limited to %d\n", NETWORK_MAX_LATENCY);
++ return NULL;
++ }
+ break;
+ }
+ }
+
+- try
+- {
++ try {
+
+- Jack::JackDriverClientInterface* driver =
+- new Jack::JackWaitThreadedDriver (
+- new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
+- midi_input_ports, midi_output_ports, net_name, transport_sync, network_mode ) );
+- if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports,
+- monitor, "from_master_", "to_master_", 0, 0 ) == 0 )
+- {
++ Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver(
++ new Jack::JackNetDriver("system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
++ midi_input_ports, midi_output_ports,
++ net_name, transport_sync,
++ network_latency, celt_encoding));
++ if (driver->Open(period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports, monitor, "from_master_", "to_master_", 0, 0) == 0) {
+ return driver;
+- }
+- else
+- {
++ } else {
+ delete driver;
+ return NULL;
+ }
+
+- }
+- catch ( ... )
+- {
++ } catch (...) {
+ return NULL;
+ }
+ }
+--- a/common/JackNetDriver.h
++++ b/common/JackNetDriver.h
+@@ -1,6 +1,5 @@
+ /*
+-Copyright (C) 2001 Paul Davis
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -21,12 +20,10 @@
+ #ifndef __JackNetDriver__
+ #define __JackNetDriver__
+
+-#include "JackAudioDriver.h"
++#include "JackTimedDriver.h"
+ #include "JackNetInterface.h"
+
+-#ifdef JACK_MONITOR
+-#include "JackFrameTimer.h"
+-#endif
++//#define JACK_MONITOR
+
+ namespace Jack
+ {
+@@ -34,17 +31,19 @@
+ \Brief This class describes the Net Backend
+ */
+
+- class JackNetDriver : public JackAudioDriver, public JackNetSlaveInterface
++ class JackNetDriver : public JackWaiterDriver, public JackNetSlaveInterface
+ {
++
+ private:
++
+ //jack data
+ jack_port_id_t* fMidiCapturePortList;
+ jack_port_id_t* fMidiPlaybackPortList;
+-
++
+ //transport
+ int fLastTransportState;
+ int fLastTimebaseMaster;
+-
++
+ //monitoring
+ #ifdef JACK_MONITOR
+ JackGnuPlotMonitor<float>* fNetTimeMon;
+@@ -53,7 +52,7 @@
+
+ bool Initialize();
+ void FreeAll();
+-
++
+ int AllocPorts();
+ int FreePorts();
+
+@@ -61,18 +60,18 @@
+ void EncodeTransportData();
+ void DecodeTransportData();
+
+- JackMidiBuffer* GetMidiInputBuffer ( int port_index );
+- JackMidiBuffer* GetMidiOutputBuffer ( int port_index );
++ JackMidiBuffer* GetMidiInputBuffer(int port_index);
++ JackMidiBuffer* GetMidiOutputBuffer(int port_index);
++
++ void SaveConnections();
+
+ public:
+- JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
+- const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
+- char* net_name, uint transport_sync, char network_master_mode );
+- ~JackNetDriver();
+-
+- 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 );
++
++ JackNetDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
++ const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
++ char* net_name, uint transport_sync, int network_latency, int celt_encoding);
++ virtual ~JackNetDriver();
++
+ int Close();
+
+ int Attach();
+@@ -87,12 +86,12 @@
+ return true;
+ }
+
+- int SetBufferSize ( jack_nframes_t buffer_size )
++ int SetBufferSize(jack_nframes_t buffer_size)
+ {
+ return -1;
+ }
+
+- int SetSampleRate ( jack_nframes_t sample_rate )
++ int SetSampleRate(jack_nframes_t sample_rate)
+ {
+ return -1;
+ }
+--- /dev/null
++++ b/common/jack/net.h
+@@ -0,0 +1,316 @@
++/*
++ Copyright (C) 2009-2010 Grame
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU Lesser General Public License as published by
++ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __net_h__
++#define __net_h__
++
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++
++#include <jack/systemdeps.h>
++#include <jack/types.h>
++
++#define DEFAULT_MULTICAST_IP "225.3.19.154"
++#define DEFAULT_PORT 19000
++#define DEFAULT_MTU 1500
++#define MASTER_NAME_SIZE 256
++
++#define SOCKET_ERROR -1
++
++enum JackNetEncoder {
++
++ JackFloatEncoder = 0, // samples are transmitted as float
++ JackIntEncoder = 1, // samples are transmitted as 16 bits integer
++ JackCeltEncoder = 2, // samples are transmitted using CELT codec (http://www.celt-codec.org/)
++};
++
++typedef struct {
++
++ int audio_input; // from master or to slave (-1 for get master audio physical outputs)
++ int audio_output; // to master or from slave (-1 for get master audio physical inputs)
++ int midi_input; // from master or to slave (-1 for get master MIDI physical outputs)
++ int midi_output; // to master or from slave (-1 for get master MIDI physical inputs)
++ int mtu; // network Maximum Transmission Unit
++ int time_out; // in second, -1 means in infinite
++ int encoder; // encoder type (one of JackNetEncoder)
++ int kbps; // KB per second for CELT encoder
++ int latency; // network latency
++
++} jack_slave_t;
++
++typedef struct {
++
++ int audio_input; // master audio physical outputs
++ int audio_output; // master audio physical inputs
++ int midi_input; // master MIDI physical outputs
++ int midi_output; // master MIDI physical inputs
++ jack_nframes_t buffer_size; // mater buffer size
++ jack_nframes_t sample_rate; // mater sample rate
++ char master_name[MASTER_NAME_SIZE]; // master machine name
++
++} jack_master_t;
++
++/**
++ * jack_net_slave_t is an opaque type. You may only access it using the
++ * API provided.
++ */
++typedef struct _jack_net_slave jack_net_slave_t;
++
++ /**
++ * Open a network connection with the master machine.
++ * @param ip the multicast address of the master
++ * @param port the connection port
++ * @param request a connection request structure
++ * @param result a connection result structure
++ *
++ * @return Opaque net handle if successful or NULL in case of error.
++ */
++jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, jack_slave_t* request, jack_master_t* result);
++
++/**
++ * Close the network connection with the master machine.
++ * @param net the network connection to be closed
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_net_slave_close(jack_net_slave_t* net);
++
++/**
++ * Prototype for Process callback.
++ * @param nframes buffer size
++ * @param audio_input number of audio inputs
++ * @param audio_input_buffer an array of audio input buffers (from master)
++ * @param midi_input number of MIDI inputs
++ * @param midi_input_buffer an array of MIDI input buffers (from master)
++ * @param audio_output number of audio outputs
++ * @param audio_output_buffer an array of audio output buffers (to master)
++ * @param midi_output number of MIDI outputs
++ * @param midi_output_buffer an array of MIDI output buffers (to master)
++ * @param arg pointer to a client supplied structure supplied by jack_set_net_process_callback()
++ *
++ * @return zero on success, non-zero on error
++ */
++typedef int (* JackNetSlaveProcessCallback) (jack_nframes_t buffer_size,
++ int audio_input,
++ float** audio_input_buffer,
++ int midi_input,
++ void** midi_input_buffer,
++ int audio_output,
++ float** audio_output_buffer,
++ int midi_output,
++ void** midi_output_buffer,
++ void* data);
++
++/**
++ * Set network process callback.
++ * @param net the network connection
++ * @param net_callback the process callback
++ * @param arg pointer to a client supplied structure
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg);
++
++/**
++ * Start processing thread, the net_callback will start to be called.
++ * @param net the network connection
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_net_slave_activate(jack_net_slave_t* net);
++
++/**
++ * Stop processing thread.
++ * @param net the network connection
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_net_slave_deactivate(jack_net_slave_t* net);
++
++/**
++ * Prototype for BufferSize callback.
++ * @param nframes buffer size
++ * @param arg pointer to a client supplied structure supplied by jack_set_net_buffer_size_callback()
++ *
++ * @return zero on success, non-zero on error
++ */
++typedef int (*JackNetSlaveBufferSizeCallback)(jack_nframes_t nframes, void *arg);
++
++/**
++ * Prototype for SampleRate callback.
++ * @param nframes sample rate
++ * @param arg pointer to a client supplied structure supplied by jack_set_net_sample_rate_callback()
++ *
++ * @return zero on success, non-zero on error
++ */
++typedef int (*JackNetSlaveSampleRateCallback)(jack_nframes_t nframes, void *arg);
++
++/**
++ * Set network buffer size callback.
++ * @param net the network connection
++ * @param bufsize_callback the buffer size callback
++ * @param arg pointer to a client supplied structure
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg);
++
++/**
++ * Set network sample rate callback.
++ * @param net the network connection
++ * @param samplerate_callback the sample rate callback
++ * @param arg pointer to a client supplied structure
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg);
++
++/**
++ * Prototype for server Shutdown callback (if not set, the client will just restart, waiting for an available master again).
++ * @param arg pointer to a client supplied structure supplied by jack_set_net_shutdown_callback()
++ */
++typedef void (*JackNetSlaveShutdownCallback)(void* data);
++
++/**
++ * Set network shutdown callback.
++ * @param net the network connection
++ * @param shutdown_callback the shutdown callback
++ * @param arg pointer to a client supplied structure
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg);
++
++/**
++ * jack_net_master_t is an opaque type, you may only access it using the API provided.
++ */
++typedef struct _jack_net_master jack_net_master_t;
++
++ /**
++ * Open a network connection with the slave machine.
++ * @param ip the multicast address of the master
++ * @param port the connection port
++ * @param request a connection request structure
++ * @param result a connection result structure
++ *
++ * @return Opaque net handle if successful or NULL in case of error.
++ */
++jack_net_master_t* jack_net_master_open(const char* ip, int port, const char* name, jack_master_t* request, jack_slave_t* result);
++
++/**
++ * Close the network connection with the slave machine.
++ * @param net the network connection to be closed
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_net_master_close(jack_net_master_t* net);
++
++/**
++ * Receive sync and data from the network.
++ * @param net the network connection
++ * @param audio_input number of audio inputs
++ * @param audio_input_buffer an array of audio input buffers
++ * @param midi_input number of MIDI inputs
++ * @param midi_input_buffer an array of MIDI input buffers
++ *
++ * @return zero on success, non-zero on error
++ */
++int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer);
++
++/**
++ * Send sync and data to the network.
++ * @param net the network connection
++ * @param audio_output number of audio outputs
++ * @param audio_output_buffer an array of audio output buffers
++ * @param midi_output number of MIDI ouputs
++ * @param midi_output_buffer an array of MIDI output buffers
++ *
++ * @return zero on success, non-zero on error
++ */
++int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer);
++
++// Experimental Adapter API
++
++/**
++ * jack_adapter_t is an opaque type, you may only access it using the API provided.
++ */
++typedef struct _jack_adapter jack_adapter_t;
++
++/**
++ * Create an adapter.
++ * @param input number of audio inputs
++ * @param output of audio outputs
++ * @param host_buffer_size the host buffer size in frames
++ * @param host_sample_rate the host buffer sample rate
++ * @param adapted_buffer_size the adapted buffer size in frames
++ * @param adapted_sample_rate the adapted buffer sample rate
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++jack_adapter_t* jack_create_adapter(int input, int output,
++ jack_nframes_t host_buffer_size,
++ jack_nframes_t host_sample_rate,
++ jack_nframes_t adapted_buffer_size,
++ jack_nframes_t adapted_sample_rate);
++
++/**
++ * Destroy an adapter.
++ * @param adapter the adapter to be destroyed
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_destroy_adapter(jack_adapter_t* adapter);
++
++/**
++ * Flush internal state of an adapter.
++ * @param adapter the adapter to be flushed
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++void jack_flush_adapter(jack_adapter_t* adapter);
++
++/**
++ * Push input to and pull output from adapter ringbuffer.
++ * @param adapter the adapter
++ * @param input an array of audio input buffers
++ * @param output an array of audio ouput buffers
++ * @param frames number of frames
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
++
++/**
++ * Pull input to and push output from adapter ringbuffer.
++ * @param adapter the adapter
++ * @param input an array of audio input buffers
++ * @param output an array of audio ouput buffers
++ * @param frames number of frames
++ *
++ * @return 0 on success, otherwise a non-zero error code
++ */
++int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* __net_h__ */
+--- a/common/JackNetInterface.cpp
++++ b/common/JackNetInterface.cpp
+@@ -1,6 +1,5 @@
+ /*
+-Copyright (C) 2001 Paul Davis
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -24,9 +23,10 @@
+
+ using namespace std;
+
+-/*
+- TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames,
+- probably also use BUFFER_SIZE_MAX in everything related to MIDI events
++
++/*
++ TODO : since midi buffers now uses up to BUFFER_SIZE_MAX frames,
++ probably also use BUFFER_SIZE_MAX in everything related to MIDI events
+ handling (see MidiBufferInit in JackMidiPort.cpp)
+ */
+
+@@ -36,33 +36,24 @@
+
+ JackNetInterface::JackNetInterface() : fSocket()
+ {
+- fTxBuffer = NULL;
+- fRxBuffer = NULL;
+- fNetAudioCaptureBuffer = NULL;
+- fNetAudioPlaybackBuffer = NULL;
+- fNetMidiCaptureBuffer = NULL;
+- fNetMidiPlaybackBuffer = NULL;
+- memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
+- memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
++ Initialize();
+ }
+
+- JackNetInterface::JackNetInterface ( const char* multicast_ip, int port ) : fSocket ( multicast_ip, port )
++ JackNetInterface::JackNetInterface(const char* multicast_ip, int port) : fSocket(multicast_ip, port)
+ {
+ strcpy(fMulticastIP, multicast_ip);
+- fTxBuffer = NULL;
+- fRxBuffer = NULL;
+- fNetAudioCaptureBuffer = NULL;
+- fNetAudioPlaybackBuffer = NULL;
+- fNetMidiCaptureBuffer = NULL;
+- fNetMidiPlaybackBuffer = NULL;
+- memset(&fSendTransportData, 0, sizeof(net_transport_data_t));
+- memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
++ Initialize();
+ }
+
+- JackNetInterface::JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip ) : fSocket ( socket )
++ JackNetInterface::JackNetInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip) : fSocket(socket)
+ {
+ fParams = params;
+ strcpy(fMulticastIP, multicast_ip);
++ Initialize();
++ }
++
++ void JackNetInterface::Initialize()
++ {
+ fTxBuffer = NULL;
+ fRxBuffer = NULL;
+ fNetAudioCaptureBuffer = NULL;
+@@ -73,9 +64,21 @@
+ memset(&fReturnTransportData, 0, sizeof(net_transport_data_t));
+ }
+
++ void JackNetInterface::FreeNetworkBuffers()
++ {
++ delete fNetMidiCaptureBuffer;
++ delete fNetMidiPlaybackBuffer;
++ delete fNetAudioCaptureBuffer;
++ delete fNetAudioPlaybackBuffer;
++ fNetMidiCaptureBuffer = NULL;
++ fNetMidiPlaybackBuffer = NULL;
++ fNetAudioCaptureBuffer = NULL;
++ fNetAudioPlaybackBuffer = NULL;
++ }
++
+ JackNetInterface::~JackNetInterface()
+ {
+- jack_log ( "JackNetInterface::~JackNetInterface" );
++ jack_log("JackNetInterface::~JackNetInterface");
+
+ fSocket.Close();
+ delete[] fTxBuffer;
+@@ -86,178 +89,212 @@
+ delete fNetMidiPlaybackBuffer;
+ }
+
+- void JackNetInterface::SetFramesPerPacket()
+- {
+- jack_log ( "JackNetInterface::SetFramesPerPacket" );
+-
+- if (fParams.fSendAudioChannels == 0 && fParams.fReturnAudioChannels == 0) {
+- fParams.fFramesPerPacket = fParams.fPeriodSize;
+- } else {
+- jack_nframes_t period = ( int ) powf ( 2.f, ( int ) ( log (float ( fParams.fMtu - sizeof ( packet_header_t ) )
+- / ( max ( fParams.fReturnAudioChannels, fParams.fSendAudioChannels ) * sizeof ( sample_t ) ) ) / log ( 2. ) ) );
+- fParams.fFramesPerPacket = ( period > fParams.fPeriodSize ) ? fParams.fPeriodSize : period;
+- }
+- }
+-
+ int JackNetInterface::SetNetBufferSize()
+ {
+- jack_log ( "JackNetInterface::SetNetBufferSize" );
+-
+- float audio_size, midi_size;
+- int bufsize;
+- //audio
+- audio_size = fParams.fMtu * ( fParams.fPeriodSize / fParams.fFramesPerPacket );
+- //midi
+- midi_size = fParams.fMtu * ( max ( fParams.fSendMidiChannels, fParams.fReturnMidiChannels ) *
+- fParams.fPeriodSize * sizeof ( sample_t ) / ( fParams.fMtu - sizeof ( packet_header_t ) ) );
+- //bufsize = sync + audio + midi
+- bufsize = MAX_LATENCY * (fParams.fMtu + ( int ) audio_size + ( int ) midi_size);
++ // audio
++ float audio_size = (fNetAudioCaptureBuffer)
++ ? fNetAudioCaptureBuffer->GetCycleSize()
++ : (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->GetCycleSize() : 0;
++ jack_log("audio_size %f", audio_size);
++
++ // midi
++ float midi_size = (fNetMidiCaptureBuffer)
++ ? fNetMidiCaptureBuffer->GetCycleSize()
++ : (fNetMidiPlaybackBuffer) ? fNetMidiPlaybackBuffer->GetCycleSize() : 0;
++ jack_log("midi_size %f", midi_size);
++
++ // bufsize = sync + audio + midi
++ int bufsize = NETWORK_MAX_LATENCY * (fParams.fMtu + (int)audio_size + (int)midi_size);
++ jack_log("SetNetBufferSize bufsize = %d", bufsize);
+
+- //tx buffer
+- if ( fSocket.SetOption ( SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
++ // tx buffer
++ if (fSocket.SetOption(SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+- //rx buffer
+- if ( fSocket.SetOption ( SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof ( bufsize ) ) == SOCKET_ERROR )
++ // rx buffer
++ if (fSocket.SetOption(SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ return 0;
+ }
+
+- int JackNetInterface::GetNMidiPckt()
+- {
+- //even if there is no midi data, jack need an empty buffer to know there is no event to read
+- //99% of the cases : all data in one packet
+- if ( fTxHeader.fMidiDataSize <= ( fParams.fMtu - sizeof ( packet_header_t ) ) )
+- return 1;
+- //else, get the number of needed packets (simply slice the biiig buffer)
+- int npckt = fTxHeader.fMidiDataSize / ( fParams.fMtu - sizeof ( packet_header_t ) );
+- if ( fTxHeader.fMidiDataSize % ( fParams.fMtu - sizeof ( packet_header_t ) ) )
+- return ++npckt;
+- return npckt;
+- }
+-
+- bool JackNetInterface::IsNextPacket()
+- {
+- packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
+- //ignore first cycle
+- if ( fRxHeader.fCycle <= 1 ) {
+- return true;
+- }
+- //same PcktID (cycle), next SubPcktID (subcycle)
+- if ( ( fRxHeader.fSubCycle < ( fNSubProcess - 1 ) ) && ( rx_head->fCycle == fRxHeader.fCycle ) && ( rx_head->fSubCycle == ( fRxHeader.fSubCycle + 1 ) ) ) {
+- return true;
+- }
+- //next PcktID (cycle), SubPcktID reset to 0 (first subcyle)
+- if ( ( rx_head->fCycle == ( fRxHeader.fCycle + 1 ) ) && ( fRxHeader.fSubCycle == ( fNSubProcess - 1 ) ) && ( rx_head->fSubCycle == 0 ) ) {
+- return true;
+- }
+- //else, packet(s) missing, return false
+- return false;
+- }
+-
+- void JackNetInterface::SetParams()
++ bool JackNetInterface::SetParams()
+ {
+- //number of audio subcycles (packets)
+- fNSubProcess = fParams.fPeriodSize / fParams.fFramesPerPacket;
+-
+- //payload size
+- fPayloadSize = fParams.fMtu - sizeof ( packet_header_t );
+-
+- //TX header init
+- strcpy ( fTxHeader.fPacketType, "header" );
++ // TX header init
++ strcpy(fTxHeader.fPacketType, "header");
+ fTxHeader.fID = fParams.fID;
+ fTxHeader.fCycle = 0;
+ fTxHeader.fSubCycle = 0;
+- fTxHeader.fMidiDataSize = 0;
+- fTxHeader.fBitdepth = fParams.fBitdepth;
+ fTxHeader.fIsLastPckt = 0;
+
+- //RX header init
+- strcpy ( fRxHeader.fPacketType, "header" );
++ // RX header init
++ strcpy(fRxHeader.fPacketType, "header");
+ fRxHeader.fID = fParams.fID;
+ fRxHeader.fCycle = 0;
+ fRxHeader.fSubCycle = 0;
+- fRxHeader.fMidiDataSize = 0;
+- fRxHeader.fBitdepth = fParams.fBitdepth;
+ fRxHeader.fIsLastPckt = 0;
+
+- //network buffers
++ // network buffers
+ fTxBuffer = new char[fParams.fMtu];
+ fRxBuffer = new char[fParams.fMtu];
+- assert ( fTxBuffer );
+- assert ( fRxBuffer );
++ assert(fTxBuffer);
++ assert(fRxBuffer);
++
++ // net audio/midi buffers'addresses
++ fTxData = fTxBuffer + HEADER_SIZE;
++ fRxData = fRxBuffer + HEADER_SIZE;
++
++ return true;
++ }
++
++ int JackNetInterface::MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels)
++ {
++ if (midi_channnels > 0) {
++ // set global header fields and get the number of midi packets
++ fTxHeader.fDataType = 'm';
++ uint data_size = buffer->RenderFromJackPorts();
++ fTxHeader.fNumPacket = buffer->GetNumPackets(data_size, PACKET_AVAILABLE_SIZE(&fParams));
++
++ for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) {
++ fTxHeader.fSubCycle = subproc;
++ fTxHeader.fIsLastPckt = ((subproc == (fTxHeader.fNumPacket - 1)) && audio_channels == 0) ? 1 : 0;
++ fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, data_size);
++ memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
++ if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++ }
++ }
++ return 0;
++ }
++
++ int JackNetInterface::AudioSend(NetAudioBuffer* buffer, int audio_channels)
++ {
++ // audio
++ if (audio_channels > 0) {
++ fTxHeader.fDataType = 'a';
++ fTxHeader.fActivePorts = buffer->RenderFromJackPorts();
++ fTxHeader.fNumPacket = buffer->GetNumPackets(fTxHeader.fActivePorts);
++
++ for (uint subproc = 0; subproc < fTxHeader.fNumPacket; subproc++) {
++ fTxHeader.fSubCycle = subproc;
++ fTxHeader.fIsLastPckt = (subproc == (fTxHeader.fNumPacket - 1)) ? 1 : 0;
++ fTxHeader.fPacketSize = HEADER_SIZE + buffer->RenderToNetwork(subproc, fTxHeader.fActivePorts);
++ memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
++ // PacketHeaderDisplay(&fTxHeader);
++ if (Send(fTxHeader.fPacketSize, 0) == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++ }
++ }
++ return 0;
++ }
++
++ int JackNetInterface::MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt)
++ {
++ int rx_bytes = Recv(rx_head->fPacketSize, 0);
++ fRxHeader.fCycle = rx_head->fCycle;
++ fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
++ buffer->RenderFromNetwork(rx_head->fSubCycle, rx_bytes - HEADER_SIZE);
++ // Last midi packet is received, so finish rendering...
++ if (++recvd_midi_pckt == rx_head->fNumPacket) {
++ buffer->RenderToJackPorts();
++ }
++ return rx_bytes;
++ }
++
++ int JackNetInterface::AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer)
++ {
++ int rx_bytes = Recv(rx_head->fPacketSize, 0);
++ fRxHeader.fCycle = rx_head->fCycle;
++ fRxHeader.fSubCycle = rx_head->fSubCycle;
++ fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
++ fRxHeader.fActivePorts = rx_head->fActivePorts;
++ rx_bytes = buffer->RenderFromNetwork(rx_head->fCycle, rx_head->fSubCycle, fRxHeader.fActivePorts);
++ // Last audio packet is received, so finish rendering...
++ if (fRxHeader.fIsLastPckt) {
++ buffer->RenderToJackPorts();
++ }
++ return rx_bytes;
++ }
++
++ int JackNetInterface::FinishRecv(NetAudioBuffer* buffer)
++ {
++ // TODO : finish midi and audio rendering ?
++ buffer->RenderToJackPorts();
++ return NET_PACKET_ERROR;
++ }
++
++ NetAudioBuffer* JackNetInterface::AudioBufferFactory(int nports, char* buffer)
++ {
++ switch (fParams.fSampleEncoder) {
++
++ case JackFloatEncoder:
++ return new NetFloatAudioBuffer(&fParams, nports, buffer);
++
++ case JackIntEncoder:
++ return new NetIntAudioBuffer(&fParams, nports, buffer);
+
+- //net audio/midi buffers'addresses
+- fTxData = fTxBuffer + sizeof ( packet_header_t );
+- fRxData = fRxBuffer + sizeof ( packet_header_t );
++ #if HAVE_CELT
++ case JackCeltEncoder:
++ return new NetCeltAudioBuffer(&fParams, nports, buffer, fParams.fKBps);
++ #endif
++ }
++ return NULL;
+ }
+
+ // JackNetMasterInterface ************************************************************************************
+
+ bool JackNetMasterInterface::Init()
+ {
+- jack_log ( "JackNetMasterInterface::Init, ID %u.", fParams.fID );
++ jack_log("JackNetMasterInterface::Init, ID %u", fParams.fID);
+
+ session_params_t host_params;
+ uint attempt = 0;
+ int rx_bytes = 0;
+
+- //socket
+- if ( fSocket.NewSocket() == SOCKET_ERROR ) {
+- jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
++ // socket
++ if (fSocket.NewSocket() == SOCKET_ERROR) {
++ jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE));
+ return false;
+ }
+
+- //timeout on receive (for init)
+- if ( fSocket.SetTimeOut ( MASTER_INIT_TIMEOUT ) < 0 )
+- jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
+-
+- //connect
+- if ( fSocket.Connect() == SOCKET_ERROR ) {
+- jack_error ( "Can't connect : %s", StrError ( NET_ERROR_CODE ) );
++ // timeout on receive (for init)
++ if (fSocket.SetTimeOut(MASTER_INIT_TIMEOUT) < 0)
++ jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
++
++ // connect
++ if (fSocket.Connect() == SOCKET_ERROR) {
++ jack_error("Can't connect : %s", StrError(NET_ERROR_CODE));
+ return false;
+ }
+
+- //set the number of complete audio frames we can put in a packet
+- SetFramesPerPacket();
+-
+- //send 'SLAVE_SETUP' until 'START_MASTER' received
+- jack_info ( "Sending parameters to %s ...", fParams.fSlaveNetName );
++ // send 'SLAVE_SETUP' until 'START_MASTER' received
++ jack_info("Sending parameters to %s...", fParams.fSlaveNetName);
+ do
+ {
+ session_params_t net_params;
+- memset(&net_params, 0, sizeof ( session_params_t ));
+- SetPacketType ( &fParams, SLAVE_SETUP );
++ memset(&net_params, 0, sizeof(session_params_t));
++ SetPacketType(&fParams, SLAVE_SETUP);
+ SessionParamsHToN(&fParams, &net_params);
+-
+- if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
+- jack_error ( "Error in send : ", StrError ( NET_ERROR_CODE ) );
+-
+- memset(&net_params, 0, sizeof ( session_params_t ));
+- if ( ( ( rx_bytes = fSocket.Recv ( &net_params, sizeof ( session_params_t ), 0 ) ) == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
+- {
+- jack_error ( "Problem with network." );
++
++ if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) {
++ jack_error("Error in send : %s", StrError(NET_ERROR_CODE));
++ }
++
++ memset(&net_params, 0, sizeof(session_params_t));
++ if (((rx_bytes = fSocket.Recv(&net_params, sizeof(session_params_t), 0)) == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
++ jack_error("Problem with network");
+ return false;
+ }
+-
+- SessionParamsNToH(&net_params, &host_params);
+- }
+- while ( ( GetPacketType ( &host_params ) != START_MASTER ) && ( ++attempt < SLAVE_SETUP_RETRY ) );
+- if ( attempt == SLAVE_SETUP_RETRY ) {
+- jack_error ( "Slave doesn't respond, exiting." );
+- return false;
+- }
+
+- //set the new timeout for the socket
+- if ( SetRxTimeout() == SOCKET_ERROR ) {
+- jack_error ( "Can't set rx timeout : %s", StrError ( NET_ERROR_CODE ) );
+- return false;
++ SessionParamsNToH(&net_params, &host_params);
+ }
+-
+- //set the new rx buffer size
+- if ( SetNetBufferSize() == SOCKET_ERROR ) {
+- jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
++ while ((GetPacketType(&host_params) != START_MASTER) && (++attempt < SLAVE_SETUP_RETRY));
++ if (attempt == SLAVE_SETUP_RETRY) {
++ jack_error("Slave doesn't respond, exiting");
+ return false;
+ }
+
+@@ -266,334 +303,307 @@
+
+ int JackNetMasterInterface::SetRxTimeout()
+ {
+- jack_log ( "JackNetMasterInterface::SetRxTimeout" );
+-
+- float time = 0;
+- //slow or normal mode, short timeout on recv (2 audio subcycles)
+- if ( ( fParams.fNetworkMode == 's' ) || ( fParams.fNetworkMode == 'n' ) )
+- time = 2000000.f * ( static_cast<float> ( fParams.fFramesPerPacket ) / static_cast<float> ( fParams.fSampleRate ) );
+- //fast mode, wait for 75% of the entire cycle duration
+- else if ( fParams.fNetworkMode == 'f' )
+- time = 750000.f * ( static_cast<float> ( fParams.fPeriodSize ) / static_cast<float> ( fParams.fSampleRate ) );
+- return fSocket.SetTimeOut ( static_cast<int> ( time ) );
++ jack_log("JackNetMasterInterface::SetRxTimeout");
++ float time = 3 * 1000000.f * (static_cast<float>(fParams.fPeriodSize) / static_cast<float>(fParams.fSampleRate));
++ return fSocket.SetTimeOut(static_cast<int>(time));
+ }
+
+- void JackNetMasterInterface::SetParams()
++ bool JackNetMasterInterface::SetParams()
+ {
+- jack_log ( "JackNetMasterInterface::SetParams" );
++ jack_log("JackNetMasterInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d",
++ fParams.fSendAudioChannels, fParams.fReturnAudioChannels,
++ fParams.fSendMidiChannels, fParams.fReturnMidiChannels);
+
+ JackNetInterface::SetParams();
+
+ fTxHeader.fDataStream = 's';
+ fRxHeader.fDataStream = 'r';
+
+- //midi net buffers
+- fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fTxData );
+- fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fRxData );
+- assert ( fNetMidiCaptureBuffer );
+- assert ( fNetMidiPlaybackBuffer );
+-
+- //audio net buffers
+- fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fTxData );
+- fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fRxData );
+- assert ( fNetAudioCaptureBuffer );
+- assert ( fNetAudioPlaybackBuffer );
+-
+- //audio netbuffer length
+- fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
+- fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
++ fMaxCycleOffset = fParams.fNetworkLatency;
++
++ // midi net buffers
++ if (fParams.fSendMidiChannels > 0) {
++ fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fTxData);
++ }
++
++ if (fParams.fReturnMidiChannels > 0) {
++ fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fRxData);
++ }
++
++ try {
++
++ // audio net buffers
++ if (fParams.fSendAudioChannels > 0) {
++ fNetAudioCaptureBuffer = AudioBufferFactory(fParams.fSendAudioChannels, fTxData);
++ assert(fNetAudioCaptureBuffer);
++ }
++
++ if (fParams.fReturnAudioChannels > 0) {
++ fNetAudioPlaybackBuffer = AudioBufferFactory(fParams.fReturnAudioChannels, fRxData);
++ assert(fNetAudioPlaybackBuffer);
++ }
++
++ } catch (exception&) {
++ jack_error("NetAudioBuffer allocation error...");
++ return false;
++ }
++
++ // set the new timeout for the socket
++ /*
++ if (SetRxTimeout() == SOCKET_ERROR) {
++ jack_error("Can't set rx timeout : %s", StrError(NET_ERROR_CODE));
++ goto error;
++ }
++ */
++
++ // set the new rx buffer size
++ if (SetNetBufferSize() == SOCKET_ERROR) {
++ jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE));
++ goto error;
++ }
++
++ return true;
++
++ error:
++ FreeNetworkBuffers();
++ return false;
+ }
+
+ void JackNetMasterInterface::Exit()
+ {
+- jack_log ( "JackNetMasterInterface::Exit, ID %u", fParams.fID );
++ jack_log("JackNetMasterInterface::Exit, ID %u", fParams.fID);
+
+- //stop process
++ // stop process
+ fRunning = false;
+
+- //send a 'multicast euthanasia request' - new socket is required on macosx
+- jack_info ( "Exiting '%s'", fParams.fName );
+- SetPacketType ( &fParams, KILL_MASTER );
+- JackNetSocket mcast_socket ( fMulticastIP, fSocket.GetPort() );
+-
++ // send a 'multicast euthanasia request' - new socket is required on macosx
++ jack_info("Exiting '%s'", fParams.fName);
++ SetPacketType(&fParams, KILL_MASTER);
++ JackNetSocket mcast_socket(fMulticastIP, fSocket.GetPort());
++
+ session_params_t net_params;
+- memset(&net_params, 0, sizeof ( session_params_t ));
++ memset(&net_params, 0, sizeof(session_params_t));
+ SessionParamsHToN(&fParams, &net_params);
+
+- if ( mcast_socket.NewSocket() == SOCKET_ERROR )
+- jack_error ( "Can't create socket : %s", StrError ( NET_ERROR_CODE ) );
+- if ( mcast_socket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
+- jack_error ( "Can't send suicide request : %s", StrError ( NET_ERROR_CODE ) );
+-
++ if (mcast_socket.NewSocket() == SOCKET_ERROR) {
++ jack_error("Can't create socket : %s", StrError(NET_ERROR_CODE));
++ }
++ if (mcast_socket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR) {
++ jack_error("Can't send suicide request : %s", StrError(NET_ERROR_CODE));
++ }
++
+ mcast_socket.Close();
+ }
+
+- int JackNetMasterInterface::Recv ( size_t size, int flags )
++ void JackNetMasterInterface::FatalRecvError()
++ {
++ // fatal connection issue, exit
++ jack_error("Recv connection lost error = %s, '%s' exiting", StrError(NET_ERROR_CODE), fParams.fName);
++ // ask to the manager to properly remove the master
++ Exit();
++ // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
++ ThreadExit();
++ }
++
++ void JackNetMasterInterface::FatalSendError()
++ {
++ // fatal connection issue, exit
++ jack_error("Send connection lost error = %s, '%s' exiting", StrError(NET_ERROR_CODE), fParams.fName);
++ // ask to the manager to properly remove the master
++ Exit();
++ // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
++ ThreadExit();
++ }
++
++ int JackNetMasterInterface::Recv(size_t size, int flags)
+ {
+ int rx_bytes;
+- if ( ( ( rx_bytes = fSocket.Recv ( fRxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
+- {
++
++ if (((rx_bytes = fSocket.Recv(fRxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) {
++
++ /*
+ net_error_t error = fSocket.GetError();
+- //no data isn't really a network error, so just return 0 avalaible read bytes
+- if ( error == NET_NO_DATA )
++ // no data isn't really a network error, so just return 0 available read bytes
++ if (error == NET_NO_DATA) {
+ return 0;
+- else if ( error == NET_CONN_ERROR )
+- {
+- //fatal connection issue, exit
+- jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
+- //ask to the manager to properly remove the master
+- Exit();
+-
+- // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
+- ThreadExit();
++ } else if (error == NET_CONN_ERROR) {
++ FatalRecvError();
++ } else {
++ jack_error("Error in master receive : %s", StrError(NET_ERROR_CODE));
+ }
+- else
+- jack_error ( "Error in master receive : %s", StrError ( NET_ERROR_CODE ) );
++ */
++
++ FatalRecvError();
+ }
+-
++
+ packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
+ PacketHeaderNToH(header, header);
+ return rx_bytes;
+ }
+-
+- int JackNetMasterInterface::Send ( size_t size, int flags )
++
++ int JackNetMasterInterface::Send(size_t size, int flags)
+ {
+ int tx_bytes;
+ packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
+ PacketHeaderHToN(header, header);
+-
+- if ( ( ( tx_bytes = fSocket.Send ( fTxBuffer, size, flags ) ) == SOCKET_ERROR ) && fRunning )
+- {
++
++ if (((tx_bytes = fSocket.Send(fTxBuffer, size, flags)) == SOCKET_ERROR) && fRunning) {
++ /*
+ net_error_t error = fSocket.GetError();
+- if ( error == NET_CONN_ERROR )
+- {
+- //fatal connection issue, exit
+- jack_error ( "'%s' : %s, exiting.", fParams.fName, StrError ( NET_ERROR_CODE ) );
+- Exit();
+-
+- // UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
+- ThreadExit();
++ if (error == NET_CONN_ERROR) {
++ FatalSendError();
++ } else {
++ jack_error("Error in master send : %s", StrError(NET_ERROR_CODE));
+ }
+- else
+- jack_error ( "Error in master send : %s", StrError ( NET_ERROR_CODE ) );
++ */
++ FatalSendError();
+ }
+ return tx_bytes;
+ }
+-
++
+ bool JackNetMasterInterface::IsSynched()
+ {
+- if (fParams.fNetworkMode == 's') {
+- return (fCycleOffset < 3);
+- } else {
+- return true;
+- }
++ return (fCurrentCycleOffset <= fMaxCycleOffset);
+ }
+-
++
+ int JackNetMasterInterface::SyncSend()
+ {
+ fTxHeader.fCycle++;
+ fTxHeader.fSubCycle = 0;
+ fTxHeader.fDataType = 's';
+- fTxHeader.fIsLastPckt = ( fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ? 1 : 0;
++ fTxHeader.fIsLastPckt = (fParams.fSendMidiChannels == 0 && fParams.fSendAudioChannels == 0) ? 1 : 0;
+ fTxHeader.fPacketSize = fParams.fMtu;
+- memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
+- return Send ( fTxHeader.fPacketSize, 0 );
++
++ memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
++ // PacketHeaderDisplay(&fTxHeader);
++ return Send(fTxHeader.fPacketSize, 0);
+ }
+
+ int JackNetMasterInterface::DataSend()
+ {
+- uint subproc;
+- //midi
+- if ( fParams.fSendMidiChannels > 0)
+- {
+- //set global header fields and get the number of midi packets
+- fTxHeader.fDataType = 'm';
+- fTxHeader.fMidiDataSize = fNetMidiCaptureBuffer->RenderFromJackPorts();
+- fTxHeader.fNMidiPckt = GetNMidiPckt();
+- for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
+- {
+- fTxHeader.fSubCycle = subproc;
+- fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && (fParams.fSendAudioChannels == 0)) ? 1 : 0;
+- fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiCaptureBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
+- memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
+- if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
+- return SOCKET_ERROR;
+- }
+- }
+-
+- //audio
+- if ( fParams.fSendAudioChannels > 0)
+- {
+- fTxHeader.fDataType = 'a';
+- fTxHeader.fMidiDataSize = 0;
+- fTxHeader.fNMidiPckt = 0;
+- for ( subproc = 0; subproc < fNSubProcess; subproc++ )
+- {
+- fTxHeader.fSubCycle = subproc;
+- fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
+- fTxHeader.fPacketSize = fAudioTxLen;
+- memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
+- fNetAudioCaptureBuffer->RenderFromJackPorts ( subproc );
+- if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
+- return SOCKET_ERROR;
+- }
++ if (MidiSend(fNetMidiCaptureBuffer, fParams.fSendMidiChannels, fParams.fSendAudioChannels) == SOCKET_ERROR) {
++ return SOCKET_ERROR;
+ }
+-
+- return 0;
++ return AudioSend(fNetAudioCaptureBuffer, fParams.fSendAudioChannels);
+ }
+
+ int JackNetMasterInterface::SyncRecv()
+ {
+- packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
+- int rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
+-
+- if ( ( rx_bytes == 0 ) || ( rx_bytes == SOCKET_ERROR ) )
+- return rx_bytes;
++ int rx_bytes = 0;
++ packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
+
+- fCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
+-
+- switch ( fParams.fNetworkMode )
+- {
+- case 's' :
+- //slow mode : allow to use full bandwidth and heavy process on the slave
+- // - extra latency is set to two cycles, one cycle for send/receive operations + one cycle for heavy process on the slave
+- // - if the network is two fast, just wait the next cycle, this mode allows a shorter cycle duration for the master
+- // - this mode will skip the two first cycles, thus it lets time for data to be processed and queued on the socket rx buffer
+- //the slow mode is the safest mode because it wait twice the bandwidth relative time (send/return + process)
+- if (fCycleOffset < 2)
+- return 0;
+- else
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+-
+- if (fCycleOffset > 2) {
+- jack_info("Warning : '%s' runs in slow network mode, but data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
+- }
+- break;
++ /*
++ int rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
+
+- case 'n' :
+- //normal use of the network :
+- // - extra latency is set to one cycle, what is the time needed to receive streams using full network bandwidth
+- // - if the network is too fast, just wait the next cycle, the benefit here is the master's cycle is shorter
+- // - indeed, data is supposed to be on the network rx buffer, so we don't have to wait for it
+- if (fCycleOffset < 1)
+- return 0;
+- else
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+-
+- if (fCycleOffset != 1)
+- jack_info("'%s' can't run in normal network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
+- break;
+-
+- case 'f' :
+- //fast mode suppose the network bandwith is larger than required for the transmission (only a few channels for example)
+- // - packets can be quickly received, quickly is here relative to the cycle duration
+- // - here, receive data, we can't keep it queued on the rx buffer,
+- // - but if there is a cycle offset, tell the user, that means we're not in fast mode anymore, network is too slow
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+-
+- if (fCycleOffset != 0)
+- jack_info("'%s' can't run in fast network mode, data received too late (%d cycle(s) offset)", fParams.fName, fCycleOffset);
+- break;
++ if ((rx_bytes == 0) || (rx_bytes == SOCKET_ERROR)) {
++ // 0 bytes considered an error (lost connection)
++ return SOCKET_ERROR;
+ }
+
+- fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
+- return rx_bytes;
++ fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
++ */
++
++ // receive sync (launch the cycle)
++ do {
++ rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
++ // connection issue, send will detect it, so don't skip the cycle (return 0)
++ if (rx_bytes == SOCKET_ERROR) {
++ return SOCKET_ERROR;
++ }
++ }
++ while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's'));
++
++ fCurrentCycleOffset = fTxHeader.fCycle - rx_head->fCycle;
++
++ if (fCurrentCycleOffset < fMaxCycleOffset) {
++ jack_info("Synching with latency = %d", fCurrentCycleOffset);
++ return 0;
++ } else {
++ rx_bytes = Recv(rx_head->fPacketSize, 0);
++ fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
++ return rx_bytes;
++ }
+ }
+-
++
+ int JackNetMasterInterface::DataRecv()
+ {
+ int rx_bytes = 0;
+- uint jumpcnt = 0;
+ uint recvd_midi_pckt = 0;
+- uint recvd_audio_pckt = 0;
+- packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
+-
+- while ( !fRxHeader.fIsLastPckt )
+- {
+- //how much data is queued on the rx buffer ?
+- rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
+-
+- if ( rx_bytes == SOCKET_ERROR )
++ packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
++
++ while (!fRxHeader.fIsLastPckt) {
++ // how much data is queued on the rx buffer ?
++ rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
++
++ // error here, problem with recv, just skip the cycle (return -1)
++ if (rx_bytes == SOCKET_ERROR) {
+ return rx_bytes;
+- //if no data
+- if ( ( rx_bytes == 0 ) && ( ++jumpcnt == fNSubProcess ) )
+- {
+- jack_error ( "No data from %s...", fParams.fName );
+- jumpcnt = 0;
+- }
+- //else if data is valid,
+- if ( rx_bytes && ( rx_head->fDataStream == 'r' ) && ( rx_head->fID == fParams.fID ) )
+- {
+- //read data
+- switch ( rx_head->fDataType )
+- {
+- case 'm': //midi
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+- fRxHeader.fCycle = rx_head->fCycle;
+- fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
+- fNetMidiPlaybackBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
+- if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
+- fNetMidiPlaybackBuffer->RenderToJackPorts();
+- jumpcnt = 0;
++ }
++
++ if (rx_bytes && (rx_head->fDataStream == 'r') && (rx_head->fID == fParams.fID)) {
++ // read data
++ switch (rx_head->fDataType) {
++
++ case 'm': // midi
++ rx_bytes = MidiRecv(rx_head, fNetMidiPlaybackBuffer, recvd_midi_pckt);
+ break;
+
+- case 'a': //audio
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+- // SL: 25/01/09
+- // if ( !IsNextPacket() )
+- // jack_error ( "Packet(s) missing from '%s'...", fParams.fName );
+- if (recvd_audio_pckt++ != rx_head->fSubCycle) {
+- jack_error("Packet(s) missing from '%s'...", fParams.fSlaveNetName);
+- }
+- fRxHeader.fCycle = rx_head->fCycle;
+- fRxHeader.fSubCycle = rx_head->fSubCycle;
+- fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
+- fNetAudioPlaybackBuffer->RenderToJackPorts ( rx_head->fSubCycle );
+- jumpcnt = 0;
++ case 'a': // audio
++ rx_bytes = AudioRecv(rx_head, fNetAudioPlaybackBuffer);
+ break;
+
+- case 's': //sync
+- /* SL: 25/01/09
+- if ( rx_head->fCycle == fTxHeader.fCycle )
+- return 0;
+- */
++ case 's': // sync
+ jack_info("NetMaster : overloaded, skipping receive from '%s'", fParams.fName);
+- return 0;
++ return FinishRecv(fNetAudioPlaybackBuffer);
+ }
+ }
+ }
++
+ return rx_bytes;
+ }
+-
++
+ void JackNetMasterInterface::EncodeSyncPacket()
+ {
+- //this method contains every step of sync packet informations coding
+- //first of all, reset sync packet
+- memset ( fTxData, 0, fPayloadSize );
++ // This method contains every step of sync packet informations coding
++ // first of all, clear sync packet
++ memset(fTxData, 0, PACKET_AVAILABLE_SIZE(&fParams));
+
+- //then, first step : transport
++ // then, first step : transport
+ if (fParams.fTransportSync) {
+ EncodeTransportData();
+- TransportDataHToN( &fSendTransportData, &fSendTransportData);
+- //copy to TxBuffer
+- memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) );
++ TransportDataHToN(&fSendTransportData, &fSendTransportData);
++ // copy to TxBuffer
++ memcpy(fTxData, &fSendTransportData, sizeof(net_transport_data_t));
+ }
+- //then others (freewheel etc.)
+- //...
++ // then others (freewheel etc.)
++ // ...
++
++ // Transport not used for now...
++
++ // Write active ports list
++ fTxHeader.fActivePorts = (fNetAudioPlaybackBuffer) ? fNetAudioPlaybackBuffer->ActivePortsToNetwork(fTxData) : 0;
+ }
+
+ void JackNetMasterInterface::DecodeSyncPacket()
+ {
+- //this method contains every step of sync packet informations decoding process
+- //first : transport
++ // This method contains every step of sync packet informations decoding process
++ // first : transport
+ if (fParams.fTransportSync) {
+- //copy received transport data to transport data structure
+- memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) );
+- TransportDataNToH( &fReturnTransportData, &fReturnTransportData);
++ // copy received transport data to transport data structure
++ memcpy(&fReturnTransportData, fRxData, sizeof(net_transport_data_t));
++ TransportDataNToH(&fReturnTransportData, &fReturnTransportData);
+ DecodeTransportData();
+ }
+- //then others
+- //...
++ // then others
++ // ...
++
++ // Transport not used for now...
++ packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
++
++ // Read active ports list
++ if (fNetAudioCaptureBuffer) {
++ fNetAudioCaptureBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts);
++ }
+ }
+
+ // JackNetSlaveInterface ************************************************************************************************
+@@ -602,229 +612,269 @@
+
+ bool JackNetSlaveInterface::Init()
+ {
+- jack_log ( "JackNetSlaveInterface::Init()" );
++ jack_log("JackNetSlaveInterface::Init()");
+
+- //set the parameters to send
+- strcpy ( fParams.fPacketType, "params" );
++ // set the parameters to send
++ strcpy(fParams.fPacketType, "params");
+ fParams.fProtocolVersion = SLAVE_PROTOCOL;
+- SetPacketType ( &fParams, SLAVE_AVAILABLE );
++ SetPacketType(&fParams, SLAVE_AVAILABLE);
+
+- //init loop : get a master and start, do it until connection is ok
++ // init loop : get a master and start, do it until connection is ok
+ net_status_t status;
+- do
+- {
+- //first, get a master, do it until a valid connection is running
+- do
+- {
++ do {
++ // first, get a master, do it until a valid connection is running
++ do {
+ status = SendAvailableToMaster();
+- if ( status == NET_SOCKET_ERROR )
++ if (status == NET_SOCKET_ERROR) {
+ return false;
++ }
+ }
+- while ( status != NET_CONNECTED );
++ while (status != NET_CONNECTED);
+
+- //then tell the master we are ready
+- jack_info ( "Initializing connection with %s...", fParams.fMasterNetName );
++ // then tell the master we are ready
++ jack_info("Initializing connection with %s...", fParams.fMasterNetName);
+ status = SendStartToMaster();
+- if ( status == NET_ERROR )
++ if (status == NET_ERROR) {
+ return false;
++ }
+ }
+- while ( status != NET_ROLLING );
++ while (status != NET_ROLLING);
+
+ return true;
+ }
+-
++
+ // Separate the connection protocol into two separated step
+-
+- bool JackNetSlaveInterface::InitConnection()
++ bool JackNetSlaveInterface::InitConnection(int time_out_sec)
+ {
+- jack_log ( "JackNetSlaveInterface::InitConnection()" );
++ jack_log("JackNetSlaveInterface::InitConnection()");
++ uint try_count = (time_out_sec > 0) ? ((1000000 * time_out_sec) / SLAVE_INIT_TIMEOUT) : LONG_MAX;
+
+- //set the parameters to send
+- strcpy (fParams.fPacketType, "params");
++ // set the parameters to send
++ strcpy(fParams.fPacketType, "params");
+ fParams.fProtocolVersion = SLAVE_PROTOCOL;
+- SetPacketType (&fParams, SLAVE_AVAILABLE);
++ SetPacketType(&fParams, SLAVE_AVAILABLE);
+
+ net_status_t status;
+- do
+- {
+- //get a master
+- status = SendAvailableToMaster();
+- if (status == NET_SOCKET_ERROR)
++ do {
++ // get a master
++ status = SendAvailableToMaster(try_count);
++ if (status == NET_SOCKET_ERROR) {
+ return false;
++ }
+ }
+- while (status != NET_CONNECTED);
+-
+- return true;
++ while (status != NET_CONNECTED && --try_count > 0);
++
++ return (try_count != 0);
+ }
+-
++
+ bool JackNetSlaveInterface::InitRendering()
+ {
+ jack_log("JackNetSlaveInterface::InitRendering()");
+
+ net_status_t status;
+- do
+- {
+- //then tell the master we are ready
++ do {
++ // then tell the master we are ready
+ jack_info("Initializing connection with %s...", fParams.fMasterNetName);
+ status = SendStartToMaster();
+ if (status == NET_ERROR)
+ return false;
+ }
+- while (status != NET_ROLLING);
+-
++ while (status != NET_ROLLING);
++
+ return true;
+ }
+
+- net_status_t JackNetSlaveInterface::SendAvailableToMaster()
++ net_status_t JackNetSlaveInterface::SendAvailableToMaster(long try_count)
+ {
+- jack_log ( "JackNetSlaveInterface::SendAvailableToMaster()" );
+- //utility
++ jack_log("JackNetSlaveInterface::SendAvailableToMaster()");
++ // utility
+ session_params_t host_params;
+ int rx_bytes = 0;
+
+- //socket
+- if ( fSocket.NewSocket() == SOCKET_ERROR ) {
+- jack_error ( "Fatal error : network unreachable - %s", StrError ( NET_ERROR_CODE ) );
++ // socket
++ if (fSocket.NewSocket() == SOCKET_ERROR) {
++ jack_error("Fatal error : network unreachable - %s", StrError(NET_ERROR_CODE));
+ return NET_SOCKET_ERROR;
+ }
+
+- //bind the socket
+- if ( fSocket.Bind() == SOCKET_ERROR ) {
+- jack_error ( "Can't bind the socket : %s", StrError ( NET_ERROR_CODE ) );
+- return NET_SOCKET_ERROR;
++ if (fSocket.IsLocal(fMulticastIP)) {
++ jack_info("Local IP is used...");
++ } else {
++ // bind the socket
++ if (fSocket.Bind() == SOCKET_ERROR) {
++ jack_error("Can't bind the socket : %s", StrError(NET_ERROR_CODE));
++ return NET_SOCKET_ERROR;
++ }
+ }
+
+- //timeout on receive
+- if ( fSocket.SetTimeOut ( SLAVE_INIT_TIMEOUT ) == SOCKET_ERROR )
+- jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
+-
+- //disable local loop
+- if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
+- jack_error ( "Can't disable multicast loop : %s", StrError ( NET_ERROR_CODE ) );
++ // timeout on receive
++ if (fSocket.SetTimeOut(SLAVE_INIT_TIMEOUT) == SOCKET_ERROR)
++ jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
+
+- //send 'AVAILABLE' until 'SLAVE_SETUP' received
+- jack_info ( "Waiting for a master..." );
+- do
+- {
+- //send 'available'
++ // disable local loop
++ if (fSocket.SetLocalLoop() == SOCKET_ERROR)
++ jack_error("Can't disable multicast loop : %s", StrError(NET_ERROR_CODE));
++
++ // send 'AVAILABLE' until 'SLAVE_SETUP' received
++ jack_info("Waiting for a master...");
++ do {
++ // send 'available'
+ session_params_t net_params;
+- memset(&net_params, 0, sizeof ( session_params_t ));
++ memset(&net_params, 0, sizeof(session_params_t));
+ SessionParamsHToN(&fParams, &net_params);
+- if ( fSocket.SendTo ( &net_params, sizeof ( session_params_t ), 0, fMulticastIP ) == SOCKET_ERROR )
+- jack_error ( "Error in data send : %s", StrError ( NET_ERROR_CODE ) );
+-
+- //filter incoming packets : don't exit while no error is detected
+- memset(&net_params, 0, sizeof ( session_params_t ));
+- rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
++ if (fSocket.SendTo(&net_params, sizeof(session_params_t), 0, fMulticastIP) == SOCKET_ERROR)
++ jack_error("Error in data send : %s", StrError(NET_ERROR_CODE));
++
++ // filter incoming packets : don't exit while no error is detected
++ memset(&net_params, 0, sizeof(session_params_t));
++ rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
+ SessionParamsNToH(&net_params, &host_params);
+- if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
+- {
+- jack_error ( "Can't receive : %s", StrError ( NET_ERROR_CODE ) );
++ if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
++ jack_error("Can't receive : %s", StrError(NET_ERROR_CODE));
+ return NET_RECV_ERROR;
+ }
+ }
+- while ( strcmp ( host_params.fPacketType, fParams.fPacketType ) && ( GetPacketType ( &host_params ) != SLAVE_SETUP ) );
++ while (strcmp(host_params.fPacketType, fParams.fPacketType) && (GetPacketType(&host_params) != SLAVE_SETUP) && (--try_count > 0));
+
+- //everything is OK, copy parameters
+- fParams = host_params;
+-
+- //set the new buffer sizes
+- if ( SetNetBufferSize() == SOCKET_ERROR ) {
+- jack_error ( "Can't set net buffer sizes : %s", StrError ( NET_ERROR_CODE ) );
+- return NET_SOCKET_ERROR;
++ // Time out failure..
++ if (try_count == 0) {
++ jack_error("Time out error in connect");
++ return NET_CONNECT_ERROR;
+ }
+
+- //connect the socket
+- if ( fSocket.Connect() == SOCKET_ERROR ) {
+- jack_error ( "Error in connect : %s", StrError ( NET_ERROR_CODE ) );
++ // everything is OK, copy parameters
++ fParams = host_params;
++
++ // connect the socket
++ if (fSocket.Connect() == SOCKET_ERROR) {
++ jack_error("Error in connect : %s", StrError(NET_ERROR_CODE));
+ return NET_CONNECT_ERROR;
+ }
+-
+ return NET_CONNECTED;
+ }
+
+ net_status_t JackNetSlaveInterface::SendStartToMaster()
+ {
+- jack_log ( "JackNetSlaveInterface::SendStartToMaster" );
++ jack_log("JackNetSlaveInterface::SendStartToMaster");
+
+- //tell the master to start
++ // tell the master to start
+ session_params_t net_params;
+- memset(&net_params, 0, sizeof ( session_params_t ));
+- SetPacketType ( &fParams, START_MASTER );
++ memset(&net_params, 0, sizeof(session_params_t));
++ SetPacketType(&fParams, START_MASTER);
+ SessionParamsHToN(&fParams, &net_params);
+- if ( fSocket.Send ( &net_params, sizeof ( session_params_t ), 0 ) == SOCKET_ERROR )
+- {
+- jack_error ( "Error in send : %s", StrError ( NET_ERROR_CODE ) );
+- return ( fSocket.GetError() == NET_CONN_ERROR ) ? NET_ERROR : NET_SEND_ERROR;
++ if (fSocket.Send(&net_params, sizeof(session_params_t), 0) == SOCKET_ERROR) {
++ jack_error("Error in send : %s", StrError(NET_ERROR_CODE));
++ return (fSocket.GetError() == NET_CONN_ERROR) ? NET_ERROR : NET_SEND_ERROR;
+ }
+ return NET_ROLLING;
+ }
+
+- void JackNetSlaveInterface::SetParams()
++ bool JackNetSlaveInterface::SetParams()
+ {
+- jack_log ( "JackNetSlaveInterface::SetParams" );
++ jack_log("JackNetSlaveInterface::SetParams audio in = %d audio out = %d MIDI in = %d MIDI out = %d",
++ fParams.fSendAudioChannels, fParams.fReturnAudioChannels,
++ fParams.fSendMidiChannels, fParams.fReturnMidiChannels);
+
+ JackNetInterface::SetParams();
+
+ fTxHeader.fDataStream = 'r';
+ fRxHeader.fDataStream = 's';
+
+- //midi net buffers
+- fNetMidiCaptureBuffer = new NetMidiBuffer ( &fParams, fParams.fSendMidiChannels, fRxData );
+- fNetMidiPlaybackBuffer = new NetMidiBuffer ( &fParams, fParams.fReturnMidiChannels, fTxData );
++ // midi net buffers
++ if (fParams.fSendMidiChannels > 0) {
++ fNetMidiCaptureBuffer = new NetMidiBuffer(&fParams, fParams.fSendMidiChannels, fRxData);
++ }
++
++ if (fParams.fReturnMidiChannels > 0) {
++ fNetMidiPlaybackBuffer = new NetMidiBuffer(&fParams, fParams.fReturnMidiChannels, fTxData);
++ }
++
++ try {
++
++ // audio net buffers
++ if (fParams.fSendAudioChannels > 0) {
++ fNetAudioCaptureBuffer = AudioBufferFactory(fParams.fSendAudioChannels, fRxData);
++ assert(fNetAudioCaptureBuffer);
++ }
++
++ if (fParams.fReturnAudioChannels > 0) {
++ fNetAudioPlaybackBuffer = AudioBufferFactory(fParams.fReturnAudioChannels, fTxData);
++ assert(fNetAudioPlaybackBuffer);
++ }
++
++ } catch (exception&) {
++ jack_error("NetAudioBuffer allocation error...");
++ return false;
++ }
++
++ // set the new buffer sizes
++ if (SetNetBufferSize() == SOCKET_ERROR) {
++ jack_error("Can't set net buffer sizes : %s", StrError(NET_ERROR_CODE));
++ goto error;
++ }
+
+- //audio net buffers
+- fNetAudioCaptureBuffer = new NetAudioBuffer ( &fParams, fParams.fSendAudioChannels, fRxData );
+- fNetAudioPlaybackBuffer = new NetAudioBuffer ( &fParams, fParams.fReturnAudioChannels, fTxData );
++ return true;
+
+- //audio netbuffer length
+- fAudioTxLen = sizeof ( packet_header_t ) + fNetAudioPlaybackBuffer->GetSize();
+- fAudioRxLen = sizeof ( packet_header_t ) + fNetAudioCaptureBuffer->GetSize();
++ error:
++ FreeNetworkBuffers();
++ return false;
+ }
+
+- int JackNetSlaveInterface::Recv ( size_t size, int flags )
++ void JackNetSlaveInterface::FatalRecvError()
+ {
+- int rx_bytes = fSocket.Recv ( fRxBuffer, size, flags );
+- //handle errors
+- if ( rx_bytes == SOCKET_ERROR )
+- {
++ jack_error("Recv connection lost error = %s", StrError(NET_ERROR_CODE));
++ throw JackNetException();
++ }
++
++ void JackNetSlaveInterface::FatalSendError()
++ {
++ jack_error("Send connection lost error = %s", StrError(NET_ERROR_CODE));
++ throw JackNetException();
++ }
++
++ int JackNetSlaveInterface::Recv(size_t size, int flags)
++ {
++ int rx_bytes = fSocket.Recv(fRxBuffer, size, flags);
++ // handle errors
++ if (rx_bytes == SOCKET_ERROR) {
++ /*
+ net_error_t error = fSocket.GetError();
+- //no data isn't really an error in realtime processing, so just return 0
+- if ( error == NET_NO_DATA )
+- jack_error ( "No data, is the master still running ?" );
+- //if a network error occurs, this exception will restart the driver
+- else if ( error == NET_CONN_ERROR )
+- {
+- jack_error ( "Connection lost." );
+- throw JackNetException();
++ // no data isn't really an error in realtime processing, so just return 0
++ if (error == NET_NO_DATA) {
++ jack_error("No data, is the master still running ?");
++ // if a network error occurs, this exception will restart the driver
++ } else if (error == NET_CONN_ERROR) {
++ FatalRecvError();
++ } else {
++ jack_error("Fatal error in slave receive : %s", StrError(NET_ERROR_CODE));
+ }
+- else
+- jack_error ( "Fatal error in slave receive : %s", StrError ( NET_ERROR_CODE ) );
++ */
++ FatalRecvError();
+ }
+-
++
+ packet_header_t* header = reinterpret_cast<packet_header_t*>(fRxBuffer);
+ PacketHeaderNToH(header, header);
+ return rx_bytes;
+ }
+
+- int JackNetSlaveInterface::Send ( size_t size, int flags )
++ int JackNetSlaveInterface::Send(size_t size, int flags)
+ {
+ packet_header_t* header = reinterpret_cast<packet_header_t*>(fTxBuffer);
+ PacketHeaderHToN(header, header);
+- int tx_bytes = fSocket.Send ( fTxBuffer, size, flags );
+-
+- //handle errors
+- if ( tx_bytes == SOCKET_ERROR )
+- {
++ int tx_bytes = fSocket.Send(fTxBuffer, size, flags);
++
++ // handle errors
++ if (tx_bytes == SOCKET_ERROR) {
++ /*
+ net_error_t error = fSocket.GetError();
+- //if a network error occurs, this exception will restart the driver
+- if ( error == NET_CONN_ERROR )
+- {
+- jack_error ( "Connection lost." );
+- throw JackNetException();
++ // if a network error occurs, this exception will restart the driver
++ if (error == NET_CONN_ERROR) {
++ FatalSendError();
++ } else {
++ jack_error("Fatal error in slave send : %s", StrError(NET_ERROR_CODE));
+ }
+- else
+- jack_error ( "Fatal error in slave send : %s", StrError ( NET_ERROR_CODE ) );
++ */
++ FatalSendError();
+ }
+ return tx_bytes;
+ }
+@@ -832,157 +882,129 @@
+ int JackNetSlaveInterface::SyncRecv()
+ {
+ int rx_bytes = 0;
+- packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
+- //receive sync (launch the cycle)
+- do
+- {
+- rx_bytes = Recv ( fParams.fMtu, 0 );
+- //connection issue, send will detect it, so don't skip the cycle (return 0)
+- if ( rx_bytes == SOCKET_ERROR )
++ packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
++
++ // receive sync (launch the cycle)
++ do {
++ rx_bytes = Recv(fParams.fMtu, 0);
++ // connection issue, send will detect it, so don't skip the cycle (return 0)
++ if (rx_bytes == SOCKET_ERROR) {
+ return rx_bytes;
++ }
+ }
+ while ((strcmp(rx_head->fPacketType, "header") != 0) && (rx_head->fDataType != 's'));
+-
++
+ fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
+ return rx_bytes;
+ }
+
+ int JackNetSlaveInterface::DataRecv()
+ {
+- uint recvd_midi_pckt = 0;
+- uint recvd_audio_pckt = 0;
+ int rx_bytes = 0;
+- packet_header_t* rx_head = reinterpret_cast<packet_header_t*> ( fRxBuffer );
++ uint recvd_midi_pckt = 0;
++ packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
+
+- while ( !fRxHeader.fIsLastPckt )
+- {
+- rx_bytes = Recv ( fParams.fMtu, MSG_PEEK );
+- //error here, problem with recv, just skip the cycle (return -1)
++ while (!fRxHeader.fIsLastPckt) {
++ // how much data is queued on the rx buffer ?
++ rx_bytes = Recv(fParams.fMtu, MSG_PEEK);
+
+- if ( rx_bytes == SOCKET_ERROR )
++ // error here, problem with recv, just skip the cycle (return -1)
++ if (rx_bytes == SOCKET_ERROR) {
+ return rx_bytes;
+- if ( rx_bytes && ( rx_head->fDataStream == 's' ) && ( rx_head->fID == fParams.fID ) )
+- {
+- switch ( rx_head->fDataType )
+- {
+- case 'm': //midi
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+- fRxHeader.fCycle = rx_head->fCycle;
+- fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
+- fNetMidiCaptureBuffer->RenderFromNetwork ( rx_head->fSubCycle, rx_bytes - sizeof ( packet_header_t ) );
+- if ( ++recvd_midi_pckt == rx_head->fNMidiPckt )
+- fNetMidiCaptureBuffer->RenderToJackPorts();
++ }
++
++ if (rx_bytes && (rx_head->fDataStream == 's') && (rx_head->fID == fParams.fID)) {
++ // read data
++ switch (rx_head->fDataType) {
++
++ case 'm': // midi
++ rx_bytes = MidiRecv(rx_head, fNetMidiCaptureBuffer, recvd_midi_pckt);
+ break;
+
+- case 'a': //audio
+- rx_bytes = Recv ( rx_head->fPacketSize, 0 );
+- //SL: 25/01/09
+- // if ( !IsNextPacket() )
+- // jack_error ( "Packet(s) missing..." );
+- if (recvd_audio_pckt++ != rx_head->fSubCycle) {
+- jack_error("Packet(s) missing from '%s'...", fParams.fMasterNetName);
+- }
+- fRxHeader.fCycle = rx_head->fCycle;
+- fRxHeader.fSubCycle = rx_head->fSubCycle;
+- fRxHeader.fIsLastPckt = rx_head->fIsLastPckt;
+- fNetAudioCaptureBuffer->RenderToJackPorts ( rx_head->fSubCycle );
++ case 'a': // audio
++ rx_bytes = AudioRecv(rx_head, fNetAudioCaptureBuffer);
+ break;
+
+- case 's': //sync
+- jack_info ( "NetSlave : overloaded, skipping receive." );
+- return 0;
++ case 's': // sync
++ jack_info("NetSlave : overloaded, skipping receive");
++ return FinishRecv(fNetAudioCaptureBuffer);
+ }
+ }
+ }
++
+ fRxHeader.fCycle = rx_head->fCycle;
+- return 0;
++ return rx_bytes;
+ }
+
+ int JackNetSlaveInterface::SyncSend()
+ {
+- //tx header
+- if ( fParams.fSlaveSyncMode )
++ // tx header
++ if (fParams.fSlaveSyncMode) {
+ fTxHeader.fCycle = fRxHeader.fCycle;
+- else
++ } else {
+ fTxHeader.fCycle++;
++ }
+ fTxHeader.fSubCycle = 0;
+ fTxHeader.fDataType = 's';
+- fTxHeader.fIsLastPckt = ( fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ? 1 : 0;
++ fTxHeader.fIsLastPckt = (fParams.fReturnMidiChannels == 0 && fParams.fReturnAudioChannels == 0) ? 1 : 0;
+ fTxHeader.fPacketSize = fParams.fMtu;
+- memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
+- return Send ( fTxHeader.fPacketSize, 0 );
++
++ memcpy(fTxBuffer, &fTxHeader, HEADER_SIZE);
++ // PacketHeaderDisplay(&fTxHeader);
++ return Send(fTxHeader.fPacketSize, 0);
+ }
+
+ int JackNetSlaveInterface::DataSend()
+ {
+- uint subproc;
+-
+- //midi
+- if ( fParams.fReturnMidiChannels > 0)
+- {
+- fTxHeader.fDataType = 'm';
+- fTxHeader.fMidiDataSize = fNetMidiPlaybackBuffer->RenderFromJackPorts();
+- fTxHeader.fNMidiPckt = GetNMidiPckt();
+- for ( subproc = 0; subproc < fTxHeader.fNMidiPckt; subproc++ )
+- {
+- fTxHeader.fSubCycle = subproc;
+- fTxHeader.fIsLastPckt = ( ( subproc == ( fTxHeader.fNMidiPckt - 1 ) ) && !fParams.fReturnAudioChannels ) ? 1 : 0;
+- fTxHeader.fPacketSize = sizeof ( packet_header_t ) + fNetMidiPlaybackBuffer->RenderToNetwork ( subproc, fTxHeader.fMidiDataSize );
+- memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
+- if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
+- return SOCKET_ERROR;
+- }
+- }
+-
+- //audio
+- if ( fParams.fReturnAudioChannels > 0)
+- {
+- fTxHeader.fDataType = 'a';
+- fTxHeader.fMidiDataSize = 0;
+- fTxHeader.fNMidiPckt = 0;
+- for ( subproc = 0; subproc < fNSubProcess; subproc++ )
+- {
+- fTxHeader.fSubCycle = subproc;
+- fTxHeader.fIsLastPckt = ( subproc == ( fNSubProcess - 1 ) ) ? 1 : 0;
+- fTxHeader.fPacketSize = fAudioTxLen;
+- memcpy ( fTxBuffer, &fTxHeader, sizeof ( packet_header_t ) );
+- fNetAudioPlaybackBuffer->RenderFromJackPorts ( subproc );
+- if ( Send ( fTxHeader.fPacketSize, 0 ) == SOCKET_ERROR )
+- return SOCKET_ERROR;
+- }
++ if (MidiSend(fNetMidiPlaybackBuffer, fParams.fReturnMidiChannels, fParams.fReturnAudioChannels) == SOCKET_ERROR) {
++ return SOCKET_ERROR;
+ }
+- return 0;
++ return AudioSend(fNetAudioPlaybackBuffer, fParams.fReturnAudioChannels);
+ }
+-
+- //network sync------------------------------------------------------------------------
++
++ // network sync------------------------------------------------------------------------
+ void JackNetSlaveInterface::EncodeSyncPacket()
+ {
+- //this method contains every step of sync packet informations coding
+- //first of all, reset sync packet
+- memset ( fTxData, 0, fPayloadSize );
+- //then first step : transport
++ // This method contains every step of sync packet informations coding
++ // first of all, clear sync packet
++ memset(fTxData, 0, PACKET_AVAILABLE_SIZE(&fParams));
++
++ // then first step : transport
+ if (fParams.fTransportSync) {
+ EncodeTransportData();
+- TransportDataHToN( &fReturnTransportData, &fReturnTransportData);
+- //copy to TxBuffer
+- memcpy ( fTxData, &fReturnTransportData, sizeof ( net_transport_data_t ) );
++ TransportDataHToN(&fReturnTransportData, &fReturnTransportData);
++ // copy to TxBuffer
++ memcpy(fTxData, &fReturnTransportData, sizeof(net_transport_data_t));
+ }
+- //then others
+- //...
++ // then others
++ // ...
++
++ // Transport is not used for now...
++
++ // Write active ports list
++ fTxHeader.fActivePorts = (fNetAudioCaptureBuffer) ? fNetAudioCaptureBuffer->ActivePortsToNetwork(fTxData) : 0;
+ }
+-
++
+ void JackNetSlaveInterface::DecodeSyncPacket()
+ {
+- //this method contains every step of sync packet informations decoding process
+- //first : transport
++ // This method contains every step of sync packet informations decoding process
++ // first : transport
+ if (fParams.fTransportSync) {
+- //copy received transport data to transport data structure
+- memcpy ( &fSendTransportData, fRxData, sizeof ( net_transport_data_t ) );
+- TransportDataNToH( &fSendTransportData, &fSendTransportData);
++ // copy received transport data to transport data structure
++ memcpy(&fSendTransportData, fRxData, sizeof(net_transport_data_t));
++ TransportDataNToH(&fSendTransportData, &fSendTransportData);
+ DecodeTransportData();
+ }
+- //then others
+- //...
++ // then others
++ // ...
++
++ // Transport not used for now...
++ packet_header_t* rx_head = reinterpret_cast<packet_header_t*>(fRxBuffer);
++
++ // Read active ports list
++ if (fNetAudioPlaybackBuffer) {
++ fNetAudioPlaybackBuffer->ActivePortsFromNetwork(fRxData, rx_head->fActivePorts);
++ }
+ }
+
+ }
+--- a/common/JackNetInterface.h
++++ b/common/JackNetInterface.h
+@@ -1,6 +1,5 @@
+ /*
+-Copyright (C) 2001 Paul Davis
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -25,58 +24,67 @@
+
+ namespace Jack
+ {
++
++#define DEFAULT_MULTICAST_IP "225.3.19.154"
++#define DEFAULT_PORT 19000
++#define DEFAULT_MTU 1500
++
++#define SLAVE_SETUP_RETRY 5
++
++#define MANAGER_INIT_TIMEOUT 2000000 // in usec
++#define MASTER_INIT_TIMEOUT 1000000 // in usec
++#define SLAVE_INIT_TIMEOUT 1000000 // in usec
++
++#define NETWORK_MAX_LATENCY 20
++
+ /**
+- \Brief This class describes the basic Net Interface, used by both master and slave
++ \Brief This class describes the basic Net Interface, used by both master and slave.
+ */
+
+ class SERVER_EXPORT JackNetInterface
+ {
++
+ protected:
++
++ void Initialize();
++
+ session_params_t fParams;
+ JackNetSocket fSocket;
+ char fMulticastIP[32];
+- uint fNSubProcess;
+
+- //headers
++ // headers
+ packet_header_t fTxHeader;
+ packet_header_t fRxHeader;
+-
++
+ // transport
+ net_transport_data_t fSendTransportData;
+ net_transport_data_t fReturnTransportData;
+
+- //network buffers
++ // network buffers
+ char* fTxBuffer;
+ char* fRxBuffer;
+ char* fTxData;
+ char* fRxData;
+
+- //jack buffers
++ // JACK buffers
+ NetMidiBuffer* fNetMidiCaptureBuffer;
+ NetMidiBuffer* fNetMidiPlaybackBuffer;
+ NetAudioBuffer* fNetAudioCaptureBuffer;
+ NetAudioBuffer* fNetAudioPlaybackBuffer;
+
+- //sizes
+- int fAudioRxLen;
+- int fAudioTxLen;
+- int fPayloadSize;
+-
+- //utility methods
+- void SetFramesPerPacket();
++ // utility methods
+ int SetNetBufferSize();
+- int GetNMidiPckt();
+- bool IsNextPacket();
++ void FreeNetworkBuffers();
+
+- //virtual methods : depends on the sub class master/slave
+- virtual void SetParams();
++ // virtual methods : depends on the sub class master/slave
++ virtual bool SetParams();
+ virtual bool Init() = 0;
+
+- //transport
++ // transport
+ virtual void EncodeTransportData() = 0;
+ virtual void DecodeTransportData() = 0;
+
+- //sync packet
++ // sync packet
+ virtual void EncodeSyncPacket() = 0;
+ virtual void DecodeSyncPacket() = 0;
+
+@@ -85,15 +93,30 @@
+ virtual int DataRecv() = 0;
+ virtual int DataSend() = 0;
+
+- virtual int Send ( size_t size, int flags ) = 0;
+- virtual int Recv ( size_t size, int flags ) = 0;
++ virtual int Send(size_t size, int flags) = 0;
++ virtual int Recv(size_t size, int flags) = 0;
+
+- JackNetInterface();
+- JackNetInterface ( const char* multicast_ip, int port );
+- JackNetInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip );
++ virtual void FatalRecvError() = 0;
++ virtual void FatalSendError() = 0;
++
++ int MidiSend(NetMidiBuffer* buffer, int midi_channnels, int audio_channels);
++ int AudioSend(NetAudioBuffer* buffer, int audio_channels);
++
++ int MidiRecv(packet_header_t* rx_head, NetMidiBuffer* buffer, uint& recvd_midi_pckt);
++ int AudioRecv(packet_header_t* rx_head, NetAudioBuffer* buffer);
++
++ int FinishRecv(NetAudioBuffer* buffer);
++
++ NetAudioBuffer* AudioBufferFactory(int nports, char* buffer);
+
+ public:
++
++ JackNetInterface();
++ JackNetInterface(const char* multicast_ip, int port);
++ JackNetInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip);
++
+ virtual ~JackNetInterface();
++
+ };
+
+ /**
+@@ -102,38 +125,48 @@
+
+ class SERVER_EXPORT JackNetMasterInterface : public JackNetInterface
+ {
++
+ protected:
++
+ bool fRunning;
+- int fCycleOffset;
++
++ int fCurrentCycleOffset;
++ int fMaxCycleOffset;
++ int fLastfCycleOffset;
+
+ bool Init();
+ int SetRxTimeout();
+- void SetParams();
+-
++ bool SetParams();
++
+ void Exit();
+-
++
+ int SyncRecv();
+ int SyncSend();
+-
++
+ int DataRecv();
+ int DataSend();
+-
+- //sync packet
++
++ // sync packet
+ void EncodeSyncPacket();
+ void DecodeSyncPacket();
+
+- int Send ( size_t size, int flags );
+- int Recv ( size_t size, int flags );
+-
++ int Send(size_t size, int flags);
++ int Recv(size_t size, int flags);
++
+ bool IsSynched();
+
++ void FatalRecvError();
++ void FatalSendError();
++
+ public:
+- JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCycleOffset(0)
++
++ JackNetMasterInterface() : JackNetInterface(), fRunning(false), fCurrentCycleOffset(0), fMaxCycleOffset(0), fLastfCycleOffset(0)
+ {}
+- JackNetMasterInterface ( session_params_t& params, JackNetSocket& socket, const char* multicast_ip )
+- : JackNetInterface ( params, socket, multicast_ip )
++ JackNetMasterInterface(session_params_t& params, JackNetSocket& socket, const char* multicast_ip)
++ : JackNetInterface(params, socket, multicast_ip)
+ {}
+- ~JackNetMasterInterface()
++
++ virtual~JackNetMasterInterface()
+ {}
+ };
+
+@@ -143,75 +176,67 @@
+
+ class SERVER_EXPORT JackNetSlaveInterface : public JackNetInterface
+ {
++
+ protected:
+-
++
+ static uint fSlaveCounter;
+-
++
+ bool Init();
+- bool InitConnection();
++ bool InitConnection(int time_out_sec);
+ bool InitRendering();
+-
+- net_status_t SendAvailableToMaster();
++
++ net_status_t SendAvailableToMaster(long count = LONG_MAX); // long here (and not int...)
+ net_status_t SendStartToMaster();
+-
+- void SetParams();
+-
++
++ bool SetParams();
++
+ int SyncRecv();
+ int SyncSend();
+-
++
+ int DataRecv();
+ int DataSend();
+-
+- //sync packet
++
++ // sync packet
+ void EncodeSyncPacket();
+ void DecodeSyncPacket();
+
+- int Recv ( size_t size, int flags );
+- int Send ( size_t size, int flags );
++ int Recv(size_t size, int flags);
++ int Send(size_t size, int flags);
+
+- public:
+- JackNetSlaveInterface() : JackNetInterface()
++ void FatalRecvError();
++ void FatalSendError();
++
++ void InitAPI()
+ {
+- //open Socket API with the first slave
+- if ( fSlaveCounter++ == 0 )
+- {
+- if ( SocketAPIInit() < 0 )
+- {
+- jack_error ( "Can't init Socket API, exiting..." );
+- throw -1;
++ // open Socket API with the first slave
++ if (fSlaveCounter++ == 0) {
++ if (SocketAPIInit() < 0) {
++ jack_error("Can't init Socket API, exiting...");
++ throw std::bad_alloc();
+ }
+ }
+ }
+- JackNetSlaveInterface ( const char* ip, int port ) : JackNetInterface ( ip, port )
++
++ public:
++
++ JackNetSlaveInterface() : JackNetInterface()
+ {
+- //open Socket API with the first slave
+- if ( fSlaveCounter++ == 0 )
+- {
+- if ( SocketAPIInit() < 0 )
+- {
+- jack_error ( "Can't init Socket API, exiting..." );
+- throw -1;
+- }
+- }
++ InitAPI();
++ }
++
++ JackNetSlaveInterface(const char* ip, int port) : JackNetInterface(ip, port)
++ {
++ InitAPI();
+ }
+- ~JackNetSlaveInterface()
++
++ virtual ~JackNetSlaveInterface()
+ {
+- //close Socket API with the last slave
+- if ( --fSlaveCounter == 0 )
++ // close Socket API with the last slave
++ if (--fSlaveCounter == 0) {
+ SocketAPIEnd();
++ }
+ }
+ };
+ }
+
+-#define DEFAULT_MULTICAST_IP "225.3.19.154"
+-#define DEFAULT_PORT 19000
+-#define DEFAULT_MTU 1500
+-
+-#define SLAVE_SETUP_RETRY 5
+-
+-#define MASTER_INIT_TIMEOUT 1000000 // in usec
+-#define SLAVE_INIT_TIMEOUT 2000000 // in usec
+-
+-#define MAX_LATENCY 6
+-
+ #endif
+--- a/common/JackNetManager.cpp
++++ b/common/JackNetManager.cpp
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright(C) 2008-2011 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
+@@ -19,86 +19,84 @@
+ #include "JackNetManager.h"
+ #include "JackArgParser.h"
+ #include "JackTime.h"
++#include "JackServerGlobals.h"
++#include "JackLockedEngine.h"
+
+ using namespace std;
+
++
+ namespace Jack
+ {
+ //JackNetMaster******************************************************************************************************
+
+- JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip)
+- : JackNetMasterInterface ( params, socket, multicast_ip )
++ JackNetMaster::JackNetMaster(JackNetSocket& socket, session_params_t& params, const char* multicast_ip)
++ : JackNetMasterInterface(params, socket, multicast_ip)
+ {
+- jack_log ( "JackNetMaster::JackNetMaster" );
++ jack_log("JackNetMaster::JackNetMaster");
+
+ //settings
+- fClientName = const_cast<char*> ( fParams.fName );
++ fClientName = const_cast<char*>(fParams.fName);
+ fJackClient = NULL;
+ fSendTransportData.fState = -1;
+ fReturnTransportData.fState = -1;
+ fLastTransportState = -1;
+- uint port_index;
++ int port_index;
+
+ //jack audio ports
+ fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
+- for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
++ for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) {
+ fAudioCapturePorts[port_index] = NULL;
++ }
++
+ fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
+- for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
++ for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) {
+ fAudioPlaybackPorts[port_index] = NULL;
++ }
++
+ //jack midi ports
+ fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
+- for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
++ for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) {
+ fMidiCapturePorts[port_index] = NULL;
++ }
++
+ fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
+- for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
++ for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) {
+ fMidiPlaybackPorts[port_index] = NULL;
++ }
+
+ //monitor
+ #ifdef JACK_MONITOR
+- fPeriodUsecs = ( int ) ( 1000000.f * ( ( float ) fParams.fPeriodSize / ( float ) fParams.fSampleRate ) );
++ fPeriodUsecs = (int)(1000000.f * ((float) fParams.fPeriodSize / (float) fParams.fSampleRate));
+ string plot_name;
+- plot_name = string ( fParams.fName );
+- plot_name += string ( "_master" );
+- plot_name += string ( ( fParams.fSlaveSyncMode ) ? "_sync" : "_async" );
+- switch ( fParams.fNetworkMode )
+- {
+- case 's' :
+- plot_name += string ( "_slow" );
+- break;
+- case 'n' :
+- plot_name += string ( "_normal" );
+- break;
+- case 'f' :
+- plot_name += string ( "_fast" );
+- break;
+- }
+- fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
++ plot_name = string(fParams.fName);
++ plot_name += string("_master");
++ plot_name += string((fParams.fSlaveSyncMode) ? "_sync" : "_async");
++ plot_name += string("_latency");
++ fNetTimeMon = new JackGnuPlotMonitor<float>(128, 4, plot_name);
+ string net_time_mon_fields[] =
+ {
+- string ( "sync send" ),
+- string ( "end of send" ),
+- string ( "sync recv" ),
+- string ( "end of cycle" )
++ string("sync send"),
++ string("end of send"),
++ string("sync recv"),
++ string("end of cycle")
+ };
+ string net_time_mon_options[] =
+ {
+- string ( "set xlabel \"audio cycles\"" ),
+- string ( "set ylabel \"% of audio cycle\"" )
++ string("set xlabel \"audio cycles\""),
++ string("set ylabel \"% of audio cycle\"")
+ };
+- fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
++ fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 4);
+ #endif
+ }
+
+ JackNetMaster::~JackNetMaster()
+ {
+- jack_log ( "JackNetMaster::~JackNetMaster, ID %u.", fParams.fID );
++ jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID);
+
+- if ( fJackClient )
+- {
+- jack_deactivate ( fJackClient );
++ if (fJackClient) {
++ jack_deactivate(fJackClient);
+ FreePorts();
+- jack_client_close ( fJackClient );
++ jack_client_close(fJackClient);
+ }
+ delete[] fAudioCapturePorts;
+ delete[] fAudioPlaybackPorts;
+@@ -113,29 +111,34 @@
+ bool JackNetMaster::Init(bool auto_connect)
+ {
+ //network init
+- if ( !JackNetMasterInterface::Init() )
++ if (!JackNetMasterInterface::Init()) {
++ jack_error("JackNetMasterInterface::Init() error...");
+ return false;
++ }
+
+ //set global parameters
+- SetParams();
++ if (!SetParams()) {
++ jack_error("SetParams error...");
++ return false;
++ }
+
+ //jack client and process
+ jack_status_t status;
+- if ( ( fJackClient = jack_client_open ( fClientName, JackNullOption, &status, NULL ) ) == NULL )
+- {
+- jack_error ( "Can't open a new jack client." );
++ if ((fJackClient = jack_client_open(fClientName, JackNullOption, &status, NULL)) == NULL) {
++ jack_error("Can't open a new JACK client");
+ return false;
+ }
+
+- if (jack_set_process_callback(fJackClient, SetProcess, this ) < 0)
+- goto fail;
++ if (jack_set_process_callback(fJackClient, SetProcess, this) < 0) {
++ goto fail;
++ }
+
+- if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0)
+- goto fail;
++ if (jack_set_buffer_size_callback(fJackClient, SetBufferSize, this) < 0) {
++ goto fail;
++ }
+
+- if ( AllocPorts() != 0 )
+- {
+- jack_error ( "Can't allocate jack ports." );
++ if (AllocPorts() != 0) {
++ jack_error("Can't allocate JACK ports");
+ goto fail;
+ }
+
+@@ -143,20 +146,20 @@
+ fRunning = true;
+
+ //finally activate jack client
+- if ( jack_activate ( fJackClient ) != 0 )
+- {
+- jack_error ( "Can't activate jack client." );
++ if (jack_activate(fJackClient) != 0) {
++ jack_error("Can't activate JACK client");
+ goto fail;
+ }
+
+- if (auto_connect)
++ if (auto_connect) {
+ ConnectPorts();
+- jack_info ( "New NetMaster started." );
++ }
++ jack_info("New NetMaster started");
+ return true;
+
+ fail:
+ FreePorts();
+- jack_client_close ( fJackClient );
++ jack_client_close(fJackClient);
+ fJackClient = NULL;
+ return false;
+ }
+@@ -164,79 +167,49 @@
+ //jack ports--------------------------------------------------------------------------
+ int JackNetMaster::AllocPorts()
+ {
+- uint i;
++ int i;
+ char name[24];
+- jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient );
++ jack_nframes_t port_latency = jack_get_buffer_size(fJackClient);
+ jack_latency_range_t range;
+
+- jack_log ( "JackNetMaster::AllocPorts" );
++ jack_log("JackNetMaster::AllocPorts");
+
+ //audio
+- for ( i = 0; i < fParams.fSendAudioChannels; i++ )
+- {
+- sprintf ( name, "to_slave_%d", i+1 );
+- if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
++ for (i = 0; i < fParams.fSendAudioChannels; i++) {
++ snprintf(name, sizeof(name), "to_slave_%d", i+1);
++ if ((fAudioCapturePorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL)
+ return -1;
+ //port latency
+ range.min = range.max = 0;
+ jack_port_set_latency_range(fAudioCapturePorts[i], JackCaptureLatency, &range);
+ }
+
+- for ( i = 0; i < fParams.fReturnAudioChannels; i++ )
+- {
+- sprintf ( name, "from_slave_%d", i+1 );
+- if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
++ for (i = 0; i < fParams.fReturnAudioChannels; i++) {
++ snprintf(name, sizeof(name), "from_slave_%d", i+1);
++ if ((fAudioPlaybackPorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL)
+ return -1;
+ //port latency
+- switch ( fParams.fNetworkMode )
+- {
+- case 'f' :
+- range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency;
+- jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
+- break;
+- case 'n' :
+- range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
+- jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
+- break;
+- case 's' :
+- range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
+- jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
+- break;
+- }
++ range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
++ jack_port_set_latency_range(fAudioPlaybackPorts[i], JackPlaybackLatency, &range);
+ }
+
+-
+ //midi
+- for ( i = 0; i < fParams.fSendMidiChannels; i++ )
+- {
+- sprintf ( name, "midi_to_slave_%d", i+1 );
+- if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL )
++ for (i = 0; i < fParams.fSendMidiChannels; i++) {
++ snprintf(name, sizeof(name), "midi_to_slave_%d", i+1);
++ if ((fMidiCapturePorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL)
+ return -1;
+ //port latency
+ range.min = range.max = 0;
+ jack_port_set_latency_range(fMidiCapturePorts[i], JackCaptureLatency, &range);
+ }
+- for ( i = 0; i < fParams.fReturnMidiChannels; i++ )
+- {
+- sprintf ( name, "midi_from_slave_%d", i+1 );
+- if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL )
++
++ for (i = 0; i < fParams.fReturnMidiChannels; i++) {
++ snprintf(name, sizeof(name), "midi_from_slave_%d", i+1);
++ if ((fMidiPlaybackPorts[i] = jack_port_register(fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL)
+ return -1;
+ //port latency
+- switch ( fParams.fNetworkMode )
+- {
+- case 'f' :
+- range.min = range.max = (fParams.fSlaveSyncMode) ? 0 : port_latency;
+- jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
+- break;
+- case 'n' :
+- range.min = range.max = port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
+- jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
+- break;
+- case 's' :
+- range.min = range.max = 2 * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
+- jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
+- break;
+- }
++ range.min = range.max = fParams.fNetworkLatency * port_latency + (fParams.fSlaveSyncMode) ? 0 : port_latency;
++ jack_port_set_latency_range(fMidiPlaybackPorts[i], JackPlaybackLatency, &range);
+ }
+ return 0;
+ }
+@@ -247,7 +220,7 @@
+
+ ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput);
+ if (ports != NULL) {
+- for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
++ for (int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
+ jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i]));
+ }
+ free(ports);
+@@ -255,7 +228,7 @@
+
+ ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
+ if (ports != NULL) {
+- for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
++ for (int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
+ jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]);
+ }
+ free(ports);
+@@ -264,21 +237,29 @@
+
+ void JackNetMaster::FreePorts()
+ {
+- jack_log ( "JackNetMaster::FreePorts, ID %u", fParams.fID );
++ jack_log("JackNetMaster::FreePorts ID = %u", fParams.fID);
+
+- uint port_index;
+- for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
+- if ( fAudioCapturePorts[port_index] )
+- jack_port_unregister ( fJackClient, fAudioCapturePorts[port_index] );
+- for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
+- if ( fAudioPlaybackPorts[port_index] )
+- jack_port_unregister ( fJackClient, fAudioPlaybackPorts[port_index] );
+- for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
+- if ( fMidiCapturePorts[port_index] )
+- jack_port_unregister ( fJackClient, fMidiCapturePorts[port_index] );
+- for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
+- if ( fMidiPlaybackPorts[port_index] )
+- jack_port_unregister ( fJackClient, fMidiPlaybackPorts[port_index] );
++ int port_index;
++ for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) {
++ if (fAudioCapturePorts[port_index]) {
++ jack_port_unregister(fJackClient, fAudioCapturePorts[port_index]);
++ }
++ }
++ for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) {
++ if (fAudioPlaybackPorts[port_index]) {
++ jack_port_unregister(fJackClient, fAudioPlaybackPorts[port_index]);
++ }
++ }
++ for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) {
++ if (fMidiCapturePorts[port_index]) {
++ jack_port_unregister(fJackClient, fMidiCapturePorts[port_index]);
++ }
++ }
++ for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) {
++ if (fMidiPlaybackPorts[port_index]) {
++ jack_port_unregister(fJackClient, fMidiPlaybackPorts[port_index]);
++ }
++ }
+ }
+
+ //transport---------------------------------------------------------------------------
+@@ -289,87 +270,88 @@
+ fSendTransportData.fTimebaseMaster = NO_CHANGE;
+
+ //update state and position
+- fSendTransportData.fState = static_cast<uint> ( jack_transport_query ( fJackClient, &fSendTransportData.fPosition ) );
++ fSendTransportData.fState = static_cast<uint>(jack_transport_query(fJackClient, &fSendTransportData.fPosition));
+
+ //is it a new state ?
+- fSendTransportData.fNewState = ( ( fSendTransportData.fState != fLastTransportState ) &&
+- ( fSendTransportData.fState != fReturnTransportData.fState ) );
+- if ( fSendTransportData.fNewState )
+- jack_info ( "Sending '%s' to '%s' frame = %ld", GetTransportState ( fSendTransportData.fState ), fParams.fName, fSendTransportData.fPosition.frame );
++ fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState));
++ if (fSendTransportData.fNewState) {
++ jack_info("Sending '%s' to '%s' frame = %ld", GetTransportState(fSendTransportData.fState), fParams.fName, fSendTransportData.fPosition.frame);
++ }
+ fLastTransportState = fSendTransportData.fState;
+ }
+
+ void JackNetMaster::DecodeTransportData()
+ {
+ //is there timebase master change ?
+- if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE )
+- {
++ if (fReturnTransportData.fTimebaseMaster != NO_CHANGE) {
++
+ int timebase = 0;
+- switch ( fReturnTransportData.fTimebaseMaster )
++ switch (fReturnTransportData.fTimebaseMaster)
+ {
+ case RELEASE_TIMEBASEMASTER :
+- timebase = jack_release_timebase ( fJackClient );
+- if ( timebase < 0 )
+- jack_error ( "Can't release timebase master." );
+- else
+- jack_info ( "'%s' isn't the timebase master anymore.", fParams.fName );
++ timebase = jack_release_timebase(fJackClient);
++ if (timebase < 0) {
++ jack_error("Can't release timebase master");
++ } 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 )
+- jack_error ( "Can't set a new timebase master." );
+- else
+- jack_info ( "'%s' is the new timebase master.", fParams.fName );
++ timebase = jack_set_timebase_callback(fJackClient, 0, SetTimebaseCallback, this);
++ if (timebase < 0) {
++ jack_error("Can't set a new timebase master");
++ } 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 )
+- {
+- if ( timebase < 0 )
+- jack_error ( "Can't set a new timebase master." );
++ timebase = jack_set_timebase_callback(fJackClient, 1, SetTimebaseCallback, this);
++ if (timebase != EBUSY) {
++ if (timebase < 0)
++ jack_error("Can't set a new timebase master");
+ else
+- jack_info ( "'%s' is the new timebase master.", fParams.fName );
++ jack_info("'%s' is the new timebase master", fParams.fName);
+ }
+ break;
+ }
+ }
+
+ //is the slave in a new transport state and is this state different from master's ?
+- if ( fReturnTransportData.fNewState && ( fReturnTransportData.fState != jack_transport_query ( fJackClient, NULL ) ) )
+- {
+- switch ( fReturnTransportData.fState )
++ if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fJackClient, NULL))) {
++
++ switch (fReturnTransportData.fState)
+ {
+ case JackTransportStopped :
+- jack_transport_stop ( fJackClient );
+- jack_info ( "'%s' stops transport.", fParams.fName );
++ 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", fParams.fName, fReturnTransportData.fPosition.frame);
++ 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", fParams.fName, fReturnTransportData.fPosition.frame);
+ break;
+
+ case JackTransportNetStarting :
+- jack_info ( "'%s' is ready to roll..", fParams.fName );
++ jack_info("'%s' is ready to roll...", fParams.fName);
+ break;
+
+ case JackTransportRolling :
+- jack_info ( "'%s' is rolling.", fParams.fName );
++ jack_info("'%s' is rolling", fParams.fName);
+ break;
+ }
+ }
+ }
+
+- void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg )
++ void JackNetMaster::SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg)
+ {
+- static_cast<JackNetMaster*> ( arg )->TimebaseCallback ( pos );
++ static_cast<JackNetMaster*>(arg)->TimebaseCallback(pos);
+ }
+
+- void JackNetMaster::TimebaseCallback ( jack_position_t* pos )
++ void JackNetMaster::TimebaseCallback(jack_position_t* pos)
+ {
+ pos->bar = fReturnTransportData.fPosition.bar;
+ pos->beat = fReturnTransportData.fPosition.beat;
+@@ -385,32 +367,36 @@
+
+ bool JackNetMaster::IsSlaveReadyToRoll()
+ {
+- return ( fReturnTransportData.fState == JackTransportNetStarting );
++ return (fReturnTransportData.fState == JackTransportNetStarting);
+ }
+
+ int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg)
+ {
+ JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
+ if (nframes != obj->fParams.fPeriodSize) {
+- jack_error("Cannot handle bufer size change, so JackNetMaster proxy will be removed...");
++ jack_error("Cannot handle buffer size change, so JackNetMaster proxy will be removed...");
+ obj->Exit();
+ }
+ return 0;
+ }
+
+ //process-----------------------------------------------------------------------------
+- int JackNetMaster::SetProcess ( jack_nframes_t nframes, void* arg )
++ int JackNetMaster::SetProcess(jack_nframes_t nframes, void* arg)
+ {
+- return static_cast<JackNetMaster*> ( arg )->Process();
++ try {
++ return static_cast<JackNetMaster*>(arg)->Process();
++ } catch (JackNetException& e) {
++ return 0;
++ }
+ }
+
+ int JackNetMaster::Process()
+ {
+- if ( !fRunning )
+- return 0;
++ int res;
+
+- uint port_index;
+- int res = 0;
++ if (!fRunning) {
++ return 0;
++ }
+
+ #ifdef JACK_MONITOR
+ jack_time_t begin_time = GetMicroSeconds();
+@@ -418,38 +404,75 @@
+ #endif
+
+ //buffers
+- for ( port_index = 0; port_index < fParams.fSendMidiChannels; port_index++ )
+- fNetMidiCaptureBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiCapturePorts[port_index],
+- fParams.fPeriodSize ) ) );
+- for ( port_index = 0; port_index < fParams.fSendAudioChannels; port_index++ )
+- fNetAudioCaptureBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioCapturePorts[port_index],
+- fParams.fPeriodSize ) ) );
+- for ( port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++ )
+- fNetMidiPlaybackBuffer->SetBuffer ( port_index, static_cast<JackMidiBuffer*> ( jack_port_get_buffer ( fMidiPlaybackPorts[port_index],
+- fParams.fPeriodSize ) ) );
+- for ( port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++ )
+- fNetAudioPlaybackBuffer->SetBuffer ( port_index, static_cast<sample_t*> ( jack_port_get_buffer ( fAudioPlaybackPorts[port_index],
+- fParams.fPeriodSize ) ) );
++ for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
++ fNetMidiCaptureBuffer->SetBuffer(midi_port_index,
++ static_cast<JackMidiBuffer*>(jack_port_get_buffer(fMidiCapturePorts[midi_port_index],
++ fParams.fPeriodSize)));
++ }
++ for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
++
++ #ifdef OPTIMIZED_PROTOCOL
++ if (fNetAudioCaptureBuffer->GetConnected(audio_port_index)) {
++ // Port is connected on other side...
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index,
++ ((jack_port_connected(fAudioCapturePorts[audio_port_index]) > 0)
++ ? static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index], fParams.fPeriodSize))
++ : NULL));
++ } else {
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL);
++ }
++ #else
++ fNetAudioCaptureBuffer->SetBuffer(audio_port_index,
++ static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index],
++ fParams.fPeriodSize)));
++ #endif
++ // TODO
++ }
++
++ for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
++ fNetMidiPlaybackBuffer->SetBuffer(midi_port_index,
++ static_cast<JackMidiBuffer*>(jack_port_get_buffer(fMidiPlaybackPorts[midi_port_index],
++ fParams.fPeriodSize)));
++ }
++ for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
++
++ #ifdef OPTIMIZED_PROTOCOL
++ sample_t* out = (jack_port_connected(fAudioPlaybackPorts[audio_port_index]) > 0)
++ ? static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize))
++ : NULL;
++ if (out) {
++ memset(out, 0, sizeof(float) * fParams.fPeriodSize);
++ }
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out);
++ #else
++ sample_t* out = static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize));
++ if (out) {
++ memset(out, 0, sizeof(float) * fParams.fPeriodSize);
++ }
++ fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out)));
++ #endif
++ }
+
+ if (IsSynched()) { // only send if connection is "synched"
+
+ //encode the first packet
+ EncodeSyncPacket();
+
+- //send sync
+- if ( SyncSend() == SOCKET_ERROR )
++ if (SyncSend() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
++ fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
+ #endif
+
+ //send data
+- if ( DataSend() == SOCKET_ERROR )
++ if (DataSend() == SOCKET_ERROR) {
+ return SOCKET_ERROR;
++ }
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
++ fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
+ #endif
+
+ } else {
+@@ -458,11 +481,32 @@
+
+ //receive sync
+ res = SyncRecv();
+- if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
++ if ((res == 0) || (res == SOCKET_ERROR)) {
+ return res;
++ }
++
++ /*
++ switch (SyncRecv()) {
++
++ case 0:
++ jack_error("Connection is not yet synched, skip cycle...");
++ return 0;
++
++ case SOCKET_ERROR:
++ jack_error("Connection is lost, quit master...");
++ //ask to the manager to properly remove the master
++ Exit();
++ //UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
++ ThreadExit();
++ break;
++
++ default:
++ break;
++ }
++ */
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->Add ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
++ fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
+ #endif
+
+ //decode sync
+@@ -470,45 +514,80 @@
+
+ //receive data
+ res = DataRecv();
+- if ( ( res == 0 ) || ( res == SOCKET_ERROR ) )
++ if ((res == 0) || (res == SOCKET_ERROR)) {
+ return res;
++ } else if (res == NET_PACKET_ERROR) {
++ // Well not a real XRun...
++ JackServerGlobals::fInstance->GetEngine()->NotifyXRun(GetMicroSeconds(), 0);
++ }
++
++ /*
++ switch (DataRecv()) {
++
++ case 0:
++ jack_error("Connection is not yet synched, skip cycle...");
++ return 0;
++
++ case SOCKET_ERROR:
++ jack_error("Connection is lost, quit master...");
++ //ask to the manager to properly remove the master
++ Exit();
++ //UGLY temporary way to be sure the thread does not call code possibly causing a deadlock in JackEngine.
++ ThreadExit();
++ break;
++
++ default:
++ break;
++ }
++ */
+
+ #ifdef JACK_MONITOR
+- fNetTimeMon->AddLast ( ( ( ( float ) (GetMicroSeconds() - begin_time ) ) / ( float ) fPeriodUsecs ) * 100.f );
++ fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
+ #endif
+ return 0;
+ }
+
+ //JackNetMasterManager***********************************************************************************************
+
+- JackNetMasterManager::JackNetMasterManager ( jack_client_t* client, const JSList* params ) : fSocket()
++ JackNetMasterManager::JackNetMasterManager(jack_client_t* client, const JSList* params) : fSocket()
+ {
+- jack_log ( "JackNetMasterManager::JackNetMasterManager" );
++ jack_log("JackNetMasterManager::JackNetMasterManager");
+
+ fManagerClient = client;
+- fManagerName = jack_get_client_name ( fManagerClient );
+- strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
+- fSocket.SetPort ( DEFAULT_PORT );
++ fManagerName = jack_get_client_name(fManagerClient);
+ fGlobalID = 0;
+ fRunning = true;
+ fAutoConnect = false;
+
+ const JSList* node;
+ const jack_driver_param_t* param;
+- for ( node = params; node; node = jack_slist_next ( node ) )
+- {
+- param = ( const jack_driver_param_t* ) node->data;
+- switch ( param->character )
++
++ // Possibly use env variable
++ const char* default_udp_port = getenv("JACK_NETJACK_PORT");
++ fSocket.SetPort((default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT);
++
++ const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
++ if (default_multicast_ip) {
++ strcpy(fMulticastIP, default_multicast_ip);
++ } else {
++ strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
++ }
++
++ for (node = params; node; node = jack_slist_next(node)) {
++
++ param = (const jack_driver_param_t*) node->data;
++ switch (param->character)
+ {
+ case 'a' :
+- if (strlen (param->value.str) < 32)
++ if (strlen(param->value.str) < 32) {
+ strcpy(fMulticastIP, param->value.str);
+- else
++ } else {
+ jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
++ }
+ break;
+
+ case 'p':
+- fSocket.SetPort ( param->value.ui );
++ fSocket.SetPort(param->value.ui);
+ break;
+
+ case 'c':
+@@ -518,59 +597,82 @@
+ }
+
+ //set sync callback
+- jack_set_sync_callback ( fManagerClient, SetSyncCallback, this );
++ jack_set_sync_callback(fManagerClient, SetSyncCallback, this);
+
+ //activate the client (for sync callback)
+- if ( jack_activate ( fManagerClient ) != 0 )
+- jack_error ( "Can't activate the network manager client, transport disabled." );
++ if (jack_activate(fManagerClient) != 0) {
++ jack_error("Can't activate the NetManager client, transport disabled");
++ }
+
+ //launch the manager thread
+- if ( jack_client_create_thread ( fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this ) )
+- jack_error ( "Can't create the network manager control thread." );
++ if (jack_client_create_thread(fManagerClient, &fManagerThread, 0, 0, NetManagerThread, this)) {
++ jack_error("Can't create the NetManager control thread");
++ }
+ }
+
+ JackNetMasterManager::~JackNetMasterManager()
+ {
+- jack_log ( "JackNetMasterManager::~JackNetMasterManager" );
+- jack_info ( "Exiting net manager..." );
++ jack_log("JackNetMasterManager::~JackNetMasterManager");
++ jack_info("Exiting NetManager...");
+ fRunning = false;
+- jack_client_kill_thread ( fManagerClient, fManagerThread );
++ jack_client_kill_thread(fManagerClient, fManagerThread);
+ master_list_t::iterator it;
+- for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
+- delete ( *it );
++ for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
++ delete(*it);
++ }
+ fSocket.Close();
+ SocketAPIEnd();
+ }
+
+- int JackNetMasterManager::SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg )
++ int JackNetMasterManager::CountIO(int flags)
++ {
++ const char **ports;
++ int count = 0;
++ jack_port_t* port;
++
++ ports = jack_get_ports(fManagerClient, NULL, NULL, flags);
++ if (ports != NULL) {
++ while (ports[count]
++ && (port = jack_port_by_name(fManagerClient, ports[count]))
++ && (strcmp(jack_port_type(port), JACK_DEFAULT_AUDIO_TYPE) == 0)) {
++ count++;
++ }
++ free(ports);
++ }
++ return count;
++ }
++
++ int JackNetMasterManager::SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg)
+ {
+- return static_cast<JackNetMasterManager*> ( arg )->SyncCallback ( state, pos );
++ return static_cast<JackNetMasterManager*>(arg)->SyncCallback(state, pos);
+ }
+
+- int JackNetMasterManager::SyncCallback ( jack_transport_state_t state, jack_position_t* pos )
++ int JackNetMasterManager::SyncCallback(jack_transport_state_t state, jack_position_t* pos)
+ {
+ //check if each slave is ready to roll
+ int ret = 1;
+ master_list_it_t it;
+- for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
+- if ( ! ( *it )->IsSlaveReadyToRoll() )
++ for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
++ if (!(*it)->IsSlaveReadyToRoll()) {
+ ret = 0;
+- jack_log ( "JackNetMasterManager::SyncCallback returns '%s'", ( ret ) ? "true" : "false" );
++ }
++ }
++ jack_log("JackNetMasterManager::SyncCallback returns '%s'", (ret) ? "true" : "false");
+ return ret;
+ }
+
+- void* JackNetMasterManager::NetManagerThread ( void* arg )
++ void* JackNetMasterManager::NetManagerThread(void* arg)
+ {
+- JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*> ( arg );
+- jack_info ( "Starting Jack Network Manager." );
+- jack_info ( "Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort() );
++ JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*>(arg);
++ jack_info("Starting Jack NetManager");
++ jack_info("Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort());
+ master_manager->Run();
+ return NULL;
+ }
+
+ void JackNetMasterManager::Run()
+ {
+- jack_log ( "JackNetMasterManager::Run" );
++ jack_log("JackNetMasterManager::Run");
+ //utility variables
+ int attempt = 0;
+
+@@ -580,137 +682,133 @@
+ JackNetMaster* net_master;
+
+ //init socket API (win32)
+- if ( SocketAPIInit() < 0 )
+- {
+- jack_error ( "Can't init Socket API, exiting..." );
++ if (SocketAPIInit() < 0) {
++ jack_error("Can't init Socket API, exiting...");
+ return;
+ }
+
+ //socket
+- if ( fSocket.NewSocket() == SOCKET_ERROR )
+- {
+- jack_error ( "Can't create the network management input socket : %s", StrError ( NET_ERROR_CODE ) );
++ if (fSocket.NewSocket() == SOCKET_ERROR) {
++ jack_error("Can't create NetManager input socket : %s", StrError(NET_ERROR_CODE));
+ return;
+ }
+
+ //bind the socket to the local port
+- if ( fSocket.Bind() == SOCKET_ERROR )
+- {
+- jack_error ( "Can't bind the network manager socket : %s", StrError ( NET_ERROR_CODE ) );
++ if (fSocket.Bind() == SOCKET_ERROR) {
++ jack_error("Can't bind NetManager socket : %s", StrError(NET_ERROR_CODE));
+ fSocket.Close();
+ return;
+ }
+
+ //join multicast group
+- if ( fSocket.JoinMCastGroup ( fMulticastIP ) == SOCKET_ERROR )
+- jack_error ( "Can't join multicast group : %s", StrError ( NET_ERROR_CODE ) );
++ if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
++ jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
++ }
+
+ //local loop
+- if ( fSocket.SetLocalLoop() == SOCKET_ERROR )
+- jack_error ( "Can't set local loop : %s", StrError ( NET_ERROR_CODE ) );
++ if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
++ jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
++ }
+
+ //set a timeout on the multicast receive (the thread can now be cancelled)
+- if ( fSocket.SetTimeOut ( 2000000 ) == SOCKET_ERROR )
+- jack_error ( "Can't set timeout : %s", StrError ( NET_ERROR_CODE ) );
+-
+- jack_info ( "Waiting for a slave..." );
++ if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
++ jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
++ }
+
+ //main loop, wait for data, deal with it and wait again
+ do
+ {
+ session_params_t net_params;
+- rx_bytes = fSocket.CatchHost ( &net_params, sizeof ( session_params_t ), 0 );
++ rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
+ SessionParamsNToH(&net_params, &host_params);
+- if ( ( rx_bytes == SOCKET_ERROR ) && ( fSocket.GetError() != NET_NO_DATA ) )
+- {
+- jack_error ( "Error in receive : %s", StrError ( NET_ERROR_CODE ) );
+- if ( ++attempt == 10 )
+- {
+- jack_error ( "Can't receive on the socket, exiting net manager." );
++ if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
++ jack_error("Error in receive : %s", StrError(NET_ERROR_CODE));
++ if (++attempt == 10) {
++ jack_error("Can't receive on the socket, exiting net manager");
+ return;
+ }
+ }
+- if ( rx_bytes == sizeof ( session_params_t ) )
+- {
+- switch ( GetPacketType ( &host_params ) )
++
++ if (rx_bytes == sizeof(session_params_t)) {
++ switch (GetPacketType (&host_params))
+ {
+ case SLAVE_AVAILABLE:
+- if ( ( net_master = InitMaster ( host_params ) ) )
+- SessionParamsDisplay ( &net_master->fParams );
+- else
+- jack_error ( "Can't init new net master..." );
+- jack_info ( "Waiting for a slave..." );
++ if ((net_master = InitMaster(host_params))) {
++ SessionParamsDisplay(&net_master->fParams);
++ } else {
++ jack_error("Can't init new NetMaster...");
++ }
++ jack_info("Waiting for a slave...");
+ break;
+ case KILL_MASTER:
+- if ( KillMaster ( &host_params ) )
+- jack_info ( "Waiting for a slave..." );
++ if (KillMaster(&host_params)) {
++ jack_info("Waiting for a slave...");
++ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+- while ( fRunning );
++ while (fRunning);
+ }
+
+- JackNetMaster* JackNetMasterManager::InitMaster ( session_params_t& params )
++ JackNetMaster* JackNetMasterManager::InitMaster(session_params_t& params)
+ {
+- jack_log ( "JackNetMasterManager::InitMaster, Slave : %s", params.fName );
++ jack_log("JackNetMasterManager::InitMaster, Slave : %s", params.fName);
+
+ //check MASTER <<==> SLAVE network protocol coherency
+ if (params.fProtocolVersion != MASTER_PROTOCOL) {
+- jack_error ( "Error : slave is running with a different protocol %s", params.fName );
++ jack_error("Error : slave %s is running with a different protocol %d != %d", params.fName, params.fProtocolVersion, MASTER_PROTOCOL);
+ return NULL;
+ }
+
+ //settings
+- fSocket.GetName ( params.fMasterNetName );
++ fSocket.GetName(params.fMasterNetName);
+ params.fID = ++fGlobalID;
+- params.fSampleRate = jack_get_sample_rate ( fManagerClient );
+- params.fPeriodSize = jack_get_buffer_size ( fManagerClient );
+- params.fBitdepth = 0;
+- SetSlaveName ( params );
++ params.fSampleRate = jack_get_sample_rate(fManagerClient);
++ params.fPeriodSize = jack_get_buffer_size(fManagerClient);
++
++ if (params.fSendAudioChannels == -1) {
++ params.fSendAudioChannels = CountIO(JackPortIsPhysical | JackPortIsOutput);
++ jack_info("Takes physical %d inputs for client", params.fSendAudioChannels);
++ }
++
++ if (params.fReturnAudioChannels == -1) {
++ params.fReturnAudioChannels = CountIO(JackPortIsPhysical | JackPortIsInput);
++ jack_info("Takes physical %d outputs for client", params.fReturnAudioChannels);
++ }
+
+ //create a new master and add it to the list
+ JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP);
+- if ( master->Init(fAutoConnect) )
+- {
+- fMasterList.push_back ( master );
++ if (master->Init(fAutoConnect)) {
++ fMasterList.push_back(master);
+ return master;
+ }
+ delete master;
+ return NULL;
+ }
+
+- void JackNetMasterManager::SetSlaveName ( session_params_t& params )
++ master_list_it_t JackNetMasterManager::FindMaster(uint32_t id)
+ {
+- jack_log ( "JackNetMasterManager::SetSlaveName" );
++ jack_log("JackNetMasterManager::FindMaster ID = %u", id);
+
+ master_list_it_t it;
+- for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
+- if ( strcmp ( ( *it )->fParams.fName, params.fName ) == 0 )
+- sprintf ( params.fName, "%s-%u", params.fName, params.fID );
+- }
+-
+- master_list_it_t JackNetMasterManager::FindMaster ( uint32_t id )
+- {
+- jack_log ( "JackNetMasterManager::FindMaster, ID %u.", id );
+-
+- master_list_it_t it;
+- for ( it = fMasterList.begin(); it != fMasterList.end(); it++ )
+- if ( ( *it )->fParams.fID == id )
++ for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
++ if ((*it)->fParams.fID == id) {
+ return it;
++ }
++ }
+ return it;
+ }
+
+- int JackNetMasterManager::KillMaster ( session_params_t* params )
++ int JackNetMasterManager::KillMaster(session_params_t* params)
+ {
+- jack_log ( "JackNetMasterManager::KillMaster, ID %u.", params->fID );
++ jack_log("JackNetMasterManager::KillMaster ID = %u", params->fID);
+
+- master_list_it_t master = FindMaster ( params->fID );
+- if ( master != fMasterList.end() )
+- {
+- fMasterList.erase ( master );
++ master_list_it_t master = FindMaster(params->fID);
++ if (master != fMasterList.end()) {
++ fMasterList.erase(master);
+ delete *master;
+ return 1;
+ }
+@@ -727,84 +825,64 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
+
+- strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
++ desc = jack_driver_descriptor_construct("netmanager", JackDriverNone, "netjack multi-cast master component", &filler);
+
+- desc->nparams = 3;
+- desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
++ strcpy(value.str, DEFAULT_MULTICAST_IP);
++ jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast Address", NULL);
+
+- int i = 0;
+- strcpy ( desc->params[i].name, "multicast_ip" );
+- desc->params[i].character = 'a';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
+- strcpy ( desc->params[i].short_desc, "Multicast Address" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "udp_net_port" );
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = DEFAULT_PORT;
+- strcpy ( desc->params[i].short_desc, "UDP port" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "auto_connect" );
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
++ value.i = DEFAULT_PORT;
++ jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", NULL);
+
+ return desc;
+ }
+
+- SERVER_EXPORT int jack_internal_initialize ( jack_client_t* jack_client, const JSList* params )
++ SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params)
+ {
+- if ( master_manager )
+- {
+- jack_error ( "Master Manager already loaded" );
++ if (master_manager) {
++ jack_error("Master Manager already loaded");
+ return 1;
+- }
+- else
+- {
+- jack_log ( "Loading Master Manager" );
+- master_manager = new Jack::JackNetMasterManager ( jack_client, params );
+- return ( master_manager ) ? 0 : 1;
++ } else {
++ jack_log("Loading Master Manager");
++ master_manager = new Jack::JackNetMasterManager(jack_client, params);
++ return (master_manager) ? 0 : 1;
+ }
+ }
+
+- SERVER_EXPORT int jack_initialize ( jack_client_t* jack_client, const char* load_init )
++ SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
+ {
+ JSList* params = NULL;
+ bool parse_params = true;
+ int res = 1;
+ jack_driver_desc_t* desc = jack_get_descriptor();
+
+- Jack::JackArgParser parser ( load_init );
+- if ( parser.GetArgc() > 0 )
+- parse_params = parser.ParseParams ( desc, ¶ms );
++ Jack::JackArgParser parser(load_init);
++ if (parser.GetArgc() > 0) {
++ parse_params = parser.ParseParams(desc, ¶ms);
++ }
+
+ if (parse_params) {
+- res = jack_internal_initialize ( jack_client, params );
+- parser.FreeParams ( params );
++ res = jack_internal_initialize(jack_client, params);
++ parser.FreeParams(params);
+ }
+ return res;
+ }
+
+- SERVER_EXPORT void jack_finish ( void* arg )
++ SERVER_EXPORT void jack_finish(void* arg)
+ {
+- if ( master_manager )
+- {
+- jack_log ( "Unloading Master Manager" );
++ if (master_manager) {
++ jack_log ("Unloading Master Manager");
+ delete master_manager;
+ master_manager = NULL;
+ }
+ }
++
+ #ifdef __cplusplus
+ }
+ #endif
+--- a/common/JackNetManager.h
++++ b/common/JackNetManager.h
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Grame
++Copyright (C) 2008-2011 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
+@@ -37,10 +37,12 @@
+ class JackNetMaster : public JackNetMasterInterface
+ {
+ friend class JackNetMasterManager;
++
+ private:
+- static int SetProcess ( jack_nframes_t nframes, void* arg );
+- static int SetBufferSize (jack_nframes_t nframes, void* arg);
+- static void SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg );
++
++ static int SetProcess(jack_nframes_t nframes, void* arg);
++ static int SetBufferSize(jack_nframes_t nframes, void* arg);
++ static void SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg);
+
+ //jack client
+ jack_client_t* fJackClient;
+@@ -70,12 +72,13 @@
+ void DecodeTransportData();
+
+ int Process();
+- void TimebaseCallback ( jack_position_t* pos );
++ void TimebaseCallback(jack_position_t* pos);
+ void ConnectPorts();
+
+ public:
+- JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip);
+- ~JackNetMaster ();
++
++ JackNetMaster(JackNetSocket& socket, session_params_t& params, const char* multicast_ip);
++ ~JackNetMaster();
+
+ bool IsSlaveReadyToRoll();
+ };
+@@ -90,9 +93,11 @@
+ class JackNetMasterManager
+ {
+ friend class JackNetMaster;
++
+ private:
+- static int SetSyncCallback ( jack_transport_state_t state, jack_position_t* pos, void* arg );
+- static void* NetManagerThread ( void* arg );
++
++ static int SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg);
++ static void* NetManagerThread(void* arg);
+
+ jack_client_t* fManagerClient;
+ const char* fManagerName;
+@@ -105,14 +110,15 @@
+ bool fAutoConnect;
+
+ void Run();
+- JackNetMaster* InitMaster ( session_params_t& params );
+- master_list_it_t FindMaster ( uint32_t client_id );
+- int KillMaster ( session_params_t* params );
+- void SetSlaveName ( session_params_t& params );
++ JackNetMaster* InitMaster(session_params_t& params);
++ master_list_it_t FindMaster(uint32_t client_id);
++ int KillMaster(session_params_t* params);
++ int SyncCallback(jack_transport_state_t state, jack_position_t* pos);
++ int CountIO(int flags);
+
+- int SyncCallback ( jack_transport_state_t state, jack_position_t* pos );
+ public:
+- JackNetMasterManager ( jack_client_t* jack_client, const JSList* params);
++
++ JackNetMasterManager(jack_client_t* jack_client, const JSList* params);
+ ~JackNetMasterManager();
+ };
+ }
+--- a/common/JackNetOneDriver.cpp
++++ b/common/JackNetOneDriver.cpp
+@@ -1,6 +1,5 @@
+ /*
+-Copyright (C) 2001 Paul Davis
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 Torben Horn
+
+ 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
+@@ -23,6 +22,7 @@
+
+ #include "JackNetOneDriver.h"
+ #include "JackEngineControl.h"
++#include "JackLockedEngine.h"
+ #include "JackGraphManager.h"
+ #include "JackWaitThreadedDriver.h"
+ #include "JackTools.h"
+@@ -32,7 +32,7 @@
+ #include "netjack_packet.h"
+
+ #if HAVE_SAMPLERATE
+-#include "samplerate.h"
++#include <samplerate.h>
+ #endif
+
+ #if HAVE_CELT
+@@ -45,974 +45,804 @@
+
+ namespace Jack
+ {
+- JackNetOneDriver::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 )
+- : JackAudioDriver ( name, alias, engine, table )
+- {
+- jack_log ( "JackNetOneDriver::JackNetOneDriver port %d", port );
++JackNetOneDriver::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)
++ : JackWaiterDriver(name, alias, engine, table)
++{
++ jack_log("JackNetOneDriver::JackNetOneDriver port %d", port);
+
+- #ifdef WIN32
+- WSADATA wsa;
+- int rc = WSAStartup(MAKEWORD(2,0),&wsa);
+- #endif
+-
+- netjack_init( & (this->netj),
+- NULL, // client
+- name,
+- capture_ports,
+- playback_ports,
+- midi_input_ports,
+- midi_output_ports,
+- sample_rate,
+- period_size,
+- port,
+- transport_sync,
+- resample_factor,
+- 0,
+- bitdepth,
+- use_autoconfig,
+- latency,
+- redundancy,
+- dont_htonl_floats,
+- always_deadline,
+- jitter_val);
+- }
++#ifdef WIN32
++ WSADATA wsa;
++ int rc = WSAStartup(MAKEWORD(2, 0), &wsa);
++#endif
+
+- JackNetOneDriver::~JackNetOneDriver()
+- {
+- // No destructor yet.
+- }
++ netjack_init(& (this->netj),
++ NULL, // client
++ name,
++ capture_ports,
++ playback_ports,
++ midi_input_ports,
++ midi_output_ports,
++ sample_rate,
++ period_size,
++ port,
++ transport_sync,
++ resample_factor,
++ 0,
++ bitdepth,
++ use_autoconfig,
++ latency,
++ redundancy,
++ dont_htonl_floats,
++ always_deadline,
++ jitter_val);
++}
++
++JackNetOneDriver::~JackNetOneDriver()
++{
++ // No destructor yet.
++}
+
+ //open, close, attach and detach------------------------------------------------------
+- int JackNetOneDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, 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 )
+- {
+- if ( JackAudioDriver::Open ( buffer_size,
+- samplerate,
+- capturing,
+- playing,
+- inchannels,
+- outchannels,
+- monitor,
+- capture_driver_name,
+- playback_driver_name,
+- capture_latency,
+- playback_latency ) == 0 )
+- {
+- fEngineControl->fPeriod = 0;
+- fEngineControl->fComputation = 500 * 1000;
+- fEngineControl->fConstraint = 500 * 1000;
+- return 0;
+- }
+- else
+- {
+- jack_error( "open fail" );
+- return -1;
+- }
+- }
+
+- int JackNetOneDriver::Close()
+- {
+- FreePorts();
+- netjack_release( &netj );
+- return JackDriver::Close();
+- }
++int JackNetOneDriver::Close()
++{
++ // Generic audio driver close
++ int res = JackWaiterDriver::Close();
+
+- int JackNetOneDriver::Attach()
+- {
+- return 0;
+- }
++ FreePorts();
++ netjack_release(&netj);
++ return res;
++}
+
+- int JackNetOneDriver::Detach()
+- {
+- return 0;
+- }
++int JackNetOneDriver::Attach()
++{
++ return 0;
++}
+
+- int JackNetOneDriver::AllocPorts()
+- {
+- jack_port_id_t port_id;
+- char buf[64];
+- unsigned int chn;
+-
+- //if (netj.handle_transport_sync)
+- // jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
+-
+- for (chn = 0; chn < netj.capture_channels_audio; chn++) {
+- snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
+-
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
+- CaptureDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", buf );
+- return -1;
+- }
+- //port = fGraphManager->GetPort ( port_id );
++int JackNetOneDriver::Detach()
++{
++ return 0;
++}
+
+- netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id);
++int JackNetOneDriver::AllocPorts()
++{
++ jack_port_id_t port_index;
++ char buf[64];
++ unsigned int chn;
++
++ //if (netj.handle_transport_sync)
++ // jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
++
++ for (chn = 0; chn < netj.capture_channels_audio; chn++) {
++ snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
++
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
++ CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", buf);
++ return -1;
++ }
++ //port = fGraphManager->GetPort(port_index);
+
+- if( netj.bitdepth == CELT_MODE ) {
+- #if HAVE_CELT
+- #if HAVE_CELT_API_0_11
+- 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_custom( celt_mode, 1, NULL ) );
+- #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
+- 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, (void *)src_new(SRC_LINEAR, 1, NULL));
+- #endif
+- }
++ netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
++
++ if (netj.bitdepth == CELT_MODE) {
++#if HAVE_CELT
++#if HAVE_CELT_API_0_11
++ 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_custom(celt_mode, 1, NULL));
++#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
++ 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, (void *)src_new(SRC_LINEAR, 1, NULL));
++#endif
+ }
+- for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
+- snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
++ }
+
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
+- CaptureDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", buf );
+- return -1;
+- }
+- //port = fGraphManager->GetPort ( port_id );
++ for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
++ snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
+
+- netj.capture_ports =
+- jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id);
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
++ CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", buf);
++ return -1;
+ }
++ //port = fGraphManager->GetPort(port_index);
+
+- for (chn = 0; chn < netj.playback_channels_audio; chn++) {
+- snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
++ netj.capture_ports =
++ jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
++ }
+
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
+- PlaybackDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", buf );
+- return -1;
+- }
+- //port = fGraphManager->GetPort ( port_id );
++ for (chn = 0; chn < netj.playback_channels_audio; chn++) {
++ snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
+
+- netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id);
+- if( netj.bitdepth == CELT_MODE ) {
+- #if HAVE_CELT
+- #if HAVE_CELT_API_0_11
+- 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_custom( celt_mode, 1, NULL ) );
+- #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
+- 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, (void *)src_new(SRC_LINEAR, 1, NULL));
+- #endif
+- }
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
++ PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", buf);
++ return -1;
+ }
+- for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
+- snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
++ //port = fGraphManager->GetPort(port_index);
+
+- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
+- PlaybackDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT )
+- {
+- jack_error ( "driver: cannot register port for %s", buf );
+- return -1;
+- }
+- //port = fGraphManager->GetPort ( port_id );
++ netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
++ if (netj.bitdepth == CELT_MODE) {
++#if HAVE_CELT
++#if HAVE_CELT_API_0_11
++ 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_custom(celt_mode, 1, NULL));
++#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
++ 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, (void *)src_new(SRC_LINEAR, 1, NULL));
++#endif
++ }
++ }
++ for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
++ snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
+
+- netj.playback_ports =
+- jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id);
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
++ PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("driver: cannot register port for %s", buf);
++ return -1;
+ }
+- return 0;
++ //port = fGraphManager->GetPort(port_index);
++
++ netj.playback_ports =
++ jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
+ }
++ return 0;
++}
+
+ //init and restart--------------------------------------------------------------------
+- bool JackNetOneDriver::Initialize()
+- {
+- jack_log ( "JackNetOneDriver::Init()" );
+-
+- FreePorts();
+- netjack_release( &netj );
++bool JackNetOneDriver::Initialize()
++{
++ jack_log("JackNetOneDriver::Init");
+
+- //display some additional infos
+- jack_info ( "NetOne driver started" );
+- if( netjack_startup( &netj ) ) {
+- return false;
+- }
++ FreePorts();
++ netjack_release(&netj);
+
+- //register jack ports
+- if ( AllocPorts() != 0 )
+- {
+- jack_error ( "Can't allocate ports." );
+- return false;
+- }
++ //display some additional infos
++ jack_info("NetOne driver started");
++ if (netjack_startup(&netj)) {
++ return false;
++ }
+
+- //monitor
+- //driver parametering
+- JackAudioDriver::SetBufferSize ( netj.period_size );
+- JackAudioDriver::SetSampleRate ( netj.sample_rate );
+-
+- JackDriver::NotifyBufferSize ( netj.period_size );
+- JackDriver::NotifySampleRate ( netj.sample_rate );
+-
+- //transport engine parametering
+- fEngineControl->fTransport.SetNetworkSync ( true );
+- return true;
++ //register jack ports
++ if (AllocPorts() != 0) {
++ jack_error("Can't allocate ports.");
++ return false;
+ }
+
++ //monitor
++ //driver parametering
++ JackTimedDriver::SetBufferSize(netj.period_size);
++ JackTimedDriver::SetSampleRate(netj.sample_rate);
++
++ JackDriver::NotifyBufferSize(netj.period_size);
++ JackDriver::NotifySampleRate(netj.sample_rate);
++
++ //transport engine parametering
++ fEngineControl->fTransport.SetNetworkSync(true);
++ return true;
++}
++
+
+ //jack ports and buffers--------------------------------------------------------------
+
+ //driver processes--------------------------------------------------------------------
+- int JackNetOneDriver::Read()
+- {
+- int delay;
+- delay = netjack_wait( &netj );
+- if( delay ) {
+- NotifyXRun(fBeginDateUst, (float) delay);
+- jack_error( "netxruns... duration: %dms", delay/1000 );
+- }
+
+- if( (netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2 )
+- JackTools::ThrowJackNetException();
++int JackNetOneDriver::Read()
++{
++ int delay;
++ delay = netjack_wait(&netj);
++ if (delay) {
++ NotifyXRun(fBeginDateUst, (float) delay);
++ jack_error("netxruns... duration: %dms", delay / 1000);
++ }
+
+- //netjack_read( &netj, netj.period_size );
+- JackDriver::CycleTakeBeginTime();
++ if ((netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2)
++ JackTools::ThrowJackNetException();
+
+- jack_position_t local_trans_pos;
+- jack_transport_state_t local_trans_state;
++ //netjack_read(&netj, netj.period_size);
++ JackDriver::CycleTakeBeginTime();
+
+- unsigned int *packet_buf, *packet_bufX;
++ jack_position_t local_trans_pos;
++ jack_transport_state_t local_trans_state;
+
+- if( ! netj.packet_data_valid ) {
+- jack_log( "data not valid" );
+- render_payload_to_jack_ports (netj.bitdepth, NULL, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats );
+- return 0;
+- }
+- packet_buf = netj.rx_buf;
++ unsigned int *packet_buf, *packet_bufX;
+
+- jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
++ if (! netj.packet_data_valid) {
++ jack_log("data not valid");
++ render_payload_to_jack_ports (netj.bitdepth, NULL, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats);
++ return 0;
++ }
++ packet_buf = netj.rx_buf;
+
+- packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
++ jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
+
+- netj.reply_port = pkthdr->reply_port;
+- netj.latency = pkthdr->latency;
++ packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
+
+- // Special handling for latency=0
+- if( netj.latency == 0 )
+- netj.resync_threshold = 0;
+- else
+- netj.resync_threshold = MIN( 15, pkthdr->latency-1 );
+-
+- // check whether, we should handle the transport sync stuff, or leave trnasports untouched.
+- if (netj.handle_transport_sync) {
+- #if 1
+- unsigned int compensated_tranport_pos = (pkthdr->transport_frame + (pkthdr->latency * netj.period_size) + netj.codec_latency);
+-
+- // read local transport info....
+- //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
+-
+- local_trans_state = fEngineControl->fTransport.Query ( &local_trans_pos );
+-
+- // Now check if we have to start or stop local transport to sync to remote...
+- switch (pkthdr->transport_state) {
+-
+- case JackTransportStarting:
+- // the master transport is starting... so we set our reply to the sync_callback;
+- if (local_trans_state == JackTransportStopped) {
+- fEngineControl->fTransport.SetCommand ( TransportCommandStart );
+- //jack_transport_start(netj.client);
+- //last_transport_state = JackTransportStopped;
+- netj.sync_state = 0;
+- jack_info("locally stopped... starting...");
+- }
++ netj.reply_port = pkthdr->reply_port;
++ netj.latency = pkthdr->latency;
+
+- if (local_trans_pos.frame != compensated_tranport_pos) {
+- jack_position_t new_pos = local_trans_pos;
+- new_pos.frame = compensated_tranport_pos + 2*netj.period_size;
+- new_pos.valid = (jack_position_bits_t) 0;
++ // Special handling for latency=0
++ if (netj.latency == 0)
++ netj.resync_threshold = 0;
++ else
++ netj.resync_threshold = MIN(15, pkthdr->latency - 1);
++
++ // check whether, we should handle the transport sync stuff, or leave trnasports untouched.
++ if (netj.handle_transport_sync) {
++#if 1
++ unsigned int compensated_tranport_pos = (pkthdr->transport_frame + (pkthdr->latency * netj.period_size) + netj.codec_latency);
++
++ // read local transport info....
++ //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
++
++ local_trans_state = fEngineControl->fTransport.Query(&local_trans_pos);
++
++ // Now check if we have to start or stop local transport to sync to remote...
++ switch (pkthdr->transport_state) {
++
++ case JackTransportStarting:
++ // the master transport is starting... so we set our reply to the sync_callback;
++ if (local_trans_state == JackTransportStopped) {
++ fEngineControl->fTransport.SetCommand(TransportCommandStart);
++ //jack_transport_start(netj.client);
++ //last_transport_state = JackTransportStopped;
++ netj.sync_state = 0;
++ jack_info("locally stopped... starting...");
++ }
+
++ if (local_trans_pos.frame != compensated_tranport_pos) {
++ jack_position_t new_pos = local_trans_pos;
++ new_pos.frame = compensated_tranport_pos + 2 * netj.period_size;
++ new_pos.valid = (jack_position_bits_t) 0;
+
+- fEngineControl->fTransport.RequestNewPos ( &new_pos );
+- //jack_transport_locate(netj.client, compensated_tranport_pos);
+- //last_transport_state = JackTransportRolling;
+- netj.sync_state = 0;
+- jack_info("starting locate to %d", compensated_tranport_pos );
+- }
+- break;
+
+- case JackTransportStopped:
+- netj.sync_state = 1;
+- if (local_trans_pos.frame != (pkthdr->transport_frame)) {
+- jack_position_t new_pos = local_trans_pos;
+- new_pos.frame = pkthdr->transport_frame;
+- new_pos.valid = (jack_position_bits_t)0;
+- fEngineControl->fTransport.RequestNewPos ( &new_pos );
+- //jack_transport_locate(netj.client, (pkthdr->transport_frame));
+- jack_info("transport is stopped locate to %d", pkthdr->transport_frame);
+- }
+- if (local_trans_state != JackTransportStopped)
+- //jack_transport_stop(netj.client);
+- fEngineControl->fTransport.SetCommand ( TransportCommandStop );
+- break;
++ fEngineControl->fTransport.RequestNewPos(&new_pos);
++ //jack_transport_locate(netj.client, compensated_tranport_pos);
++ //last_transport_state = JackTransportRolling;
++ netj.sync_state = 0;
++ jack_info("starting locate to %d", compensated_tranport_pos);
++ }
++ break;
+
+- case JackTransportRolling:
+- netj.sync_state = 1;
+- // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) {
+- // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size));
+- // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size);
+- // }
+- if (local_trans_state != JackTransportRolling)
+- fEngineControl->fTransport.SetState ( JackTransportRolling );
+- break;
++ case JackTransportStopped:
++ netj.sync_state = 1;
++ if (local_trans_pos.frame != (pkthdr->transport_frame)) {
++ jack_position_t new_pos = local_trans_pos;
++ new_pos.frame = pkthdr->transport_frame;
++ new_pos.valid = (jack_position_bits_t)0;
++ fEngineControl->fTransport.RequestNewPos(&new_pos);
++ //jack_transport_locate(netj.client, (pkthdr->transport_frame));
++ jack_info("transport is stopped locate to %d", pkthdr->transport_frame);
++ }
++ if (local_trans_state != JackTransportStopped)
++ //jack_transport_stop(netj.client);
++ fEngineControl->fTransport.SetCommand(TransportCommandStop);
++ break;
++
++ case JackTransportRolling:
++ netj.sync_state = 1;
++ // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) {
++ // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size));
++ // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size);
++ // }
++ if (local_trans_state != JackTransportRolling)
++ fEngineControl->fTransport.SetState(JackTransportRolling);
++ break;
+
+- case JackTransportLooping:
+- break;
+- }
+-#endif
++ case JackTransportLooping:
++ break;
+ }
+-
+- render_payload_to_jack_ports (netj.bitdepth, packet_bufX, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats );
+- packet_cache_release_packet(netj.packcache, netj.expected_framecnt );
+- return 0;
++#endif
+ }
+
+- int JackNetOneDriver::Write()
+- {
+- int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0 );
+- uint32_t *packet_buf, *packet_bufX;
++ render_payload_to_jack_ports (netj.bitdepth, packet_bufX, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats);
++ packet_cache_release_packet(netj.packcache, netj.expected_framecnt);
++ return 0;
++}
+
+- int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header);
+- jacknet_packet_header *pkthdr;
++int JackNetOneDriver::Write()
++{
++ int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0);
++ uint32_t *packet_buf, *packet_bufX;
+
+- packet_buf = (uint32_t *) alloca(packet_size);
+- pkthdr = (jacknet_packet_header *)packet_buf;
++ int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header);
++ jacknet_packet_header *pkthdr;
+
+- if( netj.running_free ) {
+- return 0;
+- }
++ packet_buf = (uint32_t *) alloca(packet_size);
++ pkthdr = (jacknet_packet_header *)packet_buf;
+
+- // offset packet_bufX by the packetheader.
+- packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
++ if (netj.running_free) {
++ return 0;
++ }
+
+- pkthdr->sync_state = syncstate;;
+- pkthdr->latency = netj.time_to_deadline;
+- //printf( "time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness );
+- pkthdr->framecnt = netj.expected_framecnt;
+-
+- render_jack_ports_to_payload(netj.bitdepth, netj.playback_ports, netj.playback_srcs, netj.period_size, packet_bufX, netj.net_period_up, netj.dont_htonl_floats );
+-
+- packet_header_hton(pkthdr);
+- if (netj.srcaddress_valid)
+- {
+- unsigned int r;
+- static const int flag = 0;
++ // offset packet_bufX by the packetheader.
++ packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
+
+- if (netj.reply_port)
++ pkthdr->sync_state = syncstate;;
++ pkthdr->latency = netj.time_to_deadline;
++ //printf("time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness);
++ pkthdr->framecnt = netj.expected_framecnt;
++
++ render_jack_ports_to_payload(netj.bitdepth, netj.playback_ports, netj.playback_srcs, netj.period_size, packet_bufX, netj.net_period_up, netj.dont_htonl_floats);
++
++ packet_header_hton(pkthdr);
++ if (netj.srcaddress_valid) {
++ unsigned int r;
++ static const int flag = 0;
++
++ if (netj.reply_port)
+ netj.syncsource_address.sin_port = htons(netj.reply_port);
+
+- for( r=0; r<netj.redundancy; r++ )
++ for (r = 0; r < netj.redundancy; r++)
+ netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size,
+- flag, (struct sockaddr*)&(netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu);
+- }
+- return 0;
++ flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu);
+ }
++ return 0;
++}
+
+- void
+- JackNetOneDriver::FreePorts ()
+- {
+- JSList *node = netj.capture_ports;
+-
+- while( node != NULL ) {
+- JSList *this_node = node;
+- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
+- node = jack_slist_remove_link( node, this_node );
+- jack_slist_free_1( this_node );
+- fGraphManager->ReleasePort( fClientControl.fRefNum, port_id );
+- }
+- netj.capture_ports = NULL;
++void
++JackNetOneDriver::FreePorts ()
++{
++ JSList *node = netj.capture_ports;
+
+- node = netj.playback_ports;
+- while( node != NULL ) {
+- JSList *this_node = node;
+- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
+- node = jack_slist_remove_link( node, this_node );
+- jack_slist_free_1( this_node );
+- fGraphManager->ReleasePort( fClientControl.fRefNum, port_id );
+- }
+- netj.playback_ports = NULL;
++ while (node != NULL) {
++ JSList *this_node = node;
++ jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
++ node = jack_slist_remove_link(node, this_node);
++ jack_slist_free_1(this_node);
++ fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
++ }
++ netj.capture_ports = NULL;
++
++ node = netj.playback_ports;
++ while (node != NULL) {
++ JSList *this_node = node;
++ jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
++ node = jack_slist_remove_link(node, this_node);
++ jack_slist_free_1(this_node);
++ fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
++ }
++ netj.playback_ports = NULL;
+
+- if( netj.bitdepth == CELT_MODE ) {
+- #if HAVE_CELT
++ if (netj.bitdepth == CELT_MODE) {
++#if HAVE_CELT
+ node = netj.playback_srcs;
+- while( node != NULL ) {
++ while (node != NULL) {
+ JSList *this_node = node;
+ CELTEncoder *enc = (CELTEncoder *) node->data;
+- node = jack_slist_remove_link( node, this_node );
+- jack_slist_free_1( this_node );
+- celt_encoder_destroy( enc );
++ node = jack_slist_remove_link(node, this_node);
++ jack_slist_free_1(this_node);
++ celt_encoder_destroy(enc);
+ }
+ netj.playback_srcs = NULL;
+
+ node = netj.capture_srcs;
+- while( node != NULL ) {
++ while (node != NULL) {
+ JSList *this_node = node;
+ CELTDecoder *dec = (CELTDecoder *) node->data;
+- node = jack_slist_remove_link( node, this_node );
+- jack_slist_free_1( this_node );
+- celt_decoder_destroy( dec );
++ node = jack_slist_remove_link(node, this_node);
++ jack_slist_free_1(this_node);
++ celt_decoder_destroy(dec);
+ }
+ netj.capture_srcs = NULL;
+- #endif
+- } else {
+- #if HAVE_SAMPLERATE
++#endif
++ } else {
++#if HAVE_SAMPLERATE
+ node = netj.playback_srcs;
+- while( node != NULL ) {
++ while (node != NULL) {
+ JSList *this_node = node;
+ SRC_STATE *state = (SRC_STATE *) node->data;
+- node = jack_slist_remove_link( node, this_node );
+- jack_slist_free_1( this_node );
+- src_delete( state );
++ node = jack_slist_remove_link(node, this_node);
++ jack_slist_free_1(this_node);
++ src_delete(state);
+ }
+ netj.playback_srcs = NULL;
+
+ node = netj.capture_srcs;
+- while( node != NULL ) {
++ while (node != NULL) {
+ JSList *this_node = node;
+ SRC_STATE *state = (SRC_STATE *) node->data;
+- node = jack_slist_remove_link( node, this_node );
+- jack_slist_free_1( this_node );
+- src_delete( state );
++ node = jack_slist_remove_link(node, this_node);
++ jack_slist_free_1(this_node);
++ src_delete(state);
+ }
+ netj.capture_srcs = NULL;
+- #endif
+- }
++#endif
+ }
++}
+
+ //Render functions--------------------------------------------------------------------
+
+ // render functions for float
+- void
+- JackNetOneDriver::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)
+- {
+- uint32_t chn = 0;
+- JSList *node = capture_ports;
+- #if HAVE_SAMPLERATE
+- JSList *src_node = capture_srcs;
+- #endif
+-
+- uint32_t *packet_bufX = (uint32_t *)packet_payload;
+-
+- if( !packet_payload )
+- return;
+-
+- while (node != NULL)
+- {
+- unsigned int i;
+- int_float_t val;
+- #if HAVE_SAMPLERATE
+- SRC_DATA src;
+- #endif
+- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
+- JackPort *port = fGraphManager->GetPort( port_id );
+-
+- jack_default_audio_sample_t* buf =
+- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
++void
++JackNetOneDriver::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)
++{
++ uint32_t chn = 0;
++ JSList *node = capture_ports;
++#if HAVE_SAMPLERATE
++ JSList *src_node = capture_srcs;
++#endif
+
+- const char *porttype = port->GetType();
++ uint32_t *packet_bufX = (uint32_t *)packet_payload;
+
+- if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0)
+- {
+- #if HAVE_SAMPLERATE
+- // audio port, resample if necessary
+- if (net_period_down != nframes)
+- {
+- SRC_STATE *src_state = (SRC_STATE *)src_node->data;
+- for (i = 0; i < net_period_down; i++)
+- {
+- packet_bufX[i] = ntohl (packet_bufX[i]);
+- }
++ if (!packet_payload)
++ return;
+
+- src.data_in = (float *) packet_bufX;
+- src.input_frames = net_period_down;
++ while (node != NULL) {
++ unsigned int i;
++ int_float_t val;
++#if HAVE_SAMPLERATE
++ SRC_DATA src;
++#endif
++ jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
++ JackPort *port = fGraphManager->GetPort(port_index);
+
+- src.data_out = buf;
+- src.output_frames = nframes;
++ jack_default_audio_sample_t* buf =
++ (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
+
+- src.src_ratio = (float) nframes / (float) net_period_down;
+- src.end_of_input = 0;
++ const char *porttype = port->GetType();
+
+- src_set_ratio (src_state, src.src_ratio);
+- src_process (src_state, &src);
+- src_node = jack_slist_next (src_node);
+- }
+- else
+- #endif
+- {
+- if( dont_htonl_floats )
+- {
+- memcpy( buf, packet_bufX, net_period_down*sizeof(jack_default_audio_sample_t));
+- }
+- else
+- {
+- for (i = 0; i < net_period_down; i++)
+- {
+- val.i = packet_bufX[i];
+- val.i = ntohl (val.i);
+- buf[i] = val.f;
+- }
+- }
++ if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
++#if HAVE_SAMPLERATE
++ // audio port, resample if necessary
++ if (net_period_down != nframes) {
++ SRC_STATE *src_state = (SRC_STATE *)src_node->data;
++ for (i = 0; i < net_period_down; i++) {
++ packet_bufX[i] = ntohl (packet_bufX[i]);
+ }
+- }
+- else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0)
+- {
+- // midi port, decode midi events
+- // convert the data buffer to a standard format (uint32_t based)
+- unsigned int buffer_size_uint32 = net_period_down;
+- uint32_t * buffer_uint32 = (uint32_t*)packet_bufX;
+- decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
+- }
+- packet_bufX = (packet_bufX + net_period_down);
+- node = jack_slist_next (node);
+- chn++;
+- }
+-}
+
+- void
+- JackNetOneDriver::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 )
+- {
+- uint32_t chn = 0;
+- JSList *node = playback_ports;
+- #if HAVE_SAMPLERATE
+- JSList *src_node = playback_srcs;
+- #endif
+-
+- uint32_t *packet_bufX = (uint32_t *) packet_payload;
+-
+- while (node != NULL)
+- {
+- #if HAVE_SAMPLERATE
+- SRC_DATA src;
+- #endif
+- unsigned int i;
+- int_float_t val;
+- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
+- JackPort *port = fGraphManager->GetPort( port_id );
++ src.data_in = (float *) packet_bufX;
++ src.input_frames = net_period_down;
+
+- jack_default_audio_sample_t* buf =
+- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
++ src.data_out = buf;
++ src.output_frames = nframes;
+
+- const char *porttype = port->GetType();
++ src.src_ratio = (float) nframes / (float) net_period_down;
++ src.end_of_input = 0;
+
+- if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0)
++ src_set_ratio (src_state, src.src_ratio);
++ src_process (src_state, &src);
++ src_node = jack_slist_next (src_node);
++ } else
++#endif
+ {
+- // audio port, resample if necessary
+-
+- #if HAVE_SAMPLERATE
+- if (net_period_up != nframes) {
+- SRC_STATE *src_state = (SRC_STATE *) src_node->data;
+- src.data_in = buf;
+- src.input_frames = nframes;
+-
+- src.data_out = (float *) packet_bufX;
+- src.output_frames = net_period_up;
+-
+- src.src_ratio = (float) net_period_up / (float) nframes;
+- src.end_of_input = 0;
+-
+- src_set_ratio (src_state, src.src_ratio);
+- src_process (src_state, &src);
+-
+- for (i = 0; i < net_period_up; i++)
+- {
+- packet_bufX[i] = htonl (packet_bufX[i]);
+- }
+- src_node = jack_slist_next (src_node);
+- }
+- else
+- #endif
+- {
+- if( dont_htonl_floats )
+- {
+- memcpy( packet_bufX, buf, net_period_up*sizeof(jack_default_audio_sample_t) );
+- }
+- else
+- {
+- for (i = 0; i < net_period_up; i++)
+- {
+- val.f = buf[i];
+- val.i = htonl (val.i);
+- packet_bufX[i] = val.i;
+- }
++ if (dont_htonl_floats) {
++ memcpy(buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t));
++ } else {
++ for (i = 0; i < net_period_down; i++) {
++ val.i = packet_bufX[i];
++ val.i = ntohl (val.i);
++ buf[i] = val.f;
+ }
+ }
+ }
+- else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0)
+- {
+- // encode midi events from port to packet
+- // convert the data buffer to a standard format (uint32_t based)
+- unsigned int buffer_size_uint32 = net_period_up;
+- uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
+- encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
+- }
+- packet_bufX = (packet_bufX + net_period_up);
+- node = jack_slist_next (node);
+- chn++;
+- }
++ } else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
++ // midi port, decode midi events
++ // convert the data buffer to a standard format (uint32_t based)
++ unsigned int buffer_size_uint32 = net_period_down;
++ uint32_t * buffer_uint32 = (uint32_t*)packet_bufX;
++ decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
++ }
++ packet_bufX = (packet_bufX + net_period_down);
++ node = jack_slist_next (node);
++ chn++;
+ }
++}
+
+- #if HAVE_CELT
+- // render functions for celt.
+- void
+- JackNetOneDriver::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)
+- {
+- uint32_t chn = 0;
+- JSList *node = capture_ports;
+- JSList *src_node = capture_srcs;
+- unsigned char *packet_bufX = (unsigned char *)packet_payload;
+-
+- while (node != NULL)
+- {
+- jack_port_id_t port_id = (jack_port_id_t) (intptr_t)node->data;
+- JackPort *port = fGraphManager->GetPort( port_id );
++void
++JackNetOneDriver::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)
++{
++ uint32_t chn = 0;
++ JSList *node = playback_ports;
++#if HAVE_SAMPLERATE
++ JSList *src_node = playback_srcs;
++#endif
++
++ uint32_t *packet_bufX = (uint32_t *) packet_payload;
++
++ while (node != NULL) {
++#if HAVE_SAMPLERATE
++ SRC_DATA src;
++#endif
++ unsigned int i;
++ int_float_t val;
++ jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
++ JackPort *port = fGraphManager->GetPort(port_index);
+
+- jack_default_audio_sample_t* buf =
+- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
++ jack_default_audio_sample_t* buf =
++ (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
+
+- const char *portname = port->GetType();
++ const char *porttype = port->GetType();
+
+- if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0)
+- {
+- // audio port, decode celt data.
+- CELTDecoder *decoder = (CELTDecoder *)src_node->data;
++ if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
++ // audio port, resample if necessary
++
++#if HAVE_SAMPLERATE
++ if (net_period_up != nframes) {
++ SRC_STATE *src_state = (SRC_STATE *) src_node->data;
++ src.data_in = buf;
++ src.input_frames = nframes;
++
++ src.data_out = (float *) packet_bufX;
++ src.output_frames = net_period_up;
++
++ src.src_ratio = (float) net_period_up / (float) nframes;
++ src.end_of_input = 0;
+
+- #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
+- if( !packet_payload )
+- celt_decode_float( decoder, NULL, net_period_down, buf, nframes );
+- else
+- celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes );
+- #else
+- if( !packet_payload )
+- celt_decode_float( decoder, NULL, net_period_down, buf );
+- else
+- celt_decode_float( decoder, packet_bufX, net_period_down, buf );
+- #endif
++ src_set_ratio (src_state, src.src_ratio);
++ src_process (src_state, &src);
+
++ for (i = 0; i < net_period_up; i++) {
++ packet_bufX[i] = htonl (packet_bufX[i]);
++ }
+ src_node = jack_slist_next (src_node);
+- }
+- else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0)
++ } else
++#endif
+ {
+- // midi port, decode midi events
+- // convert the data buffer to a standard format (uint32_t based)
+- unsigned int buffer_size_uint32 = net_period_down / 2;
+- uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
+- if( packet_payload )
+- decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
++ if (dont_htonl_floats) {
++ memcpy(packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t));
++ } else {
++ for (i = 0; i < net_period_up; i++) {
++ val.f = buf[i];
++ val.i = htonl (val.i);
++ packet_bufX[i] = val.i;
++ }
++ }
+ }
+- packet_bufX = (packet_bufX + net_period_down);
+- node = jack_slist_next (node);
+- chn++;
++ } else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
++ // encode midi events from port to packet
++ // convert the data buffer to a standard format (uint32_t based)
++ unsigned int buffer_size_uint32 = net_period_up;
++ uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
++ encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
++ }
++ packet_bufX = (packet_bufX + net_period_up);
++ node = jack_slist_next (node);
++ chn++;
++ }
++}
++
++#if HAVE_CELT
++// render functions for celt.
++void
++JackNetOneDriver::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)
++{
++ uint32_t chn = 0;
++ JSList *node = capture_ports;
++ JSList *src_node = capture_srcs;
++ unsigned char *packet_bufX = (unsigned char *)packet_payload;
++
++ while (node != NULL) {
++ jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data;
++ JackPort *port = fGraphManager->GetPort(port_index);
++
++ jack_default_audio_sample_t* buf =
++ (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
++
++ const char *portname = port->GetType();
++
++ if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
++ // audio port, decode celt data.
++ CELTDecoder *decoder = (CELTDecoder *)src_node->data;
++
++#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
++ if (!packet_payload)
++ celt_decode_float(decoder, NULL, net_period_down, buf, nframes);
++ else
++ celt_decode_float(decoder, packet_bufX, net_period_down, buf, nframes);
++#else
++ if (!packet_payload)
++ celt_decode_float(decoder, NULL, net_period_down, buf);
++ else
++ celt_decode_float(decoder, packet_bufX, net_period_down, buf);
++#endif
++
++ src_node = jack_slist_next (src_node);
++ } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
++ // midi port, decode midi events
++ // convert the data buffer to a standard format (uint32_t based)
++ unsigned int buffer_size_uint32 = net_period_down / 2;
++ uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
++ if (packet_payload)
++ decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
+ }
++ packet_bufX = (packet_bufX + net_period_down);
++ node = jack_slist_next (node);
++ chn++;
+ }
++}
+
+- void
+- JackNetOneDriver::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)
+- {
+- uint32_t chn = 0;
+- JSList *node = playback_ports;
+- JSList *src_node = playback_srcs;
++void
++JackNetOneDriver::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)
++{
++ uint32_t chn = 0;
++ JSList *node = playback_ports;
++ JSList *src_node = playback_srcs;
+
+- unsigned char *packet_bufX = (unsigned char *)packet_payload;
++ unsigned char *packet_bufX = (unsigned char *)packet_payload;
+
+- while (node != NULL)
+- {
+- jack_port_id_t port_id = (jack_port_id_t) (intptr_t) node->data;
+- JackPort *port = fGraphManager->GetPort( port_id );
++ while (node != NULL) {
++ jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data;
++ JackPort *port = fGraphManager->GetPort(port_index);
+
+- jack_default_audio_sample_t* buf =
+- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
++ jack_default_audio_sample_t* buf =
++ (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
+
+- const char *portname = port->GetType();
++ const char *portname = port->GetType();
+
+- if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0)
+- {
+- // audio port, encode celt data.
++ if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
++ // audio port, encode celt data.
+
+ int encoded_bytes;
+- jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes );
+- memcpy( floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t) );
++ jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes);
++ memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t));
+ CELTEncoder *encoder = (CELTEncoder *)src_node->data;
+- #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
+- encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up );
++#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
++ encoded_bytes = celt_encode_float(encoder, floatbuf, nframes, packet_bufX, net_period_up);
+ #else
+- encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up );
++ encoded_bytes = celt_encode_float(encoder, floatbuf, NULL, packet_bufX, net_period_up);
+ #endif
+- if( encoded_bytes != (int)net_period_up )
+- jack_error( "something in celt changed. netjack needs to be changed to handle this." );
+- src_node = jack_slist_next( src_node );
+- }
+- else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0)
+- {
+- // encode midi events from port to packet
+- // convert the data buffer to a standard format (uint32_t based)
+- unsigned int buffer_size_uint32 = net_period_up / 2;
+- uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
+- encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
+- }
+- packet_bufX = (packet_bufX + net_period_up);
+- node = jack_slist_next (node);
+- chn++;
+- }
++ if (encoded_bytes != (int)net_period_up)
++ jack_error("something in celt changed. netjack needs to be changed to handle this.");
++ src_node = jack_slist_next(src_node);
++ } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
++ // encode midi events from port to packet
++ // convert the data buffer to a standard format (uint32_t based)
++ unsigned int buffer_size_uint32 = net_period_up / 2;
++ uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
++ encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
++ }
++ packet_bufX = (packet_bufX + net_period_up);
++ node = jack_slist_next (node);
++ chn++;
+ }
++}
+
+- #endif
+- /* Wrapper functions with bitdepth argument... */
+- void
+- JackNetOneDriver::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)
+- {
+- #if HAVE_CELT
+- if (bitdepth == CELT_MODE)
+- render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
+- else
+- #endif
+- render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats);
+- }
++#endif
++/* Wrapper functions with bitdepth argument... */
++void
++JackNetOneDriver::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)
++{
++#if HAVE_CELT
++ if (bitdepth == CELT_MODE)
++ render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
++ else
++#endif
++ render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats);
++}
+
+- void
+- JackNetOneDriver::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)
++void
++JackNetOneDriver::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)
++{
++#if HAVE_CELT
++ if (bitdepth == CELT_MODE)
++ render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
++ else
++#endif
++ render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats);
++}
++
++//driver loader-----------------------------------------------------------------------
++
++#ifdef __cplusplus
++extern "C"
++{
++#endif
++ SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
+ {
+- #if HAVE_CELT
+- if (bitdepth == CELT_MODE)
+- render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
+- else
+- #endif
+- render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats);
+- }
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
+
+- //driver loader-----------------------------------------------------------------------
++ desc = jack_driver_descriptor_construct("netone", JackDriverMaster, "netjack one slave backend component", &filler);
+
+- #ifdef __cplusplus
+- extern "C"
+- {
+- #endif
+- SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
+- {
+- jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
+- jack_driver_param_desc_t * params;
+-
+- strcpy ( desc->name, "netone" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy ( desc->desc, "netjack one slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 18;
+- params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
+-
+- int i = 0;
+- strcpy (params[i].name, "audio-ins");
+- params[i].character = 'i';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 2U;
+- strcpy (params[i].short_desc, "Number of capture channels (defaults to 2)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "audio-outs");
+- params[i].character = 'o';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 2U;
+- strcpy (params[i].short_desc, "Number of playback channels (defaults to 2)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "midi-ins");
+- params[i].character = 'I';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1U;
+- strcpy (params[i].short_desc, "Number of midi capture channels (defaults to 1)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "midi-outs");
+- params[i].character = 'O';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1U;
+- strcpy (params[i].short_desc, "Number of midi playback channels (defaults to 1)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "rate");
+- params[i].character = 'r';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 48000U;
+- strcpy (params[i].short_desc, "Sample rate");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "period");
+- params[i].character = 'p';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1024U;
+- strcpy (params[i].short_desc, "Frames per period");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "num-periods");
+- params[i].character = 'n';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 5U;
+- strcpy (params[i].short_desc,
+- "Network latency setting in no. of periods");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "listen-port");
+- params[i].character = 'l';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 3000U;
+- strcpy (params[i].short_desc,
+- "The socket port we are listening on for sync packets");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "factor");
+- params[i].character = 'f';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1U;
+- strcpy (params[i].short_desc,
+- "Factor for sample rate reduction");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "upstream-factor");
+- params[i].character = 'u';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0U;
+- strcpy (params[i].short_desc,
+- "Factor for sample rate reduction on the upstream");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "celt");
+- params[i].character = 'c';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0U;
+- strcpy (params[i].short_desc,
+- "sets celt encoding and number of kbits per channel");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "bit-depth");
+- params[i].character = 'b';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0U;
+- strcpy (params[i].short_desc,
+- "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "transport-sync");
+- params[i].character = 't';
+- params[i].type = JackDriverParamBool;
+- params[i].value.ui = 1U;
+- strcpy (params[i].short_desc,
+- "Whether to slave the transport to the master transport");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "autoconf");
+- params[i].character = 'a';
+- params[i].type = JackDriverParamBool;
+- params[i].value.ui = 1U;
+- strcpy (params[i].short_desc,
+- "Whether to use Autoconfig, or just start.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "redundancy");
+- params[i].character = 'R';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1U;
+- strcpy (params[i].short_desc,
+- "Send packets N times");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "native-endian");
+- params[i].character = 'e';
+- params[i].type = JackDriverParamBool;
+- params[i].value.ui = 0U;
+- strcpy (params[i].short_desc,
+- "Dont convert samples to network byte order.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "jitterval");
+- params[i].character = 'J';
+- params[i].type = JackDriverParamInt;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc,
+- "attempted jitterbuffer microseconds on master");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "always-deadline");
+- params[i].character = 'D';
+- params[i].type = JackDriverParamBool;
+- params[i].value.ui = 0U;
+- strcpy (params[i].short_desc,
+- "always use deadline");
+- strcpy (params[i].long_desc, params[i].short_desc);
++ value.ui = 2U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 2)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 2)", NULL);
+
+- desc->params = params;
++ value.ui = 1U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "midi-ins", 'I', JackDriverParamUInt, &value, NULL, "Number of midi capture channels (defaults to 1)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "midi-outs", 'O', JackDriverParamUInt, &value, NULL, "Number of midi playback channels (defaults to 1)", NULL);
+
+- return desc;
+- }
++ value.ui = 48000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
+
+- SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
+- {
+- jack_nframes_t sample_rate = 48000;
+- jack_nframes_t resample_factor = 1;
+- jack_nframes_t period_size = 1024;
+- unsigned int capture_ports = 2;
+- unsigned int playback_ports = 2;
+- unsigned int capture_ports_midi = 1;
+- unsigned int playback_ports_midi = 1;
+- unsigned int listen_port = 3000;
+- unsigned int bitdepth = 0;
+- unsigned int handle_transport_sync = 1;
+- unsigned int use_autoconfig = 1;
+- unsigned int latency = 5;
+- unsigned int redundancy = 1;
+- unsigned int mtu = 1400;
+- #if HAVE_SAMPLERATE
+- unsigned int resample_factor_up = 1;
+- #endif
+- int dont_htonl_floats = 0;
+- int always_deadline = 0;
+- int jitter_val = 0;
+- const JSList * node;
+- const jack_driver_param_t * param;
+-
+- for ( node = params; node; node = jack_slist_next ( node ) )
+- {
+- param = ( const jack_driver_param_t* ) node->data;
+- switch ( param->character )
+- {
++ value.ui = 1024U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = 5U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
++
++ value.ui = 3000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "listen-port", 'l', JackDriverParamUInt, &value, NULL, "The socket port we are listening on for sync packets", NULL);
++
++ value.ui = 1U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "factor", 'f', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction", NULL);
++
++ value.ui = 0U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "upstream-factor", 'u', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction on the upstream", NULL);
++
++#if HAVE_CELT
++ value.ui = 0U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamUInt, &value, NULL, "Set CELT encoding and number of kbits per channel", NULL);
++#endif
++ value.ui = 0U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "bit-depth", 'b', JackDriverParamUInt, &value, NULL, "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)", NULL);
++
++ value.i = true;
++ jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamBool, &value, NULL, "Whether to slave the transport to the master transport", NULL);
++
++ value.ui = true;
++ jack_driver_descriptor_add_parameter(desc, &filler, "autoconf", 'a', JackDriverParamBool, &value, NULL, "Whether to use Autoconfig, or just start", NULL);
++
++ value.ui = 1U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "redundancy", 'R', JackDriverParamUInt, &value, NULL, "Send packets N times", NULL);
++
++ value.ui = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "native-endian", 'e', JackDriverParamBool, &value, NULL, "Dont convert samples to network byte order", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "jitterval", 'J', JackDriverParamInt, &value, NULL, "Attempted jitterbuffer microseconds on master", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "always-deadline", 'D', JackDriverParamBool, &value, NULL, "Always use deadline", NULL);
++
++ return desc;
++ }
++
++ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
++ {
++ jack_nframes_t sample_rate = 48000;
++ jack_nframes_t resample_factor = 1;
++ jack_nframes_t period_size = 1024;
++ unsigned int capture_ports = 2;
++ unsigned int playback_ports = 2;
++ unsigned int capture_ports_midi = 1;
++ unsigned int playback_ports_midi = 1;
++ unsigned int listen_port = 3000;
++ unsigned int bitdepth = 0;
++ unsigned int handle_transport_sync = 1;
++ unsigned int use_autoconfig = 1;
++ unsigned int latency = 5;
++ unsigned int redundancy = 1;
++ unsigned int mtu = 1400;
++#if HAVE_SAMPLERATE
++ unsigned int resample_factor_up = 1;
++#endif
++ int dont_htonl_floats = 0;
++ int always_deadline = 0;
++ int jitter_val = 0;
++ const JSList * node;
++ const jack_driver_param_t * param;
++
++ for (node = params; node; node = jack_slist_next(node)) {
++ param = (const jack_driver_param_t*) node->data;
++ switch (param->character) {
+ case 'i':
+ capture_ports = param->value.ui;
+ break;
+@@ -1042,21 +872,21 @@
+ break;
+
+ case 'f':
+- #if HAVE_SAMPLERATE
++#if HAVE_SAMPLERATE
+ resample_factor = param->value.ui;
+- #else
+- jack_error( "not built with libsamplerate support" );
++#else
++ jack_error("not built with libsamplerate support");
+ return NULL;
+- #endif
++#endif
+ break;
+
+ case 'u':
+- #if HAVE_SAMPLERATE
++#if HAVE_SAMPLERATE
+ resample_factor_up = param->value.ui;
+- #else
+- jack_error( "not built with libsamplerate support" );
++#else
++ jack_error("not built with libsamplerate support");
+ return NULL;
+- #endif
++#endif
+ break;
+
+ case 'b':
+@@ -1064,13 +894,13 @@
+ break;
+
+ case 'c':
+- #if HAVE_CELT
++#if HAVE_CELT
+ bitdepth = CELT_MODE;
+ resample_factor = param->value.ui;
+- #else
+- jack_error( "not built with celt support" );
++#else
++ jack_error("not built with celt support");
+ return NULL;
+- #endif
++#endif
+ break;
+
+ case 't':
+@@ -1100,38 +930,31 @@
+ case 'D':
+ always_deadline = param->value.ui;
+ break;
+- }
+- }
+-
+- try
+- {
+- Jack::JackDriverClientInterface* driver =
+- new Jack::JackWaitThreadedDriver (
+- new Jack::JackNetOneDriver ( "system", "net_pcm", engine, table, listen_port, mtu,
+- capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
+- sample_rate, period_size, resample_factor,
+- "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
+- dont_htonl_floats, always_deadline, jitter_val ) );
+-
+- if ( driver->Open ( period_size, sample_rate, 1, 1, capture_ports, playback_ports,
+- 0, "from_master_", "to_master_", 0, 0 ) == 0 )
+- {
+- return driver;
+- }
+- else
+- {
+- delete driver;
+- return NULL;
+- }
++ }
++ }
+
+- }
+- catch ( ... )
+- {
+- return NULL;
+- }
++ try {
++ Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
++ new Jack::JackNetOneDriver("system", "net_pcm", engine, table, listen_port, mtu,
++ capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
++ sample_rate, period_size, resample_factor,
++ "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
++ dont_htonl_floats, always_deadline, jitter_val));
++
++ if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports,
++ 0, "from_master_", "to_master_", 0, 0) == 0) {
++ return driver;
++ } else {
++ delete driver;
++ return NULL;
+ }
+
+- #ifdef __cplusplus
++ } catch (...) {
++ return NULL;
+ }
+- #endif
++ }
++
++#ifdef __cplusplus
++}
++#endif
+ }
+--- a/common/JackNetOneDriver.h
++++ b/common/JackNetOneDriver.h
+@@ -1,6 +1,5 @@
+ /*
+-Copyright (C) 2001 Paul Davis
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 Torben Horn
+
+ 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
+@@ -21,78 +20,75 @@
+ #ifndef __JackNetDriver__
+ #define __JackNetDriver__
+
+-#include "JackAudioDriver.h"
++#include "JackTimedDriver.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;
+- }
++/**
++\Brief This class describes the Net Backend
++*/
++
++class JackNetOneDriver : public JackWaiterDriver
++{
++ 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 );
++#if 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);
++ virtual ~JackNetOneDriver();
++
++ 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
+--- a/common/JackNetSocket.h
++++ b/common/JackNetSocket.h
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+--- a/common/JackNetTool.cpp
++++ b/common/JackNetTool.cpp
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -19,22 +19,92 @@
+
+ #include "JackNetTool.h"
+
++#ifdef __APPLE__
++
++#include <mach/mach_time.h>
++
++class HardwareClock
++{
++ public:
++
++ HardwareClock();
++
++ void Reset();
++ void Update();
++
++ float GetDeltaTime() const;
++ double GetTime() const;
++
++ private:
++
++ double m_clockToSeconds;
++
++ uint64_t m_startAbsTime;
++ uint64_t m_lastAbsTime;
++
++ double m_time;
++ float m_deltaTime;
++};
++
++HardwareClock::HardwareClock()
++{
++ mach_timebase_info_data_t info;
++ mach_timebase_info(&info);
++ m_clockToSeconds = (double)info.numer/info.denom/1000000000.0;
++ Reset();
++}
++
++void HardwareClock::Reset()
++{
++ m_startAbsTime = mach_absolute_time();
++ m_lastAbsTime = m_startAbsTime;
++ m_time = m_startAbsTime*m_clockToSeconds;
++ m_deltaTime = 1.0f/60.0f;
++}
++
++void HardwareClock::Update()
++{
++ const uint64_t currentTime = mach_absolute_time();
++ const uint64_t dt = currentTime - m_lastAbsTime;
++
++ m_time = currentTime*m_clockToSeconds;
++ m_deltaTime = (double)dt*m_clockToSeconds;
++ m_lastAbsTime = currentTime;
++}
++
++float HardwareClock::GetDeltaTime() const
++{
++ return m_deltaTime;
++}
++
++double HardwareClock::GetTime() const
++{
++ return m_time;
++}
++
++#endif
++
+ using namespace std;
+
+ namespace Jack
+ {
+ // NetMidiBuffer**********************************************************************************
+
+- NetMidiBuffer::NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer )
++ NetMidiBuffer::NetMidiBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
+ {
+ fNPorts = nports;
+- fMaxBufsize = fNPorts * sizeof ( sample_t ) * params->fPeriodSize ;
+- fMaxPcktSize = params->fMtu - sizeof ( packet_header_t );
++ fMaxBufsize = fNPorts * sizeof(sample_t) * params->fPeriodSize ;
++ fMaxPcktSize = params->fMtu - sizeof(packet_header_t);
+ fBuffer = new char[fMaxBufsize];
+ fPortBuffer = new JackMidiBuffer* [fNPorts];
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
+ fPortBuffer[port_index] = NULL;
++ }
+ fNetBuffer = net_buffer;
++
++ fCycleBytesSize = params->fMtu
++ * (max(params->fSendMidiChannels, params->fReturnMidiChannels)
++ * params->fPeriodSize * sizeof(sample_t) / (params->fMtu - sizeof(packet_header_t)));
+ }
+
+ NetMidiBuffer::~NetMidiBuffer()
+@@ -43,30 +113,38 @@
+ delete[] fPortBuffer;
+ }
+
+- size_t NetMidiBuffer::GetSize()
++ size_t NetMidiBuffer::GetCycleSize()
++ {
++ return fCycleBytesSize;
++ }
++
++ int NetMidiBuffer::GetNumPackets(int data_size, int max_size)
+ {
+- return fMaxBufsize;
++ int res1 = data_size % max_size;
++ int res2 = data_size / max_size;
++ return (res1) ? res2 + 1 : res2;
+ }
+
+- void NetMidiBuffer::SetBuffer ( int index, JackMidiBuffer* buffer )
++ void NetMidiBuffer::SetBuffer(int index, JackMidiBuffer* buffer)
+ {
+ fPortBuffer[index] = buffer;
+ }
+
+- JackMidiBuffer* NetMidiBuffer::GetBuffer ( int index )
++ JackMidiBuffer* NetMidiBuffer::GetBuffer(int index)
+ {
+ return fPortBuffer[index];
+ }
+
+ void NetMidiBuffer::DisplayEvents()
+ {
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
+- {
+- for ( uint event = 0; event < fPortBuffer[port_index]->event_count; event++ )
+- if ( fPortBuffer[port_index]->IsValid() )
+- jack_info ( "port %d : midi event %u/%u -> time : %u, size : %u",
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ for (uint event = 0; event < fPortBuffer[port_index]->event_count; event++) {
++ if (fPortBuffer[port_index]->IsValid()) {
++ jack_info("port %d : midi event %u/%u -> time : %u, size : %u",
+ port_index + 1, event + 1, fPortBuffer[port_index]->event_count,
+- fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size );
++ fPortBuffer[port_index]->events[event].time, fPortBuffer[port_index]->events[event].size);
++ }
++ }
+ }
+ }
+
+@@ -74,15 +152,15 @@
+ {
+ int pos = 0;
+ size_t copy_size;
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
+- {
+- char* write_pos = fBuffer + pos;
+
+- copy_size = sizeof ( JackMidiBuffer ) + fPortBuffer[port_index]->event_count * sizeof ( JackMidiEvent );
+- memcpy ( fBuffer + pos, fPortBuffer[port_index], copy_size );
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ char* write_pos = fBuffer + pos;
++ copy_size = sizeof(JackMidiBuffer) + fPortBuffer[port_index]->event_count * sizeof(JackMidiEvent);
++ memcpy(fBuffer + pos, fPortBuffer[port_index], copy_size);
+ pos += copy_size;
+- memcpy ( fBuffer + pos, fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ),
+- fPortBuffer[port_index]->write_pos );
++ memcpy(fBuffer + pos,
++ fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos),
++ fPortBuffer[port_index]->write_pos);
+ pos += fPortBuffer[port_index]->write_pos;
+
+ JackMidiBuffer* midi_buffer = reinterpret_cast<JackMidiBuffer*>(write_pos);
+@@ -91,72 +169,254 @@
+ return pos;
+ }
+
+- int NetMidiBuffer::RenderToJackPorts()
++ void NetMidiBuffer::RenderToJackPorts()
+ {
+ int pos = 0;
+- int copy_size;
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
+- {
++ size_t copy_size;
++
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
+ JackMidiBuffer* midi_buffer = reinterpret_cast<JackMidiBuffer*>(fBuffer + pos);
+ MidiBufferNToH(midi_buffer, midi_buffer);
+-
+- copy_size = sizeof ( JackMidiBuffer ) + reinterpret_cast<JackMidiBuffer*> ( fBuffer + pos )->event_count * sizeof ( JackMidiEvent );
+- memcpy ( fPortBuffer[port_index], fBuffer + pos, copy_size );
++ copy_size = sizeof(JackMidiBuffer) + reinterpret_cast<JackMidiBuffer*>(fBuffer + pos)->event_count * sizeof(JackMidiEvent);
++ memcpy(fPortBuffer[port_index], fBuffer + pos, copy_size);
+ pos += copy_size;
+- memcpy ( fPortBuffer[port_index] + ( fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos ),
+- fBuffer + pos, fPortBuffer[port_index]->write_pos );
++ memcpy(fPortBuffer[port_index] + (fPortBuffer[port_index]->buffer_size - fPortBuffer[port_index]->write_pos),
++ fBuffer + pos,
++ fPortBuffer[port_index]->write_pos);
+ pos += fPortBuffer[port_index]->write_pos;
+ }
+- return pos;
+ }
+
+- int NetMidiBuffer::RenderFromNetwork ( int subcycle, size_t copy_size )
++ void NetMidiBuffer::RenderFromNetwork(int sub_cycle, size_t copy_size)
+ {
+- memcpy ( fBuffer + subcycle * fMaxPcktSize, fNetBuffer, copy_size );
+- return copy_size;
++ memcpy(fBuffer + sub_cycle * fMaxPcktSize, fNetBuffer, copy_size);
+ }
+
+- int NetMidiBuffer::RenderToNetwork ( int subcycle, size_t total_size )
++ int NetMidiBuffer::RenderToNetwork(int sub_cycle, size_t total_size)
+ {
+- int size = total_size - subcycle * fMaxPcktSize;
+- int copy_size = ( size <= fMaxPcktSize ) ? size : fMaxPcktSize;
+- memcpy ( fNetBuffer, fBuffer + subcycle * fMaxPcktSize, copy_size );
++ int size = total_size - sub_cycle * fMaxPcktSize;
++ int copy_size = (size <= fMaxPcktSize) ? size : fMaxPcktSize;
++ memcpy(fNetBuffer, fBuffer + sub_cycle * fMaxPcktSize, copy_size);
+ return copy_size;
+ }
+
+-
+ // net audio buffer *********************************************************************************
+
+- NetAudioBuffer::NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer )
++ NetAudioBuffer::NetAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
+ {
+ fNPorts = nports;
+- fPeriodSize = params->fPeriodSize;
+- fSubPeriodSize = params->fFramesPerPacket;
+- fSubPeriodBytesSize = fSubPeriodSize * sizeof ( sample_t );
++ fNetBuffer = net_buffer;
++
+ fPortBuffer = new sample_t* [fNPorts];
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
++ fConnectedPorts = new bool[fNPorts];
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
+ fPortBuffer[port_index] = NULL;
+- fNetBuffer = net_buffer;
++ fConnectedPorts[port_index] = true;
++ }
+ }
+
+ NetAudioBuffer::~NetAudioBuffer()
+ {
+- delete[] fPortBuffer;
++ delete [] fConnectedPorts;
++ delete [] fPortBuffer;
+ }
+
+- size_t NetAudioBuffer::GetSize()
++ void NetAudioBuffer::SetBuffer(int index, sample_t* buffer)
+ {
+- return fNPorts * fSubPeriodBytesSize;
++ fPortBuffer[index] = buffer;
+ }
+
+- void NetAudioBuffer::SetBuffer ( int index, sample_t* buffer )
++ sample_t* NetAudioBuffer::GetBuffer(int index)
+ {
+- fPortBuffer[index] = buffer;
++ return fPortBuffer[index];
+ }
+
+- sample_t* NetAudioBuffer::GetBuffer ( int index )
++ int NetAudioBuffer::CheckPacket(int cycle, int sub_cycle)
+ {
+- return fPortBuffer[index];
++ int res;
++
++ if (sub_cycle != fLastSubCycle + 1) {
++ jack_error("Packet(s) missing from... %d %d", fLastSubCycle, sub_cycle);
++ res = NET_PACKET_ERROR;
++ } else {
++ res = 0;
++ }
++
++ fLastSubCycle = sub_cycle;
++ return res;
++ }
++
++ void NetAudioBuffer::NextCycle()
++ {
++ // reset for next cycle
++ fLastSubCycle = -1;
++ }
++
++ void NetAudioBuffer::Cleanup()
++ {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ if (fPortBuffer[port_index]) {
++ memset(fPortBuffer[port_index], 0, fPeriodSize * sizeof(sample_t));
++ }
++ }
++ }
++
++ //network<->buffer
++
++ int NetAudioBuffer::ActivePortsToNetwork(char* net_buffer)
++ {
++ int active_ports = 0;
++ int* active_port_address = (int*)net_buffer;
++
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ // Write the active port number
++ if (fPortBuffer[port_index]) {
++ *active_port_address = htonl(port_index);
++ active_port_address++;
++ active_ports++;
++ assert(active_ports < 256);
++ }
++ }
++
++ return active_ports;
++ }
++
++ void NetAudioBuffer::ActivePortsFromNetwork(char* net_buffer, uint32_t port_num)
++ {
++ int* active_port_address = (int*)net_buffer;
++
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ fConnectedPorts[port_index] = false;
++ }
++
++ for (uint port_index = 0; port_index < port_num; port_index++) {
++ // Use -1 when port is actually connected on other side
++ int active_port = ntohl(*active_port_address);
++ if (active_port >= 0 && active_port < fNPorts) {
++ fConnectedPorts[active_port] = true;
++ } else {
++ jack_error("ActivePortsFromNetwork: incorrect port = %d", active_port);
++ }
++ active_port_address++;
++ }
++ }
++
++ int NetAudioBuffer::RenderFromJackPorts()
++ {
++ // Count active ports
++ int active_ports = 0;
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++
++ if (fPortBuffer[port_index]) {
++ active_ports++;
++ }
++ }
++ //jack_info("active_ports %d", active_ports);
++ return active_ports;
++ }
++
++ void NetAudioBuffer::RenderToJackPorts()
++ {
++ // Nothing to do
++ NextCycle();
++ }
++
++ // Float converter
++
++ NetFloatAudioBuffer::NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
++ : NetAudioBuffer(params, nports, net_buffer)
++ {
++ fPeriodSize = params->fPeriodSize;
++ fPacketSize = PACKET_AVAILABLE_SIZE(params);
++
++ UpdateParams(max(params->fReturnAudioChannels, params->fSendAudioChannels));
++
++ fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t);
++
++ fCycleDuration = float(fSubPeriodSize) / float(params->fSampleRate);
++ fCycleBytesSize = params->fMtu * (fPeriodSize / fSubPeriodSize);
++
++ fLastSubCycle = -1;
++ }
++
++ NetFloatAudioBuffer::~NetFloatAudioBuffer()
++ {}
++
++ // needed size in bytes for an entire cycle
++ size_t NetFloatAudioBuffer::GetCycleSize()
++ {
++ return fCycleBytesSize;
++ }
++
++ // cycle duration in sec
++ float NetFloatAudioBuffer::GetCycleDuration()
++ {
++ return fCycleDuration;
++ }
++
++ void NetFloatAudioBuffer::UpdateParams(int active_ports)
++ {
++ if (active_ports == 0) {
++ fSubPeriodSize = fPeriodSize;
++ } else {
++ jack_nframes_t period = (int) powf(2.f, (int)(log(float(fPacketSize) / (active_ports * sizeof(sample_t))) / log(2.)));
++ fSubPeriodSize = (period > fPeriodSize) ? fPeriodSize : period;
++ }
++
++ fSubPeriodBytesSize = fSubPeriodSize * sizeof(sample_t) + sizeof(int); // The port number in coded on 4 bytes
++ }
++
++ int NetFloatAudioBuffer::GetNumPackets(int active_ports)
++ {
++ UpdateParams(active_ports);
++
++ /*
++ jack_log("GetNumPackets packet = %d fPeriodSize = %d fSubPeriodSize = %d fSubPeriodBytesSize = %d",
++ fPeriodSize / fSubPeriodSize, fPeriodSize, fSubPeriodSize, fSubPeriodBytesSize);
++ */
++ return fPeriodSize / fSubPeriodSize; // At least one packet
++ }
++
++ //jack<->buffer
++
++ int NetFloatAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num)
++ {
++ // Cleanup all JACK ports at the beginning of the cycle
++ if (sub_cycle == 0) {
++ Cleanup();
++ }
++
++ if (port_num > 0) {
++
++ UpdateParams(port_num);
++
++ for (uint32_t port_index = 0; port_index < port_num; port_index++) {
++ // Only copy to active ports : read the active port number then audio data
++ int* active_port_address = (int*)(fNetBuffer + port_index * fSubPeriodBytesSize);
++ int active_port = ntohl(*active_port_address);
++ RenderFromNetwork((char*)(active_port_address + 1), active_port, sub_cycle);
++ }
++ }
++
++ return CheckPacket(cycle, sub_cycle);
++ }
++
++
++ int NetFloatAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num)
++ {
++ int active_ports = 0;
++
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ // Only copy from active ports : write the active port number then audio data
++ if (fPortBuffer[port_index]) {
++ int* active_port_address = (int*)(fNetBuffer + active_ports * fSubPeriodBytesSize);
++ *active_port_address = htonl(port_index);
++ RenderToNetwork((char*)(active_port_address + 1), port_index, sub_cycle);
++ active_ports++;
++ }
++ }
++
++ return port_num * fSubPeriodBytesSize;
+ }
+
+ #ifdef __BIG_ENDIAN__
+@@ -177,23 +437,23 @@
+ return dat2.f;
+ }
+
+- void NetAudioBuffer::RenderFromJackPorts ( int subcycle )
++ void NetFloatAudioBuffer::RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle)
+ {
+- for ( int port_index = 0; port_index < fNPorts; port_index++ ) {
+- jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize);
+- jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(fNetBuffer + port_index * fSubPeriodBytesSize);
+- for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(jack_default_audio_sample_t); sample++) {
++ if (fPortBuffer[active_port]) {
++ jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(net_buffer);
++ jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize);
++ for (unsigned int sample = 0; sample < (fSubPeriodBytesSize - sizeof(int)) / sizeof(jack_default_audio_sample_t); sample++) {
+ dst[sample] = SwapFloat(src[sample]);
+ }
+ }
+ }
+
+- void NetAudioBuffer::RenderToJackPorts ( int subcycle )
++ void NetFloatAudioBuffer::RenderToNetwork(char* net_buffer, int active_port, int sub_cycle)
+ {
+ for ( int port_index = 0; port_index < fNPorts; port_index++ ) {
+- jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(fNetBuffer + port_index * fSubPeriodBytesSize);
+- jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(fPortBuffer[port_index] + subcycle * fSubPeriodSize);
+- for (unsigned int sample = 0; sample < fSubPeriodBytesSize / sizeof(jack_default_audio_sample_t); sample++) {
++ jack_default_audio_sample_t* src = (jack_default_audio_sample_t*)(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize);
++ jack_default_audio_sample_t* dst = (jack_default_audio_sample_t*)(net_buffer);
++ for (unsigned int sample = 0; sample < (fSubPeriodBytesSize - sizeof(int)) / sizeof(jack_default_audio_sample_t); sample++) {
+ dst[sample] = SwapFloat(src[sample]);
+ }
+ }
+@@ -201,98 +461,444 @@
+
+ #else
+
+- void NetAudioBuffer::RenderFromJackPorts ( int subcycle )
++ void NetFloatAudioBuffer::RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle)
+ {
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
+- memcpy ( fNetBuffer + port_index * fSubPeriodBytesSize, fPortBuffer[port_index] + subcycle * fSubPeriodSize, fSubPeriodBytesSize );
++ if (fPortBuffer[active_port]) {
++ memcpy(fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, net_buffer, fSubPeriodBytesSize - sizeof(int));
++ }
+ }
+
+- void NetAudioBuffer::RenderToJackPorts ( int subcycle )
++ void NetFloatAudioBuffer::RenderToNetwork(char* net_buffer, int active_port, int sub_cycle)
+ {
+- for ( int port_index = 0; port_index < fNPorts; port_index++ )
+- memcpy ( fPortBuffer[port_index] + subcycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize );
++ memcpy(net_buffer, fPortBuffer[active_port] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize - sizeof(int));
+ }
+
+ #endif
++ // Celt audio buffer *********************************************************************************
++
++#if HAVE_CELT
++
++ #define KPS 32
++ #define KPS_DIV 8
++
++ NetCeltAudioBuffer::NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps)
++ :NetAudioBuffer(params, nports, net_buffer)
++ {
++ fCeltMode = new CELTMode *[fNPorts];
++ fCeltEncoder = new CELTEncoder *[fNPorts];
++ fCeltDecoder = new CELTDecoder *[fNPorts];
++
++ memset(fCeltMode, 0, fNPorts * sizeof(CELTMode*));
++ memset(fCeltEncoder, 0, fNPorts * sizeof(CELTEncoder*));
++ memset(fCeltDecoder, 0, fNPorts * sizeof(CELTDecoder*));
++
++ int error = CELT_OK;
++
++ for (int i = 0; i < fNPorts; i++) {
++ fCeltMode[i] = celt_mode_create(params->fSampleRate, params->fPeriodSize, &error);
++ if (error != CELT_OK) {
++ goto error;
++ }
++
++ #if HAVE_CELT_API_0_11
++
++ fCeltEncoder[i] = celt_encoder_create_custom(fCeltMode[i], 1, &error);
++ if (error != CELT_OK) {
++ goto error;
++ }
++ celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1));
++
++ fCeltDecoder[i] = celt_decoder_create_custom(fCeltMode[i], 1, &error);
++ if (error != CELT_OK) {
++ goto error;
++ }
++ celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1));
++
++ #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
++
++ fCeltEncoder[i] = celt_encoder_create(fCeltMode[i], 1, &error);
++ if (error != CELT_OK) {
++ goto error;
++ }
++ celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1));
++
++ fCeltDecoder[i] = celt_decoder_create(fCeltMode[i], 1, &error);
++ if (error != CELT_OK) {
++ goto error;
++ }
++ celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1));
++
++ #else
++
++ fCeltEncoder[i] = celt_encoder_create(fCeltMode[i]);
++ if (error != CELT_OK) {
++ goto error;
++ }
++ celt_encoder_ctl(fCeltEncoder[i], CELT_SET_COMPLEXITY(1));
++
++ fCeltDecoder[i] = celt_decoder_create(fCeltMode[i]);
++ if (error != CELT_OK) {
++ goto error;
++ }
++ celt_decoder_ctl(fCeltDecoder[i], CELT_SET_COMPLEXITY(1));
++
++ #endif
++ }
++
++ {
++ fPeriodSize = params->fPeriodSize;
++
++ fCompressedSizeByte = (kbps * params->fPeriodSize * 1024) / (params->fSampleRate * 8);
++ jack_log("NetCeltAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte);
++
++ fCompressedBuffer = new unsigned char* [fNPorts];
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ fCompressedBuffer[port_index] = new unsigned char[fCompressedSizeByte];
++ }
++
++ int res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params);
++ int res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params);
++
++ fNumPackets = (res1) ? (res2 + 1) : res2;
++
++ jack_log("NetCeltAudioBuffer res1 = %d res2 = %d", res1, res2);
++
++ fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets;
++ fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets;
++
++ jack_log("NetCeltAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize);
++
++ fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate);
++ fCycleBytesSize = params->fMtu * fNumPackets;
++
++ fLastSubCycle = -1;
++ return;
++ }
++
++ error:
++
++ FreeCelt();
++ throw std::bad_alloc();
++ }
++
++ NetCeltAudioBuffer::~NetCeltAudioBuffer()
++ {
++ FreeCelt();
++
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ delete [] fCompressedBuffer[port_index];
++ }
++
++ delete [] fCompressedBuffer;
++ }
++
++ void NetCeltAudioBuffer::FreeCelt()
++ {
++ for (int i = 0; i < fNPorts; i++) {
++ if (fCeltEncoder[i]) {
++ celt_encoder_destroy(fCeltEncoder[i]);
++ }
++ if (fCeltDecoder[i]) {
++ celt_decoder_destroy(fCeltDecoder[i]);
++ }
++ if (fCeltMode[i]) {
++ celt_mode_destroy(fCeltMode[i]);
++ }
++ }
++
++ delete [] fCeltMode;
++ delete [] fCeltEncoder;
++ delete [] fCeltDecoder;
++ }
++
++ size_t NetCeltAudioBuffer::GetCycleSize()
++ {
++ return fCycleBytesSize;
++ }
++
++ float NetCeltAudioBuffer::GetCycleDuration()
++ {
++ return fCycleDuration;
++ }
++
++ int NetCeltAudioBuffer::GetNumPackets(int active_ports)
++ {
++ return fNumPackets;
++ }
++
++ int NetCeltAudioBuffer::RenderFromJackPorts()
++ {
++ float buffer[fPeriodSize];
++
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(buffer, fPortBuffer[port_index], fPeriodSize * sizeof(sample_t));
++#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
++ int res = celt_encode_float(fCeltEncoder[port_index], buffer, fPeriodSize, fCompressedBuffer[port_index], fCompressedSizeByte);
++#else
++ int res = celt_encode_float(fCeltEncoder[port_index], buffer, NULL, fCompressedBuffer[port_index], fCompressedSizeByte);
++#endif
++ if (res != fCompressedSizeByte) {
++ jack_error("celt_encode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res);
++ }
++ }
++
++ // All ports active
++ return fNPorts;
++ }
++
++ void NetCeltAudioBuffer::RenderToJackPorts()
++ {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
++ int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index], fPeriodSize);
++#else
++ int res = celt_decode_float(fCeltDecoder[port_index], fCompressedBuffer[port_index], fCompressedSizeByte, fPortBuffer[port_index]);
++#endif
++ if (res != CELT_OK) {
++ jack_error("celt_decode_float error fCompressedSizeByte = %d res = %d", fCompressedSizeByte, res);
++ }
++ }
++
++ NextCycle();
++ }
++
++ //network<->buffer
++ int NetCeltAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num)
++ {
++ // Last packet of the cycle
++ if (sub_cycle == fNumPackets - 1) {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize);
++ }
++ } else {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize);
++ }
++ }
++
++ return CheckPacket(cycle, sub_cycle);
++ }
++
++ int NetCeltAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num)
++ {
++ // Last packet of the cycle
++ if (sub_cycle == fNumPackets - 1) {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fLastSubPeriodBytesSize);
++ }
++ return fNPorts * fLastSubPeriodBytesSize;
++ } else {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fCompressedBuffer[port_index] + sub_cycle * fSubPeriodBytesSize, fSubPeriodBytesSize);
++ }
++ return fNPorts * fSubPeriodBytesSize;
++ }
++ }
++
++#endif
++
++ NetIntAudioBuffer::NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer)
++ : NetAudioBuffer(params, nports, net_buffer)
++ {
++ fPeriodSize = params->fPeriodSize;
++
++ fCompressedSizeByte = (params->fPeriodSize * sizeof(short));
++ jack_log("NetIntAudioBuffer fCompressedSizeByte %d", fCompressedSizeByte);
++
++ fIntBuffer = new short* [fNPorts];
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ fIntBuffer[port_index] = new short[fPeriodSize];
++ }
++
++ int res1 = (fNPorts * fCompressedSizeByte) % PACKET_AVAILABLE_SIZE(params);
++ int res2 = (fNPorts * fCompressedSizeByte) / PACKET_AVAILABLE_SIZE(params);
++
++ jack_log("NetIntAudioBuffer res1 = %d res2 = %d", res1, res2);
++
++ fNumPackets = (res1) ? (res2 + 1) : res2;
++
++ fSubPeriodBytesSize = fCompressedSizeByte / fNumPackets;
++ fLastSubPeriodBytesSize = fSubPeriodBytesSize + fCompressedSizeByte % fNumPackets;
++
++ fSubPeriodSize = fSubPeriodBytesSize / sizeof(short);
++
++ jack_log("NetIntAudioBuffer fNumPackets = %d fSubPeriodBytesSize = %d, fLastSubPeriodBytesSize = %d", fNumPackets, fSubPeriodBytesSize, fLastSubPeriodBytesSize);
++
++ fCycleDuration = float(fSubPeriodBytesSize / sizeof(sample_t)) / float(params->fSampleRate);
++ fCycleBytesSize = params->fMtu * fNumPackets;
++
++ fLastSubCycle = -1;
++ return;
++ }
++
++ NetIntAudioBuffer::~NetIntAudioBuffer()
++ {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ delete [] fIntBuffer[port_index];
++ }
++
++ delete [] fIntBuffer;
++ }
++
++ size_t NetIntAudioBuffer::GetCycleSize()
++ {
++ return fCycleBytesSize;
++ }
++
++ float NetIntAudioBuffer::GetCycleDuration()
++ {
++ return fCycleDuration;
++ }
++
++ int NetIntAudioBuffer::GetNumPackets(int active_ports)
++ {
++ return fNumPackets;
++ }
++
++ int NetIntAudioBuffer::RenderFromJackPorts()
++ {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ for (uint frame = 0; frame < fPeriodSize; frame++) {
++ fIntBuffer[port_index][frame] = short(fPortBuffer[port_index][frame] * 32768.f);
++ }
++ }
++
++ // All ports active
++ return fNPorts;
++ }
++
++ void NetIntAudioBuffer::RenderToJackPorts()
++ {
++ float coef = 1.f / 32768.f;
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ for (uint frame = 0; frame < fPeriodSize; frame++) {
++ fPortBuffer[port_index][frame] = float(fIntBuffer[port_index][frame] * coef);
++ }
++ }
++
++ NextCycle();
++ }
++
++ //network<->buffer
++ int NetIntAudioBuffer::RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num)
++ {
++ if (sub_cycle == fNumPackets - 1) {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fNetBuffer + port_index * fLastSubPeriodBytesSize, fLastSubPeriodBytesSize);
++ }
++ } else {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fNetBuffer + port_index * fSubPeriodBytesSize, fSubPeriodBytesSize);
++ }
++ }
++
++ return CheckPacket(cycle, sub_cycle);
++ }
++
++ int NetIntAudioBuffer::RenderToNetwork(int sub_cycle, uint32_t port_num)
++ {
++ // Last packet of the cycle
++ if (sub_cycle == fNumPackets - 1) {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fNetBuffer + port_index * fLastSubPeriodBytesSize, fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fLastSubPeriodBytesSize);
++ }
++ return fNPorts * fLastSubPeriodBytesSize;
++ } else {
++ for (int port_index = 0; port_index < fNPorts; port_index++) {
++ memcpy(fNetBuffer + port_index * fSubPeriodBytesSize, fIntBuffer[port_index] + sub_cycle * fSubPeriodSize, fSubPeriodBytesSize);
++ }
++ return fNPorts * fSubPeriodBytesSize;
++ }
++ }
+
+ // SessionParams ************************************************************************************
+
+- SERVER_EXPORT void SessionParamsHToN ( session_params_t* src_params, session_params_t* dst_params )
++ SERVER_EXPORT void SessionParamsHToN(session_params_t* src_params, session_params_t* dst_params)
+ {
+ memcpy(dst_params, src_params, sizeof(session_params_t));
+- dst_params->fPacketID = htonl ( src_params->fPacketID );
+- dst_params->fMtu = htonl ( src_params->fMtu );
+- dst_params->fID = htonl ( src_params->fID );
+- dst_params->fTransportSync = htonl ( src_params->fTransportSync );
+- dst_params->fSendAudioChannels = htonl ( src_params->fSendAudioChannels );
+- dst_params->fReturnAudioChannels = htonl ( src_params->fReturnAudioChannels );
+- dst_params->fSendMidiChannels = htonl ( src_params->fSendMidiChannels );
+- dst_params->fReturnMidiChannels = htonl ( src_params->fReturnMidiChannels );
+- dst_params->fSampleRate = htonl ( src_params->fSampleRate );
+- dst_params->fPeriodSize = htonl ( src_params->fPeriodSize );
+- dst_params->fFramesPerPacket = htonl ( src_params->fFramesPerPacket );
+- dst_params->fBitdepth = htonl ( src_params->fBitdepth );
+- dst_params->fSlaveSyncMode = htonl ( src_params->fSlaveSyncMode );
++ dst_params->fPacketID = htonl(src_params->fPacketID);
++ dst_params->fMtu = htonl(src_params->fMtu);
++ dst_params->fID = htonl(src_params->fID);
++ dst_params->fTransportSync = htonl(src_params->fTransportSync);
++ dst_params->fSendAudioChannels = htonl(src_params->fSendAudioChannels);
++ dst_params->fReturnAudioChannels = htonl(src_params->fReturnAudioChannels);
++ dst_params->fSendMidiChannels = htonl(src_params->fSendMidiChannels);
++ dst_params->fReturnMidiChannels = htonl(src_params->fReturnMidiChannels);
++ dst_params->fSampleRate = htonl(src_params->fSampleRate);
++ dst_params->fPeriodSize = htonl(src_params->fPeriodSize);
++ dst_params->fSampleEncoder = htonl(src_params->fSampleEncoder);
++ dst_params->fKBps = htonl(src_params->fKBps);
++ dst_params->fSlaveSyncMode = htonl(src_params->fSlaveSyncMode);
++ dst_params->fNetworkLatency = htonl(src_params->fNetworkLatency);
+ }
+
+- SERVER_EXPORT void SessionParamsNToH ( session_params_t* src_params, session_params_t* dst_params )
++ SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params)
+ {
+ memcpy(dst_params, src_params, sizeof(session_params_t));
+- dst_params->fPacketID = ntohl ( src_params->fPacketID );
+- dst_params->fMtu = ntohl ( src_params->fMtu );
+- dst_params->fID = ntohl ( src_params->fID );
+- dst_params->fTransportSync = ntohl ( src_params->fTransportSync );
+- dst_params->fSendAudioChannels = ntohl ( src_params->fSendAudioChannels );
+- dst_params->fReturnAudioChannels = ntohl ( src_params->fReturnAudioChannels );
+- dst_params->fSendMidiChannels = ntohl ( src_params->fSendMidiChannels );
+- dst_params->fReturnMidiChannels = ntohl ( src_params->fReturnMidiChannels );
+- dst_params->fSampleRate = ntohl ( src_params->fSampleRate );
+- dst_params->fPeriodSize = ntohl ( src_params->fPeriodSize );
+- dst_params->fFramesPerPacket = ntohl ( src_params->fFramesPerPacket );
+- dst_params->fBitdepth = ntohl ( src_params->fBitdepth );
+- dst_params->fSlaveSyncMode = ntohl ( src_params->fSlaveSyncMode );
++ dst_params->fPacketID = ntohl(src_params->fPacketID);
++ dst_params->fMtu = ntohl(src_params->fMtu);
++ dst_params->fID = ntohl(src_params->fID);
++ dst_params->fTransportSync = ntohl(src_params->fTransportSync);
++ dst_params->fSendAudioChannels = ntohl(src_params->fSendAudioChannels);
++ dst_params->fReturnAudioChannels = ntohl(src_params->fReturnAudioChannels);
++ dst_params->fSendMidiChannels = ntohl(src_params->fSendMidiChannels);
++ dst_params->fReturnMidiChannels = ntohl(src_params->fReturnMidiChannels);
++ dst_params->fSampleRate = ntohl(src_params->fSampleRate);
++ dst_params->fPeriodSize = ntohl(src_params->fPeriodSize);
++ dst_params->fSampleEncoder = ntohl(src_params->fSampleEncoder);
++ dst_params->fKBps = ntohl(src_params->fKBps);
++ dst_params->fSlaveSyncMode = ntohl(src_params->fSlaveSyncMode);
++ dst_params->fNetworkLatency = ntohl(src_params->fNetworkLatency);
+ }
+
+- SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params )
++ SERVER_EXPORT void SessionParamsDisplay(session_params_t* params)
+ {
+- char bitdepth[16];
+- ( params->fBitdepth ) ? sprintf ( bitdepth, "%u", params->fBitdepth ) : sprintf ( bitdepth, "%s", "float" );
+- char mode[8];
+- switch ( params->fNetworkMode )
++ char encoder[16];
++ switch (params->fSampleEncoder)
+ {
+- case 's' :
+- strcpy ( mode, "slow" );
++ case JackFloatEncoder:
++ strcpy(encoder, "float");
+ break;
+- case 'n' :
+- strcpy ( mode, "normal" );
++ case JackIntEncoder:
++ strcpy(encoder, "integer");
+ break;
+- case 'f' :
+- strcpy ( mode, "fast" );
++ case JackCeltEncoder:
++ strcpy(encoder, "CELT");
+ break;
+ }
+- jack_info ( "**************** Network parameters ****************" );
+- jack_info ( "Name : %s", params->fName );
+- jack_info ( "Protocol revision : %d", params->fProtocolVersion );
+- jack_info ( "MTU : %u", params->fMtu );
+- jack_info ( "Master name : %s", params->fMasterNetName );
+- jack_info ( "Slave name : %s", params->fSlaveNetName );
+- jack_info ( "ID : %u", params->fID );
+- jack_info ( "Transport Sync : %s", ( params->fTransportSync ) ? "yes" : "no" );
+- jack_info ( "Send channels (audio - midi) : %d - %d", params->fSendAudioChannels, params->fSendMidiChannels );
+- jack_info ( "Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels );
+- jack_info ( "Sample rate : %u frames per second", params->fSampleRate );
+- jack_info ( "Period size : %u frames per period", params->fPeriodSize );
+- jack_info ( "Frames per packet : %u", params->fFramesPerPacket );
+- jack_info ( "Packet per period : %u", (params->fFramesPerPacket != 0) ? params->fPeriodSize / params->fFramesPerPacket : 0);
+- jack_info ( "Bitdepth : %s", bitdepth );
+- jack_info ( "Slave mode : %s", ( params->fSlaveSyncMode ) ? "sync" : "async" );
+- jack_info ( "Network mode : %s", mode );
+- jack_info ( "****************************************************" );
++
++ jack_info("**************** Network parameters ****************");
++ jack_info("Name : %s", params->fName);
++ jack_info("Protocol revision : %d", params->fProtocolVersion);
++ jack_info("MTU : %u", params->fMtu);
++ jack_info("Master name : %s", params->fMasterNetName);
++ jack_info("Slave name : %s", params->fSlaveNetName);
++ jack_info("ID : %u", params->fID);
++ jack_info("Transport Sync : %s", (params->fTransportSync) ? "yes" : "no");
++ jack_info("Send channels (audio - midi) : %d - %d", params->fSendAudioChannels, params->fSendMidiChannels);
++ jack_info("Return channels (audio - midi) : %d - %d", params->fReturnAudioChannels, params->fReturnMidiChannels);
++ jack_info("Sample rate : %u frames per second", params->fSampleRate);
++ jack_info("Period size : %u frames per period", params->fPeriodSize);
++ jack_info("Network latency : %u cycles", params->fNetworkLatency);
++ switch (params->fSampleEncoder) {
++ case (JackFloatEncoder):
++ jack_info("SampleEncoder : %s", "Float");
++ break;
++ case (JackIntEncoder):
++ jack_info("SampleEncoder : %s", "16 bits integer");
++ break;
++ case (JackCeltEncoder):
++ jack_info("SampleEncoder : %s", "CELT");
++ jack_info("kBits : %d", params->fKBps);
++ break;
++ };
++ jack_info("Slave mode : %s", (params->fSlaveSyncMode) ? "sync" : "async");
++ jack_info("****************************************************");
+ }
+
+- SERVER_EXPORT sync_packet_type_t GetPacketType ( session_params_t* params )
++ SERVER_EXPORT sync_packet_type_t GetPacketType(session_params_t* params)
+ {
+- switch ( params->fPacketID )
++ switch (params->fPacketID)
+ {
+ case 0:
+ return SLAVE_AVAILABLE;
+@@ -308,9 +914,9 @@
+ return INVALID;
+ }
+
+- SERVER_EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type )
++ SERVER_EXPORT int SetPacketType(session_params_t* params, sync_packet_type_t packet_type)
+ {
+- switch ( packet_type )
++ switch (packet_type)
+ {
+ case INVALID:
+ return -1;
+@@ -334,59 +940,57 @@
+
+ // Packet header **********************************************************************************
+
+- SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* src_header, packet_header_t* dst_header )
++ SERVER_EXPORT void PacketHeaderHToN(packet_header_t* src_header, packet_header_t* dst_header)
+ {
+ memcpy(dst_header, src_header, sizeof(packet_header_t));
+- dst_header->fID = htonl ( src_header->fID );
+- dst_header->fMidiDataSize = htonl ( src_header->fMidiDataSize );
+- dst_header->fBitdepth = htonl ( src_header->fBitdepth );
+- dst_header->fNMidiPckt = htonl ( src_header->fNMidiPckt );
+- dst_header->fPacketSize = htonl ( src_header->fPacketSize );
+- dst_header->fCycle = htonl ( src_header->fCycle );
+- dst_header->fSubCycle = htonl ( src_header->fSubCycle );
+- dst_header->fIsLastPckt = htonl ( src_header->fIsLastPckt );
++ dst_header->fID = htonl(src_header->fID);
++ dst_header->fNumPacket = htonl(src_header->fNumPacket);
++ dst_header->fPacketSize = htonl(src_header->fPacketSize);
++ dst_header->fActivePorts = htonl(src_header->fActivePorts);
++ dst_header->fCycle = htonl(src_header->fCycle);
++ dst_header->fSubCycle = htonl(src_header->fSubCycle);
++ dst_header->fIsLastPckt = htonl(src_header->fIsLastPckt);
+ }
+
+- SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* src_header, packet_header_t* dst_header )
++ SERVER_EXPORT void PacketHeaderNToH(packet_header_t* src_header, packet_header_t* dst_header)
+ {
+ memcpy(dst_header, src_header, sizeof(packet_header_t));
+- dst_header->fID = ntohl ( src_header->fID );
+- dst_header->fMidiDataSize = ntohl ( src_header->fMidiDataSize );
+- dst_header->fBitdepth = ntohl ( src_header->fBitdepth );
+- dst_header->fNMidiPckt = ntohl ( src_header->fNMidiPckt );
+- dst_header->fPacketSize = ntohl ( src_header->fPacketSize );
+- dst_header->fCycle = ntohl ( src_header->fCycle );
+- dst_header->fSubCycle = ntohl ( src_header->fSubCycle );
+- dst_header->fIsLastPckt = ntohl ( src_header->fIsLastPckt );
++ dst_header->fID = ntohl(src_header->fID);
++ dst_header->fNumPacket = ntohl(src_header->fNumPacket);
++ dst_header->fPacketSize = ntohl(src_header->fPacketSize);
++ dst_header->fActivePorts = ntohl(src_header->fActivePorts);
++ dst_header->fCycle = ntohl(src_header->fCycle);
++ dst_header->fSubCycle = ntohl(src_header->fSubCycle);
++ dst_header->fIsLastPckt = ntohl(src_header->fIsLastPckt);
+ }
+
+- SERVER_EXPORT void PacketHeaderDisplay ( packet_header_t* header )
++ SERVER_EXPORT void PacketHeaderDisplay(packet_header_t* header)
+ {
+ char bitdepth[16];
+- ( header->fBitdepth ) ? sprintf ( bitdepth, "%u", header->fBitdepth ) : sprintf ( bitdepth, "%s", "float" );
+- jack_info ( "********************Header********************" );
+- jack_info ( "Data type : %c", header->fDataType );
+- jack_info ( "Data stream : %c", header->fDataStream );
+- jack_info ( "ID : %u", header->fID );
+- jack_info ( "Cycle : %u", header->fCycle );
+- jack_info ( "SubCycle : %u", header->fSubCycle );
+- jack_info ( "Midi packets : %u", header->fNMidiPckt );
+- jack_info ( "Midi data size : %u", header->fMidiDataSize );
+- jack_info ( "Last packet : '%s'", ( header->fIsLastPckt ) ? "yes" : "no" );
+- jack_info ( "Bitdepth : %s", bitdepth );
+- jack_info ( "**********************************************" );
+- }
+-
+- SERVER_EXPORT void NetTransportDataDisplay ( net_transport_data_t* data )
+- {
+- jack_info ( "********************Network Transport********************" );
+- jack_info ( "Transport new state : %u", data->fNewState );
+- jack_info ( "Transport timebase master : %u", data->fTimebaseMaster );
+- jack_info ( "Transport cycle state : %u", data->fState );
+- jack_info ( "**********************************************" );
++ jack_info("********************Header********************");
++ jack_info("Data type : %c", header->fDataType);
++ jack_info("Data stream : %c", header->fDataStream);
++ jack_info("ID : %u", header->fID);
++ jack_info("Cycle : %u", header->fCycle);
++ jack_info("SubCycle : %u", header->fSubCycle);
++ jack_info("Active ports : %u", header->fActivePorts);
++ jack_info("DATA packets : %u", header->fNumPacket);
++ jack_info("DATA size : %u", header->fPacketSize);
++ jack_info("Last packet : '%s'", (header->fIsLastPckt) ? "yes" : "no");
++ jack_info("Bitdepth : %s", bitdepth);
++ jack_info("**********************************************");
++ }
++
++ SERVER_EXPORT void NetTransportDataDisplay(net_transport_data_t* data)
++ {
++ jack_info("********************Network Transport********************");
++ jack_info("Transport new state : %u", data->fNewState);
++ jack_info("Transport timebase master : %u", data->fTimebaseMaster);
++ jack_info("Transport cycle state : %u", data->fState);
++ jack_info("**********************************************");
+ }
+
+- SERVER_EXPORT void MidiBufferHToN ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer )
++ SERVER_EXPORT void MidiBufferHToN(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer)
+ {
+ dst_buffer->magic = htonl(src_buffer->magic);
+ dst_buffer->buffer_size = htonl(src_buffer->buffer_size);
+@@ -397,7 +1001,7 @@
+ dst_buffer->mix_index = htonl(src_buffer->mix_index);
+ }
+
+- SERVER_EXPORT void MidiBufferNToH ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer )
++ SERVER_EXPORT void MidiBufferNToH(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer)
+ {
+ dst_buffer->magic = ntohl(src_buffer->magic);
+ dst_buffer->buffer_size = ntohl(src_buffer->buffer_size);
+@@ -408,7 +1012,7 @@
+ dst_buffer->mix_index = ntohl(src_buffer->mix_index);
+ }
+
+- SERVER_EXPORT void TransportDataHToN ( net_transport_data_t* src_params, net_transport_data_t* dst_params )
++ SERVER_EXPORT void TransportDataHToN(net_transport_data_t* src_params, net_transport_data_t* dst_params)
+ {
+ dst_params->fNewState = htonl(src_params->fNewState);
+ dst_params->fTimebaseMaster = htonl(src_params->fTimebaseMaster);
+@@ -434,7 +1038,7 @@
+ dst_params->fPosition.unique_2 = htonll(src_params->fPosition.unique_2);
+ }
+
+- SERVER_EXPORT void TransportDataNToH ( net_transport_data_t* src_params, net_transport_data_t* dst_params )
++ SERVER_EXPORT void TransportDataNToH(net_transport_data_t* src_params, net_transport_data_t* dst_params)
+ {
+ dst_params->fNewState = ntohl(src_params->fNewState);
+ dst_params->fTimebaseMaster = ntohl(src_params->fTimebaseMaster);
+@@ -465,18 +1069,16 @@
+ SERVER_EXPORT int SocketAPIInit()
+ {
+ #ifdef WIN32
+- WORD wVersionRequested = MAKEWORD ( 2, 2 );
++ WORD wVersionRequested = MAKEWORD(2, 2);
+ WSADATA wsaData;
+
+- if ( WSAStartup ( wVersionRequested, &wsaData ) != 0 )
+- {
+- jack_error ( "WSAStartup error : %s", strerror ( NET_ERROR_CODE ) );
++ if (WSAStartup(wVersionRequested, &wsaData) != 0) {
++ jack_error("WSAStartup error : %s", strerror(NET_ERROR_CODE));
+ return -1;
+ }
+
+- if ( LOBYTE ( wsaData.wVersion ) != 2 || HIBYTE ( wsaData.wVersion ) != 2 )
+- {
+- jack_error ( "Could not find a useable version of Winsock.dll\n" );
++ if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
++ jack_error("Could not find a useable version of Winsock.dll\n");
+ WSACleanup();
+ return -1;
+ }
+@@ -492,9 +1094,9 @@
+ return 0;
+ }
+
+- SERVER_EXPORT const char* GetTransportState ( int transport_state )
++ SERVER_EXPORT const char* GetTransportState(int transport_state)
+ {
+- switch ( transport_state )
++ switch (transport_state)
+ {
+ case JackTransportRolling:
+ return "rolling";
+--- a/common/JackNetTool.h
++++ b/common/JackNetTool.h
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -31,14 +31,24 @@
+
+ #ifndef htonll
+ #ifdef __BIG_ENDIAN__
+-#define htonll(x) (x)
+-#define ntohll(x) (x)
++#define htonll(x) (x)
++#define ntohll(x) (x)
+ #else
+-#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl(x >> 32))
+-#define ntohll(x) ((((uint64_t)ntohl(x)) << 32) + ntohl(x >> 32))
++#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl(x >> 32))
++#define ntohll(x) ((((uint64_t)ntohl(x)) << 32) + ntohl(x >> 32))
+ #endif
+ #endif
+
++#define MASTER_PROTOCOL 5
++#define SLAVE_PROTOCOL 5
++
++#define NET_PACKET_ERROR -2
++
++#define OPTIMIZED_PROTOCOL
++
++#define HEADER_SIZE (sizeof(packet_header_t))
++#define PACKET_AVAILABLE_SIZE(params) ((params)->fMtu - sizeof(packet_header_t))
++
+ namespace Jack
+ {
+ typedef struct _session_params session_params_t;
+@@ -48,6 +58,13 @@
+ typedef struct in_addr address_t;
+ typedef jack_default_audio_sample_t sample_t;
+
++ enum JackNetEncoder {
++
++ JackFloatEncoder = 0,
++ JackIntEncoder = 1,
++ JackCeltEncoder = 2,
++ };
++
+ //session params ******************************************************************************
+
+ /**
+@@ -67,9 +84,6 @@
+ are kept in LITTLE_ENDIAN format (to avoid 2 conversions in the more common LITTLE_ENDIAN <==> LITTLE_ENDIAN connection case).
+ */
+
+- #define MASTER_PROTOCOL 1
+- #define SLAVE_PROTOCOL 1
+-
+ struct _session_params
+ {
+ char fPacketType[7]; //packet type ('param')
+@@ -81,16 +95,16 @@
+ uint32_t fMtu; //connection mtu
+ uint32_t fID; //slave's ID
+ uint32_t fTransportSync; //is the transport synced ?
+- uint32_t fSendAudioChannels; //number of master->slave channels
+- uint32_t fReturnAudioChannels; //number of slave->master channels
+- uint32_t fSendMidiChannels; //number of master->slave midi channels
+- uint32_t fReturnMidiChannels; //number of slave->master midi channels
++ int32_t fSendAudioChannels; //number of master->slave channels
++ int32_t fReturnAudioChannels; //number of slave->master channels
++ int32_t fSendMidiChannels; //number of master->slave midi channels
++ int32_t fReturnMidiChannels; //number of slave->master midi channels
+ uint32_t fSampleRate; //session sample rate
+ uint32_t fPeriodSize; //period size
+- uint32_t fFramesPerPacket; //complete frames per packet
+- uint32_t fBitdepth; //samples bitdepth (unused)
++ uint32_t fSampleEncoder; //samples encoder
++ uint32_t fKBps; //KB per second for CELT encoder
+ uint32_t fSlaveSyncMode; //is the slave in sync mode ?
+- char fNetworkMode; //fast, normal or slow mode
++ uint32_t fNetworkLatency; //network latency
+ };
+
+ //net status **********************************************************************************
+@@ -154,19 +168,16 @@
+
+ struct _packet_header
+ {
+- char fPacketType[7]; //packet type ( 'headr' )
++ char fPacketType[7]; //packet type ('headr')
+ char fDataType; //a for audio, m for midi and s for sync
+ char fDataStream; //s for send, r for return
+ uint32_t fID; //unique ID of the slave
+- uint32_t fBitdepth; //bitdepth of the data samples
+- uint32_t fMidiDataSize; //size of midi data in bytes
+- uint32_t fNMidiPckt; //number of midi packets of the cycle
++ uint32_t fNumPacket; //number of data packets of the cycle
+ uint32_t fPacketSize; //packet size in bytes
++ uint32_t fActivePorts; //number of active ports
+ uint32_t fCycle; //process cycle counter
+ uint32_t fSubCycle; //midi/audio subcycle counter
+ uint32_t fIsLastPckt; //is it the last packet of a given cycle ('y' or 'n')
+- char fASyncWrongCycle; //is the current async cycle wrong (slave's side; 'y' or 'n')
+- char fFree[26]; //unused
+ };
+
+ //net timebase master
+@@ -200,7 +211,7 @@
+ jack_position_t fPosition; //current cycle position
+ };
+
+-//midi data ***********************************************************************************
++ //midi data ***********************************************************************************
+
+ /**
+ \Brief Midi buffer and operations class
+@@ -220,89 +231,233 @@
+ class SERVER_EXPORT NetMidiBuffer
+ {
+ private:
++
+ int fNPorts;
+ size_t fMaxBufsize;
+ int fMaxPcktSize;
++
+ char* fBuffer;
+ char* fNetBuffer;
+ JackMidiBuffer** fPortBuffer;
+
++ size_t fCycleBytesSize; // needed size in bytes ofr an entire cycle
++
+ public:
+- NetMidiBuffer ( session_params_t* params, uint32_t nports, char* net_buffer );
++
++ NetMidiBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
+ ~NetMidiBuffer();
+
+ void Reset();
+- size_t GetSize();
++
++ // needed size in bytes for an entire cycle
++ size_t GetCycleSize();
++ int GetNumPackets(int data_sizen, int max_size);
++
++ void SetBuffer(int index, JackMidiBuffer* buffer);
++ JackMidiBuffer* GetBuffer(int index);
++
+ //utility
+ void DisplayEvents();
++
+ //jack<->buffer
+ int RenderFromJackPorts();
+- int RenderToJackPorts();
++ void RenderToJackPorts();
++
+ //network<->buffer
+- int RenderFromNetwork ( int subcycle, size_t copy_size );
+- int RenderToNetwork ( int subcycle, size_t total_size );
++ void RenderFromNetwork(int sub_cycle, size_t copy_size);
++ int RenderToNetwork(int sub_cycle, size_t total_size);
+
+- void SetBuffer ( int index, JackMidiBuffer* buffer );
+- JackMidiBuffer* GetBuffer ( int index );
+ };
+
+ // audio data *********************************************************************************
+
+- /**
+- \Brief Audio buffer and operations class
+-
+- This class is a toolset to manipulate audio buffers.
+- The manipulation of audio buffers is similar to midi buffer, except those buffers have fixed size.
+- The interleaving/uninterleaving operations are simplier here because audio buffers have fixed size,
+- So there is no need of an intermediate buffer as in NetMidiBuffer.
+-
+- */
+-
+ class SERVER_EXPORT NetAudioBuffer
+ {
+- private:
++
++ protected:
++
+ int fNPorts;
++ int fLastSubCycle;
++
++ char* fNetBuffer;
++ sample_t** fPortBuffer;
++ bool* fConnectedPorts;
++
+ jack_nframes_t fPeriodSize;
+ jack_nframes_t fSubPeriodSize;
+ size_t fSubPeriodBytesSize;
+- char* fNetBuffer;
+- sample_t** fPortBuffer;
++
++ float fCycleDuration; // in sec
++ size_t fCycleBytesSize; // needed size in bytes for an entire cycle
++
++ int CheckPacket(int cycle, int sub_cycle);
++ void NextCycle();
++ void Cleanup();
++
++ public:
++
++ NetAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
++ virtual ~NetAudioBuffer();
++
++ bool GetConnected(int port_index) { return fConnectedPorts[port_index]; }
++ void SetConnected(int port_index, bool state) { fConnectedPorts[port_index] = state; }
++
++ // needed syze in bytes ofr an entire cycle
++ virtual size_t GetCycleSize() = 0;
++
++ // cycle duration in sec
++ virtual float GetCycleDuration() = 0;
++
++ virtual int GetNumPackets(int active_ports) = 0;
++
++ virtual void SetBuffer(int index, sample_t* buffer);
++ virtual sample_t* GetBuffer(int index);
++
++ //jack<->buffer
++ virtual int RenderFromJackPorts();
++ virtual void RenderToJackPorts();
++
++ //network<->buffer
++ virtual int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num) = 0;
++ virtual int RenderToNetwork(int sub_cycle, uint32_t port_num) = 0;
++
++ virtual void RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle, size_t copy_size) {}
++ virtual void RenderToNetwork(char* net_buffer, int active_port, int sub_cycle, size_t copy_size) {}
++
++ virtual int ActivePortsToNetwork(char* net_buffer);
++ virtual void ActivePortsFromNetwork(char* net_buffer, uint32_t port_num);
++
++ };
++
++ class SERVER_EXPORT NetFloatAudioBuffer : public NetAudioBuffer
++ {
++
++ private:
++
++ int fPacketSize;
++
++ void UpdateParams(int active_ports);
++
++ public:
++
++ NetFloatAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
++ virtual ~NetFloatAudioBuffer();
++
++ // needed size in bytes for an entire cycle
++ size_t GetCycleSize();
++
++ // cycle duration in sec
++ float GetCycleDuration();
++ int GetNumPackets(int active_ports);
++
++ //jack<->buffer
++ int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
++ int RenderToNetwork(int sub_cycle, uint32_t port_num);
++
++ void RenderFromNetwork(char* net_buffer, int active_port, int sub_cycle);
++ void RenderToNetwork(char* net_buffer, int active_port, int sub_cycle);
++
++ };
++
++#if HAVE_CELT
++
++#include <celt/celt.h>
++
++ class SERVER_EXPORT NetCeltAudioBuffer : public NetAudioBuffer
++ {
++ private:
++
++ CELTMode** fCeltMode;
++ CELTEncoder** fCeltEncoder;
++ CELTDecoder** fCeltDecoder;
++
++ int fCompressedSizeByte;
++ int fNumPackets;
++
++ size_t fLastSubPeriodBytesSize;
++
++ unsigned char** fCompressedBuffer;
++
++ void FreeCelt();
++
+ public:
+- NetAudioBuffer ( session_params_t* params, uint32_t nports, char* net_buffer );
+- ~NetAudioBuffer();
+
+- size_t GetSize();
++ NetCeltAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer, int kbps);
++ virtual ~NetCeltAudioBuffer();
++
++ // needed size in bytes for an entire cycle
++ size_t GetCycleSize();
++
++ // cycle duration in sec
++ float GetCycleDuration();
++ int GetNumPackets(int active_ports);
++
+ //jack<->buffer
+- void RenderFromJackPorts ( int subcycle );
+- void RenderToJackPorts ( int subcycle );
++ int RenderFromJackPorts();
++ void RenderToJackPorts();
++
++ //network<->buffer
++ int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
++ int RenderToNetwork(int sub_cycle, uint32_t port_num);
++ };
++
++#endif
++
++ class SERVER_EXPORT NetIntAudioBuffer : public NetAudioBuffer
++ {
++ private:
+
+- void SetBuffer ( int index, sample_t* buffer );
+- sample_t* GetBuffer ( int index );
++ int fCompressedSizeByte;
++ int fNumPackets;
++
++ size_t fLastSubPeriodBytesSize;
++
++ short** fIntBuffer;
++
++ public:
++
++ NetIntAudioBuffer(session_params_t* params, uint32_t nports, char* net_buffer);
++ virtual ~NetIntAudioBuffer();
++
++ // needed size in bytes for an entire cycle
++ size_t GetCycleSize();
++
++ // cycle duration in sec
++ float GetCycleDuration();
++ int GetNumPackets(int active_ports);
++
++ //jack<->buffer
++ int RenderFromJackPorts();
++ void RenderToJackPorts();
++
++ //network<->buffer
++ int RenderFromNetwork(int cycle, int sub_cycle, uint32_t port_num);
++ int RenderToNetwork(int sub_cycle, uint32_t port_num);
+ };
+
+-//utility *************************************************************************************
++ //utility *************************************************************************************
+
+ //socket API management
+ SERVER_EXPORT int SocketAPIInit();
+ SERVER_EXPORT int SocketAPIEnd();
+ //n<-->h functions
+- SERVER_EXPORT void SessionParamsHToN ( session_params_t* src_params, session_params_t* dst_params );
+- SERVER_EXPORT void SessionParamsNToH ( session_params_t* src_params, session_params_t* dst_params );
+- SERVER_EXPORT void PacketHeaderHToN ( packet_header_t* src_header, packet_header_t* dst_header );
+- SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* src_header, packet_header_t* dst_header );
+- SERVER_EXPORT void MidiBufferHToN ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer );
+- SERVER_EXPORT void MidiBufferNToH ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer );
+- SERVER_EXPORT void TransportDataHToN ( net_transport_data_t* src_params, net_transport_data_t* dst_params );
+- SERVER_EXPORT void TransportDataNToH ( net_transport_data_t* src_params, net_transport_data_t* dst_params );
++ SERVER_EXPORT void SessionParamsHToN(session_params_t* src_params, session_params_t* dst_params);
++ SERVER_EXPORT void SessionParamsNToH(session_params_t* src_params, session_params_t* dst_params);
++ SERVER_EXPORT void PacketHeaderHToN(packet_header_t* src_header, packet_header_t* dst_header);
++ SERVER_EXPORT void PacketHeaderNToH(packet_header_t* src_header, packet_header_t* dst_header);
++ SERVER_EXPORT void MidiBufferHToN(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer);
++ SERVER_EXPORT void MidiBufferNToH(JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer);
++ SERVER_EXPORT void TransportDataHToN(net_transport_data_t* src_params, net_transport_data_t* dst_params);
++ SERVER_EXPORT void TransportDataNToH(net_transport_data_t* src_params, net_transport_data_t* dst_params);
+ //display session parameters
+- SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params );
++ SERVER_EXPORT void SessionParamsDisplay(session_params_t* params);
+ //display packet header
+- SERVER_EXPORT void PacketHeaderDisplay ( packet_header_t* header );
++ SERVER_EXPORT void PacketHeaderDisplay(packet_header_t* header);
+ //get the packet type from a sesion parameters
+- SERVER_EXPORT sync_packet_type_t GetPacketType ( session_params_t* params );
++ SERVER_EXPORT sync_packet_type_t GetPacketType(session_params_t* params);
+ //set the packet type in a session parameters
+- SERVER_EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type );
++ SERVER_EXPORT int SetPacketType(session_params_t* params, sync_packet_type_t packet_type);
+ //transport utility
+- SERVER_EXPORT const char* GetTransportState ( int transport_state );
+- SERVER_EXPORT void NetTransportDataDisplay ( net_transport_data_t* data );
++ SERVER_EXPORT const char* GetTransportState(int transport_state);
++ SERVER_EXPORT void NetTransportDataDisplay(net_transport_data_t* data);
+ }
+--- a/common/JackPhysicalMidiInput.cpp
++++ /dev/null
+@@ -1,287 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#include <cassert>
+-#include <cstring>
+-#include <new>
+-
+-#include "JackError.h"
+-#include "JackPhysicalMidiInput.h"
+-
+-namespace Jack {
+-
+-JackPhysicalMidiInput::JackPhysicalMidiInput(size_t buffer_size)
+-{
+- size_t datum_size = sizeof(jack_midi_data_t);
+- assert(buffer_size > 0);
+- input_ring = jack_ringbuffer_create((buffer_size + 1) * datum_size);
+- if (! input_ring) {
+- throw std::bad_alloc();
+- }
+- jack_ringbuffer_mlock(input_ring);
+- Clear();
+- expected_data_bytes = 0;
+- status_byte = 0;
+-}
+-
+-JackPhysicalMidiInput::~JackPhysicalMidiInput()
+-{
+- jack_ringbuffer_free(input_ring);
+-}
+-
+-void
+-JackPhysicalMidiInput::Clear()
+-{
+- jack_ringbuffer_reset(input_ring);
+- buffered_bytes = 0;
+- unbuffered_bytes = 0;
+-}
+-
+-void
+-JackPhysicalMidiInput::HandleBufferFailure(size_t unbuffered_bytes,
+- size_t total_bytes)
+-{
+- jack_error("%d MIDI byte(s) of a %d byte message could not be buffered - "
+- "message dropped", unbuffered_bytes, total_bytes);
+-}
+-
+-void
+-JackPhysicalMidiInput::HandleIncompleteMessage(size_t bytes)
+-{
+- jack_error("Discarding %d MIDI byte(s) - incomplete message (cable "
+- "unplugged?)", bytes);
+-}
+-
+-void
+-JackPhysicalMidiInput::HandleInvalidStatusByte(jack_midi_data_t status)
+-{
+- jack_error("Dropping invalid MIDI status byte '%x'",
+- (unsigned int) status);
+-}
+-
+-void
+-JackPhysicalMidiInput::HandleUnexpectedSysexEnd(size_t bytes)
+-{
+- jack_error("Discarding %d MIDI byte(s) - received sysex end without sysex "
+- "start (cable unplugged?)", bytes);
+-}
+-
+-void
+-JackPhysicalMidiInput::HandleWriteFailure(size_t bytes)
+-{
+- jack_error("Failed to write a %d byte MIDI message to the port buffer",
+- bytes);
+-}
+-
+-void
+-JackPhysicalMidiInput::Process(jack_nframes_t frames)
+-{
+- assert(port_buffer);
+- port_buffer->Reset(frames);
+- jack_nframes_t current_frame = 0;
+- size_t datum_size = sizeof(jack_midi_data_t);
+- for (;;) {
+- jack_midi_data_t datum;
+- current_frame = Receive(&datum, current_frame, frames);
+- if (current_frame >= frames) {
+- break;
+- }
+-
+- jack_log("JackPhysicalMidiInput::Process (%d) - Received '%x' byte",
+- current_frame, (unsigned int) datum);
+-
+- if (datum >= 0xf8) {
+- // Realtime
+- if (datum == 0xfd) {
+- HandleInvalidStatusByte(datum);
+- } else {
+-
+- jack_log("JackPhysicalMidiInput::Process - Writing realtime "
+- "event.");
+-
+- WriteByteEvent(current_frame, datum);
+- }
+- continue;
+- }
+- if (datum == 0xf7) {
+- // Sysex end
+- if (status_byte != 0xf0) {
+- HandleUnexpectedSysexEnd(buffered_bytes + unbuffered_bytes);
+- Clear();
+- expected_data_bytes = 0;
+- status_byte = 0;
+- } else {
+-
+- jack_log("JackPhysicalMidiInput::Process - Writing sysex "
+- "event.");
+-
+- WriteBufferedSysexEvent(current_frame);
+- }
+- continue;
+- }
+- if (datum >= 0x80) {
+-
+- // We're handling a non-realtime status byte
+-
+- jack_log("JackPhysicalMidiInput::Process - Handling non-realtime "
+- "status byte.");
+-
+- if (buffered_bytes || unbuffered_bytes) {
+- HandleIncompleteMessage(buffered_bytes + unbuffered_bytes + 1);
+- Clear();
+- }
+- status_byte = datum;
+- switch (datum & 0xf0) {
+- case 0x80:
+- case 0x90:
+- case 0xa0:
+- case 0xb0:
+- case 0xe0:
+- // Note On, Note Off, Aftertouch, Control Change, Pitch Wheel
+- expected_data_bytes = 2;
+- break;
+- case 0xc0:
+- case 0xd0:
+- // Program Change, Channel Pressure
+- expected_data_bytes = 1;
+- break;
+- case 0xf0:
+- switch (datum) {
+- case 0xf0:
+- // Sysex message
+- expected_data_bytes = 0;
+- break;
+- case 0xf1:
+- case 0xf3:
+- // MTC Quarter frame, Song Select
+- expected_data_bytes = 1;
+- break;
+- case 0xf2:
+- // Song Position
+- expected_data_bytes = 2;
+- break;
+- case 0xf4:
+- case 0xf5:
+- // Undefined
+- HandleInvalidStatusByte(datum);
+- expected_data_bytes = 0;
+- status_byte = 0;
+- break;
+- case 0xf6:
+- // Tune Request
+- WriteByteEvent(current_frame, datum);
+- expected_data_bytes = 0;
+- status_byte = 0;
+- }
+- break;
+- }
+- continue;
+- }
+-
+- // We're handling a data byte
+-
+- jack_log("JackPhysicalMidiInput::Process - Buffering data byte.");
+-
+- if (jack_ringbuffer_write(input_ring, (const char *) &datum,
+- datum_size) == datum_size) {
+- buffered_bytes++;
+- } else {
+- unbuffered_bytes++;
+- }
+- unsigned long total_bytes = buffered_bytes + unbuffered_bytes;
+- assert((! expected_data_bytes) ||
+- (total_bytes <= expected_data_bytes));
+- if (total_bytes == expected_data_bytes) {
+- if (! unbuffered_bytes) {
+-
+- jack_log("JackPhysicalMidiInput::Process - Writing buffered "
+- "event.");
+-
+- WriteBufferedEvent(current_frame);
+- } else {
+- HandleBufferFailure(unbuffered_bytes, total_bytes);
+- Clear();
+- }
+- if (status_byte >= 0xf0) {
+- expected_data_bytes = 0;
+- status_byte = 0;
+- }
+- }
+- }
+-}
+-
+-void
+-JackPhysicalMidiInput::WriteBufferedEvent(jack_nframes_t frame)
+-{
+- assert(port_buffer && port_buffer->IsValid());
+- size_t space = jack_ringbuffer_read_space(input_ring);
+- jack_midi_data_t *event = port_buffer->ReserveEvent(frame, space + 1);
+- if (event) {
+- jack_ringbuffer_data_t vector[2];
+- jack_ringbuffer_get_read_vector(input_ring, vector);
+- event[0] = status_byte;
+- size_t data_length_1 = vector[0].len;
+- memcpy(event + 1, vector[0].buf, data_length_1);
+- size_t data_length_2 = vector[1].len;
+- if (data_length_2) {
+- memcpy(event + data_length_1 + 1, vector[1].buf, data_length_2);
+- }
+- } else {
+- HandleWriteFailure(space + 1);
+- }
+- Clear();
+-}
+-
+-void
+-JackPhysicalMidiInput::WriteBufferedSysexEvent(jack_nframes_t frame)
+-{
+- assert(port_buffer && port_buffer->IsValid());
+- size_t space = jack_ringbuffer_read_space(input_ring);
+- jack_midi_data_t *event = port_buffer->ReserveEvent(frame, space + 2);
+- if (event) {
+- jack_ringbuffer_data_t vector[2];
+- jack_ringbuffer_get_read_vector(input_ring, vector);
+- event[0] = status_byte;
+- size_t data_length_1 = vector[0].len;
+- memcpy(event + 1, vector[0].buf, data_length_1);
+- size_t data_length_2 = vector[1].len;
+- if (data_length_2) {
+- memcpy(event + data_length_1 + 1, vector[1].buf, data_length_2);
+- }
+- event[data_length_1 + data_length_2 + 1] = 0xf7;
+- } else {
+- HandleWriteFailure(space + 2);
+- }
+- Clear();
+-}
+-
+-void
+-JackPhysicalMidiInput::WriteByteEvent(jack_nframes_t frame,
+- jack_midi_data_t datum)
+-{
+- assert(port_buffer && port_buffer->IsValid());
+- jack_midi_data_t *event = port_buffer->ReserveEvent(frame, 1);
+- if (event) {
+- event[0] = datum;
+- } else {
+- HandleWriteFailure(1);
+- }
+-}
+-
+-}
+--- a/common/JackPhysicalMidiInput.h
++++ /dev/null
+@@ -1,146 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#ifndef __JackPhysicalMidiInput__
+-#define __JackPhysicalMidiInput__
+-
+-#include "JackMidiPort.h"
+-#include "ringbuffer.h"
+-
+-namespace Jack {
+-
+- class JackPhysicalMidiInput {
+-
+- private:
+-
+- size_t buffered_bytes;
+- size_t expected_data_bytes;
+- jack_ringbuffer_t *input_ring;
+- JackMidiBuffer *port_buffer;
+- jack_midi_data_t status_byte;
+- size_t unbuffered_bytes;
+-
+- void
+- Clear();
+-
+- void
+- WriteBufferedEvent(jack_nframes_t);
+-
+- void
+- WriteBufferedSysexEvent(jack_nframes_t);
+-
+- void
+- WriteByteEvent(jack_nframes_t, jack_midi_data_t);
+-
+- protected:
+-
+- /**
+- * Override to specify how to react when 1 or more bytes of a MIDI
+- * message are lost because there wasn't enough room in the input
+- * buffer. The first argument is the amount of bytes that couldn't be
+- * buffered, and the second argument is the total amount of bytes in
+- * the MIDI message. The default implementation calls 'jack_error'
+- * with a basic error message.
+- */
+-
+- virtual void
+- HandleBufferFailure(size_t, size_t);
+-
+- /**
+- * Override to specify how to react when a new status byte is received
+- * before all of the data bytes in a message are received. The
+- * argument is the number of bytes being discarded. The default
+- * implementation calls 'jack_error' with a basic error message.
+- */
+-
+- virtual void
+- HandleIncompleteMessage(size_t);
+-
+- /**
+- * Override to specify how to react when an invalid status byte (0xf4,
+- * 0xf5, 0xfd) is received. The argument contains the invalid status
+- * byte. The default implementation calls 'jack_error' with a basic
+- * error message.
+- */
+-
+- virtual void
+- HandleInvalidStatusByte(jack_midi_data_t);
+-
+- /**
+- * Override to specify how to react when a sysex end byte (0xf7) is
+- * received without first receiving a sysex start byte (0xf0). The
+- * argument contains the amount of bytes that will be discarded. The
+- * default implementation calls 'jack_error' with a basic error
+- * message.
+- */
+-
+- virtual void
+- HandleUnexpectedSysexEnd(size_t);
+-
+- /**
+- * Override to specify how to react when a MIDI message can not be
+- * written to the port buffer. The argument specifies the length of
+- * the MIDI message. The default implementation calls 'jack_error'
+- * with a basic error message.
+- */
+-
+- virtual void
+- HandleWriteFailure(size_t);
+-
+- /**
+- * This method *must* be overridden to handle receiving MIDI bytes.
+- * The first argument is a pointer to the memory location at which the
+- * MIDI byte should be stored. The second argument is the last frame
+- * at which a MIDI byte was received, except at the beginning of the
+- * period when the value is 0. The third argument is the total number
+- * of frames in the period. The return value is the frame at which the
+- * MIDI byte is received at, or the value of the third argument is no
+- * more MIDI bytes can be received in this period.
+- */
+-
+- virtual jack_nframes_t
+- Receive(jack_midi_data_t *, jack_nframes_t, jack_nframes_t) = 0;
+-
+- public:
+-
+- JackPhysicalMidiInput(size_t buffer_size=1024);
+- virtual ~JackPhysicalMidiInput();
+-
+- /**
+- * Called to process MIDI data during a period.
+- */
+-
+- void
+- Process(jack_nframes_t);
+-
+- /**
+- * Set the MIDI buffer that will receive incoming messages.
+- */
+-
+- inline void
+- SetPortBuffer(JackMidiBuffer *port_buffer)
+- {
+- this->port_buffer = port_buffer;
+- }
+-
+- };
+-
+-}
+-
+-#endif
+--- a/common/JackPhysicalMidiOutput.cpp
++++ /dev/null
+@@ -1,320 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#include <cassert>
+-
+-#include "JackError.h"
+-#include "JackPhysicalMidiOutput.h"
+-
+-namespace Jack {
+-
+-JackPhysicalMidiOutput::JackPhysicalMidiOutput(size_t non_rt_buffer_size,
+- size_t rt_buffer_size)
+-{
+- size_t datum_size = sizeof(jack_midi_data_t);
+- assert(non_rt_buffer_size > 0);
+- assert(rt_buffer_size > 0);
+- output_ring = jack_ringbuffer_create((non_rt_buffer_size + 1) *
+- datum_size);
+- if (! output_ring) {
+- throw std::bad_alloc();
+- }
+- rt_output_ring = jack_ringbuffer_create((rt_buffer_size + 1) *
+- datum_size);
+- if (! rt_output_ring) {
+- jack_ringbuffer_free(output_ring);
+- throw std::bad_alloc();
+- }
+- jack_ringbuffer_mlock(output_ring);
+- jack_ringbuffer_mlock(rt_output_ring);
+- running_status = 0;
+-}
+-
+-JackPhysicalMidiOutput::~JackPhysicalMidiOutput()
+-{
+- jack_ringbuffer_free(output_ring);
+- jack_ringbuffer_free(rt_output_ring);
+-}
+-
+-jack_nframes_t
+-JackPhysicalMidiOutput::Advance(jack_nframes_t frame)
+-{
+- return frame;
+-}
+-
+-inline jack_midi_data_t
+-JackPhysicalMidiOutput::ApplyRunningStatus(jack_midi_data_t **buffer,
+- size_t *size)
+-{
+-
+- // Stolen and modified from alsa/midi_pack.h
+-
+- jack_midi_data_t status = (*buffer)[0];
+- if ((status >= 0x80) && (status < 0xf0)) {
+- if (status == running_status) {
+- (*buffer)++;
+- (*size)--;
+- } else {
+- running_status = status;
+- }
+- } else if (status < 0xf8) {
+- running_status = 0;
+- }
+- return status;
+-}
+-
+-void
+-JackPhysicalMidiOutput::HandleEventLoss(JackMidiEvent *event)
+-{
+- jack_error("%d byte MIDI event lost", event->size);
+-}
+-
+-void
+-JackPhysicalMidiOutput::Process(jack_nframes_t frames)
+-{
+- assert(port_buffer);
+- jack_nframes_t current_frame = Advance(0);
+- jack_nframes_t current_midi_event = 0;
+- jack_midi_data_t datum;
+- size_t datum_size = sizeof(jack_midi_data_t);
+- JackMidiEvent *midi_event;
+- jack_midi_data_t *midi_event_buffer;
+- size_t midi_event_size;
+- jack_nframes_t midi_events = port_buffer->event_count;
+-
+- // First, send any realtime MIDI data that's left from last cycle.
+-
+- if ((current_frame < frames) &&
+- jack_ringbuffer_read_space(rt_output_ring)) {
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sending buffered "
+- "realtime data from last period.", current_frame);
+-
+- current_frame = SendBufferedData(rt_output_ring, current_frame,
+- frames);
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sent", current_frame);
+-
+- }
+-
+- // Iterate through the events in this cycle.
+-
+- for (; (current_midi_event < midi_events) && (current_frame < frames);
+- current_midi_event++) {
+-
+- // Once we're inside this loop, we know that the realtime buffer
+- // is empty. As long as we don't find a realtime message, we can
+- // concentrate on sending non-realtime data.
+-
+- midi_event = &(port_buffer->events[current_midi_event]);
+- jack_nframes_t midi_event_time = midi_event->time;
+- midi_event_buffer = midi_event->GetData(port_buffer);
+- midi_event_size = midi_event->size;
+- datum = ApplyRunningStatus(&midi_event_buffer, &midi_event_size);
+- if (current_frame < midi_event_time) {
+-
+- // We have time before this event is scheduled to be sent.
+- // Send data in the non-realtime buffer.
+-
+- if (jack_ringbuffer_read_space(output_ring)) {
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sending "
+- "buffered non-realtime data from last period.",
+- current_frame);
+-
+- current_frame = SendBufferedData(output_ring, current_frame,
+- midi_event_time);
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sent",
+- current_frame);
+-
+- }
+- if (current_frame < midi_event_time) {
+-
+- // We _still_ have time before this event is scheduled to
+- // be sent. Let's send as much of this event as we can
+- // (save for one byte, which will need to be sent at or
+- // after its scheduled time). First though, we need to
+- // make sure that we can buffer this data if we need to.
+- // Otherwise, we might start sending a message that we
+- // can't finish.
+-
+- if (midi_event_size > 1) {
+- if (jack_ringbuffer_write_space(output_ring) <
+- ((midi_event_size - 1) * datum_size)) {
+- HandleEventLoss(midi_event);
+- continue;
+- }
+-
+- // Send as much of the event as possible (save for one
+- // byte).
+-
+- do {
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - "
+- "Sending unbuffered event byte early.",
+- current_frame);
+-
+- current_frame = Send(current_frame,
+- *midi_event_buffer);
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - "
+- "Sent.", current_frame);
+-
+- midi_event_buffer++;
+- midi_event_size--;
+- if (current_frame >= midi_event_time) {
+-
+- // The event we're processing must be a
+- // non-realtime event. It has more than one
+- // byte.
+-
+- goto buffer_non_realtime_data;
+- }
+- } while (midi_event_size > 1);
+- }
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Advancing to "
+- ">= %d", current_frame, midi_event_time);
+-
+- current_frame = Advance(midi_event_time);
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Advanced.",
+- current_frame);
+-
+- }
+- }
+-
+- // If the event is realtime, then we'll send the event now.
+- // Otherwise, we attempt to put the rest of the event bytes in the
+- // non-realtime buffer.
+-
+- if (datum >= 0xf8) {
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sending "
+- "unbuffered realtime event.", current_frame);
+-
+- current_frame = Send(current_frame, datum);
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sent.",
+- current_frame);
+-
+- } else if (jack_ringbuffer_write_space(output_ring) >=
+- (midi_event_size * datum_size)) {
+- buffer_non_realtime_data:
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Buffering %d "
+- "byte(s) of non-realtime data.", current_frame,
+- midi_event_size);
+-
+- jack_ringbuffer_write(output_ring,
+- (const char *) midi_event_buffer,
+- midi_event_size);
+- } else {
+- HandleEventLoss(midi_event);
+- }
+- }
+-
+- if (current_frame < frames) {
+-
+- // If we have time left to send data, then we know that all of the
+- // data in the realtime buffer has been sent, and that all of the
+- // non-realtime messages have either been sent, or buffered. We
+- // use whatever time is left to send data in the non-realtime
+- // buffer.
+-
+- if (jack_ringbuffer_read_space(output_ring)) {
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - All events "
+- "processed. Sending buffered non-realtime data.",
+- current_frame);
+-
+- current_frame = SendBufferedData(output_ring, current_frame,
+- frames);
+-
+- jack_log("JackPhysicalMidiOutput::Process (%d) - Sent.",
+- current_frame);
+-
+- }
+- } else {
+-
+- // Since we have no time left, we need to put all remaining midi
+- // events in their appropriate buffers, and send them next period.
+-
+- for (; current_midi_event < midi_events; current_midi_event++) {
+- midi_event = &(port_buffer->events[current_midi_event]);
+- midi_event_buffer = midi_event->GetData(port_buffer);
+- midi_event_size = midi_event->size;
+- datum = ApplyRunningStatus(&midi_event_buffer, &midi_event_size);
+- if (datum >= 0xf8) {
+-
+- // Realtime.
+-
+- if (jack_ringbuffer_write_space(rt_output_ring) >=
+- datum_size) {
+-
+- jack_log("JackPhysicalMidiOutput::Process - Buffering "
+- "realtime event for next period.");
+-
+- jack_ringbuffer_write(rt_output_ring,
+- (const char *) &datum, datum_size);
+- continue;
+- }
+- } else {
+-
+- // Non-realtime.
+-
+- if (jack_ringbuffer_write_space(output_ring) >=
+- (midi_event_size * datum_size)) {
+-
+- jack_log("JackPhysicalMidiOutput::Process - Buffering "
+- "non-realtime event for next period.");
+-
+- jack_ringbuffer_write(output_ring,
+- (const char *) midi_event_buffer,
+- midi_event_size * datum_size);
+- continue;
+- }
+- }
+- HandleEventLoss(midi_event);
+- }
+- }
+-}
+-
+-jack_nframes_t
+-JackPhysicalMidiOutput::SendBufferedData(jack_ringbuffer_t *buffer,
+- jack_nframes_t current_frame,
+- jack_nframes_t boundary)
+-{
+- assert(buffer);
+- assert(current_frame < boundary);
+- size_t datum_size = sizeof(jack_midi_data_t);
+- size_t data_length = jack_ringbuffer_read_space(buffer) / datum_size;
+- for (size_t i = 0; i < data_length; i++) {
+- jack_midi_data_t datum;
+- jack_ringbuffer_read(buffer, (char *) &datum, datum_size);
+- current_frame = Send(current_frame, datum);
+- if (current_frame >= boundary) {
+- break;
+- }
+- }
+- return current_frame;
+-}
+-
+-}
+--- a/common/JackPhysicalMidiOutput.h
++++ /dev/null
+@@ -1,118 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#ifndef __JackPhysicalMidiOutput__
+-#define __JackPhysicalMidiOutput__
+-
+-#include "JackMidiPort.h"
+-#include "ringbuffer.h"
+-
+-namespace Jack {
+-
+- class JackPhysicalMidiOutput {
+-
+- private:
+-
+- jack_midi_data_t
+- ApplyRunningStatus(jack_midi_data_t **, size_t *);
+-
+- jack_ringbuffer_t *output_ring;
+- JackMidiBuffer *port_buffer;
+- jack_ringbuffer_t *rt_output_ring;
+- jack_midi_data_t running_status;
+-
+- protected:
+-
+- /**
+- * Override to specify the next frame at which a midi byte can be sent.
+- * The returned frame must be greater than or equal to the frame
+- * argument. The default returns the frame passed to it.
+- */
+-
+- virtual jack_nframes_t
+- Advance(jack_nframes_t);
+-
+- /**
+- * Override to customize how to react when a MIDI event can't be
+- * buffered and can't be sent immediately. The default calls
+- * 'jack_error' and specifies the number of bytes lost.
+- */
+-
+- virtual void
+- HandleEventLoss(JackMidiEvent *);
+-
+- /**
+- * This method *must* be overridden to specify what happens when a MIDI
+- * byte is sent at the specfied frame. The frame argument specifies
+- * the frame at which the MIDI byte should be sent, and the second
+- * argument specifies the byte itself. The return value is the next
+- * frame at which a MIDI byte can be sent, and must be greater than or
+- * equal to the frame argument.
+- */
+-
+- virtual jack_nframes_t
+- Send(jack_nframes_t, jack_midi_data_t) = 0;
+-
+- /**
+- * Override to optimize behavior when sending MIDI data that's in the
+- * ringbuffer. The first frame argument is the current frame, and the
+- * second frame argument is the boundary frame. The function returns
+- * the next frame at which MIDI data can be sent, regardless of whether
+- * or not the boundary is reached. The default implementation calls
+- * 'Send' with each byte in the ringbuffer until either the ringbuffer
+- * is empty, or a frame beyond the boundary frame is returned by
+- * 'Send'.
+- */
+-
+- virtual jack_nframes_t
+- SendBufferedData(jack_ringbuffer_t *, jack_nframes_t, jack_nframes_t);
+-
+- public:
+-
+- /**
+- * The non-realtime buffer size and the realtime buffer size are both
+- * optional arguments.
+- */
+-
+- JackPhysicalMidiOutput(size_t non_rt_buffer_size=1024,
+- size_t rt_buffer_size=64);
+- virtual ~JackPhysicalMidiOutput();
+-
+- /**
+- * Called to process MIDI data during a period.
+- */
+-
+- void
+- Process(jack_nframes_t);
+-
+- /**
+- * Set the MIDI buffer that will contain the outgoing MIDI messages.
+- */
+-
+- inline void
+- SetPortBuffer(JackMidiBuffer *port_buffer)
+- {
+- this->port_buffer = port_buffer;
+- }
+-
+- };
+-
+-}
+-
+-#endif
+--- a/common/JackPort.cpp
++++ b/common/JackPort.cpp
+@@ -35,6 +35,7 @@
+ bool JackPort::Allocate(int refnum, const char* port_name, const char* port_type, JackPortFlags flags)
+ {
+ jack_port_type_id_t id = GetPortTypeId(port_type);
++ assert(id >= 0 && id <= PORT_TYPES_MAX);
+ if (id == PORT_TYPES_MAX)
+ return false;
+ fTypeId = id;
+@@ -44,6 +45,7 @@
+ fInUse = true;
+ fLatency = 0;
+ fTotalLatency = 0;
++ fMonitorRequests = 0;
+ fPlaybackLatency.min = fPlaybackLatency.max = 0;
+ fCaptureLatency.min = fCaptureLatency.max = 0;
+ fTied = NO_PORT;
+@@ -65,6 +67,8 @@
+ fLatency = 0;
+ fTotalLatency = 0;
+ fMonitorRequests = 0;
++ fPlaybackLatency.min = fPlaybackLatency.max = 0;
++ fCaptureLatency.min = fCaptureLatency.max = 0;
+ fTied = NO_PORT;
+ fAlias1[0] = '\0';
+ fAlias2[0] = '\0';
+@@ -107,7 +111,7 @@
+ if (mode == JackCaptureLatency) {
+ fCaptureLatency = *range;
+
+- /* hack to set port->shared->latency up for
++ /* hack to set latency up for
+ * backend ports
+ */
+ if ((fFlags & JackPortIsOutput) && (fFlags & JackPortIsPhysical))
+@@ -115,7 +119,7 @@
+ } else {
+ fPlaybackLatency = *range;
+
+- /* hack to set port->shared->latency up for
++ /* hack to set latency up for
+ * backend ports
+ */
+ if ((fFlags & JackPortIsInput) && (fFlags & JackPortIsPhysical))
+@@ -221,7 +225,7 @@
+
+ bool JackPort::NameEquals(const char* target)
+ {
+- char buf[JACK_PORT_NAME_SIZE + 1];
++ char buf[REAL_JACK_PORT_NAME_SIZE];
+
+ /* this nasty, nasty kludge is here because between 0.109.0 and 0.109.1,
+ the ALSA audio backend had the name "ALSA", whereas as before and
+@@ -245,12 +249,12 @@
+ int cnt = 0;
+
+ if (fAlias1[0] != '\0') {
+- snprintf(aliases[0], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias1);
++ snprintf(aliases[0], REAL_JACK_PORT_NAME_SIZE, "%s", fAlias1);
+ cnt++;
+ }
+
+ if (fAlias2[0] != '\0') {
+- snprintf(aliases[1], JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE, "%s", fAlias2);
++ snprintf(aliases[1], REAL_JACK_PORT_NAME_SIZE, "%s", fAlias2);
+ cnt++;
+ }
+
+--- a/common/JackPort.h
++++ b/common/JackPort.h
+@@ -35,6 +35,7 @@
+ \brief Base class for port.
+ */
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackPort
+ {
+
+@@ -44,9 +45,9 @@
+
+ int fTypeId;
+ enum JackPortFlags fFlags;
+- char fName[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char fAlias1[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char fAlias2[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
++ char fName[REAL_JACK_PORT_NAME_SIZE];
++ char fAlias1[REAL_JACK_PORT_NAME_SIZE];
++ char fAlias2[REAL_JACK_PORT_NAME_SIZE];
+ int fRefNum;
+
+ jack_nframes_t fLatency;
+@@ -107,7 +108,7 @@
+ // Since we are in shared memory, the resulting pointer cannot be cached, so align it here...
+ jack_default_audio_sample_t* GetBuffer()
+ {
+- return (jack_default_audio_sample_t*)((long)fBuffer & ~15L) + 4;
++ return (jack_default_audio_sample_t*)((uintptr_t)fBuffer & ~15L) + 4;
+ }
+
+ int GetRefNum() const;
+--- a/common/JackProfiler.cpp
++++ b/common/JackProfiler.cpp
+@@ -206,37 +206,16 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t* desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "profiler"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "real-time server profiling"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 3;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- int i = 0;
+- strcpy(desc->params[i].name, "cpu-load");
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Show DSP CPU load");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "driver-period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Show driver period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "driver-end-time");
+- desc->params[i].character = 'e';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Show driver end time");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("profiler", JackDriverNone, "real-time server profiling", &filler);
++
++ value.i = FALSE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "cpu-load", 'c', JackDriverParamBool, &value, NULL, "Show DSP CPU load", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "driver-period", 'p', JackDriverParamBool, &value, NULL, "Show driver period", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "driver-end-time", 'e', JackDriverParamBool, &value, NULL, "Show driver end time", NULL);
+
+ return desc;
+ }
+--- a/common/JackRequest.h
++++ b/common/JackRequest.h
+@@ -23,15 +23,28 @@
+
+ #include "JackConstants.h"
+ #include "JackPlatformPlug.h"
++#include "JackTime.h"
+ #include "types.h"
+ #include <string.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <list>
+
+ namespace Jack
+ {
+
+-#define CheckRes(exp) { if ((exp) < 0) return -1;}
++#define CheckRes(exp) { if ((exp) < 0) return -1; }
++
++/*!
++\brief Session API constants.
++*/
++
++enum JackSessionReply {
++
++ kImmediateSessionReply = 1,
++ kPendingSessionReply = 2
++
++};
+
+ /*!
+ \brief Request from client to server.
+@@ -78,7 +91,7 @@
+
+ RequestType fType;
+
+- JackRequest()
++ JackRequest(): fType((RequestType)0)
+ {}
+
+ JackRequest(RequestType type): fType(type)
+@@ -138,11 +151,12 @@
+ int fProtocol;
+ int fOptions;
+ int fUUID;
++ int fOpen;
+
+ JackClientCheckRequest()
+ {}
+- JackClientCheckRequest(const char* name, int protocol, int options, int uuid)
+- : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid)
++ JackClientCheckRequest(const char* name, int protocol, int options, int uuid, int open = false)
++ : JackRequest(JackRequest::kClientCheck), fProtocol(protocol), fOptions(options), fUUID(uuid), fOpen(open)
+ {
+ snprintf(fName, sizeof(fName), "%s", name);
+ }
+@@ -152,16 +166,18 @@
+ CheckRes(trans->Read(&fName, sizeof(fName)));
+ CheckRes(trans->Read(&fProtocol, sizeof(int)));
+ CheckRes(trans->Read(&fOptions, sizeof(int)));
+- return trans->Read(&fUUID, sizeof(int));
++ CheckRes(trans->Read(&fUUID, sizeof(int)));
++ return trans->Read(&fOpen, sizeof(int));
+ }
+
+ int Write(JackChannelTransaction* trans)
+ {
+ CheckRes(JackRequest::Write(trans));
+- CheckRes(trans->Write(&fName, sizeof(fName)));
++ CheckRes(trans->Write(&fName, sizeof(fName)));
+ CheckRes(trans->Write(&fProtocol, sizeof(int)));
+ CheckRes(trans->Write(&fOptions, sizeof(int)));
+- return trans->Write(&fUUID, sizeof(int));
++ CheckRes(trans->Write(&fUUID, sizeof(int)));
++ return trans->Write(&fOpen, sizeof(int));
+ }
+
+ };
+@@ -226,7 +242,7 @@
+ {
+ CheckRes(trans->Read(&fPID, sizeof(int)));
+ CheckRes(trans->Read(&fUUID, sizeof(int)));
+- return trans->Read(&fName, sizeof(fName));
++ return trans->Read(&fName, sizeof(fName));
+ }
+
+ int Write(JackChannelTransaction* trans)
+@@ -234,7 +250,7 @@
+ CheckRes(JackRequest::Write(trans));
+ CheckRes(trans->Write(&fPID, sizeof(int)));
+ CheckRes(trans->Write(&fUUID, sizeof(int)));
+- return trans->Write(&fName, sizeof(fName));
++ return trans->Write(&fName, sizeof(fName));
+ }
+
+ };
+@@ -846,14 +862,14 @@
+ int Read(JackChannelTransaction* trans)
+ {
+ CheckRes(JackResult::Read(trans));
+- CheckRes(trans->Read(&fName, sizeof(fName)));
++ CheckRes(trans->Read(&fName, sizeof(fName)));
+ return 0;
+ }
+
+ int Write(JackChannelTransaction* trans)
+ {
+ CheckRes(JackResult::Write(trans));
+- CheckRes(trans->Write(&fName, sizeof(fName)));
++ CheckRes(trans->Write(&fName, sizeof(fName)));
+ return 0;
+ }
+
+@@ -880,14 +896,14 @@
+ int Read(JackChannelTransaction* trans)
+ {
+ CheckRes(trans->Read(&fRefNum, sizeof(int)));
+- return trans->Read(&fName, sizeof(fName));
++ return trans->Read(&fName, sizeof(fName));
+ }
+
+ int Write(JackChannelTransaction* trans)
+ {
+ CheckRes(JackRequest::Write(trans));
+ CheckRes(trans->Write(&fRefNum, sizeof(int)));
+- return trans->Write(&fName, sizeof(fName));
++ return trans->Write(&fName, sizeof(fName));
+ }
+
+ };
+@@ -958,7 +974,7 @@
+ int Read(JackChannelTransaction* trans)
+ {
+ CheckRes(trans->Read(&fRefNum, sizeof(int)));
+- CheckRes(trans->Read(&fName, sizeof(fName)));
++ CheckRes(trans->Read(&fName, sizeof(fName)));
+ CheckRes(trans->Read(&fDllName, sizeof(fDllName)));
+ CheckRes(trans->Read(&fLoadInitName, sizeof(fLoadInitName)));
+ CheckRes(trans->Read(&fUUID, sizeof(int)));
+@@ -969,7 +985,7 @@
+ {
+ CheckRes(JackRequest::Write(trans));
+ CheckRes(trans->Write(&fRefNum, sizeof(int)));
+- CheckRes(trans->Write(&fName, sizeof(fName)));
++ CheckRes(trans->Write(&fName, sizeof(fName)));
+ CheckRes(trans->Write(&fDllName, sizeof(fDllName)));
+ CheckRes(trans->Write(&fLoadInitName, sizeof(fLoadInitName)));
+ CheckRes(trans->Write(&fUUID, sizeof(int)));
+@@ -1119,11 +1135,11 @@
+ JackSessionCommand()
+ {}
+
+- JackSessionCommand( const char *uuid, const char *clientname, const char *command, jack_session_flags_t flags )
++ JackSessionCommand(const char *uuid, const char *clientname, const char *command, jack_session_flags_t flags)
+ {
+- strncpy( fUUID, uuid, sizeof(fUUID));
+- strncpy( fClientName, clientname, sizeof(fClientName));
+- strncpy( fCommand, command, sizeof(fCommand));
++ strncpy(fUUID, uuid, sizeof(fUUID));
++ strncpy(fClientName, clientname, sizeof(fClientName));
++ strncpy(fCommand, command, sizeof(fCommand));
+ fFlags = flags;
+ }
+ };
+@@ -1132,17 +1148,23 @@
+ {
+
+ std::list<JackSessionCommand> fCommandList;
++ bool fDone;
+
+- JackSessionNotifyResult(): JackResult()
++ JackSessionNotifyResult(): JackResult(), fDone(false)
+ {}
+ JackSessionNotifyResult(int32_t result)
+- : JackResult(result)
++ : JackResult(result), fDone(false)
+ {}
+
+ int Read(JackChannelTransaction* trans)
+ {
++ if (trans == NULL)
++ {
++ return 0;
++ }
++
+ CheckRes(JackResult::Read(trans));
+- while(1) {
++ while (true) {
+ JackSessionCommand buffer;
+
+ CheckRes(trans->Read(buffer.fUUID, sizeof(buffer.fUUID)));
+@@ -1155,16 +1177,25 @@
+
+ fCommandList.push_back(buffer);
+ }
++
++ fDone = true;
++
+ return 0;
+ }
+
+ int Write(JackChannelTransaction* trans)
+ {
++ if (trans == NULL)
++ {
++ fDone = true;
++ return 0;
++ }
++
+ char terminator[JACK_UUID_SIZE];
+ terminator[0] = '\0';
+
+ CheckRes(JackResult::Write(trans));
+- for (std::list<JackSessionCommand>::iterator i=fCommandList.begin(); i!=fCommandList.end(); i++) {
++ for (std::list<JackSessionCommand>::iterator i = fCommandList.begin(); i != fCommandList.end(); i++) {
+ CheckRes(trans->Write(i->fUUID, sizeof(i->fUUID)));
+ CheckRes(trans->Write(i->fClientName, sizeof(i->fClientName)));
+ CheckRes(trans->Write(i->fCommand, sizeof(i->fCommand)));
+@@ -1174,6 +1205,32 @@
+ return 0;
+ }
+
++ jack_session_command_t* GetCommands()
++ {
++ /* TODO: some kind of signal should be used instead */
++ while (!fDone)
++ {
++ JackSleep(50000); /* 50 ms */
++ }
++
++ jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (fCommandList.size() + 1));
++ int i = 0;
++
++ for (std::list<JackSessionCommand>::iterator ci = fCommandList.begin(); ci != fCommandList.end(); ci++) {
++ session_command[i].uuid = strdup(ci->fUUID);
++ session_command[i].client_name = strdup(ci->fClientName);
++ session_command[i].command = strdup(ci->fCommand);
++ session_command[i].flags = ci->fFlags;
++ i += 1;
++ }
++
++ session_command[i].uuid = NULL;
++ session_command[i].client_name = NULL;
++ session_command[i].command = NULL;
++ session_command[i].flags = (jack_session_flags_t)0;
++
++ return session_command;
++ }
+ };
+
+ /*!
+@@ -1184,19 +1241,20 @@
+ {
+ char fPath[JACK_MESSAGE_SIZE + 1];
+ char fDst[JACK_CLIENT_NAME_SIZE + 1];
+- jack_session_event_type_t fEventType;
+- int fRefNum;
++ jack_session_event_type_t fEventType;
++ int fRefNum;
+
+ JackSessionNotifyRequest()
+ {}
+- JackSessionNotifyRequest(int refnum, const char *path, jack_session_event_type_t type, const char *dst)
++ JackSessionNotifyRequest(int refnum, const char* path, jack_session_event_type_t type, const char* dst)
+ : JackRequest(JackRequest::kSessionNotify), fEventType(type), fRefNum(refnum)
+ {
+ snprintf(fPath, sizeof(fPath), "%s", path);
+- if (dst)
++ if (dst) {
+ snprintf(fDst, sizeof(fDst), "%s", dst);
+- else
++ } else {
+ fDst[0] = '\0';
++ }
+ }
+
+ int Read(JackChannelTransaction* trans)
+@@ -1276,7 +1334,6 @@
+
+ struct JackUUIDResult : public JackResult
+ {
+-
+ char fUUID[JACK_UUID_SIZE];
+
+ JackUUIDResult(): JackResult()
+@@ -1453,7 +1510,7 @@
+ CheckRes(trans->Read(&fValue1, sizeof(int)));
+ CheckRes(trans->Read(&fValue2, sizeof(int)));
+ CheckRes(trans->Read(&fSync, sizeof(int)));
+- CheckRes(trans->Read(&fMessage, sizeof(fName)));
++ CheckRes(trans->Read(&fMessage, sizeof(fMessage)));
+ return 0;
+ }
+
+@@ -1465,7 +1522,7 @@
+ CheckRes(trans->Write(&fValue1, sizeof(int)));
+ CheckRes(trans->Write(&fValue2, sizeof(int)));
+ CheckRes(trans->Write(&fSync, sizeof(int)));
+- CheckRes(trans->Write(&fMessage, sizeof(fName)));
++ CheckRes(trans->Write(&fMessage, sizeof(fMessage)));
+ return 0;
+ }
+
+--- a/common/JackResampler.cpp
++++ b/common/JackResampler.cpp
+@@ -24,7 +24,7 @@
+ {
+
+ JackResampler::JackResampler()
+- :fRatio(1),fRingBufferSize(DEFAULT_RB_SIZE)
++ :fRatio(1), fRingBufferSize(DEFAULT_RB_SIZE)
+ {
+ fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize);
+ jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2);
+@@ -32,13 +32,15 @@
+
+ JackResampler::~JackResampler()
+ {
+- if (fRingBuffer)
++ if (fRingBuffer) {
+ jack_ringbuffer_free(fRingBuffer);
++ }
+ }
+
+ void JackResampler::Reset(unsigned int new_size)
+ {
+ fRingBufferSize = new_size;
++ jack_ringbuffer_reset(fRingBuffer);
+ jack_ringbuffer_reset_size(fRingBuffer, sizeof(jack_default_audio_sample_t) * fRingBufferSize);
+ jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize / 2));
+ }
+@@ -81,6 +83,34 @@
+ }
+ }
+
++unsigned int JackResampler::Read(void* buffer, unsigned int bytes)
++{
++ size_t len = jack_ringbuffer_read_space(fRingBuffer);
++ jack_log("JackResampler::Read input available = %ld", len);
++
++ if (len < bytes) {
++ jack_error("JackResampler::Read : producer too slow, missing bytes = %d", bytes);
++ return 0;
++ } else {
++ jack_ringbuffer_read(fRingBuffer, (char*)buffer, bytes);
++ return bytes;
++ }
++}
++
++unsigned int JackResampler::Write(void* buffer, unsigned int bytes)
++{
++ size_t len = jack_ringbuffer_write_space(fRingBuffer);
++ jack_log("JackResampler::Write output available = %ld", len);
++
++ if (len < bytes) {
++ jack_error("JackResampler::Write : consumer too slow, skip bytes = %d", bytes);
++ return 0;
++ } else {
++ jack_ringbuffer_write(fRingBuffer, (char*)buffer, bytes);
++ return bytes;
++ }
++}
++
+ unsigned int JackResampler::ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames)
+ {
+ return Read(buffer, frames);
+--- a/common/JackResampler.h
++++ b/common/JackResampler.h
+@@ -61,6 +61,9 @@
+ virtual unsigned int Read(jack_default_audio_sample_t* buffer, unsigned int frames);
+ virtual unsigned int Write(jack_default_audio_sample_t* buffer, unsigned int frames);
+
++ virtual unsigned int Read(void* buffer, unsigned int bytes);
++ virtual unsigned int Write(void* buffer, unsigned int bytes);
++
+ virtual unsigned int ReadSpace();
+ virtual unsigned int WriteSpace();
+
+--- a/common/JackRestartThreadedDriver.cpp
++++ b/common/JackRestartThreadedDriver.cpp
+@@ -35,7 +35,7 @@
+ return false;
+ } catch (JackNetException& e) {
+ e.PrintMessage();
+- jack_log("Driver is restarted");
++ jack_info("Driver is restarted");
+ fThread.DropSelfRealTime();
+ // Thread in kIniting status again...
+ fThread.SetStatus(JackThread::kIniting);
+--- a/common/JackServerAPI.cpp
++++ b/common/JackServerAPI.cpp
+@@ -33,17 +33,14 @@
+ {
+ #endif
+
+- jack_client_t * jack_client_new_aux (const char *client_name,
+- jack_options_t options,
+- jack_status_t *status);
+- jack_client_t * jack_client_open_aux (const char *client_name,
+- jack_options_t options,
+- jack_status_t *status, va_list ap);
+- EXPORT jack_client_t * jack_client_open (const char *client_name,
++ jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t options, jack_status_t* status);
++ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t options, jack_status_t* status, va_list ap);
++
++ SERVER_EXPORT jack_client_t * jack_client_open (const char *client_name,
+ jack_options_t options,
+ jack_status_t *status, ...);
+- EXPORT int jack_client_close (jack_client_t *client);
+- EXPORT int jack_get_client_pid (const char *name);
++ SERVER_EXPORT int jack_client_close (jack_client_t *client);
++ SERVER_EXPORT int jack_get_client_pid (const char *name);
+
+ #ifdef __cplusplus
+ }
+@@ -153,7 +150,7 @@
+ }
+ }
+
+-EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
++SERVER_EXPORT jack_client_t* jack_client_open(const char* ext_client_name, jack_options_t options, jack_status_t* status, ...)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_open");
+@@ -176,7 +173,7 @@
+ }
+ }
+
+-EXPORT int jack_client_close(jack_client_t* ext_client)
++SERVER_EXPORT int jack_client_close(jack_client_t* ext_client)
+ {
+ #ifdef __CLIENTDEBUG__
+ JackGlobals::CheckContext("jack_client_close");
+@@ -198,7 +195,7 @@
+ return res;
+ }
+
+-EXPORT int jack_get_client_pid(const char *name)
++SERVER_EXPORT int jack_get_client_pid(const char *name)
+ {
+ return (JackServerGlobals::fInstance != NULL)
+ ? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name)
+--- a/common/JackServer.cpp
++++ b/common/JackServer.cpp
+@@ -22,7 +22,6 @@
+ #include "JackServerGlobals.h"
+ #include "JackTime.h"
+ #include "JackFreewheelDriver.h"
+-#include "JackDummyDriver.h"
+ #include "JackThreadedDriver.h"
+ #include "JackGlobals.h"
+ #include "JackLockedEngine.h"
+@@ -58,7 +57,7 @@
+ new JackFreewheelDriver(fEngine, GetSynchroTable());
+ fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver);
+
+- fFreewheelDriver = freewheelDriver;
++ fFreewheelDriver = freewheelDriver;
+ fDriverInfo = new JackDriverInfo();
+ fAudioDriver = NULL;
+ fFreewheel = false;
+@@ -188,6 +187,8 @@
+ int JackServer::Stop()
+ {
+ jack_log("JackServer::Stop");
++ fChannel.Stop();
++
+ if (fFreewheel) {
+ return fThreadedFreewheelDriver->Stop();
+ } else {
+@@ -223,13 +224,11 @@
+ }
+
+ if (fAudioDriver->SetBufferSize(buffer_size) == 0) {
+- fFreewheelDriver->SetBufferSize(buffer_size);
+ fEngine->NotifyBufferSize(buffer_size);
+ return fAudioDriver->Start();
+ } else { // Failure: try to restore current value
+ jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size);
+ fAudioDriver->SetBufferSize(current_buffer_size);
+- fFreewheelDriver->SetBufferSize(current_buffer_size);
+ fAudioDriver->Start();
+ // SetBufferSize actually failed, so return an error...
+ return -1;
+--- a/common/JackServerGlobals.cpp
++++ b/common/JackServerGlobals.cpp
+@@ -84,7 +84,7 @@
+ int status;
+ int refnum = (*it2).second;
+ if (refnum > 0) {
+- // Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload
++ // Client object is internally kept in JackEngine, and will be deallocated in InternalClientUnload
+ fInstance->GetEngine()->InternalClientUnload(refnum, &status);
+ }
+ }
+--- a/common/jack/session.h
++++ b/common/jack/session.h
+@@ -37,7 +37,7 @@
+ /**
+ * Session event type.
+ *
+- * if a client cant save templates, i might just do a normal save.
++ * If a client cant save templates, i might just do a normal save.
+ *
+ * There is no "quit without saving" event because a client might refuse to
+ * quit when it has unsaved data, but other clients may have already quit.
+@@ -190,19 +190,20 @@
+
+
+ /**
+- * free memory used by a jack_session_event_t
+- * this also frees the memory used by the command_line pointer.
+- * if its non NULL.
++ * Free memory used by a jack_session_event_t.
++ *
++ * This also frees the memory used by the command_line pointer, if its non NULL.
+ */
+ void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT;
+
+
+ /**
+- * get the assigned uuid for client.
+- * safe to call from callback and all other threads.
+- * memory needs to be freed.
++ * Get the assigned uuid for client.
++ * Safe to call from callback and all other threads.
++ *
++ * The caller is responsible for calling jack_free(3) on any non-NULL
++ * returned value.
+ */
+-
+ char *jack_client_get_uuid (jack_client_t *client) JACK_WEAK_EXPORT;
+
+ /**
+@@ -242,7 +243,11 @@
+
+ /**
+ * Get the session ID for a client name.
++ *
+ * The session manager needs this to reassociate a client name to the session_id.
++ *
++ * The caller is responsible for calling jack_free(3) on any non-NULL
++ * returned value.
+ */
+ char *jack_get_uuid_for_client_name (jack_client_t *client,
+ const char *client_name) JACK_WEAK_EXPORT;
+@@ -252,6 +257,9 @@
+ *
+ * In order to snapshot the graph connections, the session manager needs to map
+ * session_ids to client names.
++ *
++ * The caller is responsible for calling jack_free(3) on any non-NULL
++ * returned value.
+ */
+ char *jack_get_client_name_by_uuid (jack_client_t *client,
+ const char *client_uuid ) JACK_WEAK_EXPORT;
+--- /dev/null
++++ b/common/JackSession.h
+@@ -0,0 +1,69 @@
++/*
++ Copyright (C) 2001 Paul Davis
++ Copyright (C) 2004 Jack O'Quin
++ Copyright (C) 2010 Torben Hohn
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU Lesser General Public License as published by
++ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++*/
++
++#ifndef __jack_session_int_h__
++#define __jack_session_int_h__
++
++#include <stdint.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++enum JackSessionEventType {
++ JackSessionSave = 1,
++ JackSessionSaveAndQuit = 2,
++ JackSessionSaveTemplate = 3
++};
++
++typedef enum JackSessionEventType jack_session_event_type_t;
++
++enum JackSessionFlags {
++ JackSessionSaveError = 0x01,
++ JackSessionNeedTerminal = 0x02
++};
++
++typedef enum JackSessionFlags jack_session_flags_t;
++
++struct _jack_session_event {
++ jack_session_event_type_t type;
++ const char *session_dir;
++ const char *client_uuid;
++ char *command_line;
++ jack_session_flags_t flags;
++ uint32_t future;
++};
++
++typedef struct _jack_session_event jack_session_event_t;
++
++typedef void (*JackSessionCallback)(jack_session_event_t *event,
++ void *arg);
++
++typedef struct {
++ const char *uuid;
++ const char *client_name;
++ const char *command;
++ jack_session_flags_t flags;
++} jack_session_command_t;
++
++#ifdef __cplusplus
++}
++#endif
++#endif
+--- a/common/JackShmMem.cpp
++++ b/common/JackShmMem.cpp
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+- along with this program; if not, write to the Free Software
++ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+ #include "JackError.h"
+@@ -33,7 +33,7 @@
+ JackShmMemAble::Init();
+ LockMemory();
+ }
+-
++
+ JackShmMem::~JackShmMem()
+ {
+ UnlockMemory();
+@@ -45,7 +45,7 @@
+ fInfo.ptr.attached_at = gInfo.ptr.attached_at;
+ fInfo.size = gInfo.size;
+ }
+-
++
+ void* JackShmMem::operator new(size_t size, void* memory)
+ {
+ jack_log("JackShmMem::new placement size = %ld", size);
+@@ -61,12 +61,12 @@
+ snprintf(name, sizeof(name), "/jack_shared%d", fSegmentNum++);
+
+ if (jack_shmalloc(name, size, &info)) {
+- jack_error("cannot create shared memory segment of size = %d", size, strerror(errno));
++ jack_error("Cannot create shared memory segment of size = %d", size, strerror(errno));
+ goto error;
+ }
+
+ if (jack_attach_shm(&info)) {
+- jack_error("cannot attach shared memory segment name = %s err = %s", name, strerror(errno));
++ jack_error("Cannot attach shared memory segment name = %s err = %s", name, strerror(errno));
+ jack_destroy_shm(&info);
+ goto error;
+ }
+@@ -100,7 +100,7 @@
+ }
+
+ void JackShmMem::operator delete(void* obj)
+-{
++{
+ if (obj) {
+ JackShmMem::operator delete(obj, 0);
+ }
+@@ -111,7 +111,7 @@
+ if (CHECK_MLOCK((char*)ptr, size)) {
+ jack_log("Succeeded in locking %u byte memory area", size);
+ } else {
+- jack_error("Cannot lock down memory area (%s)", strerror(errno));
++ jack_error("Cannot lock down %u byte memory area (%s)", size, strerror(errno));
+ }
+ }
+
+@@ -121,7 +121,7 @@
+ memset(ptr, 0, size);
+ jack_log("Succeeded in locking %u byte memory area", size);
+ } else {
+- jack_error("Cannot lock down memory area (%s)", strerror(errno));
++ jack_error("Cannot lock down %u byte memory area (%s)", size, strerror(errno));
+ }
+ }
+
+@@ -130,7 +130,7 @@
+ if (CHECK_MUNLOCK((char*)ptr, size)) {
+ jack_log("Succeeded in unlocking %u byte memory area", size);
+ } else {
+- jack_error("Cannot unlock down memory area (%s)", strerror(errno));
++ jack_error("Cannot unlock down %u byte memory area (%s)", size, strerror(errno));
+ }
+ }
+
+--- a/common/JackShmMem.h
++++ b/common/JackShmMem.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+- along with this program; if not, write to the Free Software
++ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+ #ifndef __JackShmMem__
+@@ -47,12 +47,12 @@
+ static size_t gSize;
+
+ protected:
+-
++
+ JackMem(): fSize(gSize)
+ {}
+ ~JackMem()
+ {}
+-
++
+ public:
+
+ void* operator new(size_t size)
+@@ -65,7 +65,7 @@
+ {
+ free(ptr);
+ }
+-
++
+ void LockMemory()
+ {
+ LockMemoryImp(this, fSize);
+@@ -87,11 +87,11 @@
+ class JackShmMemAble
+ {
+ protected:
+-
++
+ jack_shm_info_t fInfo;
+-
++
+ public:
+-
++
+ void Init();
+
+ int GetShmIndex()
+@@ -126,18 +126,18 @@
+ {
+
+ protected:
+-
++
+ JackShmMem();
+ ~JackShmMem();
+-
++
+ public:
+-
++
+ void* operator new(size_t size);
+ void* operator new(size_t size, void* memory);
+-
++
+ void operator delete(void* p, size_t size);
+ void operator delete(void* p);
+-
++
+ };
+
+ /*!
+@@ -156,11 +156,12 @@
+ {
+ if (fInfo.index < 0 && index >= 0) {
+ jack_log("JackShmReadWritePtr::Init %ld %ld", index, fInfo.index);
+- if (jack_initialize_shm(server_name) < 0)
+- throw - 1;
++ if (jack_initialize_shm(server_name) < 0) {
++ throw std::bad_alloc();
++ }
+ fInfo.index = index;
+- if (jack_attach_shm(&fInfo)) {
+- throw - 2;
++ if (jack_attach_lib_shm(&fInfo)) {
++ throw std::bad_alloc();
+ }
+ GetShmAddress()->LockMemory();
+ }
+@@ -184,7 +185,7 @@
+ if (fInfo.index >= 0) {
+ jack_log("JackShmReadWritePtr::~JackShmReadWritePtr %ld", fInfo.index);
+ GetShmAddress()->UnlockMemory();
+- jack_release_shm(&fInfo);
++ jack_release_lib_shm(&fInfo);
+ fInfo.index = -1;
+ }
+ }
+@@ -237,19 +238,20 @@
+ {
+ if (fInfo.index < 0 && index >= 0) {
+ jack_log("JackShmReadWritePtr1::Init %ld %ld", index, fInfo.index);
+- if (jack_initialize_shm(server_name) < 0)
+- throw - 1;
++ if (jack_initialize_shm(server_name) < 0) {
++ throw std::bad_alloc();
++ }
+ fInfo.index = index;
+- if (jack_attach_shm(&fInfo)) {
+- throw - 2;
++ if (jack_attach_lib_shm(&fInfo)) {
++ throw std::bad_alloc();
+ }
++ GetShmAddress()->LockMemory();
+ /*
+ 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,7 +273,7 @@
+ if (fInfo.index >= 0) {
+ jack_log("JackShmReadWritePtr1::~JackShmReadWritePtr1 %ld", fInfo.index);
+ GetShmAddress()->UnlockMemory();
+- jack_release_shm(&fInfo);
++ jack_release_lib_shm(&fInfo);
+ fInfo.index = -1;
+ }
+ }
+@@ -324,11 +326,12 @@
+ {
+ if (fInfo.index < 0 && index >= 0) {
+ jack_log("JackShmPtrRead::Init %ld %ld", index, fInfo.index);
+- if (jack_initialize_shm(server_name) < 0)
+- throw - 1;
++ if (jack_initialize_shm(server_name) < 0) {
++ throw std::bad_alloc();
++ }
+ fInfo.index = index;
+- if (jack_attach_shm_read(&fInfo)) {
+- throw - 2;
++ if (jack_attach_lib_shm_read(&fInfo)) {
++ throw std::bad_alloc();
+ }
+ GetShmAddress()->LockMemory();
+ }
+@@ -352,7 +355,7 @@
+ if (fInfo.index >= 0) {
+ jack_log("JackShmPtrRead::~JackShmPtrRead %ld", fInfo.index);
+ GetShmAddress()->UnlockMemory();
+- jack_release_shm(&fInfo);
++ jack_release_lib_shm(&fInfo);
+ fInfo.index = -1;
+ }
+ }
+--- a/common/jack/systemdeps.h
++++ b/common/jack/systemdeps.h
+@@ -20,13 +20,14 @@
+ #ifndef __jack_systemdeps_h__
+ #define __jack_systemdeps_h__
+
+-#ifdef WIN32
++#if defined(WIN32) && !defined(__CYGWIN__) && !defined(GNU_WIN32)
+
+ #include <windows.h>
+
+ #ifdef _MSC_VER /* Microsoft compiler */
+ #define __inline__ inline
+- #ifndef int8_t
++ #if (!defined(int8_t) && !defined(_STDINT_H))
++ #define __int8_t_defined
+ typedef char int8_t;
+ typedef unsigned char uint8_t;
+ typedef short int16_t;
+@@ -36,28 +37,39 @@
+ typedef LONGLONG int64_t;
+ typedef ULONGLONG uint64_t;
+ #endif
+- /**
+- * to make jack API independent of different thread implementations,
+- * we define jack_native_thread_t to HANDLE here.
+- */
+- typedef HANDLE jack_native_thread_t;
+ #elif __MINGW32__ /* MINGW */
+ #include <stdint.h>
+ #include <sys/types.h>
++#else /* other compilers ...*/
++ #include <inttypes.h>
++ #include <pthread.h>
++ #include <sys/types.h>
++#endif
++
++#if !defined(_PTHREAD_H) && !defined(PTHREAD_WIN32)
+ /**
+ * to make jack API independent of different thread implementations,
+ * we define jack_native_thread_t to HANDLE here.
+ */
+ typedef HANDLE jack_native_thread_t;
+-#else /* other compilers ...*/
+- #include <inttypes.h>
+- #include <pthread.h>
+- #include <sys/types.h>
++#else
++ #ifdef PTHREAD_WIN32 // Added by JE - 10-10-2011
++ #include <ptw32/pthread.h> // Makes sure we #include the ptw32 version !
++ #endif
++ /**
++ * to make jack API independent of different thread implementations,
++ * we define jack_native_thread_t to pthread_t here.
++ */
++ typedef pthread_t jack_native_thread_t;
+ #endif
+
+-#endif /* WIN32 */
++#endif // WIN32 && !__CYGWIN__ && !GNU_WIN32 */
++
++#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32)
+
+-#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__)
++#if defined(__CYGWIN__) || defined(GNU_WIN32)
++ #include <stdint.h>
++#endif
+ #include <inttypes.h>
+ #include <pthread.h>
+ #include <sys/types.h>
+--- a/common/JackThreadedDriver.cpp
++++ b/common/JackThreadedDriver.cpp
+@@ -21,6 +21,7 @@
+ #include "JackSystemDeps.h"
+ #include "JackThreadedDriver.h"
+ #include "JackError.h"
++#include "JackTools.h"
+ #include "JackGlobals.h"
+ #include "JackEngineControl.h"
+
+@@ -43,16 +44,16 @@
+ }
+
+ int JackThreadedDriver::Open(jack_nframes_t buffer_size,
+- jack_nframes_t samplerate,
+- 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)
++ jack_nframes_t samplerate,
++ 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)
+ {
+ return fDriver->Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency);
+ }
+@@ -67,11 +68,6 @@
+ return fDriver->Process();
+ }
+
+-int JackThreadedDriver::ProcessNull()
+-{
+- return fDriver->ProcessNull();
+-}
+-
+ int JackThreadedDriver::Attach()
+ {
+ return fDriver->Attach();
+@@ -127,9 +123,24 @@
+ fDriver->RemoveSlave(slave);
+ }
+
+-int JackThreadedDriver::ProcessSlaves()
++int JackThreadedDriver::ProcessReadSlaves()
++{
++ return fDriver->ProcessReadSlaves();
++}
++
++int JackThreadedDriver::ProcessWriteSlaves()
+ {
+- return fDriver->ProcessSlaves();
++ return fDriver->ProcessWriteSlaves();
++}
++
++int JackThreadedDriver::ProcessRead()
++{
++ return fDriver->ProcessRead();
++}
++
++int JackThreadedDriver::ProcessWrite()
++{
++ return fDriver->ProcessWrite();
+ }
+
+ std::list<JackDriverInterface*> JackThreadedDriver::GetSlaves()
+@@ -184,7 +195,6 @@
+ case JackThread::kIniting:
+ if (fThread.Kill() < 0) {
+ jack_error("Cannot kill thread");
+- return -1;
+ }
+ break;
+
+@@ -192,7 +202,6 @@
+ case JackThread::kRunning:
+ if (fThread.Stop() < 0) {
+ jack_error("Cannot stop thread");
+- return -1;
+ }
+ break;
+
+@@ -215,21 +224,30 @@
+ bool JackThreadedDriver::Init()
+ {
+ if (fDriver->Initialize()) {
+- if (fDriver->IsRealTime()) {
+- jack_log("JackThreadedDriver::Init IsRealTime");
+- // Will do "something" on OSX only...
+- GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
+- fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
+- if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
+- jack_error("AcquireSelfRealTime error");
+- } else {
+- set_threaded_log_function();
+- }
+- }
++ SetRealTime();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
++void JackThreadedDriver::SetRealTime()
++{
++ if (fDriver->IsRealTime()) {
++ jack_log("JackThreadedDriver::Init real-time");
++ // Will do "something" on OSX only...
++ GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
++ GetEngineControl()->fComputation = JackTools::ComputationMicroSec(GetEngineControl()->fBufferSize) * 1000;
++ fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
++ if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
++ jack_error("AcquireSelfRealTime error");
++ } else {
++ set_threaded_log_function();
++ }
++ } else {
++ jack_log("JackThreadedDriver::Init non-realtime");
++ }
++}
++
++
+ } // end of namespace
+--- a/common/JackThreadedDriver.h
++++ b/common/JackThreadedDriver.h
+@@ -39,6 +39,8 @@
+ JackThread fThread;
+ JackDriver* fDriver;
+
++ void SetRealTime();
++
+ public:
+
+ JackThreadedDriver(JackDriver* driver);
+@@ -72,7 +74,6 @@
+ virtual int Close();
+
+ virtual int Process();
+- virtual int ProcessNull();
+
+ virtual int Attach();
+ virtual int Detach();
+@@ -89,10 +90,17 @@
+
+ virtual void SetMaster(bool onoff);
+ virtual bool GetMaster();
++
+ virtual void AddSlave(JackDriverInterface* slave);
+ virtual void RemoveSlave(JackDriverInterface* slave);
++
+ virtual std::list<JackDriverInterface*> GetSlaves();
+- virtual int ProcessSlaves();
++
++ virtual int ProcessReadSlaves();
++ virtual int ProcessWriteSlaves();
++
++ virtual int ProcessRead();
++ virtual int ProcessWrite();
+
+ virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2);
+ virtual JackClientControl* GetClientControl() const;
+--- a/common/jack/thread.h
++++ b/common/jack/thread.h
+@@ -114,7 +114,7 @@
+ int jack_client_stop_thread(jack_client_t* client, jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT;
+
+ /**
+- * Cancel the thread then waits for the thread handler to terminate.
++ * Kill the thread.
+ *
+ * @param thread POSIX thread ID.
+ *
+--- /dev/null
++++ b/common/JackTimedDriver.cpp
+@@ -0,0 +1,89 @@
++/*
++Copyright (C) 2001 Paul Davis
++Copyright (C) 2004-2008 Grame
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2 of the License, or
++(at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#include "JackTimedDriver.h"
++#include "JackEngineControl.h"
++#include "JackTime.h"
++#include "JackCompilerDeps.h"
++#include <iostream>
++#include <unistd.h>
++#include <math.h>
++
++namespace Jack
++{
++
++int JackTimedDriver::FirstCycle(jack_time_t cur_time_usec)
++{
++ fAnchorTimeUsec = cur_time_usec;
++ return int((double(fEngineControl->fBufferSize) * 1000000) / double(fEngineControl->fSampleRate));
++}
++
++int JackTimedDriver::CurrentCycle(jack_time_t cur_time_usec)
++{
++ return int(((double(fCycleCount) * double(fEngineControl->fBufferSize) * 1000000.) / double(fEngineControl->fSampleRate)) - (cur_time_usec - fAnchorTimeUsec));
++}
++
++int JackTimedDriver::Start()
++{
++ fCycleCount = 0;
++ return JackAudioDriver::Start();
++}
++
++void JackTimedDriver::ProcessWait()
++{
++ jack_time_t cur_time_usec = GetMicroSeconds();
++ int wait_time_usec;
++
++ if (fCycleCount++ == 0) {
++ wait_time_usec = FirstCycle(cur_time_usec);
++ } else {
++ wait_time_usec = CurrentCycle(cur_time_usec);
++ }
++
++ if (wait_time_usec < 0) {
++ NotifyXRun(cur_time_usec, float(cur_time_usec - fBeginDateUst));
++ fCycleCount = 0;
++ wait_time_usec = 0;
++ jack_error("JackTimedDriver::Process XRun = %ld usec", (cur_time_usec - fBeginDateUst));
++ }
++
++ //jack_log("JackTimedDriver::Process wait_time = %d", wait_time_usec);
++ JackSleep(wait_time_usec);
++}
++
++int JackWaiterDriver::ProcessNull()
++{
++ JackDriver::CycleTakeBeginTime();
++
++ // Graph processing without Read/Write
++ if (fEngineControl->fSyncMode) {
++ ProcessGraphSync();
++ } else {
++ ProcessGraphAsync();
++ }
++
++ // Keep end cycle time
++ JackDriver::CycleTakeEndTime();
++
++ ProcessWait();
++ return 0;
++}
++
++} // end of namespace
+--- /dev/null
++++ b/common/JackTimedDriver.h
+@@ -0,0 +1,80 @@
++/*
++Copyright (C) 2001 Paul Davis
++Copyright (C) 2004-2008 Grame
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU General Public License as published by
++the Free Software Foundation; either version 2 of the License, or
++(at your option) any later version.
++
++This program is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++GNU General Public License for more details.
++
++You should have received a copy of the GNU General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#ifndef __JackTimedDriver__
++#define __JackTimedDriver__
++
++#include "JackAudioDriver.h"
++
++namespace Jack
++{
++
++/*!
++\brief The timed driver.
++*/
++
++class SERVER_EXPORT JackTimedDriver : public JackAudioDriver
++{
++ protected:
++
++ int fCycleCount;
++ jack_time_t fAnchorTimeUsec;
++
++ int FirstCycle(jack_time_t cur_time);
++ int CurrentCycle(jack_time_t cur_time);
++
++ void ProcessWait();
++
++ public:
++
++ JackTimedDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
++ : JackAudioDriver(name, alias, engine, table), fCycleCount(0), fAnchorTimeUsec(0)
++ {}
++ virtual ~JackTimedDriver()
++ {}
++
++ // BufferSize can be changed
++ bool IsFixedBufferSize()
++ {
++ return false;
++ }
++
++ int Start();
++
++};
++
++class SERVER_EXPORT JackWaiterDriver : public JackTimedDriver
++{
++
++ public:
++
++ JackWaiterDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
++ : JackTimedDriver(name, alias, engine, table)
++ {}
++ virtual ~JackWaiterDriver()
++ {}
++
++ virtual int ProcessNull();
++
++};
++
++} // end of namespace
++
++#endif
+--- a/common/JackTools.cpp
++++ b/common/JackTools.cpp
+@@ -43,11 +43,11 @@
+ #endif
+ }
+
+- void JackTools::ThrowJackNetException()
++ void JackTools::ThrowJackNetException()
+ {
+ throw JackNetException();
+ }
+-
++
+ int JackTools::MkDir(const char* path)
+ {
+ #ifdef WIN32
+--- a/common/JackTools.h
++++ b/common/JackTools.h
+@@ -63,13 +63,24 @@
+
+ static int MkDir(const char* path);
+ static char* UserDir();
+- static char* ServerDir ( const char* server_name, char* server_dir );
++ static char* ServerDir(const char* server_name, char* server_dir);
+ static const char* DefaultServerName();
+- static void CleanupFiles ( const char* server_name );
++ static void CleanupFiles(const char* server_name);
+ static int GetTmpdir();
+- static void RewriteName ( const char* name, char* new_name );
+-
++ static void RewriteName(const char* name, char* new_name);
+ static void ThrowJackNetException();
++
++ // For OSX only
++ static int ComputationMicroSec(int buffer_size)
++ {
++ if (buffer_size < 128) {
++ return 500;
++ } else if (buffer_size < 256) {
++ return 300;
++ } else {
++ return 100;
++ }
++ }
+ };
+
+ /*!
+@@ -141,7 +152,7 @@
+
+ T Add ( T measure_point )
+ {
+- return fCurrentMeasure[fMeasureId++] = measure_point;
++ return fCurrentMeasure[fMeasureId++] = measure_point;
+ }
+
+ uint32_t AddLast ( T measure_point )
+--- a/common/JackTransportEngine.cpp
++++ b/common/JackTransportEngine.cpp
+@@ -13,7 +13,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -38,7 +38,7 @@
+ {
+ fTransportState = JackTransportStopped;
+ fTransportCmd = fPreviousCmd = TransportCommandStop;
+- fSyncTimeout = 10000000; /* 10 seconds default...
++ fSyncTimeout = 10000000; /* 10 seconds default...
+ in case of big netjack1 roundtrip */
+ fSyncTimeLeft = 0;
+ fTimeBaseMaster = -1;
+@@ -112,8 +112,8 @@
+ JackClientControl* control = client->GetClientControl();
+ // Inactive clients don't have their process function called at all, so they must appear as already "rolling" for the transport....
+ control->fTransportState = (control->fActive && control->fCallback[kRealTimeCallback]) ? JackTransportStarting : JackTransportRolling;
+- control->fTransportSync = true;
+- control->fTransportTimebase = true;
++ control->fTransportSync = true;
++ control->fTransportTimebase = true;
+ jack_log("MakeAllStartingLocating ref = %ld", i);
+ }
+ }
+@@ -127,8 +127,8 @@
+ if (client) {
+ JackClientControl* control = client->GetClientControl();
+ control->fTransportState = JackTransportStopped;
+- control->fTransportSync = false;
+- control->fTransportTimebase = false;
++ control->fTransportSync = false;
++ control->fTransportTimebase = false;
+ jack_log("MakeAllStopping ref = %ld", i);
+ }
+ }
+@@ -142,8 +142,8 @@
+ if (client) {
+ JackClientControl* control = client->GetClientControl();
+ control->fTransportState = JackTransportStopped;
+- control->fTransportSync = true;
+- control->fTransportTimebase = true;
++ control->fTransportSync = true;
++ control->fTransportTimebase = true;
+ jack_log("MakeAllLocating ref = %ld", i);
+ }
+ }
+--- a/common/JackTransportEngine.h
++++ b/common/JackTransportEngine.h
+@@ -13,7 +13,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -48,47 +48,48 @@
+ The current position can be read by clients.
+
+ We use a JackAtomicArrayState pattern that allows to manage several "next" states independantly.
+-
++
+ In jack1 implementation, transport code (jack_transport_cycle_end) was not called if the graph could not be locked (see jack_run_one_cycle).
+ Here transport cycle (CycleBegin, CycleEnd) has to run in the RT thread concurrently with code executed from the "command" thread.
+-
++
+ Each client maintains a state in it's shared memory area defined by:
+-
++
+ - it's current transport state
+ - a boolean that is "true" when slow-sync cb has to be called
+ - a boolean that is "true" when timebase cb is called with new_pos on
+-
++
+ Several operations set the "slow-sync cb" flag to true:
+-
++
+ - setting a new cb (client)
+ - activate (client)
+ - transport start (server)
+ - new pos (server)
+-
++
+ Slow-sync cb calls stops when:
+-
++
+ - the cb return true (client)
+ - desactivate (client)
+ - transport stop (server)
+-
++
+ Several operations set the "timebase cb" flag to true:
+-
++
+ - setting a new cb (client)
+ - activate (client)
+ - transport start (server) ??
+ - new pos (server)
+-
++
+ Timebase cb "new_pos" argument calls stops when:
+-
++
+ - after one cb call with "new_pos" argument true (client)
+ - desactivate (client)
+ - release (client)
+ - transport stop (server)
+-
++
+ */
+
+ class JackClientInterface;
+
++PRE_PACKED_STRUCTURE
+ class SERVER_EXPORT JackTransportEngine : public JackAtomicArrayState<jack_position_t>
+ {
+
+@@ -109,7 +110,7 @@
+ void MakeAllStartingLocating(JackClientInterface** table);
+ void MakeAllStopping(JackClientInterface** table);
+ void MakeAllLocating(JackClientInterface** table);
+-
++
+ void SyncTimeout(jack_nframes_t frame_rate, jack_nframes_t buffer_size);
+
+ public:
+@@ -128,22 +129,22 @@
+ {
+ return fTransportState;
+ }
+-
++
+ void SetState(jack_transport_state_t state)
+ {
+ fTransportState = state;
+ }
+-
++
+ /*
+- \brief
++ \brief
+ */
+ int ResetTimebase(int refnum);
+
+ /*
+- \brief
++ \brief
+ */
+ int SetTimebaseMaster(int refnum, bool conditionnal);
+-
++
+ void GetTimebaseMaster(int& refnum, bool& conditionnal)
+ {
+ refnum = fTimeBaseMaster;
+@@ -151,17 +152,17 @@
+ }
+
+ /*
+- \brief
++ \brief
+ */
+ void CycleBegin(jack_nframes_t frame_rate, jack_time_t time);
+
+ /*
+- \brief
++ \brief
+ */
+ void CycleEnd(JackClientInterface** table, jack_nframes_t frame_rate, jack_nframes_t buffer_size);
+
+ /*
+- \brief
++ \brief
+ */
+ void SetSyncTimeout(jack_time_t timeout)
+ {
+@@ -174,20 +175,20 @@
+ {
+ return (jack_unique_t)INC_ATOMIC(&fWriteCounter);
+ }
+-
++
+ void RequestNewPos(jack_position_t* pos);
+-
++
+ jack_transport_state_t Query(jack_position_t* pos);
+-
++
+ jack_nframes_t GetCurrentFrame();
+
+ static void CopyPosition(jack_position_t* from, jack_position_t* to);
+-
++
+ bool GetNetworkSync() const
+ {
+ return fNetworkSync;
+ }
+-
++
+ void SetNetworkSync(bool sync)
+ {
+ fNetworkSync = sync;
+--- a/common/jack/transport.h
++++ b/common/jack/transport.h
+@@ -1,19 +1,19 @@
+ /*
+ Copyright (C) 2002 Paul Davis
+ 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 Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+- along with this program; if not, write to the Free Software
++ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -135,7 +135,7 @@
+ * sync_callbacks until ready. This function is realtime-safe.
+ *
+ * @see jack_transport_reposition, jack_set_sync_callback
+- *
++ *
+ * @param client the JACK client structure.
+ * @param frame frame number of new transport position.
+ *
+@@ -170,7 +170,7 @@
+ * @param client the JACK client structure
+ */
+ jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT;
+-
++
+ /**
+ * Request a new transport position.
+ *
+@@ -181,14 +181,14 @@
+ * sync_callbacks until ready. This function is realtime-safe.
+ *
+ * @see jack_transport_locate, jack_set_sync_callback
+- *
++ *
+ * @param client the JACK client structure.
+ * @param pos requested new transport position.
+ *
+ * @return 0 if valid request, EINVAL if position structure rejected.
+ */
+ int jack_transport_reposition (jack_client_t *client,
+- jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT;
++ const jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT;
+
+ /**
+ * Start the JACK transport rolling.
+@@ -239,7 +239,7 @@
+ jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_EXPORT;
+
+ /*@}*/
+-
++
+ #ifdef __cplusplus
+ }
+ #endif
+--- a/common/JackWaitThreadedDriver.cpp
++++ b/common/JackWaitThreadedDriver.cpp
+@@ -25,6 +25,7 @@
+ #include "JackEngineControl.h"
+ #include "JackException.h"
+ #include "JackError.h"
++#include "JackTools.h"
+
+ namespace Jack
+ {
+@@ -37,43 +38,44 @@
+ bool JackWaitThreadedDriver::Execute()
+ {
+ try {
++
++ SetRealTime();
++
+ // Process a null cycle until NetDriver has started
+ while (!fStarter.fRunning && fThread.GetStatus() == JackThread::kRunning) {
+- fDriver->ProcessNull();
+- }
+-
+- // Set RT
+- if (fDriver->IsRealTime()) {
+- jack_log("JackWaitThreadedDriver::Init IsRealTime");
+- // Will do "something" on OSX only...
+- GetEngineControl()->fPeriod = GetEngineControl()->fConstraint = GetEngineControl()->fPeriodUsecs * 1000;
+- fThread.SetParams(GetEngineControl()->fPeriod, GetEngineControl()->fComputation, GetEngineControl()->fConstraint);
+- if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) {
+- jack_error("AcquireSelfRealTime error");
+- } else {
+- set_threaded_log_function();
+- }
++ // Use base class method
++ assert(static_cast<JackWaiterDriver*>(fDriver));
++ static_cast<JackWaiterDriver*>(fDriver)->ProcessNull();
+ }
+
+ // Switch to keep running even in case of error
+ while (fThread.GetStatus() == JackThread::kRunning) {
+ fDriver->Process();
+ }
++
+ return false;
++
+ } catch (JackNetException& e) {
++
+ e.PrintMessage();
+ jack_info("Driver is restarted");
+ fThread.DropSelfRealTime();
++
++ // Thread has been stopped...
++ if (fThread.GetStatus() == JackThread::kIdle) {
++ return false;
++ }
++
+ // Thread in kIniting status again...
+ fThread.SetStatus(JackThread::kIniting);
+ if (Init()) {
+ // Thread in kRunning status again...
+ fThread.SetStatus(JackThread::kRunning);
+ return true;
+- } else {
+- return false;
+ }
+- }
++
++ return false;
++ }
+ }
+
+ } // end of namespace
+--- a/common/JackWaitThreadedDriver.h
++++ b/common/JackWaitThreadedDriver.h
+@@ -22,70 +22,74 @@
+ #define __JackWaitThreadedDriver__
+
+ #include "JackThreadedDriver.h"
+-#include "JackAudioDriver.h"
++#include "JackTimedDriver.h"
+
+ namespace Jack
+ {
+-
++
+ /*!
+-\brief To be used as a wrapper of JackNetDriver.
++\brief To be used as a wrapper of JackNetDriver.
+
+-The idea is to behave as the "dummy" driver, until the network connection is really started and processing starts.
+-The Execute method will call the ProcessNull method until the decorated driver Init method returns.
++The idea is to behave as the "dummy" driver, until the network connection is really started and processing starts.
++The Execute method will call the Process method from the base JackTimedDriver, until the decorated driver Init method returns.
+ A helper JackDriverStarter thread is used for that purpose.
+ */
+
+ class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver
+ {
+ private:
+-
+- struct SERVER_EXPORT JackDriverStarter : public JackRunnableInterface
++
++ struct JackDriverStarter : public JackRunnableInterface
+ {
+-
++
+ JackDriver* fDriver;
+ JackThread fThread;
+- bool fRunning;
+-
++ volatile bool fRunning;
++
+ JackDriverStarter(JackDriver* driver)
+- :fDriver(driver),fThread(this),fRunning(false)
++ :fDriver(driver), fThread(this), fRunning(false)
+ {}
+-
++
+ ~JackDriverStarter()
+ {
+ fThread.Kill();
+ }
+-
++
+ int Start()
+ {
+ fRunning = false;
+ return fThread.Start();
+ }
+-
++
+ // JackRunnableInterface interface
+ bool Execute()
+ {
+- // Blocks until decorated driver is started (that is when it's Init method returns).
+- fDriver->Initialize();
+- fRunning = true;
++ // Blocks until decorated driver is started (that is when it's Initialize method returns).
++ if (fDriver->Initialize()) {
++ fRunning = true;
++ } else {
++ jack_error("Initing net driver fails...");
++ }
++
+ return false;
+ }
+-
++
+ };
+-
++
+ JackDriverStarter fStarter;
+-
++
+ public:
+
+- JackWaitThreadedDriver(JackDriver* netdriver)
+- :JackThreadedDriver(netdriver),fStarter(netdriver)
++ JackWaitThreadedDriver(JackDriver* net_driver)
++ : JackThreadedDriver(net_driver), fStarter(net_driver)
+ {}
+ virtual ~JackWaitThreadedDriver()
+ {}
+-
++
+ // JackRunnableInterface interface
+ bool Init();
+ bool Execute();
+-};
++};
+
+
+ } // end of namespace
+--- /dev/null
++++ b/common/JackWeakAPI.c
+@@ -0,0 +1,307 @@
++//=============================================================================
++//
++// jackWeakAPI partly based on Julien Pommier (PianoTeq : http://www.pianoteq.com/) code.
++//
++// Copyright (C) 2002-2007 Werner Schweer and others
++// Copyright (C) 2009 Grame
++
++// This program is free software; you can redistribute it and/or modify
++// it under the terms of the GNU Lesser General Public License as published by
++// the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++// You should have received a copy of the GNU Lesser General Public License
++// along with this program; if not, write to the Free Software
++// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++#include <jack/jack.h>
++#include <jack/session.h>
++#include <jack/thread.h>
++#include <jack/midiport.h>
++#include <math.h>
++#ifndef WIN32
++#include <dlfcn.h>
++#endif
++#include <stdlib.h>
++#include <stdio.h>
++
++/* dynamically load libjack and forward all registered calls to libjack
++ (similar to what relaytool is trying to do, but more portably..)
++*/
++
++typedef void (*print_function)(const char *);
++typedef void *(*thread_routine)(void*);
++
++static int libjack_is_present = 0; // public symbol, similar to what relaytool does.
++
++#ifdef WIN32
++static HMODULE libjack_handle = 0;
++#else
++static void *libjack_handle = 0;
++#endif
++
++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);
++ #elif defined(WIN32)
++ #ifdef _WIN64
++ libjack_handle = LoadLibrary("libjack64.dll");
++ #else
++ libjack_handle = LoadLibrary("libjack.dll");
++ #endif
++ #else
++ libjack_handle = dlopen("libjack.so.0", RTLD_LAZY);
++ #endif
++
++ }
++ libjack_is_present = (libjack_handle != 0);
++}
++
++void *load_jack_function(const char *fn_name)
++{
++ void *fn = 0;
++ if (!libjack_handle) {
++ fprintf (stderr, "libjack not found, so do not try to load %s ffs !\n", fn_name);
++ return 0;
++ }
++#ifdef WIN32
++ fn = (void*)GetProcAddress(libjack_handle, fn_name);
++#else
++ fn = dlsym(libjack_handle, fn_name);
++#endif
++ if (!fn) {
++#ifdef WIN32
++ char* lpMsgBuf;
++ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL );
++ fprintf (stderr, "could not GetProcAddress( %s ), %s \n", fn_name, lpMsgBuf) ;
++#else
++ fprintf (stderr, "could not dlsym( %s ), %s \n", fn_name, dlerror()) ;
++#endif
++ }
++ return fn;
++}
++
++#define DECL_FUNCTION(return_type, fn_name, arguments_types, arguments) \
++ typedef return_type (*fn_name##_ptr_t)arguments_types; \
++ return_type fn_name arguments_types { \
++ 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 (return_type)-1; \
++ }
++
++#define DECL_FUNCTION_NULL(return_type, fn_name, arguments_types, arguments) \
++ typedef return_type (*fn_name##_ptr_t)arguments_types; \
++ return_type fn_name arguments_types { \
++ 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 (return_type)0; \
++ }
++
++#define DECL_VOID_FUNCTION(fn_name, arguments_types, arguments) \
++ typedef void (*fn_name##_ptr_t)arguments_types; \
++ void fn_name arguments_types { \
++ static fn_name##_ptr_t fn = 0; \
++ if (fn == 0) { fn = (fn_name##_ptr_t)load_jack_function(#fn_name); } \
++ if (fn) (*fn)arguments; \
++ }
++
++
++DECL_VOID_FUNCTION(jack_get_version, (int *major_ptr, int *minor_ptr, int *micro_ptr, int *proto_ptr), (major_ptr, minor_ptr, micro_ptr, proto_ptr));
++DECL_FUNCTION_NULL(const char *, jack_get_version_string, (), ());
++DECL_FUNCTION_NULL(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_NULL(jack_client_t *, jack_client_new, (const char *client_name), (client_name));
++DECL_FUNCTION(int, jack_client_name_size, (), ());
++DECL_FUNCTION_NULL(char*, jack_get_client_name, (jack_client_t *client), (client));
++DECL_FUNCTION(int, jack_internal_client_new, (const char *client_name,
++ const char *load_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, 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));
++DECL_FUNCTION(jack_nframes_t, jack_thread_wait, (jack_client_t *client, int status), (client, status));
++
++//
++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_FUNCTION(int, jack_set_process_thread, (jack_client_t *client,
++ JackThreadCallback fun,
++ void *arg), (client, fun, arg));
++DECL_FUNCTION(int, jack_set_thread_init_callback, (jack_client_t *client,
++ JackThreadInitCallback thread_init_callback,
++ void *arg), (client, thread_init_callback, arg));
++DECL_FUNCTION(int, jack_set_freewheel_callback, (jack_client_t *client,
++ JackFreewheelCallback freewheel_callback,
++ void *arg), (client, freewheel_callback, arg));
++DECL_FUNCTION(int, jack_set_freewheel, (jack_client_t *client, int onoff), (client, onoff));
++DECL_FUNCTION(int, jack_set_buffer_size, (jack_client_t *client, jack_nframes_t nframes), (client, nframes));
++DECL_FUNCTION(int, jack_set_buffer_size_callback, (jack_client_t *client,
++ JackBufferSizeCallback bufsize_callback,
++ void *arg), (client, bufsize_callback, arg));
++DECL_FUNCTION(int, jack_set_sample_rate_callback, (jack_client_t *client,
++ JackSampleRateCallback srate_callback,
++ void *arg), (client, srate_callback, arg));
++DECL_FUNCTION(int, jack_set_client_registration_callback, (jack_client_t *client,
++ JackClientRegistrationCallback registration_callback,
++ void *arg), (client, registration_callback, arg));
++DECL_FUNCTION(int, jack_set_port_registration_callback, (jack_client_t *client,
++ JackPortRegistrationCallback registration_callback,
++ void *arg), (client, registration_callback, arg));
++DECL_FUNCTION(int, jack_set_port_connect_callback, (jack_client_t *client,
++ JackPortConnectCallback connect_callback,
++ void *arg), (client, connect_callback, arg));
++DECL_FUNCTION(int, jack_set_port_rename_callback, (jack_client_t *client,
++ JackPortRenameCallback rename_callback,
++ void *arg), (client, rename_callback, arg));
++DECL_FUNCTION(int, jack_set_graph_order_callback, (jack_client_t *client,
++ JackGraphOrderCallback graph_callback,
++ void *arg), (client, graph_callback, arg));
++DECL_FUNCTION(int, jack_set_xrun_callback, (jack_client_t *client,
++ JackXRunCallback xrun_callback,
++ void *arg), (client, xrun_callback, arg));
++DECL_FUNCTION(int, jack_set_latency_callback, (jack_client_t *client,
++ JackLatencyCallback latency_callback,
++ void *arg), (client, latency_callback, arg));
++DECL_FUNCTION(int, jack_activate, (jack_client_t *client), (client));
++DECL_FUNCTION(int, jack_deactivate, (jack_client_t *client), (client));
++DECL_FUNCTION_NULL(jack_port_t *, jack_port_register, (jack_client_t *client, const char *port_name, const char *port_type,
++ unsigned long flags, unsigned long buffer_size),
++ (client, port_name, port_type, flags, buffer_size));
++DECL_FUNCTION(int, jack_port_unregister, (jack_client_t *client, jack_port_t* port), (client, port));
++DECL_FUNCTION_NULL(void *, jack_port_get_buffer, (jack_port_t *port, jack_nframes_t nframes), (port, nframes));
++DECL_FUNCTION_NULL(const char*, jack_port_name, (const jack_port_t *port), (port));
++DECL_FUNCTION_NULL(const char*, jack_port_short_name, (const jack_port_t *port), (port));
++DECL_FUNCTION(int, jack_port_flags, (const jack_port_t *port), (port));
++DECL_FUNCTION_NULL(const char*, jack_port_type, (const jack_port_t *port), (port));
++DECL_FUNCTION(jack_port_type_id_t, jack_port_type_id, (const jack_port_t *port), (port));
++DECL_FUNCTION(int, jack_port_is_mine, (const jack_client_t *client, const jack_port_t* port), (client, port));
++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_NULL(const char**, jack_port_get_connections, (const jack_port_t *port), (port));
++DECL_FUNCTION_NULL(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), (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_VOID_FUNCTION(jack_port_get_latency_range, (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range), (port, mode, range));
++DECL_VOID_FUNCTION(jack_port_set_latency_range, (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range), (port, mode, range));
++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(size_t, jack_port_type_get_buffer_size, (jack_client_t *client, const char* port_type), (client, port_type));
++
++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_NULL(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_NULL(jack_port_t *, jack_port_by_name, (jack_client_t * client, const char *port_name), (client, port_name));
++DECL_FUNCTION_NULL(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_NULL(jack_native_thread_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, (jack_native_thread_t thread, int priority), (thread, priority));
++DECL_FUNCTION(int, jack_client_create_thread, (jack_client_t* client,
++ jack_native_thread_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, (jack_native_thread_t thread), (thread));
++
++DECL_FUNCTION(int, jack_client_stop_thread, (jack_client_t* client, jack_native_thread_t thread), (client, thread));
++DECL_FUNCTION(int, jack_client_kill_thread, (jack_client_t* client, jack_native_thread_t thread), (client, thread));
++#ifndef WIN32
++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), (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));
++
++// session
++DECL_FUNCTION(int, jack_set_session_callback, (jack_client_t* ext_client, JackSessionCallback session_callback, void* arg), (ext_client, session_callback, arg));
++DECL_FUNCTION(jack_session_command_t*, jack_session_notify, (jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path), (ext_client, target, ev_type, path));
++DECL_FUNCTION(int, jack_session_reply, (jack_client_t* ext_client, jack_session_event_t *event), (ext_client, event));
++DECL_VOID_FUNCTION(jack_session_event_free, (jack_session_event_t* ev), (ev));
++DECL_FUNCTION(char*, jack_client_get_uuid, (jack_client_t* ext_client),(ext_client));
++DECL_FUNCTION(char*, jack_get_uuid_for_client_name, (jack_client_t* ext_client, const char* client_name),(ext_client, client_name));
++DECL_FUNCTION(char*, jack_get_client_name_by_uuid, (jack_client_t* ext_client, const char* client_uuid),(ext_client, client_uuid));
++DECL_FUNCTION(int, jack_reserve_client_name, (jack_client_t* ext_client, const char* name, const char* uuid),(ext_client, name, uuid));
++DECL_VOID_FUNCTION(jack_session_commands_free, (jack_session_command_t *cmds),(cmds));
++DECL_FUNCTION(int, jack_client_has_session_callback, (jack_client_t *client, const char* client_name),(client, client_name));
++
++// MIDI
++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_NULL(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));
+--- a/common/JackWeakAPI.cpp
++++ /dev/null
+@@ -1,308 +0,0 @@
+-//=============================================================================
+-// MuseScore
+-// Linux Music Score Editor
+-// $Id:
+-//
+-// jackWeakAPI based on code from Stéphane Letz (Grame)
+-// partly based on Julien Pommier (PianoTeq : http://www.pianoteq.com/) code.
+-//
+-// Copyright (C) 2002-2007 Werner Schweer and others
+-// Copyright (C) 2009 Grame
+-
+-// This program is free software; you can redistribute it and/or modify
+-// it under the terms of the GNU Lesser General Public License as published by
+-// the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-// You should have received a copy of the GNU Lesser General Public License
+-// along with this program; if not, write to the Free Software
+-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-#include <jack/jack.h>
+-#include <jack/thread.h>
+-#include <jack/midiport.h>
+-#include <math.h>
+-#ifndef WIN32
+-#include <dlfcn.h>
+-#endif
+-#include <stdlib.h>
+-#include <iostream>
+-
+-/* dynamically load libjack and forward all registered calls to libjack
+- (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.
+-
+-#ifdef WIN32
+-HMODULE libjack_handle = 0;
+-#else
+-static void *libjack_handle = 0;
+-#endif
+-
+-
+-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);
+- #elif defined(WIN32)
+- libjack_handle = LoadLibrary("libjack.dll");
+- #else
+- libjack_handle = dlopen("libjack.so.0", RTLD_LAZY);
+- #endif
+-
+- }
+- libjack_is_present = (libjack_handle != 0);
+-}
+-
+-void *load_jack_function(const char *fn_name)
+-{
+- void *fn = 0;
+- if (!libjack_handle) {
+- fprintf (stderr, "libjack not found, so do not try to load %s ffs !\n", fn_name);
+- return 0;
+- }
+-#ifdef WIN32
+- fn = (void*)GetProcAddress(libjack_handle, fn_name);
+-#else
+- fn = dlsym(libjack_handle, fn_name);
+-#endif
+- if (!fn) {
+-#ifdef WIN32
+- char* lpMsgBuf;
+- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL );
+- fprintf (stderr, "could not GetProcAddress( %s ), %s \n", fn_name, lpMsgBuf) ;
+-#else
+- fprintf (stderr, "could not dlsym( %s ), %s \n", fn_name, dlerror()) ;
+-#endif
+- }
+- return fn;
+-}
+-
+-#define DECL_FUNCTION(return_type, fn_name, arguments_types, arguments) \
+- typedef return_type (*fn_name##_ptr_t)arguments_types; \
+- return_type fn_name arguments_types { \
+- 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 (return_type)-1; \
+- }
+-
+-#define DECL_FUNCTION_NULL(return_type, fn_name, arguments_types, arguments) \
+- typedef return_type (*fn_name##_ptr_t)arguments_types; \
+- return_type fn_name arguments_types { \
+- 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 (return_type)0; \
+- }
+-
+-#define DECL_VOID_FUNCTION(fn_name, arguments_types, arguments) \
+- typedef void (*fn_name##_ptr_t)arguments_types; \
+- void fn_name arguments_types { \
+- static fn_name##_ptr_t fn = 0; \
+- if (fn == 0) { fn = (fn_name##_ptr_t)load_jack_function(#fn_name); } \
+- if (fn) (*fn)arguments; \
+- }
+-
+-
+-DECL_VOID_FUNCTION(jack_get_version, (int *major_ptr, int *minor_ptr, int *micro_ptr, int *proto_ptr), (major_ptr, minor_ptr, micro_ptr, proto_ptr));
+-DECL_FUNCTION_NULL(const char *, jack_get_version_string, (), ());
+-DECL_FUNCTION_NULL(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_NULL(jack_client_t *, jack_client_new, (const char *client_name), (client_name));
+-DECL_FUNCTION(int, jack_client_name_size, (), ());
+-DECL_FUNCTION_NULL(char*, jack_get_client_name, (jack_client_t *client), (client));
+-DECL_FUNCTION(int, jack_internal_client_new, (const char *client_name,
+- const char *load_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, 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));
+-DECL_FUNCTION(jack_nframes_t, jack_thread_wait, (jack_client_t *client, int status), (client, status));
+-
+-//
+-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_FUNCTION(int, jack_set_process_thread, (jack_client_t *client,
+- JackThreadCallback fun,
+- void *arg), (client, fun, arg));
+-DECL_FUNCTION(int, jack_set_thread_init_callback, (jack_client_t *client,
+- JackThreadInitCallback thread_init_callback,
+- void *arg), (client, thread_init_callback, arg));
+-DECL_FUNCTION(int, jack_set_freewheel_callback, (jack_client_t *client,
+- JackFreewheelCallback freewheel_callback,
+- void *arg), (client, freewheel_callback, arg));
+-DECL_FUNCTION(int, jack_set_freewheel, (jack_client_t *client, int onoff), (client, onoff));
+-DECL_FUNCTION(int, jack_set_buffer_size, (jack_client_t *client, jack_nframes_t nframes), (client, nframes));
+-DECL_FUNCTION(int, jack_set_buffer_size_callback, (jack_client_t *client,
+- JackBufferSizeCallback bufsize_callback,
+- void *arg), (client, bufsize_callback, arg));
+-DECL_FUNCTION(int, jack_set_sample_rate_callback, (jack_client_t *client,
+- JackSampleRateCallback srate_callback,
+- void *arg), (client, srate_callback, arg));
+-DECL_FUNCTION(int, jack_set_client_registration_callback, (jack_client_t *client,
+- JackClientRegistrationCallback registration_callback,
+- void *arg), (client, registration_callback, arg));
+-DECL_FUNCTION(int, jack_set_port_registration_callback, (jack_client_t *client,
+- JackPortRegistrationCallback registration_callback,
+- void *arg), (client, registration_callback, arg));
+-DECL_FUNCTION(int, jack_set_port_connect_callback, (jack_client_t *client,
+- JackPortConnectCallback connect_callback,
+- void *arg), (client, connect_callback, arg));
+-DECL_FUNCTION(int, jack_set_port_rename_callback, (jack_client_t *client,
+- JackPortRenameCallback rename_callback,
+- void *arg), (client, rename_callback, arg));
+-DECL_FUNCTION(int, jack_set_graph_order_callback, (jack_client_t *client,
+- JackGraphOrderCallback graph_callback,
+- void *arg), (client, graph_callback, arg));
+-DECL_FUNCTION(int, jack_set_xrun_callback, (jack_client_t *client,
+- JackXRunCallback xrun_callback,
+- void *arg), (client, xrun_callback, arg));
+-DECL_FUNCTION(int, jack_set_latency_callback, (jack_client_t *client,
+- JackLatencyCallback latency_callback,
+- void *arg), (client, latency_callback, arg));
+-DECL_FUNCTION(int, jack_activate, (jack_client_t *client), (client));
+-DECL_FUNCTION(int, jack_deactivate, (jack_client_t *client), (client));
+-DECL_FUNCTION_NULL(jack_port_t *, jack_port_register, (jack_client_t *client, const char *port_name, const char *port_type,
+- unsigned long flags, unsigned long buffer_size),
+- (client, port_name, port_type, flags, buffer_size));
+-DECL_FUNCTION(int, jack_port_unregister, (jack_client_t *client, jack_port_t* port), (client, port));
+-DECL_FUNCTION_NULL(void *, jack_port_get_buffer, (jack_port_t *port, jack_nframes_t nframes), (port, nframes));
+-DECL_FUNCTION_NULL(const char*, jack_port_name, (const jack_port_t *port), (port));
+-DECL_FUNCTION_NULL(const char*, jack_port_short_name, (const jack_port_t *port), (port));
+-DECL_FUNCTION(int, jack_port_flags, (const jack_port_t *port), (port));
+-DECL_FUNCTION_NULL(const char*, jack_port_type, (const jack_port_t *port), (port));
+-DECL_FUNCTION(jack_port_type_id_t, jack_port_type_id, (const jack_port_t *port), (port));
+-DECL_FUNCTION(int, jack_port_is_mine, (const jack_client_t *client, const jack_port_t* port), (client, port));
+-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_NULL(const char**, jack_port_get_connections, (const jack_port_t *port), (port));
+-DECL_FUNCTION_NULL(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), (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_VOID_FUNCTION(jack_port_get_latency_range, (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range), (port, mode, range));
+-DECL_VOID_FUNCTION(jack_port_set_latency_range, (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range), (port, mode, range));
+-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(size_t, jack_port_type_get_buffer_size, (jack_client_t *client, const char* port_type), (client, port_type));
+-
+-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_NULL(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_NULL(jack_port_t *, jack_port_by_name, (jack_client_t * client, const char *port_name), (client, port_name));
+-DECL_FUNCTION_NULL(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_NULL(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), (jtc));
+-#endif
+-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));
+-
+-// session
+-DECL_FUNCTION(int, jack_set_session_callback, (jack_client_t* ext_client, JackSessionCallback session_callback, void* arg), (ext_client, session_callback, arg));
+-DECL_FUNCTION(jack_session_command_t*, jack_session_notify, (jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path), (ext_client, target, ev_type, path)Ã );
+-DECL_FUNCTION(int jack_session_reply, (jack_client_t* ext_client, jack_session_event_t *event), (ext_client, event));
+-DECL_VOID_FUNCTION(jack_session_event_free, (jack_session_event_t* ev), (ev));
+-DECL_FUNCTION(char*, jack_get_uuid_for_client_name, (jack_client_t* ext_client, const char* client_name),(ext_client, client_name));
+-DECL_FUNCTION(char*, jack_get_client_name_by_uuid, (jack_client_t* ext_client, const char* client_uuid),(ext_client, client_uuid));
+-DECL_FUNCTION(int, jack_reserve_client_name, (jack_client_t* ext_client, const char* name, const char* uuid),(ext_client, name, uuid));
+-DECL_VOID_FUNCTION(jack_session_commands_free, (jack_session_command_t *cmds),(cmds));
+-DECL_FUNCTION(int, jack_client_has_session_callback, (jack_client_t *client, const char* client_name),(client, client_name));
+-
+-// MIDI
+-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_NULL(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));
+--- a/common/jack/weakjack.h
++++ b/common/jack/weakjack.h
+@@ -21,17 +21,29 @@
+ #define __weakjack_h__
+
+ /**
+- * @defgroup WeakLinkage managing support for newer/older versions of JACK
+- * @{ One challenge faced by developers is that of taking advantage of new features introduced in new versions of [ JACK ] while still
+- * supporting older versions of the system. Normally, if an application uses a new feature in a library/API, it is unable to run on
+- * earlier versions of the library/API that do not support that feature. Such applications would either fail to launch or crash when
+- * an attempt to use the feature was made. This problem cane be solved using weakly-linked symbols.
+- *
+- * When a symbol in a framework is defined as weakly linked, the symbol does not have to be present at runtime for a process to
+- * continue running. The static linker identifies a weakly linked symbol as such in any code module that references the symbol. The
+- * dynamic linker uses this same information at runtime to determine whether a process can continue running. If a weakly linked symbol
+- * is not present in the framework, the code module can continue to run as long as it does not reference the symbol. However, if the
+- * symbol is present, the code can use it normally.
++ * @defgroup WeakLinkage Managing support for newer/older versions of JACK
++ * @{ One challenge faced by developers is that of taking
++ * advantage of new features introduced in new versions
++ * of [ JACK ] while still supporting older versions of
++ * the system. Normally, if an application uses a new
++ * feature in a library/API, it is unable to run on
++ * earlier versions of the library/API that do not
++ * support that feature. Such applications would either
++ * fail to launch or crash when an attempt to use the
++ * feature was made. This problem cane be solved using
++ * weakly-linked symbols.
++ *
++ * When a symbol in a framework is defined as weakly
++ * linked, the symbol does not have to be present at
++ * runtime for a process to continue running. The static
++ * linker identifies a weakly linked symbol as such in
++ * any code module that references the symbol. The
++ * dynamic linker uses this same information at runtime
++ * to determine whether a process can continue
++ * running. If a weakly linked symbol is not present in
++ * the framework, the code module can continue to run as
++ * long as it does not reference the symbol. However, if
++ * the symbol is present, the code can use it normally.
+ *
+ * (adapted from: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html)
+ *
+@@ -73,6 +85,12 @@
+ *
+ */
+
++#ifdef __APPLE__
++#define WEAK_ATTRIBUTE weak_import
++#else
++#define WEAK_ATTRIBUTE __weak__
++#endif
++
+ #ifndef JACK_OPTIONAL_WEAK_EXPORT
+ /* JACK_OPTIONAL_WEAK_EXPORT needs to be a macro which
+ expands into a compiler directive. If non-null, the directive
+@@ -81,7 +99,7 @@
+ require linker arguments for the client as well.
+ */
+ #ifdef __GNUC__
+-#define JACK_OPTIONAL_WEAK_EXPORT __attribute__((__weak__))
++#define JACK_OPTIONAL_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE))
+ #else
+ /* Add other things here for non-gcc platforms */
+ #endif
+@@ -96,7 +114,7 @@
+ linker arguments for the client as well.
+ */
+ #ifdef __GNUC__
+-#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__weak__,__deprecated__))
++#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((WEAK_ATTRIBUTE,__deprecated__))
+ #else
+ /* Add other things here for non-gcc platforms */
+ #endif
+--- a/common/jack/weakmacros.h
++++ b/common/jack/weakmacros.h
+@@ -32,6 +32,12 @@
+ * <jack/weakjack.h> before jack.h.
+ *************************************************************/
+
++#ifdef __APPLE__
++#define WEAK_ATTRIBUTE weak_import
++#else
++#define WEAK_ATTRIBUTE __weak__
++#endif
++
+ #ifndef JACK_WEAK_EXPORT
+ #ifdef __GNUC__
+ /* JACK_WEAK_EXPORT needs to be a macro which
+@@ -40,13 +46,23 @@
+ 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))
++
++#ifdef WIN32
++ /*
++ Not working with __declspec(dllexport) so normal linking
++ Linking with JackWeakAPI.cpp will be the preferred way.
++ */
++ #define JACK_WEAK_EXPORT
++#else
++ #define JACK_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE))
++#endif
++
+ #else
+-/* Add other things here for non-gcc platforms */
+-
+-#ifdef WIN32
+-#define JACK_WEAK_EXPORT
+-#endif
++/* Add other things here for non-gcc platforms */
++
++#ifdef WIN32
++#define JACK_WEAK_EXPORT
++#endif
+
+ #endif
+ #endif
+@@ -59,13 +75,14 @@
+ #ifdef __GNUC__
+ #define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__deprecated__))
+ #else
+-/* Add other things here for non-gcc platforms */
+-
+-#ifdef WIN32
+-#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT
+-#endif
++/* Add other things here for non-gcc platforms */
++
++#ifdef WIN32
++#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT
++#endif
+
+ #endif /* __GNUC__ */
+ #endif
+
+ #endif /* __weakmacros_h__ */
++
+--- a/common/netjack.c
++++ b/common/netjack.c
+@@ -57,9 +57,7 @@
+
+ #include "netjack.h"
+ #include "netjack_packet.h"
+-
+-// JACK2
+-#include "control.h"
++#include "JackError.h"
+
+ #define MIN(x,y) ((x)<(y) ? (x) : (y))
+
+@@ -88,26 +86,25 @@
+ jacknet_packet_header *pkthdr;
+
+ if( !netj->next_deadline_valid ) {
+- netj->next_deadline = jack_get_time() + netj->period_usecs;
+- netj->next_deadline_valid = 1;
++ netj->next_deadline = jack_get_time() + netj->period_usecs;
++ netj->next_deadline_valid = 1;
+ }
+
+ // Increment expected frame here.
+
+ if( netj->expected_framecnt_valid ) {
+- netj->expected_framecnt += 1;
++ netj->expected_framecnt += 1;
+ } else {
+- // starting up.... lets look into the packetcache, and fetch the highest packet.
+- packet_cache_drain_socket( netj->packcache, netj->sockfd );
+- if( packet_cache_get_highest_available_framecnt( netj->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;
+- }
+-
++ // starting up.... lets look into the packetcache, and fetch the highest packet.
++ packet_cache_drain_socket( netj->packcache, netj->sockfd );
++ if( packet_cache_get_highest_available_framecnt( netj->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 );
+@@ -115,26 +112,26 @@
+ // then poll (have deadline calculated)
+ // then drain socket, rinse and repeat.
+ while(1) {
+- if( packet_cache_get_next_available_framecnt( netj->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;
+- }
++ if( packet_cache_get_next_available_framecnt( netj->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( netj->packcache, netj->sockfd );
++ packet_cache_drain_socket( netj->packcache, netj->sockfd );
+ }
+
+ // check if we know who to send our packets too.
+ if (!netj->srcaddress_valid)
+- if( netj->packcache->master_address_valid ) {
+- memcpy (&(netj->syncsource_address), &(netj->packcache->master_address), sizeof( struct sockaddr_in ) );
+- netj->srcaddress_valid = 1;
+- }
++ if( netj->packcache->master_address_valid ) {
++ memcpy (&(netj->syncsource_address), &(netj->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
+@@ -148,169 +145,168 @@
+
+ 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( netj->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->next_deadline -= 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->next_deadline += netj->period_usecs/100;
+- //jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 );
+- }
+- }
++ 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( netj->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->next_deadline -= 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->next_deadline += netj->period_usecs / 100;
++ //jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 );
++ }
++ }
+ // if( netj->next_deadline < (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 += netj->period_usecs;
++ netj->next_deadline += netj->period_usecs;
+ } else {
+- netj->time_to_deadline = 0;
+- netj->next_deadline += netj->period_usecs;
+- // 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( netj->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( netj->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( netj->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( netj->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( netj->packcache, &next_frame_avail) ) {
+- netj->expected_framecnt = next_frame_avail;
+- packet_cache_retreive_packet_pointer( netj->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( netj->packcache );
+- }
+- }
+- }
+- }
++ netj->time_to_deadline = 0;
++ netj->next_deadline += netj->period_usecs;
++ // 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( netj->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( netj->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( netj->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( netj->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( netj->packcache, &next_frame_avail) ) {
++ netj->expected_framecnt = next_frame_avail;
++ packet_cache_retreive_packet_pointer( netj->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( netj->packcache );
++ }
++ }
++ }
++ }
+ }
+
+ int retval = 0;
+
+ if( !netj->packet_data_valid ) {
+- netj->num_lost_packets += 1;
+- if( netj->num_lost_packets == 1 )
+- retval = netj->period_usecs;
++ 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;
++ if( (netj->num_lost_packets > 1) && !netj->running_free )
++ retval = (netj->num_lost_packets - 1) * netj->period_usecs;
+
+- netj->num_lost_packets = 0;
++ netj->num_lost_packets = 0;
+ }
+
+ return retval;
+@@ -340,19 +336,17 @@
+ 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);
++ 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");
+@@ -361,19 +355,17 @@
+ unsigned int chn;
+ int port_flags;
+
+-
+- if( netj->bitdepth == CELT_MODE )
+- {
++ if( netj->bitdepth == CELT_MODE ) {
+ #if HAVE_CELT
+ #if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
+- celt_int32 lookahead;
+- netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL );
++ celt_int32 lookahead;
++ netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL );
+ #else
+- celt_int32_t lookahead;
+- netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL );
++ celt_int32_t lookahead;
++ netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL );
+ #endif
+- celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead );
+- netj->codec_latency = 2*lookahead;
++ celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead );
++ netj->codec_latency = 2 * lookahead;
+ #endif
+ }
+
+@@ -396,21 +388,21 @@
+ netj->capture_ports =
+ jack_slist_append (netj->capture_ports, port);
+
+- if( netj->bitdepth == CELT_MODE ) {
++ if( netj->bitdepth == CELT_MODE ) {
+ #if HAVE_CELT
+ #if HAVE_CELT_API_0_11
+- netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create_custom( netj->celt_mode, 1, NULL ) );
++ netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create_custom( netj->celt_mode, 1, NULL ) );
+ #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
+- netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) );
++ netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) );
+ #else
+- netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) );
++ netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) );
+ #endif
+ #endif
+- } else {
++ } else {
+ #if HAVE_SAMPLERATE
+- netj->capture_srcs = jack_slist_append(netj->capture_srcs, src_new(SRC_LINEAR, 1, NULL));
++ 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++) {
+@@ -444,24 +436,24 @@
+
+ netj->playback_ports =
+ jack_slist_append (netj->playback_ports, port);
+- if( netj->bitdepth == CELT_MODE ) {
++ if( netj->bitdepth == CELT_MODE ) {
+ #if HAVE_CELT
+ #if HAVE_CELT_API_0_11
+- CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL );
+- netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) );
++ CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL );
++ netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) );
+ #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
+- 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 ) );
++ 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 ) );
++ 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 {
++ } else {
+ #if HAVE_SAMPLERATE
+- netj->playback_srcs = jack_slist_append(netj->playback_srcs, src_new(SRC_LINEAR, 1, NULL));
++ 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);
+@@ -494,15 +486,12 @@
+ jack_slist_free (netj->capture_ports);
+ netj->capture_ports = NULL;
+
+- for (node = netj->capture_srcs; node; node = jack_slist_next (node))
+- {
++ for (node = netj->capture_srcs; node; node = jack_slist_next (node)) {
+ #if HAVE_CELT
+- if( netj->bitdepth == CELT_MODE )
+- {
++ if( netj->bitdepth == CELT_MODE ) {
+ CELTDecoder * decoder = node->data;
+ celt_decoder_destroy(decoder);
+- }
+- else
++ } else
+ #endif
+ {
+ #if HAVE_SAMPLERATE
+@@ -521,15 +510,12 @@
+ jack_slist_free (netj->playback_ports);
+ netj->playback_ports = NULL;
+
+- for (node = netj->playback_srcs; node; node = jack_slist_next (node))
+- {
++ for (node = netj->playback_srcs; node; node = jack_slist_next (node)) {
+ #if HAVE_CELT
+- if( netj->bitdepth == CELT_MODE )
+- {
++ if( netj->bitdepth == CELT_MODE ) {
+ CELTEncoder * encoder = node->data;
+ celt_encoder_destroy(encoder);
+- }
+- else
++ } else
+ #endif
+ {
+ #if HAVE_SAMPLERATE
+@@ -542,32 +528,32 @@
+ netj->playback_srcs = NULL;
+
+ #if HAVE_CELT
+- if( netj->bitdepth == CELT_MODE )
+- celt_mode_destroy(netj->celt_mode);
++ if( netj->bitdepth == CELT_MODE )
++ celt_mode_destroy(netj->celt_mode);
+ #endif
+ }
+
+
+ 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 )
++ 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.
+@@ -602,8 +588,7 @@
+ netj->client = client;
+
+
+- if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE))
+- {
++ if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE)) {
+ jack_info ("Invalid bitdepth: %d (8, 16 or 0 for float) !!!", bitdepth);
+ return NULL;
+ }
+@@ -649,8 +634,7 @@
+ 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)
+- {
++ if (bind (netj->sockfd, (struct sockaddr *) &address, sizeof (address)) < 0) {
+ jack_info("bind error");
+ return -1;
+ }
+@@ -666,14 +650,13 @@
+ return -1;
+ }
+ netj->srcaddress_valid = 0;
+- if (netj->use_autoconfig)
+- {
++ if (netj->use_autoconfig) {
+ jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header));
+- #ifdef WIN32
++#ifdef WIN32
+ int address_size = sizeof( struct sockaddr_in );
+- #else
++#else
+ socklen_t address_size = sizeof (struct sockaddr_in);
+- #endif
++#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 !!!");
+
+@@ -683,51 +666,44 @@
+ return -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
++#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))
+- {
++ 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)
+- {
++ 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)
+- {
++ 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)
+- {
++ }
++ 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)
+- {
++ 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)
+- {
++ 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)
+- {
++ }
++ 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;
+ }
+@@ -741,24 +717,24 @@
+ 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);
++ 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);
++ 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->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);
++ jack_error( "sample_rate 0 requested by autoconfig" );
++ exit(1);
+ }
+
+ // After possible Autoconfig: do all calculations...
+@@ -767,15 +743,15 @@
+ * 1000000.0f);
+
+ if( netj->latency == 0 )
+- netj->deadline_offset = 50*netj->period_usecs;
++ netj->deadline_offset = 50 * netj->period_usecs;
+ else
+- netj->deadline_offset = netj->period_usecs + 10*netj->latency*netj->period_usecs/100;
++ 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->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;
+@@ -797,7 +773,7 @@
+ if( netj->latency == 0 )
+ netj->resync_threshold = 0;
+ else
+- netj->resync_threshold = MIN( 15, netj->latency-1 );
++ netj->resync_threshold = MIN( 15, netj->latency - 1 );
+
+ netj->running_free = 0;
+
+--- a/common/netjack.h
++++ b/common/netjack.h
+@@ -24,130 +24,126 @@
+ #include <unistd.h>
+
+ #include <jack/types.h>
+-//#include <jack/driver.h>
+ #include <jack/jack.h>
+ #include <jack/transport.h>
+-
+ #include "jack/jslist.h"
+
+ #if HAVE_CELT
+ #include <celt/celt.h>
+ #endif
+
+-//#include <netinet/in.h>
+-
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
+-struct _packet_cache;
++ struct _packet_cache;
+
+-typedef struct _netjack_driver_state netjack_driver_state_t;
++ 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;
++ 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;
++ jack_client_t *client;
+
+ #ifdef WIN32
+- SOCKET sockfd;
+- SOCKET outsockfd;
++ SOCKET sockfd;
++ SOCKET outsockfd;
+ #else
+- int sockfd;
+- int outsockfd;
++ int sockfd;
++ int outsockfd;
+ #endif
+
+- struct sockaddr_in syncsource_address;
++ struct sockaddr_in syncsource_address;
+
+- int reply_port;
+- int srcaddress_valid;
++ int reply_port;
++ int srcaddress_valid;
+
+- int sync_state;
+- unsigned int handle_transport_sync;
++ int sync_state;
++ unsigned int handle_transport_sync;
+
+- unsigned int *rx_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;
+- struct _packet_cache * packcache;
++ unsigned int *rx_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;
++ struct _packet_cache * packcache;
+ #if HAVE_CELT
+- CELTMode *celt_mode;
++ CELTMode *celt_mode;
+ #endif
+-};
++ };
+
+-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 );
++ 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 );
++ void netjack_release( netjack_driver_state_t *netj );
++ int netjack_startup( netjack_driver_state_t *netj );
+
+ #ifdef __cplusplus
+ }
+--- a/common/netjack_packet.c
++++ b/common/netjack_packet.c
+@@ -73,9 +73,7 @@
+ #endif
+
+ #include "netjack_packet.h"
+-
+-// JACK2 specific.
+-#include "control.h"
++#include "JackError.h"
+
+ #ifdef NO_JACK_ERROR
+ #define jack_error printf
+@@ -154,13 +152,12 @@
+ int i, fragment_number;
+
+ if( pkt_size == sizeof(jacknet_packet_header) )
+- fragment_number = 1;
++ fragment_number = 1;
+ else
+- fragment_number = (pkt_size - sizeof (jacknet_packet_header) - 1) / fragment_payload_size + 1;
++ fragment_number = (pkt_size - sizeof (jacknet_packet_header) - 1) / fragment_payload_size + 1;
+
+ packet_cache *pcache = malloc (sizeof (packet_cache));
+- if (pcache == NULL)
+- {
++ if (pcache == NULL) {
+ jack_error ("could not allocate packet cache (1)");
+ return NULL;
+ }
+@@ -171,14 +168,12 @@
+ pcache->last_framecnt_retreived = 0;
+ pcache->last_framecnt_retreived_valid = 0;
+
+- if (pcache->packets == NULL)
+- {
++ if (pcache->packets == NULL) {
+ jack_error ("could not allocate packet cache (2)");
+ return NULL;
+ }
+
+- for (i = 0; i < num_packets; i++)
+- {
++ for (i = 0; i < num_packets; i++) {
+ pcache->packets[i].valid = 0;
+ pcache->packets[i].num_fragments = fragment_number;
+ pcache->packets[i].packet_size = pkt_size;
+@@ -186,8 +181,7 @@
+ pcache->packets[i].framecnt = 0;
+ pcache->packets[i].fragment_array = malloc (sizeof (char) * fragment_number);
+ pcache->packets[i].packet_buf = malloc (pkt_size);
+- if ((pcache->packets[i].fragment_array == NULL) || (pcache->packets[i].packet_buf == NULL))
+- {
++ if ((pcache->packets[i].fragment_array == NULL) || (pcache->packets[i].packet_buf == NULL)) {
+ jack_error ("could not allocate packet cache (3)");
+ return NULL;
+ }
+@@ -202,10 +196,9 @@
+ {
+ int i;
+ if( pcache == NULL )
+- return;
++ return;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ free (pcache->packets[i].fragment_array);
+ free (pcache->packets[i].packet_buf);
+ }
+@@ -220,8 +213,7 @@
+ int i;
+ cache_packet *retval;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt))
+ return &(pcache->packets[i]);
+ }
+@@ -230,8 +222,7 @@
+ // find a free packet.
+
+ retval = packet_cache_get_free_packet (pcache);
+- if (retval != NULL)
+- {
++ if (retval != NULL) {
+ cache_packet_set_framecnt (retval, framecnt);
+ return retval;
+ }
+@@ -259,10 +250,8 @@
+ cache_packet *retval = &(pcache->packets[0]);
+ int i;
+
+- for (i = 0; i < pcache->size; i++)
+- {
+- if (pcache->packets[i].valid && (pcache->packets[i].framecnt < minimal_frame))
+- {
++ for (i = 0; i < pcache->size; i++) {
++ if (pcache->packets[i].valid && (pcache->packets[i].framecnt < minimal_frame)) {
+ minimal_frame = pcache->packets[i].framecnt;
+ retval = &(pcache->packets[i]);
+ }
+@@ -276,8 +265,7 @@
+ {
+ int i;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ if (pcache->packets[i].valid == 0)
+ return &(pcache->packets[i]);
+ }
+@@ -322,28 +310,23 @@
+ jack_nframes_t fragment_nr = ntohl (pkthdr->fragment_nr);
+ jack_nframes_t framecnt = ntohl (pkthdr->framecnt);
+
+- if (framecnt != pack->framecnt)
+- {
++ if (framecnt != pack->framecnt) {
+ jack_error ("errror. framecnts dont match");
+ return;
+ }
+
+- if (fragment_nr == 0)
+- {
++ if (fragment_nr == 0) {
+ memcpy (pack->packet_buf, packet_buf, rcv_len);
+ pack->fragment_array[0] = 1;
+
+ return;
+ }
+
+- if ((fragment_nr < pack->num_fragments) && (fragment_nr > 0))
+- {
+- if ((fragment_nr * fragment_payload_size + rcv_len - sizeof (jacknet_packet_header)) <= (pack->packet_size - sizeof (jacknet_packet_header)))
+- {
++ if ((fragment_nr < pack->num_fragments) && (fragment_nr > 0)) {
++ if ((fragment_nr * fragment_payload_size + rcv_len - sizeof (jacknet_packet_header)) <= (pack->packet_size - sizeof (jacknet_packet_header))) {
+ memcpy (packet_bufX + fragment_nr * fragment_payload_size, dataX, rcv_len - sizeof (jacknet_packet_header));
+ pack->fragment_array[fragment_nr] = 1;
+- }
+- else
++ } else
+ jack_error ("too long packet received...");
+ }
+ }
+@@ -375,11 +358,11 @@
+
+ jack_time_t now = jack_get_time();
+ if( now >= deadline )
+- return 0;
++ return 0;
+
+- if( (deadline-now) >= 1000000 ) {
+- jack_error( "deadline more than 1 second in the future, trimming it." );
+- deadline = now+500000;
++ if( (deadline - now) >= 1000000 ) {
++ jack_error( "deadline more than 1 second in the future, trimming it." );
++ deadline = now + 500000;
+ }
+ #if HAVE_PPOLL
+ timeout_spec.tv_nsec = (deadline - now) * 1000;
+@@ -396,25 +379,23 @@
+ poll_err = poll (&fds, 1, timeout);
+ #endif
+
+- if (poll_err == -1)
+- {
+- switch (errno)
+- {
++ if (poll_err == -1) {
++ switch (errno) {
+ case EBADF:
+- jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno);
+- break;
++ jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno);
++ break;
+ case EFAULT:
+- jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno);
+- break;
++ jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno);
++ break;
+ case EINTR:
+- jack_error ("Error %d: A signal occurred before any requested event", errno);
+- break;
++ jack_error ("Error %d: A signal occurred before any requested event", errno);
++ break;
+ case EINVAL:
+- jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno);
+- break;
++ jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno);
++ break;
+ case ENOMEM:
+- jack_error ("Error %d: There was no space to allocate file descriptor tables", errno);
+- break;
++ jack_error ("Error %d: There was no space to allocate file descriptor tables", errno);
++ break;
+ }
+ }
+ return poll_err;
+@@ -429,17 +410,17 @@
+ struct sigaction action;
+
+ sigemptyset(&sigmask);
+- sigaddset(&sigmask, SIGHUP);
+- sigaddset(&sigmask, SIGINT);
+- sigaddset(&sigmask, SIGQUIT);
+- sigaddset(&sigmask, SIGPIPE);
+- sigaddset(&sigmask, SIGTERM);
+- sigaddset(&sigmask, SIGUSR1);
+- sigaddset(&sigmask, SIGUSR2);
+-
+- action.sa_handler = SIG_DFL;
+- action.sa_mask = sigmask;
+- action.sa_flags = SA_RESTART;
++ sigaddset(&sigmask, SIGHUP);
++ sigaddset(&sigmask, SIGINT);
++ sigaddset(&sigmask, SIGQUIT);
++ sigaddset(&sigmask, SIGPIPE);
++ sigaddset(&sigmask, SIGTERM);
++ sigaddset(&sigmask, SIGUSR1);
++ sigaddset(&sigmask, SIGUSR2);
++
++ action.sa_handler = SIG_DFL;
++ action.sa_mask = sigmask;
++ action.sa_flags = SA_RESTART;
+
+ for (i = 1; i < NSIG; i++)
+ if (sigismember (&sigmask, i))
+@@ -449,31 +430,28 @@
+ fds.events = POLLIN;
+
+ sigprocmask(SIG_UNBLOCK, &sigmask, &rsigmask);
+- while (poll_err == 0)
+- {
++ while (poll_err == 0) {
+ poll_err = poll (&fds, 1, timeout);
+ }
+ sigprocmask(SIG_SETMASK, &rsigmask, NULL);
+
+- if (poll_err == -1)
+- {
+- switch (errno)
+- {
++ if (poll_err == -1) {
++ switch (errno) {
+ case EBADF:
+- jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno);
+- break;
++ jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno);
++ break;
+ case EFAULT:
+- jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno);
+- break;
++ jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno);
++ break;
+ case EINTR:
+- jack_error ("Error %d: A signal occurred before any requested event", errno);
+- break;
++ jack_error ("Error %d: A signal occurred before any requested event", errno);
++ break;
+ case EINVAL:
+- jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno);
+- break;
++ jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno);
++ break;
+ case ENOMEM:
+- jack_error ("Error %d: There was no space to allocate file descriptor tables", errno);
+- break;
++ jack_error ("Error %d: There was no space to allocate file descriptor tables", errno);
++ break;
+ }
+ return 0;
+ }
+@@ -498,10 +476,10 @@
+ while( 1 ) {
+ jack_time_t now = jack_get_time();
+ if( now >= deadline )
+- return 0;
++ return 0;
+
+ int timeout_usecs = (deadline - now);
+- //jack_error( "timeout = %d", timeout_usecs );
++ //jack_error( "timeout = %d", timeout_usecs );
+ timeout.tv_sec = 0;
+ timeout.tv_usec = (timeout_usecs < 500) ? 500 : timeout_usecs;
+ timeout.tv_usec = (timeout_usecs > 1000000) ? 500000 : timeout_usecs;
+@@ -533,36 +511,35 @@
+ #else
+ socklen_t senderlen = sizeof( struct sockaddr_in );
+ #endif
+- while (1)
+- {
++ while (1) {
+ #ifdef WIN32
+ rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, 0,
+- (struct sockaddr*) &sender_address, &senderlen);
++ (struct sockaddr*) &sender_address, &senderlen);
+ #else
+ rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, MSG_DONTWAIT,
+- (struct sockaddr*) &sender_address, &senderlen);
++ (struct sockaddr*) &sender_address, &senderlen);
+ #endif
+ if (rcv_len < 0)
+ return;
+
+- if (pcache->master_address_valid) {
+- // Verify its from our master.
+- if (memcmp (&sender_address, &(pcache->master_address), senderlen) != 0)
+- continue;
+- } else {
+- // Setup this one as master
+- //printf( "setup master...\n" );
+- memcpy ( &(pcache->master_address), &sender_address, senderlen );
+- pcache->master_address_valid = 1;
+- }
++ if (pcache->master_address_valid) {
++ // Verify its from our master.
++ if (memcmp (&sender_address, &(pcache->master_address), senderlen) != 0)
++ continue;
++ } else {
++ // Setup this one as master
++ //printf( "setup master...\n" );
++ memcpy ( &(pcache->master_address), &sender_address, senderlen );
++ pcache->master_address_valid = 1;
++ }
+
+ framecnt = ntohl (pkthdr->framecnt);
+- if( pcache->last_framecnt_retreived_valid && (framecnt <= pcache->last_framecnt_retreived ))
+- continue;
++ if( pcache->last_framecnt_retreived_valid && (framecnt <= pcache->last_framecnt_retreived ))
++ continue;
+
+ cpack = packet_cache_get_packet (pcache, framecnt);
+ cache_packet_add_fragment (cpack, rx_packet, rcv_len);
+- cpack->recv_timestamp = jack_get_time();
++ cpack->recv_timestamp = jack_get_time();
+ }
+ }
+
+@@ -579,10 +556,8 @@
+ {
+ int i;
+
+- for (i = 0; i < pcache->size; i++)
+- {
+- if (pcache->packets[i].valid && (pcache->packets[i].framecnt < framecnt))
+- {
++ for (i = 0; i < pcache->size; i++) {
++ if (pcache->packets[i].valid && (pcache->packets[i].framecnt < framecnt)) {
+ cache_packet_reset (&(pcache->packets[i]));
+ }
+ }
+@@ -656,8 +631,7 @@
+ int num_packets_before_us = 0;
+ int i;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ cache_packet *cpack = &(pcache->packets[i]);
+ if (cpack->valid && cache_packet_is_complete( cpack ))
+ if( cpack->framecnt >= expected_framecnt )
+@@ -672,11 +646,10 @@
+ packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt )
+ {
+ int i;
+- jack_nframes_t best_offset = JACK_MAX_FRAMES/2-1;
++ jack_nframes_t best_offset = JACK_MAX_FRAMES / 2 - 1;
+ int retval = 0;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ cache_packet *cpack = &(pcache->packets[i]);
+ //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt );
+
+@@ -690,13 +663,13 @@
+
+ if( (cpack->framecnt - expected_framecnt) > best_offset ) {
+ continue;
+- }
++ }
+
+- best_offset = cpack->framecnt - expected_framecnt;
+- retval = 1;
++ best_offset = cpack->framecnt - expected_framecnt;
++ retval = 1;
+
+- if (best_offset == 0)
+- break;
++ if (best_offset == 0)
++ break;
+ }
+ if (retval && framecnt)
+ *framecnt = expected_framecnt + best_offset;
+@@ -711,22 +684,21 @@
+ jack_nframes_t best_value = 0;
+ int retval = 0;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ cache_packet *cpack = &(pcache->packets[i]);
+ //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt );
+
+ if (!cpack->valid || !cache_packet_is_complete( cpack )) {
+ //printf( "invalid\n" );
+ continue;
+- }
++ }
+
+- if (cpack->framecnt < best_value) {
+- continue;
+- }
++ if (cpack->framecnt < best_value) {
++ continue;
++ }
+
+- best_value = cpack->framecnt;
+- retval = 1;
++ best_value = cpack->framecnt;
++ retval = 1;
+
+ }
+ if (retval && framecnt)
+@@ -743,25 +715,24 @@
+ jack_nframes_t best_offset = 0;
+ int retval = 0;
+
+- for (i = 0; i < pcache->size; i++)
+- {
++ for (i = 0; i < pcache->size; i++) {
+ cache_packet *cpack = &(pcache->packets[i]);
+ //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt );
+
+ if (!cpack->valid || !cache_packet_is_complete( cpack )) {
+ //printf( "invalid\n" );
+ continue;
+- }
++ }
+
+- if ((cpack->framecnt - expected_framecnt) < best_offset) {
+- continue;
+- }
++ if ((cpack->framecnt - expected_framecnt) < best_offset) {
++ continue;
++ }
+
+- best_offset = cpack->framecnt - expected_framecnt;
+- retval = 1;
++ best_offset = cpack->framecnt - expected_framecnt;
++ retval = 1;
+
+- if( best_offset == 0 )
+- break;
++ if( best_offset == 0 )
++ break;
+ }
+ if (retval && framecnt)
+ *framecnt = JACK_MAX_FRAMES - best_offset;
+@@ -787,13 +758,11 @@
+ pkthdr = (jacknet_packet_header *) packet_buf;
+ pkthdr->fragment_nr = htonl (0);
+ err = sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size);
+- if( err<0 ) {
++ if( err < 0 ) {
+ //printf( "error in send\n" );
+ perror( "send" );
+ }
+- }
+- else
+- {
++ } else {
+ int err;
+ // Copy the packet header to the tx pack first.
+ memcpy(tx_packet, packet_buf, sizeof (jacknet_packet_header));
+@@ -801,8 +770,7 @@
+ // Now loop and send all
+ char *packet_bufX = packet_buf + sizeof (jacknet_packet_header);
+
+- while (packet_bufX < (packet_buf + pkt_size - fragment_payload_size))
+- {
++ while (packet_bufX < (packet_buf + pkt_size - fragment_payload_size)) {
+ pkthdr->fragment_nr = htonl (frag_cnt++);
+ memcpy (dataX, packet_bufX, fragment_payload_size);
+ sendto (sockfd, tx_packet, mtu, flags, addr, addr_size);
+@@ -816,7 +784,7 @@
+
+ // sendto(last_pack_size);
+ err = sendto(sockfd, tx_packet, last_payload_size + sizeof(jacknet_packet_header), flags, addr, addr_size);
+- if( err<0 ) {
++ if( err < 0 ) {
+ //printf( "error in send\n" );
+ perror( "send" );
+ }
+@@ -828,24 +796,21 @@
+ {
+ int i;
+ jack_midi_clear_buffer (buf);
+- for (i = 0; i < buffer_size_uint32 - 3;)
+- {
++ for (i = 0; i < buffer_size_uint32 - 3;) {
+ uint32_t payload_size;
+ payload_size = buffer_uint32[i];
+ payload_size = ntohl (payload_size);
+- if (payload_size)
+- {
++ if (payload_size) {
+ jack_midi_event_t event;
+- event.time = ntohl (buffer_uint32[i+1]);
+- event.size = ntohl (buffer_uint32[i+2]);
+- event.buffer = (jack_midi_data_t*) (&(buffer_uint32[i+3]));
++ event.time = ntohl (buffer_uint32[i + 1]);
++ event.size = ntohl (buffer_uint32[i + 2]);
++ event.buffer = (jack_midi_data_t*) (&(buffer_uint32[i + 3]));
+ jack_midi_event_write (buf, event.time, event.buffer, event.size);
+
+ // skip to the next event
+- unsigned int nb_data_quads = (((event.size-1) & ~0x3) >> 2)+1;
+- i += 3+nb_data_quads;
+- }
+- else
++ unsigned int nb_data_quads = (((event.size - 1) & ~0x3) >> 2) + 1;
++ i += 3 + nb_data_quads;
++ } else
+ break; // no events can follow an empty event, we're done
+ }
+ }
+@@ -857,38 +822,34 @@
+ unsigned int written = 0;
+ // midi port, encode midi events
+ unsigned int nevents = jack_midi_get_event_count (buf);
+- for (i = 0; i < nevents; ++i)
+- {
++ for (i = 0; i < nevents; ++i) {
+ jack_midi_event_t event;
+ jack_midi_event_get (&event, buf, i);
+ unsigned int nb_data_quads = (((event.size - 1) & ~0x3) >> 2) + 1;
+ unsigned int payload_size = 3 + nb_data_quads;
+ // only write if we have sufficient space for the event
+ // otherwise drop it
+- if (written + payload_size < buffer_size_uint32 - 1)
+- {
++ if (written + payload_size < buffer_size_uint32 - 1) {
+ // write header
+- buffer_uint32[written]=htonl (payload_size);
++ buffer_uint32[written] = htonl (payload_size);
+ written++;
+- buffer_uint32[written]=htonl (event.time);
++ buffer_uint32[written] = htonl (event.time);
+ written++;
+- buffer_uint32[written]=htonl (event.size);
++ buffer_uint32[written] = htonl (event.size);
+ written++;
+
+ // write data
+ jack_midi_data_t* tmpbuff = (jack_midi_data_t*)(&(buffer_uint32[written]));
+ memcpy (tmpbuff, event.buffer, event.size);
+ written += nb_data_quads;
+- }
+- else
+- {
++ } else {
+ // buffer overflow
+ jack_error ("midi buffer overflow");
+ break;
+ }
+ }
+ // now put a netjack_midi 'no-payload' event, signaling EOF
+- buffer_uint32[written]=0;
++ buffer_uint32[written] = 0;
+ }
+
+ // render functions for float
+@@ -906,8 +867,7 @@
+ if (!packet_payload)
+ return;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ int i;
+ int_float_t val;
+ #if HAVE_SAMPLERATE
+@@ -919,15 +879,12 @@
+
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ #if HAVE_SAMPLERATE
+ // audio port, resample if necessary
+- if (net_period_down != nframes)
+- {
++ if (net_period_down != nframes) {
+ SRC_STATE *src_state = src_node->data;
+- for (i = 0; i < net_period_down; i++)
+- {
++ for (i = 0; i < net_period_down; i++) {
+ packet_bufX[i] = ntohl (packet_bufX[i]);
+ }
+
+@@ -943,27 +900,20 @@
+ src_set_ratio (src_state, src.src_ratio);
+ src_process (src_state, &src);
+ src_node = jack_slist_next (src_node);
+- }
+- else
++ } else
+ #endif
+ {
+- if( dont_htonl_floats )
+- {
+- memcpy( buf, packet_bufX, net_period_down*sizeof(jack_default_audio_sample_t));
+- }
+- else
+- {
+- for (i = 0; i < net_period_down; i++)
+- {
+- val.i = packet_bufX[i];
+- val.i = ntohl (val.i);
+- buf[i] = val.f;
++ if( dont_htonl_floats ) {
++ memcpy( buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t));
++ } else {
++ for (i = 0; i < net_period_down; i++) {
++ val.i = packet_bufX[i];
++ val.i = ntohl (val.i);
++ buf[i] = val.f;
+ }
+ }
+ }
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // midi port, decode midi events
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_down;
+@@ -987,8 +937,7 @@
+
+ uint32_t *packet_bufX = (uint32_t *) packet_payload;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ #if HAVE_SAMPLERATE
+ SRC_DATA src;
+ #endif
+@@ -999,8 +948,7 @@
+
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ // audio port, resample if necessary
+
+ #if HAVE_SAMPLERATE
+@@ -1018,32 +966,24 @@
+ src_set_ratio (src_state, src.src_ratio);
+ src_process (src_state, &src);
+
+- for (i = 0; i < net_period_up; i++)
+- {
++ for (i = 0; i < net_period_up; i++) {
+ packet_bufX[i] = htonl (packet_bufX[i]);
+ }
+ src_node = jack_slist_next (src_node);
+- }
+- else
++ } else
+ #endif
+ {
+- if( dont_htonl_floats )
+- {
+- memcpy( packet_bufX, buf, net_period_up*sizeof(jack_default_audio_sample_t) );
+- }
+- else
+- {
+- for (i = 0; i < net_period_up; i++)
+- {
+- val.f = buf[i];
+- val.i = htonl (val.i);
+- packet_bufX[i] = val.i;
++ if( dont_htonl_floats ) {
++ memcpy( packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t) );
++ } else {
++ for (i = 0; i < net_period_up; i++) {
++ val.f = buf[i];
++ val.i = htonl (val.i);
++ packet_bufX[i] = val.i;
+ }
+ }
+ }
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // encode midi events from port to packet
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_up;
+@@ -1069,10 +1009,9 @@
+ uint16_t *packet_bufX = (uint16_t *)packet_payload;
+
+ if( !packet_payload )
+- return;
++ return;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ int i;
+ //uint32_t val;
+ #if HAVE_SAMPLERATE
+@@ -1087,16 +1026,13 @@
+ #endif
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ // audio port, resample if necessary
+
+ #if HAVE_SAMPLERATE
+- if (net_period_down != nframes)
+- {
++ if (net_period_down != nframes) {
+ SRC_STATE *src_state = src_node->data;
+- for (i = 0; i < net_period_down; i++)
+- {
++ for (i = 0; i < net_period_down; i++) {
+ floatbuf[i] = ((float) ntohs(packet_bufX[i])) / 32767.0 - 1.0;
+ }
+
+@@ -1112,14 +1048,11 @@
+ src_set_ratio (src_state, src.src_ratio);
+ src_process (src_state, &src);
+ src_node = jack_slist_next (src_node);
+- }
+- else
++ } else
+ #endif
+ for (i = 0; i < net_period_down; i++)
+ buf[i] = ((float) ntohs (packet_bufX[i])) / 32768.0 - 1.0;
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // midi port, decode midi events
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_down / 2;
+@@ -1143,8 +1076,7 @@
+
+ uint16_t *packet_bufX = (uint16_t *)packet_payload;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ #if HAVE_SAMPLERATE
+ SRC_DATA src;
+ #endif
+@@ -1153,13 +1085,11 @@
+ jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes);
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ // audio port, resample if necessary
+
+ #if HAVE_SAMPLERATE
+- if (net_period_up != nframes)
+- {
++ if (net_period_up != nframes) {
+ SRC_STATE *src_state = src_node->data;
+
+ float *floatbuf = alloca (sizeof(float) * net_period_up);
+@@ -1176,19 +1106,15 @@
+ src_set_ratio (src_state, src.src_ratio);
+ src_process (src_state, &src);
+
+- for (i = 0; i < net_period_up; i++)
+- {
++ for (i = 0; i < net_period_up; i++) {
+ packet_bufX[i] = htons (((uint16_t)((floatbuf[i] + 1.0) * 32767.0)));
+ }
+ src_node = jack_slist_next (src_node);
+- }
+- else
++ } else
+ #endif
+ for (i = 0; i < net_period_up; i++)
+ packet_bufX[i] = htons(((uint16_t)((buf[i] + 1.0) * 32767.0)));
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // encode midi events from port to packet
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_up / 2;
+@@ -1217,8 +1143,7 @@
+ if (!packet_payload)
+ return;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ int i;
+ //uint32_t val;
+ #if HAVE_SAMPLERATE
+@@ -1233,12 +1158,10 @@
+ #endif
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio(porttype))
+- {
++ if (jack_port_is_audio(porttype)) {
+ #if HAVE_SAMPLERATE
+ // audio port, resample if necessary
+- if (net_period_down != nframes)
+- {
++ if (net_period_down != nframes) {
+ SRC_STATE *src_state = src_node->data;
+ for (i = 0; i < net_period_down; i++)
+ floatbuf[i] = ((float) packet_bufX[i]) / 127.0;
+@@ -1255,14 +1178,11 @@
+ src_set_ratio (src_state, src.src_ratio);
+ src_process (src_state, &src);
+ src_node = jack_slist_next (src_node);
+- }
+- else
++ } else
+ #endif
+ for (i = 0; i < net_period_down; i++)
+ buf[i] = ((float) packet_bufX[i]) / 127.0;
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // midi port, decode midi events
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_down / 2;
+@@ -1286,8 +1206,7 @@
+
+ int8_t *packet_bufX = (int8_t *)packet_payload;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ #if HAVE_SAMPLERATE
+ SRC_DATA src;
+ #endif
+@@ -1297,12 +1216,10 @@
+ jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes);
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ #if HAVE_SAMPLERATE
+ // audio port, resample if necessary
+- if (net_period_up != nframes)
+- {
++ if (net_period_up != nframes) {
+
+ SRC_STATE *src_state = src_node->data;
+
+@@ -1323,14 +1240,11 @@
+ for (i = 0; i < net_period_up; i++)
+ packet_bufX[i] = floatbuf[i] * 127.0;
+ src_node = jack_slist_next (src_node);
+- }
+- else
++ } else
+ #endif
+ for (i = 0; i < net_period_up; i++)
+ packet_bufX[i] = buf[i] * 127.0;
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // encode midi events from port to packet
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_up / 4;
+@@ -1354,33 +1268,29 @@
+
+ unsigned char *packet_bufX = (unsigned char *)packet_payload;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ jack_port_t *port = (jack_port_t *) node->data;
+ jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes);
+
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ // audio port, decode celt data.
+ CELTDecoder *decoder = src_node->data;
+- #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
++#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
+ if( !packet_payload )
+ celt_decode_float( decoder, NULL, net_period_down, buf, nframes );
+ else
+ celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes );
+- #else
++#else
+ if( !packet_payload )
+ celt_decode_float( decoder, NULL, net_period_down, buf );
+ else
+ celt_decode_float( decoder, packet_bufX, net_period_down, buf );
+- #endif
++#endif
+
+ src_node = jack_slist_next (src_node);
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ } else if (jack_port_is_midi (porttype)) {
+ // midi port, decode midi events
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_down / 2;
+@@ -1403,31 +1313,27 @@
+
+ unsigned char *packet_bufX = (unsigned char *)packet_payload;
+
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ jack_port_t *port = (jack_port_t *) node->data;
+ jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes);
+ const char *porttype = jack_port_type (port);
+
+- if (jack_port_is_audio (porttype))
+- {
++ if (jack_port_is_audio (porttype)) {
+ // audio port, encode celt data.
+
+- int encoded_bytes;
+- float *floatbuf = alloca (sizeof(float) * nframes );
+- memcpy( floatbuf, buf, nframes*sizeof(float) );
+- CELTEncoder *encoder = src_node->data;
++ int encoded_bytes;
++ float *floatbuf = alloca (sizeof(float) * nframes );
++ memcpy( floatbuf, buf, nframes * sizeof(float) );
++ CELTEncoder *encoder = src_node->data;
+ #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
+- encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up );
++ encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up );
+ #else
+- encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up );
++ encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up );
+ #endif
+- if( encoded_bytes != net_period_up )
+- printf( "something in celt changed. netjack needs to be changed to handle this.\n" );
+- src_node = jack_slist_next( src_node );
+- }
+- else if (jack_port_is_midi (porttype))
+- {
++ if( encoded_bytes != net_period_up )
++ printf( "something in celt changed. netjack needs to be changed to handle this.\n" );
++ src_node = jack_slist_next( src_node );
++ } else if (jack_port_is_midi (porttype)) {
+ // encode midi events from port to packet
+ // convert the data buffer to a standard format (uint32_t based)
+ unsigned int buffer_size_uint32 = net_period_up / 2;
+--- a/common/netjack_packet.h
++++ b/common/netjack_packet.h
+@@ -28,132 +28,120 @@
+ #define __JACK_NET_PACKET_H__
+
+ #ifdef __cplusplus
+- extern "C"
+- {
++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;
+-};
+-
+-// 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 );
++ 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;
++ };
++
++ // 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);
+
+-// XXX: This is sort of deprecated:
+-// This one waits forever. an is not using ppoll
+-int netjack_poll(int sockfd, int timeout);
++ 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);
+
+-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
+
+--- a/common/ringbuffer.c
++++ b/common/ringbuffer.c
+@@ -43,39 +43,39 @@
+ }
+ jack_ringbuffer_t ;
+
+-EXPORT jack_ringbuffer_t *jack_ringbuffer_create(size_t sz);
+-EXPORT void jack_ringbuffer_free(jack_ringbuffer_t *rb);
+-EXPORT void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb,
++LIB_EXPORT jack_ringbuffer_t *jack_ringbuffer_create(size_t sz);
++LIB_EXPORT void jack_ringbuffer_free(jack_ringbuffer_t *rb);
++LIB_EXPORT void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb,
+ jack_ringbuffer_data_t *vec);
+-EXPORT void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb,
++LIB_EXPORT void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb,
+ jack_ringbuffer_data_t *vec);
+-EXPORT size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt);
+-EXPORT size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt);
+-EXPORT void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt);
+-EXPORT size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb);
+-EXPORT int jack_ringbuffer_mlock(jack_ringbuffer_t *rb);
+-EXPORT void jack_ringbuffer_reset(jack_ringbuffer_t *rb);
+-EXPORT void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz);
+-EXPORT size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src,
++LIB_EXPORT size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt);
++LIB_EXPORT size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt);
++LIB_EXPORT void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt);
++LIB_EXPORT size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb);
++LIB_EXPORT int jack_ringbuffer_mlock(jack_ringbuffer_t *rb);
++LIB_EXPORT void jack_ringbuffer_reset(jack_ringbuffer_t *rb);
++LIB_EXPORT void jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz);
++LIB_EXPORT size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src,
+ size_t cnt);
+ void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt);
+-size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);
++size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb);
+
+ /* Create a new ringbuffer to hold at least `sz' bytes of data. The
+ actual buffer size is rounded up to the next power of two. */
+
+-EXPORT jack_ringbuffer_t *
++LIB_EXPORT jack_ringbuffer_t *
+ jack_ringbuffer_create (size_t sz)
+ {
+ int power_of_two;
+ jack_ringbuffer_t *rb;
+-
++
+ if ((rb = (jack_ringbuffer_t *) 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;
+@@ -86,13 +86,13 @@
+ return NULL;
+ }
+ rb->mlocked = 0;
+-
++
+ return rb;
+ }
+
+ /* Free all data associated with the ringbuffer `rb'. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_free (jack_ringbuffer_t * rb)
+ {
+ #ifdef USE_MLOCK
+@@ -106,7 +106,7 @@
+
+ /* Lock the data block of `rb' using the system call 'mlock'. */
+
+-EXPORT int
++LIB_EXPORT int
+ jack_ringbuffer_mlock (jack_ringbuffer_t * rb)
+ {
+ #ifdef USE_MLOCK
+@@ -121,17 +121,18 @@
+ /* Reset the read and write pointers to zero. This is not thread
+ safe. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_reset (jack_ringbuffer_t * rb)
+ {
+ rb->read_ptr = 0;
+ rb->write_ptr = 0;
++ memset(rb->buf, 0, rb->size);
+ }
+
+ /* Reset the read and write pointers to zero. This is not thread
+ safe. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz)
+ {
+ rb->size = sz;
+@@ -145,14 +146,14 @@
+ number of bytes in front of the read pointer and behind the write
+ pointer. */
+
+-EXPORT size_t
++LIB_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 {
+@@ -164,7 +165,7 @@
+ number of bytes in front of the write pointer and behind the read
+ pointer. */
+
+-EXPORT size_t
++LIB_EXPORT size_t
+ jack_ringbuffer_write_space (const jack_ringbuffer_t * rb)
+ {
+ size_t w, r;
+@@ -184,7 +185,7 @@
+ /* The copying data reader. Copy at most `cnt' bytes from `rb' to
+ `dest'. Returns the actual number of bytes copied. */
+
+-EXPORT size_t
++LIB_EXPORT size_t
+ jack_ringbuffer_read (jack_ringbuffer_t * rb, char *dest, size_t cnt)
+ {
+ size_t free_cnt;
+@@ -219,11 +220,11 @@
+ 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
++/* 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
++LIB_EXPORT size_t
+ jack_ringbuffer_peek (jack_ringbuffer_t * rb, char *dest, size_t cnt)
+ {
+ size_t free_cnt;
+@@ -263,7 +264,7 @@
+ /* The copying data writer. Copy at most `cnt' bytes to `rb' from
+ `src'. Returns the actual number of bytes copied. */
+
+-EXPORT size_t
++LIB_EXPORT size_t
+ jack_ringbuffer_write (jack_ringbuffer_t * rb, const char *src, size_t cnt)
+ {
+ size_t free_cnt;
+@@ -300,7 +301,7 @@
+
+ /* Advance the read pointer `cnt' places. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_read_advance (jack_ringbuffer_t * rb, size_t cnt)
+ {
+ size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
+@@ -309,7 +310,7 @@
+
+ /* Advance the write pointer `cnt' places. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_write_advance (jack_ringbuffer_t * rb, size_t cnt)
+ {
+ size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
+@@ -321,7 +322,7 @@
+ the readable data is in one segment the second segment has zero
+ length. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_get_read_vector (const jack_ringbuffer_t * rb,
+ jack_ringbuffer_data_t * vec)
+ {
+@@ -365,7 +366,7 @@
+ the writeable data is in one segment the second segment has zero
+ length. */
+
+-EXPORT void
++LIB_EXPORT void
+ jack_ringbuffer_get_write_vector (const jack_ringbuffer_t * rb,
+ jack_ringbuffer_data_t * vec)
+ {
+--- a/common/shm.c
++++ b/common/shm.c
+@@ -12,21 +12,21 @@
+
+ /*
+ Copyright (C) 2001-2003 Paul Davis
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+- along with this program; if not, write to the Free Software
++ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+ #include "JackConstants.h"
+@@ -143,6 +143,31 @@
+
+ #ifdef WIN32
+
++#include <psapi.h>
++#include <lmcons.h>
++
++static BOOL check_process_running(DWORD process_id)
++{
++ DWORD aProcesses[2048], cbNeeded, cProcesses;
++ unsigned int i;
++
++ // Enumerate all processes
++ if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) {
++ return FALSE;
++ }
++
++ // Calculate how many process identifiers were returned.
++ cProcesses = cbNeeded / sizeof(DWORD);
++
++ for (i = 0; i < cProcesses; i++) {
++ if (aProcesses[i] == process_id) {
++ // Process process_id is running...
++ return TRUE;
++ }
++ }
++ return FALSE;
++}
++
+ static int
+ semaphore_init () {return 0;}
+
+@@ -289,8 +314,16 @@
+ static void
+ jack_set_server_prefix (const char *server_name)
+ {
+- snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
++#ifdef WIN32
++ char buffer[UNLEN+1]={0};
++ DWORD len = UNLEN+1;
++ GetUserName(buffer, &len);
++ snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
++ "jack-%s:%s:", buffer, server_name);
++#else
++ snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
+ "jack-%d:%s:", GetUID(), server_name);
++#endif
+ }
+
+ /* gain server addressability to shared memory registration segment
+@@ -481,7 +514,12 @@
+ }
+
+ /* see if server still exists */
+- #ifndef WIN32 // steph TO CHECK
++ #ifdef WIN32
++ if (check_process_running(jack_shm_header->server[i].pid)) {
++ res = EEXIST; /* other server running */
++ goto unlock;
++ }
++ #else
+ if (kill (jack_shm_header->server[i].pid, 0) == 0) {
+ res = EEXIST; /* other server running */
+ goto unlock;
+@@ -572,7 +610,7 @@
+
+ /* see if allocator still exists */
+ #ifdef WIN32 // steph
+- jack_info("TODO: kill API not available !!");
++ //jack_info("TODO: kill API not available !!");
+ #else
+ if (kill (r->allocator, 0)) {
+ if (errno == ESRCH) {
+@@ -636,6 +674,24 @@
+ return jack_attach_shm (si);
+ }
+
++int
++jack_attach_lib_shm (jack_shm_info_t* si)
++{
++ int res = jack_attach_shm(si);
++ if (res == 0)
++ si->size = jack_shm_registry[si->index].size; // Keep size in si struct
++ return res;
++}
++
++int
++jack_attach_lib_shm_read (jack_shm_info_t* si)
++{
++ int res = jack_attach_shm_read(si);
++ if (res == 0)
++ si->size = jack_shm_registry[si->index].size; // Keep size in si struct
++ return res;
++}
++
+ #ifdef USE_POSIX_SHM
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+@@ -759,6 +815,15 @@
+ /* registry may or may not be locked */
+ if (si->ptr.attached_at != MAP_FAILED) {
+ munmap (si->ptr.attached_at, jack_shm_registry[si->index].size);
++ }
++}
++
++void
++jack_release_lib_shm (jack_shm_info_t* si)
++{
++ /* registry may or may not be locked */
++ if (si->ptr.attached_at != MAP_FAILED) {
++ munmap (si->ptr.attached_at, si->size);
+ }
+ }
+
+@@ -961,6 +1026,12 @@
+ }
+ }
+
++void
++jack_release_lib_shm (jack_shm_info_t* si)
++{
++ jack_release_shm(si);
++}
++
+ int
+ jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* si)
+ {
+@@ -1160,6 +1231,12 @@
+ }
+ }
+
++void
++jack_release_lib_shm (jack_shm_info_t* si)
++{
++ jack_release_shm(si);
++}
++
+ int
+ jack_shmalloc (const char* name_not_used, jack_shmsize_t size,
+ jack_shm_info_t* si)
+@@ -1210,3 +1287,4 @@
+ }
+
+ #endif /* !USE_POSIX_SHM */
++
+--- a/common/shm.h
++++ b/common/shm.h
+@@ -116,6 +116,7 @@
+ * attached to the address space.
+ */
+
++ PRE_PACKED_STRUCTURE
+ typedef struct _jack_shm_info {
+ jack_shm_registry_index_t index; /* offset into the registry */
+ uint32_t size;
+@@ -124,9 +125,13 @@
+ char ptr_size[8];
+ } ptr; /* a "pointer" that has the same 8 bytes size when compling in 32 or 64 bits */
+ }
++#ifdef _MSC_VER
++ jack_shm_info_t; POST_PACKED_STRUCTURE
++#else
+ POST_PACKED_STRUCTURE jack_shm_info_t;
++#endif
+
+- /* utility functions used only within JACK */
++ /* utility functions used only within JACK */
+
+ void jack_shm_copy_from_registry (jack_shm_info_t*,
+ jack_shm_registry_index_t);
+@@ -147,9 +152,12 @@
+ int jack_shmalloc (const char *shm_name, jack_shmsize_t size,
+ jack_shm_info_t* result);
+ void jack_release_shm (jack_shm_info_t*);
++ void jack_release_lib_shm (jack_shm_info_t*);
+ void jack_destroy_shm (jack_shm_info_t*);
+ int jack_attach_shm (jack_shm_info_t*);
++ int jack_attach_lib_shm (jack_shm_info_t*);
+ int jack_attach_shm_read (jack_shm_info_t*);
++ int jack_attach_lib_shm_read (jack_shm_info_t*);
+ int jack_resize_shm (jack_shm_info_t*, jack_shmsize_t size);
+
+ #ifdef __cplusplus
+--- a/common/wscript
++++ b/common/wscript
+@@ -11,6 +11,7 @@
+ if conf.is_defined('HAVE_SAMPLERATE'):
+ conf.env['LIB_SAMPLERATE'] = ['samplerate']
+
++ conf.env['BUILD_NETLIB'] = conf.is_defined('HAVE_SAMPLERATE')
+ conf.env['BUILD_ADAPTER'] = conf.is_defined('HAVE_SAMPLERATE')
+
+ def create_jack_process_obj(bld, target, sources, uselib = None):
+@@ -30,8 +31,8 @@
+ if bld.env['IS_LINUX']:
+ process.env.append_value("CPPFLAGS", "-fvisibility=hidden")
+ if bld.env['IS_MACOSX']:
+- process.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc")
++ process.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64")
+ process.env.append_value("CPPFLAGS", "-fvisibility=hidden")
+ process.install_path = '${ADDON_DIR}/'
+ process.uselib_local = uselib.name
+@@ -65,7 +66,7 @@
+ ]
+
+ includes = ['.', './jack', '..']
+- uselib = ["PTHREAD"]
++ uselib = ["PTHREAD", "CELT"]
+
+ if bld.env['IS_LINUX']:
+ common_libsources += [
+@@ -113,6 +114,7 @@
+ serverlib.source = [] + common_libsources
+ serverlib.source += [
+ 'JackAudioDriver.cpp',
++ 'JackTimedDriver.cpp',
+ 'JackMidiDriver.cpp',
+ 'JackDriver.cpp',
+ 'JackEngine.cpp',
+@@ -130,8 +132,17 @@
+ 'JackNetTool.cpp',
+ 'JackNetInterface.cpp',
+ 'JackArgParser.cpp',
+- 'JackPhysicalMidiInput.cpp',
+- 'JackPhysicalMidiOutput.cpp',
++ 'JackMidiAsyncQueue.cpp',
++ 'JackMidiAsyncWaitQueue.cpp',
++ 'JackMidiBufferReadQueue.cpp',
++ 'JackMidiBufferWriteQueue.cpp',
++ 'JackMidiRawInputWriteQueue.cpp',
++ 'JackMidiRawOutputWriteQueue.cpp',
++ 'JackMidiReadQueue.cpp',
++ 'JackMidiReceiveQueue.cpp',
++ 'JackMidiSendQueue.cpp',
++ 'JackMidiUtil.cpp',
++ 'JackMidiWriteQueue.cpp'
+ ]
+
+ if bld.env['IS_LINUX']:
+@@ -165,14 +176,48 @@
+
+ if bld.env['IS_MACOSX']:
+ serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden")
+- serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc")
++ serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc -arch x86_64")
+ serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework CoreFoundation -framework vecLib -single_module")
+ serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1")
+
+ if bld.env['IS_SUN']:
+ serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket")
+
++ if bld.env['BUILD_NETLIB'] == True:
++ netlib = bld.new_task_gen('cxx', 'shlib')
++ netlib.features.append('cc')
++ netlib.defines = ['HAVE_CONFIG_H','SERVER_SIDE']
++ netlib.includes = includes
++ netlib.name = 'netlib'
++ netlib.target = 'jacknet'
++ netlib.uselib = ['SAMPLERATE', 'CELT', 'PTHREAD' , 'RT']
++ netlib.install_path = '${LIBDIR}'
++ netlib.source = [
++ 'JackNetAPI.cpp',
++ 'JackNetInterface.cpp',
++ 'JackNetTool.cpp',
++ 'JackAudioAdapterInterface.cpp',
++ 'JackLibSampleRateResampler.cpp',
++ 'JackResampler.cpp',
++ 'JackGlobals.cpp',
++ 'ringbuffer.c']
++
++ if bld.env['IS_LINUX']:
++ netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../linux/JackLinuxTime.c']
++ netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden")
++
++ if bld.env['IS_SUN']:
++ netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../solaris/JackSolarisTime.c']
++ netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden")
++
++
++ if bld.env['IS_MACOSX']:
++ netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../macosx/JackMachThread.cpp', '../macosx/JackMachTime.c']
++ netlib.env.append_value("LINKFLAGS", "-framework CoreAudio -single_module")
++
++ netlib.vnum = bld.env['JACK_API_VERSION']
++
+ clientlib = bld.new_task_gen('cxx', 'shlib')
+ clientlib.features.append('cc')
+ clientlib.defines = 'HAVE_CONFIG_H'
+@@ -214,8 +259,8 @@
+
+ if bld.env['IS_MACOSX']:
+ clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden")
+- clientlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc"
++ clientlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc -arch x86_64"
+ clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module")
+ clientlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1")
+
+--- a/dbus/controller.c
++++ b/dbus/controller.c
+@@ -1,6 +1,6 @@
+ /* -*- Mode: C ; c-basic-offset: 4 -*- */
+ /*
+- Copyright (C) 2007,2008,2010 Nedko Arnaudov
++ Copyright (C) 2007,2008,2010,2011 Nedko Arnaudov
+ Copyright (C) 2007-2008 Juuso Alasuutari
+
+ This program is free software; you can redistribute it and/or modify
+@@ -26,6 +26,9 @@
+ #include <string.h>
+ #include <dbus/dbus.h>
+ #include <assert.h>
++#include <unistd.h>
++#include <sys/sysinfo.h>
++#include <errno.h>
+
+ #include "controller.h"
+ #include "controller_internal.h"
+@@ -38,10 +41,12 @@
+ &g_jack_controller_iface_control,
+ &g_jack_controller_iface_configure,
+ &g_jack_controller_iface_patchbay,
++ &g_jack_controller_iface_session_manager,
+ &g_jack_controller_iface_transport,
+ NULL
+ };
+
++static
+ jackctl_driver_t *
+ jack_controller_find_driver(
+ jackctl_server_t *server,
+@@ -64,6 +69,80 @@
+ return NULL;
+ }
+
++static bool jack_controller_check_slave_driver(struct jack_controller * controller_ptr, const char * name)
++{
++ struct list_head * node_ptr;
++ struct jack_controller_slave_driver * driver_ptr;
++
++ list_for_each(node_ptr, &controller_ptr->slave_drivers)
++ {
++ driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
++ if (strcmp(name, driver_ptr->name) == 0)
++ {
++ return true;
++ }
++ }
++
++ return false;
++}
++
++static bool jack_controller_load_slave_drivers(struct jack_controller * controller_ptr)
++{
++ struct list_head * node_ptr;
++ struct jack_controller_slave_driver * driver_ptr;
++
++ list_for_each(node_ptr, &controller_ptr->slave_drivers)
++ {
++ driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
++
++ assert(driver_ptr->handle != NULL);
++ assert(!driver_ptr->loaded);
++
++ if (!jackctl_server_add_slave(controller_ptr->server, driver_ptr->handle))
++ {
++ jack_error("Driver \"%s\" cannot be loaded", driver_ptr->name);
++ return false;
++ }
++
++ driver_ptr->loaded = true;
++ }
++
++ return true;
++}
++
++static void jack_controller_unload_slave_drivers(struct jack_controller * controller_ptr)
++{
++ struct list_head * node_ptr;
++ struct jack_controller_slave_driver * driver_ptr;
++
++ list_for_each(node_ptr, &controller_ptr->slave_drivers)
++ {
++ driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
++ if (driver_ptr->loaded)
++ {
++ jackctl_server_remove_slave(controller_ptr->server, driver_ptr->handle);
++ driver_ptr->loaded = false;
++ }
++ }
++}
++
++static void jack_controller_remove_slave_drivers(struct jack_controller * controller_ptr)
++{
++ struct jack_controller_slave_driver * driver_ptr;
++
++ while (!list_empty(&controller_ptr->slave_drivers))
++ {
++ driver_ptr = list_entry(controller_ptr->slave_drivers.next, struct jack_controller_slave_driver, siblings);
++ assert(!driver_ptr->loaded);
++ list_del(&driver_ptr->siblings);
++ free(driver_ptr->name);
++ free(driver_ptr);
++ }
++
++ controller_ptr->slave_drivers_vparam_value.str[0] = 0;
++}
++
++static
+ jackctl_internal_t *
+ jack_controller_find_internal(
+ jackctl_server_t *server,
+@@ -86,42 +165,18 @@
+ return NULL;
+ }
+
+-jackctl_parameter_t *
+-jack_controller_find_parameter(
+- const JSList * parameters_list,
+- const char * parameter_name)
+-{
+- while (parameters_list)
+- {
+- if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
+- {
+- return parameters_list->data;
+- }
+-
+- parameters_list = jack_slist_next(parameters_list);
+- }
+-
+- return NULL;
+-}
+-
+ bool
+ jack_controller_select_driver(
+ struct jack_controller * controller_ptr,
+ const char * driver_name)
+ {
+- jackctl_driver_t *driver;
+-
+- driver = jack_controller_find_driver(controller_ptr->server, driver_name);
+- if (driver == NULL)
++ if (!jack_params_set_driver(controller_ptr->params, driver_name))
+ {
+ return false;
+ }
+
+ jack_info("driver \"%s\" selected", driver_name);
+
+- controller_ptr->driver = driver;
+- controller_ptr->driver_set = true;
+-
+ return true;
+ }
+
+@@ -145,22 +200,18 @@
+
+ assert(!controller_ptr->started); /* should be ensured by caller */
+
+- if (controller_ptr->driver == NULL)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
+- goto fail;
+- }
+-
+ controller_ptr->xruns = 0;
+
+ if (!jackctl_server_open(
+ controller_ptr->server,
+- controller_ptr->driver))
++ jack_params_get_driver(controller_ptr->params)))
+ {
+ jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server");
+ goto fail;
+ }
+
++ jack_controller_load_slave_drivers(controller_ptr);
++
+ if (!jackctl_server_start(
+ controller_ptr->server))
+ {
+@@ -221,6 +272,8 @@
+ }
+
+ fail_close_server:
++ jack_controller_unload_slave_drivers(controller_ptr);
++
+ if (!jackctl_server_close(controller_ptr->server))
+ {
+ jack_error("failed to close jack server");
+@@ -237,6 +290,15 @@
+ {
+ int ret;
+
++ pthread_mutex_lock(&controller_ptr->lock);
++ if (!list_empty(&controller_ptr->session_pending_commands))
++ {
++ pthread_mutex_unlock(&controller_ptr->lock);
++ jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Refusing to stop JACK server because of pending session commands");
++ return false;
++ }
++ pthread_mutex_unlock(&controller_ptr->lock);
++
+ jack_info("Stopping jack server...");
+
+ assert(controller_ptr->started); /* should be ensured by caller */
+@@ -263,6 +325,8 @@
+ return FALSE;
+ }
+
++ jack_controller_unload_slave_drivers(controller_ptr);
++
+ if (!jackctl_server_close(controller_ptr->server))
+ {
+ jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server");
+@@ -279,11 +343,14 @@
+ struct jack_controller * controller_ptr,
+ void *dbus_call_context_ptr)
+ {
++ assert(controller_ptr->started); /* should be ensured by caller */
++
+ if (!jackctl_server_switch_master(
+ controller_ptr->server,
+- controller_ptr->driver))
++ jack_params_get_driver(controller_ptr->params)))
+ {
+ jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
++ controller_ptr->started = false;
+ return FALSE;
+ }
+
+@@ -338,10 +405,10 @@
+
+ // Look for corresponding reserved device
+ for (i = 0; i < DEVICE_MAX; i++) {
+- if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
++ if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
+ break;
+ }
+-
++
+ if (i < DEVICE_MAX) {
+ jack_info("Released audio card %s", device_name);
+ rd_release(g_reserved_device[i].reserved_device);
+@@ -352,16 +419,109 @@
+ g_device_count--;
+ }
+
++#define controller_ptr ((struct jack_controller *)obj)
++
++static bool slave_drivers_parameter_is_set(void * obj)
++{
++ return controller_ptr->slave_drivers_set;
++}
++
++static bool slave_drivers_parameter_reset(void * obj)
++{
++ if (controller_ptr->started)
++ {
++ jack_error("Cannot modify slave-drivers when server is started");
++ return false;
++ }
++
++ jack_controller_remove_slave_drivers(controller_ptr);
++ controller_ptr->slave_drivers_set = false;
++ return true;
++}
++
++static union jackctl_parameter_value slave_drivers_parameter_get_value(void * obj)
++{
++ return controller_ptr->slave_drivers_vparam_value;
++}
++
++static bool slave_drivers_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr)
++{
++ char * buffer;
++ char * save;
++ const char * token;
++ struct list_head old_list;
++ struct list_head new_list;
++ union jackctl_parameter_value old_value;
++ union jackctl_parameter_value new_value;
++ bool old_set;
++
++ if (controller_ptr->started)
++ {
++ jack_error("Cannot modify slave-drivers when server is started");
++ return false;
++ }
++
++ old_set = controller_ptr->slave_drivers_set;
++ old_value = controller_ptr->slave_drivers_vparam_value;
++ controller_ptr->slave_drivers_vparam_value.str[0] = 0;
++ old_list = controller_ptr->slave_drivers;
++ INIT_LIST_HEAD(&controller_ptr->slave_drivers);
++
++ buffer = strdup(value_ptr->str);
++ if (buffer == NULL)
++ {
++ jack_error("strdup() failed.");
++ return false;
++ }
++
++ token = strtok_r(buffer, ",", &save);
++ while (token)
++ {
++ //jack_info("slave driver '%s'", token);
++ if (!jack_controller_add_slave_driver(controller_ptr, token))
++ {
++ jack_controller_remove_slave_drivers(controller_ptr);
++ controller_ptr->slave_drivers = old_list;
++ controller_ptr->slave_drivers_vparam_value = old_value;
++ controller_ptr->slave_drivers_set = old_set;
++
++ free(buffer);
++
++ return false;
++ }
++
++ token = strtok_r(NULL, ",", &save);
++ }
++
++ new_value = controller_ptr->slave_drivers_vparam_value;
++ new_list = controller_ptr->slave_drivers;
++ controller_ptr->slave_drivers = old_list;
++ jack_controller_remove_slave_drivers(controller_ptr);
++ controller_ptr->slave_drivers_vparam_value = new_value;
++ controller_ptr->slave_drivers = new_list;
++ controller_ptr->slave_drivers_set = true;
++
++ free(buffer);
++
++ return true;
++}
++
++static union jackctl_parameter_value slave_drivers_parameter_get_default_value(void * obj)
++{
++ union jackctl_parameter_value value;
++ value.str[0] = 0;
++ return value;
++}
++
++#undef controller_ptr
++
+ void *
+ jack_controller_create(
+ DBusConnection *connection)
+ {
++ int error;
+ struct jack_controller *controller_ptr;
+- const JSList * node_ptr;
+- const char ** driver_name_target;
+- const char ** internal_name_target;
+- JSList * drivers;
+- JSList * internals;
++ const char * address[PARAM_ADDRESS_SIZE];
+ DBusObjectPathVTable vtable =
+ {
+ jack_dbus_message_handler_unregister,
+@@ -376,60 +536,55 @@
+ goto fail;
+ }
+
+- controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release);
+- if (controller_ptr->server == NULL)
++ error = pthread_mutex_init(&controller_ptr->lock, NULL);
++ if (error != 0)
+ {
+- jack_error("Failed to create server object");
++ jack_error("Failed to initialize mutex. error %d", error);
+ goto fail_free;
+ }
+
+- controller_ptr->client = NULL;
+- controller_ptr->started = false;
+- controller_ptr->driver = NULL;
+- controller_ptr->driver_set = false;
++ INIT_LIST_HEAD(&controller_ptr->session_pending_commands);
+
+- drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
+- controller_ptr->drivers_count = jack_slist_length(drivers);
+- controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
+- if (controller_ptr->driver_names == NULL)
++ controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release);
++ if (controller_ptr->server == NULL)
+ {
+- jack_error("Ran out of memory trying to allocate driver names array");
+- goto fail_destroy_server;
++ jack_error("Failed to create server object");
++ goto fail_uninit_mutex;
+ }
+
+- driver_name_target = controller_ptr->driver_names;
+- node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
+- while (node_ptr != NULL)
++ controller_ptr->params = jack_params_create(controller_ptr->server);
++ if (controller_ptr->params == NULL)
+ {
+- *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
++ jack_error("Failed to initialize parameter tree");
++ goto fail_destroy_server;
++ }
+
+- /* select default driver */
+- if (controller_ptr->driver == NULL && strcmp(*driver_name_target, DEFAULT_DRIVER) == 0)
+- {
+- controller_ptr->driver = (jackctl_driver_t *)node_ptr->data;
+- }
++ controller_ptr->client = NULL;
++ controller_ptr->started = false;
+
+- node_ptr = jack_slist_next(node_ptr);
+- driver_name_target++;
+- }
+-
+- internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server);
+- controller_ptr->internals_count = jack_slist_length(internals);
+- controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *));
+- if (controller_ptr->internal_names == NULL)
+- {
+- jack_error("Ran out of memory trying to allocate internals names array");
+- goto fail_free_driver_names_array;
+- }
++ controller_ptr->pending_save = 0;
+
+- internal_name_target = controller_ptr->internal_names;
+- node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
+- while (node_ptr != NULL)
+- {
+- *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data);
+- node_ptr = jack_slist_next(node_ptr);
+- internal_name_target++;
+- }
++ INIT_LIST_HEAD(&controller_ptr->slave_drivers);
++ controller_ptr->slave_drivers_set = false;
++ controller_ptr->slave_drivers_vparam_value.str[0] = 0;
++
++ controller_ptr->slave_drivers_vparam.obj = controller_ptr;
++
++ controller_ptr->slave_drivers_vparam.vtable.is_set = slave_drivers_parameter_is_set;
++ controller_ptr->slave_drivers_vparam.vtable.reset = slave_drivers_parameter_reset;
++ controller_ptr->slave_drivers_vparam.vtable.get_value = slave_drivers_parameter_get_value;
++ controller_ptr->slave_drivers_vparam.vtable.set_value = slave_drivers_parameter_set_value;
++ controller_ptr->slave_drivers_vparam.vtable.get_default_value = slave_drivers_parameter_get_default_value;
++
++ controller_ptr->slave_drivers_vparam.type = JackParamString;
++ controller_ptr->slave_drivers_vparam.name = "slave-drivers";
++ controller_ptr->slave_drivers_vparam.short_decr = "Slave drivers to use";
++ controller_ptr->slave_drivers_vparam.long_descr = "A comma separated list of slave drivers";
++ controller_ptr->slave_drivers_vparam.constraint_flags = 0;
++
++ address[0] = PTNODE_ENGINE;
++ address[1] = NULL;
++ jack_params_add_parameter(controller_ptr->params, address, true, &controller_ptr->slave_drivers_vparam);
+
+ controller_ptr->dbus_descriptor.context = controller_ptr;
+ controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
+@@ -441,22 +596,22 @@
+ &controller_ptr->dbus_descriptor))
+ {
+ jack_error("Ran out of memory trying to register D-Bus object path");
+- goto fail_free_internal_names_array;
++ goto fail_destroy_params;
+ }
+
+ jack_controller_settings_load(controller_ptr);
+
+ return controller_ptr;
+
+-fail_free_internal_names_array:
+- free(controller_ptr->internal_names);
+-
+-fail_free_driver_names_array:
+- free(controller_ptr->driver_names);
++fail_destroy_params:
++ jack_params_destroy(controller_ptr->params);
+
+ fail_destroy_server:
+ jackctl_server_destroy(controller_ptr->server);
+
++fail_uninit_mutex:
++ pthread_mutex_destroy(&controller_ptr->lock);
++
+ fail_free:
+ free(controller_ptr);
+
+@@ -465,41 +620,106 @@
+ }
+
+ bool
+-jack_controller_add_slave(
+- struct jack_controller *controller_ptr,
++jack_controller_add_slave_driver(
++ struct jack_controller * controller_ptr,
+ const char * driver_name)
+ {
+- jackctl_driver_t *driver;
++ jackctl_driver_t * driver;
++ struct jack_controller_slave_driver * driver_ptr;
++ size_t len_old;
++ size_t len_new;
++
++ len_old = strlen(controller_ptr->slave_drivers_vparam_value.str);
++ len_new = strlen(driver_name);
++ if (len_old + len_new + 2 > sizeof(controller_ptr->slave_drivers_vparam_value.str))
++ {
++ jack_error("No more space for slave drivers.");
++ return false;
++ }
+
+ driver = jack_controller_find_driver(controller_ptr->server, driver_name);
+-
+ if (driver == NULL)
+ {
++ jack_error("Unknown driver \"%s\"", driver_name);
+ return false;
+ }
+
+- jack_info("driver \"%s\" selected", driver_name);
++ if (jack_controller_check_slave_driver(controller_ptr, driver_name))
++ {
++ jack_info("Driver \"%s\" is already slave", driver_name);
++ return true;
++ }
++
++ driver_ptr = malloc(sizeof(struct jack_controller_slave_driver));
++ if (driver_ptr == NULL)
++ {
++ jack_error("malloc() failed to allocate jack_controller_slave_driver struct");
++ return false;
++ }
+
+- return jackctl_server_add_slave(controller_ptr->server, driver);
++ driver_ptr->name = strdup(driver_name);
++ if (driver_ptr->name == NULL)
++ {
++ jack_error("strdup() failed for slave driver name \"%s\"", driver_name);
++ free(driver_ptr);
++ return false;
++ }
++
++ driver_ptr->handle = driver;
++ driver_ptr->loaded = false;
++
++ jack_info("driver \"%s\" set as slave", driver_name);
++
++ list_add_tail(&driver_ptr->siblings, &controller_ptr->slave_drivers);
++
++ if (len_old != 0)
++ {
++ controller_ptr->slave_drivers_vparam_value.str[len_old++] = ',';
++ }
++
++ memcpy(controller_ptr->slave_drivers_vparam_value.str + len_old, driver_name, len_new + 1);
++ controller_ptr->slave_drivers_set = true;
++
++ return true;
+ }
+
+ bool
+-jack_controller_remove_slave(
+- struct jack_controller *controller_ptr,
++jack_controller_remove_slave_driver(
++ struct jack_controller * controller_ptr,
+ const char * driver_name)
+ {
+- jackctl_driver_t *driver;
++ struct list_head * node_ptr;
++ struct jack_controller_slave_driver * driver_ptr;
+
+- driver = jack_controller_find_driver(controller_ptr->server, driver_name);
+-
+- if (driver == NULL)
++ list_for_each(node_ptr, &controller_ptr->slave_drivers)
+ {
+- return false;
+- }
++ driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
++ if (strcmp(driver_ptr->name, driver_name) == 0)
++ {
++ list_del(&driver_ptr->siblings);
++ free(driver_ptr->name);
++ free(driver_ptr);
++
++ /* update the slave-drivers param value */
++ controller_ptr->slave_drivers_vparam_value.str[0] = 0;
++ list_for_each(node_ptr, &controller_ptr->slave_drivers)
++ {
++ driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
++ if (controller_ptr->slave_drivers_vparam_value.str[0] != 0)
++ {
++ strcat(controller_ptr->slave_drivers_vparam_value.str, ",");
++ }
+
+- jack_info("driver \"%s\" selected", driver_name);
++ strcat(controller_ptr->slave_drivers_vparam_value.str, driver_ptr->name);
++ }
++
++ jack_info("driver \"%s\" is not slave anymore", driver_name);
++
++ return true;
++ }
++ }
+
+- return jackctl_server_remove_slave(controller_ptr->server, driver);
++ return false;
+ }
+
+ bool
+@@ -546,14 +766,59 @@
+ {
+ if (controller_ptr->started)
+ {
+- jack_controller_stop_server(controller_ptr, NULL);
++ while (!jack_controller_stop_server(controller_ptr, NULL))
++ {
++ jack_info("jack server failed to stop, retrying in 3 seconds...");
++ usleep(3000000);
++ }
+ }
+
+- free(controller_ptr->driver_names);
+- free(controller_ptr->internal_names);
+-
++ jack_controller_remove_slave_drivers(controller_ptr);
++ jack_params_destroy(controller_ptr->params);
+ jackctl_server_destroy(controller_ptr->server);
+-
++ pthread_mutex_destroy(&controller_ptr->lock);
+ free(controller_ptr);
+ }
+
++void
++jack_controller_run(
++ void * context)
++{
++ struct sysinfo si;
++
++ if (controller_ptr->pending_save == 0)
++ {
++ return;
++ }
++
++ if (sysinfo(&si) != 0)
++ {
++ jack_error("sysinfo() failed with %d", errno);
++ }
++ else if (si.uptime < controller_ptr->pending_save + 2) /* delay save by two seconds */
++ {
++ return;
++ }
++
++ controller_ptr->pending_save = 0;
++ jack_controller_settings_save_auto(controller_ptr);
++}
++
++#undef controller_ptr
++
++void
++jack_controller_pending_save(
++ struct jack_controller * controller_ptr)
++{
++ struct sysinfo si;
++
++ if (sysinfo(&si) != 0)
++ {
++ jack_error("sysinfo() failed with %d.", errno);
++ controller_ptr->pending_save = 0;
++ jack_controller_settings_save_auto(controller_ptr);
++ return;
++ }
++
++ controller_ptr->pending_save = si.uptime;
++}
+--- a/dbus/controller.h
++++ b/dbus/controller.h
+@@ -25,6 +25,10 @@
+ DBusConnection *connection);
+
+ void
++jack_controller_run(
++ void *controller_ptr);
++
++void
+ jack_controller_destroy(
+ void *controller_ptr);
+
+--- a/dbus/controller_iface_configure.c
++++ b/dbus/controller_iface_configure.c
+@@ -1,6 +1,6 @@
+ /* -*- Mode: C ; c-basic-offset: 4 -*- */
+ /*
+- Copyright (C) 2007,2008 Nedko Arnaudov
++ Copyright (C) 2007,2008,2011 Nedko Arnaudov
+ Copyright (C) 2007-2008 Juuso Alasuutari
+
+ This program is free software; you can redistribute it and/or modify
+@@ -31,24 +31,6 @@
+ #include "controller_internal.h"
+ #include "xml.h"
+
+-#define PTNODE_ENGINE "engine"
+-#define PTNODE_DRIVER "driver"
+-#define PTNODE_DRIVERS "drivers"
+-#define PTNODE_INTERNALS "internals"
+-
+-#define ENGINE_DRIVER_PARAMETER_NAME "driver"
+-#define ENGINE_DRIVER_PARAMETER_TYPE JackParamString
+-#define ENGINE_DRIVER_PARAMETER_SHORT_DESCR "Driver to use"
+-#define ENGINE_DRIVER_PARAMETER_LONG_DESCR ""
+-
+-struct parameter_info
+-{
+- unsigned char type;
+- const char * name;
+- const char * short_decr;
+- const char * long_descr;
+-};
+-
+ unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] =
+ {
+ [JackParamInt] = DBUS_TYPE_INT32,
+@@ -238,12 +220,13 @@
+ index = 0;
+ while ((type = dbus_message_iter_get_arg_type(&array_iter)) != DBUS_TYPE_INVALID)
+ {
+- if (index == 3)
++ if (index == PARAM_ADDRESS_SIZE)
+ {
+ jack_dbus_error(
+ call,
+ JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid arguments to method '%s'. Parameter address array must contain not more than three elements.",
++ "Invalid arguments to method '%s'. Parameter address array must contain not more than %u elements.",
++ (unsigned int)PARAM_ADDRESS_SIZE,
+ call->method_name);
+ return false;
+ }
+@@ -267,7 +250,7 @@
+ index++;
+ }
+
+- while (index < 3)
++ while (index < PARAM_ADDRESS_SIZE)
+ {
+ address_array[index] = NULL;
+ index++;
+@@ -301,45 +284,9 @@
+
+ #define controller_ptr ((struct jack_controller *)call->context)
+
+-static
+-bool
+-jack_controller_fill_parameter_names(
+- struct jack_dbus_method_call * call,
+- DBusMessageIter * iter_ptr,
+- const char * special_first,
+- const JSList * parameters_list)
++static bool append_node_name(void * context, const char * name)
+ {
+- DBusMessageIter array_iter;
+- const char * param_name;
+-
+- if (!dbus_message_iter_open_container(iter_ptr, DBUS_TYPE_ARRAY, "s", &array_iter))
+- {
+- return false;
+- }
+-
+- if (special_first != NULL)
+- {
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &special_first))
+- {
+- dbus_message_iter_close_container(iter_ptr, &array_iter);
+- return false;
+- }
+- }
+-
+- /* Append parameter descriptions to the array. */
+- while (parameters_list != NULL)
+- {
+- param_name = jackctl_parameter_get_name(parameters_list->data);
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, ¶m_name))
+- {
+- dbus_message_iter_close_container(iter_ptr, &array_iter);
+- return false;
+- }
+-
+- parameters_list = jack_slist_next(parameters_list);
+- }
+-
+- return dbus_message_iter_close_container(iter_ptr, &array_iter);
++ return dbus_message_iter_append_basic(context, DBUS_TYPE_STRING, &name);
+ }
+
+ static
+@@ -347,14 +294,10 @@
+ jack_controller_dbus_read_container(
+ struct jack_dbus_method_call * call)
+ {
+- const char * address[3];
++ const char * address[PARAM_ADDRESS_SIZE];
+ dbus_bool_t leaf;
+ DBusMessageIter iter;
+ DBusMessageIter array_iter;
+- const char * child_name;
+- unsigned int index;
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+
+ //jack_info("jack_controller_dbus_read_container() called");
+
+@@ -377,218 +320,37 @@
+
+ dbus_message_iter_init_append(call->reply, &iter);
+
+- if (address[0] == NULL) /* root node */
++ if (!jack_params_check_address(controller_ptr->params, address, false))
+ {
+- //jack_info("reading root container");
+-
+- leaf = false;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
+- {
+- goto oom_unref;
+- }
+-
+- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter))
+- {
+- goto oom_unref;
+- }
+-
+- child_name = PTNODE_ENGINE;
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name))
+- {
+- goto oom_close_unref;
+- }
+-
+- child_name = PTNODE_DRIVER;
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name))
+- {
+- goto oom_close_unref;
+- }
+-
+- child_name = PTNODE_DRIVERS;
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name))
+- {
+- goto oom_close_unref;
+- }
+-
+- child_name = PTNODE_INTERNALS;
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name))
+- {
+- goto oom_close_unref;
+- }
+-
+- dbus_message_iter_close_container(&iter, &array_iter);
+-
++ jack_dbus_error(
++ call,
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
+ return;
+ }
+
+- if (address[0] != NULL &&
+- address[1] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
++ leaf = jack_params_is_leaf_container(controller_ptr->params, address);
++ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
+ {
+- //jack_info("reading engine params container");
+-
+- leaf = true;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
+- {
+- goto oom_unref;
+- }
+-
+- if (!jack_controller_fill_parameter_names(
+- call,
+- &iter,
+- ENGINE_DRIVER_PARAMETER_NAME,
+- jackctl_server_get_parameters(controller_ptr->server)))
+- {
+- goto oom_unref;
+- }
+-
+- return;
++ goto oom_unref;
+ }
+
+- if (address[0] != NULL &&
+- address[1] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
++ if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter))
+ {
+- //jack_info("reading current driver params container");
+-
+- leaf = true;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
+- {
+- goto oom_unref;
+- }
+-
+- if (!jack_controller_fill_parameter_names(
+- call,
+- &iter,
+- NULL,
+- jackctl_driver_get_parameters(controller_ptr->driver)))
+- {
+- goto oom_unref;
+- }
+-
+- return;
++ goto oom_unref;
+ }
+
+- if (address[0] != NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
+- {
+- leaf = address[1] != NULL;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
+- {
+- goto oom_unref;
+- }
+-
+- if (!leaf) /* available drivers requested */
+- {
+- //jack_info("reading drivers container");
+-
+- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter))
+- {
+- goto oom_unref;
+- }
+-
+- for (index = 0; index < controller_ptr->drivers_count; index++)
+- {
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, controller_ptr->driver_names + index))
+- {
+- goto oom_close_unref;
+- }
+- }
+-
+- dbus_message_iter_close_container(&iter, &array_iter);
+- }
+- else /* specified driver parameters requested */
+- {
+- //jack_info("reading driver '%s' params container", address[1]);
+-
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
+-
+- if (!jack_controller_fill_parameter_names(
+- call,
+- &iter,
+- NULL,
+- jackctl_driver_get_parameters(driver)))
+- {
+- goto oom_unref;
+- }
+- }
+-
+- return;
+- }
+
+- if (address[0] != NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
++ if (!jack_params_iterate_container(controller_ptr->params, address, append_node_name, &array_iter))
+ {
+- leaf = address[1] != NULL;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf))
+- {
+- goto oom_unref;
+- }
+-
+- if (!leaf) /* available internals requested */
+- {
+- //jack_info("reading internals container");
+-
+- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter))
+- {
+- goto oom_unref;
+- }
+-
+- for (index = 0; index < controller_ptr->internals_count; index++)
+- {
+- if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, controller_ptr->internal_names + index))
+- {
+- goto oom_close_unref;
+- }
+- }
+-
+- dbus_message_iter_close_container(&iter, &array_iter);
+- }
+- else /* specified driver parameters requested */
+- {
+- //jack_info("reading internal '%s' params container", address[1]);
+-
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- if (!jack_controller_fill_parameter_names(
+- call,
+- &iter,
+- NULL,
+- jackctl_internal_get_parameters(internal)))
+- {
+- goto oom_unref;
+- }
+- }
+-
+- return;
++ goto oom_close_unref;
+ }
+
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
++ dbus_message_iter_close_container(&iter, &array_iter);
+
+ return;
+
+@@ -603,115 +365,107 @@
+ jack_error ("Ran out of memory trying to construct method return");
+ }
+
+-static
+-void
+-jack_controller_get_parameters_info(
+- struct jack_dbus_method_call * call,
+- struct parameter_info * special_parameter_info_ptr,
+- const JSList * parameters_list)
++static bool append_parameter(void * context, const struct jack_parameter * param_ptr)
+ {
+- DBusMessageIter iter, array_iter, struct_iter;
++ DBusMessageIter struct_iter;
+ unsigned char type;
+- const char *str;
+
+- call->reply = dbus_message_new_method_return (call->message);
+- if (!call->reply)
++ /* Open the struct. */
++ if (!dbus_message_iter_open_container(context, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+ {
+ goto fail;
+ }
+
+- dbus_message_iter_init_append (call->reply, &iter);
++ /* Append parameter type. */
++ type = PARAM_TYPE_JACK_TO_DBUS(param_ptr->type);
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BYTE, &type))
++ {
++ goto fail_close;
++ }
+
+- /* Open the array. */
+- if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter))
++ /* Append parameter name. */
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, ¶m_ptr->name))
+ {
+- goto fail_unref;
++ goto fail_close;
+ }
+
+- if (special_parameter_info_ptr != NULL)
++ /* Append parameter short description. */
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, ¶m_ptr->short_decr))
+ {
+- /* Open the struct. */
+- if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+- {
+- goto fail_close_unref;
+- }
++ goto fail_close;
++ }
+
+- /* Append parameter type. */
+- type = PARAM_TYPE_JACK_TO_DBUS(special_parameter_info_ptr->type);
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, &type))
+- {
+- goto fail_close2_unref;
+- }
++ /* Append parameter long description. */
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, ¶m_ptr->long_descr))
++ {
++ goto fail_close;
++ }
+
+- /* Append parameter name. */
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &special_parameter_info_ptr->name))
+- {
+- goto fail_close2_unref;
+- }
++ /* Close the struct. */
++ if (!dbus_message_iter_close_container(context, &struct_iter))
++ {
++ goto fail;
++ }
+
+- /* Append parameter short description. */
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &special_parameter_info_ptr->short_decr))
+- {
+- goto fail_close2_unref;
+- }
++ return true;
+
+- /* Append parameter long description. */
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &special_parameter_info_ptr->long_descr))
+- {
+- goto fail_close2_unref;
+- }
++fail_close:
++ dbus_message_iter_close_container(context, &struct_iter);
+
+- /* Close the struct. */
+- if (!dbus_message_iter_close_container (&array_iter, &struct_iter))
+- {
+- goto fail_close_unref;
+- }
+- }
++fail:
++ return false;
++}
++
++static
++void
++jack_controller_dbus_get_parameters_info(
++ struct jack_dbus_method_call * call)
++{
++ const char * address[PARAM_ADDRESS_SIZE];
++ DBusMessageIter iter, array_iter;
++
++ //jack_info("jack_controller_dbus_get_parameters_info() called");
+
+- /* Append parameter descriptions to the array. */
+- while (parameters_list != NULL)
++ if (!jack_controller_dbus_get_parameter_address(call, address))
+ {
+- /* Open the struct. */
+- if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+- {
+- goto fail_close_unref;
+- }
++ /* The method call had invalid arguments meaning that
++ * jack_controller_dbus_get_parameter_address() has
++ * constructed an error for us. */
++ return;
++ }
+
+- /* Append parameter type. */
+- type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type(parameters_list->data));
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, &type))
+- {
+- goto fail_close2_unref;
+- }
++ //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+
+- /* Append parameter name. */
+- str = jackctl_parameter_get_name(parameters_list->data);
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &str))
+- {
+- goto fail_close2_unref;
+- }
++ if (!jack_params_check_address(controller_ptr->params, address, true))
++ {
++ jack_dbus_error(
++ call,
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
++ return;
++ }
+
+- /* Append parameter short description. */
+- str = jackctl_parameter_get_short_description(parameters_list->data);
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &str))
+- {
+- goto fail_close2_unref;
+- }
++ call->reply = dbus_message_new_method_return (call->message);
++ if (!call->reply)
++ {
++ goto fail;
++ }
+
+- /* Append parameter long description. */
+- str = jackctl_parameter_get_long_description(parameters_list->data);
+- if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, &str))
+- {
+- goto fail_close2_unref;
+- }
++ dbus_message_iter_init_append (call->reply, &iter);
+
+- /* Close the struct. */
+- if (!dbus_message_iter_close_container (&array_iter, &struct_iter))
+- {
+- goto fail_close_unref;
+- }
++ /* Open the array. */
++ if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter))
++ {
++ goto fail_unref;
++ }
+
+- parameters_list = jack_slist_next(parameters_list);
++ if (!jack_params_iterate_params(controller_ptr->params, address, append_parameter, &array_iter))
++ {
++ goto fail_close_unref;
+ }
+
+ /* Close the array. */
+@@ -722,9 +476,6 @@
+
+ return;
+
+-fail_close2_unref:
+- dbus_message_iter_close_container (&iter, &struct_iter);
+-
+ fail_close_unref:
+ dbus_message_iter_close_container (&iter, &array_iter);
+
+@@ -738,15 +489,14 @@
+
+ static
+ void
+-jack_controller_dbus_get_parameters_info(
++jack_controller_dbus_get_parameter_info(
+ struct jack_dbus_method_call * call)
+ {
+- const char * address[3];
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+- struct parameter_info driver_parameter_info;
++ const char * address[PARAM_ADDRESS_SIZE];
++ const struct jack_parameter * param_ptr;
++ DBusMessageIter iter;
+
+- //jack_info("jack_controller_dbus_get_parameters_info() called");
++ //jack_info("jack_controller_dbus_get_parameter_info() called");
+
+ if (!jack_controller_dbus_get_parameter_address(call, address))
+ {
+@@ -758,152 +508,35 @@
+
+ //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+
+- if (address[0] != NULL &&
+- address[1] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
+- {
+- driver_parameter_info.type = ENGINE_DRIVER_PARAMETER_TYPE;
+- driver_parameter_info.name = ENGINE_DRIVER_PARAMETER_NAME;
+- driver_parameter_info.short_decr = ENGINE_DRIVER_PARAMETER_SHORT_DESCR;
+- driver_parameter_info.long_descr = ENGINE_DRIVER_PARAMETER_LONG_DESCR;
+-
+- jack_controller_get_parameters_info(
+- call,
+- &driver_parameter_info,
+- jackctl_server_get_parameters(controller_ptr->server));
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
++ param_ptr = jack_params_get_parameter(controller_ptr->params, address);
++ if (param_ptr == NULL)
+ {
+- jack_controller_get_parameters_info(
++ jack_dbus_error(
+ call,
+- NULL,
+- jackctl_driver_get_parameters(controller_ptr->driver));
+-
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
+ return;
+ }
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
++ call->reply = dbus_message_new_method_return(call->message);
++ if (!call->reply)
+ {
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
++ goto fail;
++ }
+
+- jack_controller_get_parameters_info(
+- call,
+- NULL,
+- jackctl_driver_get_parameters(driver));
++ dbus_message_iter_init_append(call->reply, &iter);
+
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
+- {
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameters_info(
+- call,
+- NULL,
+- jackctl_internal_get_parameters(internal));
+-
+- return;
+- }
+-
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
+-}
+-
+-static
+-void
+-jack_controller_get_parameter_info_ex(
+- struct jack_dbus_method_call * call,
+- struct parameter_info * info_ptr)
+-{
+- DBusMessageIter iter, struct_iter;
+- unsigned char type;
+-
+- call->reply = dbus_message_new_method_return(call->message);
+- if (!call->reply)
+- {
+- goto fail;
+- }
+-
+- dbus_message_iter_init_append(call->reply, &iter);
+-
+- /* Open the struct. */
+- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+- {
+- goto fail_unref;
+- }
+-
+- /* Append parameter type. */
+- type = PARAM_TYPE_JACK_TO_DBUS(info_ptr->type);
+- if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BYTE, &type))
+- {
+- goto fail_close_unref;
+- }
+-
+- /* Append parameter name. */
+- if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &info_ptr->name))
+- {
+- goto fail_close_unref;
+- }
+-
+- /* Append parameter short description. */
+- if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &info_ptr->short_decr))
+- {
+- goto fail_close_unref;
+- }
+-
+- /* Append parameter long description. */
+- if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &info_ptr->long_descr))
+- {
+- goto fail_close_unref;
+- }
+-
+- /* Close the struct. */
+- if (!dbus_message_iter_close_container(&iter, &struct_iter))
+- {
+- goto fail_unref;
++ if (!append_parameter(&iter, param_ptr))
++ {
++ goto fail_unref;
+ }
+
+ return;
+
+-fail_close_unref:
+- dbus_message_iter_close_container(&iter, &struct_iter);
+-
+ fail_unref:
+ dbus_message_unref(call->reply);
+ call->reply = NULL;
+@@ -914,32 +547,17 @@
+
+ static
+ void
+-jack_controller_get_parameter_info(
+- struct jack_dbus_method_call * call,
+- jackctl_parameter_t * parameter)
+-{
+- struct parameter_info info;
+-
+- info.type = jackctl_parameter_get_type(parameter);
+- info.name = jackctl_parameter_get_name(parameter);
+- info.short_decr = jackctl_parameter_get_short_description(parameter);
+- info.long_descr = jackctl_parameter_get_long_description(parameter);
+-
+- jack_controller_get_parameter_info_ex(call, &info);
+-}
+-
+-static
+-void
+-jack_controller_dbus_get_parameter_info(
++jack_controller_dbus_get_parameter_constraint(
+ struct jack_dbus_method_call * call)
+ {
+- const char * address[3];
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+- jackctl_parameter_t * parameter;
+- struct parameter_info driver_parameter_info;
++ const char * address[PARAM_ADDRESS_SIZE];
++ const struct jack_parameter * param_ptr;
++ uint32_t index;
++ DBusMessageIter iter, array_iter, struct_iter;
++ const char * descr;
++ message_arg_t value;
+
+- //jack_info("jack_controller_dbus_get_parameter_info() called");
++ //jack_info("jack_controller_dbus_get_parameter_constraint() called");
+
+ if (!jack_controller_dbus_get_parameter_address(call, address))
+ {
+@@ -951,178 +569,57 @@
+
+ //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
++ param_ptr = jack_params_get_parameter(controller_ptr->params, address);
++ if (param_ptr == NULL)
+ {
+- if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0)
+- {
+- driver_parameter_info.type = ENGINE_DRIVER_PARAMETER_TYPE;
+- driver_parameter_info.name = ENGINE_DRIVER_PARAMETER_NAME;
+- driver_parameter_info.short_decr = ENGINE_DRIVER_PARAMETER_SHORT_DESCR;
+- driver_parameter_info.long_descr = ENGINE_DRIVER_PARAMETER_LONG_DESCR;
+-
+- jack_controller_get_parameter_info_ex(call, &driver_parameter_info);
+-
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown engine parameter '%s'",
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_info(call, parameter);
+-
++ jack_dbus_error(
++ call,
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
+ return;
+ }
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
++ call->reply = dbus_message_new_method_return(call->message);
++ if (!call->reply)
+ {
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[1],
+- jackctl_driver_get_name(controller_ptr->driver));
+- return;
+- }
++ goto fail;
++ }
+
+- jack_controller_get_parameter_info(call, parameter);
++ dbus_message_iter_init_append(call->reply, &iter);
+
+- return;
++ if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0)
++ {
++ value.boolean = param_ptr->constraint_range;
+ }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
++ else
+ {
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_info(call, parameter);
+-
+- return;
++ value.boolean = false;
+ }
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
++ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
+ {
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for internal '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_info(call, parameter);
+-
+- return;
++ goto fail_unref;
+ }
+
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
+-}
+-
+-static
+-void
+-jack_controller_get_parameter_constraint(
+- struct jack_dbus_method_call * call,
+- jackctl_parameter_t * parameter)
+-{
+- uint32_t index;
+- uint32_t count;
+- union jackctl_parameter_value min;
+- union jackctl_parameter_value max;
+- union jackctl_parameter_value jackctl_value;
+- DBusMessageIter iter, array_iter, struct_iter;
+- const char * descr;
+- jackctl_param_type_t type;
+- message_arg_t value;
+- bool is_range;
+-
+- type = jackctl_parameter_get_type(parameter);
+-
+- call->reply = dbus_message_new_method_return(call->message);
+- if (!call->reply)
++ if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0)
+ {
+- goto fail;
++ value.boolean = (param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_STRICT) != 0;
+ }
+
+- dbus_message_iter_init_append(call->reply, &iter);
+-
+- is_range = jackctl_parameter_has_range_constraint(parameter);
+- value.boolean = is_range;
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
+ {
+ goto fail_unref;
+ }
+
+- value.boolean = jackctl_parameter_constraint_is_strict(parameter);
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
++ if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0)
+ {
+- goto fail_unref;
++ value.boolean = (param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0;
+ }
+
+- value.boolean = jackctl_parameter_constraint_is_fake_value(parameter);
+ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value))
+ {
+ goto fail_unref;
+@@ -1134,19 +631,26 @@
+ goto fail_unref;
+ }
+
+- if (is_range)
++ if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) == 0)
+ {
+- jackctl_parameter_get_range_constraint(parameter, &min, &max);
++ goto close;
++ }
+
++ if (param_ptr->constraint_range)
++ {
+ /* Open the struct. */
+ if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+ {
+ goto fail_close_unref;
+ }
+
+- jack_controller_jack_to_dbus_variant(type, &min, &value);
++ jack_controller_jack_to_dbus_variant(param_ptr->type, ¶m_ptr->constraint.range.min, &value);
+
+- if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value))
++ if (!jack_dbus_message_append_variant(
++ &struct_iter,
++ PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
++ PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
++ &value))
+ {
+ goto fail_close2_unref;
+ }
+@@ -1170,9 +674,13 @@
+ goto fail_close_unref;
+ }
+
+- jack_controller_jack_to_dbus_variant(type, &max, &value);
++ jack_controller_jack_to_dbus_variant(param_ptr->type, ¶m_ptr->constraint.range.max, &value);
+
+- if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value))
++ if (!jack_dbus_message_append_variant(
++ &struct_iter,
++ PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
++ PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
++ &value))
+ {
+ goto fail_close2_unref;
+ }
+@@ -1192,15 +700,12 @@
+ }
+ else
+ {
+- count = jackctl_parameter_get_enum_constraints_count(parameter);
+-
+ /* Append enum values to the array. */
+- for (index = 0 ; index < count ; index++)
++ for (index = 0 ; index < param_ptr->constraint.enumeration.count ; index++)
+ {
+- jackctl_value = jackctl_parameter_get_enum_constraint_value(parameter, index);
+- descr = jackctl_parameter_get_enum_constraint_description(parameter, index);
++ descr = param_ptr->constraint.enumeration.possible_values_array[index].short_desc;
+
+- jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value);
++ jack_controller_jack_to_dbus_variant(param_ptr->type, ¶m_ptr->constraint.enumeration.possible_values_array[index].value, &value);
+
+ /* Open the struct. */
+ if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+@@ -1208,7 +713,11 @@
+ goto fail_close_unref;
+ }
+
+- if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value))
++ if (!jack_dbus_message_append_variant(
++ &struct_iter,
++ PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
++ PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
++ &value))
+ {
+ goto fail_close2_unref;
+ }
+@@ -1226,6 +735,7 @@
+ }
+ }
+
++close:
+ /* Close the array. */
+ if (!dbus_message_iter_close_container(&iter, &array_iter))
+ {
+@@ -1248,120 +758,75 @@
+ jack_error ("Ran out of memory trying to construct method return");
+ }
+
+-static
+-void
+-jack_controller_get_parameter_constraint_engine_driver(
++static void
++jack_controller_dbus_get_parameter_value(
+ struct jack_dbus_method_call * call)
+ {
+- unsigned int index;
+- DBusMessageIter iter, array_iter, struct_iter;
+- jackctl_param_type_t type;
+- dbus_bool_t bval;
++ const char * address[PARAM_ADDRESS_SIZE];
++ const struct jack_parameter * param_ptr;
++ union jackctl_parameter_value jackctl_value;
++ union jackctl_parameter_value jackctl_default_value;
+ message_arg_t value;
++ message_arg_t default_value;
+
+- type = ENGINE_DRIVER_PARAMETER_TYPE;
+-
+- call->reply = dbus_message_new_method_return(call->message);
+- if (!call->reply)
+- {
+- goto fail;
+- }
+-
+- dbus_message_iter_init_append(call->reply, &iter);
+-
+- /* is_range */
+- bval = false;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &bval))
+- {
+- goto fail_unref;
+- }
+-
+- /* is_strict */
+- bval = true;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &bval))
+- {
+- goto fail_unref;
+- }
+-
+- /* is_fake_value */
+- bval = true;
+- if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &bval))
+- {
+- goto fail_unref;
+- }
++ //jack_info("jack_controller_dbus_get_parameter_value() called");
+
+- /* Open the array. */
+- if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(vs)", &array_iter))
++ if (!jack_controller_dbus_get_parameter_address(call, address))
+ {
+- goto fail_unref;
++ /* The method call had invalid arguments meaning that
++ * jack_controller_dbus_get_parameter_address() has
++ * constructed an error for us. */
++ return;
+ }
+
+- /* Append enum values to the array. */
+- for (index = 0 ; index < controller_ptr->drivers_count ; index++)
+- {
+- /* Open the struct. */
+- if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
+- {
+- goto fail_close_unref;
+- }
+-
+- value.string = controller_ptr->driver_names[index];
+- if (!jack_dbus_message_append_variant(
+- &struct_iter,
+- PARAM_TYPE_JACK_TO_DBUS(type),
+- PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type),
+- &value))
+- {
+- goto fail_close2_unref;
+- }
+-
+- if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &value))
+- {
+- goto fail_close2_unref;
+- }
+-
+- /* Close the struct. */
+- if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
+- {
+- goto fail_close_unref;
+- }
+- }
++ //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+
+- /* Close the array. */
+- if (!dbus_message_iter_close_container(&iter, &array_iter))
++ param_ptr = jack_params_get_parameter(controller_ptr->params, address);
++ if (param_ptr == NULL)
+ {
+- goto fail_unref;
++ jack_dbus_error(
++ call,
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
++ return;
+ }
+
+- return;
+-
+-fail_close2_unref:
+- dbus_message_iter_close_container(&array_iter, &struct_iter);
+-
+-fail_close_unref:
+- dbus_message_iter_close_container(&iter, &array_iter);
++ jackctl_default_value = param_ptr->vtable.get_default_value(param_ptr->obj);
++ jackctl_value = param_ptr->vtable.get_value(param_ptr->obj);
+
+-fail_unref:
+- dbus_message_unref(call->reply);
+- call->reply = NULL;
++ jack_controller_jack_to_dbus_variant(param_ptr->type, &jackctl_value, &value);
++ jack_controller_jack_to_dbus_variant(param_ptr->type, &jackctl_default_value, &default_value);
+
+-fail:
+- jack_error ("Ran out of memory trying to construct method return");
++ /* Construct the reply. */
++ jack_dbus_construct_method_return_parameter(
++ call,
++ (dbus_bool_t)(param_ptr->vtable.is_set(param_ptr->obj) ? TRUE : FALSE),
++ PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
++ PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type),
++ default_value,
++ value);
+ }
+
+ static
+ void
+-jack_controller_dbus_get_parameter_constraint(
++jack_controller_dbus_set_parameter_value(
+ struct jack_dbus_method_call * call)
+ {
+- const char * address[3];
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+- jackctl_parameter_t * parameter;
++ const char * address[PARAM_ADDRESS_SIZE];
++ const struct jack_parameter * param_ptr;
++ DBusMessageIter iter;
++ DBusMessageIter variant_iter;
++ message_arg_t arg;
++ int arg_type;
++ union jackctl_parameter_value value;
+
+- //jack_info("jack_controller_dbus_get_parameter_constraint() called");
++ //jack_info("jack_controller_dbus_set_parameter_value() called");
+
+- if (!jack_controller_dbus_get_parameter_address(call, address))
++ if (!jack_controller_dbus_get_parameter_address_ex(call, &iter, address))
+ {
+ /* The method call had invalid arguments meaning that
+ * jack_controller_dbus_get_parameter_address() has
+@@ -1371,447 +836,20 @@
+
+ //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
+- {
+- if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0)
+- {
+- jack_controller_get_parameter_constraint_engine_driver(call);
+-
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown engine parameter '%s'",
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_constraint(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
+- {
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[1],
+- jackctl_driver_get_name(controller_ptr->driver));
+- return;
+- }
+-
+- jack_controller_get_parameter_constraint(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
+- {
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_constraint(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
+- {
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for internal '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_constraint(call, parameter);
+-
+- return;
+- }
+-
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
+-}
+-
+-static
+-void
+-jack_controller_get_parameter_value(
+- struct jack_dbus_method_call * call,
+- jackctl_parameter_t * parameter)
+-{
+- int type;
+- union jackctl_parameter_value jackctl_value;
+- union jackctl_parameter_value jackctl_default_value;
+- message_arg_t value;
+- message_arg_t default_value;
+-
+- type = jackctl_parameter_get_type(parameter);
+- jackctl_default_value = jackctl_parameter_get_default_value(parameter);
+- jackctl_value = jackctl_parameter_get_value(parameter);
+-
+- jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value);
+- jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value);
+-
+- /* Construct the reply. */
+- jack_dbus_construct_method_return_parameter(
+- call,
+- (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE),
+- PARAM_TYPE_JACK_TO_DBUS(type),
+- PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type),
+- default_value,
+- value);
+-}
+-
+-static
+-void
+-jack_controller_get_parameter_value_engine_driver(
+- struct jack_dbus_method_call * call)
+-{
+- message_arg_t value;
+- message_arg_t default_value;
+-
+- default_value.string = DEFAULT_DRIVER;
+- value.string = jackctl_driver_get_name(controller_ptr->driver);
+-
+- /* Construct the reply. */
+- jack_dbus_construct_method_return_parameter(
+- call,
+- controller_ptr->driver_set,
+- DBUS_TYPE_STRING,
+- DBUS_TYPE_STRING_AS_STRING,
+- default_value,
+- value);
+-}
+-
+-
+-static void
+-jack_controller_dbus_get_parameter_value(
+- struct jack_dbus_method_call * call)
+-{
+- const char * address[3];
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+- jackctl_parameter_t * parameter;
+-
+- //jack_info("jack_controller_dbus_get_parameter_value() called");
+-
+- if (!jack_controller_dbus_get_parameter_address(call, address))
+- {
+- /* The method call had invalid arguments meaning that
+- * jack_controller_dbus_get_parameter_address() has
+- * constructed an error for us. */
+- return;
+- }
+-
+- //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
+- {
+- if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0)
+- {
+- jack_controller_get_parameter_value_engine_driver(call);
+-
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown engine parameter '%s'",
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_value(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
+- {
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[1],
+- jackctl_driver_get_name(controller_ptr->driver));
+- return;
+- }
+-
+- jack_controller_get_parameter_value(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
+- {
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_value(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
+- {
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for internal '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_get_parameter_value(call, parameter);
+-
+- return;
+- }
+-
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
+-}
+-
+-static
+-void
+-jack_controller_set_parameter_value(
+- struct jack_dbus_method_call * call,
+- jackctl_parameter_t * parameter,
+- message_arg_t * arg_ptr,
+- int arg_type)
+-{
+- jackctl_param_type_t type;
+- union jackctl_parameter_value value;
+-
+- type = jackctl_parameter_get_type(parameter);
+-
+- if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type)
++ param_ptr = jack_params_get_parameter(controller_ptr->params, address);
++ if (param_ptr == NULL)
+ {
+ jack_dbus_error(
+ call,
+ JACK_DBUS_ERROR_INVALID_ARGS,
+- "Parameter value type mismatch: was expecting '%c', got '%c'",
+- (char)PARAM_TYPE_JACK_TO_DBUS(type),
+- (char)arg_type);
+- return;
+- }
+-
+- if (!jack_controller_dbus_to_jack_variant(
+- arg_type,
+- arg_ptr,
+- &value))
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Cannot convert parameter value");
+- return;
+- }
+-
+- jackctl_parameter_set_value(parameter, &value);
+-
+- jack_controller_settings_save_auto(controller_ptr);
+-
+- jack_dbus_construct_method_return_empty(call);
+-}
+-
+-static
+-void
+-jack_controller_set_parameter_value_engine_driver(
+- struct jack_dbus_method_call * call,
+- message_arg_t * arg_ptr,
+- int arg_type)
+-{
+- union jackctl_parameter_value value;
+-
+- if (arg_type != DBUS_TYPE_STRING)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Engine parameter value type mismatch: was expecting '%c', got '%c'",
+- (char)DBUS_TYPE_STRING,
+- (char)arg_type);
+- return;
+- }
+-
+- if (!jack_controller_dbus_to_jack_variant(
+- arg_type,
+- arg_ptr,
+- &value))
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Cannot convert engine parameter value");
+- return;
+- }
+-
+- if (!jack_controller_select_driver(controller_ptr, value.str))
+- {
+- /* Couldn't find driver with the specified name. */
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_DRIVER,
+- "Unknown driver '%s'",
+- value.str);
+- return;
+- }
+-
+- jack_controller_settings_save_auto(controller_ptr);
+-
+- jack_dbus_construct_method_return_empty(call);
+-}
+-
+-static
+-void
+-jack_controller_dbus_set_parameter_value(
+- struct jack_dbus_method_call * call)
+-{
+- const char * address[3];
+- DBusMessageIter iter;
+- DBusMessageIter variant_iter;
+- message_arg_t arg;
+- int arg_type;
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+- jackctl_parameter_t * parameter;
+-
+- //jack_info("jack_controller_dbus_set_parameter_value() called");
+-
+- if (!jack_controller_dbus_get_parameter_address_ex(call, &iter, address))
+- {
+- /* The method call had invalid arguments meaning that
+- * jack_controller_dbus_get_parameter_address() has
+- * constructed an error for us. */
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
+ return;
+ }
+
+- //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+-
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_has_next(&iter))
+@@ -1840,166 +878,35 @@
+
+ //jack_info("argument of type '%c'", arg_type);
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
+- {
+- if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0)
+- {
+- jack_controller_set_parameter_value_engine_driver(call, &arg, arg_type);
+-
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown engine parameter '%s'",
+- address[1]);
+- return;
+- }
+-
+- jack_controller_set_parameter_value(call, parameter, &arg, arg_type);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
++ if (PARAM_TYPE_JACK_TO_DBUS(param_ptr->type) != arg_type)
+ {
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[1],
+- jackctl_driver_get_name(controller_ptr->driver));
+- return;
+- }
+-
+- jack_controller_set_parameter_value(call, parameter, &arg, arg_type);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
+- {
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_set_parameter_value(call, parameter, &arg, arg_type);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
+- {
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for internal '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_set_parameter_value(call, parameter, &arg, arg_type);
+-
++ jack_dbus_error(
++ call,
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Parameter value type mismatch: was expecting '%c', got '%c'",
++ (char)PARAM_TYPE_JACK_TO_DBUS(param_ptr->type),
++ (char)arg_type);
+ return;
+ }
+
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
+-}
+-
+-static
+-void
+-jack_controller_reset_parameter_value(
+- struct jack_dbus_method_call * call,
+- jackctl_parameter_t * parameter)
+-{
+- jackctl_parameter_reset(parameter);
+-
+- jack_controller_settings_save_auto(controller_ptr);
+-
+- jack_dbus_construct_method_return_empty(call);
+-}
+-
+-static
+-void
+-jack_controller_reset_parameter_value_engine_driver(
+- struct jack_dbus_method_call * call)
+-{
+- if (!jack_controller_select_driver(controller_ptr, DEFAULT_DRIVER))
++ if (!jack_controller_dbus_to_jack_variant(
++ arg_type,
++ &arg,
++ &value))
+ {
+- /* Couldn't find driver with the specified name. */
+ jack_dbus_error(
+ call,
+- JACK_DBUS_ERROR_UNKNOWN_DRIVER,
+- "Default driver '%s' is unknown",
+- DEFAULT_DRIVER);
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Cannot convert parameter value");
+ return;
+ }
+
+- controller_ptr->driver_set = false;
++ param_ptr->vtable.set_value(param_ptr->obj, &value);
+
+- jack_controller_settings_save_auto(controller_ptr);
++ jack_controller_pending_save(controller_ptr);
+
+ jack_dbus_construct_method_return_empty(call);
++
+ }
+
+ static
+@@ -2007,10 +914,8 @@
+ jack_controller_dbus_reset_parameter_value(
+ struct jack_dbus_method_call * call)
+ {
+- const char * address[3];
+- jackctl_internal_t * internal;
+- jackctl_driver_t * driver;
+- jackctl_parameter_t * parameter;
++ const char * address[PARAM_ADDRESS_SIZE];
++ const struct jack_parameter * param_ptr;
+
+ //jack_info("jack_controller_dbus_reset_parameter_value() called");
+
+@@ -2024,130 +929,25 @@
+
+ //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]);
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */
+- {
+- if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0)
+- {
+- jack_controller_reset_parameter_value_engine_driver(call);
+-
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown engine parameter '%s'",
+- address[1]);
+- return;
+- }
+-
+- jack_controller_reset_parameter_value(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] == NULL &&
+- strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */
+- {
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[1],
+- jackctl_driver_get_name(controller_ptr->driver));
+- return;
+- }
+-
+- jack_controller_reset_parameter_value(call, parameter);
+-
+- return;
+- }
+-
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_DRIVERS) == 0)
++ param_ptr = jack_params_get_parameter(controller_ptr->params, address);
++ if (param_ptr == NULL)
+ {
+- driver = jack_controller_find_driver(controller_ptr->server, address[1]);
+- if (driver == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown driver '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for driver '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
+-
+- jack_controller_reset_parameter_value(call, parameter);
+-
++ jack_dbus_error(
++ call,
++ JACK_DBUS_ERROR_INVALID_ARGS,
++ "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
++ address[0],
++ address[1],
++ address[2],
++ call->method_name);
+ return;
+ }
+
+- if (address[0] != NULL &&
+- address[1] != NULL &&
+- address[2] != NULL &&
+- strcmp(address[0], PTNODE_INTERNALS) == 0)
+- {
+- internal = jack_controller_find_internal(controller_ptr->server, address[1]);
+- if (internal == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_INTERNAL,
+- "Unknown internal '%s'",
+- address[1]);
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]);
+- if (parameter == NULL)
+- {
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_UNKNOWN_PARAMETER,
+- "Unknown parameter '%s' for internal '%s'",
+- address[2],
+- address[1]);
+- return;
+- }
++ param_ptr->vtable.reset(param_ptr->obj);
+
+- jack_controller_reset_parameter_value(call, parameter);
++ jack_controller_pending_save(controller_ptr);
+
+- return;
+- }
+-
+- jack_dbus_error(
+- call,
+- JACK_DBUS_ERROR_INVALID_ARGS,
+- "Invalid container address '%s':'%s':'%s' supplied to method '%s'.",
+- address[0],
+- address[1],
+- address[2],
+- call->method_name);
++ jack_dbus_construct_method_return_empty(call);
+ }
+
+ #undef controller_ptr
+--- a/dbus/controller_iface_control.c
++++ b/dbus/controller_iface_control.c
+@@ -30,6 +30,7 @@
+
+ #include "jackdbus.h"
+ #include "controller_internal.h"
++#include "xml.h"
+
+ #define JACK_DBUS_IFACE_NAME "org.jackaudio.JackControl"
+
+@@ -121,14 +122,19 @@
+ }
+ else if (strcmp (call->method_name, "SwitchMaster") == 0)
+ {
+- if (!jack_controller_switch_master(controller_ptr, call))
++ if (!controller_ptr->started)
+ {
+- /* the reply is set by the failed function */
+- assert(call->reply != NULL);
+- return true;
++ goto not_started;
++ }
++ else
++ {
++ if (!jack_controller_switch_master(controller_ptr, call))
++ {
++ /* the reply is set by the failed function */
++ assert(call->reply != NULL);
++ return true;
++ }
+ }
+-
+- jack_controller_control_send_signal_server_stopped();
+ }
+ else if (strcmp (call->method_name, "GetLoad") == 0)
+ {
+@@ -221,7 +227,7 @@
+ */
+ goto exit;
+ }
+-
++
+ if (!jack_controller_load_internal(controller_ptr, internal_name)) {
+ jack_dbus_error(
+ call,
+@@ -229,10 +235,15 @@
+ "jack_controller_load_internal failed for internal (%s)", internal_name);
+ }
+ }
+- else if (strcmp (call->method_name, "AddSlave") == 0)
++ else if (strcmp (call->method_name, "AddSlaveDriver") == 0)
+ {
+ const char *driver_name;
+
++ if (controller_ptr->started)
++ {
++ goto fail_started;
++ }
++
+ if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID))
+ {
+ /* The method call had invalid arguments meaning that
+@@ -240,18 +251,28 @@
+ */
+ goto exit;
+ }
+-
+- if (!jack_controller_add_slave(controller_ptr, driver_name)) {
++
++ if (!jack_controller_add_slave_driver(controller_ptr, driver_name))
++ {
+ jack_dbus_error(
+ call,
+ JACK_DBUS_ERROR_GENERIC,
+- "jack_controller_add_slave failed for driver (%s)", driver_name);
++ "jack_controller_add_slave_driver failed for driver (%s)", driver_name);
++ }
++ else
++ {
++ jack_controller_pending_save(controller_ptr);
+ }
+ }
+- else if (strcmp (call->method_name, "RemoveSlave") == 0)
++ else if (strcmp (call->method_name, "RemoveSlaveDriver") == 0)
+ {
+ const char *driver_name;
+
++ if (controller_ptr->started)
++ {
++ goto fail_started;
++ }
++
+ if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID))
+ {
+ /* The method call had invalid arguments meaning that
+@@ -259,12 +280,17 @@
+ */
+ goto exit;
+ }
+-
+- if (!jack_controller_remove_slave(controller_ptr, driver_name)) {
++
++ if (!jack_controller_remove_slave_driver(controller_ptr, driver_name))
++ {
+ jack_dbus_error(
+ call,
+ JACK_DBUS_ERROR_GENERIC,
+- "jack_controller_remove_slave failed for driver (%s)", driver_name);
++ "jack_controller_remove_slave_driver failed for driver (%s)", driver_name);
++ }
++ else
++ {
++ jack_controller_pending_save(controller_ptr);
+ }
+ }
+ else if (strcmp (call->method_name, "UnloadInternal") == 0)
+@@ -278,7 +304,7 @@
+ */
+ goto exit;
+ }
+-
++
+ if (!jack_controller_unload_internal(controller_ptr, internal_name)) {
+ jack_dbus_error(
+ call,
+@@ -293,8 +319,7 @@
+ }
+
+ jack_dbus_construct_method_return_single(call, type, arg);
+-
+- return true;
++ goto exit;
+
+ not_started:
+ jack_dbus_only_error(
+@@ -302,6 +327,15 @@
+ JACK_DBUS_ERROR_SERVER_NOT_RUNNING,
+ "Can't execute method '%s' with stopped JACK server",
+ call->method_name);
++ goto exit;
++
++fail_started:
++ jack_dbus_only_error(
++ call,
++ JACK_DBUS_ERROR_SERVER_RUNNING,
++ "Can't execute method '%s' with started JACK server",
++ call->method_name);
++ goto exit;
+
+ exit:
+ return true;
+@@ -361,12 +395,12 @@
+ JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
+ JACK_DBUS_METHOD_ARGUMENTS_END
+
+-JACK_DBUS_METHOD_ARGUMENTS_BEGIN(AddSlave)
+- JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(AddSlaveDriver)
++ JACK_DBUS_METHOD_ARGUMENT("driver_name", "s", false)
+ JACK_DBUS_METHOD_ARGUMENTS_END
+
+-JACK_DBUS_METHOD_ARGUMENTS_BEGIN(RemoveSlave)
+- JACK_DBUS_METHOD_ARGUMENT("internal", "s", false)
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(RemoveSlaveDriver)
++ JACK_DBUS_METHOD_ARGUMENT("driver_name", "s", false)
+ JACK_DBUS_METHOD_ARGUMENTS_END
+
+ JACK_DBUS_METHODS_BEGIN
+@@ -384,8 +418,8 @@
+ JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL)
+ JACK_DBUS_METHOD_DESCRIBE(LoadInternal, NULL)
+ JACK_DBUS_METHOD_DESCRIBE(UnloadInternal, NULL)
+- JACK_DBUS_METHOD_DESCRIBE(AddSlave, NULL)
+- JACK_DBUS_METHOD_DESCRIBE(RemoveSlave, NULL)
++ JACK_DBUS_METHOD_DESCRIBE(AddSlaveDriver, NULL)
++ JACK_DBUS_METHOD_DESCRIBE(RemoveSlaveDriver, NULL)
+ JACK_DBUS_METHODS_END
+
+ JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ServerStarted)
+--- /dev/null
++++ b/dbus/controller_iface_session_manager.c
+@@ -0,0 +1,572 @@
++/* -*- Mode: C ; c-basic-offset: 4 -*- */
++/*
++ Copyright (C) 2011 Nedko Arnaudov
++
++ 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.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++
++*/
++
++#if defined(HAVE_CONFIG_H)
++#include "config.h"
++#endif
++
++#include <stdint.h>
++#include <string.h>
++#include <stdio.h>
++#include <assert.h>
++#include <dbus/dbus.h>
++
++#include "jackdbus.h"
++#include "controller_internal.h"
++#include "jack/session.h"
++#include "common/JackError.h"
++
++#define JACK_DBUS_IFACE_NAME "org.jackaudio.SessionManager"
++
++static
++void
++jack_controller_control_send_signal_session_state_changed(
++ jack_session_event_type_t type,
++ const char * target)
++{
++ dbus_uint32_t u32;
++
++ u32 = type;
++ if (target == NULL)
++ {
++ target = "";
++ }
++
++ jack_dbus_send_signal(
++ JACK_CONTROLLER_OBJECT_PATH,
++ JACK_DBUS_IFACE_NAME,
++ "StateChanged",
++ DBUS_TYPE_UINT32,
++ &u32,
++ DBUS_TYPE_STRING,
++ &target,
++ DBUS_TYPE_INVALID);
++}
++
++static bool start_detached_thread(void * (* start_routine)(void *), void * arg)
++{
++ int ret;
++ static pthread_attr_t attr;
++ pthread_t tid;
++
++ ret = pthread_attr_init(&attr);
++ if (ret != 0)
++ {
++ jack_error("pthread_attr_init() failed with %d", ret);
++ goto exit;
++ }
++
++ ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
++ if (ret != 0)
++ {
++ jack_error("pthread_attr_setdetachstate() failed with %d", ret);
++ goto destroy_attr;
++ }
++
++ ret = pthread_create(&tid, &attr, start_routine, arg);
++ if (ret != 0)
++ {
++ jack_error("pthread_create() failed with %d", ret);
++ goto destroy_attr;
++ }
++
++ jack_log("Detached thread %d created", (int)tid);
++
++destroy_attr:
++ pthread_attr_destroy(&attr);
++exit:
++ return ret == 0;
++}
++
++static void send_session_notify_reply(struct jack_session_pending_command * pending_cmd_ptr, jack_session_command_t * commands)
++{
++ struct jack_dbus_method_call call;
++ const jack_session_command_t * cmd_ptr;
++ DBusMessageIter top_iter, array_iter, struct_iter;
++ dbus_uint32_t u32;
++
++ /* jack_dbus_error() wants call struct */
++ call.message = pending_cmd_ptr->message;
++ call.connection = pending_cmd_ptr->connection;
++
++ if (commands == NULL)
++ {
++ jack_dbus_error(&call, JACK_DBUS_ERROR_GENERIC, "jack_session_notify() failed");
++ goto send_reply;
++ }
++
++ jack_info("Session notify complete, commands follow:");
++
++ call.reply = dbus_message_new_method_return(pending_cmd_ptr->message);
++ if (call.reply == NULL)
++ {
++ goto oom;
++ }
++
++ dbus_message_iter_init_append(call.reply, &top_iter);
++
++ if (!dbus_message_iter_open_container(&top_iter, DBUS_TYPE_ARRAY, "(sssu)", &array_iter))
++ {
++ goto unref;
++ }
++
++ for (cmd_ptr = commands; cmd_ptr->uuid != NULL; cmd_ptr++)
++ {
++ if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter))
++ {
++ goto close_array;
++ }
++
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &cmd_ptr->uuid))
++ {
++ goto close_struct;
++ }
++
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &cmd_ptr->client_name))
++ {
++ goto close_struct;
++ }
++
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &cmd_ptr->command))
++ {
++ goto close_struct;
++ }
++
++ u32 = cmd_ptr->flags;
++ if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_UINT32, &u32))
++ {
++ goto close_struct;
++ }
++
++ jack_info("uuid='%s', client='%s', command='%s', flags=0x%"PRIX32, cmd_ptr->uuid, cmd_ptr->client_name, cmd_ptr->command, u32);
++
++ if (!dbus_message_iter_close_container(&array_iter, &struct_iter))
++ {
++ goto close_array;
++ }
++ }
++
++ jack_info("End of session commands.");
++
++ if (!dbus_message_iter_close_container(&top_iter, &array_iter))
++ {
++ goto unref;
++ }
++
++ goto send_reply;
++
++close_struct:
++ dbus_message_iter_close_container(&array_iter, &struct_iter);
++close_array:
++ dbus_message_iter_close_container(&top_iter, &array_iter);
++unref:
++ dbus_message_unref(call.reply);
++ goto oom;
++
++send_reply:
++ if (call.reply != NULL)
++ {
++ if (!dbus_connection_send(pending_cmd_ptr->connection, call.reply, NULL))
++ {
++ jack_error("Ran out of memory trying to queue method return");
++ }
++
++ dbus_connection_flush(pending_cmd_ptr->connection);
++ dbus_message_unref(call.reply);
++ }
++ else
++ {
++oom:
++ jack_error("Ran out of memory trying to construct method return");
++ }
++}
++
++#define controller_ptr ((struct jack_controller *)context)
++void * jack_controller_process_session_command_thread(void * context)
++{
++ struct jack_session_pending_command * pending_cmd_ptr;
++ jack_session_command_t * commands;
++
++ jack_log("jack_controller_process_session_command_thread enter");
++
++ pthread_mutex_lock(&controller_ptr->lock);
++loop:
++ /* get next command */
++ assert(!list_empty(&controller_ptr->session_pending_commands));
++ pending_cmd_ptr = list_entry(controller_ptr->session_pending_commands.next, struct jack_session_pending_command, siblings);
++ pthread_mutex_unlock(&controller_ptr->lock);
++
++ jack_info("Session notify initiated. target='%s', type=%d, path='%s'", pending_cmd_ptr->target, (int)pending_cmd_ptr->type, pending_cmd_ptr->path);
++
++ jack_controller_control_send_signal_session_state_changed(pending_cmd_ptr->type, pending_cmd_ptr->target);
++
++ commands = jack_session_notify(controller_ptr->client, pending_cmd_ptr->target, pending_cmd_ptr->type, pending_cmd_ptr->path);
++ send_session_notify_reply(pending_cmd_ptr, commands);
++ if (commands != NULL)
++ {
++ jack_session_commands_free(commands);
++ }
++
++ pthread_mutex_lock(&controller_ptr->lock);
++
++ /* keep state consistent by sending signal after to lock */
++ /* otherwise the main thread may receive not-to-be-queued request and fail */
++ jack_controller_control_send_signal_session_state_changed(0, NULL);
++
++ /* remove the head of the list (queue) */
++ assert(!list_empty(&controller_ptr->session_pending_commands));
++ assert(pending_cmd_ptr == list_entry(controller_ptr->session_pending_commands.next, struct jack_session_pending_command, siblings));
++ list_del(&pending_cmd_ptr->siblings);
++
++ /* command cleanup */
++ dbus_message_unref(pending_cmd_ptr->message);
++ dbus_connection_ref(pending_cmd_ptr->connection);
++ free(pending_cmd_ptr);
++
++ /* If there are more commands, process them. Otherwise - exit the thread */
++ if (!list_empty(&controller_ptr->session_pending_commands))
++ {
++ goto loop;
++ }
++
++ pthread_mutex_unlock(&controller_ptr->lock);
++
++ jack_log("jack_controller_process_session_command_thread exit");
++ return NULL;
++}
++
++#undef controller_ptr
++#define controller_ptr ((struct jack_controller *)call->context)
++
++static
++void
++jack_controller_dbus_session_notify(
++ struct jack_dbus_method_call * call)
++{
++ dbus_bool_t queue;
++ const char * target;
++ dbus_uint32_t u32;
++ const char * path;
++ jack_session_event_type_t type;
++ struct jack_session_pending_command * cmd_ptr;
++
++ if (!controller_ptr->started)
++ {
++ jack_dbus_only_error(call, JACK_DBUS_ERROR_SERVER_NOT_RUNNING, "Can't execute method '%s' with stopped JACK server", call->method_name);
++ return;
++ }
++
++ if (!jack_dbus_get_method_args(
++ call,
++ DBUS_TYPE_BOOLEAN,
++ &queue,
++ DBUS_TYPE_STRING,
++ &target,
++ DBUS_TYPE_UINT32,
++ &u32,
++ DBUS_TYPE_STRING,
++ &path,
++ DBUS_TYPE_INVALID))
++ {
++ /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */
++ return;
++ }
++
++ if (*target == 0)
++ {
++ target = NULL;
++ }
++
++ type = (jack_session_event_type_t)u32;
++
++ if (type != JackSessionSave &&
++ type != JackSessionSaveAndQuit &&
++ type != JackSessionSaveTemplate)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "Invalid session event type %" PRIu32, u32);
++ return;
++ }
++
++ pthread_mutex_lock(&controller_ptr->lock);
++ if (list_empty(&controller_ptr->session_pending_commands))
++ {
++ if (!start_detached_thread(jack_controller_process_session_command_thread, controller_ptr))
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "Cannot start thread to process the command");
++ goto unlock;
++ }
++
++ jack_log("Session notify thread started");
++ }
++ else if (!queue)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "Busy");
++ goto unlock;
++ }
++
++ cmd_ptr = malloc(sizeof(struct jack_session_pending_command));
++ if (cmd_ptr == NULL)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "malloc() failed for jack_session_pending_command struct");
++ goto unlock;
++ }
++
++ cmd_ptr->message = dbus_message_ref(call->message);
++ call->message = NULL; /* mark that reply will be sent asynchronously */
++ cmd_ptr->connection = dbus_connection_ref(call->connection);
++
++ /* it is safe to use the retrived pointers because we already made an additional message reference */
++ cmd_ptr->type = type;
++ cmd_ptr->target = target;
++ cmd_ptr->path = path;
++
++ list_add_tail(&cmd_ptr->siblings, &controller_ptr->session_pending_commands);
++
++ jack_log("Session notify scheduled. target='%s', type=%"PRIu32", path='%s'", target, u32, path);
++
++unlock:
++ pthread_mutex_unlock(&controller_ptr->lock);
++}
++
++static
++void
++jack_controller_dbus_get_uuid_for_client_name(
++ struct jack_dbus_method_call * call)
++{
++ const char * client_name;
++ char * client_uuid;
++
++ if (!jack_dbus_get_method_args(
++ call,
++ DBUS_TYPE_STRING,
++ &client_name,
++ DBUS_TYPE_INVALID))
++ {
++ /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */
++ return;
++ }
++
++ client_uuid = jack_get_uuid_for_client_name(controller_ptr->client, client_name);
++ if (client_uuid == NULL)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_get_uuid_for_client_name(\"%s\") failed", client_name);
++ return;
++ }
++
++ jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, (message_arg_t)(const char *)client_uuid);
++ free(client_uuid);
++}
++
++static
++void
++jack_controller_dbus_get_client_name_by_uuid(
++ struct jack_dbus_method_call * call)
++{
++ const char * client_uuid;
++ char * client_name;
++
++ if (!jack_dbus_get_method_args(
++ call,
++ DBUS_TYPE_STRING,
++ &client_uuid,
++ DBUS_TYPE_INVALID))
++ {
++ /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */
++ return;
++ }
++
++ client_name = jack_get_client_name_by_uuid(controller_ptr->client, client_uuid);
++ if (client_name == NULL)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_get_client_name_by_uuid(\"%s\") failed", client_uuid);
++ return;
++ }
++
++ jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, (message_arg_t)(const char *)client_name);
++ free(client_name);
++}
++
++static
++void
++jack_controller_dbus_reserve_client_name(
++ struct jack_dbus_method_call * call)
++{
++ int ret;
++ const char * client_name;
++ const char * client_uuid;
++
++ if (!jack_dbus_get_method_args(
++ call,
++ DBUS_TYPE_STRING,
++ &client_name,
++ DBUS_TYPE_STRING,
++ &client_uuid,
++ DBUS_TYPE_INVALID))
++ {
++ /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */
++ return;
++ }
++
++ ret = jack_reserve_client_name(controller_ptr->client, client_name, client_uuid);
++ if (ret < 0)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_reserve_client_name(name=\"%s\", uuid=\"%s\") failed (%d)", client_name, client_uuid, ret);
++ return;
++ }
++
++ jack_dbus_construct_method_return_empty(call);
++}
++
++static
++void
++jack_controller_dbus_has_session_callback(
++ struct jack_dbus_method_call * call)
++{
++ int ret;
++ const char * client_name;
++ message_arg_t retval;
++
++ if (!jack_dbus_get_method_args(
++ call,
++ DBUS_TYPE_STRING,
++ &client_name,
++ DBUS_TYPE_INVALID))
++ {
++ /* The method call had invalid arguments meaning that jack_dbus_get_method_args() has constructed an error for us. */
++ return;
++ }
++
++ ret = jack_client_has_session_callback(controller_ptr->client, client_name);
++ if (ret < 0)
++ {
++ jack_dbus_error(call, JACK_DBUS_ERROR_GENERIC, "jack_client_has_session_callback(\"%s\") failed (%d)", client_name, ret);
++ return;
++ }
++
++ retval.boolean = ret;
++ jack_dbus_construct_method_return_single(call, DBUS_TYPE_BOOLEAN, retval);
++}
++
++static
++void
++jack_controller_dbus_get_session_state(
++ struct jack_dbus_method_call * call)
++{
++ DBusMessageIter iter;
++ struct jack_session_pending_command * cmd_ptr;
++ const char * target;
++ dbus_uint32_t type;
++ bool append_failed;
++
++ call->reply = dbus_message_new_method_return(call->message);
++ if (call->reply == NULL)
++ {
++ goto oom;
++ }
++
++ dbus_message_iter_init_append(call->reply, &iter);
++
++ pthread_mutex_lock(&controller_ptr->lock);
++
++ if (list_empty(&controller_ptr->session_pending_commands))
++ {
++ type = 0;
++ target = "";
++ }
++ else
++ {
++ cmd_ptr = list_entry(controller_ptr->session_pending_commands.next, struct jack_session_pending_command, siblings);
++ type = (dbus_uint32_t)cmd_ptr->type;
++ target = cmd_ptr->target;
++ }
++
++ append_failed =
++ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &type) ||
++ !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &target);
++
++ pthread_mutex_unlock(&controller_ptr->lock);
++
++ if (!append_failed)
++ {
++ return;
++ }
++
++ dbus_message_unref(call->reply);
++ call->reply = NULL;
++oom:
++ jack_error("Ran out of memory trying to construct method return");
++}
++
++#undef controller_ptr
++
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Notify)
++ JACK_DBUS_METHOD_ARGUMENT("queue", DBUS_TYPE_BOOLEAN_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("target", DBUS_TYPE_STRING_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("type", DBUS_TYPE_UINT32_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("path", DBUS_TYPE_STRING_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("result", "a(sssu)", true)
++JACK_DBUS_METHOD_ARGUMENTS_END
++
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetUuidForClientName)
++ JACK_DBUS_METHOD_ARGUMENT("name", DBUS_TYPE_STRING_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("uuid", DBUS_TYPE_STRING_AS_STRING, true)
++JACK_DBUS_METHOD_ARGUMENTS_END
++
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientNameByUuid)
++ JACK_DBUS_METHOD_ARGUMENT("uuid", DBUS_TYPE_STRING_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("name", DBUS_TYPE_STRING_AS_STRING, true)
++JACK_DBUS_METHOD_ARGUMENTS_END
++
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ReserveClientName)
++ JACK_DBUS_METHOD_ARGUMENT("name", DBUS_TYPE_STRING_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("uuid", DBUS_TYPE_STRING_AS_STRING, false)
++JACK_DBUS_METHOD_ARGUMENTS_END
++
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(HasSessionCallback)
++ JACK_DBUS_METHOD_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING, false)
++ JACK_DBUS_METHOD_ARGUMENT("has_session_callback", DBUS_TYPE_BOOLEAN_AS_STRING, true)
++JACK_DBUS_METHOD_ARGUMENTS_END
++
++JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetState)
++ JACK_DBUS_METHOD_ARGUMENT("type", DBUS_TYPE_UINT32_AS_STRING, true)
++ JACK_DBUS_METHOD_ARGUMENT("target", DBUS_TYPE_STRING_AS_STRING, true)
++JACK_DBUS_METHOD_ARGUMENTS_END
++
++JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(StateChanged)
++ JACK_DBUS_SIGNAL_ARGUMENT("type", DBUS_TYPE_UINT32_AS_STRING)
++ JACK_DBUS_SIGNAL_ARGUMENT("target", DBUS_TYPE_STRING_AS_STRING)
++JACK_DBUS_SIGNAL_ARGUMENTS_END
++
++JACK_DBUS_METHODS_BEGIN
++ JACK_DBUS_METHOD_DESCRIBE(Notify, jack_controller_dbus_session_notify)
++ JACK_DBUS_METHOD_DESCRIBE(GetUuidForClientName, jack_controller_dbus_get_uuid_for_client_name)
++ JACK_DBUS_METHOD_DESCRIBE(GetClientNameByUuid, jack_controller_dbus_get_client_name_by_uuid)
++ JACK_DBUS_METHOD_DESCRIBE(ReserveClientName, jack_controller_dbus_reserve_client_name)
++ JACK_DBUS_METHOD_DESCRIBE(HasSessionCallback, jack_controller_dbus_has_session_callback)
++ JACK_DBUS_METHOD_DESCRIBE(GetState, jack_controller_dbus_get_session_state)
++JACK_DBUS_METHODS_END
++
++JACK_DBUS_SIGNALS_BEGIN
++ JACK_DBUS_SIGNAL_DESCRIBE(StateChanged)
++JACK_DBUS_SIGNALS_END
++
++JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_session_manager, JACK_DBUS_IFACE_NAME)
++ JACK_DBUS_IFACE_EXPOSE_METHODS
++ JACK_DBUS_IFACE_EXPOSE_SIGNALS
++JACK_DBUS_IFACE_END
+--- a/dbus/controller_internal.h
++++ b/dbus/controller_internal.h
+@@ -1,6 +1,6 @@
+ /* -*- Mode: C ; c-basic-offset: 4 -*- */
+ /*
+- Copyright (C) 2007,2008 Nedko Arnaudov
++ Copyright (C) 2007,2008,2011 Nedko Arnaudov
+ Copyright (C) 2007-2008 Juuso Alasuutari
+
+ This program is free software; you can redistribute it and/or modify
+@@ -25,11 +25,33 @@
+ #include "jslist.h"
+ #include "jack/control.h"
+ #include "jack/jack.h"
++#include "jack/session.h"
+ #include "jackdbus.h"
++#include "list.h"
++#include "params.h"
++
++struct jack_controller_slave_driver
++{
++ struct list_head siblings;
++ char * name;
++ jackctl_driver_t * handle;
++ bool loaded;
++};
++
++struct jack_session_pending_command
++{
++ struct list_head siblings;
++ DBusConnection * connection;
++ DBusMessage * message;
++ jack_session_event_type_t type;
++ const char * target;
++ const char * path;
++};
+
+ struct jack_controller
+ {
+ jackctl_server_t *server;
++ jack_params_handle params;
+
+ void *patchbay_context;
+
+@@ -37,16 +59,17 @@
+ jack_client_t *client;
+ unsigned int xruns;
+
+- const char **driver_names;
+- unsigned int drivers_count;
+-
+- const char **internal_names;
+- unsigned int internals_count;
+-
+- jackctl_driver_t *driver;
+- bool driver_set; /* whether driver is manually set, if false - DEFAULT_DRIVER is auto set */
++ struct list_head slave_drivers;
++ bool slave_drivers_set;
++ struct jack_parameter slave_drivers_vparam;
++ union jackctl_parameter_value slave_drivers_vparam_value;
+
+ struct jack_dbus_object_descriptor dbus_descriptor;
++
++ pthread_mutex_t lock;
++ struct list_head session_pending_commands;
++
++ long pending_save; /* uptime seconds */
+ };
+
+ #define DEFAULT_DRIVER "dummy"
+@@ -56,20 +79,9 @@
+ "You probably don't want to edit this because\n" \
+ "it will be overwritten next time jackdbus saves.\n"
+
+-jackctl_driver_t *
+-jack_controller_find_driver(
+- jackctl_server_t *server,
+- const char *driver_name);
+-
+-jackctl_internal_t *
+-jack_controller_find_internal(
+- jackctl_server_t *server,
+- const char *internal_name);
+-
+-jackctl_parameter_t *
+-jack_controller_find_parameter(
+- const JSList *parameters_list,
+- const char *parameter_name);
++void
++jack_controller_pending_save(
++ struct jack_controller *controller_ptr);
+
+ bool
+ jack_controller_start_server(
+@@ -87,12 +99,12 @@
+ void *dbus_call_context_ptr);
+
+ bool
+-jack_controller_add_slave(
++jack_controller_add_slave_driver(
+ struct jack_controller *controller_ptr,
+ const char * driver_name);
+
+ bool
+-jack_controller_remove_slave(
++jack_controller_remove_slave_driver(
+ struct jack_controller *controller_ptr,
+ const char * driver_name);
+
+@@ -112,47 +124,15 @@
+ const char * internal_name);
+
+ void
+-jack_controller_settings_set_driver_option(
+- jackctl_driver_t *driver,
+- const char *option_name,
+- const char *option_value);
+-
+-void
+-jack_controller_settings_set_internal_option(
+- jackctl_internal_t *internal,
+- const char *option_name,
+- const char *option_value);
+-
+-void
+-jack_controller_settings_set_engine_option(
+- struct jack_controller *controller_ptr,
+- const char *option_name,
+- const char *option_value);
+-
+-bool
+-jack_controller_settings_save_engine_options(
+- void *context,
++jack_controller_deserialize_parameter_value(
+ struct jack_controller *controller_ptr,
+- void *dbus_call_context_ptr);
++ const char * const * address,
++ const char * value);
+
+-bool
+-jack_controller_settings_write_option(
+- void *context,
+- const char *name,
+- const char *content,
+- void *dbus_call_context_ptr);
+-
+-bool
+-jack_controller_settings_save_driver_options(
+- void *context,
+- jackctl_driver_t *driver,
+- void *dbus_call_context_ptr);
+-
+-bool
+-jack_controller_settings_save_internal_options(
+- void *context,
+- jackctl_internal_t *internal,
+- void *dbus_call_context_ptr);
++void
++jack_controller_serialize_parameter_value(
++ const struct jack_parameter * param_ptr,
++ char * value_buffer);
+
+ bool
+ jack_controller_patchbay_init(
+@@ -223,6 +203,7 @@
+ extern struct jack_dbus_interface_descriptor g_jack_controller_iface_control;
+ extern struct jack_dbus_interface_descriptor g_jack_controller_iface_configure;
+ extern struct jack_dbus_interface_descriptor g_jack_controller_iface_patchbay;
++extern struct jack_dbus_interface_descriptor g_jack_controller_iface_session_manager;
+ extern struct jack_dbus_interface_descriptor g_jack_controller_iface_transport;
+
+ #endif /* #ifndef CONTROLLER_INTERNAL_H__04D54D51_3D79_49A2_A1DA_F8587E9E7F42__INCLUDED */
+--- a/dbus/jackdbus.c
++++ b/dbus/jackdbus.c
+@@ -105,6 +105,12 @@
+ jack_dbus_send_method_return(
+ struct jack_dbus_method_call * call)
+ {
++ if (call->message == NULL)
++ {
++ /* async call */
++ return;
++ }
++
+ if (call->reply)
+ {
+ retry_send:
+@@ -942,7 +948,10 @@
+ jack_info("Listening for D-Bus messages");
+
+ g_exit_command = FALSE;
+- while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200));
++ while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200))
++ {
++ jack_controller_run(controller_ptr);
++ }
+
+ jack_controller_destroy(controller_ptr);
+
+--- a/dbus/jackdbus.h
++++ b/dbus/jackdbus.h
+@@ -46,6 +46,7 @@
+
+ #define JACK_DBUS_ERROR_UNKNOWN_METHOD "org.jackaudio.Error.UnknownMethod"
+ #define JACK_DBUS_ERROR_SERVER_NOT_RUNNING "org.jackaudio.Error.ServerNotRunning"
++#define JACK_DBUS_ERROR_SERVER_RUNNING "org.jackaudio.Error.ServerRunning"
+ #define JACK_DBUS_ERROR_UNKNOWN_DRIVER "org.jackaudio.Error.UnknownDriver"
+ #define JACK_DBUS_ERROR_UNKNOWN_INTERNAL "org.jackaudio.Error.UnknownInternal"
+ #define JACK_DBUS_ERROR_UNKNOWN_PARAMETER "org.jackaudio.Error.UnknownParameter"
+--- /dev/null
++++ b/dbus/params.c
+@@ -0,0 +1,726 @@
++/* -*- Mode: C ; c-basic-offset: 4 -*- */
++/*
++ Copyright (C) 2011 Nedko Arnaudov
++
++ 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.
++
++ 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.
++
++*/
++
++/*
++ * Parameter addresses:
++ *
++ * "engine"
++ * "engine", "driver"
++ * "engine", "realtime"
++ * "engine", ...more engine parameters
++ *
++ * "driver", "device"
++ * "driver", ...more driver parameters
++ *
++ * "drivers", "alsa", "device"
++ * "drivers", "alsa", ...more alsa driver parameters
++ *
++ * "drivers", ...more drivers
++ *
++ * "internals", "netmanager", "multicast_ip"
++ * "internals", "netmanager", ...more netmanager parameters
++ *
++ * "internals", ...more internals
++ *
++ */
++
++#include <stdbool.h>
++#include <string.h>
++#include <assert.h>
++#include <dbus/dbus.h>
++
++#include "params.h"
++#include "controller_internal.h"
++
++#define PTNODE_ENGINE "engine"
++#define PTNODE_DRIVER "driver"
++#define PTNODE_DRIVERS "drivers"
++#define PTNODE_INTERNALS "internals"
++
++struct jack_parameter_container
++{
++ struct list_head siblings;
++ char * name;
++ struct jack_parameter_container * symlink;
++ bool leaf;
++ struct list_head children;
++ void * obj;
++};
++
++struct jack_params
++{
++ jackctl_server_t * server;
++ struct jack_parameter_container root;
++ struct list_head * drivers_ptr;
++ uint32_t drivers_count;
++ struct jack_parameter_container * driver_ptr;
++ bool driver_set; /* whether driver is manually set, if false - DEFAULT_DRIVER is auto set */
++};
++
++static bool controlapi_parameter_is_set(void * obj)
++{
++ return jackctl_parameter_is_set((jackctl_parameter_t *)obj);
++}
++
++static bool controlapi_parameter_reset(void * obj)
++{
++ return jackctl_parameter_reset((jackctl_parameter_t *)obj);
++}
++
++union jackctl_parameter_value controlapi_parameter_get_value(void * obj)
++{
++ return jackctl_parameter_get_value((jackctl_parameter_t *)obj);
++}
++
++bool controlapi_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr)
++{
++ return jackctl_parameter_set_value((jackctl_parameter_t *)obj, value_ptr);
++}
++
++union jackctl_parameter_value controlapi_parameter_get_default_value(void * obj)
++{
++ return jackctl_parameter_get_default_value((jackctl_parameter_t *)obj);
++}
++
++static struct jack_parameter_container * create_container(struct list_head * parent_list_ptr, const char * name)
++{
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = malloc(sizeof(struct jack_parameter_container));
++ if (container_ptr == NULL)
++ {
++ jack_error("Ran out of memory trying to allocate struct jack_parameter_container");
++ goto fail;
++ }
++
++ container_ptr->name = strdup(name);
++ if (container_ptr->name == NULL)
++ {
++ jack_error("Ran out of memory trying to strdup parameter container name");
++ goto free;
++ }
++
++ container_ptr->leaf = false;
++ container_ptr->symlink = NULL;
++ container_ptr->obj = NULL;
++ INIT_LIST_HEAD(&container_ptr->children);
++ list_add_tail(&container_ptr->siblings, parent_list_ptr);
++
++ return container_ptr;
++
++free:
++ free(container_ptr);
++fail:
++ return NULL;
++}
++
++static bool add_controlapi_param(struct list_head * parent_list_ptr, jackctl_parameter_t * param)
++{
++ struct jack_parameter * param_ptr;
++ uint32_t i;
++
++ param_ptr = malloc(sizeof(struct jack_parameter));
++ if (param_ptr == NULL)
++ {
++ jack_error("Ran out of memory trying to allocate struct jack_parameter");
++ goto fail;
++ }
++
++ param_ptr->ext = false;
++ param_ptr->obj = param;
++ param_ptr->vtable.is_set = controlapi_parameter_is_set;
++ param_ptr->vtable.reset = controlapi_parameter_reset;
++ param_ptr->vtable.get_value = controlapi_parameter_get_value;
++ param_ptr->vtable.set_value = controlapi_parameter_set_value;
++ param_ptr->vtable.get_default_value = controlapi_parameter_get_default_value;
++
++ param_ptr->type = jackctl_parameter_get_type(param);
++ param_ptr->name = jackctl_parameter_get_name(param);
++ param_ptr->short_decr = jackctl_parameter_get_short_description(param);
++ param_ptr->long_descr = jackctl_parameter_get_long_description(param);
++
++ if (jackctl_parameter_has_range_constraint(param))
++ {
++ param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID;
++ param_ptr->constraint_range = true;
++ jackctl_parameter_get_range_constraint(param, ¶m_ptr->constraint.range.min, ¶m_ptr->constraint.range.max);
++ }
++ else if (jackctl_parameter_has_enum_constraint(param))
++ {
++ param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID;
++ param_ptr->constraint_range = false;
++ param_ptr->constraint.enumeration.count = jackctl_parameter_get_enum_constraints_count(param);
++ param_ptr->constraint.enumeration.possible_values_array = malloc(sizeof(struct jack_parameter_enum) * param_ptr->constraint.enumeration.count);
++ if (param_ptr->constraint.enumeration.possible_values_array == NULL)
++ {
++ goto free;
++ }
++
++ for (i = 0; i < param_ptr->constraint.enumeration.count; i++)
++ {
++ param_ptr->constraint.enumeration.possible_values_array[i].value = jackctl_parameter_get_enum_constraint_value(param, i);
++ param_ptr->constraint.enumeration.possible_values_array[i].short_desc = jackctl_parameter_get_enum_constraint_description(param, i);
++ }
++ }
++ else
++ {
++ param_ptr->constraint_flags = 0;
++ goto add;
++ }
++
++ if (jackctl_parameter_constraint_is_strict(param))
++ {
++ param_ptr->constraint_flags |= JACK_CONSTRAINT_FLAG_STRICT;
++ }
++
++ if (jackctl_parameter_constraint_is_fake_value(param))
++ {
++ param_ptr->constraint_flags |= JACK_CONSTRAINT_FLAG_FAKE_VALUE;
++ }
++
++add:
++ list_add_tail(¶m_ptr->siblings, parent_list_ptr);
++ return true;
++
++free:
++ free(param_ptr);
++fail:
++ return false;
++}
++
++static void free_params(struct list_head * parent_list_ptr)
++{
++ struct jack_parameter * param_ptr;
++
++ while (!list_empty(parent_list_ptr))
++ {
++ param_ptr = list_entry(parent_list_ptr->next, struct jack_parameter, siblings);
++ list_del(¶m_ptr->siblings);
++
++ if (param_ptr->ext)
++ {
++ continue;
++ }
++
++ if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0 &&
++ !param_ptr->constraint_range &&
++ param_ptr->constraint.enumeration.possible_values_array != NULL)
++ {
++ free(param_ptr->constraint.enumeration.possible_values_array);
++ }
++
++ free(param_ptr);
++ }
++}
++
++static void free_containers(struct list_head * parent_list_ptr)
++{
++ struct jack_parameter_container * container_ptr;
++
++ while (!list_empty(parent_list_ptr))
++ {
++ container_ptr = list_entry(parent_list_ptr->next, struct jack_parameter_container, siblings);
++ list_del(&container_ptr->siblings);
++
++ if (container_ptr->leaf)
++ {
++ free_params(&container_ptr->children);
++ }
++ else
++ {
++ free_containers(&container_ptr->children);
++ }
++
++ free(container_ptr->name);
++ free(container_ptr);
++ }
++}
++
++static struct jack_parameter_container * find_container(struct jack_parameter_container * parent_ptr, const char * const * address, int max_depth)
++{
++ struct list_head * node_ptr;
++ struct jack_parameter_container * container_ptr;
++
++ if (max_depth == 0 || *address == NULL)
++ {
++ return parent_ptr;
++ }
++
++ if (parent_ptr->leaf)
++ {
++ return NULL;
++ }
++
++ if (max_depth > 0)
++ {
++ max_depth--;
++ }
++
++ list_for_each(node_ptr, &parent_ptr->children)
++ {
++ container_ptr = list_entry(node_ptr, struct jack_parameter_container, siblings);
++ if (strcmp(container_ptr->name, *address) == 0)
++ {
++ if (container_ptr->symlink != NULL)
++ {
++ container_ptr = container_ptr->symlink;
++ }
++
++ return find_container(container_ptr, address + 1, max_depth);
++ }
++ }
++
++ return NULL;
++}
++
++static bool init_leaf(struct list_head * parent_list_ptr, const char * name, const JSList * params_list, void * obj)
++{
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = create_container(parent_list_ptr, name);
++ if (container_ptr == NULL)
++ {
++ return false;
++ }
++
++ container_ptr->leaf = true;
++ container_ptr->obj = obj;
++
++ while (params_list)
++ {
++ if (!add_controlapi_param(&container_ptr->children, params_list->data))
++ {
++ return false;
++ }
++
++ params_list = jack_slist_next(params_list);
++ }
++
++ return true;
++}
++
++static bool init_engine(struct jack_params * params_ptr)
++{
++ return init_leaf(¶ms_ptr->root.children, PTNODE_ENGINE, jackctl_server_get_parameters(params_ptr->server), NULL);
++}
++
++static bool init_drivers(struct jack_params * params_ptr)
++{
++ const JSList * list;
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = create_container(¶ms_ptr->root.children, PTNODE_DRIVERS);
++ if (container_ptr == NULL)
++ {
++ return false;
++ }
++
++ params_ptr->drivers_ptr = &container_ptr->children;
++ params_ptr->drivers_count = 0;
++
++ list = jackctl_server_get_drivers_list(params_ptr->server);
++ while (list)
++ {
++ if (!init_leaf(&container_ptr->children, jackctl_driver_get_name(list->data), jackctl_driver_get_parameters(list->data), list->data))
++ {
++ return false;
++ }
++
++ params_ptr->drivers_count++;
++
++ list = jack_slist_next(list);
++ }
++
++ return true;
++}
++
++static bool init_internals(struct jack_params * params_ptr)
++{
++ const JSList * list;
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = create_container(¶ms_ptr->root.children, PTNODE_INTERNALS);
++ if (container_ptr == NULL)
++ {
++ return false;
++ }
++
++ list = jackctl_server_get_internals_list(params_ptr->server);
++ while (list)
++ {
++ if (!init_leaf(&container_ptr->children, jackctl_internal_get_name(list->data), jackctl_internal_get_parameters(list->data), NULL))
++ {
++ return false;
++ }
++
++ list = jack_slist_next(list);
++ }
++
++ return true;
++}
++
++static bool init_driver(struct jack_params * params_ptr)
++{
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = create_container(¶ms_ptr->root.children, PTNODE_DRIVER);
++ if (container_ptr == NULL)
++ {
++ return false;
++ }
++
++ params_ptr->driver_ptr = container_ptr;
++
++ return true;
++}
++
++#define params_ptr ((struct jack_params *)obj)
++
++static bool engine_driver_parameter_is_set(void * obj)
++{
++ return params_ptr->driver_set;
++}
++
++static bool engine_driver_parameter_reset(void * obj)
++{
++ if (!jack_params_set_driver(obj, DEFAULT_DRIVER))
++ {
++ return false;
++ }
++
++ params_ptr->driver_set = false;
++
++ return true;
++}
++
++union jackctl_parameter_value engine_driver_parameter_get_value(void * obj)
++{
++ union jackctl_parameter_value value;
++
++ strcpy(value.str, params_ptr->driver_ptr->symlink->name);
++
++ return value;
++}
++
++bool engine_driver_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr)
++{
++ return jack_params_set_driver(obj, value_ptr->str);
++}
++
++union jackctl_parameter_value engine_driver_parameter_get_default_value(void * obj)
++{
++ union jackctl_parameter_value value;
++
++ strcpy(value.str, DEFAULT_DRIVER);
++
++ return value;
++}
++
++#undef params_ptr
++
++static bool add_engine_driver_enum_constraint(void * context, const char * name)
++{
++ strcpy((*((struct jack_parameter_enum **)context))->value.str, name);
++ (*((struct jack_parameter_enum **)context))->short_desc = name;
++ (*((struct jack_parameter_enum **)context))++;
++ return true;
++}
++
++static bool init_engine_driver_parameter(struct jack_params * params_ptr)
++{
++ struct jack_parameter * param_ptr;
++ const char * address[PARAM_ADDRESS_SIZE] = {PTNODE_ENGINE, NULL};
++ struct jack_parameter_container * engine_ptr;
++ struct jack_parameter_enum * possible_value;
++
++ engine_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
++ if (engine_ptr == NULL)
++ {
++ return false;
++ }
++
++ param_ptr = malloc(sizeof(struct jack_parameter));
++ if (param_ptr == NULL)
++ {
++ jack_error("Ran out of memory trying to allocate struct jack_parameter");
++ goto fail;
++ }
++
++ param_ptr->ext = false;
++ param_ptr->obj = params_ptr;
++ param_ptr->vtable.is_set = engine_driver_parameter_is_set;
++ param_ptr->vtable.reset = engine_driver_parameter_reset;
++ param_ptr->vtable.get_value = engine_driver_parameter_get_value;
++ param_ptr->vtable.set_value = engine_driver_parameter_set_value;
++ param_ptr->vtable.get_default_value = engine_driver_parameter_get_default_value;
++
++ param_ptr->type = JackParamString;
++ param_ptr->name = "driver";
++ param_ptr->short_decr = "Driver to use";
++ param_ptr->long_descr = "";
++
++ param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID | JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE;
++ param_ptr->constraint_range = false;
++ param_ptr->constraint.enumeration.count = params_ptr->drivers_count;
++ param_ptr->constraint.enumeration.possible_values_array = malloc(sizeof(struct jack_parameter_enum) * params_ptr->drivers_count);
++ if (param_ptr->constraint.enumeration.possible_values_array == NULL)
++ {
++ goto free;
++ }
++
++ address[0] = PTNODE_DRIVERS;
++ possible_value = param_ptr->constraint.enumeration.possible_values_array;
++ jack_params_iterate_container((jack_params_handle)params_ptr, address, add_engine_driver_enum_constraint, &possible_value);
++
++ list_add(¶m_ptr->siblings, &engine_ptr->children);
++ return true;
++
++free:
++ free(param_ptr);
++fail:
++ return false;
++}
++
++jack_params_handle jack_params_create(jackctl_server_t * server)
++{
++ struct jack_params * params_ptr;
++
++ params_ptr = malloc(sizeof(struct jack_params));
++ if (params_ptr == NULL)
++ {
++ jack_error("Ran out of memory trying to allocate struct jack_params");
++ return NULL;
++ }
++
++ params_ptr->server = server;
++ INIT_LIST_HEAD(¶ms_ptr->root.children);
++ params_ptr->root.leaf = false;
++ params_ptr->root.name = NULL;
++
++ if (!init_engine(params_ptr) ||
++ !init_drivers(params_ptr) ||
++ !init_driver(params_ptr) ||
++ !init_engine_driver_parameter(params_ptr) ||
++ !jack_params_set_driver((jack_params_handle)params_ptr, DEFAULT_DRIVER) ||
++ !init_internals(params_ptr))
++ {
++ jack_params_destroy((jack_params_handle)params_ptr);
++ return NULL;
++ }
++
++ params_ptr->driver_set = false;
++
++ assert(strcmp(params_ptr->driver_ptr->symlink->name, DEFAULT_DRIVER) == 0);
++
++ return (jack_params_handle)params_ptr;
++}
++
++#define params_ptr ((struct jack_params *)params)
++
++void jack_params_destroy(jack_params_handle params)
++{
++ free_containers(¶ms_ptr->root.children);
++ free(params);
++}
++
++bool jack_params_set_driver(jack_params_handle params, const char * name)
++{
++ struct list_head * node_ptr;
++ struct jack_parameter_container * container_ptr;
++
++ list_for_each(node_ptr, params_ptr->drivers_ptr)
++ {
++ container_ptr = list_entry(node_ptr, struct jack_parameter_container, siblings);
++ if (strcmp(container_ptr->name, name) == 0)
++ {
++ params_ptr->driver_ptr->symlink = container_ptr;
++ params_ptr->driver_set = true;
++ return true;
++ }
++ }
++
++ return false;
++}
++
++jackctl_driver_t * jack_params_get_driver(jack_params_handle params)
++{
++ return params_ptr->driver_ptr->symlink->obj;
++}
++
++bool jack_params_check_address(jack_params_handle params, const char * const * address, bool want_leaf)
++{
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
++ if (container_ptr == NULL)
++ {
++ return false;
++ }
++
++ if (want_leaf && !container_ptr->leaf)
++ {
++ return false;
++ }
++
++ return true;
++}
++
++bool jack_params_is_leaf_container(jack_params_handle params, const char * const * address)
++{
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
++ if (container_ptr == NULL)
++ {
++ assert(false);
++ return false;
++ }
++
++ return container_ptr->leaf;
++}
++
++bool
++jack_params_iterate_container(
++ jack_params_handle params,
++ const char * const * address,
++ bool (* callback)(void * context, const char * name),
++ void * context)
++{
++ struct jack_parameter_container * container_ptr;
++ struct list_head * node_ptr;
++ const char * name;
++
++ container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
++ if (container_ptr == NULL)
++ {
++ assert(false);
++ return true;
++ }
++
++ list_for_each(node_ptr, &container_ptr->children)
++ {
++ if (container_ptr->leaf)
++ {
++ name = list_entry(node_ptr, struct jack_parameter, siblings)->name;
++ }
++ else
++ {
++ name = list_entry(node_ptr, struct jack_parameter_container, siblings)->name;
++ }
++
++ if (!callback(context, name))
++ {
++ return false;
++ }
++ }
++
++ return true;
++}
++
++bool
++jack_params_iterate_params(
++ jack_params_handle params,
++ const char * const * address,
++ bool (* callback)(void * context, const struct jack_parameter * param_ptr),
++ void * context)
++{
++ struct jack_parameter_container * container_ptr;
++ struct list_head * node_ptr;
++ struct jack_parameter * param_ptr;
++
++ container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
++ if (container_ptr == NULL || !container_ptr->leaf)
++ {
++ assert(false);
++ return true;
++ }
++
++ list_for_each(node_ptr, &container_ptr->children)
++ {
++ param_ptr = list_entry(node_ptr, struct jack_parameter, siblings);
++ if (!callback(context, param_ptr))
++ {
++ return false;
++ }
++ }
++
++ return true;
++}
++
++const struct jack_parameter * jack_params_get_parameter(jack_params_handle params, const char * const * address)
++{
++ int depth;
++ struct jack_parameter_container * container_ptr;
++ struct list_head * node_ptr;
++ struct jack_parameter * param_ptr;
++
++ for (depth = 0; depth < PARAM_ADDRESS_SIZE; depth++)
++ {
++ if (address[depth] == NULL)
++ {
++ break;
++ }
++ }
++
++ depth--;
++
++ container_ptr = find_container(¶ms_ptr->root, address, depth);
++ if (container_ptr == NULL || !container_ptr->leaf)
++ {
++ return NULL;
++ }
++
++ list_for_each(node_ptr, &container_ptr->children)
++ {
++ param_ptr = list_entry(node_ptr, struct jack_parameter, siblings);
++ if (strcmp(param_ptr->name, address[depth]) == 0)
++ {
++ return param_ptr;
++ }
++ }
++
++ return NULL;
++}
++
++void jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr)
++{
++ struct jack_parameter_container * container_ptr;
++
++ container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
++ if (container_ptr == NULL || !container_ptr->leaf)
++ {
++ assert(false);
++ return;
++ }
++
++ param_ptr->ext = true;
++
++ if (end)
++ {
++ list_add_tail(¶m_ptr->siblings, &container_ptr->children);
++ }
++ else
++ {
++ list_add(¶m_ptr->siblings, &container_ptr->children);
++ }
++
++ return;
++}
++
++#undef params_ptr
+--- /dev/null
++++ b/dbus/params.h
+@@ -0,0 +1,111 @@
++/* -*- Mode: C ; c-basic-offset: 4 -*- */
++/*
++ Copyright (C) 2011 Nedko Arnaudov
++
++ 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.
++
++ 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 PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED
++#define PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED
++
++#include "jack/control.h"
++#include "list.h"
++
++#define PARAM_ADDRESS_SIZE 3
++
++#define PTNODE_ENGINE "engine"
++#define PTNODE_DRIVER "driver"
++#define PTNODE_DRIVERS "drivers"
++#define PTNODE_INTERNALS "internals"
++
++struct jack_parameter_vtable
++{
++ bool (* is_set)(void * obj);
++ bool (* reset)(void * obj);
++ union jackctl_parameter_value (* get_value)(void * obj);
++ bool (* set_value)(void * obj, const union jackctl_parameter_value * value_ptr);
++ union jackctl_parameter_value (* get_default_value)(void * obj);
++};
++
++#define JACK_CONSTRAINT_FLAG_VALID ((uint32_t)1) /**< if not set, there is no constraint */
++#define JACK_CONSTRAINT_FLAG_STRICT ((uint32_t)2) /**< if set, constraint is strict, i.e. supplying non-matching value will not work */
++#define JACK_CONSTRAINT_FLAG_FAKE_VALUE ((uint32_t)4) /**< if set, values have no user meaningful meaning */
++
++struct jack_parameter_enum
++{
++ union jackctl_parameter_value value;
++ const char * short_desc;
++};
++
++struct jack_parameter
++{
++ void * obj;
++ struct jack_parameter_vtable vtable;
++ struct list_head siblings;
++ bool ext;
++ jackctl_param_type_t type;
++ const char * name;
++ const char * short_decr;
++ const char * long_descr;
++
++ uint32_t constraint_flags; /**< JACK_CONSTRAINT_FLAG_XXX */
++ bool constraint_range; /**< if true, constraint is a range (min-max), otherwise it is an enumeration */
++
++ union
++ {
++ struct
++ {
++ union jackctl_parameter_value min;
++ union jackctl_parameter_value max;
++ } range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */
++
++ struct
++ {
++ uint32_t count;
++ struct jack_parameter_enum * possible_values_array;
++ } enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */
++ } constraint;
++};
++
++typedef struct _jack_params { int unused; } * jack_params_handle;
++
++jack_params_handle jack_params_create(jackctl_server_t * server);
++void jack_params_destroy(jack_params_handle params);
++
++bool jack_params_set_driver(jack_params_handle params, const char * name);
++jackctl_driver_t * jack_params_get_driver(jack_params_handle params);
++
++bool jack_params_check_address(jack_params_handle params, const char * const * address, bool want_leaf);
++bool jack_params_is_leaf_container(jack_params_handle params, const char * const * address);
++
++bool
++jack_params_iterate_container(
++ jack_params_handle params,
++ const char * const * address,
++ bool (* callback)(void * context, const char * name),
++ void * context);
++
++bool
++jack_params_iterate_params(
++ jack_params_handle params,
++ const char * const * address,
++ bool (* callback)(void * context, const struct jack_parameter * param_ptr),
++ void * context);
++
++const struct jack_parameter * jack_params_get_parameter(jack_params_handle params, const char * const * address);
++
++void jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr);
++
++#endif /* #ifndef PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED */
+--- a/dbus/reserve.c
++++ b/dbus/reserve.c
+@@ -369,8 +369,7 @@
+ DBusError _error;
+ DBusMessage *m = NULL, *reply = NULL;
+ dbus_bool_t good;
+-
+- vtable.message_function = object_handler;
++ vtable.message_function = object_handler;
+
+ if (!error)
+ error = &_error;
+@@ -430,7 +429,7 @@
+ goto fail;
+ }
+
+- if (k == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
++ if (k == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER || k == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER)
+ goto success;
+
+ if (k != DBUS_REQUEST_NAME_REPLY_EXISTS) {
+--- a/dbus/wscript
++++ b/dbus/wscript
+@@ -49,17 +49,19 @@
+ sysdeps_dbus_include = ['../macosx', '../posix']
+
+ obj.includes = sysdeps_dbus_include + ['.', '../', '../common', '../common/jack']
++ obj.defines = ['HAVE_CONFIG_H','SERVER_SIDE']
+ obj.source = [
+ 'jackdbus.c',
+ 'controller.c',
++ 'params.c',
+ 'controller_iface_configure.c',
+ 'controller_iface_control.c',
+ 'controller_iface_introspectable.c',
+ 'controller_iface_patchbay.c',
++ 'controller_iface_session_manager.c',
+ 'controller_iface_transport.c',
+ 'xml.c',
+ 'xml_expat.c',
+- #'xml_libxml.c',
+ #'xml_nop.c',
+ 'xml_write_raw.c',
+ 'sigsegv.c',
+--- a/dbus/xml.c
++++ b/dbus/xml.c
+@@ -1,6 +1,6 @@
+ /* -*- Mode: C ; c-basic-offset: 4 -*- */
+ /*
+- Copyright (C) 2007,2008 Nedko Arnaudov
++ Copyright (C) 2007,2008,2011 Nedko Arnaudov
+
+ 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
+@@ -25,358 +25,116 @@
+ #include <stdint.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <assert.h>
+ #include <dbus/dbus.h>
+
+ #include "controller_internal.h"
+
+ void
+-jack_controller_settings_set_bool_option(
+- const char *value_str,
+- int *value_ptr)
+-{
+- if (strcmp(value_str, "true") == 0)
+- {
+- *value_ptr = true;
+- }
+- else if (strcmp(value_str, "false") == 0)
+- {
+- *value_ptr = false;
+- }
+- else
+- {
+- jack_error("ignoring unknown bool value \"%s\"", value_str);
+- }
+-}
+-
+-void
+-jack_controller_settings_set_sint_option(
+- const char *value_str,
+- int *value_ptr)
+-{
+- *value_ptr = atoi(value_str);
+-}
+-
+-void
+-jack_controller_settings_set_uint_option(
+- const char *value_str,
+- unsigned int *value_ptr)
+-{
+- *value_ptr = strtoul(value_str, NULL, 10);
+-}
+-
+-void
+-jack_controller_settings_set_char_option(
+- const char *value_str,
+- char *value_ptr)
+-{
+- if (value_str[0] == 0 || value_str[1] != 0)
+- {
+- jack_error("invalid char option value \"%s\"", value_str);
+- return;
+- }
+-
+- *value_ptr = *value_str;
+-}
+-
+-void
+-jack_controller_settings_set_string_option(
+- const char *value_str,
+- char *value_ptr,
+- size_t max_size)
+-{
+- size_t size;
+-
+- size = strlen(value_str);
+-
+- if (size >= max_size)
+- {
+- jack_error("string option value \"%s\" is too long, max is %u chars (including terminating zero)", value_str, (unsigned int)max_size);
+- return;
+- }
+-
+- strcpy(value_ptr, value_str);
+-}
+-
+-void
+-jack_controller_settings_set_driver_option(
+- jackctl_driver_t *driver,
+- const char *option_name,
+- const char *option_value)
++jack_controller_deserialize_parameter_value(
++ struct jack_controller *controller_ptr,
++ const char * const * address,
++ const char * option_value)
+ {
+- jackctl_parameter_t *parameter;
+- jackctl_param_type_t type;
+- int value_int = 0;
+- unsigned int value_uint = 0;
++ const struct jack_parameter * param_ptr;
+ union jackctl_parameter_value value;
++ size_t size;
+
+- jack_info("setting driver option \"%s\" to value \"%s\"", option_name, option_value);
+-
+- parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), option_name);
+- if (parameter == NULL)
++ param_ptr = jack_params_get_parameter(controller_ptr->params, address);
++ if (param_ptr == NULL)
+ {
+- jack_error(
+- "Unknown parameter \"%s\" of driver \"%s\"",
+- option_name,
+- jackctl_driver_get_name(driver));
+- return;
++ jack_error("Unknown parameter");
++ goto ignore;
+ }
+
+- type = jackctl_parameter_get_type(parameter);
++ jack_info("setting parameter '%s':'%s':'%s' to value \"%s\"", address[0], address[1], address[2], option_value);
+
+- switch (type)
++ switch (param_ptr->type)
+ {
+ case JackParamInt:
+- jack_controller_settings_set_sint_option(option_value, &value_int);
+- value.i = value_int;
++ value.i = atoi(option_value);
+ break;
+ case JackParamUInt:
+- jack_controller_settings_set_uint_option(option_value, &value_uint);
+- value.ui = value_uint;
++ value.ui = strtoul(option_value, NULL, 10);
+ break;
+ case JackParamChar:
+- jack_controller_settings_set_char_option(option_value, &value.c);
++ if (option_value[0] == 0 || option_value[1] != 0)
++ {
++ jack_error("invalid char option value \"%s\"", option_value);
++ goto ignore;
++ }
++ value.c = *option_value;
+ break;
+ case JackParamString:
+- jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str));
++ size = strlen(option_value);
++ if (size >= sizeof(value.str))
++ {
++ jack_error("string option value \"%s\" is too long, max is %zu chars (including terminating zero)", option_value, sizeof(value.str));
++ goto ignore;
++ }
++
++ strcpy(value.str, option_value);
+ break;
+ case JackParamBool:
+- jack_controller_settings_set_bool_option(option_value, &value_int);
+- value.i = value_int;
++ if (strcmp(option_value, "true") == 0)
++ {
++ value.b = true;
++ }
++ else if (strcmp(option_value, "false") == 0)
++ {
++ value.b = false;
++ }
++ else
++ {
++ jack_error("ignoring unknown bool value \"%s\"", option_value);
++ goto ignore;
++ }
+ break;
+ default:
+- jack_error("Parameter \"%s\" of driver \"%s\" is of unknown type %d",
+- jackctl_parameter_get_name(parameter),
+- jackctl_driver_get_name(driver),
+- type);
++ jack_error("Unknown type %d", (int)param_ptr->type);
++ goto ignore;
+ }
+
+- jackctl_parameter_set_value(parameter, &value);
+-}
+-
+-void
+-jack_controller_settings_set_internal_option(
+- jackctl_internal_t *internal,
+- const char *option_name,
+- const char *option_value)
+-{
+- jackctl_parameter_t *parameter;
+- jackctl_param_type_t type;
+- int value_int = 0;
+- unsigned int value_uint = 0;
+- union jackctl_parameter_value value;
+-
+- jack_info("setting internal option \"%s\" to value \"%s\"", option_name, option_value);
+-
+- parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), option_name);
+- if (parameter == NULL)
++ if (param_ptr->vtable.set_value(param_ptr->obj, &value))
+ {
+- jack_error(
+- "Unknown parameter \"%s\" of internal \"%s\"",
+- option_name,
+- jackctl_internal_get_name(internal));
+ return;
+ }
+
+- type = jackctl_parameter_get_type(parameter);
+-
+- switch (type)
+- {
+- case JackParamInt:
+- jack_controller_settings_set_sint_option(option_value, &value_int);
+- value.i = value_int;
+- break;
+- case JackParamUInt:
+- jack_controller_settings_set_uint_option(option_value, &value_uint);
+- value.ui = value_uint;
+- break;
+- case JackParamChar:
+- jack_controller_settings_set_char_option(option_value, &value.c);
+- break;
+- case JackParamString:
+- jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str));
+- break;
+- case JackParamBool:
+- jack_controller_settings_set_bool_option(option_value, &value_int);
+- value.i = value_int;
+- break;
+- default:
+- jack_error("Parameter \"%s\" of internal \"%s\" is of unknown type %d",
+- jackctl_parameter_get_name(parameter),
+- jackctl_internal_get_name(internal),
+- type);
+- }
++ jack_error("Parameter set failed");
+
+- jackctl_parameter_set_value(parameter, &value);
++ignore:
++ jack_error("Ignoring restore attempt of parameter '%s':'%s':'%s'", address[0], address[1], address[2]);
+ }
+
+ void
+-jack_controller_settings_set_engine_option(
+- struct jack_controller *controller_ptr,
+- const char *option_name,
+- const char *option_value)
++jack_controller_serialize_parameter_value(
++ const struct jack_parameter * param_ptr,
++ char * value_buffer)
+ {
+- jackctl_parameter_t *parameter;
+- jackctl_param_type_t type;
+- int value_int = 0;
+- unsigned int value_uint = 0;
+ union jackctl_parameter_value value;
+
+- jack_info("setting engine option \"%s\" to value \"%s\"", option_name, option_value);
++ value = param_ptr->vtable.get_value(param_ptr->obj);
+
+- if (strcmp(option_name, "driver") == 0)
+- {
+- if (!jack_controller_select_driver(controller_ptr, option_value))
+- {
+- jack_error("unknown driver '%s'", option_value);
+- }
+-
+- return;
+- }
+-
+- parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), option_name);
+- if (parameter == NULL)
+- {
+- jack_error(
+- "Unknown engine parameter \"%s\"",
+- option_name);
+- return;
+- }
+-
+- type = jackctl_parameter_get_type(parameter);
+-
+- switch (type)
++ switch (param_ptr->type)
+ {
+ case JackParamInt:
+- jack_controller_settings_set_sint_option(option_value, &value_int);
+- value.i = value_int;
+- break;
++ sprintf(value_buffer, "%d", (int)value.i);
++ return;
+ case JackParamUInt:
+- jack_controller_settings_set_uint_option(option_value, &value_uint);
+- value.ui = value_uint;
+- break;
++ sprintf(value_buffer, "%u", (unsigned int)value.ui);
++ return;
+ case JackParamChar:
+- jack_controller_settings_set_char_option(option_value, &value.c);
+- break;
++ sprintf(value_buffer, "%c", (char)value.c);
++ return;
+ case JackParamString:
+- jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str));
+- break;
++ strcpy(value_buffer, value.str);
++ return;
+ case JackParamBool:
+- jack_controller_settings_set_bool_option(option_value, &value_int);
+- value.i = value_int;
+- break;
+- default:
+- jack_error("Engine parameter \"%s\" is of unknown type %d",
+- jackctl_parameter_get_name(parameter),
+- type);
+- }
+-
+- jackctl_parameter_set_value(parameter, &value);
+-}
+-
+-static
+-bool
+-jack_controller_settings_save_options(
+- void *context,
+- const JSList * parameters_list,
+- void *dbus_call_context_ptr)
+-{
+- jackctl_parameter_t *parameter;
+- jackctl_param_type_t type;
+- union jackctl_parameter_value value;
+- const char * name;
+- char value_str[50];
+-
+- while (parameters_list != NULL)
+- {
+- parameter = (jackctl_parameter_t *)parameters_list->data;
+-
+- if (jackctl_parameter_is_set(parameter))
+- {
+- type = jackctl_parameter_get_type(parameter);
+- value = jackctl_parameter_get_value(parameter);
+- name = jackctl_parameter_get_name(parameter);
+-
+- switch (type)
+- {
+- case JackParamInt:
+- sprintf(value_str, "%d", (int)value.i);
+- if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr))
+- {
+- return false;
+- }
+- break;
+- case JackParamUInt:
+- sprintf(value_str, "%u", (unsigned int)value.ui);
+- if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr))
+- {
+- return false;
+- }
+- break;
+- case JackParamChar:
+- sprintf(value_str, "%c", (char)value.c);
+- if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr))
+- {
+- return false;
+- }
+- break;
+- case JackParamString:
+- if (!jack_controller_settings_write_option(context, name, value.str, dbus_call_context_ptr))
+- {
+- return false;
+- }
+- break;
+- case JackParamBool:
+- if (!jack_controller_settings_write_option(context, name, value.b ? "true" : "false", dbus_call_context_ptr))
+- {
+- return false;
+- }
+- break;
+- default:
+- jack_error("parameter of unknown type %d", type);
+- }
+- }
+-
+- parameters_list = jack_slist_next(parameters_list);
+- }
+-
+- return true;
+-}
+-
+-bool
+-jack_controller_settings_save_engine_options(
+- void *context,
+- struct jack_controller *controller_ptr,
+- void *dbus_call_context_ptr)
+-{
+- if (controller_ptr->driver != NULL)
+- {
+- if (!jack_controller_settings_write_option(
+- context,
+- "driver",
+- jackctl_driver_get_name(controller_ptr->driver),
+- dbus_call_context_ptr))
+- {
+- return false;
+- }
++ strcpy(value_buffer, value.b ? "true" : "false");
++ return;
+ }
+
+- return jack_controller_settings_save_options(context, jackctl_server_get_parameters(controller_ptr->server), dbus_call_context_ptr);
+-}
+-
+-bool
+-jack_controller_settings_save_driver_options(
+- void *context,
+- jackctl_driver_t *driver,
+- void *dbus_call_context_ptr)
+-{
+- return jack_controller_settings_save_options(context, jackctl_driver_get_parameters(driver), dbus_call_context_ptr);
+-}
+-
+-bool
+-jack_controller_settings_save_internal_options(
+- void *context,
+- jackctl_internal_t *internal,
+- void *dbus_call_context_ptr)
+-{
+- return jack_controller_settings_save_options(context, jackctl_internal_get_parameters(internal), dbus_call_context_ptr);
++ jack_error("parameter of unknown type %d", (int)param_ptr->type);
++ assert(false);
++ *value_buffer = 0;
+ }
+--- a/dbus/xml_expat.c
++++ b/dbus/xml_expat.c
+@@ -1,6 +1,6 @@
+ /* -*- Mode: C ; c-basic-offset: 4 -*- */
+ /*
+- Copyright (C) 2007,2008 Nedko Arnaudov
++ Copyright (C) 2007,2008,2011 Nedko Arnaudov
+
+ 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
+@@ -29,6 +29,7 @@
+ #include <fcntl.h>
+ #include <errno.h>
+ #include <string.h>
++#include <assert.h>
+ #include <expat.h>
+ #include <dbus/dbus.h>
+
+@@ -46,27 +47,16 @@
+ {
+ }
+
+-#define PARSE_CONTEXT_ROOT 0
+-#define PARSE_CONTEXT_JACK 1
+-#define PARSE_CONTEXT_ENGINE 1
+-#define PARSE_CONTEXT_DRIVERS 2
+-#define PARSE_CONTEXT_DRIVER 3
+-#define PARSE_CONTEXT_OPTION 4
+-#define PARSE_CONTEXT_INTERNALS 5
+-#define PARSE_CONTEXT_INTERNAL 6
+-
+-#define MAX_STACK_DEPTH 10
+-
+ struct parse_context
+ {
+ struct jack_controller *controller_ptr;
+ XML_Bool error;
+- unsigned int element[MAX_STACK_DEPTH];
+- signed int depth;
+- jackctl_driver_t *driver;
+- jackctl_internal_t *internal;
++ bool option_value_capture;
+ char option[JACK_PARAM_STRING_MAX+1];
+ int option_used;
++ const char * address[PARAM_ADDRESS_SIZE];
++ int address_index;
++ char * container;
+ char *name;
+ };
+
+@@ -80,7 +70,7 @@
+ return;
+ }
+
+- if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_OPTION)
++ if (context_ptr->option_value_capture)
+ {
+ if (context_ptr->option_used + len >= JACK_PARAM_STRING_MAX)
+ {
+@@ -97,107 +87,69 @@
+ void
+ jack_controller_settings_callback_elstart(void *data, const char *el, const char **attr)
+ {
+- jackctl_driver_t *driver;
+- jackctl_internal_t *internal;
+-
+ if (context_ptr->error)
+ {
+ return;
+ }
+
+- if (context_ptr->depth + 1 >= MAX_STACK_DEPTH)
++ if (context_ptr->address_index >= PARAM_ADDRESS_SIZE)
+ {
+- jack_error("xml parse max stack depth reached");
++ assert(context_ptr->address_index == PARAM_ADDRESS_SIZE);
++ jack_error("xml param address max depth reached");
+ context_ptr->error = XML_TRUE;
+ return;
+ }
+
++ //jack_info("<%s>", el);
++
+ if (strcmp(el, "jack") == 0)
+ {
+- //jack_info("<jack>");
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK;
+ return;
+ }
+
+- if (strcmp(el, "engine") == 0)
++ if (strcmp(el, PTNODE_ENGINE) == 0)
+ {
+- //jack_info("<engine>");
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_ENGINE;
++ context_ptr->address[context_ptr->address_index++] = PTNODE_ENGINE;
+ return;
+ }
+
+- if (strcmp(el, "drivers") == 0)
++ if (strcmp(el, PTNODE_DRIVERS) == 0)
+ {
+- //jack_info("<drivers>");
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVERS;
++ context_ptr->address[context_ptr->address_index++] = PTNODE_DRIVERS;
+ return;
+ }
+
+- if (strcmp(el, "internals") == 0)
++ if (strcmp(el, PTNODE_INTERNALS) == 0)
+ {
+- //jack_info("<internals>");
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_INTERNALS;
++ context_ptr->address[context_ptr->address_index++] = PTNODE_INTERNALS;
+ return;
+ }
+
+- if (strcmp(el, "driver") == 0)
++ if (strcmp(el, "driver") == 0 ||
++ strcmp(el, "internal") == 0)
+ {
+ if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0)
+ {
+- jack_error("<driver> XML element must contain exactly one attribute, named \"name\"");
++ jack_error("<%s> XML element must contain exactly one attribute, named \"name\"", el);
+ context_ptr->error = XML_TRUE;
+ return;
+ }
+
+- //jack_info("<driver>");
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVER;
+-
+- driver = jack_controller_find_driver(context_ptr->controller_ptr->server, attr[1]);
+- if (driver == NULL)
+- {
+- jack_error("ignoring settings for unknown driver \"%s\"", attr[1]);
+- }
+- else
+- {
+- jack_info("setting for driver \"%s\" found", attr[1]);
+- }
+-
+- context_ptr->driver = driver;
+-
+- return;
+- }
+-
+- if (strcmp(el, "internal") == 0)
+- {
+- if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0)
++ context_ptr->container = strdup(attr[1]);
++ if (context_ptr->container == NULL)
+ {
+- jack_error("<internal> XML element must contain exactly one attribute, named \"name\"");
++ jack_error("strdup() failed");
+ context_ptr->error = XML_TRUE;
+ return;
+ }
+
+- //jack_info("<internal>");
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_INTERNAL;
+-
+- internal = jack_controller_find_internal(context_ptr->controller_ptr->server, attr[1]);
+- if (internal == NULL)
+- {
+- jack_error("ignoring settings for unknown internal \"%s\"", attr[1]);
+- }
+- else
+- {
+- jack_info("setting for internal \"%s\" found", attr[1]);
+- }
+-
+- context_ptr->internal = internal;
++ context_ptr->address[context_ptr->address_index++] = context_ptr->container;
+
+ return;
+ }
+-
+-
++
+ if (strcmp(el, "option") == 0)
+ {
+- //jack_info("<option>");
+ if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0)
+ {
+ jack_error("<option> XML element must contain exactly one attribute, named \"name\"");
+@@ -213,7 +165,8 @@
+ return;
+ }
+
+- context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_OPTION;
++ context_ptr->address[context_ptr->address_index++] = context_ptr->name;
++ context_ptr->option_value_capture = true;
+ context_ptr->option_used = 0;
+ return;
+ }
+@@ -225,49 +178,48 @@
+ void
+ jack_controller_settings_callback_elend(void *data, const char *el)
+ {
++ int i;
++
+ if (context_ptr->error)
+ {
+ return;
+ }
+
+- //jack_info("element end (depth = %d, element = %u)", context_ptr->depth, context_ptr->element[context_ptr->depth]);
++ //jack_info("</%s> (depth = %d)", el, context_ptr->address_index);
+
+- if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_OPTION)
++ if (strcmp(el, "option") == 0)
+ {
++ assert(context_ptr->option_value_capture);
+ context_ptr->option[context_ptr->option_used] = 0;
+
+- if (context_ptr->depth == 2 &&
+- context_ptr->element[0] == PARSE_CONTEXT_JACK &&
+- context_ptr->element[1] == PARSE_CONTEXT_ENGINE)
++ for (i = context_ptr->address_index; i < PARAM_ADDRESS_SIZE; i++)
+ {
+- jack_controller_settings_set_engine_option(context_ptr->controller_ptr, context_ptr->name, context_ptr->option);
++ context_ptr->address[context_ptr->address_index] = NULL;
+ }
+
+- if (context_ptr->depth == 3 &&
+- context_ptr->element[0] == PARSE_CONTEXT_JACK &&
+- context_ptr->element[1] == PARSE_CONTEXT_DRIVERS &&
+- context_ptr->element[2] == PARSE_CONTEXT_DRIVER &&
+- context_ptr->driver != NULL)
+- {
+- jack_controller_settings_set_driver_option(context_ptr->driver, context_ptr->name, context_ptr->option);
+- }
+-
+- if (context_ptr->depth == 3 &&
+- context_ptr->element[0] == PARSE_CONTEXT_JACK &&
+- context_ptr->element[1] == PARSE_CONTEXT_INTERNALS &&
+- context_ptr->element[2] == PARSE_CONTEXT_INTERNAL &&
+- context_ptr->internal != NULL)
+- {
+- jack_controller_settings_set_internal_option(context_ptr->internal, context_ptr->name, context_ptr->option);
+- }
+- }
++ jack_controller_deserialize_parameter_value(context_ptr->controller_ptr, context_ptr->address, context_ptr->option);
+
+- context_ptr->depth--;
+-
+- if (context_ptr->name != NULL)
+- {
+ free(context_ptr->name);
+ context_ptr->name = NULL;
++ context_ptr->option_value_capture = false;
++ context_ptr->address_index--;
++ }
++ else if (context_ptr->container != NULL)
++ {
++ //jack_info("'%s'", context_ptr->container);
++ free(context_ptr->container);
++ context_ptr->container = NULL;
++ context_ptr->address_index--;
++ }
++ else if (strcmp(el, PTNODE_ENGINE) == 0 ||
++ strcmp(el, PTNODE_DRIVERS) == 0 ||
++ strcmp(el, PTNODE_INTERNALS) == 0)
++ {
++ context_ptr->address_index--;
++ }
++ else
++ {
++ //jack_info("no depth decrement");
+ }
+ }
+
+@@ -341,14 +293,20 @@
+
+ context.controller_ptr = controller_ptr;
+ context.error = XML_FALSE;
+- context.depth = -1;
++ context.option_value_capture = false;
++ context.address_index = 0;
+ context.name = NULL;
++ context.container = NULL;
+
+ XML_SetElementHandler(parser, jack_controller_settings_callback_elstart, jack_controller_settings_callback_elend);
+ XML_SetCharacterDataHandler(parser, jack_controller_settings_callback_chrdata);
+ XML_SetUserData(parser, &context);
+
+ xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE);
++
++ free(context.name);
++ free(context.container);
++
+ if (xmls == XML_STATUS_ERROR)
+ {
+ jack_error("XML_ParseBuffer() failed.");
+--- a/dbus/xml_libxml.c
++++ /dev/null
+@@ -1,797 +0,0 @@
+-/* -*- Mode: C ; c-basic-offset: 4 -*- */
+-/*
+- Copyright (C) 2007,2008 Nedko Arnaudov
+-
+- 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.
+-
+- This program is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- GNU General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-
+-*/
+-
+-#if defined(HAVE_CONFIG_H)
+-#include "config.h"
+-#endif
+-
+-#include <stdbool.h>
+-#include <string.h>
+-#include <dbus/dbus.h>
+-
+-#include <libxml/xmlwriter.h>
+-#include <libxml/parser.h>
+-#include <libxml/xpath.h>
+-
+-#include <jack/driver.h>
+-#include <jack/engine.h>
+-#include "controller_internal.h"
+-#include "dbus.h"
+-
+-/* XPath expression used for engine options selection */
+-#define XPATH_ENGINE_OPTIONS_EXPRESSION "/jack/engine/option"
+-
+-/* XPath expression used for drivers selection */
+-#define XPATH_DRIVERS_EXPRESSION "/jack/drivers/driver"
+-
+-/* XPath expression used for driver options selection */
+-#define XPATH_DRIVER_OPTIONS_EXPRESSION "/jack/drivers/driver[@name = '%s']/option"
+-
+-bool
+-jack_controller_settings_init()
+-{
+- /*
+- * this initialize the library and check potential ABI mismatches
+- * between the version it was compiled for and the actual shared
+- * library used.
+- */
+- LIBXML_TEST_VERSION;
+-
+- return true;
+-}
+-
+-void
+-jack_controller_settings_uninit()
+-{
+-}
+-
+-#define writer ((xmlTextWriterPtr)context)
+-
+-bool
+-jack_controller_settings_write_option(
+- void *context,
+- const char *name,
+- const char *content,
+- void *dbus_call_context_ptr)
+-{
+- if (xmlTextWriterStartElement(writer, BAD_CAST "option") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- return false;
+- }
+-
+- if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST name) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteAttribute() failed.");
+- return false;
+- }
+-
+- if (xmlTextWriterWriteString(writer, BAD_CAST content) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteString() failed.");
+- return false;
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed.");
+- return false;
+- }
+-
+- return true;
+-}
+-
+-#undef writer
+-
+-bool
+-jack_controller_settings_write_engine(
+- struct jack_controller * controller_ptr,
+- xmlTextWriterPtr writer,
+- void *dbus_call_context_ptr)
+-{
+-/* jack_info("engine settings begin"); */
+-
+-/* if (xmlTextWriterWriteComment(writer, BAD_CAST "engine parameters") == -1) */
+-/* { */
+-/* jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); */
+-/* return false; */
+-/* } */
+-
+- if (xmlTextWriterStartElement(writer, BAD_CAST "engine") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- return false;
+- }
+-
+- if (!jack_controller_settings_save_engine_options(writer, controller_ptr, dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed.");
+- return false;
+- }
+-
+-/* jack_info("engine settings end"); */
+- return true;
+-}
+-
+-bool
+-jack_controller_settings_write_driver(
+- struct jack_controller * controller_ptr,
+- xmlTextWriterPtr writer,
+- jackctl_driver driver,
+- void *dbus_call_context_ptr)
+-{
+-/* if (xmlTextWriterWriteComment(writer, BAD_CAST "driver parameters") == -1) */
+-/* { */
+-/* jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); */
+-/* return false; */
+-/* } */
+-
+- if (xmlTextWriterStartElement(writer, BAD_CAST "driver") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- return false;
+- }
+-
+- if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST jackctl_driver_get_name(driver)) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteAttribute() failed.");
+- return false;
+- }
+-
+- if (!jack_controller_settings_save_driver_options(writer, driver, dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed.");
+- return false;
+- }
+-
+- return true;
+-}
+-
+-bool
+-jack_controller_settings_write_drivers(
+- struct jack_controller * controller_ptr,
+- xmlTextWriterPtr writer,
+- void *dbus_call_context_ptr)
+-{
+- const JSList * node_ptr;
+- jackctl_driver driver;
+-
+- if (xmlTextWriterStartElement(writer, BAD_CAST "drivers") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- return false;
+- }
+-
+- node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
+-
+- while (node_ptr != NULL)
+- {
+- driver = (jackctl_driver)node_ptr->data;
+-
+- if (!jack_controller_settings_write_driver(
+- controller_ptr,
+- writer,
+- driver,
+- dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- node_ptr = jack_slist_next(node_ptr);
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed.");
+- return false;
+- }
+-
+- return true;
+-}
+-
+-bool
+-jack_controller_settings_write_internal(
+- struct jack_controller * controller_ptr,
+- xmlTextWriterPtr writer,
+- jackctl_internal internal,
+- void *dbus_call_context_ptr)
+-{
+-/* if (xmlTextWriterWriteComment(writer, BAD_CAST "driver parameters") == -1) */
+-/* { */
+-/* jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); */
+-/* return false; */
+-/* } */
+-
+- if (xmlTextWriterStartElement(writer, BAD_CAST "internal") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- return false;
+- }
+-
+- if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST jackctl_internal_get_name(driver)) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteAttribute() failed.");
+- return false;
+- }
+-
+- if (!jack_controller_settings_save_internal_options(writer, internal, dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed.");
+- return false;
+- }
+-
+- return true;
+-}
+-
+-bool
+-jack_controller_settings_write_internals(
+- struct jack_controller * controller_ptr,
+- xmlTextWriterPtr writer,
+- void *dbus_call_context_ptr)
+-{
+- const JSList * node_ptr;
+- jackctl_driver internal;
+-
+- if (xmlTextWriterStartElement(writer, BAD_CAST "internals") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- return false;
+- }
+-
+- node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
+-
+- while (node_ptr != NULL)
+- {
+- internal = (jackctl_internal)node_ptr->data;
+-
+- if (!jack_controller_settings_write_internal(
+- controller_ptr,
+- writer,
+- internal,
+- dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- node_ptr = jack_slist_next(node_ptr);
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed.");
+- return false;
+- }
+-
+- return true;
+-}
+-
+-bool
+-jack_controller_settings_save(
+- struct jack_controller * controller_ptr,
+- void *dbus_call_context_ptr)
+-{
+- xmlTextWriterPtr writer;
+- char *filename;
+- size_t conf_len;
+- bool ret;
+- time_t timestamp;
+- char timestamp_str[28];
+-
+- time(×tamp);
+- timestamp_str[0] = ' ';
+- ctime_r(×tamp, timestamp_str + 1);
+- timestamp_str[25] = ' ';
+-
+- ret = false;
+-
+- conf_len = strlen(JACKDBUS_CONF);
+-
+- filename = malloc(g_jackdbus_dir_len + conf_len + 1);
+- if (filename == NULL)
+- {
+- jack_error("Out of memory.");
+- goto fail;
+- }
+-
+- memcpy(filename, g_jackdbus_dir, g_jackdbus_dir_len);
+- memcpy(filename + g_jackdbus_dir_len, JACKDBUS_CONF, conf_len);
+- filename[g_jackdbus_dir_len + conf_len] = 0;
+-
+- jack_info("saving settings to \"%s\"", filename);
+-
+- writer = xmlNewTextWriterFilename(filename, 0);
+- if (writer == NULL)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Error creating the xml writer.");
+- goto fail_free_filename;
+- }
+-
+- if (xmlTextWriterSetIndent(writer, 1) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterSetIndent() failed.");
+- goto fail_free_writter;
+- }
+-
+- if (xmlTextWriterStartDocument(writer, NULL, NULL, NULL) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartDocument() failed.");
+- goto fail_free_writter;
+- }
+-
+- if (xmlTextWriterWriteComment(writer, BAD_CAST "\n" JACK_CONF_HEADER_TEXT) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed.");
+- goto fail_free_writter;
+- }
+-
+- if (xmlTextWriterWriteComment(writer, BAD_CAST timestamp_str) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed.");
+- goto fail_free_writter;
+- }
+-
+- if (xmlTextWriterStartElement(writer, BAD_CAST "jack") == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- goto fail_free_writter;
+- }
+-
+- if (!jack_controller_settings_write_engine(controller_ptr, writer, dbus_call_context_ptr))
+- {
+- goto fail_free_writter;
+- }
+-
+- if (!jack_controller_settings_write_drivers(controller_ptr, writer, dbus_call_context_ptr))
+- {
+- goto fail_free_writter;
+- }
+-
+- if (!jack_controller_settings_write_internals(controller_ptr, writer, dbus_call_context_ptr))
+- {
+- goto fail_free_writter;
+- }
+-
+- if (xmlTextWriterEndElement(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed.");
+- goto fail_free_writter;
+- }
+-
+- if (xmlTextWriterEndDocument(writer) == -1)
+- {
+- jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndDocument() failed.");
+- goto fail_free_writter;
+- }
+-
+- ret = true;
+-
+-fail_free_writter:
+- xmlFreeTextWriter(writer);
+-
+-fail_free_filename:
+- free(filename);
+-
+-fail:
+- return ret;
+-}
+-
+-void
+-jack_controller_settings_read_engine(
+- struct jack_controller * controller_ptr,
+- xmlXPathContextPtr xpath_ctx_ptr)
+-{
+- xmlXPathObjectPtr xpath_obj_ptr;
+- xmlBufferPtr content_buffer_ptr;
+- int i;
+- const char *option_name;
+- const char *option_value;
+-
+- /* Evaluate xpath expression */
+- xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_ENGINE_OPTIONS_EXPRESSION, xpath_ctx_ptr);
+- if (xpath_obj_ptr == NULL)
+- {
+- jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_ENGINE_OPTIONS_EXPRESSION);
+- goto exit;
+- }
+-
+- if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
+- {
+- jack_error("XPath \"%s\" evaluation returned no data", XPATH_ENGINE_OPTIONS_EXPRESSION);
+- goto free_xpath_obj;
+- }
+-
+- content_buffer_ptr = xmlBufferCreate();
+- if (content_buffer_ptr == NULL)
+- {
+- jack_error("xmlBufferCreate() failed.");
+- goto free_xpath_obj;
+- }
+-
+- for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
+- {
+- //jack_info("engine option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i);
+-
+- if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1)
+- {
+- jack_error("xmlNodeBufGetContent() failed.");
+- goto next_option;
+- }
+-
+- option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
+- option_value = (const char *)xmlBufferContent(content_buffer_ptr);
+-
+- jack_controller_settings_set_engine_option(controller_ptr, option_name, option_value);
+-
+- next_option:
+- xmlBufferEmpty(content_buffer_ptr);
+- }
+-
+-//free_buffer:
+- xmlBufferFree(content_buffer_ptr);
+-
+-free_xpath_obj:
+- xmlXPathFreeObject(xpath_obj_ptr);
+-
+-exit:
+- return;
+-}
+-
+-void
+-jack_controller_settings_read_driver(
+- struct jack_controller * controller_ptr,
+- xmlXPathContextPtr xpath_ctx_ptr,
+- jackctl_driver driver)
+-{
+- char *xpath;
+- size_t xpath_len;
+- xmlXPathObjectPtr xpath_obj_ptr;
+- xmlBufferPtr content_buffer_ptr;
+- int i;
+- const char *option_name;
+- const char *option_value;
+- const char *driver_name;
+-
+- driver_name = jackctl_driver_get_name(driver);
+-
+- jack_info("reading options for driver \"%s\"", driver_name);
+-
+- xpath_len = snprintf(NULL, 0, XPATH_DRIVER_OPTIONS_EXPRESSION, driver_name);
+-
+- xpath = malloc(xpath_len);
+- if (xpath == NULL)
+- {
+- jack_error("Out of memory.");
+- goto exit;
+- }
+-
+- snprintf(xpath, xpath_len, XPATH_DRIVER_OPTIONS_EXPRESSION, driver_name);
+-
+- //jack_info("xpath = \"%s\"", xpath);
+-
+- /* Evaluate xpath expression */
+- xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)xpath, xpath_ctx_ptr);
+- if (xpath_obj_ptr == NULL)
+- {
+- jack_error("Unable to evaluate XPath expression \"%s\"", xpath);
+- goto free_xpath;
+- }
+-
+- if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
+- {
+- //jack_info("XPath \"%s\" evaluation returned no data", xpath);
+- goto free_xpath_obj;
+- }
+-
+- content_buffer_ptr = xmlBufferCreate();
+- if (content_buffer_ptr == NULL)
+- {
+- jack_error("xmlBufferCreate() failed.");
+- goto free_xpath_obj;
+- }
+-
+- for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
+- {
+- //jack_info("driver option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i);
+-
+- if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1)
+- {
+- jack_error("xmlNodeBufGetContent() failed.");
+- goto next_option;
+- }
+-
+- option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
+- option_value = (const char *)xmlBufferContent(content_buffer_ptr);
+-
+- jack_controller_settings_set_driver_option(driver, option_name, option_value);
+-
+- next_option:
+- xmlBufferEmpty(content_buffer_ptr);
+- }
+-
+-//free_buffer:
+- xmlBufferFree(content_buffer_ptr);
+-
+-free_xpath_obj:
+- xmlXPathFreeObject(xpath_obj_ptr);
+-
+-free_xpath:
+- free(xpath);
+-
+-exit:
+- return;
+-}
+-
+-void
+-jack_controller_settings_read_internal(
+- struct jack_controller * controller_ptr,
+- xmlXPathContextPtr xpath_ctx_ptr,
+- jackctl_internal internal)
+-{
+- char *xpath;
+- size_t xpath_len;
+- xmlXPathObjectPtr xpath_obj_ptr;
+- xmlBufferPtr content_buffer_ptr;
+- int i;
+- const char *option_name;
+- const char *option_value;
+- const char *internal_name;
+-
+- internal_name = jackctl_internal_get_name(internal);
+-
+- jack_info("reading options for internal \"%s\"", internal_name);
+-
+- xpath_len = snprintf(NULL, 0, XPATH_DRIVER_OPTIONS_EXPRESSION, internal_name);
+-
+- xpath = malloc(xpath_len);
+- if (xpath == NULL)
+- {
+- jack_error("Out of memory.");
+- goto exit;
+- }
+-
+- snprintf(xpath, xpath_len, XPATH_DRIVER_OPTIONS_EXPRESSION, internal_name);
+-
+- //jack_info("xpath = \"%s\"", xpath);
+-
+- /* Evaluate xpath expression */
+- xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)xpath, xpath_ctx_ptr);
+- if (xpath_obj_ptr == NULL)
+- {
+- jack_error("Unable to evaluate XPath expression \"%s\"", xpath);
+- goto free_xpath;
+- }
+-
+- if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
+- {
+- //jack_info("XPath \"%s\" evaluation returned no data", xpath);
+- goto free_xpath_obj;
+- }
+-
+- content_buffer_ptr = xmlBufferCreate();
+- if (content_buffer_ptr == NULL)
+- {
+- jack_error("xmlBufferCreate() failed.");
+- goto free_xpath_obj;
+- }
+-
+- for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
+- {
+- //jack_info("driver option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i);
+-
+- if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1)
+- {
+- jack_error("xmlNodeBufGetContent() failed.");
+- goto next_option;
+- }
+-
+- option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
+- option_value = (const char *)xmlBufferContent(content_buffer_ptr);
+-
+- jack_controller_settings_set_internal_option(internal, option_name, option_value);
+-
+- next_option:
+- xmlBufferEmpty(content_buffer_ptr);
+- }
+-
+-//free_buffer:
+- xmlBufferFree(content_buffer_ptr);
+-
+-free_xpath_obj:
+- xmlXPathFreeObject(xpath_obj_ptr);
+-
+-free_xpath:
+- free(xpath);
+-
+-exit:
+- return;
+-}
+-
+-void
+-jack_controller_settings_read_drivers(
+- struct jack_controller * controller_ptr,
+- xmlXPathContextPtr xpath_ctx_ptr)
+-{
+- xmlXPathObjectPtr xpath_obj_ptr;
+- int i;
+- const char *driver_name;
+- jackctl_driver driver;
+-
+- /* Evaluate xpath expression */
+- xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_DRIVERS_EXPRESSION, xpath_ctx_ptr);
+- if (xpath_obj_ptr == NULL)
+- {
+- jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_DRIVERS_EXPRESSION);
+- goto exit;
+- }
+-
+- if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
+- {
+- jack_error("XPath \"%s\" evaluation returned no data", XPATH_DRIVERS_EXPRESSION);
+- goto free_xpath_obj;
+- }
+-
+- for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
+- {
+- driver_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
+-
+- driver = jack_controller_find_driver(controller_ptr->server, driver_name);
+- if (driver == NULL)
+- {
+- jack_error("ignoring settings for unknown driver \"%s\"", driver_name);
+- }
+- else
+- {
+- jack_info("setting for driver \"%s\" found", driver_name);
+-
+- jack_controller_settings_read_driver(controller_ptr, xpath_ctx_ptr, driver);
+- }
+- }
+-
+-free_xpath_obj:
+- xmlXPathFreeObject(xpath_obj_ptr);
+-
+-exit:
+- return;
+-}
+-
+-void
+-jack_controller_settings_read_internals(
+- struct jack_controller * controller_ptr,
+- xmlXPathContextPtr xpath_ctx_ptr)
+-{
+- xmlXPathObjectPtr xpath_obj_ptr;
+- int i;
+- const char *internal_name;
+- jackctl_internal internal;
+-
+- /* Evaluate xpath expression */
+- xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_DRIVERS_EXPRESSION, xpath_ctx_ptr);
+- if (xpath_obj_ptr == NULL)
+- {
+- jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_DRIVERS_EXPRESSION);
+- goto exit;
+- }
+-
+- if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0)
+- {
+- jack_error("XPath \"%s\" evaluation returned no data", XPATH_DRIVERS_EXPRESSION);
+- goto free_xpath_obj;
+- }
+-
+- for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++)
+- {
+- internal_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name");
+-
+- driver = jack_controller_find_internal(controller_ptr->server, driver_name);
+- if (driver == NULL)
+- {
+- jack_error("ignoring settings for unknown internal \"%s\"", internal_name);
+- }
+- else
+- {
+- jack_info("setting for internal \"%s\" found", internal_name);
+-
+- jack_controller_settings_read_internal(controller_ptr, xpath_ctx_ptr, driver);
+- }
+- }
+-
+-free_xpath_obj:
+- xmlXPathFreeObject(xpath_obj_ptr);
+-
+-exit:
+- return;
+-}
+-
+-
+-void
+-jack_controller_settings_load(
+- struct jack_controller * controller_ptr)
+-{
+- char *filename;
+- size_t conf_len;
+- xmlDocPtr doc_ptr;
+- xmlXPathContextPtr xpath_ctx_ptr;
+-
+- conf_len = strlen(JACKDBUS_CONF);
+-
+- filename = malloc(g_jackdbus_dir_len + conf_len + 1);
+- if (filename == NULL)
+- {
+- jack_error("Out of memory.");
+- goto exit;
+- }
+-
+- memcpy(filename, g_jackdbus_dir, g_jackdbus_dir_len);
+- memcpy(filename + g_jackdbus_dir_len, JACKDBUS_CONF, conf_len);
+- filename[g_jackdbus_dir_len + conf_len] = 0;
+-
+- jack_info("loading settings from \"%s\"", filename);
+-
+- doc_ptr = xmlParseFile(filename);
+- if (doc_ptr == NULL)
+- {
+- jack_error("Failed to parse \"%s\"", filename);
+- goto free_filename;
+- }
+-
+- /* Create xpath evaluation context */
+- xpath_ctx_ptr = xmlXPathNewContext(doc_ptr);
+- if (xpath_ctx_ptr == NULL)
+- {
+- jack_error("Unable to create new XPath context");
+- goto free_doc;
+- }
+-
+- jack_controller_settings_read_engine(controller_ptr, xpath_ctx_ptr);
+- jack_controller_settings_read_drivers(controller_ptr, xpath_ctx_ptr);
+- jack_controller_settings_read_internals(controller_ptr, xpath_ctx_ptr);
+-
+- xmlXPathFreeContext(xpath_ctx_ptr);
+-
+-free_doc:
+- xmlFreeDoc(doc_ptr);
+-
+-free_filename:
+- free(filename);
+-
+-exit:
+- return;
+-}
+-
+-void
+-jack_controller_settings_save_auto(
+- struct jack_controller * controller_ptr)
+-{
+- jack_controller_settings_save(controller_ptr, NULL);
+-}
+--- a/dbus/xml_write_raw.c
++++ b/dbus/xml_write_raw.c
+@@ -53,54 +53,57 @@
+
+ struct save_context
+ {
++ void * call;
+ int fd;
+- const char *indent;
++ const char * indent;
++ jack_params_handle params;
++ const char * address[PARAM_ADDRESS_SIZE];
++ const char * str;
+ };
+
+-#define save_context_ptr ((struct save_context *)context)
+-#define fd (save_context_ptr->fd)
++#define ctx_ptr ((struct save_context *)context)
++#define fd (ctx_ptr->fd)
+
+-bool
+-jack_controller_settings_write_option(
+- void *context,
+- const char *name,
+- const char *content,
+- void *dbus_call_context_ptr)
++static bool jack_controller_serialize_parameter(void * context, const struct jack_parameter * param_ptr)
+ {
+- if (!jack_controller_settings_write_string(fd, save_context_ptr->indent, dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- if (!jack_controller_settings_write_string(fd, "<option name=\"", dbus_call_context_ptr))
+- {
+- return false;
+- }
++ char value[JACK_PARAM_STRING_MAX + 1];
+
+- if (!jack_controller_settings_write_string(fd, name, dbus_call_context_ptr))
++ if (!param_ptr->vtable.is_set(param_ptr->obj))
+ {
+- return false;
++ return true;
+ }
+
+- if (!jack_controller_settings_write_string(fd, "\">", dbus_call_context_ptr))
+- {
+- return false;
+- }
++ jack_controller_serialize_parameter_value(param_ptr, value);
+
+- if (!jack_controller_settings_write_string(fd, content, dbus_call_context_ptr))
+- {
+- return false;
+- }
+-
+- if (!jack_controller_settings_write_string(fd, "</option>\n", dbus_call_context_ptr))
+- {
+- return false;
+- }
++ return
++ jack_controller_settings_write_string(fd, ctx_ptr->indent, ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, "<option name=\"", ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, param_ptr->name, ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, "\">", ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, value, ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, "</option>\n", ctx_ptr->call);
++}
+
+- return true;
++bool serialize_modules(void * context, const char * name)
++{
++ ctx_ptr->indent = " ";
++ ctx_ptr->address[1] = name;
++ ctx_ptr->address[2] = NULL;
++
++ return
++ jack_controller_settings_write_string(fd, " <", ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, ctx_ptr->str, ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, " name=\"", ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, name, ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, "\">\n", ctx_ptr->call) &&
++ jack_params_iterate_params(ctx_ptr->params, ctx_ptr->address, jack_controller_serialize_parameter, ctx_ptr) &&
++ jack_controller_settings_write_string(fd, " </", ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, ctx_ptr->str, ctx_ptr->call) &&
++ jack_controller_settings_write_string(fd, ">\n", ctx_ptr->call);
+ }
+
+ #undef fd
++#undef ctx_ptr
+
+ bool
+ jack_controller_settings_save(
+@@ -114,9 +117,9 @@
+ time_t timestamp;
+ char timestamp_str[26];
+ struct save_context context;
+- const JSList * node_ptr;
+- jackctl_driver_t *driver;
+- jackctl_internal_t *internal;
++ const char * modules[] = {"driver", "internal", NULL};
++ char buffer[100];
++ unsigned int i;
+
+ time(×tamp);
+ ctime_r(×tamp, timestamp_str);
+@@ -147,6 +150,7 @@
+ }
+
+ context.fd = fd;
++ context.call = dbus_call_context_ptr;
+
+ if (!jack_controller_settings_write_string(fd, "<?xml version=\"1.0\"?>\n", dbus_call_context_ptr))
+ {
+@@ -196,7 +200,9 @@
+ }
+
+ context.indent = " ";
+- if (!jack_controller_settings_save_engine_options(&context, controller_ptr, dbus_call_context_ptr))
++ context.address[0] = PTNODE_ENGINE;
++ context.address[1] = NULL;
++ if (!jack_params_iterate_params(controller_ptr->params, context.address, jack_controller_serialize_parameter, &context))
+ {
+ goto exit_close;
+ }
+@@ -206,100 +212,50 @@
+ goto exit_close;
+ }
+
+- /* drivers */
+-
+- if (!jack_controller_settings_write_string(fd, " <drivers>\n", dbus_call_context_ptr))
+- {
+- goto exit_close;
+- }
+-
+- node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
+-
+- while (node_ptr != NULL)
++ for (i = 0; modules[i] != NULL; i++)
+ {
+- driver = (jackctl_driver_t *)node_ptr->data;
+-
+- if (!jack_controller_settings_write_string(fd, " <driver name=\"", dbus_call_context_ptr))
++ if (!jack_controller_settings_write_string(fd, " <", dbus_call_context_ptr))
+ {
+ goto exit_close;
+ }
+
+- if (!jack_controller_settings_write_string(fd, jackctl_driver_get_name(driver), dbus_call_context_ptr))
++ if (!jack_controller_settings_write_string(fd, modules[i], dbus_call_context_ptr))
+ {
+ goto exit_close;
+ }
+
+- if (!jack_controller_settings_write_string(fd, "\">\n", dbus_call_context_ptr))
++ if (!jack_controller_settings_write_string(fd, "s>\n", dbus_call_context_ptr))
+ {
+ goto exit_close;
+ }
+
+- context.indent = " ";
++ context.indent = " ";
++ context.params = controller_ptr->params;
++ context.str = modules[i];
++ strcpy(buffer, modules[i]);
++ strcat(buffer, "s");
++ context.address[0] = buffer;
++ context.address[1] = NULL;
+
+- if (!jack_controller_settings_save_driver_options(&context, driver, dbus_call_context_ptr))
++ if (!jack_params_iterate_container(controller_ptr->params, context.address, serialize_modules, &context))
+ {
+ goto exit_close;
+ }
+
+- if (!jack_controller_settings_write_string(fd, " </driver>\n", dbus_call_context_ptr))
++ if (!jack_controller_settings_write_string(fd, " </", dbus_call_context_ptr))
+ {
+ goto exit_close;
+ }
+
+- node_ptr = jack_slist_next(node_ptr);
+- }
+-
+- if (!jack_controller_settings_write_string(fd, " </drivers>\n", dbus_call_context_ptr))
+- {
+- goto exit_close;
+- }
+-
+- /* internals */
+-
+- if (!jack_controller_settings_write_string(fd, " <internals>\n", dbus_call_context_ptr))
+- {
+- goto exit_close;
+- }
+-
+- node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
+-
+- while (node_ptr != NULL)
+- {
+- internal = (jackctl_internal_t *)node_ptr->data;
+-
+- if (!jack_controller_settings_write_string(fd, " <internal name=\"", dbus_call_context_ptr))
++ if (!jack_controller_settings_write_string(fd, modules[i], dbus_call_context_ptr))
+ {
+ goto exit_close;
+ }
+
+- if (!jack_controller_settings_write_string(fd, jackctl_internal_get_name(internal), dbus_call_context_ptr))
++ if (!jack_controller_settings_write_string(fd, "s>\n", dbus_call_context_ptr))
+ {
+ goto exit_close;
+ }
+-
+- if (!jack_controller_settings_write_string(fd, "\">\n", dbus_call_context_ptr))
+- {
+- goto exit_close;
+- }
+-
+- context.indent = " ";
+-
+- if (!jack_controller_settings_save_internal_options(&context, internal, dbus_call_context_ptr))
+- {
+- goto exit_close;
+- }
+-
+- if (!jack_controller_settings_write_string(fd, " </internal>\n", dbus_call_context_ptr))
+- {
+- goto exit_close;
+- }
+-
+- node_ptr = jack_slist_next(node_ptr);
+- }
+-
+- if (!jack_controller_settings_write_string(fd, " </internals>\n", dbus_call_context_ptr))
+- {
+- goto exit_close;
+ }
+
+ if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))
+--- a/doxyfile
++++ b/doxyfile
+@@ -31,7 +31,7 @@
+ # This could be handy for archiving the generated documentation or
+ # if some version control system is used.
+
+-PROJECT_NUMBER = 1.9.7
++PROJECT_NUMBER = 1.9.8
+
+ # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+ # base path where the generated documentation will be put.
+--- a/example-clients/alias.c
++++ b/example-clients/alias.c
+@@ -55,7 +55,7 @@
+ int option_index;
+ extern int optind;
+ jack_port_t* port;
+-
++
+ struct option long_options[] = {
+ { "unalias", 0, 0, 'u' },
+ { "help", 0, 0, 'h' },
+@@ -129,5 +129,5 @@
+ jack_client_close (client);
+
+ return ret;
+-
++
+ }
+--- a/example-clients/bufsize.c
++++ b/example-clients/bufsize.c
+@@ -71,13 +71,13 @@
+
+ nframes = strtoul(argv[1], NULL, 0);
+ if (errno == ERANGE) {
+- fprintf(stderr, "%s: invalid buffer size: %s (range is 1-8182)\n",
++ fprintf(stderr, "%s: invalid buffer size: %s (range is 1-8192)\n",
+ package, argv[1]);
+ exit(2);
+ }
+
+ if (nframes < 1 || nframes > 8182) {
+- fprintf(stderr, "%s: invalid buffer size: %s (range is 1-8182)\n",
++ fprintf(stderr, "%s: invalid buffer size: %s (range is 1-8192)\n",
+ package, argv[1]);
+ exit(3);
+ }
+@@ -103,7 +103,7 @@
+ jack_on_shutdown(client, jack_shutdown, 0);
+
+ if (just_print_bufsize) {
+- fprintf(stdout, "%d\n", jack_get_buffer_size( client ) );
++ fprintf(stdout, "buffer size = %d sample rate = %d\n", jack_get_buffer_size(client), jack_get_sample_rate(client));
+ rc=0;
+ }
+ else
+--- a/example-clients/capture_client.c
++++ b/example-clients/capture_client.c
+@@ -1,7 +1,7 @@
+ /*
+ Copyright (C) 2001 Paul Davis
+ 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
+@@ -100,7 +100,7 @@
+ info->status = EIO; /* write failed */
+ goto done;
+ }
+-
++
+ if (++total_captured >= info->duration) {
+ printf ("disk thread finished\n");
+ goto done;
+@@ -116,7 +116,7 @@
+ free (framebuf);
+ return 0;
+ }
+-
++
+ static int
+ process (jack_nframes_t nframes, void *arg)
+ {
+@@ -158,9 +158,8 @@
+ static void
+ jack_shutdown (void *arg)
+ {
+- fprintf (stderr, "JACK shutdown\n");
+- // exit (0);
+- abort();
++ fprintf(stderr, "JACK shut down, exiting ...\n");
++ exit(1);
+ }
+
+ static void
+@@ -168,10 +167,10 @@
+ {
+ SF_INFO sf_info;
+ int short_mask;
+-
++
+ sf_info.samplerate = jack_get_sample_rate (info->client);
+ sf_info.channels = info->channels;
+-
++
+ switch (info->bitdepth) {
+ case 8: short_mask = SF_FORMAT_PCM_U8;
+ break;
+@@ -183,7 +182,7 @@
+ break;
+ default: short_mask = SF_FORMAT_PCM_16;
+ break;
+- }
++ }
+ sf_info.format = SF_FORMAT_WAV|short_mask;
+
+ if ((info->sf = sf_open (info->path, SFM_WRITE, &sf_info)) == NULL) {
+@@ -253,7 +252,7 @@
+ fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]);
+ jack_client_close (info->client);
+ exit (1);
+- }
++ }
+ }
+
+ info->can_process = 1; /* process() can start, now */
+@@ -315,7 +314,7 @@
+ }
+
+ if ((client = jack_client_open ("jackrec", JackNullOption, NULL)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ exit (1);
+ }
+
+@@ -333,7 +332,7 @@
+ }
+
+ setup_ports (argc - optind, &argv[optind], &thread_info);
+-
++
+ /* install a signal handler to properly quits jack client */
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+--- a/example-clients/connect.c
++++ b/example-clients/connect.c
+@@ -133,7 +133,7 @@
+ /* try to become a client of the JACK server */
+
+ if ((client = jack_client_open (my_name, options, &status, server_name)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ return 1;
+ }
+
+--- a/example-clients/cpu_load.c
++++ b/example-clients/cpu_load.c
+@@ -16,11 +16,11 @@
+
+ jack_client_t *client;
+
+-static void signal_handler ( int sig )
++static void signal_handler(int sig)
+ {
+- jack_client_close ( client );
+- fprintf ( stderr, "signal received, exiting ...\n" );
+- exit ( 0 );
++ jack_client_close(client);
++ fprintf(stderr, "signal received, exiting ...\n");
++ exit(0);
+ }
+
+
+@@ -29,13 +29,13 @@
+ * decides to disconnect the client.
+ */
+ void
+-jack_shutdown ( void *arg )
++jack_shutdown(void *arg)
+ {
+- exit ( 1 );
++ exit(1);
+ }
+
+ int
+-main ( int argc, char *argv[] )
++main(int argc, char *argv[])
+ {
+ jack_options_t options = JackNullOption;
+ jack_status_t status;
+@@ -43,50 +43,46 @@
+ /* open a client connection to the JACK server */
+
+ client = jack_client_open ("jack_cpu_load", options, &status);
+- if ( client == NULL )
+- {
+- fprintf ( stderr, "jack_client_open() failed, "
+- "status = 0x%2.0x\n", status );
+- if ( status & JackServerFailed )
+- {
+- fprintf ( stderr, "Unable to connect to JACK server\n" );
++ if (client == NULL) {
++ fprintf(stderr, "jack_client_open() failed, "
++ "status = 0x%2.0x\n", status);
++ if (status & JackServerFailed) {
++ fprintf(stderr, "Unable to connect to JACK server\n");
+ }
+- exit ( 1 );
++ exit(1);
+ }
+-
+- jack_on_shutdown ( client, jack_shutdown, 0 );
++
++ jack_on_shutdown(client, jack_shutdown, 0);
+
+ /* Tell the JACK server that we are ready to roll. Our
+ * process() callback will start running now. */
+
+- if ( jack_activate ( client ) )
+- {
+- fprintf ( stderr, "cannot activate client" );
+- exit ( 1 );
++ if (jack_activate(client)) {
++ fprintf(stderr, "cannot activate client");
++ exit(1);
+ }
+
+ /* install a signal handler to properly quits jack client */
+ #ifdef WIN32
+- signal ( SIGINT, signal_handler );
+- signal ( SIGABRT, signal_handler );
+- signal ( SIGTERM, signal_handler );
++ signal(SIGINT, signal_handler);
++ signal(SIGABRT, signal_handler);
++ signal(SIGTERM, signal_handler);
+ #else
+- signal ( SIGQUIT, signal_handler );
+- signal ( SIGTERM, signal_handler );
+- signal ( SIGHUP, signal_handler );
+- signal ( SIGINT, signal_handler );
++ signal(SIGQUIT, signal_handler);
++ signal(SIGTERM, signal_handler);
++ signal(SIGHUP, signal_handler);
++ signal(SIGINT, signal_handler);
+ #endif
+
+- while (1)
+- {
++ while (1) {
+ printf("jack DSP load %f\n", jack_cpu_load(client));
+ #ifdef WIN32
+- Sleep ( 1000 );
++ Sleep(1000);
+ #else
+- sleep ( 1 );
++ sleep(1);
+ #endif
+ }
+
+- jack_client_close ( client );
+- exit ( 0 );
++ jack_client_close(client);
++ exit(0 );
+ }
+--- a/example-clients/freewheel.c
++++ b/example-clients/freewheel.c
+@@ -2,7 +2,7 @@
+ * freewheel - start/stop JACK "freewheeling" mode
+ *
+ * Copyright (C) 2003 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
+@@ -58,7 +58,7 @@
+ }
+ }
+
+-int
++int
+ main (int argc, char *argv[])
+ {
+ parse_arguments (argc, argv);
+--- a/example-clients/impulse_grabber.c
++++ b/example-clients/impulse_grabber.c
+@@ -36,7 +36,7 @@
+ unsigned long response_pos;
+ int grab_finished = 0;
+ jack_client_t *client;
+-
++
+ static void signal_handler(int sig)
+ {
+ jack_client_close(client);
+@@ -60,7 +60,7 @@
+ }
+ if (response_pos >= response_duration) {
+ grab_finished = 1;
+- }
++ }
+ for (i=0; i<nframes; i++) {
+ out[i] = 0.0f;;
+ }
+@@ -72,12 +72,13 @@
+ impulse_sent = 1;
+ }
+
+- return 0;
++ return 0;
+ }
+
+ static void
+ jack_shutdown (void *arg)
+ {
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit (1);
+ }
+
+@@ -132,7 +133,7 @@
+ /* try to become a client of the JACK server */
+
+ if ((client = jack_client_open("impulse_grabber", JackNullOption, NULL)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ return 1;
+ }
+
+@@ -149,7 +150,7 @@
+
+ jack_on_shutdown (client, jack_shutdown, 0);
+
+- /* display the current sample rate. once the client is activated
++ /* display the current sample rate. once the client is activated
+ (see below), you should rely on your own sample rate
+ callback (see above) for this value.
+ */
+@@ -187,7 +188,7 @@
+ }
+
+ free (ports);
+-
++
+ if ((ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == NULL) {
+ fprintf(stderr, "Cannot find any physical playback ports");
+ exit(1);
+@@ -198,7 +199,7 @@
+ }
+
+ free (ports);
+-
++
+ /* install a signal handler to properly quits jack client */
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+--- a/example-clients/ipunload.c
++++ b/example-clients/ipunload.c
+@@ -85,9 +85,9 @@
+ } else {
+ fprintf (stdout, "%s unloaded.\n", client_name);
+ }
+-
++
+ jack_client_close(client);
+ return 0;
+ }
+-
+-
++
++
+--- a/example-clients/jack_control
++++ b/example-clients/jack_control
+@@ -116,6 +116,8 @@
+ print " dp - get parameters of currently selected driver"
+ print " dpd <param> - get long description for driver parameter"
+ print " dps <param> <value> - set driver parameter"
++ print " asd <driver> - add slave driver"
++ print " rsd <driver> - remove slave driver"
+ print " il - get list of available internals"
+ print " ip <name> - get parameters of given internal"
+ print " ipd <name> <param> - get long description for internal parameter"
+@@ -305,6 +307,26 @@
+ name = sys.argv[index]
+ index += 1
+ result = control_iface.UnloadInternal(name)
++ elif arg == 'asd':
++ print "--- add slave driver"
++
++ if index >= len(sys.argv):
++ print "add slave driver command requires driver name argument"
++ sys.exit()
++
++ name = sys.argv[index]
++ index += 1
++ result = control_iface.AddSlaveDriver(name)
++ elif arg == 'rsd':
++ print "--- remove slave driver"
++
++ if index >= len(sys.argv):
++ print "remove slave driver command requires driver name argument"
++ sys.exit()
++
++ name = sys.argv[index]
++ index += 1
++ result = control_iface.RemoveSlaveDriver(name)
+ else:
+ print "Unknown command '%s'" % arg
+ except dbus.DBusException, e:
+--- a/example-clients/latent_client.c
++++ b/example-clients/latent_client.c
+@@ -1,4 +1,4 @@
+-/** @file simple_client.c
++/** @file latent_client.c
+ *
+ * @brief This simple client demonstrates the most basic features of JACK
+ * as they would be used by many applications.
+@@ -8,7 +8,7 @@
+ #include <errno.h>
+ #include <unistd.h>
+ #include <stdlib.h>
+-#include <string.h>
++#include <string.h>
+ #include <inttypes.h>
+
+ #include <jack/jack.h>
+@@ -19,12 +19,12 @@
+
+ jack_default_audio_sample_t *delay_line;
+ jack_nframes_t delay_index;
+-jack_nframes_t latency = 1024;
+-
+-#ifdef WIN32
+-#define jack_sleep(val) Sleep((val))
+-#else
+-#define jack_sleep(val) usleep((val) * 1000)
++jack_nframes_t latency = 1024;
++
++#ifdef WIN32
++#define jack_sleep(val) Sleep((val))
++#else
++#define jack_sleep(val) usleep((val) * 1000)
+ #endif
+
+ /**
+@@ -77,6 +77,7 @@
+ void
+ jack_shutdown (void *arg)
+ {
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit (1);
+ }
+
+@@ -213,3 +214,4 @@
+ jack_client_close (client);
+ exit (0);
+ }
++
+--- a/example-clients/lsp.c
++++ b/example-clients/lsp.c
+@@ -20,7 +20,7 @@
+ #include <unistd.h>
+ #endif
+ #include <string.h>
+-#include <getopt.h>
++#include <getopt.h>
+ #include <inttypes.h>
+ #include <jack/jack.h>
+
+@@ -246,3 +246,4 @@
+ jack_client_close (client);
+ exit (0);
+ }
++
+--- a/example-clients/metro.c
++++ b/example-clients/metro.c
+@@ -1,6 +1,6 @@
+ /*
+ Copyright (C) 2002 Anthony Van Groningen
+-
++
+ 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
+@@ -69,18 +69,21 @@
+ }
+
+ static void
+-process_silence (jack_nframes_t nframes)
++process_silence (jack_nframes_t nframes)
+ {
+ sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes);
+ memset (buffer, 0, sizeof (jack_default_audio_sample_t) * nframes);
+ }
+
++jack_nframes_t last_time;
++jack_time_t last_micro_time;
++
+ static void
+-process_audio (jack_nframes_t nframes)
++process_audio (jack_nframes_t nframes)
+ {
+ sample_t *buffer = (sample_t *) jack_port_get_buffer (output_port, nframes);
+ jack_nframes_t frames_left = nframes;
+-
++
+ while (wave_length - offset < frames_left) {
+ memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * (wave_length - offset));
+ frames_left -= wave_length - offset;
+@@ -90,6 +93,15 @@
+ memcpy (buffer + (nframes - frames_left), wave + offset, sizeof (sample_t) * frames_left);
+ offset += frames_left;
+ }
++
++ /*
++ jack_nframes_t cur_time = jack_frame_time(client);
++ jack_time_t cur_micro_time = jack_get_time();
++
++ printf("jack_frame_timed %lld micro %lld delta %d\n", cur_time, (cur_micro_time - last_micro_time), cur_time - last_time);
++ last_time = cur_time;
++ last_micro_time = cur_micro_time;
++ */
+ }
+
+ static int
+@@ -141,7 +153,7 @@
+ {"verbose", 0, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+-
++
+ while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
+ switch (opt) {
+ case 'f':
+@@ -178,12 +190,12 @@
+ fprintf (stderr, "invalid bpm\n");
+ return -1;
+ }
+- bpm_string = (char *) malloc ((strlen (optarg) + 4) * sizeof (char));
++ bpm_string = (char *) malloc ((strlen (optarg) + 5) * sizeof (char));
+ strcpy (bpm_string, optarg);
+ strcat (bpm_string, "_bpm");
+ break;
+ case 'n':
+- client_name = (char *) malloc (strlen (optarg) * sizeof (char));
++ client_name = (char *) malloc ((strlen (optarg) + 1) * sizeof (char));
+ strcpy (client_name, optarg);
+ break;
+ case 'v':
+@@ -193,7 +205,7 @@
+ transport_aware = 1;
+ break;
+ default:
+- fprintf (stderr, "unknown option %c\n", opt);
++ fprintf (stderr, "unknown option %c\n", opt);
+ case 'h':
+ usage ();
+ return -1;
+@@ -211,7 +223,7 @@
+ strcpy (client_name, "metro");
+ }
+ if ((client = jack_client_open (client_name, JackNoStartServer, &status)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ return 1;
+ }
+ jack_set_process_callback (client, process, 0);
+@@ -259,7 +271,7 @@
+ fprintf (stderr, "cannot activate client\n");
+ goto error;
+ }
+-
++
+ /* install a signal handler to properly quits jack client */
+ #ifdef WIN32
+ signal(SIGINT, signal_handler);
+@@ -280,9 +292,9 @@
+ sleep(1);
+ #endif
+ };
+-
++
+ jack_client_close(client);
+-
++
+ error:
+ free(amp);
+ free(wave);
+--- a/example-clients/midi_dump.c
++++ b/example-clients/midi_dump.c
+@@ -10,16 +10,16 @@
+ describe (jack_midi_event_t* event, char* buffer, size_t buflen)
+ {
+ assert (buflen > 0);
+-
++
+ buffer[0] = '\0';
+-
++
+ if (event->size == 0) {
+ return;
+ }
+-
++
+ int type = event->buffer[0] & 0xf0;
+ int channel = event->buffer[0] & 0xf;
+-
++
+ switch (type) {
+ case 0x90:
+ assert (event->size == 3);
+@@ -48,12 +48,12 @@
+
+ buffer = jack_port_get_buffer (port, frames);
+ assert (buffer);
+-
++
+ N = jack_midi_get_event_count (buffer);
+ for (i = 0; i < N; ++i) {
+ jack_midi_event_t event;
+ int r;
+-
++
+ r = jack_midi_event_get (&event, buffer, i);
+ if (r == 0) {
+ size_t j;
+@@ -65,7 +65,7 @@
+
+ describe (&event, description, sizeof (description));
+ printf (" %s", description);
+-
++
+ printf ("\n");
+ }
+ }
+@@ -108,7 +108,14 @@
+ exit (EXIT_FAILURE);
+ }
+
+- sleep (-1);
++ /* run until interrupted */
++ while (1) {
++ #ifdef WIN32
++ Sleep(1000);
++ #else
++ sleep(1);
++ #endif
++ };
+
+ return 0;
+ }
+--- /dev/null
++++ b/example-clients/midi_latency_test.c
+@@ -0,0 +1,969 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++/*
++ * This program is used to measure MIDI latency and jitter. It writes MIDI
++ * messages to one port and calculates how long it takes before it reads the
++ * same MIDI message over another port. It was written to calculate the
++ * latency and jitter of hardware and JACK hardware drivers, but might have
++ * other practical applications.
++ *
++ * The latency results of the program include the latency introduced by the
++ * JACK system. Because JACK has sample accurate MIDI, the same latency
++ * imposed on audio is also imposed on MIDI going through the system. Make
++ * sure you take this into account before complaining to me or (*especially*)
++ * other JACK developers about reported MIDI latency.
++ *
++ * The jitter results are a little more interesting. The program attempts to
++ * calculate 'average jitter' and 'peak jitter', as defined here:
++ *
++ * http://openmuse.org/transport/fidelity.html
++ *
++ * It also outputs a jitter plot, which gives you a more specific idea about
++ * the MIDI jitter for the ports you're testing. This is useful for catching
++ * extreme jitter values, and for analyzing the amount of truth in the
++ * technical specifications for your MIDI interface(s). :)
++ *
++ * This program is loosely based on 'alsa-midi-latency-test' in the ALSA test
++ * suite.
++ *
++ * To port this program to non-POSIX platforms, you'll have to include
++ * implementations for semaphores and command-line argument handling.
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <math.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <getopt.h>
++
++#include <jack/jack.h>
++#include <jack/midiport.h>
++
++#ifdef WIN32
++#include <windows.h>
++#include <unistd.h>
++#else
++#include <semaphore.h>
++#endif
++
++#define ABS(x) (((x) >= 0) ? (x) : (-(x)))
++
++#ifdef WIN32
++typedef HANDLE semaphore_t;
++#else
++typedef sem_t *semaphore_t;
++#endif
++
++const char *ERROR_MSG_TIMEOUT = "timed out while waiting for MIDI message";
++const char *ERROR_RESERVE = "could not reserve MIDI event on port buffer";
++const char *ERROR_SHUTDOWN = "the JACK server has been shutdown";
++
++const char *SOURCE_EVENT_RESERVE = "jack_midi_event_reserve";
++const char *SOURCE_PROCESS = "handle_process";
++const char *SOURCE_SHUTDOWN = "handle_shutdown";
++const char *SOURCE_SIGNAL_SEMAPHORE = "signal_semaphore";
++const char *SOURCE_WAIT_SEMAPHORE = "wait_semaphore";
++
++char *alias1;
++char *alias2;
++jack_client_t *client;
++semaphore_t connect_semaphore;
++volatile int connections_established;
++const char *error_message;
++const char *error_source;
++jack_nframes_t highest_latency;
++jack_time_t highest_latency_time;
++jack_latency_range_t in_latency_range;
++jack_port_t *in_port;
++semaphore_t init_semaphore;
++jack_nframes_t last_activity;
++jack_time_t last_activity_time;
++jack_time_t *latency_time_values;
++jack_nframes_t *latency_values;
++jack_nframes_t lowest_latency;
++jack_time_t lowest_latency_time;
++jack_midi_data_t *message_1;
++jack_midi_data_t *message_2;
++int messages_received;
++int messages_sent;
++size_t message_size;
++jack_latency_range_t out_latency_range;
++jack_port_t *out_port;
++semaphore_t process_semaphore;
++volatile sig_atomic_t process_state;
++char *program_name;
++jack_port_t *remote_in_port;
++jack_port_t *remote_out_port;
++size_t samples;
++const char *target_in_port_name;
++const char *target_out_port_name;
++int timeout;
++jack_nframes_t total_latency;
++jack_time_t total_latency_time;
++int unexpected_messages;
++int xrun_count;
++
++#ifdef WIN32
++char semaphore_error_msg[1024];
++#endif
++
++static void
++output_error(const char *source, const char *message);
++
++static void
++output_usage(void);
++
++static void
++set_process_error(const char *source, const char *message);
++
++static int
++signal_semaphore(semaphore_t semaphore);
++
++static jack_port_t *
++update_connection(jack_port_t *remote_port, int connected,
++ jack_port_t *local_port, jack_port_t *current_port,
++ const char *target_name);
++
++static int
++wait_semaphore(semaphore_t semaphore, int block);
++
++static semaphore_t
++create_semaphore(int id)
++{
++ semaphore_t semaphore;
++
++#ifdef WIN32
++ semaphore = CreateSemaphore(NULL, 0, 2, NULL);
++#elif defined (__APPLE__)
++ char name[128];
++ sprintf(name, "midi_sem_%d", id);
++ semaphore = sem_open(name, O_CREAT, 0777, 0);
++ if (semaphore == (sem_t *) SEM_FAILED) {
++ semaphore = NULL;
++ }
++#else
++ semaphore = malloc(sizeof(semaphore_t));
++ if (semaphore != NULL) {
++ if (sem_init(semaphore, 0, 0)) {
++ free(semaphore);
++ semaphore = NULL;
++ }
++ }
++#endif
++
++ return semaphore;
++}
++
++static void
++destroy_semaphore(semaphore_t semaphore, int id)
++{
++
++#ifdef WIN32
++ CloseHandle(semaphore);
++#else
++ sem_destroy(semaphore);
++#ifdef __APPLE__
++ {
++ char name[128];
++ sprintf(name, "midi_sem_%d", id);
++ sem_close(semaphore);
++ sem_unlink(name);
++ }
++#else
++ free(semaphore);
++#endif
++#endif
++
++}
++
++static void
++die(const char *source, const char *error_message)
++{
++ output_error(source, error_message);
++ output_usage();
++ exit(EXIT_FAILURE);
++}
++
++static const char *
++get_semaphore_error(void)
++{
++
++#ifdef WIN32
++ DWORD error = GetLastError();
++ if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error,
++ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
++ semaphore_error_msg, 1024, NULL)) {
++ snprintf(semaphore_error_msg, 1023, "Unknown OS error code '%d'",
++ error);
++ }
++ return semaphore_error_msg;
++#else
++ return strerror(errno);
++#endif
++
++}
++
++static void
++handle_info(const char *message)
++{
++ /* Suppress info */
++}
++
++static void
++handle_port_connection_change(jack_port_id_t port_id_1,
++ jack_port_id_t port_id_2, int connected,
++ void *arg)
++{
++ jack_port_t *port_1;
++ jack_port_t *port_2;
++ if ((remote_in_port != NULL) && (remote_out_port != NULL)) {
++ return;
++ }
++ port_1 = jack_port_by_id(client, port_id_1);
++ port_2 = jack_port_by_id(client, port_id_2);
++
++ /* The 'update_connection' call is not RT-safe. It calls
++ 'jack_port_get_connections' and 'jack_free'. This might be a problem
++ with JACK 1, as this callback runs in the process thread in JACK 1. */
++
++ if (port_1 == in_port) {
++ remote_in_port = update_connection(port_2, connected, in_port,
++ remote_in_port,
++ target_in_port_name);
++ } else if (port_2 == in_port) {
++ remote_in_port = update_connection(port_1, connected, in_port,
++ remote_in_port,
++ target_in_port_name);
++ } else if (port_1 == out_port) {
++ remote_out_port = update_connection(port_2, connected, out_port,
++ remote_out_port,
++ target_out_port_name);
++ } else if (port_2 == out_port) {
++ remote_out_port = update_connection(port_1, connected, out_port,
++ remote_out_port,
++ target_out_port_name);
++ }
++ if ((remote_in_port != NULL) && (remote_out_port != NULL)) {
++ connections_established = 1;
++ if (! signal_semaphore(connect_semaphore)) {
++ /* Sigh ... */
++ die("post_semaphore", get_semaphore_error());
++ }
++ if (! signal_semaphore(init_semaphore)) {
++ /* Sigh ... */
++ die("post_semaphore", get_semaphore_error());
++ }
++ }
++}
++
++static int
++handle_process(jack_nframes_t frames, void *arg)
++{
++ jack_midi_data_t *buffer;
++ jack_midi_event_t event;
++ jack_nframes_t event_count;
++ jack_nframes_t event_time;
++ jack_nframes_t frame;
++ size_t i;
++ jack_nframes_t last_frame_time;
++ jack_midi_data_t *message;
++ jack_time_t microseconds;
++ void *port_buffer;
++ jack_time_t time;
++ jack_midi_clear_buffer(jack_port_get_buffer(out_port, frames));
++ switch (process_state) {
++
++ case 0:
++ /* State: initializing */
++ switch (wait_semaphore(init_semaphore, 0)) {
++ case -1:
++ set_process_error(SOURCE_WAIT_SEMAPHORE, get_semaphore_error());
++ /* Fallthrough on purpose */
++ case 0:
++ return 0;
++ }
++ highest_latency = 0;
++ lowest_latency = 0;
++ messages_received = 0;
++ messages_sent = 0;
++ process_state = 1;
++ total_latency = 0;
++ total_latency_time = 0;
++ unexpected_messages = 0;
++ xrun_count = 0;
++ jack_port_get_latency_range(remote_in_port, JackCaptureLatency,
++ &in_latency_range);
++ jack_port_get_latency_range(remote_out_port, JackPlaybackLatency,
++ &out_latency_range);
++ goto send_message;
++
++ case 1:
++ /* State: processing */
++ port_buffer = jack_port_get_buffer(in_port, frames);
++ event_count = jack_midi_get_event_count(port_buffer);
++ last_frame_time = jack_last_frame_time(client);
++ for (i = 0; i < event_count; i++) {
++ jack_midi_event_get(&event, port_buffer, i);
++ message = (messages_received % 2) ? message_2 : message_1;
++ if ((event.size == message_size) &&
++ (! memcmp(message, event.buffer,
++ message_size * sizeof(jack_midi_data_t)))) {
++ goto found_message;
++ }
++ unexpected_messages++;
++ }
++ microseconds = jack_frames_to_time(client, last_frame_time) -
++ last_activity_time;
++ if ((microseconds / 1000000) >= timeout) {
++ set_process_error(SOURCE_PROCESS, ERROR_MSG_TIMEOUT);
++ }
++ break;
++ found_message:
++ event_time = last_frame_time + event.time;
++ frame = event_time - last_activity;
++ time = jack_frames_to_time(client, event_time) - last_activity_time;
++ if ((! highest_latency) || (frame > highest_latency)) {
++ highest_latency = frame;
++ highest_latency_time = time;
++ }
++ if ((! lowest_latency) || (frame < lowest_latency)) {
++ lowest_latency = frame;
++ lowest_latency_time = time;
++ }
++ latency_time_values[messages_received] = time;
++ latency_values[messages_received] = frame;
++ total_latency += frame;
++ total_latency_time += time;
++ messages_received++;
++ if (messages_received == samples) {
++ process_state = 2;
++ if (! signal_semaphore(process_semaphore)) {
++ /* Sigh ... */
++ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error());
++ }
++ break;
++ }
++ send_message:
++ frame = (jack_nframes_t) ((((double) rand()) / RAND_MAX) * frames);
++ if (frame >= frames) {
++ frame = frames - 1;
++ }
++ port_buffer = jack_port_get_buffer(out_port, frames);
++ buffer = jack_midi_event_reserve(port_buffer, frame, message_size);
++ if (buffer == NULL) {
++ set_process_error(SOURCE_EVENT_RESERVE, ERROR_RESERVE);
++ break;
++ }
++ message = (messages_sent % 2) ? message_2 : message_1;
++ memcpy(buffer, message, message_size * sizeof(jack_midi_data_t));
++ last_activity = jack_last_frame_time(client) + frame;
++ last_activity_time = jack_frames_to_time(client, last_activity);
++ messages_sent++;
++
++ case 2:
++ /* State: finished - do nothing */
++ case -1:
++ /* State: error - do nothing */
++ case -2:
++ /* State: signalled - do nothing */
++ ;
++ }
++ return 0;
++}
++
++static void
++handle_shutdown(void *arg)
++{
++ set_process_error(SOURCE_SHUTDOWN, ERROR_SHUTDOWN);
++}
++
++static void
++handle_signal(int sig)
++{
++ process_state = -2;
++ if (! signal_semaphore(connect_semaphore)) {
++ /* Sigh ... */
++ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error());
++ }
++ if (! signal_semaphore(process_semaphore)) {
++ /* Sigh ... */
++ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error());
++ }
++}
++
++static int
++handle_xrun(void *arg)
++{
++ xrun_count++;
++ return 0;
++}
++
++static void
++output_error(const char *source, const char *message)
++{
++ fprintf(stderr, "%s: %s: %s\n", program_name, source, message);
++}
++
++static void
++output_usage(void)
++{
++ fprintf(stderr, "Usage: %s [options] [out-port-name in-port-name]\n\n"
++ "\t-h, --help print program usage\n"
++ "\t-m, --message-size=size set size of MIDI messages to send "
++ "(default: 3)\n"
++ "\t-s, --samples=n number of MIDI messages to send "
++ "(default: 1024)\n"
++ "\t-t, --timeout=seconds message timeout (default: 5)\n\n",
++ program_name);
++}
++
++static unsigned long
++parse_positive_number_arg(char *s, char *name)
++{
++ char *end_ptr;
++ unsigned long result;
++ errno = 0;
++ result = strtoul(s, &end_ptr, 10);
++ if (errno) {
++ die(name, strerror(errno));
++ }
++ if (*s == '\0') {
++ die(name, "argument value cannot be empty");
++ }
++ if (*end_ptr != '\0') {
++ die(name, "invalid value");
++ }
++ if (! result) {
++ die(name, "must be a positive number");
++ }
++ return result;
++}
++
++static int
++register_signal_handler(void (*func)(int))
++{
++
++#ifdef WIN32
++ if (signal(SIGABRT, func) == SIG_ERR) {
++ return 0;
++ }
++#else
++ if (signal(SIGQUIT, func) == SIG_ERR) {
++ return 0;
++ }
++ if (signal(SIGHUP, func) == SIG_ERR) {
++ return 0;
++ }
++#endif
++
++ if (signal(SIGINT, func) == SIG_ERR) {
++ return 0;
++ }
++ if (signal(SIGTERM, func) == SIG_ERR) {
++ return 0;
++ }
++ return 1;
++}
++
++static void
++set_process_error(const char *source, const char *message)
++{
++ error_source = source;
++ error_message = message;
++ process_state = -1;
++ if (! signal_semaphore(process_semaphore)) {
++ /* Sigh ... */
++ output_error(source, message);
++ die(SOURCE_SIGNAL_SEMAPHORE, get_semaphore_error());
++ }
++}
++
++static int
++signal_semaphore(semaphore_t semaphore)
++{
++
++#ifdef WIN32
++ return ReleaseSemaphore(semaphore, 1, NULL);
++#else
++ return ! sem_post(semaphore);
++#endif
++
++}
++
++static jack_port_t *
++update_connection(jack_port_t *remote_port, int connected,
++ jack_port_t *local_port, jack_port_t *current_port,
++ const char *target_name)
++{
++ if (connected) {
++ if (current_port) {
++ return current_port;
++ }
++ if (target_name) {
++ char *aliases[2];
++ if (! strcmp(target_name, jack_port_name(remote_port))) {
++ return remote_port;
++ }
++ aliases[0] = alias1;
++ aliases[1] = alias2;
++ switch (jack_port_get_aliases(remote_port, aliases)) {
++ case -1:
++ /* Sigh ... */
++ die("jack_port_get_aliases", "Failed to get port aliases");
++ case 2:
++ if (! strcmp(target_name, alias2)) {
++ return remote_port;
++ }
++ /* Fallthrough on purpose */
++ case 1:
++ if (! strcmp(target_name, alias1)) {
++ return remote_port;
++ }
++ /* Fallthrough on purpose */
++ case 0:
++ return NULL;
++ }
++ /* This shouldn't happen. */
++ assert(0);
++ }
++ return remote_port;
++ }
++ if (! strcmp(jack_port_name(remote_port), jack_port_name(current_port))) {
++ const char **port_names;
++ if (target_name) {
++ return NULL;
++ }
++ port_names = jack_port_get_connections(local_port);
++ if (port_names == NULL) {
++ return NULL;
++ }
++
++ /* If a connected port is disconnected and other ports are still
++ connected, then we take the first port name in the array and use it
++ as our remote port. It's a dumb implementation. */
++ current_port = jack_port_by_name(client, port_names[0]);
++ jack_free(port_names);
++ if (current_port == NULL) {
++ /* Sigh */
++ die("jack_port_by_name", "failed to get port by name");
++ }
++ }
++ return current_port;
++}
++
++static int
++wait_semaphore(semaphore_t semaphore, int block)
++{
++
++#ifdef WIN32
++ DWORD result = WaitForSingleObject(semaphore, block ? INFINITE : 0);
++ switch (result) {
++ case WAIT_OBJECT_0:
++ return 1;
++ case WAIT_TIMEOUT:
++ return 0;
++ }
++ return -1;
++#else
++ if (block) {
++ while (sem_wait(semaphore)) {
++ if (errno != EINTR) {
++ return -1;
++ }
++ }
++ } else {
++ while (sem_trywait(semaphore)) {
++ switch (errno) {
++ case EAGAIN:
++ return 0;
++ case EINTR:
++ continue;
++ default:
++ return -1;
++ }
++ }
++ }
++ return 1;
++#endif
++
++}
++
++int
++main(int argc, char **argv)
++{
++ int jitter_plot[101];
++ int latency_plot[101];
++ int long_index = 0;
++ struct option long_options[] = {
++ {"help", 0, NULL, 'h'},
++ {"message-size", 1, NULL, 'm'},
++ {"samples", 1, NULL, 's'},
++ {"timeout", 1, NULL, 't'}
++ };
++ size_t name_arg_count;
++ size_t name_size;
++ char *option_string = "hm:s:t:";
++ int show_usage = 0;
++ connections_established = 0;
++ error_message = NULL;
++ message_size = 3;
++ program_name = argv[0];
++ remote_in_port = 0;
++ remote_out_port = 0;
++ samples = 1024;
++ timeout = 5;
++
++ for (;;) {
++ char c = getopt_long(argc, argv, option_string, long_options,
++ &long_index);
++ switch (c) {
++ case 'h':
++ show_usage = 1;
++ break;
++ case 'm':
++ message_size = parse_positive_number_arg(optarg, "message-size");
++ break;
++ case 's':
++ samples = parse_positive_number_arg(optarg, "samples");
++ break;
++ case 't':
++ timeout = parse_positive_number_arg(optarg, "timeout");
++ break;
++ default:
++ {
++ char *s = "'- '";
++ s[2] = c;
++ die(s, "invalid switch");
++ }
++ case -1:
++ if (show_usage) {
++ output_usage();
++ exit(EXIT_SUCCESS);
++ }
++ goto parse_port_names;
++ case 1:
++ /* end of switch :) */
++ ;
++ }
++ }
++ parse_port_names:
++ name_arg_count = argc - optind;
++ switch (name_arg_count) {
++ case 2:
++ target_in_port_name = argv[optind + 1];
++ target_out_port_name = argv[optind];
++ break;
++ case 0:
++ target_in_port_name = 0;
++ target_out_port_name = 0;
++ break;
++ default:
++ output_usage();
++ return EXIT_FAILURE;
++ }
++ name_size = jack_port_name_size();
++ alias1 = malloc(name_size * sizeof(char));
++ if (alias1 == NULL) {
++ error_message = strerror(errno);
++ error_source = "malloc";
++ goto show_error;
++ }
++ alias2 = malloc(name_size * sizeof(char));
++ if (alias2 == NULL) {
++ error_message = strerror(errno);
++ error_source = "malloc";
++ goto free_alias1;
++ }
++ latency_values = malloc(sizeof(jack_nframes_t) * samples);
++ if (latency_values == NULL) {
++ error_message = strerror(errno);
++ error_source = "malloc";
++ goto free_alias2;
++ }
++ latency_time_values = malloc(sizeof(jack_time_t) * samples);
++ if (latency_time_values == NULL) {
++ error_message = strerror(errno);
++ error_source = "malloc";
++ goto free_latency_values;
++ }
++ message_1 = malloc(message_size * sizeof(jack_midi_data_t));
++ if (message_1 == NULL) {
++ error_message = strerror(errno);
++ error_source = "malloc";
++ goto free_latency_time_values;
++ }
++ message_2 = malloc(message_size * sizeof(jack_midi_data_t));
++ if (message_2 == NULL) {
++ error_message = strerror(errno);
++ error_source = "malloc";
++ goto free_message_1;
++ }
++ switch (message_size) {
++ case 1:
++ message_1[0] = 0xf6;
++ message_2[0] = 0xfe;
++ break;
++ case 2:
++ message_1[0] = 0xc0;
++ message_1[1] = 0x00;
++ message_2[0] = 0xd0;
++ message_2[1] = 0x7f;
++ break;
++ case 3:
++ message_1[0] = 0x80;
++ message_1[1] = 0x00;
++ message_1[2] = 0x00;
++ message_2[0] = 0x90;
++ message_2[1] = 0x7f;
++ message_2[2] = 0x7f;
++ break;
++ default:
++ message_1[0] = 0xf0;
++ memset(message_1 + 1, 0,
++ (message_size - 2) * sizeof(jack_midi_data_t));
++ message_1[message_size - 1] = 0xf7;
++ message_2[0] = 0xf0;
++ memset(message_2 + 1, 0x7f,
++ (message_size - 2) * sizeof(jack_midi_data_t));
++ message_2[message_size - 1] = 0xf7;
++ }
++ client = jack_client_open(program_name, JackNullOption, NULL);
++ if (client == NULL) {
++ error_message = "failed to open JACK client";
++ error_source = "jack_client_open";
++ goto free_message_2;
++ }
++ in_port = jack_port_register(client, "in", JACK_DEFAULT_MIDI_TYPE,
++ JackPortIsInput, 0);
++ if (in_port == NULL) {
++ error_message = "failed to register MIDI-in port";
++ error_source = "jack_port_register";
++ goto close_client;
++ }
++ out_port = jack_port_register(client, "out", JACK_DEFAULT_MIDI_TYPE,
++ JackPortIsOutput, 0);
++ if (out_port == NULL) {
++ error_message = "failed to register MIDI-out port";
++ error_source = "jack_port_register";
++ goto unregister_in_port;
++ }
++ if (jack_set_process_callback(client, handle_process, NULL)) {
++ error_message = "failed to set process callback";
++ error_source = "jack_set_process_callback";
++ goto unregister_out_port;
++ }
++ if (jack_set_xrun_callback(client, handle_xrun, NULL)) {
++ error_message = "failed to set xrun callback";
++ error_source = "jack_set_xrun_callback";
++ goto unregister_out_port;
++ }
++ if (jack_set_port_connect_callback(client, handle_port_connection_change,
++ NULL)) {
++ error_message = "failed to set port connection callback";
++ error_source = "jack_set_port_connect_callback";
++ goto unregister_out_port;
++ }
++ jack_on_shutdown(client, handle_shutdown, NULL);
++ jack_set_info_function(handle_info);
++ process_state = 0;
++
++ connect_semaphore = create_semaphore(0);
++ if (connect_semaphore == NULL) {
++ error_message = get_semaphore_error();
++ error_source = "create_semaphore";
++ goto unregister_out_port;
++ }
++ init_semaphore = create_semaphore(1);
++ if (init_semaphore == NULL) {
++ error_message = get_semaphore_error();
++ error_source = "create_semaphore";
++ goto destroy_connect_semaphore;;
++ }
++ process_semaphore = create_semaphore(2);
++ if (process_semaphore == NULL) {
++ error_message = get_semaphore_error();
++ error_source = "create_semaphore";
++ goto destroy_init_semaphore;
++ }
++ if (jack_activate(client)) {
++ error_message = "could not activate client";
++ error_source = "jack_activate";
++ goto destroy_process_semaphore;
++ }
++ if (name_arg_count) {
++ if (jack_connect(client, jack_port_name(out_port),
++ target_out_port_name)) {
++ error_message = "could not connect MIDI out port";
++ error_source = "jack_connect";
++ goto deactivate_client;
++ }
++ if (jack_connect(client, target_in_port_name,
++ jack_port_name(in_port))) {
++ error_message = "could not connect MIDI in port";
++ error_source = "jack_connect";
++ goto deactivate_client;
++ }
++ }
++ if (! register_signal_handler(handle_signal)) {
++ error_message = strerror(errno);
++ error_source = "register_signal_handler";
++ goto deactivate_client;
++ }
++ printf("Waiting for connections ...\n");
++ if (wait_semaphore(connect_semaphore, 1) == -1) {
++ error_message = get_semaphore_error();
++ error_source = "wait_semaphore";
++ goto deactivate_client;
++ }
++ if (connections_established) {
++ printf("Waiting for test completion ...\n\n");
++ if (wait_semaphore(process_semaphore, 1) == -1) {
++ error_message = get_semaphore_error();
++ error_source = "wait_semaphore";
++ goto deactivate_client;
++ }
++ }
++ if (! register_signal_handler(SIG_DFL)) {
++ error_message = strerror(errno);
++ error_source = "register_signal_handler";
++ goto deactivate_client;
++ }
++ if (process_state == 2) {
++ double average_latency = ((double) total_latency) / samples;
++ double average_latency_time = total_latency_time / samples;
++ size_t i;
++ double latency_plot_offset =
++ floor(((double) lowest_latency_time) / 100.0) / 10.0;
++ double sample_rate = (double) jack_get_sample_rate(client);
++ jack_nframes_t total_jitter = 0;
++ jack_time_t total_jitter_time = 0;
++ for (i = 0; i <= 100; i++) {
++ jitter_plot[i] = 0;
++ latency_plot[i] = 0;
++ }
++ for (i = 0; i < samples; i++) {
++ double latency_time_value = (double) latency_time_values[i];
++ double latency_plot_time =
++ (latency_time_value / 1000.0) - latency_plot_offset;
++ double jitter_time = ABS(average_latency_time -
++ latency_time_value);
++ if (latency_plot_time >= 10.0) {
++ (latency_plot[100])++;
++ } else {
++ (latency_plot[(int) (latency_plot_time * 10.0)])++;
++ }
++ if (jitter_time >= 10000.0) {
++ (jitter_plot[100])++;
++ } else {
++ (jitter_plot[(int) (jitter_time / 100.0)])++;
++ }
++ total_jitter += ABS(average_latency -
++ ((double) latency_values[i]));
++ total_jitter_time += jitter_time;
++ }
++ printf("Reported out-port latency: %.2f-%.2f ms (%u-%u frames)\n"
++ "Reported in-port latency: %.2f-%.2f ms (%u-%u frames)\n"
++ "Average latency: %.2f ms (%.2f frames)\n"
++ "Lowest latency: %.2f ms (%u frames)\n"
++ "Highest latency: %.2f ms (%u frames)\n"
++ "Peak MIDI jitter: %.2f ms (%u frames)\n"
++ "Average MIDI jitter: %.2f ms (%.2f frames)\n",
++ (out_latency_range.min / sample_rate) * 1000.0,
++ (out_latency_range.max / sample_rate) * 1000.0,
++ out_latency_range.min, out_latency_range.max,
++ (in_latency_range.min / sample_rate) * 1000.0,
++ (in_latency_range.max / sample_rate) * 1000.0,
++ in_latency_range.min, in_latency_range.max,
++ average_latency_time / 1000.0, average_latency,
++ lowest_latency_time / 1000.0, lowest_latency,
++ highest_latency_time / 1000.0, highest_latency,
++ (highest_latency_time - lowest_latency_time) / 1000.0,
++ highest_latency - lowest_latency,
++ (total_jitter_time / 1000.0) / samples,
++ ((double) total_jitter) / samples);
++ printf("\nJitter Plot:\n");
++ for (i = 0; i < 100; i++) {
++ if (jitter_plot[i]) {
++ printf("%.1f - %.1f ms: %d\n", ((float) i) / 10.0,
++ ((float) (i + 1)) / 10.0, jitter_plot[i]);
++ }
++ }
++ if (jitter_plot[100]) {
++ printf(" > 10 ms: %d\n", jitter_plot[100]);
++ }
++ printf("\nLatency Plot:\n");
++ for (i = 0; i < 100; i++) {
++ if (latency_plot[i]) {
++ printf("%.1f - %.1f ms: %d\n",
++ latency_plot_offset + (((float) i) / 10.0),
++ latency_plot_offset + (((float) (i + 1)) / 10.0),
++ latency_plot[i]);
++ }
++ }
++ if (latency_plot[100]) {
++ printf(" > %.1f ms: %d\n", latency_plot_offset + 10.0,
++ latency_plot[100]);
++ }
++ }
++ deactivate_client:
++ jack_deactivate(client);
++ printf("\nMessages sent: %d\nMessages received: %d\n", messages_sent,
++ messages_received);
++ if (unexpected_messages) {
++ printf("Unexpected messages received: %d\n", unexpected_messages);
++ }
++ if (xrun_count) {
++ printf("Xruns: %d\n", xrun_count);
++ }
++ destroy_process_semaphore:
++ destroy_semaphore(process_semaphore, 2);
++ destroy_init_semaphore:
++ destroy_semaphore(init_semaphore, 1);
++ destroy_connect_semaphore:
++ destroy_semaphore(connect_semaphore, 0);
++ unregister_out_port:
++ jack_port_unregister(client, out_port);
++ unregister_in_port:
++ jack_port_unregister(client, in_port);
++ close_client:
++ jack_client_close(client);
++ free_message_2:
++ free(message_2);
++ free_message_1:
++ free(message_1);
++ free_latency_time_values:
++ free(latency_time_values);
++ free_latency_values:
++ free(latency_values);
++ free_alias2:
++ free(alias2);
++ free_alias1:
++ free(alias1);
++ if (error_message != NULL) {
++ show_error:
++ output_error(error_source, error_message);
++ exit(EXIT_FAILURE);
++ }
++ return EXIT_SUCCESS;
++}
+--- a/example-clients/midiseq.c
++++ b/example-clients/midiseq.c
+@@ -1,6 +1,6 @@
+ /*
+ Copyright (C) 2004 Ian Esten
+-
++
+ 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
+@@ -93,7 +93,7 @@
+ }
+ if((client = jack_client_open (args[1], JackNullOption, NULL)) == 0)
+ {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ return 1;
+ }
+ jack_set_process_callback (client, process, 0);
+@@ -117,7 +117,7 @@
+ fprintf (stderr, "cannot activate client");
+ return 1;
+ }
+-
++
+ /* install a signal handler to properly quits jack client */
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+@@ -128,7 +128,7 @@
+ while (1) {
+ sleep(1);
+ };
+-
++
+ jack_client_close(client);
+ exit (0);
+ }
+--- a/example-clients/midisine.c
++++ b/example-clients/midisine.c
+@@ -1,6 +1,6 @@
+ /*
+ Copyright (C) 2004 Ian Esten
+-
++
+ 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
+@@ -76,7 +76,7 @@
+ if ((in_event.time == i) && (event_index < event_count))
+ {
+ if (((*(in_event.buffer) & 0xf0)) == 0x90)
+- {
++ {
+ /* note on */
+ note = *(in_event.buffer + 1);
+ if (*(in_event.buffer + 2) == 0) {
+@@ -99,7 +99,7 @@
+ ramp = (ramp > 1.0) ? ramp - 2.0 : ramp;
+ out[i] = note_on*sin(2*M_PI*ramp);
+ }
+- return 0;
++ return 0;
+ }
+
+ static int srate(jack_nframes_t nframes, void *arg)
+@@ -111,6 +111,7 @@
+
+ static void jack_shutdown(void *arg)
+ {
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit(1);
+ }
+
+@@ -118,10 +119,10 @@
+ {
+ if ((client = jack_client_open("midisine", JackNullOption, NULL)) == 0)
+ {
+- fprintf(stderr, "jack server not running?\n");
++ fprintf(stderr, "JACK server not running?\n");
+ return 1;
+ }
+-
++
+ calc_note_frqs(jack_get_sample_rate (client));
+
+ jack_set_process_callback (client, process, 0);
+@@ -138,7 +139,7 @@
+ fprintf(stderr, "cannot activate client");
+ return 1;
+ }
+-
++
+ /* install a signal handler to properly quits jack client */
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+--- a/example-clients/monitor_client.c
++++ b/example-clients/monitor_client.c
+@@ -42,7 +42,7 @@
+ }
+
+ if ((client = jack_client_open ("input monitoring", JackNullOption, NULL)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ return 1;
+ }
+
+--- /dev/null
++++ b/example-clients/netmaster.c
+@@ -0,0 +1,181 @@
++/*
++ Copyright (C) 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
++ 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 <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#ifndef WIN32
++#include <unistd.h>
++#endif
++#include <math.h>
++#include <signal.h>
++#include <getopt.h>
++#include <string.h>
++
++#include <jack/net.h>
++
++jack_net_master_t* net;
++
++#define BUFFER_SIZE 512
++#define SAMPLE_RATE 44100
++
++static void signal_handler(int sig)
++{
++ jack_net_master_close(net);
++ fprintf(stderr, "signal received, exiting ...\n");
++ exit(0);
++}
++
++static void
++usage ()
++{
++ fprintf (stderr, "\n"
++ "usage: jack_net_master \n"
++ " [ -b buffer size (default = %d) ]\n"
++ " [ -r sample rate (default = %d) ]\n"
++ " [ -a hostname (default = %s) ]\n"
++ " [ -p port (default = %d) ]\n", BUFFER_SIZE, SAMPLE_RATE, DEFAULT_MULTICAST_IP, DEFAULT_PORT);
++}
++
++int
++main (int argc, char *argv[])
++{
++ int buffer_size = BUFFER_SIZE;
++ int sample_rate = SAMPLE_RATE;
++ int udp_port = DEFAULT_PORT;
++ const char* multicast_ip = DEFAULT_MULTICAST_IP;
++ const char *options = "b:r:a:p:h";
++ int option_index;
++ int opt;
++
++ struct option long_options[] =
++ {
++ {"buffer size", 1, 0, 'b'},
++ {"sample rate", 1, 0, 'r'},
++ {"hostname", 1, 0, 'a'},
++ {"port", 1, 0, 'p'},
++ {0, 0, 0, 0}
++ };
++
++ while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
++
++ switch (opt) {
++
++ case 'b':
++ buffer_size = atoi(optarg);
++ break;
++
++ case 'r':
++ sample_rate = atoi(optarg);
++ break;
++
++ case 'a':
++ multicast_ip = strdup(optarg);
++ break;
++
++ case 'p':
++ udp_port = atoi(optarg);
++ break;
++
++ case 'h':
++ usage();
++ return -1;
++ }
++ }
++
++ int i;
++ jack_master_t request = { -1, -1, -1, -1, buffer_size, sample_rate, "master" };
++ jack_slave_t result;
++ float** audio_input_buffer;
++ float** audio_output_buffer;
++ int wait_usec = (int) ((((float)buffer_size) * 1000000) / ((float)sample_rate));
++
++ printf("Waiting for a slave...\n");
++
++ if ((net = jack_net_master_open(multicast_ip, udp_port, "net_master", &request, &result)) == 0) {
++ fprintf(stderr, "NetJack master can not be opened\n");
++ return 1;
++ }
++
++ printf("Slave is running...\n");
++
++ /* install a signal handler to properly quits jack client */
++#ifdef WIN32
++ signal(SIGINT, signal_handler);
++ signal(SIGABRT, signal_handler);
++ signal(SIGTERM, signal_handler);
++#else
++ signal(SIGQUIT, signal_handler);
++ signal(SIGTERM, signal_handler);
++ signal(SIGHUP, signal_handler);
++ signal(SIGINT, signal_handler);
++#endif
++
++ // Allocate buffers
++ audio_input_buffer = (float**)calloc(result.audio_input, sizeof(float*));
++ for (i = 0; i < result.audio_input; i++) {
++ audio_input_buffer[i] = (float*)calloc(buffer_size, sizeof(float));
++ }
++
++ audio_output_buffer = (float**)calloc(result.audio_output, sizeof(float*));
++ for (i = 0; i < result.audio_output; i++) {
++ audio_output_buffer[i] = (float*)calloc(buffer_size, sizeof(float));
++ }
++
++ /*
++ Run until interrupted.
++
++ WARNING !! : this code is given for demonstration purpose. For proper timing bevahiour
++ it has to be called in a real-time context (which is *not* the case here...)
++ */
++
++ while (1) {
++
++ // Copy input to output
++ for (i = 0; i < result.audio_input; i++) {
++ memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float));
++ }
++
++ if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) {
++ printf("jack_net_master_send failure, exiting\n");
++ break;
++ }
++
++ if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) {
++ printf("jack_net_master_recv failure, exiting\n");
++ break;
++ }
++
++ usleep(wait_usec);
++ };
++
++ // Wait for application end
++ jack_net_master_close(net);
++
++ for (i = 0; i < result.audio_input; i++) {
++ free(audio_input_buffer[i]);
++ }
++ free(audio_input_buffer);
++
++ for (i = 0; i < result.audio_output; i++) {
++ free(audio_output_buffer[i]);
++ }
++ free(audio_output_buffer);
++
++ exit (0);
++}
+--- /dev/null
++++ b/example-clients/netslave.c
+@@ -0,0 +1,168 @@
++/*
++ Copyright (C) 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
++ 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 <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#ifndef WIN32
++#include <unistd.h>
++#endif
++#include <math.h>
++#include <signal.h>
++#include <getopt.h>
++#include <string.h>
++
++#include <jack/net.h>
++
++jack_net_slave_t* net;
++
++static void signal_handler(int sig)
++{
++ jack_net_slave_close(net);
++ fprintf(stderr, "signal received, exiting ...\n");
++ exit(0);
++}
++
++static void
++usage ()
++{
++ fprintf (stderr, "\n"
++ "usage: jack_net_slave \n"
++ " [ -C capture channels (default = 2)]\n"
++ " [ -P playback channels (default = 2) ]\n"
++ " [ -a hostname (default = %s) ]\n"
++ " [ -p port (default = %d)]\n", DEFAULT_MULTICAST_IP, DEFAULT_PORT);
++}
++
++static void net_shutdown(void* data)
++{
++ printf("Restarting...\n");
++}
++
++static int net_process(jack_nframes_t buffer_size,
++ int audio_input,
++ float** audio_input_buffer,
++ int midi_input,
++ void** midi_input_buffer,
++ int audio_output,
++ float** audio_output_buffer,
++ int midi_output,
++ void** midi_output_buffer,
++ void* data)
++{
++ int i;
++
++ // Copy input to output
++ for (i = 0; i < audio_input; i++) {
++ memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float));
++ }
++ return 0;
++}
++
++int
++main (int argc, char *argv[])
++{
++ int audio_input = 2;
++ int audio_output = 2;
++ int udp_port = DEFAULT_PORT;
++ const char* multicast_ip = DEFAULT_MULTICAST_IP;
++ const char *options = "C:P:a:p:h";
++ int option_index;
++ int opt;
++
++ struct option long_options[] =
++ {
++ {"audio input", 1, 0, 'C'},
++ {"audio output", 1, 0, 'P'},
++ {"hostname", 1, 0, 'a'},
++ {"port", 1, 0, 'p'},
++ {0, 0, 0, 0}
++ };
++
++ while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
++
++ switch (opt) {
++
++ case 'C':
++ audio_input = atoi(optarg);
++ break;
++
++ case 'P':
++ audio_output = atoi(optarg);
++ break;
++
++ case 'a':
++ multicast_ip = strdup(optarg);
++ break;
++
++ case 'p':
++ udp_port = atoi(optarg);
++ break;
++
++ case 'h':
++ usage();
++ return -1;
++ }
++ }
++
++ jack_slave_t request = { audio_input, audio_output, 0, 0, DEFAULT_MTU, -1, JackFloatEncoder, 0, 2 };
++ jack_master_t result;
++
++ printf("Waiting for a master...\n");
++
++ if ((net = jack_net_slave_open(multicast_ip, udp_port, "net_slave", &request, &result)) == 0) {
++ fprintf(stderr, "JACK server not running?\n");
++ return 1;
++ }
++
++ printf("Master is found and running...\n");
++
++ jack_set_net_slave_process_callback(net, net_process, NULL);
++ jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL);
++
++ if (jack_net_slave_activate(net) != 0) {
++ fprintf(stderr, "Cannot activate slave client\n");
++ return 1;
++ }
++
++ /* install a signal handler to properly quits jack client */
++#ifdef WIN32
++ signal(SIGINT, signal_handler);
++ signal(SIGABRT, signal_handler);
++ signal(SIGTERM, signal_handler);
++#else
++ signal(SIGQUIT, signal_handler);
++ signal(SIGTERM, signal_handler);
++ signal(SIGHUP, signal_handler);
++ signal(SIGINT, signal_handler);
++#endif
++
++ /* run until interrupted */
++ while (1) {
++ #ifdef WIN32
++ Sleep(1000);
++ #else
++ sleep(1);
++ #endif
++ };
++
++ // Wait for application end
++ jack_net_slave_deactivate(net);
++ jack_net_slave_close(net);
++ exit(0);
++}
+--- a/example-clients/netsource.c
++++ b/example-clients/netsource.c
+@@ -51,10 +51,8 @@
+ /* 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>
+@@ -94,7 +92,7 @@
+ int state_currentframe = 0;
+ int state_recv_packet_queue_time = 0;
+
+-int quit=0;
++int quit = 0;
+
+
+ int outsockfd;
+@@ -130,43 +128,39 @@
+
+ capture_ports = NULL;
+ /* Allocate audio capture channels */
+- for (chn = 0; chn < n_capture_audio; chn++)
+- {
++ 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)
+- {
++ if (!port) {
+ printf( "jack_netsource: cannot register %s port\n", buf);
+ break;
+ }
+- if (bitdepth == 1000) {
+- #if HAVE_CELT
+- #if HAVE_CELT_API_0_11
++ if (bitdepth == 1000) {
++#if HAVE_CELT
++#if HAVE_CELT_API_0_11
+ 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_custom( celt_mode, 1, NULL ) );
+- #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
++#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
+ 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
++#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
++#endif
++#endif
+ } else {
+- #if HAVE_SAMPLERATE
+- capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL));
+- #endif
++#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++)
+- {
++ 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)
+- {
++ if (!port) {
+ printf ("jack_netsource: cannot register %s port\n", buf);
+ break;
+ }
+@@ -176,43 +170,39 @@
+ /* Allocate audio playback channels */
+ port_flags = JackPortIsInput;
+ playback_ports = NULL;
+- for (chn = 0; chn < n_playback_audio; chn++)
+- {
++ 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)
+- {
++ if (!port) {
+ printf ("jack_netsource: cannot register %s port\n", buf);
+ break;
+ }
+ if( bitdepth == 1000 ) {
+- #if HAVE_CELT
+- #if HAVE_CELT_API_0_11
++#if HAVE_CELT
++#if HAVE_CELT_API_0_11
+ 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_custom( celt_mode, 1, NULL ) );
+- #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
++#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
+ 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
++#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
++#endif
++#endif
+ } else {
+- #if HAVE_SAMPLERATE
++#if HAVE_SAMPLERATE
+ playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL));
+- #endif
++#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++)
+- {
++ 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)
+- {
++ if (!port) {
+ printf ("jack_netsource: cannot register %s port\n", buf);
+ break;
+ }
+@@ -239,8 +229,7 @@
+ retval = 0;
+ }
+
+- else if (state == JackTransportStarting && last_transport_state != JackTransportStarting)
+- {
++ else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) {
+ retval = 0;
+ latency_count = latency - 1;
+ }
+@@ -252,10 +241,10 @@
+ void
+ freewheel_cb (int starting, void *arg)
+ {
+- freewheeling = starting;
++ freewheeling = starting;
+ }
+
+- int deadline_goodness=0;
++int deadline_goodness = 0;
+ /**
+ * The process callback for this JACK application.
+ * It is called by JACK at the appropriate times.
+@@ -281,7 +270,7 @@
+ 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) ;
++ net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ;
+ else
+ net_period = (float) nframes / (float) factor;
+
+@@ -301,47 +290,45 @@
+ */
+
+ if( latency == 0 ) {
+- /* reset packet_bufX... */
+- packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
++ /* reset packet_bufX... */
++ packet_bufX = packet_buf_tx + 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_tx->transport_state = jack_transport_query (client, &local_trans_pos);
+- pkthdr_tx->transport_frame = local_trans_pos.frame;
+- pkthdr_tx->framecnt = framecnt;
+- pkthdr_tx->latency = latency;
+- pkthdr_tx->reply_port = reply_port;
+- pkthdr_tx->sample_rate = jack_get_sample_rate (client);
+- pkthdr_tx->period_size = nframes;
+-
+- /* playback for us is capture on the other side */
+- pkthdr_tx->capture_channels_audio = playback_channels_audio;
+- pkthdr_tx->playback_channels_audio = capture_channels_audio;
+- pkthdr_tx->capture_channels_midi = playback_channels_midi;
+- pkthdr_tx->playback_channels_midi = capture_channels_midi;
+- pkthdr_tx->mtu = mtu;
+- if( freewheeling!= 0 )
+- pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
+- else
+- pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
+- //printf("goodness=%d\n", deadline_goodness );
+-
+- packet_header_hton (pkthdr_tx);
+- if (cont_miss < 3*latency+5) {
+- int r;
+- for( r=0; r<redundancy; r++ )
+- netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
+- }
+- else if (cont_miss > 50+5*latency)
+- {
+- state_connected = 0;
+- packet_cache_reset_master_address( packcache );
+- //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
+- cont_miss = 0;
+- }
++ /* ---------- Send ---------- */
++ render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
++ packet_bufX, net_period, dont_htonl_floats);
++
++ /* fill in packet hdr */
++ pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos);
++ pkthdr_tx->transport_frame = local_trans_pos.frame;
++ pkthdr_tx->framecnt = framecnt;
++ pkthdr_tx->latency = latency;
++ pkthdr_tx->reply_port = reply_port;
++ pkthdr_tx->sample_rate = jack_get_sample_rate (client);
++ pkthdr_tx->period_size = nframes;
++
++ /* playback for us is capture on the other side */
++ pkthdr_tx->capture_channels_audio = playback_channels_audio;
++ pkthdr_tx->playback_channels_audio = capture_channels_audio;
++ pkthdr_tx->capture_channels_midi = playback_channels_midi;
++ pkthdr_tx->playback_channels_midi = capture_channels_midi;
++ pkthdr_tx->mtu = mtu;
++ if( freewheeling != 0 )
++ pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
++ else
++ pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
++ //printf("goodness=%d\n", deadline_goodness );
++
++ packet_header_hton (pkthdr_tx);
++ if (cont_miss < 3 * latency + 5) {
++ int r;
++ for( r = 0; r < redundancy; r++ )
++ netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
++ } else if (cont_miss > 50 + 5 * latency) {
++ state_connected = 0;
++ packet_cache_reset_master_address( packcache );
++ //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
++ cont_miss = 0;
++ }
+ }
+
+ /*
+@@ -356,19 +343,19 @@
+ 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);
++ 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;
++ break;
+
+ packet_cache_drain_socket(packcache, input_fd);
+
+ if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame ))
+- if( got_frame == (framecnt - latency) )
+- break;
++ if( got_frame == (framecnt - latency) )
++ break;
+ }
+ } else {
+ // normally:
+@@ -379,8 +366,7 @@
+ size = packet_cache_retreive_packet_pointer( 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)
+- {
++ if (size == rx_bufsize) {
+ uint32_t *packet_buf_rx = rx_packet_ptr;
+ jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx;
+ packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
+@@ -391,13 +377,12 @@
+ deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency;
+ //printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset );
+
+- if (cont_miss)
+- {
++ 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);
++ capture_ports, capture_srcs, nframes, dont_htonl_floats);
+
+ state_currentframe = framecnt;
+ state_recv_packet_queue_time = recv_time_offset;
+@@ -408,8 +393,7 @@
+ /* 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
+- {
++ else {
+ jack_nframes_t latency_estimate;
+ if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) )
+ //if( (state_latency == 0) || (latency_estimate < state_latency) )
+@@ -425,8 +409,7 @@
+ cont_miss += 1;
+ chn = 0;
+ node = capture_ports;
+- while (node != NULL)
+- {
++ while (node != NULL) {
+ port = (jack_port_t *) node->data;
+ buf = jack_port_get_buffer (port, nframes);
+ porttype = jack_port_type (port);
+@@ -440,47 +423,45 @@
+ }
+ }
+ if (latency != 0) {
+- /* reset packet_bufX... */
+- packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
++ /* reset packet_bufX... */
++ packet_bufX = packet_buf_tx + 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_tx->transport_state = jack_transport_query (client, &local_trans_pos);
+- pkthdr_tx->transport_frame = local_trans_pos.frame;
+- pkthdr_tx->framecnt = framecnt;
+- pkthdr_tx->latency = latency;
+- pkthdr_tx->reply_port = reply_port;
+- pkthdr_tx->sample_rate = jack_get_sample_rate (client);
+- pkthdr_tx->period_size = nframes;
+-
+- /* playback for us is capture on the other side */
+- pkthdr_tx->capture_channels_audio = playback_channels_audio;
+- pkthdr_tx->playback_channels_audio = capture_channels_audio;
+- pkthdr_tx->capture_channels_midi = playback_channels_midi;
+- pkthdr_tx->playback_channels_midi = capture_channels_midi;
+- pkthdr_tx->mtu = mtu;
+- if( freewheeling!= 0 )
+- pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
+- else
+- pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
+- //printf("goodness=%d\n", deadline_goodness );
+-
+- packet_header_hton (pkthdr_tx);
+- if (cont_miss < 3*latency+5) {
+- int r;
+- for( r=0; r<redundancy; r++ )
+- netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
+- }
+- else if (cont_miss > 50+5*latency)
+- {
+- state_connected = 0;
+- packet_cache_reset_master_address( packcache );
+- //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
+- cont_miss = 0;
+- }
++ /* ---------- Send ---------- */
++ render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes,
++ packet_bufX, net_period, dont_htonl_floats);
++
++ /* fill in packet hdr */
++ pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos);
++ pkthdr_tx->transport_frame = local_trans_pos.frame;
++ pkthdr_tx->framecnt = framecnt;
++ pkthdr_tx->latency = latency;
++ pkthdr_tx->reply_port = reply_port;
++ pkthdr_tx->sample_rate = jack_get_sample_rate (client);
++ pkthdr_tx->period_size = nframes;
++
++ /* playback for us is capture on the other side */
++ pkthdr_tx->capture_channels_audio = playback_channels_audio;
++ pkthdr_tx->playback_channels_audio = capture_channels_audio;
++ pkthdr_tx->capture_channels_midi = playback_channels_midi;
++ pkthdr_tx->playback_channels_midi = capture_channels_midi;
++ pkthdr_tx->mtu = mtu;
++ if( freewheeling != 0 )
++ pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS;
++ else
++ pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness;
++ //printf("goodness=%d\n", deadline_goodness );
++
++ packet_header_hton (pkthdr_tx);
++ if (cont_miss < 3 * latency + 5) {
++ int r;
++ for( r = 0; r < redundancy; r++ )
++ netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu);
++ } else if (cont_miss > 50 + 5 * latency) {
++ state_connected = 0;
++ packet_cache_reset_master_address( packcache );
++ //printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss);
++ cont_miss = 0;
++ }
+ }
+
+ framecnt++;
+@@ -496,6 +477,7 @@
+ void
+ jack_shutdown (void *arg)
+ {
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit (1);
+ }
+
+@@ -504,20 +486,18 @@
+ {
+ name->sin_family = AF_INET ;
+ name->sin_port = htons (port);
+- if (hostname)
+- {
++ if (hostname) {
+ struct hostent *hostinfo = gethostbyname (hostname);
+ if (hostinfo == NULL) {
+ fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname);
+- fflush( stderr );
+- }
++ fflush( stderr );
++ }
+ #ifdef WIN32
+ name->sin_addr.s_addr = inet_addr( hostname );
+ #else
+ name->sin_addr = *(struct in_addr *) hostinfo->h_addr ;
+ #endif
+- }
+- else
++ } else
+ name->sin_addr.s_addr = htonl (INADDR_ANY) ;
+
+ }
+@@ -525,32 +505,32 @@
+ 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");
++ 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;
++ quit = 1;
+ }
+
+ int
+@@ -563,7 +543,7 @@
+ jack_status_t status;
+ #ifdef WIN32
+ WSADATA wsa;
+- int rc = WSAStartup(MAKEWORD(2,0),&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 ;) */
+@@ -572,10 +552,9 @@
+ /* Argument parsing stuff */
+ extern char *optarg;
+ extern int optind, optopt;
+- int errflg=0, c;
++ int errflg = 0, c;
+
+- if (argc < 3)
+- {
++ if (argc < 3) {
+ printUsage ();
+ return 1;
+ }
+@@ -585,17 +564,15 @@
+ 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)
+- {
++ 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);
++ peer_ip = (char *) malloc (sizeof (char) * strlen (optarg) + 1);
+ strcpy (peer_ip, optarg);
+ break;
+ case 'o':
+@@ -649,11 +626,11 @@
+ break;
+ case 'N':
+ free(client_name);
+- client_name = (char *) malloc (sizeof (char) * strlen (optarg)+1);
++ 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);
++ server_name = (char *) malloc (sizeof (char) * strlen (optarg) + 1);
+ strcpy (server_name, optarg);
+ options |= JackServerName;
+ break;
+@@ -666,8 +643,7 @@
+ errflg++;
+ }
+ }
+- if (errflg)
+- {
++ if (errflg) {
+ printUsage ();
+ exit (2);
+ }
+@@ -690,8 +666,7 @@
+ fprintf (stderr, "bind failure\n" );
+ }
+ }
+- if (reply_port)
+- {
++ if (reply_port) {
+ init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port);
+ if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) {
+ fprintf (stderr, "bind failure\n" );
+@@ -700,10 +675,9 @@
+
+ /* try to become a client of the JACK server */
+ client = jack_client_open (client_name, options, &status, server_name);
+- if (client == NULL)
+- {
++ if (client == NULL) {
+ fprintf (stderr, "jack_client_open() failed, status = 0x%2.0x\n"
+- "Is the JACK server running ?\n", status);
++ "Is the JACK server running ?\n", status);
+ return 1;
+ }
+
+@@ -716,7 +690,7 @@
+ 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) ;
++ 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);
+
+@@ -724,8 +698,7 @@
+ packcache = packet_cache_new (latency + 50, rx_bufsize, mtu);
+
+ /* tell the JACK server that we are ready to roll */
+- if (jack_activate (client))
+- {
++ if (jack_activate (client)) {
+ fprintf (stderr, "Cannot activate client");
+ return 1;
+ }
+@@ -739,49 +712,41 @@
+ statecopy_latency = state_latency;
+ statecopy_netxruns = state_netxruns;
+
+- while ( !quit )
+- {
++ while ( !quit ) {
+ #ifdef WIN32
+ Sleep (1000);
+ #else
+ sleep(1);
+ #endif
+- if (statecopy_connected != state_connected)
+- {
++ if (statecopy_connected != state_connected) {
+ statecopy_connected = state_connected;
+- if (statecopy_connected)
+- {
++ if (statecopy_connected) {
+ state_netxruns = 1; // We want to reset the netxrun count on each new connection
+ printf ("Connected :-)\n");
+- }
+- else
++ } else
+ printf ("Not Connected\n");
+
+- fflush(stdout);
++ 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);
++ 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);
++ 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);
++ } else {
++ if (statecopy_latency != state_latency) {
++ statecopy_latency = state_latency;
++ if (statecopy_latency > 1)
++ printf ("current latency %d\n", statecopy_latency);
++ fflush(stdout);
+ }
+ }
+ }
+--- a/example-clients/samplerate.c
++++ b/example-clients/samplerate.c
+@@ -56,7 +56,7 @@
+ if (argc==1) {
+ return;
+ }
+- fprintf(stderr, "usage: %s [bufsize]\n", package);
++ fprintf(stderr, "usage: %s\n", package);
+ exit(9);
+ }
+
+--- a/example-clients/server_control.cpp
++++ b/example-clients/server_control.cpp
+@@ -53,6 +53,7 @@
+ return NULL;
+ }
+
++#if 0
+ static jackctl_parameter_t *
+ jackctl_get_parameter(
+ const JSList * parameters_list,
+@@ -70,6 +71,7 @@
+
+ return NULL;
+ }
++#endif
+
+ static void print_value(union jackctl_parameter_value value, jackctl_param_type_t type)
+ {
+--- a/example-clients/session_notify.c
++++ b/example-clients/session_notify.c
+@@ -2,7 +2,7 @@
+ * session_notify.c -- ultra minimal session manager
+ *
+ * Copyright (C) 2010 Torben Hohn.
+- *
++ *
+ * 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
+@@ -141,15 +141,15 @@
+
+
+ retval = jack_session_notify( client, NULL, notify_type, save_path );
+- for(i=0; retval[i].uuid; i++ ) {
++ for (i = 0; retval[i].uuid; i++) {
+ printf( "export SESSION_DIR=\"%s%s/\"\n", save_path, retval[i].client_name );
+ printf( "%s &\n", retval[i].command );
+- add_uuid_mapping(retval[i].uuid);
++ add_uuid_mapping(retval[i].uuid);
+ }
+
+ printf( "sleep 10\n" );
+
+- for(k=0; retval[k].uuid; k++ ) {
++ for (k = 0; retval[k].uuid; k++) {
+
+ char* port_regexp = alloca( jack_client_name_size()+3 );
+ char* client_name = jack_get_client_name_by_uuid( client, retval[k].uuid );
+@@ -163,12 +163,12 @@
+ const char **connections;
+ if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) {
+ for (j = 0; connections[j]; j++) {
+- char *src = map_port_name_to_uuid_port( ports[i] );
+- char *dst = map_port_name_to_uuid_port( connections[j] );
++ char *src = map_port_name_to_uuid_port( ports[i] );
++ char *dst = map_port_name_to_uuid_port( connections[j] );
+ printf( "jack_connect -u \"%s\" \"%s\"\n", src, dst );
+ }
+ jack_free (connections);
+- }
++ }
+ }
+ jack_free(ports);
+
+--- a/example-clients/showtime.c
++++ b/example-clients/showtime.c
+@@ -34,7 +34,7 @@
+
+ transport_state = jack_transport_query (client, ¤t);
+ frame_time = jack_frame_time (client);
+-
++
+ printf ("frame = %u frame_time = %u usecs = %lld \t", current.frame, frame_time, current.usecs);
+
+ switch (transport_state) {
+@@ -64,6 +64,7 @@
+ static void
+ jack_shutdown (void *arg)
+ {
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit (1);
+ }
+
+@@ -81,7 +82,7 @@
+ /* try to become a client of the JACK server */
+
+ if ((client = jack_client_open ("showtime", JackNullOption, NULL)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ return 1;
+ }
+
+@@ -103,7 +104,7 @@
+ fprintf (stderr, "cannot activate client");
+ return 1;
+ }
+-
++
+ while (1) {
+ usleep (20);
+ showtime ();
+--- a/example-clients/thru_client.c
++++ b/example-clients/thru_client.c
+@@ -1,4 +1,4 @@
+-/** @file simple_client.c
++/** @file thru_client.c
+ *
+ * @brief This simple through client demonstrates the basic features of JACK
+ * as they would be used by many applications.
+--- a/example-clients/tw.c
++++ b/example-clients/tw.c
+@@ -1,4 +1,4 @@
+-/** @file simple_client.c
++/** @file tw.c
+ *
+ * @brief This simple client demonstrates the basic features of JACK
+ * as they would be used by many applications.
+@@ -42,56 +42,56 @@
+ {
+ jack_default_audio_sample_t *in, *out;
+ jack_transport_state_t ts = jack_transport_query(client, NULL);
+-
++
+ if (ts == JackTransportRolling) {
+-
++
+ if (client_state == Init)
+ client_state = Run;
+-
++
+ in = jack_port_get_buffer (input_port, nframes);
+ out = jack_port_get_buffer (output_port, nframes);
+ memcpy (out, in,
+ sizeof (jack_default_audio_sample_t) * nframes);
+-
++
+ } else if (ts == JackTransportStopped) {
+-
++
+ if (client_state == Run) {
+ client_state = Exit;
+ return -1; // to stop the thread
+ }
+ }
+
+- return 0;
++ return 0;
+ }
+
+-static void* jack_thread(void *arg)
++static void* jack_thread(void *arg)
+ {
+ jack_client_t* client = (jack_client_t*) arg;
+-
++
+ while (1) {
+-
++
+ jack_nframes_t frames = jack_cycle_wait (client);
+ int status = _process(frames);
+ jack_cycle_signal (client, status);
+-
++
+ /*
+ Possibly do something else after signaling next clients in the graph
+ */
+-
++
+ /* End condition */
+ if (status != 0)
+- return 0;
++ return 0;
+ }
+-
++
+ /* not reached*/
+ return 0;
+ }
+
+ /*
+-static void* jack_thread(void *arg)
++static void* jack_thread(void *arg)
+ {
+ jack_client_t* client = (jack_client_t*) arg;
+-
++
+ while (1) {
+ jack_nframes_t frames;
+ int status;
+@@ -103,7 +103,7 @@
+ frames = jack_cycle_wait (client);
+ status = _process(frames);
+ jack_cycle_signal (client, status);
+- // cycle 3
++ // cycle 3
+ frames = jack_cycle_wait (client);
+ status = _process(frames);
+ jack_cycle_signal (client, status);
+@@ -112,7 +112,7 @@
+ status = _process(frames);
+ jack_cycle_signal (client, status);
+ }
+-
++
+ return 0;
+ }
+ */
+@@ -124,6 +124,7 @@
+ static void
+ jack_shutdown (void *arg)
+ {
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit (1);
+ }
+
+@@ -172,8 +173,8 @@
+
+ /* tell the JACK server to call `process()' whenever
+ there is work to be done.
+- */
+- if (jack_set_process_thread(client, jack_thread, client) < 0)
++ */
++ if (jack_set_process_thread(client, jack_thread, client) < 0)
+ exit(1);
+
+ /* tell the JACK server to call `jack_shutdown()' if
+@@ -183,7 +184,7 @@
+
+ jack_on_shutdown (client, jack_shutdown, 0);
+
+- /* display the current sample rate.
++ /* display the current sample rate.
+ */
+
+ printf ("engine sample rate: %" PRIu32 "\n",
+@@ -231,7 +232,7 @@
+ }
+
+ free (ports);
+-
++
+ ports = jack_get_ports (client, NULL, NULL,
+ JackPortIsPhysical|JackPortIsInput);
+ if (ports == NULL) {
+@@ -244,7 +245,7 @@
+ }
+
+ free (ports);
+-
++
+ /* install a signal handler to properly quits jack client */
+ signal(SIGQUIT, signal_handler);
+ signal(SIGTERM, signal_handler);
+--- a/example-clients/wait.c
++++ b/example-clients/wait.c
+@@ -11,22 +11,22 @@
+ char * my_name;
+
+ void
+-show_usage (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");
++ 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[])
++main(int argc, char *argv[])
+ {
+ jack_client_t *client;
+ jack_status_t status;
+@@ -40,7 +40,7 @@
+ int wait_timeout = 0;
+ time_t start_timestamp;
+
+-
++
+ struct option long_options[] = {
+ { "server", 1, 0, 's' },
+ { "wait", 0, 0, 'w' },
+@@ -78,11 +78,11 @@
+ wait_timeout = atoi(optarg);
+ break;
+ case 'h':
+- show_usage ();
++ show_usage();
+ return 1;
+ break;
+ default:
+- show_usage ();
++ show_usage();
+ return 1;
+ break;
+ }
+@@ -90,40 +90,40 @@
+
+ /* try to open server in a loop. breaking under certein conditions */
+
+- start_timestamp = time( NULL );
++ start_timestamp = time(NULL);
+
+- while(1) {
++ while (1) {
+ client = jack_client_open ("wait", options, &status, server_name);
+ /* check for some real error and bail out */
+- if( (client == NULL) && !(status & JackServerFailed) ) {
++ 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" );
++ if (client == NULL) {
++ if (wait_for_quit) {
++ fprintf(stdout, "server is gone\n");
+ break;
+ }
+- if( just_check ) {
+- fprintf( stdout, "not running\n" );
++ if (just_check) {
++ fprintf(stdout, "not running\n");
+ break;
+ }
+ } else {
+- jack_client_close( client );
+- if( wait_for_start ) {
+- fprintf( stdout, "server is available\n" );
++ jack_client_close(client);
++ if (wait_for_start) {
++ fprintf(stdout, "server is available\n");
+ break;
+ }
+- if( just_check ) {
+- fprintf( stdout, "running\n" );
++ if (just_check) {
++ fprintf(stdout, "running\n");
+ break;
+ }
+ }
+- if( wait_timeout ) {
+- if( (time( NULL ) - start_timestamp) > wait_timeout ) {
+- fprintf( stdout, "timeout\n" );
++ if (wait_timeout) {
++ if ((time(NULL) - start_timestamp) > wait_timeout) {
++ fprintf(stdout, "timeout\n");
+ break;
+ }
+ }
+@@ -132,5 +132,5 @@
+ sleep(1);
+ }
+
+- exit (0);
++ exit(0);
+ }
+--- a/example-clients/wscript
++++ b/example-clients/wscript
+@@ -25,8 +25,11 @@
+ 'jack_simple_session_client' : 'simple_session_client.c',
+ 'jack_session_notify' : 'session_notify.c',
+ 'jack_server_control' : 'server_control.cpp',
++ 'jack_net_slave' : 'netslave.c',
++ 'jack_net_master' : 'netmaster.c',
+ 'jack_latent_client' : 'latent_client.c',
+ 'jack_midi_dump' : 'midi_dump.c',
++ 'jack_midi_latency_test' : 'midi_latency_test.c'
+ }
+
+ example_libs = {
+@@ -36,11 +39,6 @@
+ 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']
+
+@@ -71,22 +69,34 @@
+ if bld.env['IS_SUN']:
+ os_incdir = ['../solaris', '../posix']
+ for example_program, example_program_source in example_programs.items():
++ if example_program == 'jack_server_control':
++ uselib_local = 'serverlib'
++ elif example_program == 'jack_net_slave':
++ if not bld.env['BUILD_NETLIB']:
++ continue
++ uselib_local = 'netlib'
++ elif example_program == 'jack_net_master':
++ if not bld.env['BUILD_NETLIB']:
++ continue
++ uselib_local = 'netlib'
++ else:
++ uselib_local = 'clientlib'
++
+ prog = bld.new_task_gen('cxx', 'program')
+ prog.features.append('cc')
+ prog.includes = os_incdir + ['../common/jack', '../common']
+ prog.source = example_program_source
+ if bld.env['IS_MACOSX']:
+- prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc")
++ prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64")
+ prog.env.append_value("LINKFLAGS", "")
+ if bld.env['IS_LINUX']:
+ prog.uselib = 'RT'
+ if bld.env['IS_SUN']:
+ prog.env.append_value("LINKFLAGS", "-lm")
+- if example_program == 'jack_server_control':
+- prog.uselib_local = 'serverlib'
+- else:
+- prog.uselib_local = 'clientlib'
++
++ prog.uselib_local = uselib_local
++
+ prog.target = example_program
+
+ if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT']:
+@@ -94,8 +104,8 @@
+ prog.includes = os_incdir + ['../common/jack', '../common']
+ prog.source = 'transport.c'
+ if bld.env['IS_MACOSX']:
+- prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc")
++ prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64")
+ prog.env.append_value("LINKFLAGS", "")
+ if bld.env['IS_LINUX']:
+ prog.uselib = 'RT READLINE NCURSES'
+@@ -109,8 +119,8 @@
+ prog.includes = os_incdir + ['../common/jack', '../common']
+ prog.source = 'capture_client.c'
+ if bld.env['IS_MACOSX']:
+- prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc")
++ prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64")
+ prog.env.append_value("LINKFLAGS", "")
+ prog.uselib = 'SNDFILE'
+ if bld.env['IS_LINUX']:
+@@ -153,8 +163,8 @@
+ lib.target = example_lib
+ lib.source = example_lib_source
+ if bld.env['IS_MACOSX']:
+- lib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #lib.env.append_value("LINKFLAGS", "-arch i386 -arch ppc")
++ lib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #lib.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64")
+ lib.env.append_value("LINKFLAGS", "")
+ if bld.env['IS_SUN']:
+ lib.env.append_value("LINKFLAGS", "-lm")
+--- a/example-clients/zombie.c
++++ b/example-clients/zombie.c
+@@ -1,6 +1,6 @@
+ /*
+ Copyright (C) 2002 Jeremy Hall
+-
++
+ 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
+@@ -30,18 +30,18 @@
+ jack_port_t* output_port;
+
+ static int
+-process(jack_nframes_t nframes, void* arg)
++process(jack_nframes_t nframes, void* arg)
+ {
+ if (count++ == 1000) {
+ printf("process block\n");
+ //while (1) {}
+ sleep(1);
+ }
+-
++
+ return 0;
+ }
+
+-static void
++static void
+ shutdown (void *arg)
+ {
+ printf("shutdown \n");
+@@ -54,10 +54,10 @@
+ jack_client_t* client = NULL;
+ /* try to become a client of the JACK server */
+ if ((client = jack_client_open ("zombie", JackNullOption, NULL)) == 0) {
+- fprintf (stderr, "jack server not running?\n");
++ fprintf (stderr, "JACK server not running?\n");
+ goto error;
+ }
+-
++
+ jack_set_process_callback (client, process, NULL);
+ jack_on_shutdown(client, shutdown, NULL);
+ output_port = jack_port_register (client, "port1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+@@ -67,9 +67,9 @@
+ fprintf (stderr, "cannot activate client");
+ goto error;
+ }
+-
++
+ jack_connect(client, jack_port_name(output_port), "coreaudio:Built-in Audio:in2");
+-
++
+ while (running) {
+ sleep(1);
+ printf ("run\n");
+@@ -78,9 +78,9 @@
+ jack_deactivate (client);
+ jack_client_close (client);
+ return 0;
+-
++
+ error:
+- if (client)
++ if (client)
+ jack_client_close (client);
+ return 1;
+ }
+--- a/linux/alsa/alsa_driver.c
++++ b/linux/alsa/alsa_driver.c
+@@ -20,6 +20,7 @@
+
+
+ #define __STDC_FORMAT_MACROS // For inttypes.h to work in C++
++#define _GNU_SOURCE /* for strcasestr() from string.h */
+
+ #include <math.h>
+ #include <stdio.h>
+@@ -52,6 +53,8 @@
+
+ #undef DEBUG_WAKEUP
+
++char* strcasestr(const char* haystack, const char* needle);
++
+ /* Delay (in process calls) before jackd will report an xrun */
+ #define XRUN_REPORT_DELAY 0
+
+@@ -151,7 +154,7 @@
+ * should be hw:x where x is the card number */
+
+ char tmp[5];
+- strncpy(tmp,strstr(driver->alsa_name_playback,"hw"),4);
++ strncpy(tmp,strcasestr(driver->alsa_name_playback,"hw"),4);
+ tmp[4]='\0';
+ jack_info("control device %s",tmp);
+ ctl_name = strdup(tmp);
+@@ -204,8 +207,8 @@
+ static int
+ alsa_driver_usx2y_hardware (alsa_driver_t *driver)
+ {
+- driver->hw = jack_alsa_usx2y_hw_new (driver);
+- return 0;
++ driver->hw = jack_alsa_usx2y_hw_new (driver);
++ return 0;
+ }
+ */
+
+@@ -1823,6 +1826,107 @@
+ free (driver);
+ }
+
++static char*
++discover_alsa_using_apps ()
++{
++ char found[2048];
++ char command[5192];
++ char* path = getenv ("PATH");
++ char* dir;
++ size_t flen = 0;
++ int card;
++ int device;
++ size_t cmdlen = 0;
++
++ if (!path) {
++ return NULL;
++ }
++
++ /* look for lsof and give up if its not in PATH */
++
++ path = strdup (path);
++ dir = strtok (path, ":");
++ while (dir) {
++ char maybe[PATH_MAX+1];
++ snprintf (maybe, sizeof(maybe), "%s/lsof", dir);
++ if (access (maybe, X_OK)) {
++ break;
++ }
++ dir = strtok (NULL, ":");
++ }
++ free (path);
++
++ if (!dir) {
++ return NULL;
++ }
++
++ snprintf (command, sizeof (command), "lsof -Fc0 ");
++ cmdlen = strlen (command);
++
++ for (card = 0; card < 8; ++card) {
++ for (device = 0; device < 8; ++device) {
++ char buf[32];
++
++ snprintf (buf, sizeof (buf), "/dev/snd/pcmC%dD%dp", card, device);
++ if (access (buf, F_OK) == 0) {
++ snprintf (command+cmdlen, sizeof(command)-cmdlen, "%s ", buf);
++ }
++ cmdlen = strlen (command);
++
++ snprintf (buf, sizeof (buf), "/dev/snd/pcmC%dD%dc", card, device);
++ if (access (buf, F_OK) == 0) {
++ snprintf (command+cmdlen, sizeof(command)-cmdlen, "%s ", buf);
++ }
++ cmdlen = strlen (command);
++ }
++ }
++
++ FILE* f = popen (command, "r");
++
++ if (!f) {
++ return NULL;
++ }
++
++ while (!feof (f)) {
++ char buf[1024]; /* lsof doesn't output much */
++
++ if (!fgets (buf, sizeof (buf), f)) {
++ break;
++ }
++
++ if (*buf != 'p') {
++ return NULL;
++ }
++
++ /* buf contains NULL as a separator between the process field and the command field */
++ char *pid = buf;
++ ++pid; /* skip leading 'p' */
++ char *cmd = pid;
++
++ /* skip to NULL */
++ while (*cmd) {
++ ++cmd;
++ }
++ ++cmd; /* skip to 'c' */
++ ++cmd; /* skip to first character of command */
++
++ snprintf (found+flen, sizeof (found)-flen, "%s (process ID %s)\n", cmd, pid);
++ flen = strlen (found);
++
++ if (flen >= sizeof (found)) {
++ break;
++ }
++ }
++
++ pclose (f);
++
++ if (flen) {
++ return strdup (found);
++ } else {
++ return NULL;
++ }
++}
++
+ jack_driver_t *
+ alsa_driver_new (char *name, char *playback_alsa_device,
+ char *capture_alsa_device,
+@@ -1846,7 +1950,7 @@
+ )
+ {
+ int err;
+-
++ char* current_apps;
+ alsa_driver_t *driver;
+
+ jack_info ("creating alsa driver ... %s|%s|%" PRIu32 "|%" PRIu32
+@@ -1944,14 +2048,25 @@
+ SND_PCM_NONBLOCK) < 0) {
+ switch (errno) {
+ case EBUSY:
+- jack_error ("the playback device \"%s\" is "
+- "already in use. Please stop the"
+- " application using it and "
+- "run JACK again",
+- playback_alsa_device);
+- alsa_driver_delete (driver);
++ current_apps = discover_alsa_using_apps ();
++ if (current_apps) {
++ jack_error ("\n\nATTENTION: The playback device \"%s\" is "
++ "already in use. The following applications "
++ " are using your soundcard(s) so you should "
++ " check them and stop them as necessary before "
++ " trying to start JACK again:\n\n%s",
++ playback_alsa_device,
++ current_apps);
++ free (current_apps);
++ } else {
++ jack_error ("\n\nATTENTION: The playback device \"%s\" is "
++ "already in use. Please stop the"
++ " application using it and "
++ "run JACK again",
++ playback_alsa_device);
++ }
++ alsa_driver_delete (driver);
+ return NULL;
+- break;
+
+ case EPERM:
+ jack_error ("you do not have permission to open "
+@@ -1977,11 +2092,23 @@
+ SND_PCM_NONBLOCK) < 0) {
+ switch (errno) {
+ case EBUSY:
+- jack_error ("the capture device \"%s\" is "
+- "already in use. Please stop the"
+- " application using it and "
+- "run JACK again",
+- capture_alsa_device);
++ current_apps = discover_alsa_using_apps ();
++ if (current_apps) {
++ jack_error ("\n\nATTENTION: The capture device \"%s\" is "
++ "already in use. The following applications "
++ " are using your soundcard(s) so you should "
++ " check them and stop them as necessary before "
++ " trying to start JACK again:\n\n%s",
++ capture_alsa_device,
++ current_apps);
++ free (current_apps);
++ } else {
++ jack_error ("\n\nATTENTION: The capture (recording) device \"%s\" is "
++ "already in use. Please stop the"
++ " application using it and "
++ "run JACK again",
++ capture_alsa_device);
++ }
+ alsa_driver_delete (driver);
+ return NULL;
+ break;
+--- a/linux/alsa/alsa_rawmidi.c
++++ b/linux/alsa/alsa_rawmidi.c
+@@ -427,9 +427,9 @@
+ char name[128];
+
+ if (type & JackPortIsOutput)
+- snprintf(name, sizeof(name) - 1, "system:midi_capture_%d", ++midi->midi_in_cnt);
++ snprintf(name, sizeof(name), "system:midi_capture_%d", ++midi->midi_in_cnt);
+ else
+- snprintf(name, sizeof(name) - 1, "system:midi_playback_%d", ++midi->midi_out_cnt);
++ snprintf(name, sizeof(name), "system:midi_playback_%d", ++midi->midi_out_cnt);
+
+ port->jack = jack_port_register(midi->client, name, JACK_DEFAULT_MIDI_TYPE,
+ type | JackPortIsPhysical | JackPortIsTerminal, 0);
+--- a/linux/alsa/alsa_seqmidi.c
++++ b/linux/alsa/alsa_seqmidi.c
+@@ -492,9 +492,9 @@
+ }
+
+ if (jack_caps & JackPortIsOutput)
+- snprintf(name, sizeof(name) - 1, "system:midi_capture_%d", ++self->midi_in_cnt);
++ snprintf(name, sizeof(name), "system:midi_capture_%d", ++self->midi_in_cnt);
+ else
+- snprintf(name, sizeof(name) - 1, "system:midi_playback_%d", ++self->midi_out_cnt);
++ snprintf(name, sizeof(name), "system:midi_playback_%d", ++self->midi_out_cnt);
+
+ port->jack_port = jack_port_register(self->jack,
+ name, JACK_DEFAULT_MIDI_TYPE, jack_caps, 0);
+--- a/linux/alsa/JackAlsaAdapter.cpp
++++ b/linux/alsa/JackAlsaAdapter.cpp
+@@ -187,108 +187,40 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
+-
+- strcpy ( desc->name, "audioadapter" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy ( desc->desc, "netjack audio <==> net backend adapter" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 11;
+- desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
+-
+- i = 0;
+- strcpy ( desc->params[i].name, "capture" );
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "none" );
+- strcpy ( desc->params[i].short_desc,
+- "Provide capture ports. Optionally set device" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "playback" );
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "none" );
+- strcpy ( desc->params[i].short_desc,
+- "Provide playback ports. Optionally set device" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "device" );
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy ( desc->params[i].value.str, "hw:0" );
+- strcpy ( desc->params[i].short_desc, "ALSA device name" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "rate" );
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 48000U;
+- strcpy ( desc->params[i].short_desc, "Sample rate" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "periodsize" );
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 512U;
+- strcpy ( desc->params[i].short_desc, "Period size" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "nperiods" );
+- desc->params[i].character = 'n';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 2U;
+- strcpy ( desc->params[i].short_desc, "Number of periods of playback latency" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "duplex" );
+- desc->params[i].character = 'D';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = true;
+- strcpy ( desc->params[i].short_desc,
+- "Provide both capture and playback ports" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "inchannels" );
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy ( desc->params[i].short_desc,
+- "Number of capture channels (defaults to hardware max)" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy ( desc->params[i].name, "outchannels" );
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy ( desc->params[i].short_desc,
+- "Number of playback channels (defaults to hardware max)" );
+- strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
+-
+- i++;
+- strcpy(desc->params[i].name, "quality");
+- desc->params[i].character = 'q';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ring-buffer");
+- desc->params[i].character = 'g';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 32768;
+- strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
+- strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
++
++ strcpy(value.str, "none");
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set device", NULL);
++
++ strcpy(value.str, "hw:0");
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "ALSA device name", NULL);
++
++ value.ui = 48000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = 512U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL);
++
++ value.ui = 2U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
++
++ value.i = true;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamUInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
++
++ value.ui = 32768;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamUInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
+
+ return desc;
+ }
+--- a/linux/alsa/JackAlsaAdapter.h
++++ b/linux/alsa/JackAlsaAdapter.h
+@@ -622,7 +622,7 @@
+ #include "JackCompilerDeps.h"
+ #include "driver_interface.h"
+
+- EXPORT jack_driver_desc_t* jack_get_descriptor();
++SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor();
+
+ #ifdef __cplusplus
+ }
+--- a/linux/alsa/JackAlsaDriver.cpp
++++ b/linux/alsa/JackAlsaDriver.cpp
+@@ -55,8 +55,11 @@
+ ((alsa_driver_t *)fDriver)->frame_rate);
+
+ if (res == 0) { // update fEngineControl and fGraphManager
+- JackAudioDriver::SetBufferSize(buffer_size); // never fails
++ JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
++ // ALSA specific
++ UpdateLatencies();
+ } else {
++ // Restore old values
+ alsa_driver_reset_parameters((alsa_driver_t *)fDriver, fEngineControl->fBufferSize,
+ ((alsa_driver_t *)fDriver)->user_nperiods,
+ ((alsa_driver_t *)fDriver)->frame_rate);
+@@ -65,14 +68,36 @@
+ return res;
+ }
+
++void JackAlsaDriver::UpdateLatencies()
++{
++ jack_latency_range_t range;
++ alsa_driver_t* alsa_driver = (alsa_driver_t*)fDriver;
++
++ for (int i = 0; i < fCaptureChannels; i++) {
++ range.min = range.max = alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency;
++ fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &range);
++ }
++
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ // Add one buffer more latency if "async" mode is used...
++ range.min = range.max = (alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) +
++ ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency;
++ fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &range);
++ // Monitor port
++ if (fWithMonitorPorts) {
++ range.min = range.max = alsa_driver->frames_per_cycle;
++ fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &range);
++ }
++ }
++}
++
+ int JackAlsaDriver::Attach()
+ {
+ JackPort* port;
+- int port_index;
++ jack_port_id_t port_index;
+ unsigned long port_flags = (unsigned long)CaptureDriverFlags;
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- jack_latency_range_t range;
++ char name[REAL_JACK_PORT_NAME_SIZE];
++ char alias[REAL_JACK_PORT_NAME_SIZE];
+
+ assert(fCaptureChannels < DRIVER_PORT_NUM);
+ assert(fPlaybackChannels < DRIVER_PORT_NUM);
+@@ -89,16 +114,14 @@
+ jack_log("JackAlsaDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
+
+ for (int i = 0; i < fCaptureChannels; i++) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
+- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(alias, sizeof(alias), "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
++ snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+ port = fGraphManager->GetPort(port_index);
+ port->SetAlias(alias);
+- range.min = range.max = alsa_driver->frames_per_cycle + alsa_driver->capture_frame_latency;
+- port->SetLatencyRange(JackCaptureLatency, &range);
+ fCapturePortList[i] = port_index;
+ jack_log("JackAlsaDriver::Attach fCapturePortList[i] %ld ", port_index);
+ }
+@@ -106,37 +129,31 @@
+ port_flags = (unsigned long)PlaybackDriverFlags;
+
+ for (int i = 0; i < fPlaybackChannels; i++) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
+- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(alias, sizeof(alias), "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
++ snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", name);
+ return -1;
+ }
+ port = fGraphManager->GetPort(port_index);
+ port->SetAlias(alias);
+- // Add one buffer more latency if "async" mode is used...
+- range.min = range.max = (alsa_driver->frames_per_cycle * (alsa_driver->user_nperiods - 1)) +
+- ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + alsa_driver->playback_frame_latency;
+-
+- port->SetLatencyRange(JackPlaybackLatency, &range);
+ fPlaybackPortList[i] = port_index;
+ jack_log("JackAlsaDriver::Attach fPlaybackPortList[i] %ld ", port_index);
+
+ // Monitor ports
+ if (fWithMonitorPorts) {
+ jack_log("Create monitor port");
+- snprintf(name, sizeof(name) - 1, "%s:monitor_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
+- jack_error ("ALSA: cannot register monitor port for %s", name);
++ snprintf(name, sizeof(name), "%s:monitor_%d", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
++ jack_error("ALSA: cannot register monitor port for %s", name);
+ } else {
+- port = fGraphManager->GetPort(port_index);
+- range.min = range.max = alsa_driver->frames_per_cycle;
+- port->SetLatencyRange(JackCaptureLatency, &range);
+ fMonitorPortList[i] = port_index;
+ }
+ }
+ }
+
++ UpdateLatencies();
++
+ if (alsa_driver->midi) {
+ int err = (alsa_driver->midi->attach)(alsa_driver->midi);
+ if (err)
+@@ -256,26 +273,27 @@
+ else if (strcmp(midi_driver_name, "raw") == 0)
+ midi = alsa_rawmidi_new((jack_client_t*)this);
+
+- if (JackServerGlobals::on_device_acquire != NULL)
+- {
++ if (JackServerGlobals::on_device_acquire != NULL) {
+ int capture_card = card_to_num(capture_driver_name);
+ int playback_card = card_to_num(playback_driver_name);
+ char audio_name[32];
+
+- snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", capture_card);
++ snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card);
+ if (!JackServerGlobals::on_device_acquire(audio_name)) {
+- jack_error("Audio device %s cannot be acquired, trying to open it anyway...", capture_driver_name);
++ jack_error("Audio device %s cannot be acquired...", capture_driver_name);
++ return -1;
+ }
+
+ if (playback_card != capture_card) {
+- snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", playback_card);
++ snprintf(audio_name, sizeof(audio_name), "Audio%d", playback_card);
+ if (!JackServerGlobals::on_device_acquire(audio_name)) {
+- jack_error("Audio device %s cannot be acquired, trying to open it anyway...", playback_driver_name);
++ jack_error("Audio device %s cannot be acquired...", playback_driver_name);
++ return -1;
+ }
+ }
+ }
+
+- fDriver = alsa_driver_new ("alsa_pcm", (char*)playback_driver_name, (char*)capture_driver_name,
++ fDriver = alsa_driver_new ((char*)"alsa_pcm", (char*)playback_driver_name, (char*)capture_driver_name,
+ NULL,
+ nframes,
+ user_nperiods,
+@@ -316,13 +334,13 @@
+ char audio_name[32];
+ int capture_card = card_to_num(fCaptureDriverName);
+ if (capture_card >= 0) {
+- snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", capture_card);
++ snprintf(audio_name, sizeof(audio_name), "Audio%d", capture_card);
+ JackServerGlobals::on_device_release(audio_name);
+ }
+
+ int playback_card = card_to_num(fPlaybackDriverName);
+ if (playback_card >= 0 && playback_card != capture_card) {
+- snprintf(audio_name, sizeof(audio_name) - 1, "Audio%d", playback_card);
++ snprintf(audio_name, sizeof(audio_name), "Audio%d", playback_card);
+ JackServerGlobals::on_device_release(audio_name);
+ }
+ }
+@@ -556,7 +574,7 @@
+
+ while(snd_card_next(&card_no) >= 0 && card_no >= 0)
+ {
+- sprintf(card_id, "hw:%d", card_no);
++ snprintf(card_id, sizeof(card_id), "hw:%d", card_no);
+
+ if (snd_ctl_open(&handle, card_id, 0) >= 0 &&
+ snd_ctl_card_info(handle, info) >= 0)
+@@ -567,7 +585,7 @@
+
+ while (snd_ctl_pcm_next_device(handle, &device_no) >= 0 && device_no != -1)
+ {
+- sprintf(device_id, "%s,%d", card_id, device_no);
++ snprintf(device_id, sizeof(device_id), "%s,%d", card_id, device_no);
+
+ snd_pcm_info_set_device(pcminfo_capture, device_no);
+ snd_pcm_info_set_subdevice(pcminfo_capture, 0);
+@@ -708,179 +726,84 @@
+ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor ()
+ {
+ jack_driver_desc_t * desc;
+- jack_driver_param_desc_t * params;
+- unsigned int i;
+-
+- desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
+
+- strcpy(desc->name, "alsa"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Linux ALSA API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
++ desc = jack_driver_descriptor_construct("alsa", JackDriverMaster, "Linux ALSA API based audio backend", &filler);
+
+- desc->nparams = 18;
+- params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy (params[i].name, "capture");
+- params[i].character = 'C';
+- params[i].type = JackDriverParamString;
+- strcpy (params[i].value.str, "none");
+- strcpy (params[i].short_desc,
+- "Provide capture ports. Optionally set device");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "playback");
+- params[i].character = 'P';
+- params[i].type = JackDriverParamString;
+- strcpy (params[i].value.str, "none");
+- strcpy (params[i].short_desc,
+- "Provide playback ports. Optionally set device");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "device");
+- params[i].character = 'd';
+- params[i].type = JackDriverParamString;
+- strcpy (params[i].value.str, "hw:0");
+- strcpy (params[i].short_desc, "ALSA device name");
+- strcpy (params[i].long_desc, params[i].short_desc);
+- params[i].constraint = enum_alsa_devices();
+-
+- i++;
+- strcpy (params[i].name, "rate");
+- params[i].character = 'r';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 48000U;
+- strcpy (params[i].short_desc, "Sample rate");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "period");
+- params[i].character = 'p';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1024U;
+- strcpy (params[i].short_desc, "Frames per period");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "nperiods");
+- params[i].character = 'n';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 2U;
+- strcpy (params[i].short_desc, "Number of periods of playback latency");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "hwmon");
+- params[i].character = 'H';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Hardware monitoring, if available");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "hwmeter");
+- params[i].character = 'M';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Hardware metering, if available");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "duplex");
+- params[i].character = 'D';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 1;
+- strcpy (params[i].short_desc,
+- "Provide both capture and playback ports");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "softmode");
+- params[i].character = 's';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Soft-mode, no xrun handling");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "monitor");
+- params[i].character = 'm';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Provide monitor ports for the output");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "dither");
+- params[i].character = 'z';
+- params[i].type = JackDriverParamChar;
+- params[i].value.c = 'n';
+- strcpy (params[i].short_desc, "Dithering mode");
+- strcpy (params[i].long_desc,
+- "Dithering mode:\n"
+- " n - none\n"
+- " r - rectangular\n"
+- " s - shaped\n"
+- " t - triangular");
+- params[i].constraint = get_dither_constraint();
+-
+- i++;
+- strcpy (params[i].name, "inchannels");
+- params[i].character = 'i';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc,
+- "Number of capture channels (defaults to hardware max)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "outchannels");
+- params[i].character = 'o';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc,
+- "Number of playback channels (defaults to hardware max)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "shorts");
+- params[i].character = 'S';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = FALSE;
+- strcpy (params[i].short_desc, "Try 16-bit samples before 32-bit");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "input-latency");
+- params[i].character = 'I';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Extra input latency (frames)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "output-latency");
+- params[i].character = 'O';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Extra output latency (frames)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "midi-driver");
+- params[i].character = 'X';
+- params[i].type = JackDriverParamString;
+- strcpy (params[i].value.str, "none");
+- strcpy (params[i].short_desc, "ALSA MIDI driver name (seq|raw)");
+- strcpy (params[i].long_desc,
+- "ALSA MIDI driver:\n"
+- " none - no MIDI driver\n"
+- " seq - ALSA Sequencer driver\n"
+- " raw - ALSA RawMIDI driver\n");
+- params[i].constraint = get_midi_driver_constraint();
++ strcpy(value.str, "none");
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set device", NULL);
++
++ strcpy(value.str, "hw:0");
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices(), "ALSA device name", NULL);
++
++ value.ui = 48000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = 1024U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = 2U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "hwmon", 'H', JackDriverParamBool, &value, NULL, "Hardware monitoring, if available", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "hwmeter", 'M', JackDriverParamBool, &value, NULL, "Hardware metering, if available", NULL);
++
++ value.i = 1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "softmode", 's', JackDriverParamBool, &value, NULL, "Soft-mode, no xrun handling", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
++
++ value.c = 'n';
++ jack_driver_descriptor_add_parameter(
++ desc,
++ &filler,
++ "dither",
++ 'z',
++ JackDriverParamChar,
++ &value,
++ get_dither_constraint(),
++ "Dithering mode",
++ "Dithering mode:\n"
++ " n - none\n"
++ " r - rectangular\n"
++ " s - shaped\n"
++ " t - triangular");
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamInt, &value, NULL, "Number of capture channels (defaults to hardware max)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamInt, &value, NULL, "Number of playback channels (defaults to hardware max)", NULL);
++
++ value.i = FALSE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "shorts", 'S', JackDriverParamBool, &value, NULL, "Try 16-bit samples before 32-bit", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
++
++ strcpy(value.str, "none");
++ jack_driver_descriptor_add_parameter(
++ desc,
++ &filler,
++ "midi-driver",
++ 'X',
++ JackDriverParamString,
++ &value,
++ get_midi_driver_constraint(),
++ "ALSA device name",
++ "ALSA MIDI driver:\n"
++ " none - no MIDI driver\n"
++ " seq - ALSA Sequencer driver\n"
++ " raw - ALSA RawMIDI driver\n");
+
+- desc->params = params;
+ return desc;
+ }
+
+--- a/linux/alsa/JackAlsaDriver.h
++++ b/linux/alsa/JackAlsaDriver.h
+@@ -42,6 +42,8 @@
+ int fReservedCaptureDevice;
+ int fReservedPlaybackDevice;
+
++ void UpdateLatencies();
++
+ public:
+
+ JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiDriver.cpp
+@@ -0,0 +1,653 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <memory>
++#include <new>
++#include <stdexcept>
++
++#include <alsa/asoundlib.h>
++
++#include "JackALSARawMidiDriver.h"
++#include "JackALSARawMidiUtil.h"
++#include "JackEngineControl.h"
++#include "JackError.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackALSARawMidiDriver;
++
++JackALSARawMidiDriver::JackALSARawMidiDriver(const char *name,
++ const char *alias,
++ JackLockedEngine *engine,
++ JackSynchro *table):
++ JackMidiDriver(name, alias, engine, table)
++{
++ thread = new JackThread(this);
++ fds[0] = -1;
++ fds[1] = -1;
++ input_ports = 0;
++ output_ports = 0;
++ output_port_timeouts = 0;
++ poll_fds = 0;
++}
++
++JackALSARawMidiDriver::~JackALSARawMidiDriver()
++{
++ delete thread;
++}
++
++int
++JackALSARawMidiDriver::Attach()
++{
++ const char *alias;
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ jack_port_id_t index;
++ jack_nframes_t latency = buffer_size;
++ jack_latency_range_t latency_range;
++ const char *name;
++ JackPort *port;
++ latency_range.max = latency;
++ latency_range.min = latency;
++ for (int i = 0; i < fCaptureChannels; i++) {
++ JackALSARawMidiInputPort *input_port = input_ports[i];
++ name = input_port->GetName();
++ fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ CaptureDriverFlags, buffer_size, &index);
++ if (index == NO_PORT) {
++ jack_error("JackALSARawMidiDriver::Attach - cannot register input "
++ "port with name '%s'.", name);
++ // XX: Do we need to deallocate ports?
++ return -1;
++ }
++ alias = input_port->GetAlias();
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(alias);
++ port->SetLatencyRange(JackCaptureLatency, &latency_range);
++ fCapturePortList[i] = index;
++
++ jack_info("JackALSARawMidiDriver::Attach - input port registered "
++ "(name='%s', alias='%s').", name, alias);
++ }
++ if (! fEngineControl->fSyncMode) {
++ latency += buffer_size;
++ latency_range.max = latency;
++ latency_range.min = latency;
++ }
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ JackALSARawMidiOutputPort *output_port = output_ports[i];
++ name = output_port->GetName();
++ fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ PlaybackDriverFlags, buffer_size, &index);
++ if (index == NO_PORT) {
++ jack_error("JackALSARawMidiDriver::Attach - cannot register "
++ "output port with name '%s'.", name);
++ // XX: Do we need to deallocate ports?
++ return -1;
++ }
++ alias = output_port->GetAlias();
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(alias);
++ port->SetLatencyRange(JackPlaybackLatency, &latency_range);
++ fPlaybackPortList[i] = index;
++
++ jack_info("JackALSARawMidiDriver::Attach - output port registered "
++ "(name='%s', alias='%s').", name, alias);
++ }
++ return 0;
++}
++
++int
++JackALSARawMidiDriver::Close()
++{
++ // Generic MIDI driver close
++ int result = JackMidiDriver::Close();
++
++ if (input_ports) {
++ for (int i = 0; i < fCaptureChannels; i++) {
++ delete input_ports[i];
++ }
++ delete[] input_ports;
++ input_ports = 0;
++ }
++ if (output_ports) {
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ delete output_ports[i];
++ }
++ delete[] output_ports;
++ output_ports = 0;
++ }
++ return result;
++}
++
++bool
++JackALSARawMidiDriver::Execute()
++{
++ jack_nframes_t timeout_frame = 0;
++ for (;;) {
++ struct timespec timeout;
++ struct timespec *timeout_ptr;
++ if (! timeout_frame) {
++ timeout_ptr = 0;
++ } else {
++
++ // The timeout value is relative to the time that
++ // 'GetMicroSeconds()' is called, not the time that 'poll()' is
++ // called. This means that the amount of time that passes between
++ // 'GetMicroSeconds()' and 'ppoll()' is time that will be lost
++ // while waiting for 'poll() to timeout.
++ //
++ // I tried to replace the timeout with a 'timerfd' with absolute
++ // times, but, strangely, it actually slowed things down, and made
++ // the code a lot more complicated.
++ //
++ // I wonder about using the 'epoll' interface instead of 'ppoll()'.
++ // The problem with the 'epoll' interface is that the timeout
++ // resolution of 'epoll_wait()' is set in milliseconds. We need
++ // microsecond resolution. Without microsecond resolution, we
++ // impose the same jitter as USB MIDI.
++ //
++ // Another problem is that 'ppoll()' returns later than the wait
++ // time. The problem can be minimized with high precision timers.
++
++ timeout_ptr = &timeout;
++ jack_time_t next_time = GetTimeFromFrames(timeout_frame);
++ jack_time_t now = GetMicroSeconds();
++ if (next_time <= now) {
++ timeout.tv_sec = 0;
++ timeout.tv_nsec = 0;
++ } else {
++ jack_time_t wait_time = next_time - now;
++ timeout.tv_sec = wait_time / 1000000;
++ timeout.tv_nsec = (wait_time % 1000000) * 1000;
++ }
++ }
++ int poll_result = ppoll(poll_fds, poll_fd_count, timeout_ptr, 0);
++
++ // Getting the current frame value here allows us to use it for
++ // incoming MIDI bytes. This makes sense, as the data has already
++ // arrived at this point.
++ jack_nframes_t current_frame = GetCurrentFrame();
++
++ if (poll_result == -1) {
++ if (errno == EINTR) {
++ continue;
++ }
++ jack_error("JackALSARawMidiDriver::Execute - poll error: %s",
++ strerror(errno));
++ break;
++ }
++ jack_nframes_t port_timeout;
++ timeout_frame = 0;
++ if (! poll_result) {
++
++ // No I/O events occurred. So, only handle timeout events on
++ // output ports.
++
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ port_timeout = output_port_timeouts[i];
++ if (port_timeout && (port_timeout <= current_frame)) {
++ if (! output_ports[i]->ProcessPollEvents(false, true,
++ &port_timeout)) {
++ jack_error("JackALSARawMidiDriver::Execute - a fatal "
++ "error occurred while processing ALSA "
++ "output events.");
++ goto cleanup;
++ }
++ output_port_timeouts[i] = port_timeout;
++ }
++ if (port_timeout && ((! timeout_frame) ||
++ (port_timeout < timeout_frame))) {
++ timeout_frame = port_timeout;
++ }
++ }
++ continue;
++ }
++
++ // See if it's time to shutdown.
++
++ unsigned short revents = poll_fds[0].revents;
++ if (revents) {
++ if (revents & (~ POLLHUP)) {
++ jack_error("JackALSARawMidiDriver::Execute - unexpected poll "
++ "event on pipe file descriptor.");
++ }
++ break;
++ }
++
++ // Handle I/O events *and* timeout events on output ports.
++
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ port_timeout = output_port_timeouts[i];
++ bool timeout = port_timeout && (port_timeout <= current_frame);
++ if (! output_ports[i]->ProcessPollEvents(true, timeout,
++ &port_timeout)) {
++ jack_error("JackALSARawMidiDriver::Execute - a fatal error "
++ "occurred while processing ALSA output events.");
++ goto cleanup;
++ }
++ output_port_timeouts[i] = port_timeout;
++ if (port_timeout && ((! timeout_frame) ||
++ (port_timeout < timeout_frame))) {
++ timeout_frame = port_timeout;
++ }
++ }
++
++ // Handle I/O events on input ports. We handle these last because we
++ // already computed the arrival time above, and will impose a delay on
++ // the events by 'period-size' frames anyway, which gives us a bit of
++ // borrowed time.
++
++ for (int i = 0; i < fCaptureChannels; i++) {
++ if (! input_ports[i]->ProcessPollEvents(current_frame)) {
++ jack_error("JackALSARawMidiDriver::Execute - a fatal error "
++ "occurred while processing ALSA input events.");
++ goto cleanup;
++ }
++ }
++ }
++ cleanup:
++ close(fds[0]);
++ fds[0] = -1;
++
++ jack_info("JackALSARawMidiDriver::Execute - ALSA thread exiting.");
++
++ return false;
++}
++
++void
++JackALSARawMidiDriver::
++FreeDeviceInfo(std::vector<snd_rawmidi_info_t *> *in_info_list,
++ std::vector<snd_rawmidi_info_t *> *out_info_list)
++{
++ size_t length = in_info_list->size();
++ for (size_t i = 0; i < length; i++) {
++ snd_rawmidi_info_free(in_info_list->at(i));
++ }
++ length = out_info_list->size();
++ for (size_t i = 0; i < length; i++) {
++ snd_rawmidi_info_free(out_info_list->at(i));
++ }
++}
++
++void
++JackALSARawMidiDriver::
++GetDeviceInfo(snd_ctl_t *control, snd_rawmidi_info_t *info,
++ std::vector<snd_rawmidi_info_t *> *info_list)
++{
++ snd_rawmidi_info_set_subdevice(info, 0);
++ int code = snd_ctl_rawmidi_info(control, info);
++ if (code) {
++ if (code != -ENOENT) {
++ HandleALSAError("GetDeviceInfo", "snd_ctl_rawmidi_info", code);
++ }
++ return;
++ }
++ unsigned int count = snd_rawmidi_info_get_subdevices_count(info);
++ for (unsigned int i = 0; i < count; i++) {
++ snd_rawmidi_info_set_subdevice(info, i);
++ int code = snd_ctl_rawmidi_info(control, info);
++ if (code) {
++ HandleALSAError("GetDeviceInfo", "snd_ctl_rawmidi_info", code);
++ continue;
++ }
++ snd_rawmidi_info_t *info_copy;
++ code = snd_rawmidi_info_malloc(&info_copy);
++ if (code) {
++ HandleALSAError("GetDeviceInfo", "snd_rawmidi_info_malloc", code);
++ continue;
++ }
++ snd_rawmidi_info_copy(info_copy, info);
++ try {
++ info_list->push_back(info_copy);
++ } catch (std::bad_alloc &e) {
++ snd_rawmidi_info_free(info_copy);
++ jack_error("JackALSARawMidiDriver::GetDeviceInfo - "
++ "std::vector::push_back: %s", e.what());
++ }
++ }
++}
++
++void
++JackALSARawMidiDriver::HandleALSAError(const char *driver_func,
++ const char *alsa_func, int code)
++{
++ jack_error("JackALSARawMidiDriver::%s - %s: %s", driver_func, alsa_func,
++ snd_strerror(code));
++}
++
++bool
++JackALSARawMidiDriver::Init()
++{
++ set_threaded_log_function();
++ if (thread->AcquireSelfRealTime(fEngineControl->fServerPriority + 1)) {
++ jack_error("JackALSARawMidiDriver::Init - could not acquire realtime "
++ "scheduling. Continuing anyway.");
++ }
++ return true;
++}
++
++int
++JackALSARawMidiDriver::Open(bool capturing, bool playing, int in_channels,
++ int out_channels, bool monitor,
++ const char *capture_driver_name,
++ const char *playback_driver_name,
++ jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency)
++{
++ snd_rawmidi_info_t *info;
++ int code = snd_rawmidi_info_malloc(&info);
++ if (code) {
++ HandleALSAError("Open", "snd_rawmidi_info_malloc", code);
++ return -1;
++ }
++ std::vector<snd_rawmidi_info_t *> in_info_list;
++ std::vector<snd_rawmidi_info_t *> out_info_list;
++ for (int card = -1;;) {
++ int code = snd_card_next(&card);
++ if (code) {
++ HandleALSAError("Open", "snd_card_next", code);
++ continue;
++ }
++ if (card == -1) {
++ break;
++ }
++ char name[32];
++ snprintf(name, sizeof(name), "hw:%d", card);
++ snd_ctl_t *control;
++ code = snd_ctl_open(&control, name, SND_CTL_NONBLOCK);
++ if (code) {
++ HandleALSAError("Open", "snd_ctl_open", code);
++ continue;
++ }
++ for (int device = -1;;) {
++ code = snd_ctl_rawmidi_next_device(control, &device);
++ if (code) {
++ HandleALSAError("Open", "snd_ctl_rawmidi_next_device", code);
++ continue;
++ }
++ if (device == -1) {
++ break;
++ }
++ snd_rawmidi_info_set_device(info, device);
++ snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_INPUT);
++ GetDeviceInfo(control, info, &in_info_list);
++ snd_rawmidi_info_set_stream(info, SND_RAWMIDI_STREAM_OUTPUT);
++ GetDeviceInfo(control, info, &out_info_list);
++ }
++ snd_ctl_close(control);
++ }
++ snd_rawmidi_info_free(info);
++ size_t potential_inputs = in_info_list.size();
++ size_t potential_outputs = out_info_list.size();
++ if (! (potential_inputs || potential_outputs)) {
++ jack_error("JackALSARawMidiDriver::Open - no ALSA raw MIDI input or "
++ "output ports found.");
++ FreeDeviceInfo(&in_info_list, &out_info_list);
++ return -1;
++ }
++ size_t num_inputs = 0;
++ size_t num_outputs = 0;
++ if (potential_inputs) {
++ try {
++ input_ports = new JackALSARawMidiInputPort *[potential_inputs];
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Open - while creating input "
++ "port array: %s", e.what());
++ FreeDeviceInfo(&in_info_list, &out_info_list);
++ return -1;
++ }
++ }
++ if (potential_outputs) {
++ try {
++ output_ports = new JackALSARawMidiOutputPort *[potential_outputs];
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Open - while creating output "
++ "port array: %s", e.what());
++ FreeDeviceInfo(&in_info_list, &out_info_list);
++ goto delete_input_ports;
++ }
++ }
++ for (size_t i = 0; i < potential_inputs; i++) {
++ snd_rawmidi_info_t *info = in_info_list.at(i);
++ try {
++ input_ports[num_inputs] = new JackALSARawMidiInputPort(info, i);
++ num_inputs++;
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Open - while creating new "
++ "JackALSARawMidiInputPort: %s", e.what());
++ }
++ snd_rawmidi_info_free(info);
++ }
++ for (size_t i = 0; i < potential_outputs; i++) {
++ snd_rawmidi_info_t *info = out_info_list.at(i);
++ try {
++ output_ports[num_outputs] = new JackALSARawMidiOutputPort(info, i);
++ num_outputs++;
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Open - while creating new "
++ "JackALSARawMidiOutputPort: %s", e.what());
++ }
++ snd_rawmidi_info_free(info);
++ }
++ if (! (num_inputs || num_outputs)) {
++ jack_error("JackALSARawMidiDriver::Open - none of the potential "
++ "inputs or outputs were successfully opened.");
++ } else if (JackMidiDriver::Open(capturing, playing, num_inputs,
++ num_outputs, monitor, capture_driver_name,
++ playback_driver_name, capture_latency,
++ playback_latency)) {
++ jack_error("JackALSARawMidiDriver::Open - JackMidiDriver::Open error");
++ } else {
++ return 0;
++ }
++ if (output_ports) {
++ for (size_t i = 0; i < num_outputs; i++) {
++ delete output_ports[i];
++ }
++ delete[] output_ports;
++ output_ports = 0;
++ }
++ delete_input_ports:
++ if (input_ports) {
++ for (size_t i = 0; i < num_inputs; i++) {
++ delete input_ports[i];
++ }
++ delete[] input_ports;
++ input_ports = 0;
++ }
++ return -1;
++}
++
++int
++JackALSARawMidiDriver::Read()
++{
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ for (int i = 0; i < fCaptureChannels; i++) {
++ if (! input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size)) {
++ return -1;
++ }
++ }
++ return 0;
++}
++
++int
++JackALSARawMidiDriver::Start()
++{
++
++ jack_info("JackALSARawMidiDriver::Start - Starting 'alsarawmidi' driver.");
++
++ JackMidiDriver::Start();
++ poll_fd_count = 1;
++ for (int i = 0; i < fCaptureChannels; i++) {
++ poll_fd_count += input_ports[i]->GetPollDescriptorCount();
++ }
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ poll_fd_count += output_ports[i]->GetPollDescriptorCount();
++ }
++ try {
++ poll_fds = new pollfd[poll_fd_count];
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Start - creating poll descriptor "
++ "structures failed: %s", e.what());
++ return -1;
++ }
++ if (fPlaybackChannels) {
++ try {
++ output_port_timeouts = new jack_nframes_t[fPlaybackChannels];
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Start - creating array for "
++ "output port timeout values failed: %s", e.what());
++ goto free_poll_descriptors;
++ }
++ }
++ struct pollfd *poll_fd_iter;
++ try {
++ CreateNonBlockingPipe(fds);
++ } catch (std::exception e) {
++ jack_error("JackALSARawMidiDriver::Start - while creating wake pipe: "
++ "%s", e.what());
++ goto free_output_port_timeouts;
++ }
++ poll_fds[0].events = POLLERR | POLLIN | POLLNVAL;
++ poll_fds[0].fd = fds[0];
++ poll_fd_iter = poll_fds + 1;
++ for (int i = 0; i < fCaptureChannels; i++) {
++ JackALSARawMidiInputPort *input_port = input_ports[i];
++ input_port->PopulatePollDescriptors(poll_fd_iter);
++ poll_fd_iter += input_port->GetPollDescriptorCount();
++ }
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ JackALSARawMidiOutputPort *output_port = output_ports[i];
++ output_port->PopulatePollDescriptors(poll_fd_iter);
++ poll_fd_iter += output_port->GetPollDescriptorCount();
++ output_port_timeouts[i] = 0;
++ }
++
++ jack_info("JackALSARawMidiDriver::Start - starting ALSA thread ...");
++
++ if (! thread->StartSync()) {
++
++ jack_info("JackALSARawMidiDriver::Start - started ALSA thread.");
++
++ return 0;
++ }
++ jack_error("JackALSARawMidiDriver::Start - failed to start MIDI "
++ "processing thread.");
++
++ DestroyNonBlockingPipe(fds);
++ fds[1] = -1;
++ fds[0] = -1;
++ free_output_port_timeouts:
++ delete[] output_port_timeouts;
++ output_port_timeouts = 0;
++ free_poll_descriptors:
++ delete[] poll_fds;
++ poll_fds = 0;
++ return -1;
++}
++
++int
++JackALSARawMidiDriver::Stop()
++{
++ jack_info("JackALSARawMidiDriver::Stop - stopping 'alsarawmidi' driver.");
++ JackMidiDriver::Stop();
++
++ if (fds[1] != -1) {
++ close(fds[1]);
++ fds[1] = -1;
++ }
++ int result;
++ const char *verb;
++ switch (thread->GetStatus()) {
++ case JackThread::kIniting:
++ case JackThread::kStarting:
++ result = thread->Kill();
++ verb = "kill";
++ break;
++ case JackThread::kRunning:
++ result = thread->Stop();
++ verb = "stop";
++ break;
++ default:
++ result = 0;
++ verb = 0;
++ }
++ if (fds[0] != -1) {
++ close(fds[0]);
++ fds[0] = -1;
++ }
++ if (output_port_timeouts) {
++ delete[] output_port_timeouts;
++ output_port_timeouts = 0;
++ }
++ if (poll_fds) {
++ delete[] poll_fds;
++ poll_fds = 0;
++ }
++ if (result) {
++ jack_error("JackALSARawMidiDriver::Stop - could not %s MIDI "
++ "processing thread.", verb);
++ }
++ return result;
++}
++
++int
++JackALSARawMidiDriver::Write()
++{
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ if (! output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size)) {
++ return -1;
++ }
++ }
++ return 0;
++}
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++ SERVER_EXPORT jack_driver_desc_t *
++ driver_get_descriptor()
++ {
++ // X: There could be parameters here regarding setting I/O buffer
++ // sizes. I don't think MIDI drivers can accept parameters right
++ // now without being set as the main driver.
++
++ return jack_driver_descriptor_construct("alsarawmidi", JackDriverSlave, "Alternative ALSA raw MIDI backend.", NULL);
++ }
++
++ SERVER_EXPORT Jack::JackDriverClientInterface *
++ driver_initialize(Jack::JackLockedEngine *engine, Jack::JackSynchro *table,
++ const JSList *params)
++ {
++ Jack::JackDriverClientInterface *driver =
++ new Jack::JackALSARawMidiDriver("system_midi", "alsarawmidi",
++ engine, table);
++ if (driver->Open(1, 1, 0, 0, false, "midi in", "midi out", 0, 0)) {
++ delete driver;
++ driver = 0;
++ }
++ return driver;
++ }
++
++#ifdef __cplusplus
++}
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiDriver.h
+@@ -0,0 +1,100 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiDriver__
++#define __JackALSARawMidiDriver__
++
++#include <vector>
++
++#include <alsa/asoundlib.h>
++#include <poll.h>
++
++#include "JackALSARawMidiInputPort.h"
++#include "JackALSARawMidiOutputPort.h"
++#include "JackMidiDriver.h"
++#include "JackThread.h"
++
++namespace Jack {
++
++ class JackALSARawMidiDriver:
++ public JackMidiDriver, public JackRunnableInterface {
++
++ private:
++
++ int fds[2];
++ JackALSARawMidiInputPort **input_ports;
++ JackALSARawMidiOutputPort **output_ports;
++ jack_nframes_t *output_port_timeouts;
++ nfds_t poll_fd_count;
++ struct pollfd *poll_fds;
++ JackThread *thread;
++
++ void
++ FreeDeviceInfo(std::vector<snd_rawmidi_info_t *> *in_info_list,
++ std::vector<snd_rawmidi_info_t *> *out_info_list);
++
++ void
++ GetDeviceInfo(snd_ctl_t *control, snd_rawmidi_info_t *info,
++ std::vector<snd_rawmidi_info_t *> *info_list);
++
++ void
++ HandleALSAError(const char *driver_func, const char *alsa_func,
++ int code);
++
++ public:
++
++ JackALSARawMidiDriver(const char *name, const char *alias,
++ JackLockedEngine *engine, JackSynchro *table);
++ ~JackALSARawMidiDriver();
++
++ int
++ Attach();
++
++ int
++ Close();
++
++ bool
++ Execute();
++
++ bool
++ Init();
++
++ int
++ Open(bool capturing, bool playing, int in_channels, int out_channels,
++ bool monitoring, const char *capture_driver_name,
++ const char *playback_driver_name, jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency);
++
++ int
++ Read();
++
++ int
++ Start();
++
++ int
++ Stop();
++
++ int
++ Write();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiInputPort.cpp
+@@ -0,0 +1,122 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++#include <memory>
++
++#include "JackALSARawMidiInputPort.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackALSARawMidiInputPort;
++
++JackALSARawMidiInputPort::JackALSARawMidiInputPort(snd_rawmidi_info_t *info,
++ size_t index,
++ size_t max_bytes,
++ size_t max_messages):
++ JackALSARawMidiPort(info, index, POLLIN)
++{
++ alsa_event = 0;
++ jack_event = 0;
++ receive_queue = new JackALSARawMidiReceiveQueue(rawmidi, max_bytes);
++ std::auto_ptr<JackALSARawMidiReceiveQueue> receive_ptr(receive_queue);
++ thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
++ std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
++ write_queue = new JackMidiBufferWriteQueue();
++ std::auto_ptr<JackMidiBufferWriteQueue> write_ptr(write_queue);
++ raw_queue = new JackMidiRawInputWriteQueue(thread_queue, max_bytes,
++ max_messages);
++ write_ptr.release();
++ thread_ptr.release();
++ receive_ptr.release();
++}
++
++JackALSARawMidiInputPort::~JackALSARawMidiInputPort()
++{
++ delete raw_queue;
++ delete receive_queue;
++ delete thread_queue;
++ delete write_queue;
++}
++
++bool
++JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
++ jack_nframes_t frames)
++{
++ write_queue->ResetMidiBuffer(port_buffer, frames);
++ bool dequeued = false;
++ if (! jack_event) {
++ goto dequeue_event;
++ }
++ for (;;) {
++ switch (write_queue->EnqueueEvent(jack_event, frames)) {
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackALSARawMidiInputPort::ProcessJack - The write "
++ "queue couldn't enqueue a %d-byte event. Dropping "
++ "event.", jack_event->size);
++ // Fallthrough on purpose.
++ case JackMidiWriteQueue::OK:
++ break;
++ default:
++ goto trigger_queue_event;
++ }
++ dequeue_event:
++ jack_event = thread_queue->DequeueEvent();
++ if (! jack_event) {
++ break;
++ }
++ dequeued = true;
++ }
++ trigger_queue_event:
++ return dequeued ? TriggerQueueEvent() : true;
++}
++
++bool
++JackALSARawMidiInputPort::ProcessPollEvents(jack_nframes_t current_frame)
++{
++ if (GetQueuePollEvent() == -1) {
++ return false;
++ }
++ int io_event = GetIOPollEvent();
++ switch (io_event) {
++ case -1:
++ return false;
++ case 1:
++ alsa_event = receive_queue->DequeueEvent();
++ }
++ if (alsa_event) {
++ size_t size = alsa_event->size;
++ size_t space = raw_queue->GetAvailableSpace();
++ bool enough_room = space >= size;
++ if (enough_room) {
++ assert(raw_queue->EnqueueEvent(current_frame, size,
++ alsa_event->buffer) ==
++ JackMidiWriteQueue::OK);
++ alsa_event = 0;
++ } else if (space) {
++ assert(raw_queue->EnqueueEvent(current_frame, space,
++ alsa_event->buffer) ==
++ JackMidiWriteQueue::OK);
++ alsa_event->buffer += space;
++ alsa_event->size -= space;
++ }
++ SetIOEventsEnabled(enough_room);
++ }
++ raw_queue->Process();
++ return true;
++}
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiInputPort.h
+@@ -0,0 +1,60 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiInputPort__
++#define __JackALSARawMidiInputPort__
++
++#include "JackALSARawMidiPort.h"
++#include "JackALSARawMidiReceiveQueue.h"
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiBufferWriteQueue.h"
++#include "JackMidiRawInputWriteQueue.h"
++
++namespace Jack {
++
++ class JackALSARawMidiInputPort: public JackALSARawMidiPort {
++
++ private:
++
++ jack_midi_event_t *alsa_event;
++ jack_midi_event_t *jack_event;
++ JackMidiRawInputWriteQueue *raw_queue;
++ JackALSARawMidiReceiveQueue *receive_queue;
++ JackMidiAsyncQueue *thread_queue;
++ JackMidiBufferWriteQueue *write_queue;
++
++ public:
++
++ JackALSARawMidiInputPort(snd_rawmidi_info_t *info, size_t index,
++ size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackALSARawMidiInputPort();
++
++ bool
++ ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames);
++
++ bool
++ ProcessPollEvents(jack_nframes_t current_frame);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiOutputPort.cpp
+@@ -0,0 +1,146 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++#include <memory>
++
++#include "JackALSARawMidiOutputPort.h"
++
++using Jack::JackALSARawMidiOutputPort;
++
++JackALSARawMidiOutputPort::JackALSARawMidiOutputPort(snd_rawmidi_info_t *info,
++ size_t index,
++ size_t max_bytes_per_poll,
++ size_t max_bytes,
++ size_t max_messages):
++ JackALSARawMidiPort(info, index, POLLOUT)
++{
++ alsa_event = 0;
++ read_queue = new JackMidiBufferReadQueue();
++ std::auto_ptr<JackMidiBufferReadQueue> read_ptr(read_queue);
++ send_queue = new JackALSARawMidiSendQueue(rawmidi, max_bytes_per_poll);
++ std::auto_ptr<JackALSARawMidiSendQueue> send_ptr(send_queue);
++ thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
++ std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
++ raw_queue = new JackMidiRawOutputWriteQueue(send_queue, max_bytes,
++ max_messages, max_messages);
++ thread_ptr.release();
++ send_ptr.release();
++ read_ptr.release();
++}
++
++JackALSARawMidiOutputPort::~JackALSARawMidiOutputPort()
++{
++ delete raw_queue;
++ delete read_queue;
++ delete send_queue;
++ delete thread_queue;
++}
++
++bool
++JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
++ jack_nframes_t frames)
++{
++ read_queue->ResetMidiBuffer(port_buffer);
++ bool enqueued = false;
++ for (jack_midi_event_t *event = read_queue->DequeueEvent(); event;
++ event = read_queue->DequeueEvent()) {
++ switch (thread_queue->EnqueueEvent(event, frames)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++ jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
++ "queue doesn't have enough room to enqueue a %d-byte "
++ "event. Dropping event.", event->size);
++ continue;
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
++ "queue is too small to enqueue a %d-byte event. "
++ "Dropping event.", event->size);
++ continue;
++ default:
++ enqueued = true;
++ }
++ }
++ return enqueued ? TriggerQueueEvent() : true;
++}
++
++bool
++JackALSARawMidiOutputPort::ProcessPollEvents(bool handle_output, bool timeout,
++ jack_nframes_t *frame)
++{
++ int io_event;
++ int queue_event;
++ send_queue->ResetPollByteCount();
++ if (! handle_output) {
++ assert(timeout);
++ goto process_raw_queue;
++ }
++ io_event = GetIOPollEvent();
++ if (io_event == -1) {
++ return false;
++ }
++ queue_event = GetQueuePollEvent();
++ if (queue_event == -1) {
++ return false;
++ }
++ if (io_event || timeout) {
++ process_raw_queue:
++ // We call the 'Process' event early because there are events waiting
++ // to be processed that either need to be sent now, or before now.
++ raw_queue->Process();
++ } else if (! queue_event) {
++ return true;
++ }
++ if (! alsa_event) {
++ alsa_event = thread_queue->DequeueEvent();
++ }
++ for (; alsa_event; alsa_event = thread_queue->DequeueEvent()) {
++ switch (raw_queue->EnqueueEvent(alsa_event)) {
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackALSARawMidiOutputPort::ProcessQueues - The raw "
++ "output queue couldn't enqueue a %d-byte event. "
++ "Dropping event.", alsa_event->size);
++ // Fallthrough on purpose.
++ case JackMidiWriteQueue::OK:
++ continue;
++ default:
++ ;
++ }
++
++ // Try to free up some space by processing events early.
++ *frame = raw_queue->Process();
++
++ switch (raw_queue->EnqueueEvent(alsa_event)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++ goto set_io_events;
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ // This shouldn't happen.
++ assert(false);
++ default:
++ ;
++ }
++ }
++ *frame = raw_queue->Process();
++ set_io_events:
++ bool blocked = send_queue->IsBlocked();
++ SetIOEventsEnabled(blocked);
++ if (blocked) {
++ *frame = 0;
++ }
++ return true;
++}
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiOutputPort.h
+@@ -0,0 +1,61 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiOutputPort__
++#define __JackALSARawMidiOutputPort__
++
++#include "JackALSARawMidiPort.h"
++#include "JackALSARawMidiSendQueue.h"
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiBufferReadQueue.h"
++#include "JackMidiRawOutputWriteQueue.h"
++
++namespace Jack {
++
++ class JackALSARawMidiOutputPort: public JackALSARawMidiPort {
++
++ private:
++
++ jack_midi_event_t *alsa_event;
++ JackMidiRawOutputWriteQueue *raw_queue;
++ JackMidiBufferReadQueue *read_queue;
++ JackALSARawMidiSendQueue *send_queue;
++ JackMidiAsyncQueue *thread_queue;
++
++ public:
++
++ JackALSARawMidiOutputPort(snd_rawmidi_info_t *info, size_t index,
++ size_t max_bytes_per_poll=3,
++ size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackALSARawMidiOutputPort();
++
++ bool
++ ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames);
++
++ bool
++ ProcessPollEvents(bool handle_output, bool timeout,
++ jack_nframes_t *frame);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiPort.cpp
+@@ -0,0 +1,256 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++#include <stdexcept>
++#include <string>
++
++#include "JackALSARawMidiPort.h"
++#include "JackALSARawMidiUtil.h"
++#include "JackError.h"
++
++using Jack::JackALSARawMidiPort;
++
++JackALSARawMidiPort::JackALSARawMidiPort(snd_rawmidi_info_t *info,
++ size_t index, unsigned short io_mask)
++{
++ int card = snd_rawmidi_info_get_card(info);
++ unsigned int device = snd_rawmidi_info_get_device(info);
++ unsigned int subdevice = snd_rawmidi_info_get_subdevice(info);
++ char device_id[32];
++ snprintf(device_id, sizeof(device_id), "hw:%d,%d,%d", card, device,
++ subdevice);
++ const char *alias_suffix;
++ const char *error_message;
++ snd_rawmidi_t **in;
++ const char *name_prefix;
++ snd_rawmidi_t **out;
++ if (snd_rawmidi_info_get_stream(info) == SND_RAWMIDI_STREAM_OUTPUT) {
++ alias_suffix = "out";
++ in = 0;
++ name_prefix = "system:midi_playback_";
++ out = &rawmidi;
++ } else {
++ alias_suffix = "in";
++ in = &rawmidi;
++ name_prefix = "system:midi_capture_";
++ out = 0;
++ }
++ const char *func;
++ int code = snd_rawmidi_open(in, out, device_id, SND_RAWMIDI_NONBLOCK);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_open";
++ goto handle_error;
++ }
++ snd_rawmidi_params_t *params;
++ code = snd_rawmidi_params_malloc(¶ms);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_params_malloc";
++ goto close;
++ }
++ code = snd_rawmidi_params_current(rawmidi, params);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_params_current";
++ goto free_params;
++ }
++ code = snd_rawmidi_params_set_avail_min(rawmidi, params, 1);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_params_set_avail_min";
++ goto free_params;
++ }
++
++ // Minimum buffer size allowed by ALSA
++ code = snd_rawmidi_params_set_buffer_size(rawmidi, params, 32);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_params_set_buffer_size";
++ goto free_params;
++ }
++
++ code = snd_rawmidi_params_set_no_active_sensing(rawmidi, params, 1);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_params_set_no_active_sensing";
++ goto free_params;
++ }
++ code = snd_rawmidi_params(rawmidi, params);
++ if (code) {
++ error_message = snd_strerror(code);
++ func = "snd_rawmidi_params";
++ goto free_params;
++ }
++ snd_rawmidi_params_free(params);
++ alsa_poll_fd_count = snd_rawmidi_poll_descriptors_count(rawmidi);
++ if (! alsa_poll_fd_count) {
++ error_message = "returned '0' count for poll descriptors";
++ func = "snd_rawmidi_poll_descriptors_count";
++ goto close;
++ }
++ try {
++ CreateNonBlockingPipe(fds);
++ } catch (std::exception e) {
++ error_message = e.what();
++ func = "CreateNonBlockingPipe";
++ goto close;
++ }
++ snprintf(alias, sizeof(alias), "system:%d-%d %s %d %s", card + 1,
++ device + 1, snd_rawmidi_info_get_name(info), subdevice + 1,
++ alias_suffix);
++ snprintf(name, sizeof(name), "%s%zu", name_prefix, index + 1);
++ this->io_mask = io_mask;
++ return;
++ free_params:
++ snd_rawmidi_params_free(params);
++ close:
++ snd_rawmidi_close(rawmidi);
++ handle_error:
++ throw std::runtime_error(std::string(func) + ": " + error_message);
++}
++
++JackALSARawMidiPort::~JackALSARawMidiPort()
++{
++ DestroyNonBlockingPipe(fds);
++ if (rawmidi) {
++ int code = snd_rawmidi_close(rawmidi);
++ if (code) {
++ jack_error("JackALSARawMidiPort::~JackALSARawMidiPort - "
++ "snd_rawmidi_close: %s", snd_strerror(code));
++ }
++ rawmidi = 0;
++ }
++}
++
++const char *
++JackALSARawMidiPort::GetAlias()
++{
++ return alias;
++}
++
++int
++JackALSARawMidiPort::GetIOPollEvent()
++{
++ unsigned short events;
++ int code = snd_rawmidi_poll_descriptors_revents(rawmidi, alsa_poll_fds,
++ alsa_poll_fd_count,
++ &events);
++ if (code) {
++ jack_error("JackALSARawMidiPort::GetIOPollEvents - "
++ "snd_rawmidi_poll_descriptors_revents: %s",
++ snd_strerror(code));
++ return -1;
++ }
++ if (events & POLLNVAL) {
++ jack_error("JackALSARawMidiPort::GetIOPollEvents - the file "
++ "descriptor is invalid.");
++ return -1;
++ }
++ if (events & POLLERR) {
++ jack_error("JackALSARawMidiPort::GetIOPollEvents - an error has "
++ "occurred on the device or stream.");
++ return -1;
++ }
++ return (events & io_mask) ? 1 : 0;
++}
++
++const char *
++JackALSARawMidiPort::GetName()
++{
++ return name;
++}
++
++int
++JackALSARawMidiPort::GetPollDescriptorCount()
++{
++ return alsa_poll_fd_count + 1;
++}
++
++int
++JackALSARawMidiPort::GetQueuePollEvent()
++{
++ unsigned short events = queue_poll_fd->revents;
++ if (events & POLLNVAL) {
++ jack_error("JackALSARawMidiPort::GetQueuePollEvents - the file "
++ "descriptor is invalid.");
++ return -1;
++ }
++ if (events & POLLERR) {
++ jack_error("JackALSARawMidiPort::GetQueuePollEvents - an error has "
++ "occurred on the device or stream.");
++ return -1;
++ }
++ int event = events & POLLIN ? 1 : 0;
++ if (event) {
++ char c;
++ ssize_t result = read(fds[0], &c, 1);
++ assert(result);
++ if (result < 0) {
++ jack_error("JackALSARawMidiPort::GetQueuePollEvents - error "
++ "reading a byte from the pipe file descriptor: %s",
++ strerror(errno));
++ return -1;
++ }
++ }
++ return event;
++}
++
++void
++JackALSARawMidiPort::PopulatePollDescriptors(struct pollfd *poll_fd)
++{
++ alsa_poll_fds = poll_fd + 1;
++ assert(snd_rawmidi_poll_descriptors(rawmidi, alsa_poll_fds,
++ alsa_poll_fd_count) ==
++ alsa_poll_fd_count);
++ queue_poll_fd = poll_fd;
++ queue_poll_fd->events = POLLERR | POLLIN | POLLNVAL;
++ queue_poll_fd->fd = fds[0];
++ SetIOEventsEnabled(true);
++}
++
++void
++JackALSARawMidiPort::SetIOEventsEnabled(bool enabled)
++{
++ unsigned short mask = POLLNVAL | POLLERR | (enabled ? io_mask : 0);
++ for (int i = 0; i < alsa_poll_fd_count; i++) {
++ (alsa_poll_fds + i)->events = mask;
++ }
++}
++
++bool
++JackALSARawMidiPort::TriggerQueueEvent()
++{
++ char c;
++ ssize_t result = write(fds[1], &c, 1);
++ assert(result <= 1);
++ switch (result) {
++ case 1:
++ return true;
++ case 0:
++ jack_error("JackALSARawMidiPort::TriggerQueueEvent - error writing a "
++ "byte to the pipe file descriptor: %s", strerror(errno));
++ break;
++ default:
++ jack_error("JackALSARawMidiPort::TriggerQueueEvent - couldn't write a "
++ "byte to the pipe file descriptor.");
++ }
++ return false;
++}
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiPort.h
+@@ -0,0 +1,85 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiPort__
++#define __JackALSARawMidiPort__
++
++#include <alsa/asoundlib.h>
++#include <poll.h>
++
++#include "JackConstants.h"
++
++namespace Jack {
++
++ class JackALSARawMidiPort {
++
++ private:
++
++ char alias[REAL_JACK_PORT_NAME_SIZE];
++ struct pollfd *alsa_poll_fds;
++ int alsa_poll_fd_count;
++ int fds[2];
++ unsigned short io_mask;
++ char name[REAL_JACK_PORT_NAME_SIZE];
++ struct pollfd *queue_poll_fd;
++
++ protected:
++
++ snd_rawmidi_t *rawmidi;
++
++ int
++ GetIOPollEvent();
++
++ int
++ GetQueuePollEvent();
++
++ void
++ SetIOEventsEnabled(bool enabled);
++
++ void
++ SetQueueEventsEnabled(bool enabled);
++
++ bool
++ TriggerQueueEvent();
++
++ public:
++
++ JackALSARawMidiPort(snd_rawmidi_info_t *info, size_t index,
++ unsigned short io_mask);
++
++ virtual
++ ~JackALSARawMidiPort();
++
++ const char *
++ GetAlias();
++
++ const char *
++ GetName();
++
++ int
++ GetPollDescriptorCount();
++
++ void
++ PopulatePollDescriptors(struct pollfd *poll_fd);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiReceiveQueue.cpp
+@@ -0,0 +1,54 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 "JackALSARawMidiReceiveQueue.h"
++#include "JackError.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackALSARawMidiReceiveQueue;
++
++JackALSARawMidiReceiveQueue::
++JackALSARawMidiReceiveQueue(snd_rawmidi_t *rawmidi, size_t buffer_size)
++{
++ buffer = new jack_midi_data_t[buffer_size];
++ this->buffer_size = buffer_size;
++ this->rawmidi = rawmidi;
++}
++
++JackALSARawMidiReceiveQueue::~JackALSARawMidiReceiveQueue()
++{
++ delete[] buffer;
++}
++
++jack_midi_event_t *
++JackALSARawMidiReceiveQueue::DequeueEvent()
++{
++ ssize_t result = snd_rawmidi_read(rawmidi, buffer, buffer_size);
++ if (result > 0) {
++ event.buffer = buffer;
++ event.size = (size_t) result;
++ event.time = GetCurrentFrame();
++ return &event;
++ }
++ if (result && (result != -EWOULDBLOCK)) {
++ jack_error("JackALSARawMidiReceiveQueue::DequeueEvent - "
++ "snd_rawmidi_read: %s", snd_strerror(result));
++ }
++ return 0;
++}
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiReceiveQueue.h
+@@ -0,0 +1,51 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiReceiveQueue__
++#define __JackALSARawMidiReceiveQueue__
++
++#include <alsa/asoundlib.h>
++
++#include "JackMidiReceiveQueue.h"
++
++namespace Jack {
++
++ class JackALSARawMidiReceiveQueue: public JackMidiReceiveQueue {
++
++ private:
++
++ jack_midi_data_t *buffer;
++ size_t buffer_size;
++ jack_midi_event_t event;
++ snd_rawmidi_t *rawmidi;
++
++ public:
++
++ JackALSARawMidiReceiveQueue(snd_rawmidi_t *rawmidi,
++ size_t buffer_size=4096);
++ ~JackALSARawMidiReceiveQueue();
++
++ jack_midi_event_t *
++ DequeueEvent();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiSendQueue.cpp
+@@ -0,0 +1,73 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++
++#include "JackALSARawMidiSendQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackALSARawMidiSendQueue;
++
++JackALSARawMidiSendQueue::JackALSARawMidiSendQueue(snd_rawmidi_t *rawmidi,
++ size_t bytes_per_poll)
++{
++ assert(bytes_per_poll > 0);
++ this->bytes_per_poll = bytes_per_poll;
++ this->rawmidi = rawmidi;
++ blocked = false;
++ bytes_available = bytes_per_poll;
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackALSARawMidiSendQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ assert(size == 1);
++ if (time > GetCurrentFrame()) {
++ return EVENT_EARLY;
++ }
++ if (! bytes_available) {
++ return BUFFER_FULL;
++ }
++ ssize_t result = snd_rawmidi_write(rawmidi, buffer, 1);
++ switch (result) {
++ case 1:
++ blocked = false;
++ bytes_available--;
++ return OK;
++ case -EWOULDBLOCK:
++ blocked = true;
++ return BUFFER_FULL;
++ }
++ jack_error("JackALSARawMidiSendQueue::EnqueueEvent - snd_rawmidi_write: "
++ "%s", snd_strerror(result));
++ return EN_ERROR;
++}
++
++bool
++JackALSARawMidiSendQueue::IsBlocked()
++{
++ return blocked;
++}
++
++void
++JackALSARawMidiSendQueue::ResetPollByteCount()
++{
++ bytes_available = bytes_per_poll;
++}
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiSendQueue.h
+@@ -0,0 +1,57 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiSendQueue__
++#define __JackALSARawMidiSendQueue__
++
++#include <alsa/asoundlib.h>
++
++#include "JackMidiSendQueue.h"
++
++namespace Jack {
++
++ class JackALSARawMidiSendQueue: public JackMidiSendQueue {
++
++ private:
++
++ bool blocked;
++ size_t bytes_available;
++ size_t bytes_per_poll;
++ snd_rawmidi_t *rawmidi;
++
++ public:
++
++ JackALSARawMidiSendQueue(snd_rawmidi_t *rawmidi,
++ size_t bytes_per_poll=0);
++
++ JackMidiWriteQueue::EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ bool
++ IsBlocked();
++
++ void
++ ResetPollByteCount();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiUtil.cpp
+@@ -0,0 +1,43 @@
++#include <cerrno>
++#include <cstring>
++#include <stdexcept>
++
++#include <fcntl.h>
++#include <unistd.h>
++
++#include "JackALSARawMidiUtil.h"
++
++void
++Jack::CreateNonBlockingPipe(int *fds)
++{
++ if (pipe(fds) == -1) {
++ throw std::runtime_error(strerror(errno));
++ }
++ try {
++ SetNonBlocking(fds[0]);
++ SetNonBlocking(fds[1]);
++ } catch (...) {
++ close(fds[1]);
++ close(fds[0]);
++ throw;
++ }
++}
++
++void
++Jack::DestroyNonBlockingPipe(int *fds)
++{
++ close(fds[1]);
++ close(fds[0]);
++}
++
++void
++Jack::SetNonBlocking(int fd)
++{
++ int flags = fcntl(fd, F_GETFL);
++ if (flags == -1) {
++ throw std::runtime_error(strerror(errno));
++ }
++ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
++ throw std::runtime_error(strerror(errno));
++ }
++}
+--- /dev/null
++++ b/linux/alsarawmidi/JackALSARawMidiUtil.h
+@@ -0,0 +1,36 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackALSARawMidiUtil__
++#define __JackALSARawMidiUtil__
++
++namespace Jack {
++
++ void
++ CreateNonBlockingPipe(int *fds);
++
++ void
++ DestroyNonBlockingPipe(int *fds);
++
++ void
++ SetNonBlocking(int fd);
++
++}
++
++#endif
+--- a/linux/firewire/JackFFADODriver.cpp
++++ b/linux/firewire/JackFFADODriver.cpp
+@@ -36,13 +36,14 @@
+ #include <string.h>
+
+ #include "JackFFADODriver.h"
+-#include "JackFFADOMidiInput.h"
+-#include "JackFFADOMidiOutput.h"
++#include "JackFFADOMidiInputPort.h"
++#include "JackFFADOMidiOutputPort.h"
+ #include "JackEngineControl.h"
+ #include "JackClientControl.h"
+ #include "JackPort.h"
+ #include "JackGraphManager.h"
+ #include "JackCompilerDeps.h"
++#include "JackLockedEngine.h"
+
+ namespace Jack
+ {
+@@ -94,14 +95,9 @@
+ /* process the midi data */
+ for (chn = 0; chn < driver->capture_nchannels; chn++) {
+ if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
+- JackFFADOMidiInput *midi_input = (JackFFADOMidiInput *) driver->capture_channels[chn].midi_input;
++ JackFFADOMidiInputPort *midi_input = (JackFFADOMidiInputPort *) driver->capture_channels[chn].midi_input;
+ JackMidiBuffer *buffer = (JackMidiBuffer *) fGraphManager->GetBuffer(fCapturePortList[chn], nframes);
+- if (! buffer) {
+- continue;
+- }
+- midi_input->SetInputBuffer(driver->capture_channels[chn].midi_buffer);
+- midi_input->SetPortBuffer(buffer);
+- midi_input->Process(nframes);
++ midi_input->Process(buffer, driver->capture_channels[chn].midi_buffer, nframes);
+ }
+ }
+
+@@ -138,16 +134,9 @@
+ memset(midi_buffer, 0, nframes * sizeof(uint32_t));
+ buf = (jack_default_audio_sample_t *) fGraphManager->GetBuffer(fPlaybackPortList[chn], nframes);
+ ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(midi_buffer));
+- /* if the returned buffer is invalid, continue */
+- if (!buf) {
+- ffado_streaming_playback_stream_onoff(driver->dev, chn, 0);
+- continue;
+- }
+- ffado_streaming_playback_stream_onoff(driver->dev, chn, 1);
+- JackFFADOMidiOutput *midi_output = (JackFFADOMidiOutput *) driver->playback_channels[chn].midi_output;
+- midi_output->SetPortBuffer((JackMidiBuffer *) buf);
+- midi_output->SetOutputBuffer(midi_buffer);
+- midi_output->Process(nframes);
++ ffado_streaming_playback_stream_onoff(driver->dev, chn, buf ? 1 : 0);
++ JackFFADOMidiOutputPort *midi_output = (JackFFADOMidiOutputPort *) driver->playback_channels[chn].midi_output;
++ midi_output->Process((JackMidiBuffer *) buf, midi_buffer, nframes);
+
+ } else { // always have a valid buffer
+ ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(driver->nullbuffer));
+@@ -155,9 +144,7 @@
+ }
+ }
+ }
+-
+ ffado_streaming_transfer_playback_buffers(driver->dev);
+-
+ printExit();
+ return 0;
+ }
+@@ -359,9 +346,9 @@
+ int JackFFADODriver::Attach()
+ {
+ JackPort* port;
+- int port_index;
+- char buf[JACK_PORT_NAME_SIZE];
+- char portname[JACK_PORT_NAME_SIZE];
++ jack_port_id_t port_index;
++ char buf[REAL_JACK_PORT_NAME_SIZE];
++ char portname[REAL_JACK_PORT_NAME_SIZE];
+ jack_latency_range_t range;
+
+ ffado_driver_t* driver = (ffado_driver_t*)fDriver;
+@@ -427,16 +414,16 @@
+
+ fCaptureChannels = 0;
+ for (channel_t chn = 0; chn < driver->capture_nchannels; chn++) {
+- ffado_streaming_get_capture_stream_name(driver->dev, chn, portname, sizeof(portname) - 1);
++ ffado_streaming_get_capture_stream_name(driver->dev, chn, portname, sizeof(portname));
+
+ driver->capture_channels[chn].stream_type = ffado_streaming_get_capture_stream_type(driver->dev, chn);
+ if (driver->capture_channels[chn].stream_type == ffado_stream_type_audio) {
+- snprintf(buf, sizeof(buf) - 1, "firewire_pcm:%s_in", portname);
++ snprintf(buf, sizeof(buf), "firewire_pcm:%s_in", portname);
+ printMessage ("Registering audio capture port %s", buf);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, buf,
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf,
+ JACK_DEFAULT_AUDIO_TYPE,
+ CaptureDriverFlags,
+- fEngineControl->fBufferSize)) == NO_PORT) {
++ fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", buf);
+ return -1;
+ }
+@@ -451,19 +438,18 @@
+ range.min = range.max = driver->period_size + driver->capture_frame_latency;
+ port->SetLatencyRange(JackCaptureLatency, &range);
+ // capture port aliases (jackd1 style port names)
+- snprintf(buf, sizeof(buf) - 1, "%s:capture_%i", fClientControl.fName, (int) chn + 1);
++ snprintf(buf, sizeof(buf), "%s:capture_%i", fClientControl.fName, (int) chn + 1);
+ port->SetAlias(buf);
+ fCapturePortList[chn] = port_index;
+ jack_log("JackFFADODriver::Attach fCapturePortList[i] %ld ", port_index);
+ fCaptureChannels++;
+-
+ } else if (driver->capture_channels[chn].stream_type == ffado_stream_type_midi) {
+- snprintf(buf, sizeof(buf) - 1, "firewire_pcm:%s_in", portname);
++ snprintf(buf, sizeof(buf), "firewire_pcm:%s_in", portname);
+ printMessage ("Registering midi capture port %s", buf);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, buf,
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf,
+ JACK_DEFAULT_MIDI_TYPE,
+ CaptureDriverFlags,
+- fEngineControl->fBufferSize)) == NO_PORT) {
++ fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", buf);
+ return -1;
+ }
+@@ -476,7 +462,7 @@
+ printError(" cannot enable port %s", buf);
+ }
+
+- driver->capture_channels[chn].midi_input = new JackFFADOMidiInput();
++ driver->capture_channels[chn].midi_input = new JackFFADOMidiInputPort();
+ // setup the midi buffer
+ driver->capture_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));
+
+@@ -501,17 +487,17 @@
+
+ fPlaybackChannels = 0;
+ for (channel_t chn = 0; chn < driver->playback_nchannels; chn++) {
+- ffado_streaming_get_playback_stream_name(driver->dev, chn, portname, sizeof(portname) - 1);
++ ffado_streaming_get_playback_stream_name(driver->dev, chn, portname, sizeof(portname));
+
+ driver->playback_channels[chn].stream_type = ffado_streaming_get_playback_stream_type(driver->dev, chn);
+
+ if (driver->playback_channels[chn].stream_type == ffado_stream_type_audio) {
+- snprintf(buf, sizeof(buf) - 1, "firewire_pcm:%s_out", portname);
++ snprintf(buf, sizeof(buf), "firewire_pcm:%s_out", portname);
+ printMessage ("Registering audio playback port %s", buf);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, buf,
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf,
+ JACK_DEFAULT_AUDIO_TYPE,
+ PlaybackDriverFlags,
+- fEngineControl->fBufferSize)) == NO_PORT) {
++ fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", buf);
+ return -1;
+ }
+@@ -529,18 +515,19 @@
+ range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
+ port->SetLatencyRange(JackPlaybackLatency, &range);
+ // playback port aliases (jackd1 style port names)
+- snprintf(buf, sizeof(buf) - 1, "%s:playback_%i", fClientControl.fName, (int) chn + 1);
++ snprintf(buf, sizeof(buf), "%s:playback_%i", fClientControl.fName, (int) chn + 1);
+ port->SetAlias(buf);
+ fPlaybackPortList[chn] = port_index;
+ jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index);
+ fPlaybackChannels++;
+ } else if (driver->playback_channels[chn].stream_type == ffado_stream_type_midi) {
+- snprintf(buf, sizeof(buf) - 1, "firewire_pcm:%s_out", portname);
++ snprintf(buf, sizeof(buf), "firewire_pcm:%s_out", portname);
+ printMessage ("Registering midi playback port %s", buf);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, buf,
++
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf,
+ JACK_DEFAULT_MIDI_TYPE,
+ PlaybackDriverFlags,
+- fEngineControl->fBufferSize)) == NO_PORT) {
++ fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", buf);
+ return -1;
+ }
+@@ -557,12 +544,12 @@
+ // This constructor optionally accepts arguments for the
+ // non-realtime buffer size and the realtime buffer size. Ideally,
+ // these would become command-line options for the FFADO driver.
+- driver->playback_channels[chn].midi_output = new JackFFADOMidiOutput();
++ driver->playback_channels[chn].midi_output = new JackFFADOMidiOutputPort();
+
+ driver->playback_channels[chn].midi_buffer = (uint32_t *)calloc(driver->period_size, sizeof(uint32_t));
+
+ port = fGraphManager->GetPort(port_index);
+- range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + driver->playback_frame_latency;
++ range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
+ port->SetLatencyRange(JackPlaybackLatency, &range);
+ fPlaybackPortList[chn] = port_index;
+ jack_log("JackFFADODriver::Attach fPlaybackPortList[i] %ld ", port_index);
+@@ -600,7 +587,7 @@
+ if (driver->capture_channels[chn].midi_buffer)
+ free(driver->capture_channels[chn].midi_buffer);
+ if (driver->capture_channels[chn].midi_input)
+- delete ((JackFFADOMidiInput *) (driver->capture_channels[chn].midi_input));
++ delete ((JackFFADOMidiInputPort *) (driver->capture_channels[chn].midi_input));
+ }
+ free(driver->capture_channels);
+
+@@ -608,7 +595,7 @@
+ if (driver->playback_channels[chn].midi_buffer)
+ free(driver->playback_channels[chn].midi_buffer);
+ if (driver->playback_channels[chn].midi_output)
+- delete ((JackFFADOMidiOutput *) (driver->playback_channels[chn].midi_output));
++ delete ((JackFFADOMidiOutputPort *) (driver->playback_channels[chn].midi_output));
+ }
+ free(driver->playback_channels);
+
+@@ -765,122 +752,52 @@
+ SERVER_EXPORT const jack_driver_desc_t *
+ driver_get_descriptor () {
+ jack_driver_desc_t * desc;
+- jack_driver_param_desc_t * params;
+- unsigned int i;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("firewire", JackDriverMaster, "Linux FFADO API based audio backend", &filler);
+
+- desc = (jack_driver_desc_t *)calloc (1, sizeof (jack_driver_desc_t));
++ strcpy(value.str, "hw:0");
++ jack_driver_descriptor_add_parameter(
++ desc,
++ &filler,
++ "device",
++ 'd',
++ JackDriverParamString,
++ &value,
++ NULL,
++ "The FireWire device to use.",
++ "The FireWire device to use. Please consult the FFADO documentation for more info.");
++
++ value.ui = 1024;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = 3;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
++
++ value.ui = 48000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamBool, &value, NULL, "Provide capture ports.", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamBool, &value, NULL, "Provide playback ports.", NULL);
++
++ value.i = 1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports.", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of input channels to provide (note: currently ignored)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of output channels to provide (note: currently ignored)", NULL);
+
+- strcpy (desc->name, "firewire"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Linux FFADO API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
++ value.ui = 3;
++ jack_driver_descriptor_add_parameter(desc, &filler, "verbose", 'v', JackDriverParamUInt, &value, NULL, "libffado verbose level", NULL);
+
+- desc->nparams = 13;
+-
+- params = (jack_driver_param_desc_t *)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+- desc->params = params;
+-
+- i = 0;
+- strcpy (params[i].name, "device");
+- params[i].character = 'd';
+- params[i].type = JackDriverParamString;
+- strcpy (params[i].value.str, "hw:0");
+- strcpy (params[i].short_desc, "The FireWire device to use.");
+- strcpy (params[i].long_desc, "The FireWire device to use. Please consult the FFADO documentation for more info.");
+-
+- i++;
+- strcpy (params[i].name, "period");
+- params[i].character = 'p';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1024;
+- strcpy (params[i].short_desc, "Frames per period");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "nperiods");
+- params[i].character = 'n';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 3;
+- strcpy (params[i].short_desc, "Number of periods of playback latency");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "rate");
+- params[i].character = 'r';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 48000U;
+- strcpy (params[i].short_desc, "Sample rate");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "capture");
+- params[i].character = 'C';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Provide capture ports.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "playback");
+- params[i].character = 'P';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Provide playback ports.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "duplex");
+- params[i].character = 'D';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 1;
+- strcpy (params[i].short_desc, "Provide both capture and playback ports.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "input-latency");
+- params[i].character = 'I';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Extra input latency (frames)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "output-latency");
+- params[i].character = 'O';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Extra output latency (frames)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "inchannels");
+- params[i].character = 'i';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Number of input channels to provide (note: currently ignored)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "outchannels");
+- params[i].character = 'o';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Number of output channels to provide (note: currently ignored)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "verbose");
+- params[i].character = 'v';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 3;
+- strcpy (params[i].short_desc, "libffado verbose level");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "snoop");
+- params[i].character = 'X';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Snoop firewire traffic");
+- strcpy (params[i].long_desc, params[i].short_desc);
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "snoop", 'X', JackDriverParamBool, &value, NULL, "Snoop firewire traffic", NULL);
+
+ return desc;
+ }
+--- a/linux/firewire/JackFFADOMidiInput.cpp
++++ /dev/null
+@@ -1,59 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#include <cassert>
+-
+-#include "JackFFADOMidiInput.h"
+-
+-namespace Jack {
+-
+-JackFFADOMidiInput::JackFFADOMidiInput(size_t buffer_size):
+- JackPhysicalMidiInput(buffer_size)
+-{
+- new_period = true;
+-}
+-
+-JackFFADOMidiInput::~JackFFADOMidiInput()
+-{
+- // Empty
+-}
+-
+-jack_nframes_t
+-JackFFADOMidiInput::Receive(jack_midi_data_t *datum,
+- jack_nframes_t current_frame,
+- jack_nframes_t total_frames)
+-{
+- assert(input_buffer);
+- if (! new_period) {
+- current_frame += 8;
+- } else {
+- new_period = false;
+- }
+- for (; current_frame < total_frames; current_frame += 8) {
+- uint32_t data = input_buffer[current_frame];
+- if (data & 0xff000000) {
+- *datum = (jack_midi_data_t) (data & 0xff);
+- return current_frame;
+- }
+- }
+- new_period = true;
+- return total_frames;
+-}
+-
+-}
+--- a/linux/firewire/JackFFADOMidiInput.h
++++ /dev/null
+@@ -1,54 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#ifndef __JackFFADOMidiInput__
+-#define __JackFFADOMidiInput__
+-
+-#include "JackPhysicalMidiInput.h"
+-
+-namespace Jack {
+-
+- class JackFFADOMidiInput: public JackPhysicalMidiInput {
+-
+- private:
+-
+- uint32_t *input_buffer;
+- bool new_period;
+-
+- protected:
+-
+- jack_nframes_t
+- Receive(jack_midi_data_t *, jack_nframes_t, jack_nframes_t);
+-
+- public:
+-
+- JackFFADOMidiInput(size_t buffer_size=1024);
+- ~JackFFADOMidiInput();
+-
+- inline void
+- SetInputBuffer(uint32_t *input_buffer)
+- {
+- this->input_buffer = input_buffer;
+- }
+-
+- };
+-
+-}
+-
+-#endif
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiInputPort.cpp
+@@ -0,0 +1,94 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <memory>
++
++#include "JackFFADOMidiInputPort.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackFFADOMidiInputPort;
++
++JackFFADOMidiInputPort::JackFFADOMidiInputPort(size_t max_bytes)
++{
++ event = 0;
++ receive_queue = new JackFFADOMidiReceiveQueue();
++ std::auto_ptr<JackFFADOMidiReceiveQueue> receive_queue_ptr(receive_queue);
++ write_queue = new JackMidiBufferWriteQueue();
++ std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
++ raw_queue = new JackMidiRawInputWriteQueue(write_queue, max_bytes,
++ max_bytes);
++ write_queue_ptr.release();
++ receive_queue_ptr.release();
++}
++
++JackFFADOMidiInputPort::~JackFFADOMidiInputPort()
++{
++ delete raw_queue;
++ delete receive_queue;
++ delete write_queue;
++}
++
++void
++JackFFADOMidiInputPort::Process(JackMidiBuffer *port_buffer,
++ uint32_t *input_buffer, jack_nframes_t frames)
++{
++ receive_queue->ResetInputBuffer(input_buffer, frames);
++ write_queue->ResetMidiBuffer(port_buffer, frames);
++ jack_nframes_t boundary_frame = GetLastFrame() + frames;
++ if (! event) {
++ event = receive_queue->DequeueEvent();
++ }
++ for (; event; event = receive_queue->DequeueEvent()) {
++ switch (raw_queue->EnqueueEvent(event)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++
++ // Processing events early might free up some space in the raw
++ // input queue.
++
++ raw_queue->Process(boundary_frame);
++ switch (raw_queue->EnqueueEvent(event)) {
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ // This shouldn't really happen. It indicates a bug if it
++ // does.
++ jack_error("JackFFADOMidiInputPort::Process - **BUG** "
++ "JackMidiRawInputWriteQueue::EnqueueEvent returned "
++ "`BUFFER_FULL`, and then returned "
++ "`BUFFER_TOO_SMALL` after a `Process()` call.");
++ // Fallthrough on purpose
++ case JackMidiWriteQueue::OK:
++ continue;
++ default:
++ return;
++ }
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackFFADOMidiInputPort::Process - The write queue "
++ "couldn't enqueue a %d-byte event. Dropping event.",
++ event->size);
++ // Fallthrough on purpose
++ case JackMidiWriteQueue::OK:
++ continue;
++ default:
++ // This is here to stop compliers from warning us about not
++ // handling enumeration values.
++ ;
++ }
++ break;
++ }
++ raw_queue->Process(boundary_frame);
++}
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiInputPort.h
+@@ -0,0 +1,51 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackFFADOMidiInputPort__
++#define __JackFFADOMidiInputPort__
++
++#include "JackFFADOMidiReceiveQueue.h"
++#include "JackMidiBufferWriteQueue.h"
++#include "JackMidiRawInputWriteQueue.h"
++
++namespace Jack {
++
++ class JackFFADOMidiInputPort {
++
++ private:
++
++ jack_midi_event_t *event;
++ JackMidiRawInputWriteQueue *raw_queue;
++ JackFFADOMidiReceiveQueue *receive_queue;
++ JackMidiBufferWriteQueue *write_queue;
++
++ public:
++
++ JackFFADOMidiInputPort(size_t max_bytes=4096);
++ ~JackFFADOMidiInputPort();
++
++ void
++ Process(JackMidiBuffer *port_buffer, uint32_t *input_buffer,
++ jack_nframes_t frames);
++
++ };
++
++}
++
++#endif
+--- a/linux/firewire/JackFFADOMidiOutput.cpp
++++ /dev/null
+@@ -1,60 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#include <cassert>
+-
+-#include "JackError.h"
+-#include "JackFFADOMidiOutput.h"
+-
+-namespace Jack {
+-
+-JackFFADOMidiOutput::JackFFADOMidiOutput(size_t non_rt_buffer_size,
+- size_t rt_buffer_size):
+- JackPhysicalMidiOutput(non_rt_buffer_size, rt_buffer_size)
+-{
+- // Empty
+-}
+-
+-JackFFADOMidiOutput::~JackFFADOMidiOutput()
+-{
+- // Empty
+-}
+-
+-jack_nframes_t
+-JackFFADOMidiOutput::Advance(jack_nframes_t current_frame)
+-{
+- if (current_frame % 8) {
+- current_frame = (current_frame & (~ ((jack_nframes_t) 7))) + 8;
+- }
+- return current_frame;
+-}
+-
+-jack_nframes_t
+-JackFFADOMidiOutput::Send(jack_nframes_t current_frame, jack_midi_data_t datum)
+-{
+- assert(output_buffer);
+-
+- jack_log("JackFFADOMidiOutput::Send (%d) - Sending '%x' byte.",
+- current_frame, (unsigned int) datum);
+-
+- output_buffer[current_frame] = 0x01000000 | ((uint32_t) datum);
+- return current_frame + 8;
+-}
+-
+-}
+--- a/linux/firewire/JackFFADOMidiOutput.h
++++ /dev/null
+@@ -1,57 +0,0 @@
+-/*
+-Copyright (C) 2009 Devin Anderson
+-
+-This program is free software; you can redistribute it and/or modify
+-it under the terms of the GNU Lesser General Public License as published by
+-the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
+-You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
+-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+-*/
+-
+-#ifndef __JackFFADOMidiOutput__
+-#define __JackFFADOMidiOutput__
+-
+-#include "JackPhysicalMidiOutput.h"
+-
+-namespace Jack {
+-
+- class JackFFADOMidiOutput: public JackPhysicalMidiOutput {
+-
+- private:
+-
+- uint32_t *output_buffer;
+-
+- protected:
+-
+- jack_nframes_t
+- Advance(jack_nframes_t);
+-
+- jack_nframes_t
+- Send(jack_nframes_t, jack_midi_data_t);
+-
+- public:
+-
+- JackFFADOMidiOutput(size_t non_rt_buffer_size=1024,
+- size_t rt_buffer_size=64);
+- ~JackFFADOMidiOutput();
+-
+- inline void
+- SetOutputBuffer(uint32_t *output_buffer)
+- {
+- this->output_buffer = output_buffer;
+- }
+-
+- };
+-
+-}
+-
+-#endif
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiOutputPort.cpp
+@@ -0,0 +1,98 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <memory>
++
++#include "JackFFADOMidiOutputPort.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackFFADOMidiOutputPort;
++
++JackFFADOMidiOutputPort::JackFFADOMidiOutputPort(size_t non_rt_size,
++ size_t max_non_rt_messages,
++ size_t max_rt_messages)
++{
++ event = 0;
++ read_queue = new JackMidiBufferReadQueue();
++ std::auto_ptr<JackMidiBufferReadQueue> read_queue_ptr(read_queue);
++ send_queue = new JackFFADOMidiSendQueue();
++ std::auto_ptr<JackFFADOMidiSendQueue> send_queue_ptr(send_queue);
++ raw_queue = new JackMidiRawOutputWriteQueue(send_queue, non_rt_size,
++ max_non_rt_messages,
++ max_rt_messages);
++ send_queue_ptr.release();
++ read_queue_ptr.release();
++}
++
++JackFFADOMidiOutputPort::~JackFFADOMidiOutputPort()
++{
++ delete raw_queue;
++ delete read_queue;
++ delete send_queue;
++}
++
++void
++JackFFADOMidiOutputPort::Process(JackMidiBuffer *port_buffer,
++ uint32_t *output_buffer,
++ jack_nframes_t frames)
++{
++ read_queue->ResetMidiBuffer(port_buffer);
++ send_queue->ResetOutputBuffer(output_buffer, frames);
++ jack_nframes_t boundary_frame = GetLastFrame() + frames;
++ if (! event) {
++ event = read_queue->DequeueEvent();
++ }
++ for (; event; event = read_queue->DequeueEvent()) {
++ switch (raw_queue->EnqueueEvent(event)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++
++ // Processing events early might free up some space in the raw
++ // output queue.
++
++ raw_queue->Process(boundary_frame);
++ switch (raw_queue->EnqueueEvent(event)) {
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ // This shouldn't really happen. It indicates a bug if it
++ // does.
++ jack_error("JackFFADOMidiOutputPort::Process - **BUG** "
++ "JackMidiRawOutputWriteQueue::EnqueueEvent "
++ "returned `BUFFER_FULL`, and then returned "
++ "`BUFFER_TOO_SMALL` after a `Process()` call.");
++ // Fallthrough on purpose
++ case JackMidiWriteQueue::OK:
++ continue;
++ default:
++ return;
++ }
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackFFADOMidiOutputPort::Process - The write queue "
++ "couldn't enqueue a %d-byte event. Dropping event.",
++ event->size);
++ // Fallthrough on purpose
++ case JackMidiWriteQueue::OK:
++ continue;
++ default:
++ // This is here to stop compliers from warning us about not
++ // handling enumeration values.
++ ;
++ }
++ break;
++ }
++ raw_queue->Process(boundary_frame);
++}
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiOutputPort.h
+@@ -0,0 +1,53 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackFFADOMidiOutputPort__
++#define __JackFFADOMidiOutputPort__
++
++#include "JackFFADOMidiSendQueue.h"
++#include "JackMidiBufferReadQueue.h"
++#include "JackMidiRawOutputWriteQueue.h"
++
++namespace Jack {
++
++ class JackFFADOMidiOutputPort {
++
++ private:
++
++ jack_midi_event_t *event;
++ JackMidiRawOutputWriteQueue *raw_queue;
++ JackMidiBufferReadQueue *read_queue;
++ JackFFADOMidiSendQueue *send_queue;
++
++ public:
++
++ JackFFADOMidiOutputPort(size_t non_rt_size=4096,
++ size_t max_non_rt_messages=1024,
++ size_t max_rt_messages=128);
++ ~JackFFADOMidiOutputPort();
++
++ void
++ Process(JackMidiBuffer *port_buffer, uint32_t *output_buffer,
++ jack_nframes_t frames);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiReceiveQueue.cpp
+@@ -0,0 +1,55 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include "JackFFADOMidiReceiveQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackFFADOMidiReceiveQueue;
++
++JackFFADOMidiReceiveQueue::JackFFADOMidiReceiveQueue()
++{
++ // Empty
++}
++
++jack_midi_event_t *
++JackFFADOMidiReceiveQueue::DequeueEvent()
++{
++ for (; index < length; index += 8) {
++ uint32_t data = input_buffer[index];
++ if (data & 0xff000000) {
++ byte = (jack_midi_data_t) (data & 0xff);
++ event.buffer = &byte;
++ event.size = 1;
++ event.time = last_frame + index;
++ index += 8;
++ return &event;
++ }
++ }
++ return 0;
++}
++
++void
++JackFFADOMidiReceiveQueue::ResetInputBuffer(uint32_t *input_buffer,
++ jack_nframes_t length)
++{
++ this->input_buffer = input_buffer;
++ index = 0;
++ last_frame = GetLastFrame();
++ this->length = length;
++}
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiReceiveQueue.h
+@@ -0,0 +1,52 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackFFADOMidiReceiveQueue__
++#define __JackFFADOMidiReceiveQueue__
++
++#include "JackMidiReceiveQueue.h"
++
++namespace Jack {
++
++ class JackFFADOMidiReceiveQueue: public JackMidiReceiveQueue {
++
++ private:
++
++ jack_midi_data_t byte;
++ jack_midi_event_t event;
++ jack_nframes_t index;
++ uint32_t *input_buffer;
++ jack_nframes_t last_frame;
++ jack_nframes_t length;
++
++ public:
++
++ JackFFADOMidiReceiveQueue();
++
++ jack_midi_event_t *
++ DequeueEvent();
++
++ void
++ ResetInputBuffer(uint32_t *input_buffer, jack_nframes_t length);
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiSendQueue.cpp
+@@ -0,0 +1,64 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#include <cassert>
++
++#include "JackFFADOMidiSendQueue.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackFFADOMidiSendQueue;
++
++JackFFADOMidiSendQueue::JackFFADOMidiSendQueue()
++{
++ // Empty
++}
++
++Jack::JackMidiWriteQueue::EnqueueResult
++JackFFADOMidiSendQueue::EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer)
++{
++ assert(size == 1);
++ jack_nframes_t relative_time = (time < last_frame) ? 0 : time - last_frame;
++ if (index < relative_time) {
++ index = (relative_time % 8) ?
++ (relative_time & (~ ((jack_nframes_t) 7))) + 8 : relative_time;
++ }
++ if (index >= length) {
++ return BUFFER_FULL;
++ }
++ output_buffer[index] = 0x01000000 | ((uint32_t) *buffer);
++ index += 8;
++ return OK;
++}
++
++jack_nframes_t
++JackFFADOMidiSendQueue::GetNextScheduleFrame()
++{
++ return last_frame + index;
++}
++
++void
++JackFFADOMidiSendQueue::ResetOutputBuffer(uint32_t *output_buffer,
++ jack_nframes_t length)
++{
++ index = 0;
++ last_frame = GetLastFrame();
++ this->length = length;
++ this->output_buffer = output_buffer;
++}
+--- /dev/null
++++ b/linux/firewire/JackFFADOMidiSendQueue.h
+@@ -0,0 +1,54 @@
++/*
++Copyright (C) 2010 Devin Anderson
++
++This program is free software; you can redistribute it and/or modify
++it under the terms of the GNU Lesser General Public License as published by
++the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++You should have received a copy of the GNU Lesser General Public License
++along with this program; if not, write to the Free Software
++Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++*/
++
++#ifndef __JackFFADOMidiSendQueue__
++#define __JackFFADOMidiSendQueue__
++
++#include "JackMidiSendQueue.h"
++
++namespace Jack {
++
++ class JackFFADOMidiSendQueue: public JackMidiSendQueue {
++
++ private:
++
++ jack_nframes_t index;
++ jack_nframes_t last_frame;
++ jack_nframes_t length;
++ uint32_t *output_buffer;
++
++ public:
++
++ JackFFADOMidiSendQueue();
++
++ EnqueueResult
++ EnqueueEvent(jack_nframes_t time, size_t size,
++ jack_midi_data_t *buffer);
++
++ jack_nframes_t
++ GetNextScheduleFrame();
++
++ void
++ ResetOutputBuffer(uint32_t *output_buffer, jack_nframes_t length);
++
++ };
++
++}
++
++#endif
+--- a/linux/freebob/JackFreebobDriver.cpp
++++ b/linux/freebob/JackFreebobDriver.cpp
+@@ -39,6 +39,7 @@
+ #include "JackClientControl.h"
+ #include "JackPort.h"
+ #include "JackGraphManager.h"
++#include "JackLockedEngine.h"
+
+ namespace Jack
+ {
+@@ -509,7 +510,7 @@
+ continue;
+ }
+
+- freebob_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf) - 1);
++ freebob_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf));
+ printMessage("Register MIDI IN port %s", buf);
+
+ m->input_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
+@@ -566,7 +567,7 @@
+ continue;
+ }
+
+- freebob_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf) - 1);
++ freebob_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf));
+ printMessage("Register MIDI OUT port %s", buf);
+
+ m->output_ports[i]->seq_port_nr = snd_seq_create_simple_port(m->seq_handle, buf,
+@@ -666,10 +667,10 @@
+ int JackFreebobDriver::Attach()
+ {
+ JackPort* port;
+- int port_index;
++ jack_port_id_t port_index;
+
+- char buf[JACK_PORT_NAME_SIZE];
+- char portname[JACK_PORT_NAME_SIZE];
++ char buf[REAL_JACK_PORT_NAME_SIZE];
++ char portname[REAL_JACK_PORT_NAME_SIZE];
+ jack_latency_range_t range;
+
+ freebob_driver_t* driver = (freebob_driver_t*)fDriver;
+@@ -722,18 +723,18 @@
+
+ for (unsigned int i = 0; i < driver->capture_nchannels; i++) {
+
+- freebob_streaming_get_capture_stream_name(driver->dev, i, portname, sizeof(portname) - 1);
+- snprintf(buf, sizeof(buf) - 1, "%s:%s", fClientControl.fName, portname);
++ freebob_streaming_get_capture_stream_name(driver->dev, i, portname, sizeof(portname));
++ snprintf(buf, sizeof(buf), "%s:%s", fClientControl.fName, portname);
+
+ if (freebob_streaming_get_capture_stream_type(driver->dev, i) != freebob_stream_type_audio) {
+ printMessage ("Don't register capture port %s", buf);
+ } else {
+ printMessage ("Registering capture port %s", buf);
+
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, buf,
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf,
+ JACK_DEFAULT_AUDIO_TYPE,
+ CaptureDriverFlags,
+- fEngineControl->fBufferSize)) == NO_PORT) {
++ fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", buf);
+ return -1;
+ }
+@@ -752,23 +753,23 @@
+
+ for (unsigned int i = 0; i < driver->playback_nchannels; i++) {
+
+- freebob_streaming_get_playback_stream_name(driver->dev, i, portname, sizeof(portname) - 1);
+- snprintf(buf, sizeof(buf) - 1, "%s:%s", fClientControl.fName, portname);
++ freebob_streaming_get_playback_stream_name(driver->dev, i, portname, sizeof(portname));
++ snprintf(buf, sizeof(buf), "%s:%s", fClientControl.fName, portname);
+
+ if (freebob_streaming_get_playback_stream_type(driver->dev, i) != freebob_stream_type_audio) {
+ printMessage ("Don't register playback port %s", buf);
+ } else {
+ printMessage ("Registering playback port %s", buf);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, buf,
++ if (fEngine->PortRegister(fClientControl.fRefNum, buf,
+ JACK_DEFAULT_AUDIO_TYPE,
+ PlaybackDriverFlags,
+- fEngineControl->fBufferSize)) == NO_PORT) {
++ fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("driver: cannot register port for %s", buf);
+ return -1;
+ }
+ port = fGraphManager->GetPort(port_index);
+ // Add one buffer more latency if "async" mode is used...
+- range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency);
++ range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency;
+ port->SetLatencyRange(JackPlaybackLatency, &range);
+ fPlaybackPortList[i] = port_index;
+ jack_log("JackFreebobDriver::Attach fPlaybackPortList[i] %ld ", port_index);
+@@ -952,106 +953,37 @@
+ const jack_driver_desc_t *
+ driver_get_descriptor () {
+ jack_driver_desc_t * desc;
+- jack_driver_param_desc_t * params;
+- unsigned int i;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
+
+- desc = (jack_driver_desc_t *)calloc (1, sizeof (jack_driver_desc_t));
++ desc = jack_driver_descriptor_construct("freebob", JackDriverMaster, "Linux FreeBob API based audio backend", &filler);
+
+- strcpy (desc->name, "freebob"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Linux FreeBob API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
++ strcpy(value.str, "hw:0");
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "The FireWire device to use. Format is: 'hw:port[,node]'.", NULL);
+
+- desc->nparams = 11;
+-
+- params = (jack_driver_param_desc_t *)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+- desc->params = params;
+-
+- i = 0;
+- strcpy (params[i].name, "device");
+- params[i].character = 'd';
+- params[i].type = JackDriverParamString;
+- strcpy (params[i].value.str, "hw:0");
+- strcpy (params[i].short_desc, "The FireWire device to use. Format is: 'hw:port[,node]'.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "period");
+- params[i].character = 'p';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 1024;
+- strcpy (params[i].short_desc, "Frames per period");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "nperiods");
+- params[i].character = 'n';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 3;
+- strcpy (params[i].short_desc, "Number of periods of playback latency");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "rate");
+- params[i].character = 'r';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 48000U;
+- strcpy (params[i].short_desc, "Sample rate");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "capture");
+- params[i].character = 'C';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Provide capture ports.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "playback");
+- params[i].character = 'P';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 0;
+- strcpy (params[i].short_desc, "Provide playback ports.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "duplex");
+- params[i].character = 'D';
+- params[i].type = JackDriverParamBool;
+- params[i].value.i = 1;
+- strcpy (params[i].short_desc, "Provide both capture and playback ports.");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "input-latency");
+- params[i].character = 'I';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Extra input latency (frames)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "output-latency");
+- params[i].character = 'O';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Extra output latency (frames)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "inchannels");
+- params[i].character = 'i';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Number of input channels to provide (note: currently ignored)");
+- strcpy (params[i].long_desc, params[i].short_desc);
+-
+- i++;
+- strcpy (params[i].name, "outchannels");
+- params[i].character = 'o';
+- params[i].type = JackDriverParamUInt;
+- params[i].value.ui = 0;
+- strcpy (params[i].short_desc, "Number of output channels to provide (note: currently ignored)");
+- strcpy (params[i].long_desc, params[i].short_desc);
++ value.ui = 1024;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = 3;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods of playback latency", NULL);
++
++ value.ui = 48000U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamBool, &value, NULL, "Provide capture ports.", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamBool, &value, NULL, "Provide playback ports.", NULL);
++
++ value.i = 1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports.", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Number of input channels to provide (note: currently ignored)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Number of output channels to provide (note: currently ignored)", NULL);
+
+ return desc;
+ }
+--- a/linux/JackLinuxTime.c
++++ b/linux/JackLinuxTime.c
+@@ -143,7 +143,7 @@
+ exit(1);
+ }
+
+- for ( ; ; )
++ for (;;)
+ {
+ jack_time_t mhz;
+ int ret;
+@@ -166,6 +166,8 @@
+ ret = sscanf(buf, "Clocking: %" SCNu64, &mhz);
+ #elif defined( __s390__ )
+ ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz);
++#elif defined( __sh__ )
++ ret = sscanf(buf, "bogomips : %" SCNu64, &mhz);
+ #else /* MIPS, ARM, alpha */
+ ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz);
+ #endif
+--- a/linux/wscript
++++ b/linux/wscript
+@@ -13,12 +13,14 @@
+
+ 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', 'HAVE_PPOLL']
++
++ #driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL']
++ driver.defines = ['HAVE_CONFIG_H','SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD']
++
+ driver.includes = ['.', '../linux', '../posix', '../common', '../common/jack', '../dbus']
+ driver.target = target
+ driver.source = sources
+@@ -32,7 +34,7 @@
+ if bld.env['BUILD_JACKD'] == True:
+ jackd = bld.new_task_gen('cxx', 'program')
+ jackd.includes = ['../linux', '../posix', '../common/jack', '../common', '../dbus']
+- jackd.defines = 'HAVE_CONFIG_H'
++ jackd.defines = ['HAVE_CONFIG_H','SERVER_SIDE']
+ jackd.source = ['../common/Jackdmp.cpp']
+ if bld.env['IS_LINUX'] and bld.env['BUILD_JACKDBUS']:
+ jackd.source += ['../dbus/reserve.c', '../dbus/audio_reserve.c']
+@@ -57,15 +59,26 @@
+ 'alsa/ice1712.c'
+ ]
+
++ alsarawmidi_driver_src = ['alsarawmidi/JackALSARawMidiDriver.cpp',
++ 'alsarawmidi/JackALSARawMidiInputPort.cpp',
++ 'alsarawmidi/JackALSARawMidiOutputPort.cpp',
++ 'alsarawmidi/JackALSARawMidiPort.cpp',
++ 'alsarawmidi/JackALSARawMidiReceiveQueue.cpp',
++ 'alsarawmidi/JackALSARawMidiSendQueue.cpp',
++ 'alsarawmidi/JackALSARawMidiUtil.cpp'
++ ]
++
+ ffado_driver_src = ['firewire/JackFFADODriver.cpp',
+- 'firewire/JackFFADOMidiInput.cpp',
+- 'firewire/JackFFADOMidiOutput.cpp',
+- '../common/JackPhysicalMidiInput.cpp',
+- '../common/JackPhysicalMidiOutput.cpp'
++ 'firewire/JackFFADOMidiInputPort.cpp',
++ 'firewire/JackFFADOMidiOutputPort.cpp',
++ 'firewire/JackFFADOMidiReceiveQueue.cpp',
++ 'firewire/JackFFADOMidiSendQueue.cpp'
+ ]
+
+ if bld.env['BUILD_DRIVER_ALSA'] == True:
+ create_jack_driver_obj(bld, 'alsa', alsa_driver_src, "ALSA")
++ create_jack_driver_obj(bld, 'alsarawmidi', alsarawmidi_driver_src,
++ "ALSA")
+
+ if bld.env['BUILD_DRIVER_FREEBOB'] == True:
+ create_jack_driver_obj(bld, 'freebob', 'freebob/JackFreebobDriver.cpp', "LIBFREEBOB")
+--- a/macosx/coreaudio/JackCoreAudioAdapter.cpp
++++ b/macosx/coreaudio/JackCoreAudioAdapter.cpp
+@@ -49,15 +49,17 @@
+ CFStringRef UIname;
+
+ err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
+- if (err != noErr)
++ if (err != noErr) {
+ return err;
++ }
+
+ deviceNum = size / sizeof(AudioDeviceID);
+ AudioDeviceID devices[deviceNum];
+
+ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
+- if (err != noErr)
++ if (err != noErr) {
+ return err;
++ }
+
+ for (i = 0; i < deviceNum; i++) {
+ char device_name[256];
+@@ -74,8 +76,9 @@
+
+ size = 256;
+ err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
+- if (err != noErr)
++ if (err != noErr) {
+ return err;
++ }
+
+ jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
+ }
+@@ -83,8 +86,9 @@
+ return noErr;
+
+ error:
+- if (UIname != NULL)
++ if (UIname != NULL) {
+ CFRelease(UIname);
++ }
+ return err;
+ }
+
+@@ -168,7 +172,7 @@
+ switch (inPropertyID) {
+
+ case kAudioDevicePropertyNominalSampleRate: {
+- jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
++ jack_log("JackCoreAudioAdapter::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
+ driver->fState = true;
+ break;
+ }
+@@ -267,27 +271,31 @@
+ }
+
+ OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
+- AudioUnitRenderActionFlags *ioActionFlags,
+- const AudioTimeStamp *inTimeStamp,
+- UInt32 inBusNumber,
+- UInt32 inNumberFrames,
+- AudioBufferList *ioData)
++ AudioUnitRenderActionFlags *ioActionFlags,
++ const AudioTimeStamp *inTimeStamp,
++ UInt32 inBusNumber,
++ UInt32 inNumberFrames,
++ AudioBufferList *ioData)
+ {
+ JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
+- AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
++ OSStatus err = AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
+
+- jack_default_audio_sample_t* inputBuffer[adapter->fCaptureChannels];
+- jack_default_audio_sample_t* outputBuffer[adapter->fPlaybackChannels];
++ if (err == noErr) {
++ jack_default_audio_sample_t* inputBuffer[adapter->fCaptureChannels];
++ jack_default_audio_sample_t* outputBuffer[adapter->fPlaybackChannels];
+
+- for (int i = 0; i < adapter->fCaptureChannels; i++) {
+- inputBuffer[i] = (jack_default_audio_sample_t*)adapter->fInputData->mBuffers[i].mData;
+- }
+- for (int i = 0; i < adapter->fPlaybackChannels; i++) {
+- outputBuffer[i] = (jack_default_audio_sample_t*)ioData->mBuffers[i].mData;
+- }
++ for (int i = 0; i < adapter->fCaptureChannels; i++) {
++ inputBuffer[i] = (jack_default_audio_sample_t*)adapter->fInputData->mBuffers[i].mData;
++ }
++ for (int i = 0; i < adapter->fPlaybackChannels; i++) {
++ outputBuffer[i] = (jack_default_audio_sample_t*)ioData->mBuffers[i].mData;
++ }
+
+- adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, inNumberFrames);
+- return noErr;
++ adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, inNumberFrames);
++ return noErr;
++ } else {
++ return err;
++ }
+ }
+
+ JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
+@@ -391,27 +399,38 @@
+ fPlaying = true;
+ }
+
+- if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0)
+- throw -1;
++ if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0) {
++ throw std::bad_alloc();
++ }
+
+- if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
+- throw -1;
++ if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0) {
++ throw std::bad_alloc();
++ }
+
+- if (SetupBufferSize(fAdaptedBufferSize) < 0)
+- throw -1;
++ if (SetupBufferSize(fAdaptedBufferSize) < 0) {
++ throw std::bad_alloc();
++ }
+
+- if (SetupSampleRate(fAdaptedSampleRate) < 0)
+- throw -1;
++ if (SetupSampleRate(fAdaptedSampleRate) < 0) {
++ throw std::bad_alloc();
++ }
+
+- if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0)
+- throw -1;
++ if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0) {
++ throw std::bad_alloc();
++ }
+
+- if (fCapturing && fCaptureChannels > 0)
+- if (SetupBuffers(fCaptureChannels) < 0)
+- throw -1;
++ if (fCapturing && fCaptureChannels > 0) {
++ if (SetupBuffers(fCaptureChannels) < 0) {
++ throw std::bad_alloc();
++ }
++ }
+
+- if (AddListeners() < 0)
+- throw -1;
++ if (AddListeners() < 0) {
++ throw std::bad_alloc();
++ }
++
++ GetStreamLatencies(fDeviceID, true, fInputLatencies);
++ GetStreamLatencies(fDeviceID, false, fOutputLatencies);
+ }
+
+ OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
+@@ -421,21 +440,26 @@
+ AudioDeviceID inDefault;
+ AudioDeviceID outDefault;
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
+ return res;
++ }
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
+ return res;
++ }
+
+ jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
+
+ // Get the device only if default input and output are the same
+- if (inDefault == outDefault) {
+- *id = inDefault;
+- return noErr;
+- } else {
++ if (inDefault != outDefault) {
+ jack_error("Default input and output devices are not the same !!");
+ return kAudioHardwareBadDeviceError;
++ } else if (inDefault == 0) {
++ jack_error("Default input and output devices are null !!");
++ return kAudioHardwareBadDeviceError;
++ } else {
++ *id = inDefault;
++ return noErr;
+ }
+ }
+
+@@ -444,20 +468,17 @@
+ OSStatus err = noErr;
+ UInt32 outSize;
+ Boolean outWritable;
+- AudioBufferList* bufferList = 0;
+
+ channelCount = 0;
+ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
+ if (err == noErr) {
+- bufferList = (AudioBufferList*)malloc(outSize);
++ AudioBufferList bufferList[outSize];
+ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
+ if (err == noErr) {
+- for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
++ for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++) {
+ channelCount += bufferList->mBuffers[i].mNumberChannels;
++ }
+ }
+-
+- if (bufferList)
+- free(bufferList);
+ }
+
+ return err;
+@@ -485,11 +506,12 @@
+ UInt32 theSize = sizeof(UInt32);
+ AudioDeviceID inDefault;
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
+ return res;
++ }
+
+ if (inDefault == 0) {
+- jack_error("Error : input device is 0, please select a correct one !!");
++ jack_error("Error: default input device is 0, please select a correct one !!");
+ return -1;
+ }
+ jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
+@@ -503,11 +525,12 @@
+ UInt32 theSize = sizeof(UInt32);
+ AudioDeviceID outDefault;
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
+ return res;
++ }
+
+ if (outDefault == 0) {
+- jack_error("Error : output device is 0, please select a correct one !!");
++ jack_error("Error: default output device is 0, please select a correct one !!");
+ return -1;
+ }
+ jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
+@@ -521,6 +544,39 @@
+ return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
+ }
+
++AudioDeviceID JackCoreAudioAdapter::GetDeviceIDFromName(const char* name)
++{
++ UInt32 size;
++ Boolean isWritable;
++ int i, deviceNum;
++
++ OSStatus err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
++ if (err != noErr) {
++ return -1;
++ }
++
++ deviceNum = size / sizeof(AudioDeviceID);
++ AudioDeviceID devices[deviceNum];
++
++ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
++ if (err != noErr) {
++ return err;
++ }
++
++ for (i = 0; i < deviceNum; i++) {
++ char device_name[256];
++ size = 256;
++ err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
++ if (err != noErr) {
++ return -1;
++ } else if (strcmp(device_name, name) == 0) {
++ return devices[i];
++ }
++ }
++
++ return -1;
++}
++
+ // Setup
+ int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
+ const char* playback_driver_uid,
+@@ -533,6 +589,7 @@
+
+ // Duplex
+ if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
++ jack_log("JackCoreAudioDriver::Open duplex");
+
+ // Same device for capture and playback...
+ if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
+@@ -570,8 +627,9 @@
+ }
+ }
+
+- if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
++ if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
+ return -1;
++ }
+ }
+
+ // Capture only
+@@ -604,18 +662,18 @@
+
+ // Use default driver in duplex mode
+ } else {
+- jack_log("JackCoreAudioDriver::Open default driver");
++ jack_log("JackCoreAudioAdapter::Open default driver");
+ if (GetDefaultDevice(&fDeviceID) != noErr) {
+ jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
+
+ // Creates aggregate device
+- AudioDeviceID captureID, playbackID;
++ AudioDeviceID captureID = -1, playbackID = -1;
+
+ if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
+ jack_log("Will take default input");
+ if (GetDefaultInputDevice(&captureID) != noErr) {
+ jack_error("Cannot open default input device");
+- return -1;
++ goto built_in;
+ }
+ }
+
+@@ -623,16 +681,39 @@
+ jack_log("Will take default output");
+ if (GetDefaultOutputDevice(&playbackID) != noErr) {
+ jack_error("Cannot open default output device");
+- return -1;
++ goto built_in;
+ }
+ }
+
+- if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
+- return -1;
++ if (captureID > 0 && playbackID > 0) {
++ if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
++ goto built_in;
++ }
++ } else {
++ jack_error("Cannot use default input/output");
++ goto built_in;
++ }
+ }
+ }
+
+ return 0;
++
++built_in:
++
++ // Aggregate built-in input and output
++ AudioDeviceID captureID = GetDeviceIDFromName("Built-in Input");
++ AudioDeviceID playbackID = GetDeviceIDFromName("Built-in Output");
++
++ if (captureID > 0 && playbackID > 0) {
++ if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
++ return -1;
++ }
++ } else {
++ jack_error("Cannot aggregate built-in input and output");
++ return -1;
++ }
++
++ return 0;
+ }
+
+ int JackCoreAudioAdapter::SetupChannels(bool capturing,
+@@ -669,14 +750,16 @@
+
+ if (inchannels > in_nChannels) {
+ jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
+- if (strict)
++ if (strict) {
+ return -1;
++ }
+ }
+
+ if (outchannels > out_nChannels) {
+ jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
+- if (strict)
++ if (strict) {
+ return -1;
++ }
+ }
+
+ if (inchannels == -1) {
+@@ -778,8 +861,9 @@
+ void JackCoreAudioAdapter::DisposeBuffers()
+ {
+ if (fInputData) {
+- for (int i = 0; i < fCaptureChannels; i++)
++ for (int i = 0; i < fCaptureChannels; i++) {
+ free(fInputData->mBuffers[i].mData);
++ }
+ free(fInputData);
+ fInputData = 0;
+ }
+@@ -894,7 +978,7 @@
+ }
+
+ // Setup channel map
+- if (capturing && inchannels > 0 && inchannels < in_nChannels) {
++ if (capturing && inchannels > 0 && inchannels <= in_nChannels) {
+ SInt32 chanArr[in_nChannels];
+ for (int i = 0; i < in_nChannels; i++) {
+ chanArr[i] = -1;
+@@ -910,7 +994,7 @@
+ }
+ }
+
+- if (playing && outchannels > 0 && outchannels < out_nChannels) {
++ if (playing && outchannels > 0 && outchannels <= out_nChannels) {
+ SInt32 chanArr[out_nChannels];
+ for (int i = 0; i < out_nChannels; i++) {
+ chanArr[i] = -1;
+@@ -1030,14 +1114,14 @@
+
+ osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
++ jack_error("JackCoreAudioAdapter::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
+ printError(osErr);
+ return osErr;
+ }
+
+ osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
++ jack_error("JackCoreAudioAdapter::DestroyAggregateDevice : AudioObjectGetPropertyData error");
+ printError(osErr);
+ return osErr;
+ }
+@@ -1115,18 +1199,18 @@
+
+ for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
+ if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : cannot set SR of input device");
+ } else {
+ // Check clock domain
+ osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
+ if (osErr != 0) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
+ printError(osErr);
+ } else {
+ keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
+- jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
++ jack_log("JackCoreAudioAdapter::CreateAggregateDevice : input clockdomain = %d", clockdomain);
+ if (clockdomain != 0 && clockdomain != keptclockdomain) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
+ need_clock_drift_compensation = true;
+ }
+ }
+@@ -1135,18 +1219,18 @@
+
+ for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
+ if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : cannot set SR of output device");
+ } else {
+ // Check clock domain
+ osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
+ if (osErr != 0) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
+ printError(osErr);
+ } else {
+ keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
+- jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
++ jack_log("JackCoreAudioAdapter::CreateAggregateDevice : output clockdomain = %d", clockdomain);
+ if (clockdomain != 0 && clockdomain != keptclockdomain) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
+ need_clock_drift_compensation = true;
+ }
+ }
+@@ -1175,7 +1259,7 @@
+
+ osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
+ printError(osErr);
+ return osErr;
+ }
+@@ -1191,7 +1275,7 @@
+
+ osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
+ printError(osErr);
+ return osErr;
+ }
+@@ -1218,13 +1302,13 @@
+ SInt32 system;
+ Gestalt(gestaltSystemVersion, &system);
+
+- jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
++ jack_log("JackCoreAudioAdapter::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
+
+ // Starting with 10.5.4 systems, the AD can be internal... (better)
+ if (system < 0x00001054) {
+- jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
++ jack_log("JackCoreAudioAdapter::CreateAggregateDevice : public aggregate device....");
+ } else {
+- jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
++ jack_log("JackCoreAudioAdapter::CreateAggregateDevice : private aggregate device....");
+ CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
+ }
+
+@@ -1277,8 +1361,9 @@
+ vector<CFStringRef> captureDeviceUID;
+ for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
+ CFStringRef ref = GetDeviceName(captureDeviceID[i]);
+- if (ref == NULL)
++ if (ref == NULL) {
+ return -1;
++ }
+ captureDeviceUID.push_back(ref);
+ // input sub-devices in this example, so append the sub-device's UID to the CFArray
+ CFArrayAppendValue(subDevicesArray, ref);
+@@ -1287,8 +1372,9 @@
+ vector<CFStringRef> playbackDeviceUID;
+ for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
+ CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
+- if (ref == NULL)
++ if (ref == NULL) {
+ return -1;
++ }
+ playbackDeviceUID.push_back(ref);
+ // output sub-devices in this example, so append the sub-device's UID to the CFArray
+ CFArrayAppendValue(subDevicesArray, ref);
+@@ -1306,14 +1392,14 @@
+
+ osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
+ printError(osErr);
+ goto error;
+ }
+
+ osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : AudioObjectGetPropertyData error");
+ printError(osErr);
+ goto error;
+ }
+@@ -1332,7 +1418,7 @@
+ outDataSize = sizeof(CFMutableArrayRef);
+ osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
+ printError(osErr);
+ goto error;
+ }
+@@ -1352,7 +1438,7 @@
+ outDataSize = sizeof(CFStringRef);
+ osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]); // First apture is master...
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
+ printError(osErr);
+ goto error;
+ }
+@@ -1370,19 +1456,19 @@
+ // Get the property data size
+ osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
+ printError(osErr);
+ }
+
+ // Calculate the number of object IDs
+ subDevicesNum = outSize / sizeof(AudioObjectID);
+- jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
++ jack_info("JackCoreAudioAdapter::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
+ AudioObjectID subDevices[subDevicesNum];
+ outSize = sizeof(subDevices);
+
+ osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
+ printError(osErr);
+ }
+
+@@ -1391,7 +1477,7 @@
+ UInt32 theDriftCompensationValue = 1;
+ osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
+ if (osErr != noErr) {
+- jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
++ jack_error("JackCoreAudioAdapter::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
+ printError(osErr);
+ }
+ }
+@@ -1414,8 +1500,9 @@
+ CFRelease(aggDeviceDict);
+ CFRelease(subDevicesArray);
+
+- if (subDevicesArrayClock)
++ if (subDevicesArrayClock) {
+ CFRelease(subDevicesArrayClock);
++ }
+
+ // release the device UID
+ for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
+@@ -1472,23 +1559,112 @@
+ DisposeBuffers();
+ CloseAUHAL();
+ RemoveListeners();
+- if (fPluginID > 0)
++ if (fPluginID > 0) {
+ DestroyAggregateDevice();
++ }
+ return 0;
+ }
+
+-int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
+- JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
++int JackCoreAudioAdapter::SetSampleRate(jack_nframes_t sample_rate)
++{
++ JackAudioAdapterInterface::SetHostSampleRate(sample_rate);
+ Close();
+ return Open();
+ }
+
+-int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
+- JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
++int JackCoreAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
++{
++ JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
+ Close();
+ return Open();
+ }
+
++OSStatus JackCoreAudioAdapter::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
++{
++ OSStatus err = noErr;
++ UInt32 outSize1, outSize2, outSize3;
++ Boolean outWritable;
++
++ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
++ if (err == noErr) {
++ int stream_count = outSize1 / sizeof(UInt32);
++ AudioStreamID streamIDs[stream_count];
++ AudioBufferList bufferList[stream_count];
++ UInt32 streamLatency;
++ outSize2 = sizeof(UInt32);
++
++ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
++ return err;
++ }
++
++ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
++ return err;
++ }
++
++ for (int i = 0; i < stream_count; i++) {
++ err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
++ return err;
++ }
++ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
++ return err;
++ }
++ // Push 'channel' time the stream latency
++ for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
++ latencies.push_back(streamLatency);
++ }
++ }
++ }
++ return err;
++}
++
++int JackCoreAudioAdapter::GetLatency(int port_index, bool input)
++{
++ UInt32 size = sizeof(UInt32);
++ UInt32 value1 = 0;
++ UInt32 value2 = 0;
++
++ OSStatus err = AudioDeviceGetProperty(fDeviceID, 0, input, kAudioDevicePropertyLatency, &size, &value1);
++ if (err != noErr) {
++ jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
++ }
++ err = AudioDeviceGetProperty(fDeviceID, 0, input, kAudioDevicePropertySafetyOffset, &size, &value2);
++ if (err != noErr) {
++ jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
++ }
++
++ // TODO : add stream latency
++
++ return value1 + value2 + fAdaptedBufferSize;
++}
++
++int JackCoreAudioAdapter::GetInputLatency(int port_index)
++{
++ if (port_index < int(fInputLatencies.size())) {
++ return GetLatency(port_index, true) + fInputLatencies[port_index];
++ } else {
++ // No stream latency
++ return GetLatency(port_index, true);
++ }
++}
++
++int JackCoreAudioAdapter::GetOutputLatency(int port_index)
++{
++ if (port_index < int(fOutputLatencies.size())) {
++ return GetLatency(port_index, false) + fOutputLatencies[port_index];
++ } else {
++ // No stream latency
++ return GetLatency(port_index, false);
++ }
++}
++
+ } // namespace
+
+ #ifdef __cplusplus
+@@ -1498,116 +1674,44 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 13;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "channels");
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = -1;
+- strcpy(desc->params[i].short_desc, "Maximum number of channels");
+- strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used");
+-
+- i++;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = -1;
+- strcpy(desc->params[i].short_desc, "Maximum number of input channels");
+- strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used");
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = -1;
+- strcpy(desc->params[i].short_desc, "Maximum number of output channels");
+- strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used");
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].short_desc, "Input CoreAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].short_desc, "Output CoreAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 44100U;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 512U;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "duplex");
+- desc->params[i].character = 'D';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = TRUE;
+- strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].short_desc, "CoreAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "list-devices");
+- desc->params[i].character = 'l';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = TRUE;
+- strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "quality");
+- desc->params[i].character = 'q';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ring-buffer");
+- desc->params[i].character = 'g';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 32768;
+- strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
+- strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
+-
+- i++;
+- strcpy(desc->params[i].name, "clock-drift");
+- desc->params[i].character = 's';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Clock drift compensation");
+- strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device");
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
++
++ value.i = -1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used");
++ jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used");
++ jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used");
++
++ value.str[0] = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output CoreAudio device name", NULL);
++
++ value.ui = 44100U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = 512U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.i = TRUE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
++
++ value.str[0] = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
++
++ value.i = TRUE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
++
++ value.ui = 32768;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
++
++ value.i = FALSE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "clock-drift", 's', JackDriverParamBool, &value, NULL, "Clock drift compensation", "Whether to compensate clock drift in dynamically created aggregate device");
+
+ return desc;
+ }
+--- a/macosx/coreaudio/JackCoreAudioAdapter.h
++++ b/macosx/coreaudio/JackCoreAudioAdapter.h
+@@ -41,7 +41,7 @@
+ #define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF)
+
+ #define WAIT_COUNTER 60
+-
++
+ /*!
+ \brief Audio adapter using CoreAudio API.
+ */
+@@ -53,16 +53,19 @@
+
+ AudioUnit fAUHAL;
+ AudioBufferList* fInputData;
+-
++
+ char fCaptureUID[256];
+ char fPlaybackUID[256];
+-
++
+ bool fCapturing;
+ bool fPlaying;
+
+ AudioDeviceID fDeviceID; // Used "duplex" device
+ AudioObjectID fPluginID; // Used for aggregate device
+
++ vector<int> fInputLatencies;
++ vector<int> fOutputLatencies;
++
+ bool fState;
+
+ AudioUnitRenderActionFlags* fActionFags;
+@@ -93,13 +96,14 @@
+ OSStatus GetDefaultInputDevice(AudioDeviceID* id);
+ OSStatus GetDefaultOutputDevice(AudioDeviceID* id);
+ OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name);
++ AudioDeviceID GetDeviceIDFromName(const char* name);
+
+ // Setup
+ OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice);
+ OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice);
+ OSStatus DestroyAggregateDevice();
+ bool IsAggregateDevice(AudioDeviceID device);
+-
++
+ int SetupDevices(const char* capture_driver_uid,
+ const char* playback_driver_uid,
+ char* capture_driver_name,
+@@ -126,17 +130,20 @@
+ int SetupBufferSize(jack_nframes_t buffer_size);
+ int SetupSampleRate(jack_nframes_t samplerate);
+ int SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate);
+-
++
+ int SetupBuffers(int inchannels);
+ void DisposeBuffers();
+ void CloseAUHAL();
+-
++
+ int AddListeners();
+ void RemoveListeners();
+
++ int GetLatency(int port_index, bool input);
++ OSStatus GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies);
++
+ public:
+
+- JackCoreAudioAdapter( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
++ JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
+ ~JackCoreAudioAdapter()
+ {}
+
+@@ -146,8 +153,12 @@
+ virtual int SetSampleRate(jack_nframes_t sample_rate);
+ virtual int SetBufferSize(jack_nframes_t buffer_size);
+
++ virtual int GetInputLatency(int port_index);
++ virtual int GetOutputLatency(int port_index);
+ };
+-}
++
++
++} // end of namepace
+
+ #ifdef __cplusplus
+ extern "C"
+--- a/macosx/coreaudio/JackCoreAudioDriver.cpp
++++ b/macosx/coreaudio/JackCoreAudioDriver.cpp
+@@ -27,7 +27,9 @@
+ #include "JackGlobals.h"
+ #include "JackTools.h"
+ #include "JackCompilerDeps.h"
++#include "JackLockedEngine.h"
+
++#include <sstream>
+ #include <iostream>
+ #include <CoreServices/CoreServices.h>
+ #include <CoreFoundation/CFNumber.h>
+@@ -136,15 +138,17 @@
+ CFStringRef UIname;
+
+ err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
+- if (err != noErr)
++ if (err != noErr) {
+ return err;
++ }
+
+ deviceNum = size / sizeof(AudioDeviceID);
+ AudioDeviceID devices[deviceNum];
+
+ err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
+- if (err != noErr)
++ if (err != noErr) {
+ return err;
++ }
+
+ for (i = 0; i < deviceNum; i++) {
+ char device_name[256];
+@@ -161,17 +165,19 @@
+
+ size = 256;
+ err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
+- if (err != noErr)
++ if (err != noErr) {
+ return err;
++ }
+
+- jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
++ jack_info("Device name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
+ }
+
+ return noErr;
+
+ error:
+- if (UIname != NULL)
++ if (UIname != NULL) {
+ CFRelease(UIname);
++ }
+ return err;
+ }
+
+@@ -183,19 +189,33 @@
+ return (err == noErr) ? UIname : NULL;
+ }
+
+-OSStatus JackCoreAudioDriver::Render(void *inRefCon,
+- AudioUnitRenderActionFlags *ioActionFlags,
+- const AudioTimeStamp *inTimeStamp,
++static void ParseChannelList(const string& list, vector<int>& result)
++{
++ stringstream ss(list);
++ string token;
++ int chan;
++
++ while (ss >> token) {
++ istringstream ins;
++ ins.str(token);
++ ins >> chan;
++ result.push_back(chan);
++ }
++}
++
++OSStatus JackCoreAudioDriver::Render(void* inRefCon,
++ AudioUnitRenderActionFlags* ioActionFlags,
++ const AudioTimeStamp* inTimeStamp,
+ UInt32 inBusNumber,
+ UInt32 inNumberFrames,
+- AudioBufferList *ioData)
++ AudioBufferList* ioData)
+ {
+ JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
+ driver->fActionFags = ioActionFlags;
+- driver->fCurrentTime = (AudioTimeStamp *)inTimeStamp;
++ driver->fCurrentTime = inTimeStamp;
+ driver->fDriverOutputData = ioData;
+
+- // Setup threadded based log function once...
++ // Setup threaded based log function et get RT thread parameters once...
+ if (set_threaded_log_function()) {
+
+ jack_log("set_threaded_log_function");
+@@ -205,19 +225,31 @@
+ jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(driver->fComputationGrain * 100));
+ driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain;
+ }
+-
+- // Signal waiting start function...
+- driver->fState = true;
+ }
+
++ // Signal waiting start function...
++ driver->fState = true;
++
+ driver->CycleTakeBeginTime();
+- return driver->Process();
++
++ if (driver->Process() < 0) {
++ jack_error("Process error, stopping driver.");
++ driver->NotifyFailure(JackBackendError, "Process error, stopping driver."); // Message length limited to JACK_MESSAGE_SIZE
++ driver->Stop();
++ kill(JackTools::GetPID(), SIGINT);
++ return kAudioHardwareUnsupportedOperationError;
++ } else {
++ return noErr;
++ }
+ }
+
+ int JackCoreAudioDriver::Read()
+ {
+- OSStatus err = AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
+- return (err == noErr) ? 0 : -1;
++ if (fCaptureChannels > 0) { // Calling AudioUnitRender with no input returns a '????' error (callback setting issue ??), so hack to avoid it here...
++ return (AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData) == noErr) ? 0 : -1;
++ } else {
++ return 0;
++ }
+ }
+
+ int JackCoreAudioDriver::Write()
+@@ -228,8 +260,9 @@
+ int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
+ memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
+ // Monitor ports
+- if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
++ if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
+ memcpy(GetMonitorBuffer(i), buffer, size);
++ }
+ } else {
+ memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
+ }
+@@ -249,17 +282,47 @@
+
+ case kAudioDevicePropertyNominalSampleRate: {
+ jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
+- driver->fState = true;
+ // Check new sample rate
+- Float64 sampleRate;
++ Float64 tmp_sample_rate;
+ UInt32 outSize = sizeof(Float64);
+- OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
++ OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
+ if (err != noErr) {
+ jack_error("Cannot get current sample rate");
+ printError(err);
+ } else {
+- jack_log("SRNotificationCallback : checked sample rate = %f", sampleRate);
++ jack_log("SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
++ }
++ driver->fState = true;
++ break;
++ }
++ }
++
++ return noErr;
++}
++
++OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
++ UInt32 inChannel,
++ Boolean isInput,
++ AudioDevicePropertyID inPropertyID,
++ void* inClientData)
++{
++ JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
++
++ switch (inPropertyID) {
++
++ case kAudioDevicePropertyBufferFrameSize: {
++ jack_log("JackCoreAudioDriver::BSNotificationCallback kAudioDevicePropertyBufferFrameSize");
++ // Check new buffer size
++ UInt32 tmp_buffer_size;
++ UInt32 outSize = sizeof(UInt32);
++ OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
++ if (err != noErr) {
++ jack_error("Cannot get current buffer size");
++ printError(err);
++ } else {
++ jack_log("BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
+ }
++ driver->fState = true;
+ break;
+ }
+ }
+@@ -303,41 +366,42 @@
+ }
+
+ case kAudioDevicePropertyNominalSampleRate: {
+- Float64 sampleRate = 0;
++ Float64 sample_rate = 0;
+ UInt32 outsize = sizeof(Float64);
+- OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate);
+- if (err != noErr)
++ OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
++ if (err != noErr) {
+ return kAudioHardwareUnsupportedOperationError;
++ }
+
+ char device_name[256];
+ const char* digidesign_name = "Digidesign";
+ driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
+
+- if (sampleRate != driver->fEngineControl->fSampleRate) {
++ if (sample_rate != driver->fEngineControl->fSampleRate) {
+
+ // Digidesign hardware, so "special" code : change the SR again here
+- if (strncmp(device_name, digidesign_name, sizeof(digidesign_name)) == 0) {
++ if (strncmp(device_name, digidesign_name, 10) == 0) {
+
+ jack_log("Digidesign HW = %s", device_name);
+
+ // Set sample rate again...
+- sampleRate = driver->fEngineControl->fSampleRate;
+- err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sampleRate);
++ sample_rate = driver->fEngineControl->fSampleRate;
++ err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sample_rate);
+ if (err != noErr) {
+- jack_error("Cannot set sample rate = %f", sampleRate);
++ jack_error("Cannot set sample rate = %f", sample_rate);
+ printError(err);
+ } else {
+- jack_log("Set sample rate = %f", sampleRate);
++ jack_log("Set sample rate = %f", sample_rate);
+ }
+
+ // Check new sample rate again...
+ outsize = sizeof(Float64);
+- err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sampleRate);
++ err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
+ if (err != noErr) {
+ jack_error("Cannot get current sample rate");
+ printError(err);
+ } else {
+- jack_log("Checked sample rate = %f", sampleRate);
++ jack_log("Checked sample rate = %f", sample_rate);
+ }
+ return noErr;
+
+@@ -377,21 +441,26 @@
+ AudioDeviceID inDefault;
+ AudioDeviceID outDefault;
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
+ return res;
++ }
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
+ return res;
++ }
+
+ jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
+
+ // Get the device only if default input and output are the same
+- if (inDefault == outDefault) {
+- *id = inDefault;
+- return noErr;
+- } else {
++ if (inDefault != outDefault) {
+ jack_error("Default input and output devices are not the same !!");
+ return kAudioHardwareBadDeviceError;
++ } else if (inDefault == 0) {
++ jack_error("Default input and output devices are null !!");
++ return kAudioHardwareBadDeviceError;
++ } else {
++ *id = inDefault;
++ return noErr;
+ }
+ }
+
+@@ -401,11 +470,12 @@
+ UInt32 theSize = sizeof(UInt32);
+ AudioDeviceID inDefault;
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
+ return res;
++ }
+
+ if (inDefault == 0) {
+- jack_error("Error : input device is 0, please select a correct one !!");
++ jack_error("Error: default input device is 0, please select a correct one !!");
+ return -1;
+ }
+ jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
+@@ -419,11 +489,12 @@
+ UInt32 theSize = sizeof(UInt32);
+ AudioDeviceID outDefault;
+
+- if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
++ if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
+ return res;
++ }
+
+ if (outDefault == 0) {
+- jack_error("Error : output device is 0, please select a correct one !!");
++ jack_error("Error: default output device is 0, please select a correct one !!");
+ return -1;
+ }
+ jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
+@@ -440,17 +511,66 @@
+ OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
+ {
+ OSStatus err = noErr;
+- UInt32 outSize;
++ UInt32 outSize;
+ Boolean outWritable;
+
+ channelCount = 0;
+ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
+ if (err == noErr) {
+- AudioBufferList bufferList[outSize];
++ int stream_count = outSize / sizeof(AudioBufferList);
++ AudioBufferList bufferList[stream_count];
+ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
+ if (err == noErr) {
+- for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
++ for (uint i = 0; i < bufferList->mNumberBuffers; i++) {
+ channelCount += bufferList->mBuffers[i].mNumberChannels;
++ //jack_info("GetTotalChannels stream = %d channels = %d", i, bufferList->mBuffers[i].mNumberChannels);
++ }
++ }
++ }
++ return err;
++}
++
++OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
++{
++ OSStatus err = noErr;
++ UInt32 outSize1, outSize2, outSize3;
++ Boolean outWritable;
++
++ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
++ if (err == noErr) {
++ int stream_count = outSize1 / sizeof(UInt32);
++ AudioStreamID streamIDs[stream_count];
++ AudioBufferList bufferList[stream_count];
++ UInt32 streamLatency;
++ outSize2 = sizeof(UInt32);
++
++ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
++ return err;
++ }
++
++ err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
++ return err;
++ }
++
++ for (int i = 0; i < stream_count; i++) {
++ err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
++ return err;
++ }
++ err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
++ if (err != noErr) {
++ jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
++ return err;
++ }
++ // Push 'channel' time the stream latency
++ for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
++ latencies.push_back(streamLatency);
++ }
+ }
+ }
+ return err;
+@@ -480,7 +600,7 @@
+ pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
+ UInt32 outDataSize;
+
+- if (fPluginID > 0) {
++ if (fPluginID > 0) {
+
+ osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
+ if (osErr != noErr) {
+@@ -725,8 +845,9 @@
+ vector<CFStringRef> captureDeviceUID;
+ for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
+ CFStringRef ref = GetDeviceName(captureDeviceID[i]);
+- if (ref == NULL)
++ if (ref == NULL) {
+ return -1;
++ }
+ captureDeviceUID.push_back(ref);
+ // input sub-devices in this example, so append the sub-device's UID to the CFArray
+ CFArrayAppendValue(subDevicesArray, ref);
+@@ -735,8 +856,9 @@
+ vector<CFStringRef> playbackDeviceUID;
+ for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
+ CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
+- if (ref == NULL)
++ if (ref == NULL) {
+ return -1;
++ }
+ playbackDeviceUID.push_back(ref);
+ // output sub-devices in this example, so append the sub-device's UID to the CFArray
+ CFArrayAppendValue(subDevicesArray, ref);
+@@ -862,8 +984,9 @@
+ CFRelease(aggDeviceDict);
+ CFRelease(subDevicesArray);
+
+- if (subDevicesArrayClock)
++ if (subDevicesArrayClock) {
+ CFRelease(subDevicesArrayClock);
++ }
+
+ // release the device UID
+ for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
+@@ -931,8 +1054,9 @@
+ }
+ }
+
+- if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
++ if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
+ return -1;
++ }
+ }
+
+ // Capture only
+@@ -990,8 +1114,9 @@
+ }
+ }
+
+- if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
++ if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
+ return -1;
++ }
+ }
+ }
+
+@@ -1035,14 +1160,16 @@
+
+ if (inchannels > in_nChannels) {
+ jack_error("This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels);
+- if (strict)
++ if (strict) {
+ return -1;
++ }
+ }
+
+ if (outchannels > out_nChannels) {
+ jack_error("This device hasn't required output channels outchannels = %d out_nChannels = %d", outchannels, out_nChannels);
+- if (strict)
++ if (strict) {
+ return -1;
++ }
+ }
+
+ if (inchannels == -1) {
+@@ -1061,42 +1188,101 @@
+ int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
+ {
+ // Setting buffer size
++ OSStatus err = noErr;
++ UInt32 tmp_buffer_size = buffer_size;
+ UInt32 outSize = sizeof(UInt32);
+- OSStatus err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
++
++ err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
+ if (err != noErr) {
+- jack_error("Cannot set buffer size %ld", buffer_size);
++ jack_error("Cannot get buffer size %ld", buffer_size);
+ printError(err);
+ return -1;
++ } else {
++ jack_log("Current buffer size = %ld", tmp_buffer_size);
++ }
++
++ // If needed, set new buffer size
++ if (buffer_size != tmp_buffer_size) {
++ tmp_buffer_size = buffer_size;
++
++ // To get BS change notification
++ err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback, this);
++ if (err != noErr) {
++ jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
++ printError(err);
++ return -1;
++ }
++
++ // Waiting for BS change notification
++ int count = 0;
++ fState = false;
++
++ err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
++ if (err != noErr) {
++ jack_error("Cannot set buffer size = %ld", tmp_buffer_size);
++ printError(err);
++ goto error;
++ }
++
++ while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
++ usleep(100000);
++ jack_log("Wait count = %d", count);
++ }
++
++ if (count >= WAIT_NOTIFICATION_COUNTER) {
++ jack_error("Did not get buffer size notification...");
++ goto error;
++ }
++
++ // Check new buffer size
++ outSize = sizeof(UInt32);
++ err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
++ if (err != noErr) {
++ jack_error("Cannot get current buffer size");
++ printError(err);
++ } else {
++ jack_log("Checked buffer size = %ld", tmp_buffer_size);
++ }
++
++ // Remove BS change notification
++ AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
+ }
+
+ return 0;
++
++error:
++
++ // Remove SR change notification
++ AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
++ return -1;
++
+ }
+
+-int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t samplerate)
++int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
+ {
+- return SetupSampleRateAux(fDeviceID, samplerate);
++ return SetupSampleRateAux(fDeviceID, sample_rate);
+ }
+
+-int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate)
++int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
+ {
+ OSStatus err = noErr;
+ UInt32 outSize;
+- Float64 sampleRate;
++ Float64 tmp_sample_rate;
+
+ // Get sample rate
+ outSize = sizeof(Float64);
+- err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
++ err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
+ if (err != noErr) {
+ jack_error("Cannot get current sample rate");
+ printError(err);
+ return -1;
+ } else {
+- jack_log("Current sample rate = %f", sampleRate);
++ jack_log("Current sample rate = %f", tmp_sample_rate);
+ }
+
+ // If needed, set new sample rate
+- if (samplerate != (jack_nframes_t)sampleRate) {
+- sampleRate = (Float64)samplerate;
++ if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
++ tmp_sample_rate = (Float64)sample_rate;
+
+ // To get SR change notification
+ err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
+@@ -1105,28 +1291,36 @@
+ printError(err);
+ return -1;
+ }
+- err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
++
++ // Waiting for SR change notification
++ int count = 0;
++ fState = false;
++
++ err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
+ if (err != noErr) {
+- jack_error("Cannot set sample rate = %ld", samplerate);
++ jack_error("Cannot set sample rate = %ld", sample_rate);
+ printError(err);
+- return -1;
++ goto error;
+ }
+
+- // Waiting for SR change notification
+- int count = 0;
+- while (!fState && count++ < WAIT_COUNTER) {
++ while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
+ usleep(100000);
+ jack_log("Wait count = %d", count);
+ }
+
++ if (count >= WAIT_NOTIFICATION_COUNTER) {
++ jack_error("Did not get sample rate notification...");
++ goto error;
++ }
++
+ // Check new sample rate
+ outSize = sizeof(Float64);
+- err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
++ err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
+ if (err != noErr) {
+ jack_error("Cannot get current sample rate");
+ printError(err);
+ } else {
+- jack_log("Checked sample rate = %f", sampleRate);
++ jack_log("Checked sample rate = %f", tmp_sample_rate);
+ }
+
+ // Remove SR change notification
+@@ -1134,6 +1328,12 @@
+ }
+
+ return 0;
++
++error:
++
++ // Remove SR change notification
++ AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
++ return -1;
+ }
+
+ int JackCoreAudioDriver::OpenAUHAL(bool capturing,
+@@ -1142,8 +1342,10 @@
+ int outchannels,
+ int in_nChannels,
+ int out_nChannels,
++ const vector<int>& chan_in_list,
++ const vector<int>& chan_out_list,
+ jack_nframes_t buffer_size,
+- jack_nframes_t samplerate)
++ jack_nframes_t sample_rate)
+ {
+ ComponentResult err1;
+ UInt32 enableIO;
+@@ -1151,7 +1353,8 @@
+ AudioDeviceID currAudioDeviceID;
+ UInt32 size;
+
+- jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels);
++ jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d chan_in_list = %d chan_out_list = %d",
++ capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, chan_in_list.size(), chan_out_list.size());
+
+ if (inchannels == 0 && outchannels == 0) {
+ jack_error("No input and output channels...");
+@@ -1244,34 +1447,69 @@
+ }
+ }
+
+- // Setup channel map
+- if (capturing && inchannels > 0 && inchannels < in_nChannels) {
++ // Setup input channel map
++ if (capturing && inchannels > 0 && inchannels <= in_nChannels) {
+ SInt32 chanArr[in_nChannels];
+ for (int i = 0; i < in_nChannels; i++) {
+ chanArr[i] = -1;
+ }
+- for (int i = 0; i < inchannels; i++) {
+- chanArr[i] = i;
++ // Explicit mapping
++ if (chan_in_list.size() > 0) {
++ for (uint i = 0; i < chan_in_list.size(); i++) {
++ int chan = chan_in_list[i];
++ if (chan < out_nChannels) {
++ // The wanted JACK input index for the 'chan' channel value
++ chanArr[chan] = i;
++ jack_info("Input channel = %d ==> JACK input port = %d", chan, i);
++ } else {
++ jack_info("Error input channel number is incorrect : %d", chan);
++ goto error;
++ }
++ }
++ } else {
++ for (int i = 0; i < inchannels; i++) {
++ chanArr[i] = i;
++ jack_info("Input channel = %d ==> JACK input port = %d", chanArr[i], i);
++ }
+ }
++
+ AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
+ if (err1 != noErr) {
+- jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
++ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
+ printError(err1);
+ goto error;
+ }
+ }
+
+- if (playing && outchannels > 0 && outchannels < out_nChannels) {
++ // Setup output channel map
++ if (playing && outchannels > 0 && outchannels <= out_nChannels) {
+ SInt32 chanArr[out_nChannels];
+ for (int i = 0; i < out_nChannels; i++) {
+ chanArr[i] = -1;
+ }
+- for (int i = 0; i < outchannels; i++) {
+- chanArr[i] = i;
++ // Explicit mapping
++ if (chan_out_list.size() > 0) {
++ for (uint i = 0; i < chan_out_list.size(); i++) {
++ int chan = chan_out_list[i];
++ if (chan < out_nChannels) {
++ // The wanted JACK output index for the 'chan' channel value
++ chanArr[chan] = i;
++ jack_info("JACK output port = %d ==> output channel = %d", i, chan);
++ } else {
++ jack_info("Error output channel number is incorrect : %d", chan);
++ goto error;
++ }
++ }
++ } else {
++ for (int i = 0; i < outchannels; i++) {
++ chanArr[i] = i;
++ jack_info("JACK output port = %d ==> output channel = %d", i, chanArr[i]);
++ }
+ }
++
+ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
+ if (err1 != noErr) {
+- jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
++ jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
+ printError(err1);
+ goto error;
+ }
+@@ -1289,8 +1527,8 @@
+ }
+ PrintStreamDesc(&srcFormat);
+
+- jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
+- srcFormat.mSampleRate = samplerate;
++ jack_log("Setup AUHAL input stream converter SR = %ld", sample_rate);
++ srcFormat.mSampleRate = sample_rate;
+ srcFormat.mFormatID = kAudioFormatLinearPCM;
+ srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
+ srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
+@@ -1319,8 +1557,8 @@
+ }
+ PrintStreamDesc(&dstFormat);
+
+- jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
+- dstFormat.mSampleRate = samplerate;
++ jack_log("Setup AUHAL output stream converter SR = %ld", sample_rate);
++ dstFormat.mSampleRate = sample_rate;
+ dstFormat.mFormatID = kAudioFormatLinearPCM;
+ dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
+ dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
+@@ -1464,11 +1702,13 @@
+ }
+
+ int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
+- jack_nframes_t samplerate,
++ jack_nframes_t sample_rate,
+ bool capturing,
+ bool playing,
+ int inchannels,
+ int outchannels,
++ const char* chan_in_list,
++ const char* chan_out_list,
+ bool monitor,
+ const char* capture_driver_uid,
+ const char* playback_driver_uid,
+@@ -1499,6 +1739,21 @@
+ Gestalt(gestaltSystemVersionMajor, &major);
+ Gestalt(gestaltSystemVersionMinor, &minor);
+
++ vector<int> parsed_chan_in_list;
++ vector<int> parsed_chan_out_list;
++
++ ParseChannelList(chan_in_list, parsed_chan_in_list);
++ if (parsed_chan_in_list.size() > 0) {
++ jack_info("Explicit input channel list size = %d", parsed_chan_in_list.size());
++ inchannels = parsed_chan_in_list.size();
++ }
++
++ ParseChannelList(chan_out_list, parsed_chan_out_list);
++ if (parsed_chan_out_list.size() > 0) {
++ jack_info("Explicit output channel list size = %d", parsed_chan_out_list.size());
++ outchannels = parsed_chan_out_list.size();
++ }
++
+ // Starting with 10.6 systems, the HAL notification thread is created internally
+ if (major == 10 && minor >= 6) {
+ CFRunLoopRef theRunLoop = NULL;
+@@ -1510,31 +1765,47 @@
+ }
+ }
+
+- if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, samplerate) < 0)
++ if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0) {
+ goto error;
++ }
+
+ // Generic JackAudioDriver Open
+- if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0)
++ if (JackAudioDriver::Open(buffer_size, sample_rate,
++ capturing, playing,
++ inchannels, outchannels,
++ monitor,
++ capture_driver_name,
++ playback_driver_name,
++ capture_latency,
++ playback_latency) != 0) {
+ goto error;
++ }
+
+- if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0)
++ if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) {
+ goto error;
++ }
+
+- if (SetupBufferSize(buffer_size) < 0)
++ if (SetupBufferSize(buffer_size) < 0) {
+ goto error;
++ }
+
+- if (SetupSampleRate(samplerate) < 0)
++ if (SetupSampleRate(sample_rate) < 0) {
+ goto error;
++ }
+
+- if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0)
++ if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
+ goto error;
++ }
+
+- if (capturing && inchannels > 0)
+- if (SetupBuffers(inchannels) < 0)
++ if (capturing && inchannels > 0) {
++ if (SetupBuffers(inchannels) < 0) {
+ goto error;
++ }
++ }
+
+- if (AddListeners() < 0)
++ if (AddListeners() < 0) {
+ goto error;
++ }
+
+ // Core driver may have changed the in/out values
+ fCaptureChannels = inchannels;
+@@ -1549,7 +1820,6 @@
+ int JackCoreAudioDriver::Close()
+ {
+ jack_log("JackCoreAudioDriver::Close");
+- Stop();
+
+ // Generic audio driver close
+ int res = JackAudioDriver::Close();
+@@ -1561,6 +1831,77 @@
+ return res;
+ }
+
++void JackCoreAudioDriver::UpdateLatencies()
++{
++ UInt32 size;
++ OSStatus err;
++ jack_latency_range_t input_range;
++ jack_latency_range_t output_range;
++ jack_latency_range_t monitor_range;
++
++ // Get Input latency
++ size = sizeof(UInt32);
++ UInt32 value1 = 0;
++ UInt32 value2 = 0;
++ err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
++ if (err != noErr) {
++ jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
++ }
++ err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
++ if (err != noErr) {
++ jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
++ }
++
++ input_range.min = input_range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
++
++ // Get input stream latencies
++ vector<int> input_latencies;
++ err = GetStreamLatencies(fDeviceID, true, input_latencies);
++
++ for (int i = 0; i < fCaptureChannels; i++) {
++ if (err != noErr) {
++ input_range.min += input_latencies[i];
++ input_range.max += input_latencies[i];
++ }
++ fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
++ }
++
++ // Get Output latency
++ size = sizeof(UInt32);
++ value1 = 0;
++ value2 = 0;
++ err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
++ if (err != noErr) {
++ jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
++ }
++ err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
++ if (err != noErr) {
++ jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
++ }
++
++ // Get output stream latencies
++ vector<int> output_latencies;
++ err = GetStreamLatencies(fDeviceID, false, output_latencies);
++
++ // Add more latency if "async" mode is used...
++ output_range.min = output_range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode)
++ ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
++
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ if (err != noErr) {
++ output_range.min += output_latencies[i];
++ output_range.max += output_latencies[i];
++ }
++ fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
++
++ // Monitor port
++ if (fWithMonitorPorts) {
++ monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
++ fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
++ }
++ }
++}
++
+ int JackCoreAudioDriver::Attach()
+ {
+ OSStatus err;
+@@ -1569,104 +1910,81 @@
+ UInt32 size;
+ Boolean isWritable;
+ char channel_name[64];
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- jack_latency_range_t range;
++ char name[REAL_JACK_PORT_NAME_SIZE];
++ char alias[REAL_JACK_PORT_NAME_SIZE];
+
+ jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
+
+ for (int i = 0; i < fCaptureChannels; i++) {
+
+ err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
+- if (err != noErr)
++ if (err != noErr) {
+ jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
++ }
+ if (err == noErr && size > 0) {
+ err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
+- if (err != noErr)
++ if (err != noErr) {
+ jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
++ }
++ snprintf(alias, sizeof(alias), "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
+ } else {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
++ snprintf(alias, sizeof(alias), "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
+ }
+
+- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
++ snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
+
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("Cannot register port for %s", name);
+ return -1;
+ }
+
+- size = sizeof(UInt32);
+- UInt32 value1 = 0;
+- UInt32 value2 = 0;
+- err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
+- if (err != noErr)
+- jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
+- err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
+- if (err != noErr)
+- jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
+-
+ port = fGraphManager->GetPort(port_index);
+ port->SetAlias(alias);
+- range.min = range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
+- port->SetLatencyRange(JackCaptureLatency, &range);
+ fCapturePortList[i] = port_index;
+ }
+
+ for (int i = 0; i < fPlaybackChannels; i++) {
+
+ err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
+- if (err != noErr)
++ if (err != noErr) {
+ jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
++ }
+ if (err == noErr && size > 0) {
+ err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
+- if (err != noErr)
++ if (err != noErr) {
+ jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
++ }
++ snprintf(alias, sizeof(alias), "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
+ } else {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
++ snprintf(alias, sizeof(alias), "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
+ }
+
+- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
++ snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
+
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("Cannot register port for %s", name);
+ return -1;
+ }
+
+- size = sizeof(UInt32);
+- UInt32 value1 = 0;
+- UInt32 value2 = 0;
+- err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
+- if (err != noErr)
+- jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
+- err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
+- if (err != noErr)
+- jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
+-
+ port = fGraphManager->GetPort(port_index);
+ port->SetAlias(alias);
+- // Add more latency if "async" mode is used...
+- range.min = range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
+- port->SetLatencyRange(JackPlaybackLatency, &range);
+ fPlaybackPortList[i] = port_index;
+
+ // Monitor ports
+ if (fWithMonitorPorts) {
+ jack_log("Create monitor port");
+- snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
++ snprintf(name, sizeof(name), "%s:monitor_%u", fClientControl.fName, i + 1);
++ if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
+ jack_error("Cannot register monitor port for %s", name);
+ return -1;
+ } else {
+- port = fGraphManager->GetPort(port_index);
+- range.min = range.max = fEngineControl->fBufferSize;
+- port->SetLatencyRange(JackCaptureLatency, &range);
+ fMonitorPortList[i] = port_index;
+ }
+ }
+ }
+
++ UpdateLatencies();
++
+ // Input buffers do no change : prepare them only once
+ for (int i = 0; i < fCaptureChannels; i++) {
+ fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
+@@ -1678,13 +1996,15 @@
+ int JackCoreAudioDriver::Start()
+ {
+ jack_log("JackCoreAudioDriver::Start");
+- if (JackAudioDriver::Start() >= 0) {
++ if (JackAudioDriver::Start() == 0) {
++
++ // Waiting for Render callback to be called (= driver has started)
++ fState = false;
++ int count = 0;
++
+ OSStatus err = AudioOutputUnitStart(fAUHAL);
+ if (err == noErr) {
+
+- // Waiting for Measure callback to be called (= driver has started)
+- fState = false;
+- int count = 0;
+ while (!fState && count++ < WAIT_COUNTER) {
+ usleep(100000);
+ jack_log("JackCoreAudioDriver::Start wait count = %d", count);
+@@ -1714,17 +2034,14 @@
+
+ int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
+ {
+- OSStatus err;
+- UInt32 outSize = sizeof(UInt32);
+-
+- err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
+- if (err != noErr) {
+- jack_error("Cannot set buffer size %ld", buffer_size);
+- printError(err);
++ if (SetupBufferSize(buffer_size) < 0) {
+ return -1;
+ }
+
+- JackAudioDriver::SetBufferSize(buffer_size); // never fails
++ JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
++
++ // CoreAudio specific
++ UpdateLatencies();
+
+ // Input buffers do no change : prepare them only once
+ for (int i = 0; i < fCaptureChannels; i++) {
+@@ -1806,148 +2123,58 @@
+
+ SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "coreaudio"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Apple CoreAudio API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 17;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "channels");
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = -1;
+- strcpy(desc->params[i].short_desc, "Maximum number of channels");
+- strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used");
+-
+- i++;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = -1;
+- strcpy(desc->params[i].short_desc, "Maximum number of input channels");
+- strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used");
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = -1;
+- strcpy(desc->params[i].short_desc, "Maximum number of output channels");
+- strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used");
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].short_desc, "Input CoreAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].short_desc, "Output CoreAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy (desc->params[i].name, "monitor");
+- desc->params[i].character = 'm';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "duplex");
+- desc->params[i].character = 'D';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = TRUE;
+- strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 44100U;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 128U;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].short_desc, "CoreAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "input-latency");
+- desc->params[i].character = 'I';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra input latency (frames)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "output-latency");
+- desc->params[i].character = 'O';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra output latency (frames)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "list-devices");
+- desc->params[i].character = 'l';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "hog");
+- desc->params[i].character = 'H';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Take exclusive access of the audio device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "async-latency");
+- desc->params[i].character = 'L';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 100;
+- strcpy(desc->params[i].short_desc, "Extra output latency in asynchronous mode (percent)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "grain");
+- desc->params[i].character = 'G';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 100;
+- strcpy(desc->params[i].short_desc, "Computation grain in RT thread (percent)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "clock-drift");
+- desc->params[i].character = 's';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = FALSE;
+- strcpy(desc->params[i].short_desc, "Clock drift compensation");
+- strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device");
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("coreaudio", JackDriverMaster, "Apple CoreAudio API based audio backend", &filler);
++
++ value.i = -1;
++ jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used");
++ jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used");
++ jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used");
++
++ value.str[0] = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-list", 'n', JackDriverParamString, &value, NULL, "Input channel list", "List of input channel number to be opened");
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-list", 'N', JackDriverParamString, &value, NULL, "Output channel list", "List of output channel number to be opened");
++
++ value.str[0] = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output CoreAudio device name", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
++
++ value.i = TRUE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
++
++ value.ui = 44100U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = 256U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.str[0] = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
++
++ value.i = FALSE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
++
++ value.i = FALSE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "hog", 'H', JackDriverParamBool, &value, NULL, "Take exclusive access of the audio device", NULL);
++
++ value.ui = 100;
++ jack_driver_descriptor_add_parameter(desc, &filler, "async-latency", 'L', JackDriverParamUInt, &value, NULL, "Extra output latency in asynchronous mode (percent)", NULL);
++
++ value.ui = 100;
++ jack_driver_descriptor_add_parameter(desc, &filler, "grain", 'G', JackDriverParamUInt, &value, NULL, "Computation grain in RT thread (percent)", NULL);
++
++ value.i = FALSE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "clock-drift", 's', JackDriverParamBool, &value, NULL, "Clock drift compensation", "Whether to compensate clock drift in dynamically created aggregate device");
+
+ return desc;
+ }
+@@ -1955,11 +2182,13 @@
+ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
+ {
+ jack_nframes_t srate = 44100;
+- jack_nframes_t frames_per_interrupt = 128;
++ jack_nframes_t frames_per_interrupt = 256;
+ bool capture = false;
+ bool playback = false;
+ int chan_in = -1; // Default: if not explicitely set, then max possible will be used...
+ int chan_out = -1; // Default: if not explicitely set, then max possible will be used...
++ const char* chan_in_list = "";
++ const char* chan_out_list = "";
+ bool monitor = false;
+ const char* capture_driver_uid = "";
+ const char* playback_driver_uid = "";
+@@ -1988,15 +2217,23 @@
+ break;
+
+ case 'c':
+- chan_in = chan_out = (int)param->value.ui;
++ chan_in = chan_out = param->value.i;
+ break;
+
+ case 'i':
+- chan_in = (int)param->value.ui;
++ chan_in = param->value.i;
+ break;
+
+ case 'o':
+- chan_out = (int)param->value.ui;
++ chan_out = param->value.i;
++ break;
++
++ case 'n':
++ chan_in_list = param->value.str;
++ break;
++
++ case 'N':
++ chan_out_list = param->value.str;
+ break;
+
+ case 'C':
+@@ -2035,7 +2272,7 @@
+
+ case 'l':
+ Jack::DisplayDeviceNames();
+- break;
++ return NULL;
+
+ case 'H':
+ hogged = true;
+@@ -2061,9 +2298,27 @@
+ playback = true;
+ }
+
++ if (strcmp(chan_in_list, "") != 0 && chan_in >= 0) {
++ printf("Input channel list and in channels are both specified, input channel list will take over...\n");
++ }
++
++ if (strcmp(chan_out_list, "") != 0 && chan_out >= 0) {
++ printf("Output channel list and out channels are both specified, output channel list will take over...\n");
++ }
++
+ Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
+- if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid,
+- playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) {
++ if (driver->Open(frames_per_interrupt,
++ srate, capture,
++ playback, chan_in,
++ chan_out, chan_in_list,
++ chan_out_list, monitor,
++ capture_driver_uid,
++ playback_driver_uid,
++ systemic_input_latency,
++ systemic_output_latency,
++ async_output_latency,
++ computation_grain,
++ hogged, clock_drift) == 0) {
+ return driver;
+ } else {
+ delete driver;
+--- a/macosx/coreaudio/JackCoreAudioDriver.h
++++ b/macosx/coreaudio/JackCoreAudioDriver.h
+@@ -40,8 +40,9 @@
+ #define kAudioDeviceSectionOutput ((CAAudioHardwareDeviceSectionID)0x00)
+ #define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00)
+ #define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF)
+-
++
+ #define WAIT_COUNTER 60
++#define WAIT_NOTIFICATION_COUNTER 30
+
+ /*!
+ \brief The CoreAudio driver.
+@@ -63,7 +64,7 @@
+ AudioObjectID fPluginID; // Used for aggregate device
+
+ AudioUnitRenderActionFlags* fActionFags;
+- AudioTimeStamp* fCurrentTime;
++ const AudioTimeStamp* fCurrentTime;
+
+ bool fState;
+ bool fHogged;
+@@ -74,14 +75,8 @@
+ float fIOUsage;
+ float fComputationGrain;
+ bool fClockDriftCompensate;
+-
+- /*
+- #ifdef MAC_OS_X_VERSION_10_5
+- AudioDeviceIOProcID fMesureCallbackID;
+- #endif
+- */
+-
+- static OSStatus Render(void *inRefCon,
++
++ static OSStatus Render(void *inRefCon,
+ AudioUnitRenderActionFlags *ioActionFlags,
+ const AudioTimeStamp *inTimeStamp,
+ UInt32 inBusNumber,
+@@ -89,10 +84,10 @@
+ AudioBufferList *ioData);
+
+ static OSStatus DeviceNotificationCallback(AudioDeviceID inDevice,
+- UInt32 inChannel,
+- Boolean isInput,
+- AudioDevicePropertyID inPropertyID,
+- void* inClientData);
++ UInt32 inChannel,
++ Boolean isInput,
++ AudioDevicePropertyID inPropertyID,
++ void* inClientData);
+
+ static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
+ UInt32 inChannel,
+@@ -100,19 +95,26 @@
+ AudioDevicePropertyID inPropertyID,
+ void* inClientData);
+
++ static OSStatus BSNotificationCallback(AudioDeviceID inDevice,
++ UInt32 inChannel,
++ Boolean isInput,
++ AudioDevicePropertyID inPropertyID,
++ void* inClientData);
++
+ OSStatus GetDeviceIDFromUID(const char* UID, AudioDeviceID* id);
+ OSStatus GetDefaultDevice(AudioDeviceID* id);
+ OSStatus GetDefaultInputDevice(AudioDeviceID* id);
+ OSStatus GetDefaultOutputDevice(AudioDeviceID* id);
+ OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name);
+ OSStatus GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput);
+-
++ OSStatus GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies);
++
+ // Setup
+ OSStatus CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice);
+ OSStatus CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice);
+ OSStatus DestroyAggregateDevice();
+ bool IsAggregateDevice(AudioDeviceID device);
+-
++
+ int SetupDevices(const char* capture_driver_uid,
+ const char* playback_driver_uid,
+ char* capture_driver_name,
+@@ -140,16 +142,20 @@
+ int outchannels,
+ int in_nChannels,
+ int out_nChannels,
++ const vector<int>& chan_in_list,
++ const vector<int>& chan_out_list,
+ jack_nframes_t nframes,
+ jack_nframes_t samplerate);
+ void CloseAUHAL();
+
+ int AddListeners();
+ void RemoveListeners();
+-
++
+ bool TakeHogAux(AudioDeviceID deviceID, bool isInput);
+ bool TakeHog();
+
++ void UpdateLatencies();
++
+ public:
+
+ JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table);
+@@ -159,8 +165,10 @@
+ jack_nframes_t samplerate,
+ bool capturing,
+ bool playing,
+- int chan_in,
+- int chan_out,
++ int inchannels,
++ int outchannels,
++ const char* chan_in_list,
++ const char* chan_out_list,
+ bool monitor,
+ const char* capture_driver_name,
+ const char* playback_driver_name,
+--- /dev/null
++++ b/macosx/coreaudio/TiPhoneCoreAudioRenderer.cpp
+@@ -0,0 +1,409 @@
++/*
++Copyright (C) 2010 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.
++
++*/
++
++#include "TiPhoneCoreAudioRenderer.h"
++
++static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
++{
++ printf("- - - - - - - - - - - - - - - - - - - -\n");
++ printf(" Sample Rate:%f\n", inDesc->mSampleRate);
++ printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
++ printf(" Format Flags:%lX\n", inDesc->mFormatFlags);
++ printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
++ printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
++ printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
++ printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
++ printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
++ printf("- - - - - - - - - - - - - - - - - - - -\n");
++}
++
++static void printError(OSStatus err)
++{
++ switch (err) {
++ case kAudioConverterErr_FormatNotSupported:
++ printf("error code : kAudioConverterErr_FormatNotSupported\n");
++ break;
++ case kAudioConverterErr_OperationNotSupported:
++ printf("error code : kAudioConverterErr_OperationNotSupported\n");
++ break;
++ case kAudioConverterErr_PropertyNotSupported:
++ printf("error code : kAudioConverterErr_PropertyNotSupported\n");
++ break;
++ case kAudioConverterErr_InvalidInputSize:
++ printf("error code : kAudioConverterErr_InvalidInputSize\n");
++ break;
++ case kAudioConverterErr_InvalidOutputSize:
++ printf("error code : kAudioConverterErr_InvalidOutputSize\n");
++ break;
++ case kAudioConverterErr_UnspecifiedError:
++ printf("error code : kAudioConverterErr_UnspecifiedError\n");
++ break;
++ case kAudioConverterErr_BadPropertySizeError:
++ printf("error code : kAudioConverterErr_BadPropertySizeError\n");
++ break;
++ case kAudioConverterErr_RequiresPacketDescriptionsError:
++ printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
++ break;
++ case kAudioConverterErr_InputSampleRateOutOfRange:
++ printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
++ break;
++ case kAudioConverterErr_OutputSampleRateOutOfRange:
++ printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
++ break;
++ default:
++ printf("error code : unknown\n");
++ break;
++ }
++}
++
++OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon,
++ AudioUnitRenderActionFlags *ioActionFlags,
++ const AudioTimeStamp *inTimeStamp,
++ UInt32,
++ UInt32 inNumberFrames,
++ AudioBufferList *ioData)
++{
++ TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon;
++ AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, renderer->fCAInputData);
++
++ float coef = float(LONG_MAX);
++ float inv_coef = 1.f/float(LONG_MAX);
++
++ for (int chan = 0; chan < renderer->fDevNumInChans; chan++) {
++ for (int frame = 0; frame < inNumberFrames; frame++) {
++ renderer->fInChannel[chan][frame] = float(((int*)renderer->fCAInputData->mBuffers[chan].mData)[frame]) * inv_coef;
++ }
++ }
++
++ renderer->PerformAudioCallback((int)inNumberFrames);
++
++ for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) {
++ for (int frame = 0; frame < inNumberFrames; frame++) {
++ ((int*)ioData->mBuffers[chan].mData)[frame] = int(renderer->fOutChannel[chan][frame] * coef);
++ }
++ }
++
++ return 0;
++}
++
++void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption)
++{
++ TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData;
++ printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption");
++
++ if (inInterruption == kAudioSessionEndInterruption) {
++ // make sure we are again the active session
++ AudioSessionSetActive(true);
++ AudioOutputUnitStart(obj->fAUHAL);
++ }
++
++ if (inInterruption == kAudioSessionBeginInterruption) {
++ AudioOutputUnitStop(obj->fAUHAL);
++ }
++}
++
++int TiPhoneCoreAudioRenderer::Open(int bufferSize, int samplerate)
++{
++ OSStatus err1;
++ UInt32 outSize;
++ UInt32 enableIO;
++ AudioStreamBasicDescription srcFormat, dstFormat;
++
++ printf("Open fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate);
++
++ // Initialize and configure the audio session
++ err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this);
++ if (err1 != noErr) {
++ printf("Couldn't initialize audio session\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ err1 = AudioSessionSetActive(true);
++ if (err1 != noErr) {
++ printf("Couldn't set audio session active\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
++ err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
++ if (err1 != noErr) {
++ printf("Couldn't set audio category\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener");
++
++ Float64 hwSampleRate;
++ outSize = sizeof(hwSampleRate);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate);
++ if (err1 != noErr) {
++ printf("Couldn't get hw sample rate\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw sample rate %f\n", hwSampleRate);
++ }
++
++ Float32 hwBufferSize;
++ outSize = sizeof(hwBufferSize);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize);
++ if (err1 != noErr) {
++ printf("Couldn't get hw buffer duration\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw buffer duration %f\n", hwBufferSize);
++ }
++
++ UInt32 hwInput;
++ outSize = sizeof(hwInput);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &hwInput);
++ if (err1 != noErr) {
++ printf("Couldn't get hw input channels\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw input channels %d\n", hwInput);
++ }
++
++ UInt32 hwOutput;
++ outSize = sizeof(hwOutput);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &hwOutput);
++ if (err1 != noErr) {
++ printf("Couldn't get hw output channels\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw output channels %d\n", hwOutput);
++ }
++
++ Float32 preferredBufferSize = float(bufferSize) / float(samplerate);
++ printf("preferredBufferSize %f \n", preferredBufferSize);
++
++ err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
++ if (err1 != noErr) {
++ printf("Couldn't set i/o buffer duration\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ Float64 preferredSamplerate = float(samplerate);
++ err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate);
++ if (err1 != noErr) {
++ printf("Couldn't set i/o sample rate\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ // AUHAL
++ AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0};
++ AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd);
++
++ err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL);
++ if (err1 != noErr) {
++ printf("Error calling OpenAComponent\n");
++ printError(err1);
++ goto error;
++ }
++
++ enableIO = 1;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n");
++ printError(err1);
++ goto error;
++ }
++
++ enableIO = 1;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n");
++ printError(err1);
++ goto error;
++ }
++
++ UInt32 maxFPS;
++ outSize = sizeof(maxFPS);
++ err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize);
++ if (err1 != noErr) {
++ printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n");
++ printError(err1);
++ goto error;
++ } else {
++ printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS);
++ }
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
++ printError(err1);
++ goto error;
++ }
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
++ printError(err1);
++ goto error;
++ }
++
++ err1 = AudioUnitInitialize(fAUHAL);
++ if (err1 != noErr) {
++ printf("Cannot initialize AUHAL unit\n");
++ printError(err1);
++ goto error;
++ }
++
++ // Setting format
++
++ if (fDevNumInChans > 0) {
++ outSize = sizeof(AudioStreamBasicDescription);
++ err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize);
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
++ printError(err1);
++ }
++ PrintStreamDesc(&srcFormat);
++
++ srcFormat.mFormatID = kAudioFormatLinearPCM;
++ srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
++ srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
++ srcFormat.mFramesPerPacket = 1;
++ srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
++ srcFormat.mChannelsPerFrame = fDevNumInChans;
++ srcFormat.mBitsPerChannel = 32;
++
++ PrintStreamDesc(&srcFormat);
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
++ printError(err1);
++ }
++ }
++
++ if (fDevNumOutChans > 0) {
++ outSize = sizeof(AudioStreamBasicDescription);
++ err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize);
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
++ printError(err1);
++ }
++ PrintStreamDesc(&dstFormat);
++
++ dstFormat.mFormatID = kAudioFormatLinearPCM;
++ dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
++ dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
++ dstFormat.mFramesPerPacket = 1;
++ dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
++ dstFormat.mChannelsPerFrame = fDevNumOutChans;
++ dstFormat.mBitsPerChannel = 32;
++
++ PrintStreamDesc(&dstFormat);
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
++ printError(err1);
++ }
++ }
++
++ if (fDevNumInChans > 0 && fDevNumOutChans == 0) {
++ AURenderCallbackStruct output;
++ output.inputProc = Render;
++ output.inputProcRefCon = this;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n");
++ printError(err1);
++ goto error;
++ }
++ } else {
++ AURenderCallbackStruct output;
++ output.inputProc = Render;
++ output.inputProcRefCon = this;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n");
++ printError(err1);
++ goto error;
++ }
++ }
++
++ // Prepare buffers
++ fCAInputData = (AudioBufferList*)malloc(sizeof(UInt32) + fDevNumInChans * sizeof(AudioBuffer));
++ fCAInputData->mNumberBuffers = fDevNumInChans;
++ for (int i = 0; i < fDevNumInChans; i++) {
++ fCAInputData->mBuffers[i].mNumberChannels = 1;
++ fCAInputData->mBuffers[i].mDataByteSize = bufferSize * sizeof(int);
++ fCAInputData->mBuffers[i].mData = malloc(bufferSize * sizeof(int));
++ }
++
++ /*
++ // Add listeners
++ err1 = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
++ if (err != noErr) {
++ jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
++ printError(err);
++ return -1;
++ }
++ */
++
++ return NO_ERR;
++
++error:
++ AudioUnitUninitialize(fAUHAL);
++ AudioComponentInstanceDispose(fAUHAL);
++ return OPEN_ERR;
++}
++
++int TiPhoneCoreAudioRenderer::Close()
++{
++ AudioUnitUninitialize(fAUHAL);
++ AudioComponentInstanceDispose(fAUHAL);
++ return NO_ERR;
++}
++
++int TiPhoneCoreAudioRenderer::Start()
++{
++ AudioSessionSetActive(true);
++ OSStatus err = AudioOutputUnitStart(fAUHAL);
++
++ if (err != noErr) {
++ printf("Error while opening device : device open error \n");
++ return OPEN_ERR;
++ } else {
++ return NO_ERR;
++ }
++}
++
++int TiPhoneCoreAudioRenderer::Stop()
++{
++ OSStatus err = AudioOutputUnitStop(fAUHAL);
++
++ if (err != noErr) {
++ printf("Error while closing device : device close error \n");
++ return OPEN_ERR;
++ } else {
++ return NO_ERR;
++ }
++}
+--- /dev/null
++++ b/macosx/coreaudio/TiPhoneCoreAudioRenderer.h
+@@ -0,0 +1,116 @@
++/*
++Copyright (C) 2010 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 __TiPhoneCoreAudioRenderer__
++#define __TiPhoneCoreAudioRenderer__
++
++#include <AudioToolbox/AudioConverter.h>
++#include <AudioToolbox/AudioServices.h>
++#include <AudioUnit/AudioUnit.h>
++
++#define MAX_CHANNELS 256
++#define OPEN_ERR -1
++#define NO_ERR 0
++
++typedef void (*AudioCallback) (int frames, float** inputs, float** outputs, void* arg);
++
++class TiPhoneCoreAudioRenderer
++{
++
++ private:
++
++ AudioUnit fAUHAL;
++ AudioCallback fAudioCallback;
++ void* fCallbackArg;
++
++ int fDevNumInChans;
++ int fDevNumOutChans;
++
++ AudioBufferList* fCAInputData;
++
++ float* fInChannel[MAX_CHANNELS];
++ float* fOutChannel[MAX_CHANNELS];
++
++ static OSStatus Render(void *inRefCon,
++ AudioUnitRenderActionFlags *ioActionFlags,
++ const AudioTimeStamp *inTimeStamp,
++ UInt32 inBusNumber,
++ UInt32 inNumberFrames,
++ AudioBufferList *ioData);
++
++ static void InterruptionListener(void *inClientData, UInt32 inInterruption);
++
++ public:
++
++ TiPhoneCoreAudioRenderer(int input, int output)
++ :fAudioCallback(NULL), fCallbackArg(NULL), fDevNumInChans(input), fDevNumOutChans(output), fCAInputData(NULL)
++ {
++ memset(fInChannel, 0, sizeof(float*) * MAX_CHANNELS);
++ memset(fOutChannel, 0, sizeof(float*) * MAX_CHANNELS);
++
++ for (int i = 0; i < fDevNumInChans; i++) {
++ fInChannel[i] = new float[8192];
++ }
++
++ for (int i = 0; i < fDevNumOutChans; i++) {
++ fOutChannel[i] = new float[8192];
++ }
++ }
++
++ virtual ~TiPhoneCoreAudioRenderer()
++ {
++ for (int i = 0; i < fDevNumInChans; i++) {
++ delete[] fInChannel[i];
++ }
++
++ for (int i = 0; i < fDevNumOutChans; i++) {
++ delete[] fOutChannel[i];
++ }
++
++ if (fCAInputData) {
++ for (int i = 0; i < fDevNumInChans; i++) {
++ free(fCAInputData->mBuffers[i].mData);
++ }
++ free(fCAInputData);
++ }
++ }
++
++ int Open(int bufferSize, int sampleRate);
++ int Close();
++
++ int Start();
++ int Stop();
++
++ void SetAudioCallback(AudioCallback callback, void* arg)
++ {
++ fAudioCallback = callback;
++ fCallbackArg = arg;
++ }
++
++ void PerformAudioCallback(int frames)
++ {
++ if (fAudioCallback)
++ fAudioCallback(frames, fInChannel, fOutChannel, fCallbackArg);
++ }
++
++};
++
++typedef TiPhoneCoreAudioRenderer * TiPhoneCoreAudioRendererPtr;
++
++#endif
+--- a/macosx/coremidi/JackCoreMidiDriver.cpp
++++ b/macosx/coremidi/JackCoreMidiDriver.cpp
+@@ -1,5 +1,6 @@
+ /*
+ Copyright (C) 2009 Grame
++Copyright (C) 2011 Devin Anderson
+
+ 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
+@@ -17,374 +18,788 @@
+
+ */
+
++#include <stdexcept>
++
++#include <mach/mach_time.h>
++
+ #include "JackCoreMidiDriver.h"
+-#include "JackGraphManager.h"
+-#include "JackServer.h"
++#include "JackCoreMidiUtil.h"
+ #include "JackEngineControl.h"
+-#include "JackDriverLoader.h"
+
+-#include <mach/mach_time.h>
+-#include <assert.h>
+-#include <iostream>
+-#include <sstream>
+-#include <string>
++using Jack::JackCoreMidiDriver;
+
+-namespace Jack
+-{
++static char capture_driver_name[256];
++static char playback_driver_name[256];
++
++static int in_channels, out_channels;
++static bool capturing, playing, monitor;
++
++static jack_nframes_t capture_latency, playback_latency;
++
++///////////////////////////////////////////////////////////////////////////////
++// Static callbacks
++///////////////////////////////////////////////////////////////////////////////
++
++void
++JackCoreMidiDriver::HandleInputEvent(const MIDIPacketList *packet_list,
++ void *driver, void *port)
++{
++ ((JackCoreMidiPhysicalInputPort *) port)->ProcessCoreMidi(packet_list);
++}
++
++void
++JackCoreMidiDriver::HandleNotificationEvent(const MIDINotification *message,
++ void *driver)
++{
++ ((JackCoreMidiDriver *) driver)->HandleNotification(message);
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Class
++///////////////////////////////////////////////////////////////////////////////
++
++JackCoreMidiDriver::JackCoreMidiDriver(const char *name, const char *alias,
++ JackLockedEngine *engine,
++ JackSynchro *table):
++ JackMidiDriver(name, alias, engine, table),fThread(this)
++{
++ mach_timebase_info_data_t info;
++ kern_return_t result = mach_timebase_info(&info);
++ if (result != KERN_SUCCESS) {
++ throw std::runtime_error(mach_error_string(result));
++ }
++ client = 0;
++ fCaptureChannels = 0;
++ fPlaybackChannels = 0;
++ num_physical_inputs = 0;
++ num_physical_outputs = 0;
++ num_virtual_inputs = 0;
++ num_virtual_outputs = 0;
++ physical_input_ports = 0;
++ physical_output_ports = 0;
++ time_ratio = (((double) info.numer) / info.denom) / 1000.0;
++ virtual_input_ports = 0;
++ virtual_output_ports = 0;
++ internal_input = 0;
++ internal_output = 0;
++}
++
++JackCoreMidiDriver::~JackCoreMidiDriver()
++{}
+
+-static MIDITimeStamp MIDIGetCurrentHostTime()
++bool JackCoreMidiDriver::Init()
+ {
+- return mach_absolute_time();
++ return OpenAux();
+ }
+
+-void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuffer_t* ringbuffer)
++bool JackCoreMidiDriver::OpenAux()
+ {
+- // Write the number of packets
+- size_t size = jack_ringbuffer_write_space(ringbuffer);
+- if (size < sizeof(UInt32)) {
+- jack_error("ReadProc : ring buffer is full, skip events...");
+- return;
++ int pi_count = 0;
++ int po_count = 0;
++ int vi_count = 0;
++ int vo_count = 0;
++ ItemCount potential_po_count;
++ ItemCount potential_pi_count;
++
++ CFStringRef name = CFStringCreateWithCString(0, "JackMidi",
++ CFStringGetSystemEncoding());
++ if (! name) {
++ jack_error("JackCoreMidiDriver::Open - failed to allocate memory for "
++ "client name string");
++ return false;
++ }
++
++ OSStatus status = MIDIClientCreate(name, HandleNotificationEvent, this,
++ &client);
++
++ CFRelease(name);
++
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientCreate",
++ status);
++ return false;
++ }
++
++ char *client_name = fClientControl.fName;
++
++ // Allocate and connect physical inputs
++ potential_pi_count = MIDIGetNumberOfSources();
++ if (potential_pi_count) {
++ status = MIDIInputPortCreate(client, CFSTR("Physical Input Port"),
++ HandleInputEvent, this, &internal_input);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Open", "MIDIInputPortCreate",
++ status);
++ goto destroy;
++ }
++
++ try {
++ physical_input_ports =
++ new JackCoreMidiPhysicalInputPort*[potential_pi_count];
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating physical "
++ "input port array: %s", e.what());
++ goto destroy;
++ }
++
++ for (ItemCount i = 0; i < potential_pi_count; i++) {
++ try {
++ physical_input_ports[pi_count] =
++ new JackCoreMidiPhysicalInputPort(fAliasName, client_name,
++ capture_driver_name, i,
++ client, internal_input,
++ time_ratio);
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating "
++ "physical input port: %s", e.what());
++ goto destroy;
++ }
++ pi_count++;
++ }
+ }
+
+- jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32));
++ // Allocate and connect physical outputs
++ potential_po_count = MIDIGetNumberOfDestinations();
++ if (potential_po_count) {
++ status = MIDIOutputPortCreate(client, CFSTR("Physical Output Port"),
++ &internal_output);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Open", "MIDIOutputPortCreate",
++ status);
++ goto destroy;
++ }
++
++ try {
++ physical_output_ports =
++ new JackCoreMidiPhysicalOutputPort*[potential_po_count];
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating physical "
++ "output port array: %s", e.what());
++ goto destroy;
++ }
++
++ for (ItemCount i = 0; i < potential_po_count; i++) {
++ try {
++ physical_output_ports[po_count] =
++ new JackCoreMidiPhysicalOutputPort(fAliasName, client_name,
++ playback_driver_name, i,
++ client, internal_output,
++ time_ratio);
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating "
++ "physical output port: %s", e.what());
++ goto destroy;
++ }
++ po_count++;
++ }
++ }
+
+- for (unsigned int i = 0; i < pktlist->numPackets; ++i) {
++ // Allocate and connect virtual inputs
++ if (in_channels) {
++ try {
++ virtual_input_ports =
++ new JackCoreMidiVirtualInputPort*[in_channels];
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating virtual "
++ "input port array: %s", e.what());
++ goto destroy;
++
++ }
++ for (vi_count = 0; vi_count < in_channels; vi_count++) {
++ try {
++ virtual_input_ports[vi_count] =
++ new JackCoreMidiVirtualInputPort(fAliasName, client_name,
++ capture_driver_name,
++ vi_count + pi_count, client,
++ time_ratio);
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating virtual "
++ "input port: %s", e.what());
++ goto destroy;
++ }
++ }
++ }
+
+- MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
++ // Allocate and connect virtual outputs
++ if (out_channels) {
++ try {
++ virtual_output_ports =
++ new JackCoreMidiVirtualOutputPort*[out_channels];
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating virtual "
++ "output port array: %s", e.what());
++ goto destroy;
++ }
++ for (vo_count = 0; vo_count < out_channels; vo_count++) {
++ try {
++ virtual_output_ports[vo_count] =
++ new JackCoreMidiVirtualOutputPort(fAliasName, client_name,
++ playback_driver_name,
++ vo_count + po_count, client,
++ time_ratio);
++ } catch (std::exception e) {
++ jack_error("JackCoreMidiDriver::Open - while creating virtual "
++ "output port: %s", e.what());
++ goto destroy;
++ }
++ }
++ }
++
++
++ if (! (pi_count || po_count || in_channels || out_channels)) {
++ jack_error("JackCoreMidiDriver::Open - no CoreMIDI inputs or outputs "
++ "found, and no virtual ports allocated.");
++ }
+
+- // TODO : use timestamp
++ if (! JackMidiDriver::Open(capturing, playing,
++ in_channels + pi_count,
++ out_channels + po_count, monitor,
++ capture_driver_name,
++ playback_driver_name, capture_latency,
++ playback_latency)) {
++ num_physical_inputs = pi_count;
++ num_physical_outputs = po_count;
++ num_virtual_inputs = in_channels;
++ num_virtual_outputs = out_channels;
++ return true;
++ }
++
++ destroy:
+
+- // Check available size first..
+- size = jack_ringbuffer_write_space(ringbuffer);
+- if (size < (sizeof(UInt16) + packet->length)) {
+- jack_error("ReadProc : ring buffer is full, skip events...");
+- return;
++ if (physical_input_ports) {
++ for (int i = 0; i < pi_count; i++) {
++ delete physical_input_ports[i];
+ }
+- // Write length of each packet first
+- jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16));
+- // Write event actual data
+- jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length);
++ delete[] physical_input_ports;
++ physical_input_ports = 0;
++ }
+
+- packet = MIDIPacketNext(packet);
++ if (physical_output_ports) {
++ for (int i = 0; i < po_count; i++) {
++ delete physical_output_ports[i];
++ }
++ delete[] physical_output_ports;
++ physical_output_ports = 0;
+ }
+-}
+
+-void JackCoreMidiDriver::ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
+-{
+- jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)connRefCon;
+- ReadProcAux(pktlist, ringbuffer);
+-}
++ if (virtual_input_ports) {
++ for (int i = 0; i < vi_count; i++) {
++ delete virtual_input_ports[i];
++ }
++ delete[] virtual_input_ports;
++ virtual_input_ports = 0;
++ }
+
+-void JackCoreMidiDriver::ReadVirtualProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
+-{
+- jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)refCon;
+- ReadProcAux(pktlist, ringbuffer);
++ if (virtual_output_ports) {
++ for (int i = 0; i < vo_count; i++) {
++ delete virtual_output_ports[i];
++ }
++ delete[] virtual_output_ports;
++ virtual_output_ports = 0;
++ }
++
++ if (internal_output) {
++ status = MIDIPortDispose(internal_output);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
++ }
++ }
++
++ if (internal_input) {
++ status = MIDIPortDispose(internal_input);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Open", "MIDIPortDispose", status);
++ }
++ }
++
++ if (client) {
++ status = MIDIClientDispose(client);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Open", "MIDIClientDispose",
++ status);
++ }
++ }
++
++ // Default open
++ if (! JackMidiDriver::Open(capturing, playing,
++ in_channels + pi_count,
++ out_channels + po_count, monitor,
++ capture_driver_name,
++ playback_driver_name, capture_latency,
++ playback_latency)) {
++ client = 0;
++ num_physical_inputs = 0;
++ num_physical_outputs = 0;
++ num_virtual_inputs = 0;
++ num_virtual_outputs = 0;
++ return true;
++ } else {
++ return false;
++ }
+ }
+
+-void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon)
++bool JackCoreMidiDriver::Execute()
+ {
+- jack_log("NotifyProc %d", message->messageID);
++ CFRunLoopRun();
++ return false;
+ }
+
+-JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+- : JackMidiDriver(name, alias, engine, table), fMidiClient(NULL), fInputPort(NULL), fOutputPort(NULL), fRealCaptureChannels(0), fRealPlaybackChannels(0)
+-{}
++int
++JackCoreMidiDriver::Attach()
++{
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ jack_port_id_t index;
++ jack_nframes_t latency = buffer_size;
++ jack_latency_range_t latency_range;
++ const char *name;
++ JackPort *port;
++ JackCoreMidiPort *port_obj;
++ latency_range.max = latency;
++ latency_range.min = latency;
+
+-JackCoreMidiDriver::~JackCoreMidiDriver()
+-{}
++ // Physical inputs
++ for (int i = 0; i < num_physical_inputs; i++) {
++ port_obj = physical_input_ports[i];
++ name = port_obj->GetName();
++ if (fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ CaptureDriverFlags, buffer_size, &index) < 0) {
++ jack_error("JackCoreMidiDriver::Attach - cannot register physical "
++ "input port with name '%s'.", name);
++ // X: Do we need to deallocate ports?
++ return -1;
++ }
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(port_obj->GetAlias());
++ port->SetLatencyRange(JackCaptureLatency, &latency_range);
++ fCapturePortList[i] = index;
++ }
++
++ // Virtual inputs
++ for (int i = 0; i < num_virtual_inputs; i++) {
++ port_obj = virtual_input_ports[i];
++ name = port_obj->GetName();
++ if (fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ CaptureDriverFlags, buffer_size, &index) < 0) {
++ jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
++ "input port with name '%s'.", name);
++ // X: Do we need to deallocate ports?
++ return -1;
++ }
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(port_obj->GetAlias());
++ port->SetLatencyRange(JackCaptureLatency, &latency_range);
++ fCapturePortList[num_physical_inputs + i] = index;
++ }
++
++ if (! fEngineControl->fSyncMode) {
++ latency += buffer_size;
++ latency_range.max = latency;
++ latency_range.min = latency;
++ }
++
++ // Physical outputs
++ for (int i = 0; i < num_physical_outputs; i++) {
++ port_obj = physical_output_ports[i];
++ name = port_obj->GetName();
++ fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ PlaybackDriverFlags, buffer_size, &index);
++ if (index == NO_PORT) {
++ jack_error("JackCoreMidiDriver::Attach - cannot register physical "
++ "output port with name '%s'.", name);
++ // X: Do we need to deallocate ports?
++ return -1;
++ }
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(port_obj->GetAlias());
++ port->SetLatencyRange(JackPlaybackLatency, &latency_range);
++ fPlaybackPortList[i] = index;
++ }
++
++ // Virtual outputs
++ for (int i = 0; i < num_virtual_outputs; i++) {
++ port_obj = virtual_output_ports[i];
++ name = port_obj->GetName();
++ fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ PlaybackDriverFlags, buffer_size, &index);
++ if (index == NO_PORT) {
++ jack_error("JackCoreMidiDriver::Attach - cannot register virtual "
++ "output port with name '%s'.", name);
++ // X: Do we need to deallocate ports?
++ return -1;
++ }
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(port_obj->GetAlias());
++ port->SetLatencyRange(JackPlaybackLatency, &latency_range);
++ fPlaybackPortList[num_physical_outputs + i] = index;
++ }
+
+-int JackCoreMidiDriver::Open(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)
+- {
+- OSStatus err;
+- CFStringRef coutputStr;
+- std::string str;
+-
+- // Get real input/output number
+- fRealCaptureChannels = MIDIGetNumberOfSources();
+- fRealPlaybackChannels = MIDIGetNumberOfDestinations();
++ return 0;
++}
+
+- // Generic JackMidiDriver Open
+- if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0)
+- return -1;
++int
++JackCoreMidiDriver::Close()
++{
++ fThread.Kill();
++ return CloseAux();
++}
+
+- coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding());
+- err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient);
+- CFRelease(coutputStr);
+- if (!fMidiClient) {
+- jack_error("Cannot create CoreMidi client");
+- goto error;
+- }
+-
+- err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort);
+- if (!fInputPort) {
+- jack_error("Cannot open CoreMidi in port\n");
+- goto error;
+- }
+-
+- err = MIDIOutputPortCreate(fMidiClient, CFSTR("Output port"), &fOutputPort);
+- if (!fOutputPort) {
+- jack_error("Cannot open CoreMidi out port\n");
+- goto error;
+- }
+-
+- fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels];
+- assert(fMidiDestination);
+-
+- // Virtual input
+- for (int i = 0; i < inchannels; i++) {
+- std::stringstream num;
+- num << i;
+- str = "JackMidi" + num.str();
+- coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
+- err = MIDIDestinationCreate(fMidiClient, coutputStr, ReadVirtualProc, fRingBuffer[i], &fMidiDestination[i]);
+- CFRelease(coutputStr);
+- if (!fMidiDestination[i]) {
+- jack_error("Cannot create CoreMidi destination");
+- goto error;
++int
++JackCoreMidiDriver::CloseAux()
++{
++ // Generic MIDI driver close
++ int result = JackMidiDriver::Close();
++
++ OSStatus status;
++ if (physical_input_ports) {
++ for (int i = 0; i < num_physical_inputs; i++) {
++ delete physical_input_ports[i];
++ }
++ delete[] physical_input_ports;
++ num_physical_inputs = 0;
++ physical_input_ports = 0;
++ if (internal_input) {
++ status = MIDIPortDispose(internal_input);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
++ status);
++ result = -1;
++ }
++ internal_input = 0;
+ }
+ }
+-
+- // Real input
+- for (int i = 0; i < fRealCaptureChannels; i++) {
+- fMidiDestination[i + inchannels] = MIDIGetSource(i);
+- MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]);
+- }
+-
+- fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels];
+- assert(fMidiSource);
+-
+- // Virtual output
+- for (int i = 0; i < outchannels; i++) {
+- std::stringstream num;
+- num << i;
+- str = "JackMidi" + num.str();
+- coutputStr = CFStringCreateWithCString(0, str.c_str(), CFStringGetSystemEncoding());
+- err = MIDISourceCreate(fMidiClient, coutputStr, &fMidiSource[i]);
+- CFRelease(coutputStr);
+- if (!fMidiSource[i]) {
+- jack_error("Cannot create CoreMidi source");
+- goto error;
++ if (physical_output_ports) {
++ for (int i = 0; i < num_physical_outputs; i++) {
++ delete physical_output_ports[i];
++ }
++ delete[] physical_output_ports;
++ num_physical_outputs = 0;
++ physical_output_ports = 0;
++ if (internal_output) {
++ status = MIDIPortDispose(internal_output);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Close", "MIDIPortDispose",
++ status);
++ result = -1;
++ }
++ internal_output = 0;
++ }
++ }
++ if (virtual_input_ports) {
++ for (int i = 0; i < num_virtual_inputs; i++) {
++ delete virtual_input_ports[i];
++ }
++ delete[] virtual_input_ports;
++ num_virtual_inputs = 0;
++ virtual_input_ports = 0;
++ }
++ if (virtual_output_ports) {
++ for (int i = 0; i < num_virtual_outputs; i++) {
++ delete virtual_output_ports[i];
+ }
++ delete[] virtual_output_ports;
++ num_virtual_outputs = 0;
++ virtual_output_ports = 0;
+ }
+
+- // Real output
+- for (int i = 0; i < fRealPlaybackChannels; i++) {
+- fMidiSource[i + outchannels] = MIDIGetDestination(i);
++ if (client) {
++ status = MIDIClientDispose(client);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiDriver::Close", "MIDIClientDispose",
++ status);
++ result = -1;
++ }
++ client = 0;
+ }
++ return result;
++}
+
+- return 0;
++void
++JackCoreMidiDriver::Restart()
++{
++ JackLock lock(this);
+
+-error:
+- Close();
+- return -1;
++ SaveConnections();
++ Stop();
++ Detach();
++ CloseAux();
++ OpenAux();
++ Attach();
++ Start();
++ RestoreConnections();
+ }
+
+-int JackCoreMidiDriver::Close()
++void
++JackCoreMidiDriver::HandleNotification(const MIDINotification *message)
+ {
+- // Generic midi driver close
+- int res = JackMidiDriver::Close();
++ switch (message->messageID) {
+
+- if (fInputPort)
+- MIDIPortDispose(fInputPort);
++ case kMIDIMsgSetupChanged:
++ Restart();
++ break;
+
+- if (fOutputPort)
+- MIDIPortDispose(fOutputPort);
++ case kMIDIMsgObjectAdded:
++ break;
+
+- // Only dispose "virtual" endpoints
+- for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) {
+- if (fMidiDestination)
+- MIDIEndpointDispose(fMidiDestination[i]);
+- }
+- delete[] fMidiDestination;
++ case kMIDIMsgObjectRemoved:
++ break;
+
+- // Only dispose "virtual" endpoints
+- for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) {
+- if (fMidiSource[i])
+- MIDIEndpointDispose(fMidiSource[i]);
+ }
+- delete[] fMidiSource;
++}
+
+- if (fMidiClient)
+- MIDIClientDispose(fMidiClient);
++int
++JackCoreMidiDriver::Open(bool capturing_aux, bool playing_aux, int in_channels_aux,
++ int out_channels_aux, bool monitor_aux,
++ const char* capture_driver_name_aux,
++ const char* playback_driver_name_aux,
++ jack_nframes_t capture_latency_aux,
++ jack_nframes_t playback_latency_aux)
++{
+
+- return res;
++ strcpy(capture_driver_name, capture_driver_name_aux);
++ strcpy(playback_driver_name, playback_driver_name_aux);
++
++ capturing = capturing_aux;
++ playing = playing_aux;
++ in_channels = in_channels_aux;
++ out_channels = out_channels_aux;
++ monitor = monitor_aux;
++ capture_latency = capture_latency_aux;
++ playback_latency = playback_latency_aux;
++
++ fThread.StartSync();
++
++ int count = 0;
++ while (fThread.GetStatus() != JackThread::kRunning && ++count < WAIT_COUNTER) {
++ JackSleep(100000);
++ jack_log("JackCoreMidiDriver::Open wait count = %d", count);
++
++ }
++ if (count == WAIT_COUNTER) {
++ jack_info("Cannot open CoreMIDI driver");
++ fThread.Kill();
++ return -1;
++ } else {
++ JackSleep(10000);
++ jack_info("CoreMIDI driver is running...");
++ }
++
++ return 0;
+ }
+
+-int JackCoreMidiDriver::Attach()
++int
++JackCoreMidiDriver::Start()
+ {
+- OSStatus err;
+- JackPort* port;
+- CFStringRef pname;
+- jack_port_id_t port_index;
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char endpoint_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- int i;
+-
+- jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
+-
+- for (i = 0; i < fCaptureChannels; i++) {
+-
+- err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname);
+- if (err == noErr) {
+- CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0);
+- CFRelease(pname);
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, endpoint_name, i + 1);
+- } else {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
++ jack_info("JackCoreMidiDriver::Start - Starting driver.");
++
++ JackMidiDriver::Start();
++
++ int pi_count = 0;
++ int po_count = 0;
++ int vi_count = 0;
++ int vo_count = 0;
++
++ jack_info("JackCoreMidiDriver::Start - Enabling physical input ports.");
++
++ for (; pi_count < num_physical_inputs; pi_count++) {
++ if (physical_input_ports[pi_count]->Start() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
++ "input port.");
++ goto stop_physical_input_ports;
+ }
++ }
+
+- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
+- jack_error("driver: cannot register port for %s", name);
+- return -1;
++ jack_info("JackCoreMidiDriver::Start - Enabling physical output ports.");
++
++ for (; po_count < num_physical_outputs; po_count++) {
++ if (physical_output_ports[po_count]->Start() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to enable physical "
++ "output port.");
++ goto stop_physical_output_ports;
+ }
+- port = fGraphManager->GetPort(port_index);
+- port->SetAlias(alias);
+- fCapturePortList[i] = port_index;
+- jack_log("JackCoreMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index);
+ }
+
+- for (i = 0; i < fPlaybackChannels; i++) {
+-
+- err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname);
+- if (err == noErr) {
+- CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0);
+- CFRelease(pname);
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, endpoint_name, i + 1);
+- } else {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1);
++ jack_info("JackCoreMidiDriver::Start - Enabling virtual input ports.");
++
++ for (; vi_count < num_virtual_inputs; vi_count++) {
++ if (virtual_input_ports[vi_count]->Start() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
++ "input port.");
++ goto stop_virtual_input_ports;
+ }
++ }
+
+- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
+- jack_error("driver: cannot register port for %s", name);
+- return -1;
++ jack_info("JackCoreMidiDriver::Start - Enabling virtual output ports.");
++
++ for (; vo_count < num_virtual_outputs; vo_count++) {
++ if (virtual_output_ports[vo_count]->Start() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to enable virtual "
++ "output port.");
++ goto stop_virtual_output_ports;
+ }
+- port = fGraphManager->GetPort(port_index);
+- port->SetAlias(alias);
+- fPlaybackPortList[i] = port_index;
+- jack_log("JackCoreMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index);
+ }
+
++ jack_info("JackCoreMidiDriver::Start - Driver started.");
++
+ return 0;
++
++ stop_virtual_output_ports:
++ for (int i = 0; i < vo_count; i++) {
++ if (virtual_output_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
++ "output port.");
++ }
++ }
++ stop_virtual_input_ports:
++ for (int i = 0; i < vi_count; i++) {
++ if (virtual_input_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to disable virtual "
++ "input port.");
++ }
++ }
++ stop_physical_output_ports:
++ for (int i = 0; i < po_count; i++) {
++ if (physical_output_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to disable "
++ "physical output port.");
++ }
++ }
++ stop_physical_input_ports:
++ for (int i = 0; i < pi_count; i++) {
++ if (physical_input_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Start - Failed to disable "
++ "physical input port.");
++ }
++ }
++
++ return -1;
+ }
+-int JackCoreMidiDriver::Read()
+-{
+- for (int chan = 0; chan < fCaptureChannels; chan++) {
+
+- if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) {
++int
++JackCoreMidiDriver::Stop()
++{
++ int result = 0;
+
+- // Get JACK port
+- JackMidiBuffer* midi_buffer = GetInputBuffer(chan);
++ JackMidiDriver::Stop();
+
+- if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) {
+- // Reset buffer
+- midi_buffer->Reset(midi_buffer->nframes);
+- } else {
++ jack_info("JackCoreMidiDriver::Stop - disabling physical input ports.");
+
+- while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) {
++ for (int i = 0; i < num_physical_inputs; i++) {
++ if (physical_input_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
++ "input port.");
++ result = -1;
++ }
++ }
+
+- // Read event number
+- int ev_count = 0;
+- jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int));
+-
+- for (int j = 0; j < ev_count; j++) {
+- // Read event length
+- UInt16 event_len;
+- jack_ringbuffer_read(fRingBuffer[chan], (char*)&event_len, sizeof(UInt16));
+- // Read event actual data
+- jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len);
+- jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len);
+- }
+- }
+- }
++ jack_info("JackCoreMidiDriver::Stop - disabling physical output ports.");
+
+- } else {
+- // Consume ring buffer
+- jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan]));
++ for (int i = 0; i < num_physical_outputs; i++) {
++ if (physical_output_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Stop - Failed to disable physical "
++ "output port.");
++ result = -1;
+ }
+ }
+- return 0;
+-}
+
+-int JackCoreMidiDriver::Write()
+-{
+- MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer;
++ jack_info("JackCoreMidiDriver::Stop - disabling virtual input ports.");
+
+- for (int chan = 0; chan < fPlaybackChannels; chan++) {
++ for (int i = 0; i < num_virtual_inputs; i++) {
++ if (virtual_input_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
++ "input port.");
++ result = -1;
++ }
++ }
+
+- if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) {
++ jack_info("JackCoreMidiDriver::Stop - disabling virtual output ports.");
+
+- MIDIPacket* packet = MIDIPacketListInit(pktlist);
+- JackMidiBuffer* midi_buffer = GetOutputBuffer(chan);
++ for (int i = 0; i < num_virtual_outputs; i++) {
++ if (virtual_output_ports[i]->Stop() < 0) {
++ jack_error("JackCoreMidiDriver::Stop - Failed to disable virtual "
++ "output port.");
++ result = -1;
++ }
++ }
+
+- // TODO : use timestamp
++ return result;
++}
+
+- for (unsigned int j = 0; j < midi_buffer->event_count; j++) {
+- JackMidiEvent* ev = &midi_buffer->events[j];
+- packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer));
+- }
++int
++JackCoreMidiDriver::ProcessRead()
++{
++ int res;
++ if (Trylock()) {
++ res = (fEngineControl->fSyncMode) ? ProcessReadSync() : ProcessReadAsync();
++ Unlock();
++ } else {
++ res = -1;
++ }
++ return res;
++}
+
+- if (packet) {
+- if (chan < fPlaybackChannels - fRealPlaybackChannels) {
+- OSStatus err = MIDIReceived(fMidiSource[chan], pktlist);
+- if (err != noErr)
+- jack_error("MIDIReceived error");
+- } else {
+- OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist);
+- if (err != noErr)
+- jack_error("MIDISend error");
+- }
+- }
+- }
++int
++JackCoreMidiDriver::ProcessWrite()
++{
++ int res;
++ if (Trylock()) {
++ res = (fEngineControl->fSyncMode) ? ProcessWriteSync() : ProcessWriteAsync();
++ Unlock();
++ } else {
++ res = -1;
+ }
++ return res;
++}
+
++int
++JackCoreMidiDriver::Read()
++{
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ for (int i = 0; i < num_physical_inputs; i++) {
++ physical_input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
++ }
++ for (int i = 0; i < num_virtual_inputs; i++) {
++ virtual_input_ports[i]->
++ ProcessJack(GetInputBuffer(num_physical_inputs + i), buffer_size);
++ }
+ return 0;
+ }
+
+-} // end of namespace
++int
++JackCoreMidiDriver::Write()
++{
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ for (int i = 0; i < num_physical_outputs; i++) {
++ physical_output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
++ }
++ for (int i = 0; i < num_virtual_outputs; i++) {
++ virtual_output_ports[i]->
++ ProcessJack(GetOutputBuffer(num_physical_outputs + i), buffer_size);
++ }
++ return 0;
++}
+
+ #ifdef __cplusplus
+-extern "C"
+-{
++extern "C" {
+ #endif
+
++ // singleton kind of driver
++ static Jack::JackDriverClientInterface* driver = NULL;
++
+ SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
+ {
+ jack_driver_desc_t * desc;
+- unsigned int i;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
+
+- desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
+- strcpy(desc->name, "coremidi"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Apple CoreMIDI API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 2;
+- desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "CoreMIDI virtual bus");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "CoreMIDI virtual bus");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ desc = jack_driver_descriptor_construct("coremidi", JackDriverSlave, "Apple CoreMIDI API based MIDI backend", &filler);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "CoreMIDI virtual bus", NULL);
+
+ return desc;
+ }
+@@ -411,11 +826,17 @@
+ }
+ }
+
+- Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table);
+- if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) {
+- return driver;
++ // singleton kind of driver
++ if (!driver) {
++ driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table);
++ if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) {
++ return driver;
++ } else {
++ delete driver;
++ return NULL;
++ }
+ } else {
+- delete driver;
++ jack_info("JackCoreMidiDriver already allocated, cannot be loaded twice");
+ return NULL;
+ }
+ }
+@@ -423,4 +844,3 @@
+ #ifdef __cplusplus
+ }
+ #endif
+-
+--- a/macosx/coremidi/JackCoreMidiDriver.h
++++ b/macosx/coremidi/JackCoreMidiDriver.h
+@@ -1,5 +1,6 @@
+ /*
+ Copyright (C) 2009 Grame
++Copyright (C) 2011 Devin Anderson
+
+ 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
+@@ -20,61 +21,91 @@
+ #ifndef __JackCoreMidiDriver__
+ #define __JackCoreMidiDriver__
+
+-#include <CoreMIDI/CoreMIDI.h>
++#include "JackCoreMidiPhysicalInputPort.h"
++#include "JackCoreMidiPhysicalOutputPort.h"
++#include "JackCoreMidiVirtualInputPort.h"
++#include "JackCoreMidiVirtualOutputPort.h"
+ #include "JackMidiDriver.h"
+-#include "JackTime.h"
++#include "JackThread.h"
+
+-namespace Jack
+-{
++namespace Jack {
+
+-/*!
+-\brief The CoreMidi driver.
+-*/
+-
+-class JackCoreMidiDriver : public JackMidiDriver
+-{
++ class JackCoreMidiDriver: public JackMidiDriver, public JackRunnableInterface, public JackLockAble {
+
+ private:
+
+- MIDIClientRef fMidiClient;
+- MIDIPortRef fInputPort;
+- MIDIPortRef fOutputPort;
+- MIDIEndpointRef* fMidiDestination;
+- MIDIEndpointRef* fMidiSource;
+-
+- char fMIDIBuffer[BUFFER_SIZE_MAX * sizeof(jack_default_audio_sample_t)];
+-
+- int fRealCaptureChannels;
+- int fRealPlaybackChannels;
+-
+- static void ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuffer_t* ringbuffer);
+- static void ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon);
+- static void ReadVirtualProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon);
+- static void NotifyProc(const MIDINotification *message, void *refCon);
++ static void
++ HandleInputEvent(const MIDIPacketList *packet_list, void *driver,
++ void *port);
++
++ static void
++ HandleNotificationEvent(const MIDINotification *message, void *driver);
++
++ void
++ HandleNotification(const MIDINotification *message);
++
++ MIDIClientRef client;
++ MIDIPortRef internal_input;
++ MIDIPortRef internal_output;
++ int num_physical_inputs;
++ int num_physical_outputs;
++ int num_virtual_inputs;
++ int num_virtual_outputs;
++ JackCoreMidiPhysicalInputPort **physical_input_ports;
++ JackCoreMidiPhysicalOutputPort **physical_output_ports;
++ double time_ratio;
++ JackCoreMidiVirtualInputPort **virtual_input_ports;
++ JackCoreMidiVirtualOutputPort **virtual_output_ports;
++
++ bool OpenAux();
++ int CloseAux();
++
++ void Restart();
++
++ JackThread fThread; /*! Thread to execute the Process function */
+
+ public:
+
+- JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table);
+- virtual ~JackCoreMidiDriver();
++ JackCoreMidiDriver(const char* name, const char* alias,
++ JackLockedEngine* engine, JackSynchro* table);
++
++ ~JackCoreMidiDriver();
++
++ int
++ Attach();
++
++ int
++ Close();
++
++ int
++ Open(bool capturing, bool playing, int num_inputs, int num_outputs,
++ bool monitor, const char* capture_driver_name,
++ const char* playback_driver_name, jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency);
++
++ int
++ Read();
++
++ int
++ Start();
++
++ int
++ Stop();
++
++ int
++ Write();
+
+- int Open( bool capturing,
+- bool playing,
+- int chan_in,
+- int chan_out,
+- 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 ProcessRead();
++ int ProcessWrite();
+
+- int Attach();
++ // JackRunnableInterface interface
++ bool Init();
++ bool Execute();
+
+- int Read();
+- int Write();
++ };
+
+-};
++}
+
+-} // end of namespace
++#define WAIT_COUNTER 100
+
+ #endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiInputPort.cpp
+@@ -0,0 +1,183 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++#include <memory>
++
++#include "JackCoreMidiInputPort.h"
++#include "JackMidiUtil.h"
++
++using Jack::JackCoreMidiInputPort;
++
++JackCoreMidiInputPort::JackCoreMidiInputPort(double time_ratio,
++ size_t max_bytes,
++ size_t max_messages):
++ JackCoreMidiPort(time_ratio)
++{
++ thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
++ std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
++ write_queue = new JackMidiBufferWriteQueue();
++ std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
++ sysex_buffer = new jack_midi_data_t[max_bytes];
++ write_queue_ptr.release();
++ thread_queue_ptr.release();
++ jack_event = 0;
++}
++
++JackCoreMidiInputPort::~JackCoreMidiInputPort()
++{
++ delete thread_queue;
++ delete write_queue;
++ delete[] sysex_buffer;
++}
++
++jack_nframes_t
++JackCoreMidiInputPort::GetFramesFromTimeStamp(MIDITimeStamp timestamp)
++{
++ return GetFramesFromTime((jack_time_t) (timestamp * time_ratio));
++}
++
++void
++JackCoreMidiInputPort::Initialize(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, int index,
++ MIDIEndpointRef endpoint)
++{
++ JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index, endpoint, false);
++}
++
++void
++JackCoreMidiInputPort::ProcessCoreMidi(const MIDIPacketList *packet_list)
++{
++ set_threaded_log_function();
++
++ unsigned int packet_count = packet_list->numPackets;
++ assert(packet_count);
++ MIDIPacket *packet = (MIDIPacket *) packet_list->packet;
++ for (unsigned int i = 0; i < packet_count; i++) {
++ jack_midi_data_t *data = packet->data;
++ size_t size = packet->length;
++ assert(size);
++ jack_midi_event_t event;
++
++ // XX: There might be dragons in my spaghetti. This code is begging
++ // for a rewrite.
++
++ if (sysex_bytes_sent) {
++ if (data[0] & 0x80) {
++ jack_error("JackCoreMidiInputPort::ProcessCoreMidi - System "
++ "exclusive message aborted.");
++ sysex_bytes_sent = 0;
++ goto parse_event;
++ }
++ buffer_sysex_bytes:
++ if ((sysex_bytes_sent + size) <= sizeof(sysex_buffer)) {
++ memcpy(sysex_buffer + sysex_bytes_sent, packet,
++ size * sizeof(jack_midi_data_t));
++ }
++ sysex_bytes_sent += size;
++ if (data[size - 1] == 0xf7) {
++ if (sysex_bytes_sent > sizeof(sysex_buffer)) {
++ jack_error("JackCoreMidiInputPort::ProcessCoreMidi - "
++ "Could not buffer a %d-byte system exclusive "
++ "message. Discarding message.",
++ sysex_bytes_sent);
++ sysex_bytes_sent = 0;
++ goto get_next_packet;
++ }
++ event.buffer = sysex_buffer;
++ event.size = sysex_bytes_sent;
++ sysex_bytes_sent = 0;
++ goto send_event;
++ }
++ goto get_next_packet;
++ }
++
++ parse_event:
++ if (data[0] == 0xf0) {
++ if (data[size - 1] != 0xf7) {
++ goto buffer_sysex_bytes;
++ }
++ }
++ event.buffer = data;
++ event.size = size;
++
++ send_event:
++ event.time = GetFramesFromTimeStamp(packet->timeStamp);
++ switch (thread_queue->EnqueueEvent(&event)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++ jack_error("JackCoreMidiInputPort::ProcessCoreMidi - The thread "
++ "queue buffer is full. Dropping event.");
++ break;
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackCoreMidiInputPort::ProcessCoreMidi - The thread "
++ "queue couldn't enqueue a %d-byte packet. Dropping "
++ "event.", event.size);
++ break;
++ default:
++ ;
++ }
++
++ get_next_packet:
++ packet = MIDIPacketNext(packet);
++ assert(packet);
++ }
++}
++
++void
++JackCoreMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
++ jack_nframes_t frames)
++{
++ write_queue->ResetMidiBuffer(port_buffer, frames);
++ if (! jack_event) {
++ jack_event = thread_queue->DequeueEvent();
++ }
++
++ for (; jack_event; jack_event = thread_queue->DequeueEvent()) {
++ // Add 'frames' to MIDI events to align with audio.
++ switch (write_queue->EnqueueEvent(jack_event, frames)) {
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackCoreMidiInputPort::ProcessJack - The write queue "
++ "couldn't enqueue a %d-byte event. Dropping event.",
++ jack_event->size);
++ // Fallthrough on purpose
++ case JackMidiWriteQueue::OK:
++ continue;
++ default:
++ ;
++ }
++ break;
++ }
++}
++
++bool
++JackCoreMidiInputPort::Start()
++{
++ // Hack: Get rid of any messages that might have come in before starting
++ // the engine.
++ while (thread_queue->DequeueEvent());
++ sysex_bytes_sent = 0;
++ return true;
++}
++
++bool
++JackCoreMidiInputPort::Stop()
++{
++ return true;
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiInputPort.h
+@@ -0,0 +1,73 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiInputPort__
++#define __JackCoreMidiInputPort__
++
++#include "JackCoreMidiPort.h"
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiBufferWriteQueue.h"
++
++namespace Jack {
++
++ class JackCoreMidiInputPort: public JackCoreMidiPort {
++
++ private:
++
++ jack_nframes_t
++ GetFramesFromTimeStamp(MIDITimeStamp timestamp);
++
++ jack_midi_event_t *jack_event;
++ jack_midi_data_t *sysex_buffer;
++ size_t sysex_bytes_sent;
++ JackMidiAsyncQueue *thread_queue;
++ JackMidiBufferWriteQueue *write_queue;
++
++ protected:
++
++ void
++ Initialize(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIEndpointRef endpoint);
++
++ public:
++
++ JackCoreMidiInputPort(double time_ratio, size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ virtual
++ ~JackCoreMidiInputPort();
++
++ void
++ ProcessCoreMidi(const MIDIPacketList *packet_list);
++
++ void
++ ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames);
++
++ bool
++ Start();
++
++ bool
++ Stop();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiOutputPort.cpp
+@@ -0,0 +1,249 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++#include <cerrno>
++#include <cstring>
++#include <new>
++#include <stdexcept>
++
++#include "JackCoreMidiOutputPort.h"
++#include "JackMidiUtil.h"
++#include "JackTime.h"
++
++using Jack::JackCoreMidiOutputPort;
++
++JackCoreMidiOutputPort::JackCoreMidiOutputPort(double time_ratio,
++ size_t max_bytes,
++ size_t max_messages):
++ JackCoreMidiPort(time_ratio)
++{
++ read_queue = new JackMidiBufferReadQueue();
++ std::auto_ptr<JackMidiBufferReadQueue> read_queue_ptr(read_queue);
++ thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
++ std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
++ thread = new JackThread(this);
++ std::auto_ptr<JackThread> thread_ptr(thread);
++ snprintf(semaphore_name, sizeof(semaphore_name), "coremidi_%p", this);
++ thread_queue_semaphore = sem_open(semaphore_name, O_CREAT, 0777, 0);
++ if (thread_queue_semaphore == (sem_t *) SEM_FAILED) {
++ throw std::runtime_error(strerror(errno));
++ }
++ advance_schedule_time = 0;
++ thread_ptr.release();
++ thread_queue_ptr.release();
++ read_queue_ptr.release();
++}
++
++JackCoreMidiOutputPort::~JackCoreMidiOutputPort()
++{
++ delete thread;
++ sem_close(thread_queue_semaphore);
++ sem_unlink(semaphore_name);
++ delete read_queue;
++ delete thread_queue;
++}
++
++bool
++JackCoreMidiOutputPort::Execute()
++{
++ jack_midi_event_t *event = 0;
++ MIDIPacketList *packet_list = (MIDIPacketList *) packet_buffer;
++ for (;;) {
++ MIDIPacket *packet = MIDIPacketListInit(packet_list);
++ assert(packet);
++ if (! event) {
++ event = GetCoreMidiEvent(true);
++ }
++ jack_midi_data_t *data = event->buffer;
++ jack_nframes_t send_frame = event->time;
++ jack_time_t send_time =
++ GetTimeFromFrames(send_frame) - advance_schedule_time;
++ size_t size = event->size;
++ MIDITimeStamp timestamp = GetTimeStampFromFrames(send_frame);
++ packet = MIDIPacketListAdd(packet_list, PACKET_BUFFER_SIZE, packet,
++ timestamp, size, data);
++ if (packet) {
++ while (GetMicroSeconds() < send_time) {
++ event = GetCoreMidiEvent(false);
++ if (! event) {
++ break;
++ }
++ packet = MIDIPacketListAdd(packet_list, sizeof(packet_buffer),
++ packet,
++ GetTimeStampFromFrames(event->time),
++ event->size, event->buffer);
++ if (! packet) {
++ break;
++ }
++ }
++ SendPacketList(packet_list);
++ } else {
++
++ // We have a large system exclusive event. We'll have to send it
++ // out in multiple packets.
++ size_t bytes_sent = 0;
++ do {
++ packet = MIDIPacketListInit(packet_list);
++ assert(packet);
++ size_t num_bytes = 0;
++ for (; bytes_sent < size; bytes_sent += num_bytes) {
++ size_t num_bytes = size - bytes_sent;
++
++ // We use 256 because the MIDIPacket struct defines the
++ // size of the 'data' member to be 256 bytes. I believe
++ // this prevents packets from being dynamically allocated
++ // by 'MIDIPacketListAdd', but I might be wrong.
++ if (num_bytes > 256) {
++ num_bytes = 256;
++ }
++ packet = MIDIPacketListAdd(packet_list,
++ sizeof(packet_buffer), packet,
++ timestamp, num_bytes,
++ data + bytes_sent);
++ if (! packet) {
++ break;
++ }
++ }
++ if (! SendPacketList(packet_list)) {
++ // An error occurred. The error message has already been
++ // output. We lick our wounds and move along.
++ break;
++ }
++ } while (bytes_sent < size);
++ event = 0;
++ }
++ }
++ return false;
++}
++
++jack_midi_event_t *
++JackCoreMidiOutputPort::GetCoreMidiEvent(bool block)
++{
++ if (! block) {
++ if (sem_trywait(thread_queue_semaphore)) {
++ if (errno != EAGAIN) {
++ jack_error("JackCoreMidiOutputPort::Execute - sem_trywait: %s",
++ strerror(errno));
++ }
++ return 0;
++ }
++ } else {
++ while (sem_wait(thread_queue_semaphore)) {
++ if (errno != EINTR) {
++ jack_error("JackCoreMidiOutputPort::Execute - sem_wait: %s",
++ strerror(errno));
++ return 0;
++ }
++ }
++ }
++ return thread_queue->DequeueEvent();
++}
++
++MIDITimeStamp
++JackCoreMidiOutputPort::GetTimeStampFromFrames(jack_nframes_t frames)
++{
++ return GetTimeFromFrames(frames) / time_ratio;
++}
++
++bool
++JackCoreMidiOutputPort::Init()
++{
++ set_threaded_log_function();
++
++ // OSX only, values read in RT CoreMIDI thread
++ UInt64 period = 0;
++ UInt64 computation = 250 * 1000;
++ UInt64 constraint = 500 * 1000;
++ thread->SetParams(period, computation, constraint);
++
++ if (thread->AcquireSelfRealTime()) {
++ jack_error("JackCoreMidiOutputPort::Init - could not acquire realtime "
++ "scheduling. Continuing anyway.");
++ }
++ return true;
++}
++
++void
++JackCoreMidiOutputPort::Initialize(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, int index,
++ MIDIEndpointRef endpoint,
++ SInt32 advance_schedule_time)
++{
++ JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index,
++ endpoint, true);
++ assert(advance_schedule_time >= 0);
++ this->advance_schedule_time = advance_schedule_time;
++}
++
++void
++JackCoreMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
++ jack_nframes_t frames)
++{
++ read_queue->ResetMidiBuffer(port_buffer);
++ for (jack_midi_event_t *event = read_queue->DequeueEvent(); event;
++ event = read_queue->DequeueEvent()) {
++ switch (thread_queue->EnqueueEvent(event, frames)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++ jack_error("JackCoreMidiOutputPort::ProcessJack - The thread "
++ "queue buffer is full. Dropping event.");
++ break;
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackCoreMidiOutputPort::ProcessJack - The thread "
++ "queue couldn't enqueue a %d-byte event. Dropping "
++ "event.", event->size);
++ break;
++ default:
++ if (sem_post(thread_queue_semaphore)) {
++ jack_error("JackCoreMidiOutputPort::ProcessJack - unexpected "
++ "error while posting to thread queue semaphore: %s",
++ strerror(errno));
++ }
++ }
++ }
++}
++
++bool
++JackCoreMidiOutputPort::Start()
++{
++ bool result = thread->GetStatus() != JackThread::kIdle;
++ if (! result) {
++ result = ! thread->StartSync();
++ if (! result) {
++ jack_error("JackCoreMidiOutputPort::Start - failed to start MIDI "
++ "processing thread.");
++ }
++ }
++ return result;
++}
++
++bool
++JackCoreMidiOutputPort::Stop()
++{
++ bool result = thread->GetStatus() == JackThread::kIdle;
++ if (! result) {
++ result = ! thread->Kill();
++ if (! result) {
++ jack_error("JackCoreMidiOutputPort::Stop - failed to stop MIDI "
++ "processing thread.");
++ }
++ }
++ return result;
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiOutputPort.h
+@@ -0,0 +1,90 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiOutputPort__
++#define __JackCoreMidiOutputPort__
++
++#include <semaphore.h>
++
++#include "JackCoreMidiPort.h"
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiBufferReadQueue.h"
++#include "JackThread.h"
++
++namespace Jack {
++
++ class JackCoreMidiOutputPort:
++ public JackCoreMidiPort, public JackRunnableInterface {
++
++ private:
++
++ jack_midi_event_t *
++ GetCoreMidiEvent(bool block);
++
++ MIDITimeStamp
++ GetTimeStampFromFrames(jack_nframes_t frames);
++
++ static const size_t PACKET_BUFFER_SIZE = 65536;
++
++ SInt32 advance_schedule_time;
++ char packet_buffer[PACKET_BUFFER_SIZE];
++ JackMidiBufferReadQueue *read_queue;
++ char semaphore_name[128];
++ JackThread *thread;
++ JackMidiAsyncQueue *thread_queue;
++ sem_t *thread_queue_semaphore;
++
++ protected:
++
++ virtual bool
++ SendPacketList(MIDIPacketList *packet_list) = 0;
++
++ void
++ Initialize(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIEndpointRef endpoint, SInt32 advance_schedule_time);
++
++ public:
++
++ JackCoreMidiOutputPort(double time_ratio, size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ virtual
++ ~JackCoreMidiOutputPort();
++
++ bool
++ Execute();
++
++ bool
++ Init();
++
++ void
++ ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames);
++
++ bool
++ Start();
++
++ bool
++ Stop();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiPhysicalInputPort.cpp
+@@ -0,0 +1,53 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <sstream>
++#include <stdexcept>
++
++#include "JackCoreMidiPhysicalInputPort.h"
++#include "JackCoreMidiUtil.h"
++
++using Jack::JackCoreMidiPhysicalInputPort;
++
++JackCoreMidiPhysicalInputPort::
++JackCoreMidiPhysicalInputPort(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client, MIDIPortRef internal_input,
++ double time_ratio, size_t max_bytes,
++ size_t max_messages):
++ JackCoreMidiInputPort(time_ratio, max_bytes, max_messages)
++{
++ MIDIEndpointRef source = MIDIGetSource(index);
++ if (! source) {
++ // X: Is there a way to get a better error message?
++ std::stringstream stream;
++ stream << "The source at index '" << index << "' is not available";
++ throw std::runtime_error(stream.str().c_str());
++ }
++ OSStatus status = MIDIPortConnectSource(internal_input, source, this);
++ if (status != noErr) {
++ throw std::runtime_error(GetMacOSErrorString(status));
++ }
++ Initialize(alias_name, client_name, driver_name, index, source);
++}
++
++JackCoreMidiPhysicalInputPort::~JackCoreMidiPhysicalInputPort()
++{
++ // Empty
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiPhysicalInputPort.h
+@@ -0,0 +1,45 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiPhysicalInputPort__
++#define __JackCoreMidiPhysicalInputPort__
++
++#include "JackCoreMidiInputPort.h"
++
++namespace Jack {
++
++ class JackCoreMidiPhysicalInputPort: public JackCoreMidiInputPort {
++
++ public:
++
++ JackCoreMidiPhysicalInputPort(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client,
++ MIDIPortRef internal_input,
++ double time_ratio, size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackCoreMidiPhysicalInputPort();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiPhysicalOutputPort.cpp
+@@ -0,0 +1,78 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <sstream>
++#include <stdexcept>
++
++#include "JackCoreMidiPhysicalOutputPort.h"
++#include "JackCoreMidiUtil.h"
++
++using Jack::JackCoreMidiPhysicalOutputPort;
++
++JackCoreMidiPhysicalOutputPort::
++JackCoreMidiPhysicalOutputPort(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client,
++ MIDIPortRef internal_output, double time_ratio,
++ size_t max_bytes,
++ size_t max_messages):
++ JackCoreMidiOutputPort(time_ratio, max_bytes,
++ max_messages)
++{
++ MIDIEndpointRef destination = MIDIGetDestination(index);
++ if (! destination) {
++ // X: Can we get a better error message?
++ std::stringstream stream;
++ stream << "The destination at index '" << index
++ << "' is not available";
++ throw std::runtime_error(stream.str().c_str());
++ }
++ SInt32 advance_schedule_time;
++ OSStatus status =
++ MIDIObjectGetIntegerProperty(destination,
++ kMIDIPropertyAdvanceScheduleTimeMuSec,
++ &advance_schedule_time);
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiPhysicalOutputPort [constructor]",
++ "MIDIObjectGetIntegerProperty", status);
++ advance_schedule_time = 0;
++ } else if (advance_schedule_time < 0) {
++ advance_schedule_time = 0;
++ }
++ Initialize(alias_name, client_name, driver_name, index, destination,
++ advance_schedule_time);
++ this->internal_output = internal_output;
++}
++
++JackCoreMidiPhysicalOutputPort::~JackCoreMidiPhysicalOutputPort()
++{
++ // Empty
++}
++
++bool
++JackCoreMidiPhysicalOutputPort::SendPacketList(MIDIPacketList *packet_list)
++{
++ OSStatus status = MIDISend(internal_output, endpoint, packet_list);
++ bool result = status == noErr;
++ if (! result) {
++ WriteMacOSError("JackCoreMidiPhysicalOutputPort::SendPacketList",
++ "MIDISend", status);
++ }
++ return result;
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiPhysicalOutputPort.h
+@@ -0,0 +1,55 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiPhysicalOutputPort__
++#define __JackCoreMidiPhysicalOutputPort__
++
++#include "JackCoreMidiOutputPort.h"
++
++namespace Jack {
++
++ class JackCoreMidiPhysicalOutputPort: public JackCoreMidiOutputPort {
++
++ private:
++
++ MIDIPortRef internal_output;
++
++ protected:
++
++ bool
++ SendPacketList(MIDIPacketList *packet_list);
++
++ public:
++
++ JackCoreMidiPhysicalOutputPort(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client,
++ MIDIPortRef internal_output,
++ double time_ratio,
++ size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackCoreMidiPhysicalOutputPort();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiPort.cpp
+@@ -0,0 +1,93 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++
++#include "JackCoreMidiPort.h"
++#include "JackCoreMidiUtil.h"
++#include "JackError.h"
++
++using Jack::JackCoreMidiPort;
++
++JackCoreMidiPort::JackCoreMidiPort(double time_ratio)
++{
++ initialized = false;
++ this->time_ratio = time_ratio;
++}
++
++JackCoreMidiPort::~JackCoreMidiPort()
++{
++ // Empty
++}
++
++const char *
++JackCoreMidiPort::GetAlias()
++{
++ assert(initialized);
++ return alias;
++}
++
++MIDIEndpointRef
++JackCoreMidiPort::GetEndpoint()
++{
++ assert(initialized);
++ return endpoint;
++}
++
++const char *
++JackCoreMidiPort::GetName()
++{
++ assert(initialized);
++ return name;
++}
++
++void
++JackCoreMidiPort::Initialize(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIEndpointRef endpoint, bool is_output)
++{
++ char endpoint_name[REAL_JACK_PORT_NAME_SIZE];
++ CFStringRef endpoint_name_ref;
++ int num = index + 1;
++ Boolean res;
++ OSStatus result = MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName,
++ &endpoint_name_ref);
++ if (result != noErr) {
++ WriteMacOSError("JackCoreMidiPort::Initialize",
++ "MIDIObjectGetStringProperty", result);
++ goto get_basic_alias;
++ }
++ res = CFStringGetCString(endpoint_name_ref, endpoint_name,
++ sizeof(endpoint_name), 0);
++ CFRelease(endpoint_name_ref);
++ if (!res) {
++ jack_error("JackCoreMidiPort::Initialize - failed to allocate memory "
++ "for endpoint name.");
++ get_basic_alias:
++ snprintf(alias, sizeof(alias), "%s:%s:%s%d", alias_name,
++ driver_name, is_output ? "in" : "out", num);
++ } else {
++ snprintf(alias, sizeof(alias), "%s:%s:%s%d", alias_name,
++ endpoint_name, is_output ? "in" : "out", num);
++ }
++ snprintf(name, sizeof(name), "%s:%s_%d", client_name,
++ is_output ? "playback" : "capture", num);
++ this->endpoint = endpoint;
++ initialized = true;
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiPort.h
+@@ -0,0 +1,67 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiPort__
++#define __JackCoreMidiPort__
++
++#include <CoreMIDI/CoreMIDI.h>
++
++#include "JackConstants.h"
++
++namespace Jack {
++
++ class JackCoreMidiPort {
++
++ private:
++
++ char alias[REAL_JACK_PORT_NAME_SIZE];
++ bool initialized;
++ char name[REAL_JACK_PORT_NAME_SIZE];
++
++ protected:
++
++ MIDIEndpointRef
++ GetEndpoint();
++
++ void
++ Initialize(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIEndpointRef endpoint, bool is_output);
++
++ double time_ratio;
++ MIDIEndpointRef endpoint;
++
++ public:
++
++ JackCoreMidiPort(double time_ratio);
++
++ virtual
++ ~JackCoreMidiPort();
++
++ const char *
++ GetAlias();
++
++ const char *
++ GetName();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiUtil.cpp
+@@ -0,0 +1,43 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <sstream>
++
++#include "JackError.h"
++#include "JackCoreMidiUtil.h"
++
++std::string
++Jack::GetMacOSErrorString(OSStatus status)
++{
++ const char *message = GetMacOSStatusErrorString(status);
++ if (! message) {
++ std::stringstream stream;
++ stream << "error (code: '" << status << "')";
++ return stream.str();
++ }
++ return std::string(message);
++}
++
++void
++Jack::WriteMacOSError(const char *jack_function, const char *mac_function,
++ OSStatus status)
++{
++ jack_error("%s - %s: %s", jack_function, mac_function,
++ GetMacOSErrorString(status).c_str());
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiUtil.h
+@@ -0,0 +1,39 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiUtil__
++#define __JackCoreMidiUtil__
++
++#include <string>
++
++#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
++#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/Debugging.h>
++
++namespace Jack {
++
++ std::string
++ GetMacOSErrorString(OSStatus status);
++
++ void
++ WriteMacOSError(const char *jack_function, const char *mac_function,
++ OSStatus status);
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiVirtualInputPort.cpp
+@@ -0,0 +1,75 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <sstream>
++#include <stdexcept>
++
++#include "JackCoreMidiUtil.h"
++#include "JackCoreMidiVirtualInputPort.h"
++
++using Jack::JackCoreMidiVirtualInputPort;
++
++///////////////////////////////////////////////////////////////////////////////
++// Static callbacks
++///////////////////////////////////////////////////////////////////////////////
++
++void
++JackCoreMidiVirtualInputPort::
++HandleInputEvent(const MIDIPacketList *packet_list, void *port,
++ void */*src_ref*/)
++{
++ ((JackCoreMidiVirtualInputPort *) port)->ProcessCoreMidi(packet_list);
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Class
++///////////////////////////////////////////////////////////////////////////////
++
++JackCoreMidiVirtualInputPort::
++JackCoreMidiVirtualInputPort(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client, double time_ratio,
++ size_t max_bytes, size_t max_messages):
++ JackCoreMidiInputPort(time_ratio, max_bytes, max_messages)
++{
++ std::stringstream stream;
++ stream << "virtual" << (index + 1);
++ CFStringRef name = CFStringCreateWithCString(0, stream.str().c_str(),
++ CFStringGetSystemEncoding());
++ if (! name) {
++ throw std::bad_alloc();
++ }
++ MIDIEndpointRef destination;
++ OSStatus status = MIDIDestinationCreate(client, name, HandleInputEvent,
++ this, &destination);
++ CFRelease(name);
++ if (status != noErr) {
++ throw std::runtime_error(GetMacOSErrorString(status));
++ }
++ Initialize(alias_name, client_name, driver_name, index, destination);
++}
++
++JackCoreMidiVirtualInputPort::~JackCoreMidiVirtualInputPort()
++{
++ OSStatus status = MIDIEndpointDispose(GetEndpoint());
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiVirtualInputPort [destructor]",
++ "MIDIEndpointDispose", status);
++ }
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiVirtualInputPort.h
+@@ -0,0 +1,50 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiVirtualInputPort__
++#define __JackCoreMidiVirtualInputPort__
++
++#include "JackCoreMidiInputPort.h"
++
++namespace Jack {
++
++ class JackCoreMidiVirtualInputPort: public JackCoreMidiInputPort {
++
++ private:
++
++ static void
++ HandleInputEvent(const MIDIPacketList *packet_list, void *port,
++ void *src_ref);
++
++ public:
++
++ JackCoreMidiVirtualInputPort(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client, double time_ratio,
++ size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackCoreMidiVirtualInputPort();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiVirtualOutputPort.cpp
+@@ -0,0 +1,72 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <sstream>
++#include <stdexcept>
++
++#include "JackCoreMidiUtil.h"
++#include "JackCoreMidiVirtualOutputPort.h"
++
++using Jack::JackCoreMidiVirtualOutputPort;
++
++JackCoreMidiVirtualOutputPort::
++JackCoreMidiVirtualOutputPort(const char *alias_name, const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client, double time_ratio,
++ size_t max_bytes,
++ size_t max_messages):
++ JackCoreMidiOutputPort(time_ratio, max_bytes,
++ max_messages)
++{
++ std::stringstream stream;
++ stream << "virtual" << (index + 1);
++ CFStringRef name = CFStringCreateWithCString(0, stream.str().c_str(),
++ CFStringGetSystemEncoding());
++ if (! name) {
++ throw std::bad_alloc();
++ }
++ MIDIEndpointRef source;
++ OSStatus status = MIDISourceCreate(client, name, &source);
++ CFRelease(name);
++ if (status != noErr) {
++ throw std::runtime_error(GetMacOSErrorString(status));
++ }
++ Initialize(alias_name, client_name, driver_name, index, source, 0);
++}
++
++JackCoreMidiVirtualOutputPort::~JackCoreMidiVirtualOutputPort()
++{
++ OSStatus status = MIDIEndpointDispose(GetEndpoint());
++ if (status != noErr) {
++ WriteMacOSError("JackCoreMidiVirtualOutputPort [destructor]",
++ "MIDIEndpointDispose", status);
++ }
++}
++
++bool
++JackCoreMidiVirtualOutputPort::SendPacketList(MIDIPacketList *packet_list)
++{
++ OSStatus status = MIDIReceived(endpoint, packet_list);
++ bool result = status == noErr;
++ if (! result) {
++ WriteMacOSError("JackCoreMidiVirtualOutputPort::SendPacketList",
++ "MIDIReceived", status);
++ }
++ return result;
++}
+--- /dev/null
++++ b/macosx/coremidi/JackCoreMidiVirtualOutputPort.h
+@@ -0,0 +1,49 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackCoreMidiVirtualOutputPort__
++#define __JackCoreMidiVirtualOutputPort__
++
++#include "JackCoreMidiOutputPort.h"
++
++namespace Jack {
++
++ class JackCoreMidiVirtualOutputPort: public JackCoreMidiOutputPort {
++
++ protected:
++
++ bool
++ SendPacketList(MIDIPacketList *packet_list);
++
++ public:
++
++ JackCoreMidiVirtualOutputPort(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, int index,
++ MIDIClientRef client, double time_ratio,
++ size_t max_bytes=4096,
++ size_t max_messages=1024);
++
++ ~JackCoreMidiVirtualOutputPort();
++
++ };
++
++}
++
++#endif
+--- a/macosx/install_jackdmp
++++ b/macosx/install_jackdmp
+@@ -6,7 +6,8 @@
+
+ # Copy libraries and exe
+ sudo cp -r Jackmp.framework /Library/Frameworks/
+-sudo cp -r Jackservermp.framework /Library/Frameworks/
++sudo cp -r Jackservermp.framework /Library/Frameworks/
++sudo cp -r Jacknet.framework /Library/Frameworks/
+ sudo install -d /usr/local/bin
+ sudo cp jackdmp /usr/local/bin
+ [ -f jack_load ] && sudo cp jack_load /usr/local/bin
+@@ -31,9 +32,13 @@
+ cd /usr/local/lib && [ -f libjack.0.dylib ] && sudo mv -f libjack.0.dylib tmp_libjack.0.dylib
+ cd /usr/local/lib && [ -f jackd ] && sudo mv -f jackd tmp_jackd
+ cd /usr/local/lib && [ -f libjack.dylib ] && sudo rm libjack.dylib
++cd /usr/local/lib && [ -f libjacknet.dylib ] && sudo rm libjacknet.dylib
++cd /usr/local/lib && [ -f libjacknet.0.dylib ] && sudo rm libjacknet.0.dylib
+ cd /usr/local/bin && [ -f jackd ] && sudo rm jackd
+ cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jackmp.framework/Jackmp libjack.dylib
+ cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jackmp.framework/Jackmp libjack.0.dylib
++cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jacknet.framework/Jacknet libjacknet.dylib
++cd /usr/local/lib && sudo ln -s /Library/Frameworks/Jacknet.framework/Jacknet libjacknet.0.dylib
+ cd /usr/local/bin && sudo ln -s jackdmp jackd
+
+
+--- /dev/null
++++ b/macosx/iphone/audio_thru.mm
+@@ -0,0 +1,35 @@
++
++#include "JackAudioQueueAdapter.h"
++
++#define CHANNELS 2
++
++static void DSPcompute(int count, float** input, float** output)
++{
++ for (int i = 0; i < CHANNELS; i++) {
++ memcpy(output[i], input[i], count * sizeof(float));
++ }
++}
++
++int main(int argc, char *argv[]) {
++
++ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
++
++ Jack::JackAudioQueueAdapter audio(2, 2, 512, 44100, DSPcompute);
++
++ if (audio.Open() < 0) {
++ fprintf(stderr, "Cannot open audio\n");
++ return 1;
++ }
++
++ // Hang around forever...
++ while(1) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
++
++ int retVal = UIApplicationMain(argc, argv, nil, nil);
++ [pool release];
++
++ if (audio.Close() < 0) {
++ fprintf(stderr, "Cannot close audio\n");
++ }
++
++ return retVal;
++}
+--- /dev/null
++++ b/macosx/iphone/freeverb.mm
+@@ -0,0 +1,754 @@
++//-----------------------------------------------------
++// name: "freeverb"
++// version: "1.0"
++// author: "Grame"
++// license: "BSD"
++// copyright: "(c)GRAME 2006"
++//
++// Code generated with Faust 0.9.9.5b2 (http://faust.grame.fr)
++//-----------------------------------------------------
++/* link with */
++
++/* link with */
++#include <math.h>
++/* link with */
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <limits.h>
++#include <math.h>
++#include <errno.h>
++#include <time.h>
++#include <sys/ioctl.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <pwd.h>
++#include <sys/types.h>
++#include <assert.h>
++#include <pthread.h>
++#include <sys/wait.h>
++#include <libgen.h>
++#include <jack/net.h>
++
++#include <list>
++#include <vector>
++#include <iostream>
++#include <fstream>
++#include <stack>
++#include <list>
++#include <map>
++
++#include "JackAudioQueueAdapter.h"
++
++using namespace std;
++
++// On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
++// flags to avoid costly denormals
++#ifdef __SSE__
++ #include <xmmintrin.h>
++ #ifdef __SSE2__
++ #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
++ #else
++ #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
++ #endif
++#else
++ #define AVOIDDENORMALS
++#endif
++
++//#define BENCHMARKMODE
++
++struct Meta : map<const char*, const char*>
++{
++ void declare (const char* key, const char* value) { (*this)[key]=value; }
++};
++
++
++#define max(x,y) (((x)>(y)) ? (x) : (y))
++#define min(x,y) (((x)<(y)) ? (x) : (y))
++
++inline int lsr (int x, int n) { return int(((unsigned int)x) >> n); }
++inline int int2pow2 (int x) { int r=0; while ((1<<r)<x) r++; return r; }
++
++
++/******************************************************************************
++*******************************************************************************
++
++ VECTOR INTRINSICS
++
++*******************************************************************************
++*******************************************************************************/
++
++
++/******************************************************************************
++*******************************************************************************
++
++ USER INTERFACE
++
++*******************************************************************************
++*******************************************************************************/
++
++class UI
++{
++ bool fStopped;
++public:
++
++ UI() : fStopped(false) {}
++ virtual ~UI() {}
++
++ // -- active widgets
++
++ virtual void addButton(const char* label, float* zone) = 0;
++ virtual void addToggleButton(const char* label, float* zone) = 0;
++ virtual void addCheckButton(const char* label, float* zone) = 0;
++ virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
++ virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
++ virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
++
++ // -- passive widgets
++
++ virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
++ virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
++ virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
++ virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
++
++ // -- frames and labels
++
++ virtual void openFrameBox(const char* label) = 0;
++ virtual void openTabBox(const char* label) = 0;
++ virtual void openHorizontalBox(const char* label) = 0;
++ virtual void openVerticalBox(const char* label) = 0;
++ virtual void closeBox() = 0;
++
++ virtual void show() = 0;
++ virtual void run() = 0;
++
++ void stop() { fStopped = true; }
++ bool stopped() { return fStopped; }
++
++ virtual void declare(float* zone, const char* key, const char* value) {}
++};
++
++struct param {
++ float* fZone; float fMin; float fMax;
++ param(float* z, float a, float b) : fZone(z), fMin(a), fMax(b) {}
++};
++
++class CMDUI : public UI
++{
++ int fArgc;
++ char** fArgv;
++ stack<string> fPrefix;
++ map<string, param> fKeyParam;
++
++ void addOption(const char* label, float* zone, float min, float max)
++ {
++ string fullname = fPrefix.top() + label;
++ fKeyParam.insert(make_pair(fullname, param(zone, min, max)));
++ }
++
++ void openAnyBox(const char* label)
++ {
++ string prefix;
++
++ if (label && label[0]) {
++ prefix = fPrefix.top() + "-" + label;
++ } else {
++ prefix = fPrefix.top();
++ }
++ fPrefix.push(prefix);
++ }
++
++public:
++
++ CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv) { fPrefix.push("--"); }
++ virtual ~CMDUI() {}
++
++ virtual void addButton(const char* label, float* zone) {};
++ virtual void addToggleButton(const char* label, float* zone) {};
++ virtual void addCheckButton(const char* label, float* zone) {};
++
++ virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
++ {
++ addOption(label,zone,min,max);
++ }
++
++ virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
++ {
++ addOption(label,zone,min,max);
++ }
++
++ virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
++ {
++ addOption(label,zone,min,max);
++ }
++
++ // -- passive widgets
++
++ virtual void addNumDisplay(const char* label, float* zone, int precision) {}
++ virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) {}
++ virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {}
++ virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) {}
++
++ virtual void openFrameBox(const char* label) { openAnyBox(label); }
++ virtual void openTabBox(const char* label) { openAnyBox(label); }
++ virtual void openHorizontalBox(const char* label) { openAnyBox(label); }
++ virtual void openVerticalBox(const char* label) { openAnyBox(label); }
++
++ virtual void closeBox() { fPrefix.pop(); }
++
++ virtual void show() {}
++ virtual void run()
++ {
++ char c;
++ printf("Type 'q' to quit\n");
++ while ((c = getchar()) != 'q') {
++ sleep(1);
++ }
++ }
++
++ void print()
++ {
++ map<string, param>::iterator i;
++ cout << fArgc << "\n";
++ cout << fArgv[0] << " option list : ";
++ for (i = fKeyParam.begin(); i != fKeyParam.end(); i++) {
++ cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax <<" ] ";
++ }
++ }
++
++ void process_command()
++ {
++ map<string, param>::iterator p;
++ for (int i = 1; i < fArgc; i++) {
++ if (fArgv[i][0] == '-') {
++ p = fKeyParam.find(fArgv[i]);
++ if (p == fKeyParam.end()) {
++ cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
++ print();
++ exit(1);
++ }
++ char* end;
++ *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
++ i++;
++ }
++ }
++ }
++
++ void process_init()
++ {
++ map<string, param>::iterator p;
++ for (int i = 1; i < fArgc; i++) {
++ if (fArgv[i][0] == '-') {
++ p = fKeyParam.find(fArgv[i]);
++ if (p == fKeyParam.end()) {
++ cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
++ exit(1);
++ }
++ char* end;
++ *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
++ i++;
++ }
++ }
++ }
++};
++
++
++//----------------------------------------------------------------
++// Signal processor definition
++//----------------------------------------------------------------
++
++class dsp {
++ protected:
++ int fSamplingFreq;
++ public:
++ dsp() {}
++ virtual ~dsp() {}
++
++ virtual int getNumInputs() = 0;
++ virtual int getNumOutputs() = 0;
++ virtual void buildUserInterface(UI* interface) = 0;
++ virtual void init(int samplingRate) = 0;
++ virtual void compute(int len, float** inputs, float** outputs) = 0;
++ virtual void conclude() {}
++};
++
++
++//----------------------------------------------------------------------------
++// FAUST generated code
++//----------------------------------------------------------------------------
++
++
++class mydsp : public dsp {
++ private:
++ float fslider0;
++ float fRec9[2];
++ float fslider1;
++ int IOTA;
++ float fVec0[2048];
++ float fRec8[2];
++ float fRec11[2];
++ float fVec1[2048];
++ float fRec10[2];
++ float fRec13[2];
++ float fVec2[2048];
++ float fRec12[2];
++ float fRec15[2];
++ float fVec3[2048];
++ float fRec14[2];
++ float fRec17[2];
++ float fVec4[2048];
++ float fRec16[2];
++ float fRec19[2];
++ float fVec5[2048];
++ float fRec18[2];
++ float fRec21[2];
++ float fVec6[2048];
++ float fRec20[2];
++ float fRec23[2];
++ float fVec7[2048];
++ float fRec22[2];
++ float fVec8[1024];
++ float fRec6[2];
++ float fVec9[512];
++ float fRec4[2];
++ float fVec10[512];
++ float fRec2[2];
++ float fVec11[256];
++ float fRec0[2];
++ float fslider2;
++ float fRec33[2];
++ float fVec12[2048];
++ float fRec32[2];
++ float fRec35[2];
++ float fVec13[2048];
++ float fRec34[2];
++ float fRec37[2];
++ float fVec14[2048];
++ float fRec36[2];
++ float fRec39[2];
++ float fVec15[2048];
++ float fRec38[2];
++ float fRec41[2];
++ float fVec16[2048];
++ float fRec40[2];
++ float fRec43[2];
++ float fVec17[2048];
++ float fRec42[2];
++ float fRec45[2];
++ float fVec18[2048];
++ float fRec44[2];
++ float fRec47[2];
++ float fVec19[2048];
++ float fRec46[2];
++ float fVec20[1024];
++ float fRec30[2];
++ float fVec21[512];
++ float fRec28[2];
++ float fVec22[512];
++ float fRec26[2];
++ float fVec23[256];
++ float fRec24[2];
++ public:
++ static void metadata(Meta* m) {
++ m->declare("name", "freeverb");
++ m->declare("version", "1.0");
++ m->declare("author", "Grame");
++ m->declare("license", "BSD");
++ m->declare("copyright", "(c)GRAME 2006");
++ }
++
++ virtual int getNumInputs() { return 2; }
++ virtual int getNumOutputs() { return 2; }
++ static void classInit(int samplingFreq) {
++ }
++ virtual void instanceInit(int samplingFreq) {
++ fSamplingFreq = samplingFreq;
++ fslider0 = 0.5f;
++ for (int i=0; i<2; i++) fRec9[i] = 0;
++ fslider1 = 0.8f;
++ IOTA = 0;
++ for (int i=0; i<2048; i++) fVec0[i] = 0;
++ for (int i=0; i<2; i++) fRec8[i] = 0;
++ for (int i=0; i<2; i++) fRec11[i] = 0;
++ for (int i=0; i<2048; i++) fVec1[i] = 0;
++ for (int i=0; i<2; i++) fRec10[i] = 0;
++ for (int i=0; i<2; i++) fRec13[i] = 0;
++ for (int i=0; i<2048; i++) fVec2[i] = 0;
++ for (int i=0; i<2; i++) fRec12[i] = 0;
++ for (int i=0; i<2; i++) fRec15[i] = 0;
++ for (int i=0; i<2048; i++) fVec3[i] = 0;
++ for (int i=0; i<2; i++) fRec14[i] = 0;
++ for (int i=0; i<2; i++) fRec17[i] = 0;
++ for (int i=0; i<2048; i++) fVec4[i] = 0;
++ for (int i=0; i<2; i++) fRec16[i] = 0;
++ for (int i=0; i<2; i++) fRec19[i] = 0;
++ for (int i=0; i<2048; i++) fVec5[i] = 0;
++ for (int i=0; i<2; i++) fRec18[i] = 0;
++ for (int i=0; i<2; i++) fRec21[i] = 0;
++ for (int i=0; i<2048; i++) fVec6[i] = 0;
++ for (int i=0; i<2; i++) fRec20[i] = 0;
++ for (int i=0; i<2; i++) fRec23[i] = 0;
++ for (int i=0; i<2048; i++) fVec7[i] = 0;
++ for (int i=0; i<2; i++) fRec22[i] = 0;
++ for (int i=0; i<1024; i++) fVec8[i] = 0;
++ for (int i=0; i<2; i++) fRec6[i] = 0;
++ for (int i=0; i<512; i++) fVec9[i] = 0;
++ for (int i=0; i<2; i++) fRec4[i] = 0;
++ for (int i=0; i<512; i++) fVec10[i] = 0;
++ for (int i=0; i<2; i++) fRec2[i] = 0;
++ for (int i=0; i<256; i++) fVec11[i] = 0;
++ for (int i=0; i<2; i++) fRec0[i] = 0;
++ fslider2 = 0.8f;
++ for (int i=0; i<2; i++) fRec33[i] = 0;
++ for (int i=0; i<2048; i++) fVec12[i] = 0;
++ for (int i=0; i<2; i++) fRec32[i] = 0;
++ for (int i=0; i<2; i++) fRec35[i] = 0;
++ for (int i=0; i<2048; i++) fVec13[i] = 0;
++ for (int i=0; i<2; i++) fRec34[i] = 0;
++ for (int i=0; i<2; i++) fRec37[i] = 0;
++ for (int i=0; i<2048; i++) fVec14[i] = 0;
++ for (int i=0; i<2; i++) fRec36[i] = 0;
++ for (int i=0; i<2; i++) fRec39[i] = 0;
++ for (int i=0; i<2048; i++) fVec15[i] = 0;
++ for (int i=0; i<2; i++) fRec38[i] = 0;
++ for (int i=0; i<2; i++) fRec41[i] = 0;
++ for (int i=0; i<2048; i++) fVec16[i] = 0;
++ for (int i=0; i<2; i++) fRec40[i] = 0;
++ for (int i=0; i<2; i++) fRec43[i] = 0;
++ for (int i=0; i<2048; i++) fVec17[i] = 0;
++ for (int i=0; i<2; i++) fRec42[i] = 0;
++ for (int i=0; i<2; i++) fRec45[i] = 0;
++ for (int i=0; i<2048; i++) fVec18[i] = 0;
++ for (int i=0; i<2; i++) fRec44[i] = 0;
++ for (int i=0; i<2; i++) fRec47[i] = 0;
++ for (int i=0; i<2048; i++) fVec19[i] = 0;
++ for (int i=0; i<2; i++) fRec46[i] = 0;
++ for (int i=0; i<1024; i++) fVec20[i] = 0;
++ for (int i=0; i<2; i++) fRec30[i] = 0;
++ for (int i=0; i<512; i++) fVec21[i] = 0;
++ for (int i=0; i<2; i++) fRec28[i] = 0;
++ for (int i=0; i<512; i++) fVec22[i] = 0;
++ for (int i=0; i<2; i++) fRec26[i] = 0;
++ for (int i=0; i<256; i++) fVec23[i] = 0;
++ for (int i=0; i<2; i++) fRec24[i] = 0;
++ }
++ virtual void init(int samplingFreq) {
++ classInit(samplingFreq);
++ instanceInit(samplingFreq);
++ }
++ virtual void buildUserInterface(UI* interface) {
++ interface->openVerticalBox("Freeverb");
++ interface->addHorizontalSlider("Damp", &fslider0, 0.5f, 0.0f, 1.0f, 2.500000e-02f);
++ interface->addHorizontalSlider("RoomSize", &fslider1, 0.8f, 0.0f, 1.0f, 2.500000e-02f);
++ interface->addHorizontalSlider("Wet", &fslider2, 0.8f, 0.0f, 1.0f, 2.500000e-02f);
++ interface->closeBox();
++ }
++ virtual void compute (int count, float** input, float** output) {
++ float fSlow0 = (0.4f * fslider0);
++ float fSlow1 = (1 - fSlow0);
++ float fSlow2 = (0.7f + (0.28f * fslider1));
++ float fSlow3 = fslider2;
++ float fSlow4 = (1 - fSlow3);
++ float* input0 = input[0];
++ float* input1 = input[1];
++ float* output0 = output[0];
++ float* output1 = output[1];
++ for (int i=0; i<count; i++) {
++ fRec9[0] = ((fSlow1 * fRec8[1]) + (fSlow0 * fRec9[1]));
++ float fTemp0 = input1[i];
++ float fTemp1 = input0[i];
++ float fTemp2 = (1.500000e-02f * (fTemp1 + fTemp0));
++ fVec0[IOTA&2047] = (fTemp2 + (fSlow2 * fRec9[0]));
++ fRec8[0] = fVec0[(IOTA-1617)&2047];
++ fRec11[0] = ((fSlow1 * fRec10[1]) + (fSlow0 * fRec11[1]));
++ fVec1[IOTA&2047] = (fTemp2 + (fSlow2 * fRec11[0]));
++ fRec10[0] = fVec1[(IOTA-1557)&2047];
++ fRec13[0] = ((fSlow1 * fRec12[1]) + (fSlow0 * fRec13[1]));
++ fVec2[IOTA&2047] = (fTemp2 + (fSlow2 * fRec13[0]));
++ fRec12[0] = fVec2[(IOTA-1491)&2047];
++ fRec15[0] = ((fSlow1 * fRec14[1]) + (fSlow0 * fRec15[1]));
++ fVec3[IOTA&2047] = (fTemp2 + (fSlow2 * fRec15[0]));
++ fRec14[0] = fVec3[(IOTA-1422)&2047];
++ fRec17[0] = ((fSlow1 * fRec16[1]) + (fSlow0 * fRec17[1]));
++ fVec4[IOTA&2047] = (fTemp2 + (fSlow2 * fRec17[0]));
++ fRec16[0] = fVec4[(IOTA-1356)&2047];
++ fRec19[0] = ((fSlow1 * fRec18[1]) + (fSlow0 * fRec19[1]));
++ fVec5[IOTA&2047] = (fTemp2 + (fSlow2 * fRec19[0]));
++ fRec18[0] = fVec5[(IOTA-1277)&2047];
++ fRec21[0] = ((fSlow1 * fRec20[1]) + (fSlow0 * fRec21[1]));
++ fVec6[IOTA&2047] = (fTemp2 + (fSlow2 * fRec21[0]));
++ fRec20[0] = fVec6[(IOTA-1188)&2047];
++ fRec23[0] = ((fSlow1 * fRec22[1]) + (fSlow0 * fRec23[1]));
++ fVec7[IOTA&2047] = (fTemp2 + (fSlow2 * fRec23[0]));
++ fRec22[0] = fVec7[(IOTA-1116)&2047];
++ float fTemp3 = (((((((fRec22[0] + fRec20[0]) + fRec18[0]) + fRec16[0]) + fRec14[0]) + fRec12[0]) + fRec10[0]) + fRec8[0]);
++ fVec8[IOTA&1023] = (fTemp3 + (0.5f * fRec6[1]));
++ fRec6[0] = fVec8[(IOTA-556)&1023];
++ float fRec7 = (0 - (fTemp3 - fRec6[1]));
++ fVec9[IOTA&511] = (fRec7 + (0.5f * fRec4[1]));
++ fRec4[0] = fVec9[(IOTA-441)&511];
++ float fRec5 = (fRec4[1] - fRec7);
++ fVec10[IOTA&511] = (fRec5 + (0.5f * fRec2[1]));
++ fRec2[0] = fVec10[(IOTA-341)&511];
++ float fRec3 = (fRec2[1] - fRec5);
++ fVec11[IOTA&255] = (fRec3 + (0.5f * fRec0[1]));
++ fRec0[0] = fVec11[(IOTA-225)&255];
++ float fRec1 = (fRec0[1] - fRec3);
++ output0[i] = ((fSlow4 * fTemp1) + (fSlow3 * fRec1));
++ fRec33[0] = ((fSlow1 * fRec32[1]) + (fSlow0 * fRec33[1]));
++ fVec12[IOTA&2047] = (fTemp2 + (fSlow2 * fRec33[0]));
++ fRec32[0] = fVec12[(IOTA-1640)&2047];
++ fRec35[0] = ((fSlow1 * fRec34[1]) + (fSlow0 * fRec35[1]));
++ fVec13[IOTA&2047] = (fTemp2 + (fSlow2 * fRec35[0]));
++ fRec34[0] = fVec13[(IOTA-1580)&2047];
++ fRec37[0] = ((fSlow1 * fRec36[1]) + (fSlow0 * fRec37[1]));
++ fVec14[IOTA&2047] = (fTemp2 + (fSlow2 * fRec37[0]));
++ fRec36[0] = fVec14[(IOTA-1514)&2047];
++ fRec39[0] = ((fSlow1 * fRec38[1]) + (fSlow0 * fRec39[1]));
++ fVec15[IOTA&2047] = (fTemp2 + (fSlow2 * fRec39[0]));
++ fRec38[0] = fVec15[(IOTA-1445)&2047];
++ fRec41[0] = ((fSlow1 * fRec40[1]) + (fSlow0 * fRec41[1]));
++ fVec16[IOTA&2047] = (fTemp2 + (fSlow2 * fRec41[0]));
++ fRec40[0] = fVec16[(IOTA-1379)&2047];
++ fRec43[0] = ((fSlow1 * fRec42[1]) + (fSlow0 * fRec43[1]));
++ fVec17[IOTA&2047] = (fTemp2 + (fSlow2 * fRec43[0]));
++ fRec42[0] = fVec17[(IOTA-1300)&2047];
++ fRec45[0] = ((fSlow1 * fRec44[1]) + (fSlow0 * fRec45[1]));
++ fVec18[IOTA&2047] = (fTemp2 + (fSlow2 * fRec45[0]));
++ fRec44[0] = fVec18[(IOTA-1211)&2047];
++ fRec47[0] = ((fSlow1 * fRec46[1]) + (fSlow0 * fRec47[1]));
++ fVec19[IOTA&2047] = (fTemp2 + (fSlow2 * fRec47[0]));
++ fRec46[0] = fVec19[(IOTA-1139)&2047];
++ float fTemp4 = (((((((fRec46[0] + fRec44[0]) + fRec42[0]) + fRec40[0]) + fRec38[0]) + fRec36[0]) + fRec34[0]) + fRec32[0]);
++ fVec20[IOTA&1023] = (fTemp4 + (0.5f * fRec30[1]));
++ fRec30[0] = fVec20[(IOTA-579)&1023];
++ float fRec31 = (0 - (fTemp4 - fRec30[1]));
++ fVec21[IOTA&511] = (fRec31 + (0.5f * fRec28[1]));
++ fRec28[0] = fVec21[(IOTA-464)&511];
++ float fRec29 = (fRec28[1] - fRec31);
++ fVec22[IOTA&511] = (fRec29 + (0.5f * fRec26[1]));
++ fRec26[0] = fVec22[(IOTA-364)&511];
++ float fRec27 = (fRec26[1] - fRec29);
++ fVec23[IOTA&255] = (fRec27 + (0.5f * fRec24[1]));
++ fRec24[0] = fVec23[(IOTA-248)&255];
++ float fRec25 = (fRec24[1] - fRec27);
++ output1[i] = ((fSlow4 * fTemp0) + (fSlow3 * fRec25));
++ // post processing
++ fRec24[1] = fRec24[0];
++ fRec26[1] = fRec26[0];
++ fRec28[1] = fRec28[0];
++ fRec30[1] = fRec30[0];
++ fRec46[1] = fRec46[0];
++ fRec47[1] = fRec47[0];
++ fRec44[1] = fRec44[0];
++ fRec45[1] = fRec45[0];
++ fRec42[1] = fRec42[0];
++ fRec43[1] = fRec43[0];
++ fRec40[1] = fRec40[0];
++ fRec41[1] = fRec41[0];
++ fRec38[1] = fRec38[0];
++ fRec39[1] = fRec39[0];
++ fRec36[1] = fRec36[0];
++ fRec37[1] = fRec37[0];
++ fRec34[1] = fRec34[0];
++ fRec35[1] = fRec35[0];
++ fRec32[1] = fRec32[0];
++ fRec33[1] = fRec33[0];
++ fRec0[1] = fRec0[0];
++ fRec2[1] = fRec2[0];
++ fRec4[1] = fRec4[0];
++ fRec6[1] = fRec6[0];
++ fRec22[1] = fRec22[0];
++ fRec23[1] = fRec23[0];
++ fRec20[1] = fRec20[0];
++ fRec21[1] = fRec21[0];
++ fRec18[1] = fRec18[0];
++ fRec19[1] = fRec19[0];
++ fRec16[1] = fRec16[0];
++ fRec17[1] = fRec17[0];
++ fRec14[1] = fRec14[0];
++ fRec15[1] = fRec15[0];
++ fRec12[1] = fRec12[0];
++ fRec13[1] = fRec13[0];
++ fRec10[1] = fRec10[0];
++ fRec11[1] = fRec11[0];
++ fRec8[1] = fRec8[0];
++ IOTA = IOTA+1;
++ fRec9[1] = fRec9[0];
++ }
++ }
++};
++
++
++
++
++mydsp DSP;
++
++
++/******************************************************************************
++*******************************************************************************
++
++ NETJACK AUDIO INTERFACE
++
++*******************************************************************************
++*******************************************************************************/
++
++//----------------------------------------------------------------------------
++// number of input and output channels
++//----------------------------------------------------------------------------
++
++int gNumInChans;
++int gNumOutChans;
++
++//----------------------------------------------------------------------------
++// Jack Callbacks
++//----------------------------------------------------------------------------
++
++static void net_shutdown(void *)
++{
++ exit(1);
++}
++
++#ifdef BENCHMARKMODE
++// mesuring jack performances
++static __inline__ unsigned long long int rdtsc(void)
++{
++ unsigned long long int x;
++ __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
++ return x;
++}
++
++#define KSKIP 10
++#define KMESURE 1024
++int mesure = 0;
++unsigned long long int starts[KMESURE];
++unsigned long long int stops [KMESURE];
++
++#define STARTMESURE starts[mesure%KMESURE] = rdtsc();
++#define STOPMESURE stops[mesure%KMESURE] = rdtsc(); mesure = mesure+1;
++
++void printstats()
++{
++ unsigned long long int low, hi, tot;
++ low = hi = tot = (stops[KSKIP] - starts[KSKIP]);
++
++ if (mesure < KMESURE) {
++
++ for (int i = KSKIP+1; i<mesure; i++) {
++ unsigned long long int m = stops[i] - starts[i];
++ if (m<low) low = m;
++ if (m>hi) hi = m;
++ tot += m;
++ }
++ cout << low << ' ' << tot/(mesure-KSKIP) << ' ' << hi << endl;
++
++ } else {
++
++ for (int i = KSKIP+1; i<KMESURE; i++) {
++ unsigned long long int m = stops[i] - starts[i];
++ if (m<low) low = m;
++ if (m>hi) hi = m;
++ tot += m;
++ }
++ cout << low << ' ' << tot/(KMESURE-KSKIP) << ' ' << hi << endl;
++
++ }
++}
++
++#else
++
++#define STARTMESURE
++#define STOPMESURE
++
++#endif
++
++static int net_process(jack_nframes_t buffer_size,
++ int audio_input,
++ float** audio_input_buffer,
++ int midi_input,
++ void** midi_input_buffer,
++ int audio_output,
++ float** audio_output_buffer,
++ int midi_output,
++ void** midi_output_buffer,
++ void* data)
++{
++ AVOIDDENORMALS;
++ STARTMESURE
++ DSP.compute(buffer_size, audio_input_buffer, audio_output_buffer);
++ STOPMESURE
++ return 0;
++}
++
++/******************************************************************************
++*******************************************************************************
++
++ MAIN PLAY THREAD
++
++*******************************************************************************
++*******************************************************************************/
++
++//-------------------------------------------------------------------------
++// MAIN
++//-------------------------------------------------------------------------
++
++
++#define TEST_MASTER "194.5.49.5"
++
++int main(int argc, char *argv[]) {
++
++ UI* interface = new CMDUI(argc, argv);
++ jack_net_slave_t* net;
++ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
++
++ //Jack::JackAudioQueueAdapter audio(2, 2, 1024, 44100, NULL);
++
++ gNumInChans = DSP.getNumInputs();
++ gNumOutChans = DSP.getNumOutputs();
++
++ jack_slave_t request = { gNumInChans, gNumOutChans, 0, 0, DEFAULT_MTU, -1, 2 };
++ jack_master_t result;
++
++ printf("Network\n");
++
++ //if (audio.Open() < 0) {
++ // fprintf(stderr, "Cannot open audio\n");
++ // return 1;
++ //}
++
++ //audio.Start();
++
++ // Hang around forever...
++ //while(1) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
++
++ if ((net = jack_net_slave_open(TEST_MASTER, DEFAULT_PORT, "iPhone", &request, &result)) == 0) {
++ fprintf(stderr, "jack remote server not running ?\n");
++ return 1;
++ }
++
++ jack_set_net_slave_process_callback(net, net_process, NULL);
++
++ // We want to restart (that is "wait for available master" again)
++ //jack_set_net_shutdown_callback(net, net_shutdown, 0);
++
++ DSP.init(result.sample_rate);
++ DSP.buildUserInterface(interface);
++
++ if (jack_net_slave_activate(net) != 0) {
++ fprintf(stderr, "cannot activate net");
++ return 1;
++ }
++
++ int retVal = UIApplicationMain(argc, argv, nil, nil);
++ [pool release];
++
++ // Wait for application end
++ jack_net_slave_deactivate(net);
++ jack_net_slave_close(net);
++
++ //if (audio.Close() < 0) {
++ // fprintf(stderr, "Cannot close audio\n");
++ //}
++
++ return retVal;
++}
+--- /dev/null
++++ b/macosx/iphone/Info.plist
+@@ -0,0 +1,30 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
++<plist version="1.0">
++<dict>
++ <key>CFBundleDevelopmentRegion</key>
++ <string>English</string>
++ <key>CFBundleDisplayName</key>
++ <string>${PRODUCT_NAME}</string>
++ <key>CFBundleExecutable</key>
++ <string>${EXECUTABLE_NAME}</string>
++ <key>CFBundleIconFile</key>
++ <string></string>
++ <key>CFBundleIdentifier</key>
++ <string>fr.grame.iGrame.iPhoneFaustNet</string>
++ <key>CFBundleInfoDictionaryVersion</key>
++ <string>6.0</string>
++ <key>CFBundleName</key>
++ <string>${PRODUCT_NAME}</string>
++ <key>CFBundlePackageType</key>
++ <string>APPL</string>
++ <key>CFBundleSignature</key>
++ <string>????</string>
++ <key>CFBundleVersion</key>
++ <string>1.0</string>
++ <key>LSRequiresIPhoneOS</key>
++ <true/>
++ <key>NSMainNibFile</key>
++ <string>MainWindow</string>
++</dict>
++</plist>
+--- /dev/null
++++ b/macosx/iphone/iphone-faust.mm
+@@ -0,0 +1,3129 @@
++//-----------------------------------------------------
++// name: "freeverb"
++// version: "1.0"
++// author: "Grame"
++// license: "BSD"
++// copyright: "(c)GRAME 2006"
++//
++// Code generated with Faust 0.9.10 (http://faust.grame.fr)
++//-----------------------------------------------------
++/* link with */
++/* link with */
++#include <math.h>
++/* link with */
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <limits.h>
++#include <math.h>
++#include <errno.h>
++#include <time.h>
++#include <sys/ioctl.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <pwd.h>
++#include <sys/types.h>
++#include <assert.h>
++#include <pthread.h>
++#include <sys/wait.h>
++
++#include <list>
++#include <vector>
++#include <iostream>
++#include <fstream>
++#include <stack>
++#include <list>
++#include <map>
++#include <libgen.h>
++
++#include <AudioToolbox/AudioConverter.h>
++#include <AudioToolbox/AudioServices.h>
++#include <AudioUnit/AudioUnit.h>
++
++#include "HardwareClock.h"
++
++using namespace std;
++
++// On Intel set FZ (Flush to Zero) and DAZ (Denormals Are Zero)
++// flags to avoid costly denormals
++#ifdef __SSE__
++ #include <xmmintrin.h>
++ #ifdef __SSE2__
++ #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8040)
++ #else
++ #define AVOIDDENORMALS _mm_setcsr(_mm_getcsr() | 0x8000)
++ #endif
++#else
++ #define AVOIDDENORMALS
++#endif
++
++//#define BENCHMARKMODE
++
++struct Meta : map<const char*, const char*>
++{
++ void declare (const char* key, const char* value) { (*this)[key]=value; }
++};
++
++//inline void *aligned_calloc(size_t nmemb, size_t size) { return (void*)((unsigned)(calloc((nmemb*size)+15,sizeof(char)))+15 & 0xfffffff0); }
++
++// g++ -O3 -lm -ljack `gtk-config --cflags --libs` ex2.cpp
++
++
++#define max(x,y) (((x)>(y)) ? (x) : (y))
++#define min(x,y) (((x)<(y)) ? (x) : (y))
++
++inline int lsr(int x, int n) { return int(((unsigned int)x) >> n); }
++inline int int2pow2(int x) { int r=0; while ((1<<r)<x) r++; return r; }
++
++/******************************************************************************
++*******************************************************************************
++
++ VECTOR INTRINSICS
++
++*******************************************************************************
++*******************************************************************************/
++
++
++/******************************************************************************
++*******************************************************************************
++
++ USER INTERFACE
++
++*******************************************************************************
++*******************************************************************************/
++
++class UI
++{
++ bool fStopped;
++
++ public:
++
++ UI() : fStopped(false) {}
++ virtual ~UI() {}
++
++ // -- active widgets
++
++ virtual void addButton(const char* label, float* zone) = 0;
++ virtual void addToggleButton(const char* label, float* zone) = 0;
++ virtual void addCheckButton(const char* label, float* zone) = 0;
++ virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
++ virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step) = 0;
++ virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step) = 0;
++
++ // -- passive widgets
++
++ virtual void addNumDisplay(const char* label, float* zone, int precision) = 0;
++ virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) = 0;
++ virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) = 0;
++ virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) = 0;
++
++ // -- frames and labels
++
++ virtual void openFrameBox(const char* label) = 0;
++ virtual void openTabBox(const char* label) = 0;
++ virtual void openHorizontalBox(const char* label) = 0;
++ virtual void openVerticalBox(const char* label) = 0;
++ virtual void closeBox() = 0;
++
++ virtual void show() = 0;
++ virtual void run() = 0;
++
++ void stop() { fStopped = true; }
++ bool stopped() { return fStopped; }
++
++ virtual void declare(float* zone, const char* key, const char* value) {}
++};
++
++struct param {
++ float* fZone; float fMin; float fMax;
++ param(float* z, float a, float b) : fZone(z), fMin(a), fMax(b) {}
++};
++
++class CMDUI : public UI
++{
++ int fArgc;
++ char** fArgv;
++ stack<string> fPrefix;
++ map<string, param> fKeyParam;
++
++ void addOption(const char* label, float* zone, float init, float min, float max)
++ {
++ string fullname = fPrefix.top() + label;
++ fKeyParam.insert(make_pair(fullname, param(zone, min, max)));
++ *zone = init;
++ }
++
++ void openAnyBox(const char* label)
++ {
++ string prefix;
++
++ if (label && label[0]) {
++ prefix = fPrefix.top() + "-" + label;
++ } else {
++ prefix = fPrefix.top();
++ }
++ fPrefix.push(prefix);
++ }
++
++public:
++
++ CMDUI(int argc, char *argv[]) : UI(), fArgc(argc), fArgv(argv) { fPrefix.push("--"); }
++ virtual ~CMDUI() {}
++
++ virtual void addButton(const char* label, float* zone) {};
++ virtual void addToggleButton(const char* label, float* zone) {};
++ virtual void addCheckButton(const char* label, float* zone) {};
++
++ virtual void addVerticalSlider(const char* label, float* zone, float init, float min, float max, float step)
++ {
++ addOption(label,zone,init, min,max);
++ }
++
++ virtual void addHorizontalSlider(const char* label, float* zone, float init, float min, float max, float step)
++ {
++ addOption(label,zone,init, min,max);
++ }
++
++ virtual void addNumEntry(const char* label, float* zone, float init, float min, float max, float step)
++ {
++ addOption(label,zone,init, min,max);
++ }
++
++ // -- passive widgets
++
++ virtual void addNumDisplay(const char* label, float* zone, int precision) {}
++ virtual void addTextDisplay(const char* label, float* zone, char* names[], float min, float max) {}
++ virtual void addHorizontalBargraph(const char* label, float* zone, float min, float max) {}
++ virtual void addVerticalBargraph(const char* label, float* zone, float min, float max) {}
++
++ virtual void openFrameBox(const char* label) { openAnyBox(label); }
++ virtual void openTabBox(const char* label) { openAnyBox(label); }
++ virtual void openHorizontalBox(const char* label) { openAnyBox(label); }
++ virtual void openVerticalBox(const char* label) { openAnyBox(label); }
++
++ virtual void closeBox() { fPrefix.pop(); }
++
++ virtual void show() {}
++ virtual void run()
++ {
++ char c;
++ printf("Type 'q' to quit\n");
++ while ((c = getchar()) != 'q') {
++ sleep(1);
++ }
++ }
++
++ void print()
++ {
++ map<string, param>::iterator i;
++ cout << fArgc << "\n";
++ cout << fArgv[0] << " option list : ";
++ for (i = fKeyParam.begin(); i != fKeyParam.end(); i++) {
++ cout << "[ " << i->first << " " << i->second.fMin << ".." << i->second.fMax <<" ] ";
++ }
++ }
++
++ void process_command()
++ {
++ map<string, param>::iterator p;
++ for (int i = 1; i < fArgc; i++) {
++ if (fArgv[i][0] == '-') {
++ p = fKeyParam.find(fArgv[i]);
++ if (p == fKeyParam.end()) {
++ cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
++ print();
++ exit(1);
++ }
++ char* end;
++ *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
++ i++;
++ }
++ }
++ }
++
++ void process_init()
++ {
++ map<string, param>::iterator p;
++ for (int i = 1; i < fArgc; i++) {
++ if (fArgv[i][0] == '-') {
++ p = fKeyParam.find(fArgv[i]);
++ if (p == fKeyParam.end()) {
++ cout << fArgv[0] << " : unrecognized option " << fArgv[i] << "\n";
++ exit(1);
++ }
++ char* end;
++ *(p->second.fZone) = float(strtod(fArgv[i+1], &end));
++ i++;
++ }
++ }
++ }
++};
++
++/******************************************************************************
++*******************************************************************************
++
++ FAUST DSP
++
++*******************************************************************************
++*******************************************************************************/
++
++
++//----------------------------------------------------------------
++// abstract definition of a signal processor
++//----------------------------------------------------------------
++
++class dsp {
++ protected:
++ int fSamplingFreq;
++ public:
++ dsp() {}
++ virtual ~dsp() {}
++
++ virtual int getNumInputs() = 0;
++ virtual int getNumOutputs() = 0;
++ virtual void buildUserInterface(UI* interface) = 0;
++ virtual void init(int samplingRate) = 0;
++ virtual void compute(int len, float** inputs, float** outputs) = 0;
++};
++
++//----------------------------------------------------------------------------
++// FAUST generated signal processor
++//----------------------------------------------------------------------------
++
++#ifndef FAUSTFLOAT
++#define FAUSTFLOAT float
++#endif
++
++typedef long double quad;
++
++class mydsp : public dsp{
++ private:
++ FAUSTFLOAT fslider0;
++ float fRec9_perm[4];
++ FAUSTFLOAT fslider1;
++ float fRec19_perm[4];
++ float fYec0[4096];
++ int fYec0_idx;
++ int fYec0_idx_save;
++ float fRec18_perm[4];
++ float fRec21_perm[4];
++ float fYec1[4096];
++ int fYec1_idx;
++ int fYec1_idx_save;
++ float fRec20_perm[4];
++ float fRec23_perm[4];
++ float fYec2[4096];
++ int fYec2_idx;
++ int fYec2_idx_save;
++ float fRec22_perm[4];
++ float fRec25_perm[4];
++ float fYec3[4096];
++ int fYec3_idx;
++ int fYec3_idx_save;
++ float fRec24_perm[4];
++ float fRec27_perm[4];
++ float fYec4[4096];
++ int fYec4_idx;
++ int fYec4_idx_save;
++ float fRec26_perm[4];
++ float fRec29_perm[4];
++ float fYec5[4096];
++ int fYec5_idx;
++ int fYec5_idx_save;
++ float fRec28_perm[4];
++ float fRec31_perm[4];
++ float fYec6[4096];
++ int fYec6_idx;
++ int fYec6_idx_save;
++ float fRec30_perm[4];
++ float fRec33_perm[4];
++ float fYec7[4096];
++ int fYec7_idx;
++ int fYec7_idx_save;
++ float fRec32_perm[4];
++ float fYec8[2048];
++ int fYec8_idx;
++ int fYec8_idx_save;
++ float fRec16_perm[4];
++ float fYec9[2048];
++ int fYec9_idx;
++ int fYec9_idx_save;
++ float fRec14_perm[4];
++ float fYec10[2048];
++ int fYec10_idx;
++ int fYec10_idx_save;
++ float fRec12_perm[4];
++ float fYec11[2048];
++ int fYec11_idx;
++ int fYec11_idx_save;
++ float fRec10_perm[4];
++ FAUSTFLOAT fslider2;
++ float fRec43_perm[4];
++ float fYec12[4096];
++ int fYec12_idx;
++ int fYec12_idx_save;
++ float fRec42_perm[4];
++ float fRec45_perm[4];
++ float fYec13[4096];
++ int fYec13_idx;
++ int fYec13_idx_save;
++ float fRec44_perm[4];
++ float fRec47_perm[4];
++ float fYec14[4096];
++ int fYec14_idx;
++ int fYec14_idx_save;
++ float fRec46_perm[4];
++ float fRec49_perm[4];
++ float fYec15[4096];
++ int fYec15_idx;
++ int fYec15_idx_save;
++ float fRec48_perm[4];
++ float fRec51_perm[4];
++ float fYec16[4096];
++ int fYec16_idx;
++ int fYec16_idx_save;
++ float fRec50_perm[4];
++ float fRec53_perm[4];
++ float fYec17[4096];
++ int fYec17_idx;
++ int fYec17_idx_save;
++ float fRec52_perm[4];
++ float fRec55_perm[4];
++ float fYec18[4096];
++ int fYec18_idx;
++ int fYec18_idx_save;
++ float fRec54_perm[4];
++ float fRec57_perm[4];
++ float fYec19[4096];
++ int fYec19_idx;
++ int fYec19_idx_save;
++ float fRec56_perm[4];
++ float fYec20[2048];
++ int fYec20_idx;
++ int fYec20_idx_save;
++ float fRec40_perm[4];
++ float fYec21[2048];
++ int fYec21_idx;
++ int fYec21_idx_save;
++ float fRec38_perm[4];
++ float fYec22[2048];
++ int fYec22_idx;
++ int fYec22_idx_save;
++ float fRec36_perm[4];
++ float fYec23[2048];
++ int fYec23_idx;
++ int fYec23_idx_save;
++ float fRec34_perm[4];
++ float fYec24[4096];
++ int fYec24_idx;
++ int fYec24_idx_save;
++ float fRec8_perm[4];
++ float fRec59_perm[4];
++ float fYec25[4096];
++ int fYec25_idx;
++ int fYec25_idx_save;
++ float fRec58_perm[4];
++ float fRec61_perm[4];
++ float fYec26[4096];
++ int fYec26_idx;
++ int fYec26_idx_save;
++ float fRec60_perm[4];
++ float fRec63_perm[4];
++ float fYec27[4096];
++ int fYec27_idx;
++ int fYec27_idx_save;
++ float fRec62_perm[4];
++ float fRec65_perm[4];
++ float fYec28[4096];
++ int fYec28_idx;
++ int fYec28_idx_save;
++ float fRec64_perm[4];
++ float fRec67_perm[4];
++ float fYec29[4096];
++ int fYec29_idx;
++ int fYec29_idx_save;
++ float fRec66_perm[4];
++ float fRec69_perm[4];
++ float fYec30[4096];
++ int fYec30_idx;
++ int fYec30_idx_save;
++ float fRec68_perm[4];
++ float fRec71_perm[4];
++ float fYec31[4096];
++ int fYec31_idx;
++ int fYec31_idx_save;
++ float fRec70_perm[4];
++ float fYec32[2048];
++ int fYec32_idx;
++ int fYec32_idx_save;
++ float fRec6_perm[4];
++ float fYec33[2048];
++ int fYec33_idx;
++ int fYec33_idx_save;
++ float fRec4_perm[4];
++ float fYec34[2048];
++ int fYec34_idx;
++ int fYec34_idx_save;
++ float fRec2_perm[4];
++ float fYec35[2048];
++ int fYec35_idx;
++ int fYec35_idx_save;
++ float fRec0_perm[4];
++ float fRec81_perm[4];
++ float fYec36[4096];
++ int fYec36_idx;
++ int fYec36_idx_save;
++ float fRec80_perm[4];
++ float fRec83_perm[4];
++ float fYec37[4096];
++ int fYec37_idx;
++ int fYec37_idx_save;
++ float fRec82_perm[4];
++ float fRec85_perm[4];
++ float fYec38[4096];
++ int fYec38_idx;
++ int fYec38_idx_save;
++ float fRec84_perm[4];
++ float fRec87_perm[4];
++ float fYec39[4096];
++ int fYec39_idx;
++ int fYec39_idx_save;
++ float fRec86_perm[4];
++ float fRec89_perm[4];
++ float fYec40[4096];
++ int fYec40_idx;
++ int fYec40_idx_save;
++ float fRec88_perm[4];
++ float fRec91_perm[4];
++ float fYec41[4096];
++ int fYec41_idx;
++ int fYec41_idx_save;
++ float fRec90_perm[4];
++ float fRec93_perm[4];
++ float fYec42[4096];
++ int fYec42_idx;
++ int fYec42_idx_save;
++ float fRec92_perm[4];
++ float fRec95_perm[4];
++ float fYec43[4096];
++ int fYec43_idx;
++ int fYec43_idx_save;
++ float fRec94_perm[4];
++ float fYec44[2048];
++ int fYec44_idx;
++ int fYec44_idx_save;
++ float fRec78_perm[4];
++ float fYec45[2048];
++ int fYec45_idx;
++ int fYec45_idx_save;
++ float fRec76_perm[4];
++ float fYec46[2048];
++ int fYec46_idx;
++ int fYec46_idx_save;
++ float fRec74_perm[4];
++ float fYec47[2048];
++ int fYec47_idx;
++ int fYec47_idx_save;
++ float fRec72_perm[4];
++ public:
++ static void metadata(Meta* m) {
++ m->declare("name", "freeverb");
++ m->declare("version", "1.0");
++ m->declare("author", "Grame");
++ m->declare("license", "BSD");
++ m->declare("copyright", "(c)GRAME 2006");
++ }
++
++ virtual int getNumInputs() { return 2; }
++ virtual int getNumOutputs() { return 2; }
++ static void classInit(int samplingFreq) {
++ }
++ virtual void instanceInit(int samplingFreq) {
++ fSamplingFreq = samplingFreq;
++ fslider0 = 0.5f;
++ for (int i=0; i<4; i++) fRec9_perm[i]=0;
++ fslider1 = 0.5f;
++ for (int i=0; i<4; i++) fRec19_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec0[i]=0;
++ fYec0_idx = 0;
++ fYec0_idx_save = 0;
++ for (int i=0; i<4; i++) fRec18_perm[i]=0;
++ for (int i=0; i<4; i++) fRec21_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec1[i]=0;
++ fYec1_idx = 0;
++ fYec1_idx_save = 0;
++ for (int i=0; i<4; i++) fRec20_perm[i]=0;
++ for (int i=0; i<4; i++) fRec23_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec2[i]=0;
++ fYec2_idx = 0;
++ fYec2_idx_save = 0;
++ for (int i=0; i<4; i++) fRec22_perm[i]=0;
++ for (int i=0; i<4; i++) fRec25_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec3[i]=0;
++ fYec3_idx = 0;
++ fYec3_idx_save = 0;
++ for (int i=0; i<4; i++) fRec24_perm[i]=0;
++ for (int i=0; i<4; i++) fRec27_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec4[i]=0;
++ fYec4_idx = 0;
++ fYec4_idx_save = 0;
++ for (int i=0; i<4; i++) fRec26_perm[i]=0;
++ for (int i=0; i<4; i++) fRec29_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec5[i]=0;
++ fYec5_idx = 0;
++ fYec5_idx_save = 0;
++ for (int i=0; i<4; i++) fRec28_perm[i]=0;
++ for (int i=0; i<4; i++) fRec31_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec6[i]=0;
++ fYec6_idx = 0;
++ fYec6_idx_save = 0;
++ for (int i=0; i<4; i++) fRec30_perm[i]=0;
++ for (int i=0; i<4; i++) fRec33_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec7[i]=0;
++ fYec7_idx = 0;
++ fYec7_idx_save = 0;
++ for (int i=0; i<4; i++) fRec32_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec8[i]=0;
++ fYec8_idx = 0;
++ fYec8_idx_save = 0;
++ for (int i=0; i<4; i++) fRec16_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec9[i]=0;
++ fYec9_idx = 0;
++ fYec9_idx_save = 0;
++ for (int i=0; i<4; i++) fRec14_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec10[i]=0;
++ fYec10_idx = 0;
++ fYec10_idx_save = 0;
++ for (int i=0; i<4; i++) fRec12_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec11[i]=0;
++ fYec11_idx = 0;
++ fYec11_idx_save = 0;
++ for (int i=0; i<4; i++) fRec10_perm[i]=0;
++ fslider2 = 0.3333f;
++ for (int i=0; i<4; i++) fRec43_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec12[i]=0;
++ fYec12_idx = 0;
++ fYec12_idx_save = 0;
++ for (int i=0; i<4; i++) fRec42_perm[i]=0;
++ for (int i=0; i<4; i++) fRec45_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec13[i]=0;
++ fYec13_idx = 0;
++ fYec13_idx_save = 0;
++ for (int i=0; i<4; i++) fRec44_perm[i]=0;
++ for (int i=0; i<4; i++) fRec47_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec14[i]=0;
++ fYec14_idx = 0;
++ fYec14_idx_save = 0;
++ for (int i=0; i<4; i++) fRec46_perm[i]=0;
++ for (int i=0; i<4; i++) fRec49_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec15[i]=0;
++ fYec15_idx = 0;
++ fYec15_idx_save = 0;
++ for (int i=0; i<4; i++) fRec48_perm[i]=0;
++ for (int i=0; i<4; i++) fRec51_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec16[i]=0;
++ fYec16_idx = 0;
++ fYec16_idx_save = 0;
++ for (int i=0; i<4; i++) fRec50_perm[i]=0;
++ for (int i=0; i<4; i++) fRec53_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec17[i]=0;
++ fYec17_idx = 0;
++ fYec17_idx_save = 0;
++ for (int i=0; i<4; i++) fRec52_perm[i]=0;
++ for (int i=0; i<4; i++) fRec55_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec18[i]=0;
++ fYec18_idx = 0;
++ fYec18_idx_save = 0;
++ for (int i=0; i<4; i++) fRec54_perm[i]=0;
++ for (int i=0; i<4; i++) fRec57_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec19[i]=0;
++ fYec19_idx = 0;
++ fYec19_idx_save = 0;
++ for (int i=0; i<4; i++) fRec56_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec20[i]=0;
++ fYec20_idx = 0;
++ fYec20_idx_save = 0;
++ for (int i=0; i<4; i++) fRec40_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec21[i]=0;
++ fYec21_idx = 0;
++ fYec21_idx_save = 0;
++ for (int i=0; i<4; i++) fRec38_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec22[i]=0;
++ fYec22_idx = 0;
++ fYec22_idx_save = 0;
++ for (int i=0; i<4; i++) fRec36_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec23[i]=0;
++ fYec23_idx = 0;
++ fYec23_idx_save = 0;
++ for (int i=0; i<4; i++) fRec34_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec24[i]=0;
++ fYec24_idx = 0;
++ fYec24_idx_save = 0;
++ for (int i=0; i<4; i++) fRec8_perm[i]=0;
++ for (int i=0; i<4; i++) fRec59_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec25[i]=0;
++ fYec25_idx = 0;
++ fYec25_idx_save = 0;
++ for (int i=0; i<4; i++) fRec58_perm[i]=0;
++ for (int i=0; i<4; i++) fRec61_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec26[i]=0;
++ fYec26_idx = 0;
++ fYec26_idx_save = 0;
++ for (int i=0; i<4; i++) fRec60_perm[i]=0;
++ for (int i=0; i<4; i++) fRec63_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec27[i]=0;
++ fYec27_idx = 0;
++ fYec27_idx_save = 0;
++ for (int i=0; i<4; i++) fRec62_perm[i]=0;
++ for (int i=0; i<4; i++) fRec65_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec28[i]=0;
++ fYec28_idx = 0;
++ fYec28_idx_save = 0;
++ for (int i=0; i<4; i++) fRec64_perm[i]=0;
++ for (int i=0; i<4; i++) fRec67_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec29[i]=0;
++ fYec29_idx = 0;
++ fYec29_idx_save = 0;
++ for (int i=0; i<4; i++) fRec66_perm[i]=0;
++ for (int i=0; i<4; i++) fRec69_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec30[i]=0;
++ fYec30_idx = 0;
++ fYec30_idx_save = 0;
++ for (int i=0; i<4; i++) fRec68_perm[i]=0;
++ for (int i=0; i<4; i++) fRec71_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec31[i]=0;
++ fYec31_idx = 0;
++ fYec31_idx_save = 0;
++ for (int i=0; i<4; i++) fRec70_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec32[i]=0;
++ fYec32_idx = 0;
++ fYec32_idx_save = 0;
++ for (int i=0; i<4; i++) fRec6_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec33[i]=0;
++ fYec33_idx = 0;
++ fYec33_idx_save = 0;
++ for (int i=0; i<4; i++) fRec4_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec34[i]=0;
++ fYec34_idx = 0;
++ fYec34_idx_save = 0;
++ for (int i=0; i<4; i++) fRec2_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec35[i]=0;
++ fYec35_idx = 0;
++ fYec35_idx_save = 0;
++ for (int i=0; i<4; i++) fRec0_perm[i]=0;
++ for (int i=0; i<4; i++) fRec81_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec36[i]=0;
++ fYec36_idx = 0;
++ fYec36_idx_save = 0;
++ for (int i=0; i<4; i++) fRec80_perm[i]=0;
++ for (int i=0; i<4; i++) fRec83_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec37[i]=0;
++ fYec37_idx = 0;
++ fYec37_idx_save = 0;
++ for (int i=0; i<4; i++) fRec82_perm[i]=0;
++ for (int i=0; i<4; i++) fRec85_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec38[i]=0;
++ fYec38_idx = 0;
++ fYec38_idx_save = 0;
++ for (int i=0; i<4; i++) fRec84_perm[i]=0;
++ for (int i=0; i<4; i++) fRec87_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec39[i]=0;
++ fYec39_idx = 0;
++ fYec39_idx_save = 0;
++ for (int i=0; i<4; i++) fRec86_perm[i]=0;
++ for (int i=0; i<4; i++) fRec89_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec40[i]=0;
++ fYec40_idx = 0;
++ fYec40_idx_save = 0;
++ for (int i=0; i<4; i++) fRec88_perm[i]=0;
++ for (int i=0; i<4; i++) fRec91_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec41[i]=0;
++ fYec41_idx = 0;
++ fYec41_idx_save = 0;
++ for (int i=0; i<4; i++) fRec90_perm[i]=0;
++ for (int i=0; i<4; i++) fRec93_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec42[i]=0;
++ fYec42_idx = 0;
++ fYec42_idx_save = 0;
++ for (int i=0; i<4; i++) fRec92_perm[i]=0;
++ for (int i=0; i<4; i++) fRec95_perm[i]=0;
++ for (int i=0; i<4096; i++) fYec43[i]=0;
++ fYec43_idx = 0;
++ fYec43_idx_save = 0;
++ for (int i=0; i<4; i++) fRec94_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec44[i]=0;
++ fYec44_idx = 0;
++ fYec44_idx_save = 0;
++ for (int i=0; i<4; i++) fRec78_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec45[i]=0;
++ fYec45_idx = 0;
++ fYec45_idx_save = 0;
++ for (int i=0; i<4; i++) fRec76_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec46[i]=0;
++ fYec46_idx = 0;
++ fYec46_idx_save = 0;
++ for (int i=0; i<4; i++) fRec74_perm[i]=0;
++ for (int i=0; i<2048; i++) fYec47[i]=0;
++ fYec47_idx = 0;
++ fYec47_idx_save = 0;
++ for (int i=0; i<4; i++) fRec72_perm[i]=0;
++ }
++ virtual void init(int samplingFreq) {
++ classInit(samplingFreq);
++ instanceInit(samplingFreq);
++ }
++ virtual void buildUserInterface(UI* interface) {
++ interface->openVerticalBox("Freeverb");
++ interface->addHorizontalSlider("Damp", &fslider0, 0.5f, 0.0f, 1.0f, 2.500000e-02f);
++ interface->addHorizontalSlider("RoomSize", &fslider1, 0.5f, 0.0f, 1.0f, 2.500000e-02f);
++ interface->addHorizontalSlider("Wet", &fslider2, 0.3333f, 0.0f, 1.0f, 2.500000e-02f);
++ interface->closeBox();
++ }
++ virtual void compute (int fullcount, FAUSTFLOAT** input, FAUSTFLOAT** output) {
++ float fRec9_tmp[1024+4];
++ float fRec19_tmp[1024+4];
++ float fZec0[1024];
++ float fRec18_tmp[1024+4];
++ float fRec21_tmp[1024+4];
++ float fRec20_tmp[1024+4];
++ float fRec23_tmp[1024+4];
++ float fRec22_tmp[1024+4];
++ float fRec25_tmp[1024+4];
++ float fRec24_tmp[1024+4];
++ float fRec27_tmp[1024+4];
++ float fRec26_tmp[1024+4];
++ float fRec29_tmp[1024+4];
++ float fRec28_tmp[1024+4];
++ float fRec31_tmp[1024+4];
++ float fRec30_tmp[1024+4];
++ float fRec33_tmp[1024+4];
++ float fRec32_tmp[1024+4];
++ float fZec1[1024];
++ float fRec16_tmp[1024+4];
++ float fRec17[1024];
++ float fRec14_tmp[1024+4];
++ float fRec15[1024];
++ float fRec12_tmp[1024+4];
++ float fRec13[1024];
++ float fRec10_tmp[1024+4];
++ float fRec11[1024];
++ float fZec2[1024];
++ float fRec43_tmp[1024+4];
++ float fRec42_tmp[1024+4];
++ float fRec45_tmp[1024+4];
++ float fRec44_tmp[1024+4];
++ float fRec47_tmp[1024+4];
++ float fRec46_tmp[1024+4];
++ float fRec49_tmp[1024+4];
++ float fRec48_tmp[1024+4];
++ float fRec51_tmp[1024+4];
++ float fRec50_tmp[1024+4];
++ float fRec53_tmp[1024+4];
++ float fRec52_tmp[1024+4];
++ float fRec55_tmp[1024+4];
++ float fRec54_tmp[1024+4];
++ float fRec57_tmp[1024+4];
++ float fRec56_tmp[1024+4];
++ float fZec3[1024];
++ float fRec40_tmp[1024+4];
++ float fRec41[1024];
++ float fRec38_tmp[1024+4];
++ float fRec39[1024];
++ float fRec36_tmp[1024+4];
++ float fRec37[1024];
++ float fRec34_tmp[1024+4];
++ float fRec35[1024];
++ float fZec4[1024];
++ float fZec5[1024];
++ float fRec8_tmp[1024+4];
++ float fRec59_tmp[1024+4];
++ float fRec58_tmp[1024+4];
++ float fRec61_tmp[1024+4];
++ float fRec60_tmp[1024+4];
++ float fRec63_tmp[1024+4];
++ float fRec62_tmp[1024+4];
++ float fRec65_tmp[1024+4];
++ float fRec64_tmp[1024+4];
++ float fRec67_tmp[1024+4];
++ float fRec66_tmp[1024+4];
++ float fRec69_tmp[1024+4];
++ float fRec68_tmp[1024+4];
++ float fRec71_tmp[1024+4];
++ float fRec70_tmp[1024+4];
++ float fZec6[1024];
++ float fRec6_tmp[1024+4];
++ float fRec7[1024];
++ float fRec4_tmp[1024+4];
++ float fRec5[1024];
++ float fRec2_tmp[1024+4];
++ float fRec3[1024];
++ float fRec0_tmp[1024+4];
++ float fRec1[1024];
++ float fRec81_tmp[1024+4];
++ float fRec80_tmp[1024+4];
++ float fRec83_tmp[1024+4];
++ float fRec82_tmp[1024+4];
++ float fRec85_tmp[1024+4];
++ float fRec84_tmp[1024+4];
++ float fRec87_tmp[1024+4];
++ float fRec86_tmp[1024+4];
++ float fRec89_tmp[1024+4];
++ float fRec88_tmp[1024+4];
++ float fRec91_tmp[1024+4];
++ float fRec90_tmp[1024+4];
++ float fRec93_tmp[1024+4];
++ float fRec92_tmp[1024+4];
++ float fRec95_tmp[1024+4];
++ float fRec94_tmp[1024+4];
++ float fZec7[1024];
++ float fRec78_tmp[1024+4];
++ float fRec79[1024];
++ float fRec76_tmp[1024+4];
++ float fRec77[1024];
++ float fRec74_tmp[1024+4];
++ float fRec75[1024];
++ float fRec72_tmp[1024+4];
++ float fRec73[1024];
++ float fSlow0 = (0.4f * fslider0);
++ float fSlow1 = (1 - fSlow0);
++ float* fRec9 = &fRec9_tmp[4];
++ float fSlow2 = (0.7f + (0.28f * fslider1));
++ float* fRec19 = &fRec19_tmp[4];
++ float* fRec18 = &fRec18_tmp[4];
++ float* fRec21 = &fRec21_tmp[4];
++ float* fRec20 = &fRec20_tmp[4];
++ float* fRec23 = &fRec23_tmp[4];
++ float* fRec22 = &fRec22_tmp[4];
++ float* fRec25 = &fRec25_tmp[4];
++ float* fRec24 = &fRec24_tmp[4];
++ float* fRec27 = &fRec27_tmp[4];
++ float* fRec26 = &fRec26_tmp[4];
++ float* fRec29 = &fRec29_tmp[4];
++ float* fRec28 = &fRec28_tmp[4];
++ float* fRec31 = &fRec31_tmp[4];
++ float* fRec30 = &fRec30_tmp[4];
++ float* fRec33 = &fRec33_tmp[4];
++ float* fRec32 = &fRec32_tmp[4];
++ float* fRec16 = &fRec16_tmp[4];
++ float* fRec14 = &fRec14_tmp[4];
++ float* fRec12 = &fRec12_tmp[4];
++ float* fRec10 = &fRec10_tmp[4];
++ float fSlow3 = fslider2;
++ float fSlow4 = (1 - fSlow3);
++ float* fRec43 = &fRec43_tmp[4];
++ float* fRec42 = &fRec42_tmp[4];
++ float* fRec45 = &fRec45_tmp[4];
++ float* fRec44 = &fRec44_tmp[4];
++ float* fRec47 = &fRec47_tmp[4];
++ float* fRec46 = &fRec46_tmp[4];
++ float* fRec49 = &fRec49_tmp[4];
++ float* fRec48 = &fRec48_tmp[4];
++ float* fRec51 = &fRec51_tmp[4];
++ float* fRec50 = &fRec50_tmp[4];
++ float* fRec53 = &fRec53_tmp[4];
++ float* fRec52 = &fRec52_tmp[4];
++ float* fRec55 = &fRec55_tmp[4];
++ float* fRec54 = &fRec54_tmp[4];
++ float* fRec57 = &fRec57_tmp[4];
++ float* fRec56 = &fRec56_tmp[4];
++ float* fRec40 = &fRec40_tmp[4];
++ float* fRec38 = &fRec38_tmp[4];
++ float* fRec36 = &fRec36_tmp[4];
++ float* fRec34 = &fRec34_tmp[4];
++ float* fRec8 = &fRec8_tmp[4];
++ float* fRec59 = &fRec59_tmp[4];
++ float* fRec58 = &fRec58_tmp[4];
++ float* fRec61 = &fRec61_tmp[4];
++ float* fRec60 = &fRec60_tmp[4];
++ float* fRec63 = &fRec63_tmp[4];
++ float* fRec62 = &fRec62_tmp[4];
++ float* fRec65 = &fRec65_tmp[4];
++ float* fRec64 = &fRec64_tmp[4];
++ float* fRec67 = &fRec67_tmp[4];
++ float* fRec66 = &fRec66_tmp[4];
++ float* fRec69 = &fRec69_tmp[4];
++ float* fRec68 = &fRec68_tmp[4];
++ float* fRec71 = &fRec71_tmp[4];
++ float* fRec70 = &fRec70_tmp[4];
++ float* fRec6 = &fRec6_tmp[4];
++ float* fRec4 = &fRec4_tmp[4];
++ float* fRec2 = &fRec2_tmp[4];
++ float* fRec0 = &fRec0_tmp[4];
++ float* fRec81 = &fRec81_tmp[4];
++ float* fRec80 = &fRec80_tmp[4];
++ float* fRec83 = &fRec83_tmp[4];
++ float* fRec82 = &fRec82_tmp[4];
++ float* fRec85 = &fRec85_tmp[4];
++ float* fRec84 = &fRec84_tmp[4];
++ float* fRec87 = &fRec87_tmp[4];
++ float* fRec86 = &fRec86_tmp[4];
++ float* fRec89 = &fRec89_tmp[4];
++ float* fRec88 = &fRec88_tmp[4];
++ float* fRec91 = &fRec91_tmp[4];
++ float* fRec90 = &fRec90_tmp[4];
++ float* fRec93 = &fRec93_tmp[4];
++ float* fRec92 = &fRec92_tmp[4];
++ float* fRec95 = &fRec95_tmp[4];
++ float* fRec94 = &fRec94_tmp[4];
++ float* fRec78 = &fRec78_tmp[4];
++ float* fRec76 = &fRec76_tmp[4];
++ float* fRec74 = &fRec74_tmp[4];
++ float* fRec72 = &fRec72_tmp[4];
++ int index;
++ for (index = 0; index <= fullcount - 1024; index += 1024) {
++ // compute by blocks of 1024 samples
++ const int count = 1024;
++ FAUSTFLOAT* input0 = &input[0][index];
++ FAUSTFLOAT* input1 = &input[1][index];
++ FAUSTFLOAT* output0 = &output[0][index];
++ FAUSTFLOAT* output1 = &output[1][index];
++ // SECTION : 1
++ // LOOP 0x101350bc0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec0[i] = (1.500000e-02f * ((float)input0[i] + (float)input1[i]));
++ }
++
++ // SECTION : 2
++ // LOOP 0x10134f970
++ // pre processing
++ for (int i=0; i<4; i++) fRec19_tmp[i]=fRec19_perm[i];
++ fYec0_idx = (fYec0_idx+fYec0_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec18_tmp[i]=fRec18_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec19[i] = ((fSlow1 * fRec18[i-1]) + (fSlow0 * fRec19[i-1]));
++ fYec0[(fYec0_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec19[i]));
++ fRec18[i] = fYec0[(fYec0_idx+i-1617)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec18_perm[i]=fRec18_tmp[count+i];
++ fYec0_idx_save = count;
++ for (int i=0; i<4; i++) fRec19_perm[i]=fRec19_tmp[count+i];
++
++ // LOOP 0x101351ed0
++ // pre processing
++ for (int i=0; i<4; i++) fRec21_tmp[i]=fRec21_perm[i];
++ fYec1_idx = (fYec1_idx+fYec1_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec20_tmp[i]=fRec20_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec21[i] = ((fSlow1 * fRec20[i-1]) + (fSlow0 * fRec21[i-1]));
++ fYec1[(fYec1_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec21[i]));
++ fRec20[i] = fYec1[(fYec1_idx+i-1557)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec20_perm[i]=fRec20_tmp[count+i];
++ fYec1_idx_save = count;
++ for (int i=0; i<4; i++) fRec21_perm[i]=fRec21_tmp[count+i];
++
++ // LOOP 0x101353a50
++ // pre processing
++ for (int i=0; i<4; i++) fRec23_tmp[i]=fRec23_perm[i];
++ fYec2_idx = (fYec2_idx+fYec2_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec22_tmp[i]=fRec22_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec23[i] = ((fSlow1 * fRec22[i-1]) + (fSlow0 * fRec23[i-1]));
++ fYec2[(fYec2_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec23[i]));
++ fRec22[i] = fYec2[(fYec2_idx+i-1491)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec22_perm[i]=fRec22_tmp[count+i];
++ fYec2_idx_save = count;
++ for (int i=0; i<4; i++) fRec23_perm[i]=fRec23_tmp[count+i];
++
++ // LOOP 0x1013555d0
++ // pre processing
++ for (int i=0; i<4; i++) fRec25_tmp[i]=fRec25_perm[i];
++ fYec3_idx = (fYec3_idx+fYec3_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec24_tmp[i]=fRec24_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec25[i] = ((fSlow1 * fRec24[i-1]) + (fSlow0 * fRec25[i-1]));
++ fYec3[(fYec3_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec25[i]));
++ fRec24[i] = fYec3[(fYec3_idx+i-1422)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec24_perm[i]=fRec24_tmp[count+i];
++ fYec3_idx_save = count;
++ for (int i=0; i<4; i++) fRec25_perm[i]=fRec25_tmp[count+i];
++
++ // LOOP 0x101357120
++ // pre processing
++ for (int i=0; i<4; i++) fRec27_tmp[i]=fRec27_perm[i];
++ fYec4_idx = (fYec4_idx+fYec4_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec26_tmp[i]=fRec26_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec27[i] = ((fSlow1 * fRec26[i-1]) + (fSlow0 * fRec27[i-1]));
++ fYec4[(fYec4_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec27[i]));
++ fRec26[i] = fYec4[(fYec4_idx+i-1356)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec26_perm[i]=fRec26_tmp[count+i];
++ fYec4_idx_save = count;
++ for (int i=0; i<4; i++) fRec27_perm[i]=fRec27_tmp[count+i];
++
++ // LOOP 0x101358c70
++ // pre processing
++ for (int i=0; i<4; i++) fRec29_tmp[i]=fRec29_perm[i];
++ fYec5_idx = (fYec5_idx+fYec5_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec28_tmp[i]=fRec28_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec29[i] = ((fSlow1 * fRec28[i-1]) + (fSlow0 * fRec29[i-1]));
++ fYec5[(fYec5_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec29[i]));
++ fRec28[i] = fYec5[(fYec5_idx+i-1277)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec28_perm[i]=fRec28_tmp[count+i];
++ fYec5_idx_save = count;
++ for (int i=0; i<4; i++) fRec29_perm[i]=fRec29_tmp[count+i];
++
++ // LOOP 0x10135a7e0
++ // pre processing
++ for (int i=0; i<4; i++) fRec31_tmp[i]=fRec31_perm[i];
++ fYec6_idx = (fYec6_idx+fYec6_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec30_tmp[i]=fRec30_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec31[i] = ((fSlow1 * fRec30[i-1]) + (fSlow0 * fRec31[i-1]));
++ fYec6[(fYec6_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec31[i]));
++ fRec30[i] = fYec6[(fYec6_idx+i-1188)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec30_perm[i]=fRec30_tmp[count+i];
++ fYec6_idx_save = count;
++ for (int i=0; i<4; i++) fRec31_perm[i]=fRec31_tmp[count+i];
++
++ // LOOP 0x10135c330
++ // pre processing
++ for (int i=0; i<4; i++) fRec33_tmp[i]=fRec33_perm[i];
++ fYec7_idx = (fYec7_idx+fYec7_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec32_tmp[i]=fRec32_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec33[i] = ((fSlow1 * fRec32[i-1]) + (fSlow0 * fRec33[i-1]));
++ fYec7[(fYec7_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec33[i]));
++ fRec32[i] = fYec7[(fYec7_idx+i-1116)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec32_perm[i]=fRec32_tmp[count+i];
++ fYec7_idx_save = count;
++ for (int i=0; i<4; i++) fRec33_perm[i]=fRec33_tmp[count+i];
++
++ // LOOP 0x101364b70
++ // pre processing
++ for (int i=0; i<4; i++) fRec43_tmp[i]=fRec43_perm[i];
++ fYec12_idx = (fYec12_idx+fYec12_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec42_tmp[i]=fRec42_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec43[i] = ((fSlow1 * fRec42[i-1]) + (fSlow0 * fRec43[i-1]));
++ fYec12[(fYec12_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec43[i]));
++ fRec42[i] = fYec12[(fYec12_idx+i-1640)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec42_perm[i]=fRec42_tmp[count+i];
++ fYec12_idx_save = count;
++ for (int i=0; i<4; i++) fRec43_perm[i]=fRec43_tmp[count+i];
++
++ // LOOP 0x1013667b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec45_tmp[i]=fRec45_perm[i];
++ fYec13_idx = (fYec13_idx+fYec13_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec44_tmp[i]=fRec44_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec45[i] = ((fSlow1 * fRec44[i-1]) + (fSlow0 * fRec45[i-1]));
++ fYec13[(fYec13_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec45[i]));
++ fRec44[i] = fYec13[(fYec13_idx+i-1580)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec44_perm[i]=fRec44_tmp[count+i];
++ fYec13_idx_save = count;
++ for (int i=0; i<4; i++) fRec45_perm[i]=fRec45_tmp[count+i];
++
++ // LOOP 0x101368330
++ // pre processing
++ for (int i=0; i<4; i++) fRec47_tmp[i]=fRec47_perm[i];
++ fYec14_idx = (fYec14_idx+fYec14_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec46_tmp[i]=fRec46_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec47[i] = ((fSlow1 * fRec46[i-1]) + (fSlow0 * fRec47[i-1]));
++ fYec14[(fYec14_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec47[i]));
++ fRec46[i] = fYec14[(fYec14_idx+i-1514)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec46_perm[i]=fRec46_tmp[count+i];
++ fYec14_idx_save = count;
++ for (int i=0; i<4; i++) fRec47_perm[i]=fRec47_tmp[count+i];
++
++ // LOOP 0x101369f40
++ // pre processing
++ for (int i=0; i<4; i++) fRec49_tmp[i]=fRec49_perm[i];
++ fYec15_idx = (fYec15_idx+fYec15_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec48_tmp[i]=fRec48_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec49[i] = ((fSlow1 * fRec48[i-1]) + (fSlow0 * fRec49[i-1]));
++ fYec15[(fYec15_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec49[i]));
++ fRec48[i] = fYec15[(fYec15_idx+i-1445)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec48_perm[i]=fRec48_tmp[count+i];
++ fYec15_idx_save = count;
++ for (int i=0; i<4; i++) fRec49_perm[i]=fRec49_tmp[count+i];
++
++ // LOOP 0x10136bae0
++ // pre processing
++ for (int i=0; i<4; i++) fRec51_tmp[i]=fRec51_perm[i];
++ fYec16_idx = (fYec16_idx+fYec16_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec50_tmp[i]=fRec50_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec51[i] = ((fSlow1 * fRec50[i-1]) + (fSlow0 * fRec51[i-1]));
++ fYec16[(fYec16_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec51[i]));
++ fRec50[i] = fYec16[(fYec16_idx+i-1379)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec50_perm[i]=fRec50_tmp[count+i];
++ fYec16_idx_save = count;
++ for (int i=0; i<4; i++) fRec51_perm[i]=fRec51_tmp[count+i];
++
++ // LOOP 0x10136d660
++ // pre processing
++ for (int i=0; i<4; i++) fRec53_tmp[i]=fRec53_perm[i];
++ fYec17_idx = (fYec17_idx+fYec17_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec52_tmp[i]=fRec52_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec53[i] = ((fSlow1 * fRec52[i-1]) + (fSlow0 * fRec53[i-1]));
++ fYec17[(fYec17_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec53[i]));
++ fRec52[i] = fYec17[(fYec17_idx+i-1300)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec52_perm[i]=fRec52_tmp[count+i];
++ fYec17_idx_save = count;
++ for (int i=0; i<4; i++) fRec53_perm[i]=fRec53_tmp[count+i];
++
++ // LOOP 0x10136f1e0
++ // pre processing
++ for (int i=0; i<4; i++) fRec55_tmp[i]=fRec55_perm[i];
++ fYec18_idx = (fYec18_idx+fYec18_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec54_tmp[i]=fRec54_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec55[i] = ((fSlow1 * fRec54[i-1]) + (fSlow0 * fRec55[i-1]));
++ fYec18[(fYec18_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec55[i]));
++ fRec54[i] = fYec18[(fYec18_idx+i-1211)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec54_perm[i]=fRec54_tmp[count+i];
++ fYec18_idx_save = count;
++ for (int i=0; i<4; i++) fRec55_perm[i]=fRec55_tmp[count+i];
++
++ // LOOP 0x101370d60
++ // pre processing
++ for (int i=0; i<4; i++) fRec57_tmp[i]=fRec57_perm[i];
++ fYec19_idx = (fYec19_idx+fYec19_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec56_tmp[i]=fRec56_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec57[i] = ((fSlow1 * fRec56[i-1]) + (fSlow0 * fRec57[i-1]));
++ fYec19[(fYec19_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec57[i]));
++ fRec56[i] = fYec19[(fYec19_idx+i-1139)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec56_perm[i]=fRec56_tmp[count+i];
++ fYec19_idx_save = count;
++ for (int i=0; i<4; i++) fRec57_perm[i]=fRec57_tmp[count+i];
++
++ // SECTION : 3
++ // LOOP 0x10134f870
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec1[i] = (((((((fRec32[i] + fRec30[i]) + fRec28[i]) + fRec26[i]) + fRec24[i]) + fRec22[i]) + fRec20[i]) + fRec18[i]);
++ }
++
++ // LOOP 0x101364a70
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec3[i] = (((((((fRec56[i] + fRec54[i]) + fRec52[i]) + fRec50[i]) + fRec48[i]) + fRec46[i]) + fRec44[i]) + fRec42[i]);
++ }
++
++ // SECTION : 4
++ // LOOP 0x10134f120
++ // pre processing
++ fYec8_idx = (fYec8_idx+fYec8_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec16_tmp[i]=fRec16_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec8[(fYec8_idx+i)&2047] = (fZec1[i] + (0.5f * fRec16[i-1]));
++ fRec16[i] = fYec8[(fYec8_idx+i-556)&2047];
++ fRec17[i] = (0 - (fZec1[i] - fRec16[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec16_perm[i]=fRec16_tmp[count+i];
++ fYec8_idx_save = count;
++
++ // LOOP 0x101364320
++ // pre processing
++ fYec20_idx = (fYec20_idx+fYec20_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec40_tmp[i]=fRec40_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec20[(fYec20_idx+i)&2047] = (fZec3[i] + (0.5f * fRec40[i-1]));
++ fRec40[i] = fYec20[(fYec20_idx+i-579)&2047];
++ fRec41[i] = (0 - (fZec3[i] - fRec40[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec40_perm[i]=fRec40_tmp[count+i];
++ fYec20_idx_save = count;
++
++ // SECTION : 5
++ // LOOP 0x10134e9d0
++ // pre processing
++ fYec9_idx = (fYec9_idx+fYec9_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec14_tmp[i]=fRec14_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec9[(fYec9_idx+i)&2047] = (fRec17[i] + (0.5f * fRec14[i-1]));
++ fRec14[i] = fYec9[(fYec9_idx+i-441)&2047];
++ fRec15[i] = (fRec14[i-1] - fRec17[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec14_perm[i]=fRec14_tmp[count+i];
++ fYec9_idx_save = count;
++
++ // LOOP 0x101363bd0
++ // pre processing
++ fYec21_idx = (fYec21_idx+fYec21_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec38_tmp[i]=fRec38_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec21[(fYec21_idx+i)&2047] = (fRec41[i] + (0.5f * fRec38[i-1]));
++ fRec38[i] = fYec21[(fYec21_idx+i-464)&2047];
++ fRec39[i] = (fRec38[i-1] - fRec41[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec38_perm[i]=fRec38_tmp[count+i];
++ fYec21_idx_save = count;
++
++ // SECTION : 6
++ // LOOP 0x10134e2a0
++ // pre processing
++ fYec10_idx = (fYec10_idx+fYec10_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec12_tmp[i]=fRec12_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec10[(fYec10_idx+i)&2047] = (fRec15[i] + (0.5f * fRec12[i-1]));
++ fRec12[i] = fYec10[(fYec10_idx+i-341)&2047];
++ fRec13[i] = (fRec12[i-1] - fRec15[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec12_perm[i]=fRec12_tmp[count+i];
++ fYec10_idx_save = count;
++
++ // LOOP 0x1013634a0
++ // pre processing
++ fYec22_idx = (fYec22_idx+fYec22_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec36_tmp[i]=fRec36_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec22[(fYec22_idx+i)&2047] = (fRec39[i] + (0.5f * fRec36[i-1]));
++ fRec36[i] = fYec22[(fYec22_idx+i-364)&2047];
++ fRec37[i] = (fRec36[i-1] - fRec39[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec36_perm[i]=fRec36_tmp[count+i];
++ fYec22_idx_save = count;
++
++ // SECTION : 7
++ // LOOP 0x10134dba0
++ // pre processing
++ fYec11_idx = (fYec11_idx+fYec11_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec10_tmp[i]=fRec10_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec11[(fYec11_idx+i)&2047] = (fRec13[i] + (0.5f * fRec10[i-1]));
++ fRec10[i] = fYec11[(fYec11_idx+i-225)&2047];
++ fRec11[i] = (fRec10[i-1] - fRec13[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec10_perm[i]=fRec10_tmp[count+i];
++ fYec11_idx_save = count;
++
++ // LOOP 0x101362e30
++ // pre processing
++ fYec23_idx = (fYec23_idx+fYec23_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec34_tmp[i]=fRec34_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec23[(fYec23_idx+i)&2047] = (fRec37[i] + (0.5f * fRec34[i-1]));
++ fRec34[i] = fYec23[(fYec23_idx+i-248)&2047];
++ fRec35[i] = (fRec34[i-1] - fRec37[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec34_perm[i]=fRec34_tmp[count+i];
++ fYec23_idx_save = count;
++
++ // SECTION : 8
++ // LOOP 0x10134daa0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec2[i] = ((fSlow4 * (float)input0[i]) + (fSlow3 * fRec11[i]));
++ }
++
++ // LOOP 0x101362d30
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec4[i] = ((fSlow4 * (float)input1[i]) + (fSlow3 * fRec35[i]));
++ }
++
++ // SECTION : 9
++ // LOOP 0x10134d9a0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec5[i] = (1.500000e-02f * (fZec4[i] + fZec2[i]));
++ }
++
++ // SECTION : 10
++ // LOOP 0x10134b4b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec9_tmp[i]=fRec9_perm[i];
++ fYec24_idx = (fYec24_idx+fYec24_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec8_tmp[i]=fRec8_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec9[i] = ((fSlow1 * fRec8[i-1]) + (fSlow0 * fRec9[i-1]));
++ fYec24[(fYec24_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec9[i]));
++ fRec8[i] = fYec24[(fYec24_idx+i-1617)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec8_perm[i]=fRec8_tmp[count+i];
++ fYec24_idx_save = count;
++ for (int i=0; i<4; i++) fRec9_perm[i]=fRec9_tmp[count+i];
++
++ // LOOP 0x101377dc0
++ // pre processing
++ for (int i=0; i<4; i++) fRec59_tmp[i]=fRec59_perm[i];
++ fYec25_idx = (fYec25_idx+fYec25_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec58_tmp[i]=fRec58_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec59[i] = ((fSlow1 * fRec58[i-1]) + (fSlow0 * fRec59[i-1]));
++ fYec25[(fYec25_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec59[i]));
++ fRec58[i] = fYec25[(fYec25_idx+i-1557)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec58_perm[i]=fRec58_tmp[count+i];
++ fYec25_idx_save = count;
++ for (int i=0; i<4; i++) fRec59_perm[i]=fRec59_tmp[count+i];
++
++ // LOOP 0x101379900
++ // pre processing
++ for (int i=0; i<4; i++) fRec61_tmp[i]=fRec61_perm[i];
++ fYec26_idx = (fYec26_idx+fYec26_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec60_tmp[i]=fRec60_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec61[i] = ((fSlow1 * fRec60[i-1]) + (fSlow0 * fRec61[i-1]));
++ fYec26[(fYec26_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec61[i]));
++ fRec60[i] = fYec26[(fYec26_idx+i-1491)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec60_perm[i]=fRec60_tmp[count+i];
++ fYec26_idx_save = count;
++ for (int i=0; i<4; i++) fRec61_perm[i]=fRec61_tmp[count+i];
++
++ // LOOP 0x10137b480
++ // pre processing
++ for (int i=0; i<4; i++) fRec63_tmp[i]=fRec63_perm[i];
++ fYec27_idx = (fYec27_idx+fYec27_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec62_tmp[i]=fRec62_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec63[i] = ((fSlow1 * fRec62[i-1]) + (fSlow0 * fRec63[i-1]));
++ fYec27[(fYec27_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec63[i]));
++ fRec62[i] = fYec27[(fYec27_idx+i-1422)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec62_perm[i]=fRec62_tmp[count+i];
++ fYec27_idx_save = count;
++ for (int i=0; i<4; i++) fRec63_perm[i]=fRec63_tmp[count+i];
++
++ // LOOP 0x10137d000
++ // pre processing
++ for (int i=0; i<4; i++) fRec65_tmp[i]=fRec65_perm[i];
++ fYec28_idx = (fYec28_idx+fYec28_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec64_tmp[i]=fRec64_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec65[i] = ((fSlow1 * fRec64[i-1]) + (fSlow0 * fRec65[i-1]));
++ fYec28[(fYec28_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec65[i]));
++ fRec64[i] = fYec28[(fYec28_idx+i-1356)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec64_perm[i]=fRec64_tmp[count+i];
++ fYec28_idx_save = count;
++ for (int i=0; i<4; i++) fRec65_perm[i]=fRec65_tmp[count+i];
++
++ // LOOP 0x10137eb80
++ // pre processing
++ for (int i=0; i<4; i++) fRec67_tmp[i]=fRec67_perm[i];
++ fYec29_idx = (fYec29_idx+fYec29_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec66_tmp[i]=fRec66_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec67[i] = ((fSlow1 * fRec66[i-1]) + (fSlow0 * fRec67[i-1]));
++ fYec29[(fYec29_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec67[i]));
++ fRec66[i] = fYec29[(fYec29_idx+i-1277)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec66_perm[i]=fRec66_tmp[count+i];
++ fYec29_idx_save = count;
++ for (int i=0; i<4; i++) fRec67_perm[i]=fRec67_tmp[count+i];
++
++ // LOOP 0x101380700
++ // pre processing
++ for (int i=0; i<4; i++) fRec69_tmp[i]=fRec69_perm[i];
++ fYec30_idx = (fYec30_idx+fYec30_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec68_tmp[i]=fRec68_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec69[i] = ((fSlow1 * fRec68[i-1]) + (fSlow0 * fRec69[i-1]));
++ fYec30[(fYec30_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec69[i]));
++ fRec68[i] = fYec30[(fYec30_idx+i-1188)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec68_perm[i]=fRec68_tmp[count+i];
++ fYec30_idx_save = count;
++ for (int i=0; i<4; i++) fRec69_perm[i]=fRec69_tmp[count+i];
++
++ // LOOP 0x101382280
++ // pre processing
++ for (int i=0; i<4; i++) fRec71_tmp[i]=fRec71_perm[i];
++ fYec31_idx = (fYec31_idx+fYec31_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec70_tmp[i]=fRec70_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec71[i] = ((fSlow1 * fRec70[i-1]) + (fSlow0 * fRec71[i-1]));
++ fYec31[(fYec31_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec71[i]));
++ fRec70[i] = fYec31[(fYec31_idx+i-1116)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec70_perm[i]=fRec70_tmp[count+i];
++ fYec31_idx_save = count;
++ for (int i=0; i<4; i++) fRec71_perm[i]=fRec71_tmp[count+i];
++
++ // LOOP 0x101389fc0
++ // pre processing
++ for (int i=0; i<4; i++) fRec81_tmp[i]=fRec81_perm[i];
++ fYec36_idx = (fYec36_idx+fYec36_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec80_tmp[i]=fRec80_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec81[i] = ((fSlow1 * fRec80[i-1]) + (fSlow0 * fRec81[i-1]));
++ fYec36[(fYec36_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec81[i]));
++ fRec80[i] = fYec36[(fYec36_idx+i-1640)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec80_perm[i]=fRec80_tmp[count+i];
++ fYec36_idx_save = count;
++ for (int i=0; i<4; i++) fRec81_perm[i]=fRec81_tmp[count+i];
++
++ // LOOP 0x10138bc10
++ // pre processing
++ for (int i=0; i<4; i++) fRec83_tmp[i]=fRec83_perm[i];
++ fYec37_idx = (fYec37_idx+fYec37_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec82_tmp[i]=fRec82_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec83[i] = ((fSlow1 * fRec82[i-1]) + (fSlow0 * fRec83[i-1]));
++ fYec37[(fYec37_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec83[i]));
++ fRec82[i] = fYec37[(fYec37_idx+i-1580)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec82_perm[i]=fRec82_tmp[count+i];
++ fYec37_idx_save = count;
++ for (int i=0; i<4; i++) fRec83_perm[i]=fRec83_tmp[count+i];
++
++ // LOOP 0x10138d7b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec85_tmp[i]=fRec85_perm[i];
++ fYec38_idx = (fYec38_idx+fYec38_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec84_tmp[i]=fRec84_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec85[i] = ((fSlow1 * fRec84[i-1]) + (fSlow0 * fRec85[i-1]));
++ fYec38[(fYec38_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec85[i]));
++ fRec84[i] = fYec38[(fYec38_idx+i-1514)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec84_perm[i]=fRec84_tmp[count+i];
++ fYec38_idx_save = count;
++ for (int i=0; i<4; i++) fRec85_perm[i]=fRec85_tmp[count+i];
++
++ // LOOP 0x10138f330
++ // pre processing
++ for (int i=0; i<4; i++) fRec87_tmp[i]=fRec87_perm[i];
++ fYec39_idx = (fYec39_idx+fYec39_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec86_tmp[i]=fRec86_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec87[i] = ((fSlow1 * fRec86[i-1]) + (fSlow0 * fRec87[i-1]));
++ fYec39[(fYec39_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec87[i]));
++ fRec86[i] = fYec39[(fYec39_idx+i-1445)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec86_perm[i]=fRec86_tmp[count+i];
++ fYec39_idx_save = count;
++ for (int i=0; i<4; i++) fRec87_perm[i]=fRec87_tmp[count+i];
++
++ // LOOP 0x101390eb0
++ // pre processing
++ for (int i=0; i<4; i++) fRec89_tmp[i]=fRec89_perm[i];
++ fYec40_idx = (fYec40_idx+fYec40_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec88_tmp[i]=fRec88_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec89[i] = ((fSlow1 * fRec88[i-1]) + (fSlow0 * fRec89[i-1]));
++ fYec40[(fYec40_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec89[i]));
++ fRec88[i] = fYec40[(fYec40_idx+i-1379)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec88_perm[i]=fRec88_tmp[count+i];
++ fYec40_idx_save = count;
++ for (int i=0; i<4; i++) fRec89_perm[i]=fRec89_tmp[count+i];
++
++ // LOOP 0x101392a30
++ // pre processing
++ for (int i=0; i<4; i++) fRec91_tmp[i]=fRec91_perm[i];
++ fYec41_idx = (fYec41_idx+fYec41_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec90_tmp[i]=fRec90_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec91[i] = ((fSlow1 * fRec90[i-1]) + (fSlow0 * fRec91[i-1]));
++ fYec41[(fYec41_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec91[i]));
++ fRec90[i] = fYec41[(fYec41_idx+i-1300)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec90_perm[i]=fRec90_tmp[count+i];
++ fYec41_idx_save = count;
++ for (int i=0; i<4; i++) fRec91_perm[i]=fRec91_tmp[count+i];
++
++ // LOOP 0x1013945b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec93_tmp[i]=fRec93_perm[i];
++ fYec42_idx = (fYec42_idx+fYec42_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec92_tmp[i]=fRec92_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec93[i] = ((fSlow1 * fRec92[i-1]) + (fSlow0 * fRec93[i-1]));
++ fYec42[(fYec42_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec93[i]));
++ fRec92[i] = fYec42[(fYec42_idx+i-1211)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec92_perm[i]=fRec92_tmp[count+i];
++ fYec42_idx_save = count;
++ for (int i=0; i<4; i++) fRec93_perm[i]=fRec93_tmp[count+i];
++
++ // LOOP 0x101396130
++ // pre processing
++ for (int i=0; i<4; i++) fRec95_tmp[i]=fRec95_perm[i];
++ fYec43_idx = (fYec43_idx+fYec43_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec94_tmp[i]=fRec94_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec95[i] = ((fSlow1 * fRec94[i-1]) + (fSlow0 * fRec95[i-1]));
++ fYec43[(fYec43_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec95[i]));
++ fRec94[i] = fYec43[(fYec43_idx+i-1139)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec94_perm[i]=fRec94_tmp[count+i];
++ fYec43_idx_save = count;
++ for (int i=0; i<4; i++) fRec95_perm[i]=fRec95_tmp[count+i];
++
++ // SECTION : 11
++ // LOOP 0x10134b3b0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec6[i] = (((((((fRec70[i] + fRec68[i]) + fRec66[i]) + fRec64[i]) + fRec62[i]) + fRec60[i]) + fRec58[i]) + fRec8[i]);
++ }
++
++ // LOOP 0x101389ec0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec7[i] = (((((((fRec94[i] + fRec92[i]) + fRec90[i]) + fRec88[i]) + fRec86[i]) + fRec84[i]) + fRec82[i]) + fRec80[i]);
++ }
++
++ // SECTION : 12
++ // LOOP 0x10134acd0
++ // pre processing
++ fYec32_idx = (fYec32_idx+fYec32_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec6_tmp[i]=fRec6_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec32[(fYec32_idx+i)&2047] = (fZec6[i] + (0.5f * fRec6[i-1]));
++ fRec6[i] = fYec32[(fYec32_idx+i-556)&2047];
++ fRec7[i] = (0 - (fZec6[i] - fRec6[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec6_perm[i]=fRec6_tmp[count+i];
++ fYec32_idx_save = count;
++
++ // LOOP 0x1013897e0
++ // pre processing
++ fYec44_idx = (fYec44_idx+fYec44_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec78_tmp[i]=fRec78_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec44[(fYec44_idx+i)&2047] = (fZec7[i] + (0.5f * fRec78[i-1]));
++ fRec78[i] = fYec44[(fYec44_idx+i-579)&2047];
++ fRec79[i] = (0 - (fZec7[i] - fRec78[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec78_perm[i]=fRec78_tmp[count+i];
++ fYec44_idx_save = count;
++
++ // SECTION : 13
++ // LOOP 0x10134a5f0
++ // pre processing
++ fYec33_idx = (fYec33_idx+fYec33_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec4_tmp[i]=fRec4_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec33[(fYec33_idx+i)&2047] = (fRec7[i] + (0.5f * fRec4[i-1]));
++ fRec4[i] = fYec33[(fYec33_idx+i-441)&2047];
++ fRec5[i] = (fRec4[i-1] - fRec7[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec4_perm[i]=fRec4_tmp[count+i];
++ fYec33_idx_save = count;
++
++ // LOOP 0x101389100
++ // pre processing
++ fYec45_idx = (fYec45_idx+fYec45_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec76_tmp[i]=fRec76_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec45[(fYec45_idx+i)&2047] = (fRec79[i] + (0.5f * fRec76[i-1]));
++ fRec76[i] = fYec45[(fYec45_idx+i-464)&2047];
++ fRec77[i] = (fRec76[i-1] - fRec79[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec76_perm[i]=fRec76_tmp[count+i];
++ fYec45_idx_save = count;
++
++ // SECTION : 14
++ // LOOP 0x101349f10
++ // pre processing
++ fYec34_idx = (fYec34_idx+fYec34_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec2_tmp[i]=fRec2_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec34[(fYec34_idx+i)&2047] = (fRec5[i] + (0.5f * fRec2[i-1]));
++ fRec2[i] = fYec34[(fYec34_idx+i-341)&2047];
++ fRec3[i] = (fRec2[i-1] - fRec5[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec2_perm[i]=fRec2_tmp[count+i];
++ fYec34_idx_save = count;
++
++ // LOOP 0x101388a20
++ // pre processing
++ fYec46_idx = (fYec46_idx+fYec46_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec74_tmp[i]=fRec74_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec46[(fYec46_idx+i)&2047] = (fRec77[i] + (0.5f * fRec74[i-1]));
++ fRec74[i] = fYec46[(fYec46_idx+i-364)&2047];
++ fRec75[i] = (fRec74[i-1] - fRec77[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec74_perm[i]=fRec74_tmp[count+i];
++ fYec46_idx_save = count;
++
++ // SECTION : 15
++ // LOOP 0x101349700
++ // pre processing
++ fYec35_idx = (fYec35_idx+fYec35_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec0_tmp[i]=fRec0_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec35[(fYec35_idx+i)&2047] = (fRec3[i] + (0.5f * fRec0[i-1]));
++ fRec0[i] = fYec35[(fYec35_idx+i-225)&2047];
++ fRec1[i] = (fRec0[i-1] - fRec3[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec0_perm[i]=fRec0_tmp[count+i];
++ fYec35_idx_save = count;
++
++ // LOOP 0x1013883a0
++ // pre processing
++ fYec47_idx = (fYec47_idx+fYec47_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec72_tmp[i]=fRec72_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec47[(fYec47_idx+i)&2047] = (fRec75[i] + (0.5f * fRec72[i-1]));
++ fRec72[i] = fYec47[(fYec47_idx+i-248)&2047];
++ fRec73[i] = (fRec72[i-1] - fRec75[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec72_perm[i]=fRec72_tmp[count+i];
++ fYec47_idx_save = count;
++
++ // SECTION : 16
++ // LOOP 0x101349600
++ // exec code
++ for (int i=0; i<count; i++) {
++ output0[i] = (FAUSTFLOAT)((fSlow4 * fZec2[i]) + (fSlow3 * fRec1[i]));
++ }
++
++ // LOOP 0x1013881d0
++ // exec code
++ for (int i=0; i<count; i++) {
++ output1[i] = (FAUSTFLOAT)((fSlow4 * fZec4[i]) + (fSlow3 * fRec73[i]));
++ }
++
++ }
++ if (index < fullcount) {
++ // compute the remaining samples if any
++ int count = fullcount-index;
++ FAUSTFLOAT* input0 = &input[0][index];
++ FAUSTFLOAT* input1 = &input[1][index];
++ FAUSTFLOAT* output0 = &output[0][index];
++ FAUSTFLOAT* output1 = &output[1][index];
++ // SECTION : 1
++ // LOOP 0x101350bc0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec0[i] = (1.500000e-02f * ((float)input0[i] + (float)input1[i]));
++ }
++
++ // SECTION : 2
++ // LOOP 0x10134f970
++ // pre processing
++ for (int i=0; i<4; i++) fRec19_tmp[i]=fRec19_perm[i];
++ fYec0_idx = (fYec0_idx+fYec0_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec18_tmp[i]=fRec18_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec19[i] = ((fSlow1 * fRec18[i-1]) + (fSlow0 * fRec19[i-1]));
++ fYec0[(fYec0_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec19[i]));
++ fRec18[i] = fYec0[(fYec0_idx+i-1617)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec18_perm[i]=fRec18_tmp[count+i];
++ fYec0_idx_save = count;
++ for (int i=0; i<4; i++) fRec19_perm[i]=fRec19_tmp[count+i];
++
++ // LOOP 0x101351ed0
++ // pre processing
++ for (int i=0; i<4; i++) fRec21_tmp[i]=fRec21_perm[i];
++ fYec1_idx = (fYec1_idx+fYec1_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec20_tmp[i]=fRec20_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec21[i] = ((fSlow1 * fRec20[i-1]) + (fSlow0 * fRec21[i-1]));
++ fYec1[(fYec1_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec21[i]));
++ fRec20[i] = fYec1[(fYec1_idx+i-1557)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec20_perm[i]=fRec20_tmp[count+i];
++ fYec1_idx_save = count;
++ for (int i=0; i<4; i++) fRec21_perm[i]=fRec21_tmp[count+i];
++
++ // LOOP 0x101353a50
++ // pre processing
++ for (int i=0; i<4; i++) fRec23_tmp[i]=fRec23_perm[i];
++ fYec2_idx = (fYec2_idx+fYec2_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec22_tmp[i]=fRec22_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec23[i] = ((fSlow1 * fRec22[i-1]) + (fSlow0 * fRec23[i-1]));
++ fYec2[(fYec2_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec23[i]));
++ fRec22[i] = fYec2[(fYec2_idx+i-1491)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec22_perm[i]=fRec22_tmp[count+i];
++ fYec2_idx_save = count;
++ for (int i=0; i<4; i++) fRec23_perm[i]=fRec23_tmp[count+i];
++
++ // LOOP 0x1013555d0
++ // pre processing
++ for (int i=0; i<4; i++) fRec25_tmp[i]=fRec25_perm[i];
++ fYec3_idx = (fYec3_idx+fYec3_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec24_tmp[i]=fRec24_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec25[i] = ((fSlow1 * fRec24[i-1]) + (fSlow0 * fRec25[i-1]));
++ fYec3[(fYec3_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec25[i]));
++ fRec24[i] = fYec3[(fYec3_idx+i-1422)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec24_perm[i]=fRec24_tmp[count+i];
++ fYec3_idx_save = count;
++ for (int i=0; i<4; i++) fRec25_perm[i]=fRec25_tmp[count+i];
++
++ // LOOP 0x101357120
++ // pre processing
++ for (int i=0; i<4; i++) fRec27_tmp[i]=fRec27_perm[i];
++ fYec4_idx = (fYec4_idx+fYec4_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec26_tmp[i]=fRec26_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec27[i] = ((fSlow1 * fRec26[i-1]) + (fSlow0 * fRec27[i-1]));
++ fYec4[(fYec4_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec27[i]));
++ fRec26[i] = fYec4[(fYec4_idx+i-1356)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec26_perm[i]=fRec26_tmp[count+i];
++ fYec4_idx_save = count;
++ for (int i=0; i<4; i++) fRec27_perm[i]=fRec27_tmp[count+i];
++
++ // LOOP 0x101358c70
++ // pre processing
++ for (int i=0; i<4; i++) fRec29_tmp[i]=fRec29_perm[i];
++ fYec5_idx = (fYec5_idx+fYec5_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec28_tmp[i]=fRec28_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec29[i] = ((fSlow1 * fRec28[i-1]) + (fSlow0 * fRec29[i-1]));
++ fYec5[(fYec5_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec29[i]));
++ fRec28[i] = fYec5[(fYec5_idx+i-1277)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec28_perm[i]=fRec28_tmp[count+i];
++ fYec5_idx_save = count;
++ for (int i=0; i<4; i++) fRec29_perm[i]=fRec29_tmp[count+i];
++
++ // LOOP 0x10135a7e0
++ // pre processing
++ for (int i=0; i<4; i++) fRec31_tmp[i]=fRec31_perm[i];
++ fYec6_idx = (fYec6_idx+fYec6_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec30_tmp[i]=fRec30_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec31[i] = ((fSlow1 * fRec30[i-1]) + (fSlow0 * fRec31[i-1]));
++ fYec6[(fYec6_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec31[i]));
++ fRec30[i] = fYec6[(fYec6_idx+i-1188)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec30_perm[i]=fRec30_tmp[count+i];
++ fYec6_idx_save = count;
++ for (int i=0; i<4; i++) fRec31_perm[i]=fRec31_tmp[count+i];
++
++ // LOOP 0x10135c330
++ // pre processing
++ for (int i=0; i<4; i++) fRec33_tmp[i]=fRec33_perm[i];
++ fYec7_idx = (fYec7_idx+fYec7_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec32_tmp[i]=fRec32_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec33[i] = ((fSlow1 * fRec32[i-1]) + (fSlow0 * fRec33[i-1]));
++ fYec7[(fYec7_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec33[i]));
++ fRec32[i] = fYec7[(fYec7_idx+i-1116)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec32_perm[i]=fRec32_tmp[count+i];
++ fYec7_idx_save = count;
++ for (int i=0; i<4; i++) fRec33_perm[i]=fRec33_tmp[count+i];
++
++ // LOOP 0x101364b70
++ // pre processing
++ for (int i=0; i<4; i++) fRec43_tmp[i]=fRec43_perm[i];
++ fYec12_idx = (fYec12_idx+fYec12_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec42_tmp[i]=fRec42_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec43[i] = ((fSlow1 * fRec42[i-1]) + (fSlow0 * fRec43[i-1]));
++ fYec12[(fYec12_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec43[i]));
++ fRec42[i] = fYec12[(fYec12_idx+i-1640)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec42_perm[i]=fRec42_tmp[count+i];
++ fYec12_idx_save = count;
++ for (int i=0; i<4; i++) fRec43_perm[i]=fRec43_tmp[count+i];
++
++ // LOOP 0x1013667b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec45_tmp[i]=fRec45_perm[i];
++ fYec13_idx = (fYec13_idx+fYec13_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec44_tmp[i]=fRec44_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec45[i] = ((fSlow1 * fRec44[i-1]) + (fSlow0 * fRec45[i-1]));
++ fYec13[(fYec13_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec45[i]));
++ fRec44[i] = fYec13[(fYec13_idx+i-1580)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec44_perm[i]=fRec44_tmp[count+i];
++ fYec13_idx_save = count;
++ for (int i=0; i<4; i++) fRec45_perm[i]=fRec45_tmp[count+i];
++
++ // LOOP 0x101368330
++ // pre processing
++ for (int i=0; i<4; i++) fRec47_tmp[i]=fRec47_perm[i];
++ fYec14_idx = (fYec14_idx+fYec14_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec46_tmp[i]=fRec46_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec47[i] = ((fSlow1 * fRec46[i-1]) + (fSlow0 * fRec47[i-1]));
++ fYec14[(fYec14_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec47[i]));
++ fRec46[i] = fYec14[(fYec14_idx+i-1514)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec46_perm[i]=fRec46_tmp[count+i];
++ fYec14_idx_save = count;
++ for (int i=0; i<4; i++) fRec47_perm[i]=fRec47_tmp[count+i];
++
++ // LOOP 0x101369f40
++ // pre processing
++ for (int i=0; i<4; i++) fRec49_tmp[i]=fRec49_perm[i];
++ fYec15_idx = (fYec15_idx+fYec15_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec48_tmp[i]=fRec48_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec49[i] = ((fSlow1 * fRec48[i-1]) + (fSlow0 * fRec49[i-1]));
++ fYec15[(fYec15_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec49[i]));
++ fRec48[i] = fYec15[(fYec15_idx+i-1445)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec48_perm[i]=fRec48_tmp[count+i];
++ fYec15_idx_save = count;
++ for (int i=0; i<4; i++) fRec49_perm[i]=fRec49_tmp[count+i];
++
++ // LOOP 0x10136bae0
++ // pre processing
++ for (int i=0; i<4; i++) fRec51_tmp[i]=fRec51_perm[i];
++ fYec16_idx = (fYec16_idx+fYec16_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec50_tmp[i]=fRec50_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec51[i] = ((fSlow1 * fRec50[i-1]) + (fSlow0 * fRec51[i-1]));
++ fYec16[(fYec16_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec51[i]));
++ fRec50[i] = fYec16[(fYec16_idx+i-1379)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec50_perm[i]=fRec50_tmp[count+i];
++ fYec16_idx_save = count;
++ for (int i=0; i<4; i++) fRec51_perm[i]=fRec51_tmp[count+i];
++
++ // LOOP 0x10136d660
++ // pre processing
++ for (int i=0; i<4; i++) fRec53_tmp[i]=fRec53_perm[i];
++ fYec17_idx = (fYec17_idx+fYec17_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec52_tmp[i]=fRec52_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec53[i] = ((fSlow1 * fRec52[i-1]) + (fSlow0 * fRec53[i-1]));
++ fYec17[(fYec17_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec53[i]));
++ fRec52[i] = fYec17[(fYec17_idx+i-1300)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec52_perm[i]=fRec52_tmp[count+i];
++ fYec17_idx_save = count;
++ for (int i=0; i<4; i++) fRec53_perm[i]=fRec53_tmp[count+i];
++
++ // LOOP 0x10136f1e0
++ // pre processing
++ for (int i=0; i<4; i++) fRec55_tmp[i]=fRec55_perm[i];
++ fYec18_idx = (fYec18_idx+fYec18_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec54_tmp[i]=fRec54_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec55[i] = ((fSlow1 * fRec54[i-1]) + (fSlow0 * fRec55[i-1]));
++ fYec18[(fYec18_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec55[i]));
++ fRec54[i] = fYec18[(fYec18_idx+i-1211)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec54_perm[i]=fRec54_tmp[count+i];
++ fYec18_idx_save = count;
++ for (int i=0; i<4; i++) fRec55_perm[i]=fRec55_tmp[count+i];
++
++ // LOOP 0x101370d60
++ // pre processing
++ for (int i=0; i<4; i++) fRec57_tmp[i]=fRec57_perm[i];
++ fYec19_idx = (fYec19_idx+fYec19_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec56_tmp[i]=fRec56_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec57[i] = ((fSlow1 * fRec56[i-1]) + (fSlow0 * fRec57[i-1]));
++ fYec19[(fYec19_idx+i)&4095] = (fZec0[i] + (fSlow2 * fRec57[i]));
++ fRec56[i] = fYec19[(fYec19_idx+i-1139)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec56_perm[i]=fRec56_tmp[count+i];
++ fYec19_idx_save = count;
++ for (int i=0; i<4; i++) fRec57_perm[i]=fRec57_tmp[count+i];
++
++ // SECTION : 3
++ // LOOP 0x10134f870
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec1[i] = (((((((fRec32[i] + fRec30[i]) + fRec28[i]) + fRec26[i]) + fRec24[i]) + fRec22[i]) + fRec20[i]) + fRec18[i]);
++ }
++
++ // LOOP 0x101364a70
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec3[i] = (((((((fRec56[i] + fRec54[i]) + fRec52[i]) + fRec50[i]) + fRec48[i]) + fRec46[i]) + fRec44[i]) + fRec42[i]);
++ }
++
++ // SECTION : 4
++ // LOOP 0x10134f120
++ // pre processing
++ fYec8_idx = (fYec8_idx+fYec8_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec16_tmp[i]=fRec16_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec8[(fYec8_idx+i)&2047] = (fZec1[i] + (0.5f * fRec16[i-1]));
++ fRec16[i] = fYec8[(fYec8_idx+i-556)&2047];
++ fRec17[i] = (0 - (fZec1[i] - fRec16[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec16_perm[i]=fRec16_tmp[count+i];
++ fYec8_idx_save = count;
++
++ // LOOP 0x101364320
++ // pre processing
++ fYec20_idx = (fYec20_idx+fYec20_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec40_tmp[i]=fRec40_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec20[(fYec20_idx+i)&2047] = (fZec3[i] + (0.5f * fRec40[i-1]));
++ fRec40[i] = fYec20[(fYec20_idx+i-579)&2047];
++ fRec41[i] = (0 - (fZec3[i] - fRec40[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec40_perm[i]=fRec40_tmp[count+i];
++ fYec20_idx_save = count;
++
++ // SECTION : 5
++ // LOOP 0x10134e9d0
++ // pre processing
++ fYec9_idx = (fYec9_idx+fYec9_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec14_tmp[i]=fRec14_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec9[(fYec9_idx+i)&2047] = (fRec17[i] + (0.5f * fRec14[i-1]));
++ fRec14[i] = fYec9[(fYec9_idx+i-441)&2047];
++ fRec15[i] = (fRec14[i-1] - fRec17[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec14_perm[i]=fRec14_tmp[count+i];
++ fYec9_idx_save = count;
++
++ // LOOP 0x101363bd0
++ // pre processing
++ fYec21_idx = (fYec21_idx+fYec21_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec38_tmp[i]=fRec38_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec21[(fYec21_idx+i)&2047] = (fRec41[i] + (0.5f * fRec38[i-1]));
++ fRec38[i] = fYec21[(fYec21_idx+i-464)&2047];
++ fRec39[i] = (fRec38[i-1] - fRec41[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec38_perm[i]=fRec38_tmp[count+i];
++ fYec21_idx_save = count;
++
++ // SECTION : 6
++ // LOOP 0x10134e2a0
++ // pre processing
++ fYec10_idx = (fYec10_idx+fYec10_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec12_tmp[i]=fRec12_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec10[(fYec10_idx+i)&2047] = (fRec15[i] + (0.5f * fRec12[i-1]));
++ fRec12[i] = fYec10[(fYec10_idx+i-341)&2047];
++ fRec13[i] = (fRec12[i-1] - fRec15[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec12_perm[i]=fRec12_tmp[count+i];
++ fYec10_idx_save = count;
++
++ // LOOP 0x1013634a0
++ // pre processing
++ fYec22_idx = (fYec22_idx+fYec22_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec36_tmp[i]=fRec36_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec22[(fYec22_idx+i)&2047] = (fRec39[i] + (0.5f * fRec36[i-1]));
++ fRec36[i] = fYec22[(fYec22_idx+i-364)&2047];
++ fRec37[i] = (fRec36[i-1] - fRec39[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec36_perm[i]=fRec36_tmp[count+i];
++ fYec22_idx_save = count;
++
++ // SECTION : 7
++ // LOOP 0x10134dba0
++ // pre processing
++ fYec11_idx = (fYec11_idx+fYec11_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec10_tmp[i]=fRec10_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec11[(fYec11_idx+i)&2047] = (fRec13[i] + (0.5f * fRec10[i-1]));
++ fRec10[i] = fYec11[(fYec11_idx+i-225)&2047];
++ fRec11[i] = (fRec10[i-1] - fRec13[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec10_perm[i]=fRec10_tmp[count+i];
++ fYec11_idx_save = count;
++
++ // LOOP 0x101362e30
++ // pre processing
++ fYec23_idx = (fYec23_idx+fYec23_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec34_tmp[i]=fRec34_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec23[(fYec23_idx+i)&2047] = (fRec37[i] + (0.5f * fRec34[i-1]));
++ fRec34[i] = fYec23[(fYec23_idx+i-248)&2047];
++ fRec35[i] = (fRec34[i-1] - fRec37[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec34_perm[i]=fRec34_tmp[count+i];
++ fYec23_idx_save = count;
++
++ // SECTION : 8
++ // LOOP 0x10134daa0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec2[i] = ((fSlow4 * (float)input0[i]) + (fSlow3 * fRec11[i]));
++ }
++
++ // LOOP 0x101362d30
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec4[i] = ((fSlow4 * (float)input1[i]) + (fSlow3 * fRec35[i]));
++ }
++
++ // SECTION : 9
++ // LOOP 0x10134d9a0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec5[i] = (1.500000e-02f * (fZec4[i] + fZec2[i]));
++ }
++
++ // SECTION : 10
++ // LOOP 0x10134b4b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec9_tmp[i]=fRec9_perm[i];
++ fYec24_idx = (fYec24_idx+fYec24_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec8_tmp[i]=fRec8_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec9[i] = ((fSlow1 * fRec8[i-1]) + (fSlow0 * fRec9[i-1]));
++ fYec24[(fYec24_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec9[i]));
++ fRec8[i] = fYec24[(fYec24_idx+i-1617)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec8_perm[i]=fRec8_tmp[count+i];
++ fYec24_idx_save = count;
++ for (int i=0; i<4; i++) fRec9_perm[i]=fRec9_tmp[count+i];
++
++ // LOOP 0x101377dc0
++ // pre processing
++ for (int i=0; i<4; i++) fRec59_tmp[i]=fRec59_perm[i];
++ fYec25_idx = (fYec25_idx+fYec25_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec58_tmp[i]=fRec58_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec59[i] = ((fSlow1 * fRec58[i-1]) + (fSlow0 * fRec59[i-1]));
++ fYec25[(fYec25_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec59[i]));
++ fRec58[i] = fYec25[(fYec25_idx+i-1557)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec58_perm[i]=fRec58_tmp[count+i];
++ fYec25_idx_save = count;
++ for (int i=0; i<4; i++) fRec59_perm[i]=fRec59_tmp[count+i];
++
++ // LOOP 0x101379900
++ // pre processing
++ for (int i=0; i<4; i++) fRec61_tmp[i]=fRec61_perm[i];
++ fYec26_idx = (fYec26_idx+fYec26_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec60_tmp[i]=fRec60_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec61[i] = ((fSlow1 * fRec60[i-1]) + (fSlow0 * fRec61[i-1]));
++ fYec26[(fYec26_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec61[i]));
++ fRec60[i] = fYec26[(fYec26_idx+i-1491)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec60_perm[i]=fRec60_tmp[count+i];
++ fYec26_idx_save = count;
++ for (int i=0; i<4; i++) fRec61_perm[i]=fRec61_tmp[count+i];
++
++ // LOOP 0x10137b480
++ // pre processing
++ for (int i=0; i<4; i++) fRec63_tmp[i]=fRec63_perm[i];
++ fYec27_idx = (fYec27_idx+fYec27_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec62_tmp[i]=fRec62_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec63[i] = ((fSlow1 * fRec62[i-1]) + (fSlow0 * fRec63[i-1]));
++ fYec27[(fYec27_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec63[i]));
++ fRec62[i] = fYec27[(fYec27_idx+i-1422)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec62_perm[i]=fRec62_tmp[count+i];
++ fYec27_idx_save = count;
++ for (int i=0; i<4; i++) fRec63_perm[i]=fRec63_tmp[count+i];
++
++ // LOOP 0x10137d000
++ // pre processing
++ for (int i=0; i<4; i++) fRec65_tmp[i]=fRec65_perm[i];
++ fYec28_idx = (fYec28_idx+fYec28_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec64_tmp[i]=fRec64_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec65[i] = ((fSlow1 * fRec64[i-1]) + (fSlow0 * fRec65[i-1]));
++ fYec28[(fYec28_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec65[i]));
++ fRec64[i] = fYec28[(fYec28_idx+i-1356)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec64_perm[i]=fRec64_tmp[count+i];
++ fYec28_idx_save = count;
++ for (int i=0; i<4; i++) fRec65_perm[i]=fRec65_tmp[count+i];
++
++ // LOOP 0x10137eb80
++ // pre processing
++ for (int i=0; i<4; i++) fRec67_tmp[i]=fRec67_perm[i];
++ fYec29_idx = (fYec29_idx+fYec29_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec66_tmp[i]=fRec66_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec67[i] = ((fSlow1 * fRec66[i-1]) + (fSlow0 * fRec67[i-1]));
++ fYec29[(fYec29_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec67[i]));
++ fRec66[i] = fYec29[(fYec29_idx+i-1277)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec66_perm[i]=fRec66_tmp[count+i];
++ fYec29_idx_save = count;
++ for (int i=0; i<4; i++) fRec67_perm[i]=fRec67_tmp[count+i];
++
++ // LOOP 0x101380700
++ // pre processing
++ for (int i=0; i<4; i++) fRec69_tmp[i]=fRec69_perm[i];
++ fYec30_idx = (fYec30_idx+fYec30_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec68_tmp[i]=fRec68_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec69[i] = ((fSlow1 * fRec68[i-1]) + (fSlow0 * fRec69[i-1]));
++ fYec30[(fYec30_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec69[i]));
++ fRec68[i] = fYec30[(fYec30_idx+i-1188)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec68_perm[i]=fRec68_tmp[count+i];
++ fYec30_idx_save = count;
++ for (int i=0; i<4; i++) fRec69_perm[i]=fRec69_tmp[count+i];
++
++ // LOOP 0x101382280
++ // pre processing
++ for (int i=0; i<4; i++) fRec71_tmp[i]=fRec71_perm[i];
++ fYec31_idx = (fYec31_idx+fYec31_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec70_tmp[i]=fRec70_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec71[i] = ((fSlow1 * fRec70[i-1]) + (fSlow0 * fRec71[i-1]));
++ fYec31[(fYec31_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec71[i]));
++ fRec70[i] = fYec31[(fYec31_idx+i-1116)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec70_perm[i]=fRec70_tmp[count+i];
++ fYec31_idx_save = count;
++ for (int i=0; i<4; i++) fRec71_perm[i]=fRec71_tmp[count+i];
++
++ // LOOP 0x101389fc0
++ // pre processing
++ for (int i=0; i<4; i++) fRec81_tmp[i]=fRec81_perm[i];
++ fYec36_idx = (fYec36_idx+fYec36_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec80_tmp[i]=fRec80_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec81[i] = ((fSlow1 * fRec80[i-1]) + (fSlow0 * fRec81[i-1]));
++ fYec36[(fYec36_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec81[i]));
++ fRec80[i] = fYec36[(fYec36_idx+i-1640)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec80_perm[i]=fRec80_tmp[count+i];
++ fYec36_idx_save = count;
++ for (int i=0; i<4; i++) fRec81_perm[i]=fRec81_tmp[count+i];
++
++ // LOOP 0x10138bc10
++ // pre processing
++ for (int i=0; i<4; i++) fRec83_tmp[i]=fRec83_perm[i];
++ fYec37_idx = (fYec37_idx+fYec37_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec82_tmp[i]=fRec82_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec83[i] = ((fSlow1 * fRec82[i-1]) + (fSlow0 * fRec83[i-1]));
++ fYec37[(fYec37_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec83[i]));
++ fRec82[i] = fYec37[(fYec37_idx+i-1580)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec82_perm[i]=fRec82_tmp[count+i];
++ fYec37_idx_save = count;
++ for (int i=0; i<4; i++) fRec83_perm[i]=fRec83_tmp[count+i];
++
++ // LOOP 0x10138d7b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec85_tmp[i]=fRec85_perm[i];
++ fYec38_idx = (fYec38_idx+fYec38_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec84_tmp[i]=fRec84_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec85[i] = ((fSlow1 * fRec84[i-1]) + (fSlow0 * fRec85[i-1]));
++ fYec38[(fYec38_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec85[i]));
++ fRec84[i] = fYec38[(fYec38_idx+i-1514)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec84_perm[i]=fRec84_tmp[count+i];
++ fYec38_idx_save = count;
++ for (int i=0; i<4; i++) fRec85_perm[i]=fRec85_tmp[count+i];
++
++ // LOOP 0x10138f330
++ // pre processing
++ for (int i=0; i<4; i++) fRec87_tmp[i]=fRec87_perm[i];
++ fYec39_idx = (fYec39_idx+fYec39_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec86_tmp[i]=fRec86_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec87[i] = ((fSlow1 * fRec86[i-1]) + (fSlow0 * fRec87[i-1]));
++ fYec39[(fYec39_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec87[i]));
++ fRec86[i] = fYec39[(fYec39_idx+i-1445)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec86_perm[i]=fRec86_tmp[count+i];
++ fYec39_idx_save = count;
++ for (int i=0; i<4; i++) fRec87_perm[i]=fRec87_tmp[count+i];
++
++ // LOOP 0x101390eb0
++ // pre processing
++ for (int i=0; i<4; i++) fRec89_tmp[i]=fRec89_perm[i];
++ fYec40_idx = (fYec40_idx+fYec40_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec88_tmp[i]=fRec88_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec89[i] = ((fSlow1 * fRec88[i-1]) + (fSlow0 * fRec89[i-1]));
++ fYec40[(fYec40_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec89[i]));
++ fRec88[i] = fYec40[(fYec40_idx+i-1379)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec88_perm[i]=fRec88_tmp[count+i];
++ fYec40_idx_save = count;
++ for (int i=0; i<4; i++) fRec89_perm[i]=fRec89_tmp[count+i];
++
++ // LOOP 0x101392a30
++ // pre processing
++ for (int i=0; i<4; i++) fRec91_tmp[i]=fRec91_perm[i];
++ fYec41_idx = (fYec41_idx+fYec41_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec90_tmp[i]=fRec90_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec91[i] = ((fSlow1 * fRec90[i-1]) + (fSlow0 * fRec91[i-1]));
++ fYec41[(fYec41_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec91[i]));
++ fRec90[i] = fYec41[(fYec41_idx+i-1300)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec90_perm[i]=fRec90_tmp[count+i];
++ fYec41_idx_save = count;
++ for (int i=0; i<4; i++) fRec91_perm[i]=fRec91_tmp[count+i];
++
++ // LOOP 0x1013945b0
++ // pre processing
++ for (int i=0; i<4; i++) fRec93_tmp[i]=fRec93_perm[i];
++ fYec42_idx = (fYec42_idx+fYec42_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec92_tmp[i]=fRec92_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec93[i] = ((fSlow1 * fRec92[i-1]) + (fSlow0 * fRec93[i-1]));
++ fYec42[(fYec42_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec93[i]));
++ fRec92[i] = fYec42[(fYec42_idx+i-1211)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec92_perm[i]=fRec92_tmp[count+i];
++ fYec42_idx_save = count;
++ for (int i=0; i<4; i++) fRec93_perm[i]=fRec93_tmp[count+i];
++
++ // LOOP 0x101396130
++ // pre processing
++ for (int i=0; i<4; i++) fRec95_tmp[i]=fRec95_perm[i];
++ fYec43_idx = (fYec43_idx+fYec43_idx_save)&4095;
++ for (int i=0; i<4; i++) fRec94_tmp[i]=fRec94_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fRec95[i] = ((fSlow1 * fRec94[i-1]) + (fSlow0 * fRec95[i-1]));
++ fYec43[(fYec43_idx+i)&4095] = (fZec5[i] + (fSlow2 * fRec95[i]));
++ fRec94[i] = fYec43[(fYec43_idx+i-1139)&4095];
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec94_perm[i]=fRec94_tmp[count+i];
++ fYec43_idx_save = count;
++ for (int i=0; i<4; i++) fRec95_perm[i]=fRec95_tmp[count+i];
++
++ // SECTION : 11
++ // LOOP 0x10134b3b0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec6[i] = (((((((fRec70[i] + fRec68[i]) + fRec66[i]) + fRec64[i]) + fRec62[i]) + fRec60[i]) + fRec58[i]) + fRec8[i]);
++ }
++
++ // LOOP 0x101389ec0
++ // exec code
++ for (int i=0; i<count; i++) {
++ fZec7[i] = (((((((fRec94[i] + fRec92[i]) + fRec90[i]) + fRec88[i]) + fRec86[i]) + fRec84[i]) + fRec82[i]) + fRec80[i]);
++ }
++
++ // SECTION : 12
++ // LOOP 0x10134acd0
++ // pre processing
++ fYec32_idx = (fYec32_idx+fYec32_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec6_tmp[i]=fRec6_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec32[(fYec32_idx+i)&2047] = (fZec6[i] + (0.5f * fRec6[i-1]));
++ fRec6[i] = fYec32[(fYec32_idx+i-556)&2047];
++ fRec7[i] = (0 - (fZec6[i] - fRec6[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec6_perm[i]=fRec6_tmp[count+i];
++ fYec32_idx_save = count;
++
++ // LOOP 0x1013897e0
++ // pre processing
++ fYec44_idx = (fYec44_idx+fYec44_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec78_tmp[i]=fRec78_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec44[(fYec44_idx+i)&2047] = (fZec7[i] + (0.5f * fRec78[i-1]));
++ fRec78[i] = fYec44[(fYec44_idx+i-579)&2047];
++ fRec79[i] = (0 - (fZec7[i] - fRec78[i-1]));
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec78_perm[i]=fRec78_tmp[count+i];
++ fYec44_idx_save = count;
++
++ // SECTION : 13
++ // LOOP 0x10134a5f0
++ // pre processing
++ fYec33_idx = (fYec33_idx+fYec33_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec4_tmp[i]=fRec4_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec33[(fYec33_idx+i)&2047] = (fRec7[i] + (0.5f * fRec4[i-1]));
++ fRec4[i] = fYec33[(fYec33_idx+i-441)&2047];
++ fRec5[i] = (fRec4[i-1] - fRec7[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec4_perm[i]=fRec4_tmp[count+i];
++ fYec33_idx_save = count;
++
++ // LOOP 0x101389100
++ // pre processing
++ fYec45_idx = (fYec45_idx+fYec45_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec76_tmp[i]=fRec76_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec45[(fYec45_idx+i)&2047] = (fRec79[i] + (0.5f * fRec76[i-1]));
++ fRec76[i] = fYec45[(fYec45_idx+i-464)&2047];
++ fRec77[i] = (fRec76[i-1] - fRec79[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec76_perm[i]=fRec76_tmp[count+i];
++ fYec45_idx_save = count;
++
++ // SECTION : 14
++ // LOOP 0x101349f10
++ // pre processing
++ fYec34_idx = (fYec34_idx+fYec34_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec2_tmp[i]=fRec2_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec34[(fYec34_idx+i)&2047] = (fRec5[i] + (0.5f * fRec2[i-1]));
++ fRec2[i] = fYec34[(fYec34_idx+i-341)&2047];
++ fRec3[i] = (fRec2[i-1] - fRec5[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec2_perm[i]=fRec2_tmp[count+i];
++ fYec34_idx_save = count;
++
++ // LOOP 0x101388a20
++ // pre processing
++ fYec46_idx = (fYec46_idx+fYec46_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec74_tmp[i]=fRec74_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec46[(fYec46_idx+i)&2047] = (fRec77[i] + (0.5f * fRec74[i-1]));
++ fRec74[i] = fYec46[(fYec46_idx+i-364)&2047];
++ fRec75[i] = (fRec74[i-1] - fRec77[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec74_perm[i]=fRec74_tmp[count+i];
++ fYec46_idx_save = count;
++
++ // SECTION : 15
++ // LOOP 0x101349700
++ // pre processing
++ fYec35_idx = (fYec35_idx+fYec35_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec0_tmp[i]=fRec0_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec35[(fYec35_idx+i)&2047] = (fRec3[i] + (0.5f * fRec0[i-1]));
++ fRec0[i] = fYec35[(fYec35_idx+i-225)&2047];
++ fRec1[i] = (fRec0[i-1] - fRec3[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec0_perm[i]=fRec0_tmp[count+i];
++ fYec35_idx_save = count;
++
++ // LOOP 0x1013883a0
++ // pre processing
++ fYec47_idx = (fYec47_idx+fYec47_idx_save)&2047;
++ for (int i=0; i<4; i++) fRec72_tmp[i]=fRec72_perm[i];
++ // exec code
++ for (int i=0; i<count; i++) {
++ fYec47[(fYec47_idx+i)&2047] = (fRec75[i] + (0.5f * fRec72[i-1]));
++ fRec72[i] = fYec47[(fYec47_idx+i-248)&2047];
++ fRec73[i] = (fRec72[i-1] - fRec75[i]);
++ }
++ // post processing
++ for (int i=0; i<4; i++) fRec72_perm[i]=fRec72_tmp[count+i];
++ fYec47_idx_save = count;
++
++ // SECTION : 16
++ // LOOP 0x101349600
++ // exec code
++ for (int i=0; i<count; i++) {
++ output0[i] = (FAUSTFLOAT)((fSlow4 * fZec2[i]) + (fSlow3 * fRec1[i]));
++ }
++
++ // LOOP 0x1013881d0
++ // exec code
++ for (int i=0; i<count; i++) {
++ output1[i] = (FAUSTFLOAT)((fSlow4 * fZec4[i]) + (fSlow3 * fRec73[i]));
++ }
++
++ }
++ }
++};
++
++
++
++mydsp DSP;
++
++/******************************************************************************
++*******************************************************************************
++
++ COREAUDIO INTERFACE
++
++*******************************************************************************
++*******************************************************************************/
++
++#define MAX_CHANNELS 256
++#define OPEN_ERR -1
++#define NO_ERR 0
++
++class TiPhoneCoreAudioRenderer
++{
++
++ private:
++
++ AudioUnit fAUHAL;
++
++ int fDevNumInChans;
++ int fDevNumOutChans;
++
++ float* fInChannel[MAX_CHANNELS];
++ float* fOutChannel[MAX_CHANNELS];
++
++ static OSStatus Render(void *inRefCon,
++ AudioUnitRenderActionFlags *ioActionFlags,
++ const AudioTimeStamp *inTimeStamp,
++ UInt32 inBusNumber,
++ UInt32 inNumberFrames,
++ AudioBufferList *ioData);
++
++ static void InterruptionListener(void *inClientData, UInt32 inInterruption);
++
++ public:
++
++ TiPhoneCoreAudioRenderer(int input, int output)
++ :fDevNumInChans(input), fDevNumOutChans(output)
++ {
++ for (int i = 0; i < fDevNumInChans; i++) {
++ fInChannel[i] = new float[8192];
++ }
++
++ for (int i = 0; i < fDevNumOutChans; i++) {
++ fOutChannel[i] = new float[8192];
++ }
++ }
++ virtual ~TiPhoneCoreAudioRenderer()
++ {
++ for (int i = 0; i < fDevNumInChans; i++) {
++ delete[] fInChannel[i];
++ }
++
++ for (int i = 0; i < fDevNumOutChans; i++) {
++ delete[] fOutChannel[i];
++ }
++ }
++
++ long Open(long bufferSize, long sampleRate);
++ long Close();
++
++ long Start();
++ long Stop();
++
++};
++
++typedef TiPhoneCoreAudioRenderer * TiPhoneCoreAudioRendererPtr;
++
++static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
++{
++ printf("- - - - - - - - - - - - - - - - - - - -\n");
++ printf(" Sample Rate:%f\n", inDesc->mSampleRate);
++ printf(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
++ printf(" Format Flags:%lX\n", inDesc->mFormatFlags);
++ printf(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
++ printf(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
++ printf(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
++ printf(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
++ printf(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
++ printf("- - - - - - - - - - - - - - - - - - - -\n");
++}
++
++static void printError(OSStatus err)
++{
++ switch (err) {
++ case kAudioConverterErr_FormatNotSupported:
++ printf("error code : kAudioConverterErr_FormatNotSupported\n");
++ break;
++ case kAudioConverterErr_OperationNotSupported:
++ printf("error code : kAudioConverterErr_OperationNotSupported\n");
++ break;
++ case kAudioConverterErr_PropertyNotSupported:
++ printf("error code : kAudioConverterErr_PropertyNotSupported\n");
++ break;
++ case kAudioConverterErr_InvalidInputSize:
++ printf("error code : kAudioConverterErr_InvalidInputSize\n");
++ break;
++ case kAudioConverterErr_InvalidOutputSize:
++ printf("error code : kAudioConverterErr_InvalidOutputSize\n");
++ break;
++ case kAudioConverterErr_UnspecifiedError:
++ printf("error code : kAudioConverterErr_UnspecifiedError\n");
++ break;
++ case kAudioConverterErr_BadPropertySizeError:
++ printf("error code : kAudioConverterErr_BadPropertySizeError\n");
++ break;
++ case kAudioConverterErr_RequiresPacketDescriptionsError:
++ printf("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
++ break;
++ case kAudioConverterErr_InputSampleRateOutOfRange:
++ printf("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
++ break;
++ case kAudioConverterErr_OutputSampleRateOutOfRange:
++ printf("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
++ break;
++ default:
++ printf("error code : unknown\n");
++ break;
++ }
++}
++
++st::HardwareClock my_clock;
++
++OSStatus TiPhoneCoreAudioRenderer::Render(void *inRefCon,
++ AudioUnitRenderActionFlags *ioActionFlags,
++ const AudioTimeStamp *inTimeStamp,
++ UInt32,
++ UInt32 inNumberFrames,
++ AudioBufferList *ioData)
++{
++ TiPhoneCoreAudioRendererPtr renderer = (TiPhoneCoreAudioRendererPtr)inRefCon;
++ my_clock.Update();
++ //printf("TiPhoneCoreAudioRenderer::Render 0 %d\n", inNumberFrames);
++
++ AudioUnitRender(renderer->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);
++
++ float coef = 1.f/32768.f;
++ /*
++ for (int chan = 0; chan < fDevNumInChans; chan++) {
++ for (int frame = 0; frame < inNumberFrames; frame++) {
++ fInChannel[chan][frame] = float(((long*)ioData->mBuffers[chan].mData)[frame]) / 32768.f;
++ fInChannel[chan][frame] = float(((long*)ioData->mBuffers[chan].mData)[frame]) / 32768.f;
++ }
++ }
++ */
++
++ for (int frame = 0; frame < inNumberFrames; frame++) {
++ float sample = float(((long*)ioData->mBuffers[0].mData)[frame]) * coef;
++ renderer->fInChannel[0][frame] = sample;
++ renderer->fInChannel[1][frame] = sample;
++ }
++
++ //printf("TiPhoneCoreAudioRenderer::Render 1 %d\n", inNumberFrames);
++
++ DSP.compute((int)inNumberFrames, renderer->fInChannel, renderer->fOutChannel);
++
++ for (int chan = 0; chan < renderer->fDevNumOutChans; chan++) {
++ for (int frame = 0; frame < inNumberFrames; frame++) {
++ ((long*)ioData->mBuffers[chan].mData)[frame] = long(renderer->fOutChannel[chan][frame] * 32768.f);
++ }
++ }
++
++ my_clock.Update();
++ const float dt = my_clock.GetDeltaTime();
++ printf("Normal: %f s\n", dt);
++
++ //printf("TiPhoneCoreAudioRenderer::Render 3 %d\n", inNumberFrames);
++ return 0;
++}
++
++void TiPhoneCoreAudioRenderer::InterruptionListener(void *inClientData, UInt32 inInterruption)
++{
++ printf("Session interrupted! --- %s ---", inInterruption == kAudioSessionBeginInterruption ? "Begin Interruption" : "End Interruption");
++
++ TiPhoneCoreAudioRenderer *obj = (TiPhoneCoreAudioRenderer*)inClientData;
++
++ if (inInterruption == kAudioSessionEndInterruption) {
++ // make sure we are again the active session
++ AudioSessionSetActive(true);
++ AudioOutputUnitStart(obj->fAUHAL);
++ }
++
++ if (inInterruption == kAudioSessionBeginInterruption) {
++ AudioOutputUnitStop(obj->fAUHAL);
++ }
++}
++
++long TiPhoneCoreAudioRenderer::Open(long bufferSize, long samplerate)
++{
++ OSStatus err1;
++ UInt32 outSize;
++ UInt32 enableIO;
++ Boolean isWritable;
++ AudioStreamBasicDescription srcFormat, dstFormat;
++
++ printf("Open fDevNumInChans = %ld fDevNumOutChans = %ld bufferSize = %ld samplerate = %ld\n", fDevNumInChans, fDevNumOutChans, bufferSize, samplerate);
++
++ // Initialize and configure the audio session
++ err1 = AudioSessionInitialize(NULL, NULL, InterruptionListener, this);
++ if (err1 != noErr) {
++ printf("Couldn't initialize audio session\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ err1 = AudioSessionSetActive(true);
++ if (err1 != noErr) {
++ printf("Couldn't set audio session active\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ UInt32 audioCategory = kAudioSessionCategory_PlayAndRecord;
++ err1 = AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(audioCategory), &audioCategory);
++ if (err1 != noErr) {
++ printf("Couldn't set audio category\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ //err1 = AudioSessionAddPropertyListener(kAudioSessionProperty_AudioRouteChange, propListener, self), "couldn't set property listener");
++
++ Float64 hwSampleRate;
++ outSize = sizeof(hwSampleRate);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareSampleRate, &outSize, &hwSampleRate);
++ if (err1 != noErr) {
++ printf("Couldn't get hw sample rate\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw sample rate %f\n", hwSampleRate);
++ }
++
++ Float32 hwBufferSize;
++ outSize = sizeof(hwBufferSize);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareIOBufferDuration, &outSize, &hwBufferSize);
++ if (err1 != noErr) {
++ printf("Couldn't get hw buffer duration\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw buffer duration %f\n", hwBufferSize);
++ }
++
++ UInt32 hwInput;
++ outSize = sizeof(hwInput);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareInputNumberChannels, &outSize, &hwInput);
++ if (err1 != noErr) {
++ printf("Couldn't get hw input channels\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw input channels %d\n", hwInput);
++ }
++
++ UInt32 hwOutput;
++ outSize = sizeof(hwOutput);
++ err1 = AudioSessionGetProperty(kAudioSessionProperty_CurrentHardwareOutputNumberChannels, &outSize, &hwOutput);
++ if (err1 != noErr) {
++ printf("Couldn't get hw output channels\n");
++ printError(err1);
++ return OPEN_ERR;
++ } else {
++ printf("Get hw output channels %d\n", hwOutput);
++ }
++
++ Float32 preferredBufferSize = float(bufferSize) / float(samplerate);
++ printf("preferredBufferSize %f \n", preferredBufferSize);
++
++ err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof(preferredBufferSize), &preferredBufferSize);
++ if (err1 != noErr) {
++ printf("Couldn't set i/o buffer duration\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ Float64 preferredSamplerate = float(samplerate);
++ err1 = AudioSessionSetProperty(kAudioSessionProperty_PreferredHardwareSampleRate, sizeof(preferredSamplerate), &preferredSamplerate);
++ if (err1 != noErr) {
++ printf("Couldn't set i/o sample rate\n");
++ printError(err1);
++ return OPEN_ERR;
++ }
++
++ // AUHAL
++ AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_RemoteIO, kAudioUnitManufacturer_Apple, 0, 0};
++ AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd);
++
++ err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL);
++ if (err1 != noErr) {
++ printf("Error calling OpenAComponent\n");
++ printError(err1);
++ goto error;
++ }
++
++ enableIO = 1;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output\n");
++ printError(err1);
++ goto error;
++ }
++
++ enableIO = 1;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input\n");
++ printError(err1);
++ goto error;
++ }
++
++
++ UInt32 maxFPS;
++ outSize = sizeof(maxFPS);
++ err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &maxFPS, &outSize);
++ if (err1 != noErr) {
++ printf("Couldn't get kAudioUnitProperty_MaximumFramesPerSlice\n");
++ printError(err1);
++ goto error;
++ } else {
++ printf("Get kAudioUnitProperty_MaximumFramesPerSlice %d\n", maxFPS);
++ }
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&bufferSize, sizeof(UInt32));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
++ printError(err1);
++ goto error;
++ }
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&bufferSize, sizeof(UInt32));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice\n");
++ printError(err1);
++ goto error;
++ }
++
++
++ err1 = AudioUnitInitialize(fAUHAL);
++ if (err1 != noErr) {
++ printf("Cannot initialize AUHAL unit\n");
++ printError(err1);
++ goto error;
++ }
++
++ // Setting format
++
++ if (fDevNumInChans > 0) {
++ outSize = sizeof(AudioStreamBasicDescription);
++ err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &outSize);
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
++ printError(err1);
++ }
++ PrintStreamDesc(&srcFormat);
++
++ srcFormat.mFormatID = kAudioFormatLinearPCM;
++ srcFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
++ srcFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
++ srcFormat.mFramesPerPacket = 1;
++ srcFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
++ srcFormat.mChannelsPerFrame = fDevNumInChans;
++ srcFormat.mBitsPerChannel = 32;
++
++ PrintStreamDesc(&srcFormat);
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output\n");
++ printError(err1);
++ }
++
++ }
++
++ if (fDevNumOutChans > 0) {
++ outSize = sizeof(AudioStreamBasicDescription);
++ err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &outSize);
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
++ printError(err1);
++ }
++ PrintStreamDesc(&dstFormat);
++
++ dstFormat.mFormatID = kAudioFormatLinearPCM;
++ dstFormat.mFormatFlags = kAudioFormatFlagsCanonical | kLinearPCMFormatFlagIsNonInterleaved;
++ dstFormat.mBytesPerPacket = sizeof(AudioUnitSampleType);
++ dstFormat.mFramesPerPacket = 1;
++ dstFormat.mBytesPerFrame = sizeof(AudioUnitSampleType);
++ dstFormat.mChannelsPerFrame = fDevNumOutChans;
++ dstFormat.mBitsPerChannel = 32;
++
++ PrintStreamDesc(&dstFormat);
++
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input\n");
++ printError(err1);
++ }
++ }
++
++ if (fDevNumInChans > 0 && fDevNumOutChans == 0) {
++ AURenderCallbackStruct output;
++ output.inputProc = Render;
++ output.inputProcRefCon = this;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1\n");
++ printError(err1);
++ goto error;
++ }
++ } else {
++ AURenderCallbackStruct output;
++ output.inputProc = Render;
++ output.inputProcRefCon = this;
++ err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
++ if (err1 != noErr) {
++ printf("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0\n");
++ printError(err1);
++ goto error;
++ }
++ }
++
++ return NO_ERR;
++
++error:
++ AudioUnitUninitialize(fAUHAL);
++ AudioComponentInstanceDispose(fAUHAL);
++ return OPEN_ERR;
++}
++
++long TiPhoneCoreAudioRenderer::Close()
++{
++ AudioUnitUninitialize(fAUHAL);
++ AudioComponentInstanceDispose(fAUHAL);
++ return NO_ERR;
++}
++
++long TiPhoneCoreAudioRenderer::Start()
++{
++ AudioSessionSetActive(true);
++ OSStatus err = AudioOutputUnitStart(fAUHAL);
++
++ if (err != noErr) {
++ printf("Error while opening device : device open error \n");
++ return OPEN_ERR;
++ } else {
++ return NO_ERR;
++ }
++}
++
++long TiPhoneCoreAudioRenderer::Stop()
++{
++ OSStatus err = AudioOutputUnitStop(fAUHAL);
++
++ if (err != noErr) {
++ printf("Error while closing device : device close error \n");
++ return OPEN_ERR;
++ } else {
++ return NO_ERR;
++ }
++}
++
++/******************************************************************************
++*******************************************************************************
++
++ MAIN PLAY THREAD
++
++*******************************************************************************
++*******************************************************************************/
++
++long lopt(char *argv[], const char *name, long def)
++{
++ int i;
++ for (i = 0; argv[i]; i++) if (!strcmp(argv[i], name)) return atoi(argv[i + 1]);
++ return def;
++}
++
++//-------------------------------------------------------------------------
++// MAIN
++//-------------------------------------------------------------------------
++
++int main(int argc, char *argv[])
++{
++ UI* interface = new CMDUI(argc, argv);
++ TiPhoneCoreAudioRenderer audio_device(DSP.getNumInputs(), DSP.getNumOutputs());
++
++ long srate = (long)lopt(argv, "--frequency", 44100);
++ int fpb = lopt(argv, "--buffer", 512);
++
++ DSP.init(long(srate));
++ DSP.buildUserInterface(interface);
++
++ if (audio_device.Open(fpb, srate) < 0) {
++ printf("Cannot open CoreAudio device\n");
++ return 0;
++ }
++
++ if (audio_device.Start() < 0) {
++ printf("Cannot start CoreAudio device\n");
++ return 0;
++ }
++
++ printf("inchan = %d, outchan = %d, freq = %ld\n", DSP.getNumInputs(), DSP.getNumOutputs(), srate);
++ interface->run();
++
++ audio_device.Stop();
++ audio_device.Close();
++ return 0;
++}
++
+--- /dev/null
++++ b/macosx/iphone/iPhoneNetAppDelegate.h
+@@ -0,0 +1,23 @@
++//
++// iPhoneNetAppDelegate.h
++// iPhoneNet
++//
++// Created by Stéphane LETZ on 16/02/09.
++// Copyright Grame 2009. All rights reserved.
++//
++
++#import <UIKit/UIKit.h>
++
++ at interface iPhoneNetAppDelegate : NSObject <UIApplicationDelegate> {
++ // UIWindow *window;
++
++ IBOutlet UIWindow *window;
++ IBOutlet UINavigationController *navigationController;
++}
++
++//@property (nonatomic, retain) IBOutlet UIWindow *window;
++ at property (nonatomic, retain) UIWindow *window;
++ at property (nonatomic, retain) UINavigationController *navigationController;
++
++ at end
++
+--- /dev/null
++++ b/macosx/iphone/iPhoneNetAppDelegate.m
+@@ -0,0 +1,32 @@
++//
++// iPhoneNetAppDelegate.m
++// iPhoneNet
++//
++// Created by Stéphane LETZ on 16/02/09.
++// Copyright Grame 2009. All rights reserved.
++//
++
++#import "iPhoneNetAppDelegate.h"
++
++ at implementation iPhoneNetAppDelegate
++
++ at synthesize window, navigationController;
++
++
++- (void)applicationDidFinishLaunching:(UIApplication *)application {
++
++ // Override point for customization after application launch
++ // add the navigation controller's view to the window
++ [window addSubview: navigationController.view];
++ [window makeKeyAndVisible];
++}
++
++
++- (void)dealloc {
++ [navigationController release];
++ [window release];
++ [super dealloc];
++}
++
++
++ at end
+--- /dev/null
++++ b/macosx/iphone/iPhoneNet_Prefix.pch
+@@ -0,0 +1,10 @@
++//
++// Prefix header for all source files of the 'iPhoneNet' target in the 'iPhoneNet' project
++//
++
++#ifdef __OBJC__
++ #import <Foundation/Foundation.h>
++ #import <UIKit/UIKit.h>
++#endif
++
++#define MY_TARGET_OS_IPHONE 1
+--- /dev/null
++++ b/macosx/iphone/iPhoneNet.xcodeproj/project.pbxproj
+@@ -0,0 +1,1298 @@
++// !$*UTF8*$!
++{
++ archiveVersion = 1;
++ classes = {
++ };
++ objectVersion = 45;
++ objects = {
++
++/* Begin PBXBuildFile section */
++ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4B0772210F54018C000DC657 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4B0772240F54018C000DC657 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; };
++ 4B0772250F54018C000DC657 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; };
++ 4B0772260F54018C000DC657 /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; };
++ 4B0772270F54018C000DC657 /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; };
++ 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; };
++ 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; };
++ 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; };
++ 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; };
++ 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; };
++ 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; };
++ 4B0772310F54018C000DC657 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 4B0772320F54018C000DC657 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 4B0772330F54018C000DC657 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 4B0772340F54018C000DC657 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++ 4B07724A0F54021B000DC657 /* main_slave.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772490F54021B000DC657 /* main_slave.mm */; };
++ 4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; };
++ 4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; };
++ 4B0773880F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; };
++ 4B1A94140F49BE2C00D3626B /* iPhoneNet_Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */; };
++ 4B1A94150F49BE2F00D3626B /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; };
++ 4B1A94160F49BE3000D3626B /* JackMachThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B1A93540F49ACFC00D3626B /* JackMachThread.h */; };
++ 4B1A94170F49BE3100D3626B /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; };
++ 4B1A94180F49BE3100D3626B /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; };
++ 4B1A94190F49BE3300D3626B /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; };
++ 4B1A941A0F49BE3300D3626B /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; };
++ 4B1A941B0F49BE3400D3626B /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; };
++ 4B1A941C0F49BE3500D3626B /* JackNetUnixSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B1A93520F49ACF300D3626B /* JackNetUnixSocket.h */; };
++ 4B1A941D0F49BE3500D3626B /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; };
++ 4B1A941E0F49BE3600D3626B /* JackPosixThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B1A933C0F49AC4500D3626B /* JackPosixThread.h */; };
++ 4B1A94540F49C03300D3626B /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; };
++ 4B1A94550F49C03300D3626B /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; };
++ 4B1A94560F49C03400D3626B /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; };
++ 4B1A94570F49C03500D3626B /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; };
++ 4B1A94580F49C03600D3626B /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; };
++ 4B1A94590F49C03600D3626B /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; };
++ 4B1A945A0F49C03600D3626B /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; };
++ 4B1A95760F49CEAB00D3626B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++ 4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; };
++ 4B2791890F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; };
++ 4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; };
++ 4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; };
++ 4B41469810BD3C4300C12F0C /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4B41469A10BD3C4300C12F0C /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; };
++ 4B41469B10BD3C4300C12F0C /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; };
++ 4B41469C10BD3C4300C12F0C /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; };
++ 4B41469D10BD3C4300C12F0C /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; };
++ 4B41469E10BD3C4300C12F0C /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; };
++ 4B41469F10BD3C4300C12F0C /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; };
++ 4B4146A010BD3C4300C12F0C /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; };
++ 4B4146A210BD3C4300C12F0C /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; };
++ 4B4146A310BD3C4300C12F0C /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; };
++ 4B4146A410BD3C4300C12F0C /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; };
++ 4B4146A510BD3C4300C12F0C /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; };
++ 4B4146A610BD3C4300C12F0C /* freeverb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDC8F90F5420C000465F9C /* freeverb.mm */; };
++ 4B4146A710BD3C4300C12F0C /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; };
++ 4B4146A910BD3C4300C12F0C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 4B4146AA10BD3C4300C12F0C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 4B4146AB10BD3C4300C12F0C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 4B4146AC10BD3C4300C12F0C /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++ 4B6B712C114BAE9A00ED9788 /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4B9CB1371136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4B9CB1381136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4B9CB1391136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4B9CB13A1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4B9CB13B1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4B9CB13C1136CA99007DE01A /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BBDC8F90F5420C000465F9C /* freeverb.mm */; };
++ 4BC9C1F71135AB2800D22670 /* main_master.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772500F54022D000DC657 /* main_master.mm */; };
++ 4BCB37B6112D647C008C7BC1 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4BCB37C7112D647C008C7BC1 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 4BCB37C8112D647C008C7BC1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 4BCB37C9112D647C008C7BC1 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 4BCB37CA112D647C008C7BC1 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++ 4BCB37D9112D64D8008C7BC1 /* iphone-faust.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */; };
++ 4BCF75DA10BC2FD90082C526 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4BCF75DC10BC2FD90082C526 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; };
++ 4BCF75DD10BC2FD90082C526 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; };
++ 4BCF75DE10BC2FD90082C526 /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; };
++ 4BCF75DF10BC2FD90082C526 /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; };
++ 4BCF75E010BC2FD90082C526 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; };
++ 4BCF75E110BC2FD90082C526 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; };
++ 4BCF75E210BC2FD90082C526 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; };
++ 4BCF75E410BC2FD90082C526 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; };
++ 4BCF75E510BC2FD90082C526 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; };
++ 4BCF75E610BC2FD90082C526 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; };
++ 4BCF75E710BC2FD90082C526 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; };
++ 4BCF75E910BC2FD90082C526 /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2791870F72570C000536B7 /* JackGlobals.cpp */; };
++ 4BCF75EB10BC2FD90082C526 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 4BCF75EC10BC2FD90082C526 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 4BCF75ED10BC2FD90082C526 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 4BCF75EE10BC2FD90082C526 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++ 4BCF75F710BC30140082C526 /* audio_thru.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF75F610BC30140082C526 /* audio_thru.mm */; };
++ 4BDFCD3D113DB6B700D77992 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4BDFCD3E113DB6B700D77992 /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4B9CB1361136CA99007DE01A /* icon.png */; };
++ 4BDFCD4A113DB6B700D77992 /* main_slave.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B0772490F54021B000DC657 /* main_slave.mm */; };
++ 4BDFCD4B113DB6B700D77992 /* iPhoneNetAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */; };
++ 4BDFCD4D113DB6B700D77992 /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BDFCD4E113DB6B700D77992 /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BDFCD50113DB6B700D77992 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 4BDFCD51113DB6B700D77992 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 4BDFCD52113DB6B700D77992 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 4BDFCD53113DB6B700D77992 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++ 4BF1360F0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; };
++ 4BF136100F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; };
++ 4BF136130F4B0B5E00218A3F /* JackAudioAdapterInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */; };
++ 4BF1364D0F4B0F7700218A3F /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; };
++ 4BF1364E0F4B0F7700218A3F /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; };
++ 4BF1364F0F4B0F7700218A3F /* JackResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF1364C0F4B0F7700218A3F /* JackResampler.h */; };
++ 4BF136550F4B0F9F00218A3F /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; };
++ 4BF136560F4B0F9F00218A3F /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; };
++ 4BF15E2511356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BF15E2611356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BF15E2711356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */; };
++ 4BF15F7811357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BF15F7911357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BF15F7A11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BF15F7B11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BF15F7C11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BF15F7D11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */; };
++ 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; };
++ 4BFF45630F4D5D9700106083 /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */; };
++ 4BFF45640F4D5D9700106083 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93870F49B0E300D3626B /* JackMachTime.c */; };
++ 4BFF45650F4D5D9700106083 /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */; };
++ 4BFF45660F4D5D9700106083 /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */; };
++ 4BFF45670F4D5D9700106083 /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */; };
++ 4BFF45680F4D5D9700106083 /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */; };
++ 4BFF45690F4D5D9700106083 /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */; };
++ 4BFF456B0F4D5D9700106083 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */; };
++ 4BFF456C0F4D5D9700106083 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */; };
++ 4BFF456D0F4D5D9700106083 /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF136540F4B0F9F00218A3F /* ringbuffer.c */; };
++ 4BFF45700F4D5D9700106083 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
++ 4BFF45710F4D5D9700106083 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
++ 4BFF45720F4D5D9700106083 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; };
++ 4BFF45730F4D5D9700106083 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */; };
++/* End PBXBuildFile section */
++
++/* Begin PBXFileReference section */
++ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
++ 1D6058910D05DD3D006BFB54 /* NetJackSlave.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetJackSlave.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
++ 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
++ 28AD733E0D9D9553002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = "<group>"; };
++ 32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneNet_Prefix.pch; sourceTree = "<group>"; };
++ 4B0772380F54018C000DC657 /* NetJackMaster.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetJackMaster.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B0772490F54021B000DC657 /* main_slave.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main_slave.mm; sourceTree = SOURCE_ROOT; };
++ 4B0772500F54022D000DC657 /* main_master.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main_master.mm; sourceTree = SOURCE_ROOT; };
++ 4B0773840F541EE2000DC657 /* iPhoneNetAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iPhoneNetAppDelegate.h; sourceTree = "<group>"; };
++ 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = iPhoneNetAppDelegate.m; sourceTree = "<group>"; };
++ 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetAPI.cpp; path = ../../common/JackNetAPI.cpp; sourceTree = SOURCE_ROOT; };
++ 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetInterface.cpp; path = ../../common/JackNetInterface.cpp; sourceTree = SOURCE_ROOT; };
++ 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetTool.cpp; path = ../../common/JackNetTool.cpp; sourceTree = SOURCE_ROOT; };
++ 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPosixThread.cpp; path = ../../posix/JackPosixThread.cpp; sourceTree = SOURCE_ROOT; };
++ 4B1A933C0F49AC4500D3626B /* JackPosixThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPosixThread.h; path = ../../posix/JackPosixThread.h; sourceTree = SOURCE_ROOT; };
++ 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetUnixSocket.cpp; path = ../../posix/JackNetUnixSocket.cpp; sourceTree = SOURCE_ROOT; };
++ 4B1A93520F49ACF300D3626B /* JackNetUnixSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackNetUnixSocket.h; path = ../../posix/JackNetUnixSocket.h; sourceTree = SOURCE_ROOT; };
++ 4B1A93540F49ACFC00D3626B /* JackMachThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMachThread.h; path = ../JackMachThread.h; sourceTree = SOURCE_ROOT; };
++ 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMachThread.cpp; path = ../JackMachThread.cpp; sourceTree = SOURCE_ROOT; };
++ 4B1A93870F49B0E300D3626B /* JackMachTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = JackMachTime.c; path = ../JackMachTime.c; sourceTree = SOURCE_ROOT; };
++ 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.1.sdk/System/Library/Frameworks/AudioToolbox.framework; sourceTree = "<absolute>"; };
++ 4B2791870F72570C000536B7 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; };
++ 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B9CB1361136CA99007DE01A /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = SOURCE_ROOT; };
++ 4BBDC8F90F5420C000465F9C /* freeverb.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = freeverb.mm; sourceTree = SOURCE_ROOT; };
++ 4BC9C1D31135AA1800D22670 /* iPhoneNetMasterAppl-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "iPhoneNetMasterAppl-Info.plist"; sourceTree = "<group>"; };
++ 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaust.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "iphone-faust.mm"; sourceTree = SOURCE_ROOT; };
++ 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneThruNet.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4BCF75F610BC30140082C526 /* audio_thru.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = audio_thru.mm; sourceTree = SOURCE_ROOT; };
++ 4BDFCD57113DB6B700D77992 /* NetJackSlave.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetJackSlave.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterInterface.cpp; path = ../../common/JackAudioAdapterInterface.cpp; sourceTree = SOURCE_ROOT; };
++ 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioAdapterInterface.h; path = ../../common/JackAudioAdapterInterface.h; sourceTree = SOURCE_ROOT; };
++ 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackResampler.cpp; path = ../../common/JackResampler.cpp; sourceTree = SOURCE_ROOT; };
++ 4BF1364C0F4B0F7700218A3F /* JackResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackResampler.h; path = ../../common/JackResampler.h; sourceTree = SOURCE_ROOT; };
++ 4BF136540F4B0F9F00218A3F /* ringbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ringbuffer.c; path = ../../common/ringbuffer.c; sourceTree = SOURCE_ROOT; };
++ 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CAHostTimeBase.cpp; path = /Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.cpp; sourceTree = "<absolute>"; };
++ 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TiPhoneCoreAudioRenderer.cpp; path = ../coreaudio/TiPhoneCoreAudioRenderer.cpp; sourceTree = SOURCE_ROOT; };
++ 4BFF45120F4D59DB00106083 /* libjacknet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjacknet.a; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iPhoneFaustNet.app; sourceTree = BUILT_PRODUCTS_DIR; };
++ 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
++/* End PBXFileReference section */
++
++/* Begin PBXFrameworksBuildPhase section */
++ 1D60588F0D05DD3D006BFB54 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
++ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
++ 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */,
++ 4B1A95760F49CEAB00D3626B /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B0772300F54018C000DC657 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B0772310F54018C000DC657 /* Foundation.framework in Frameworks */,
++ 4B0772320F54018C000DC657 /* UIKit.framework in Frameworks */,
++ 4B0772330F54018C000DC657 /* CoreGraphics.framework in Frameworks */,
++ 4B0772340F54018C000DC657 /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B1A940E0F49BDE000D3626B /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B4146A810BD3C4300C12F0C /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B4146A910BD3C4300C12F0C /* Foundation.framework in Frameworks */,
++ 4B4146AA10BD3C4300C12F0C /* UIKit.framework in Frameworks */,
++ 4B4146AB10BD3C4300C12F0C /* CoreGraphics.framework in Frameworks */,
++ 4B4146AC10BD3C4300C12F0C /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BCB37C6112D647C008C7BC1 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BCB37C7112D647C008C7BC1 /* Foundation.framework in Frameworks */,
++ 4BCB37C8112D647C008C7BC1 /* UIKit.framework in Frameworks */,
++ 4BCB37C9112D647C008C7BC1 /* CoreGraphics.framework in Frameworks */,
++ 4BCB37CA112D647C008C7BC1 /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BCF75EA10BC2FD90082C526 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BCF75EB10BC2FD90082C526 /* Foundation.framework in Frameworks */,
++ 4BCF75EC10BC2FD90082C526 /* UIKit.framework in Frameworks */,
++ 4BCF75ED10BC2FD90082C526 /* CoreGraphics.framework in Frameworks */,
++ 4BCF75EE10BC2FD90082C526 /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BDFCD4F113DB6B700D77992 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BDFCD50113DB6B700D77992 /* Foundation.framework in Frameworks */,
++ 4BDFCD51113DB6B700D77992 /* UIKit.framework in Frameworks */,
++ 4BDFCD52113DB6B700D77992 /* CoreGraphics.framework in Frameworks */,
++ 4BDFCD53113DB6B700D77992 /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BFF456F0F4D5D9700106083 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BFF45700F4D5D9700106083 /* Foundation.framework in Frameworks */,
++ 4BFF45710F4D5D9700106083 /* UIKit.framework in Frameworks */,
++ 4BFF45720F4D5D9700106083 /* CoreGraphics.framework in Frameworks */,
++ 4BFF45730F4D5D9700106083 /* AudioToolbox.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++/* End PBXFrameworksBuildPhase section */
++
++/* Begin PBXGroup section */
++ 19C28FACFE9D520D11CA2CBB /* Products */ = {
++ isa = PBXGroup;
++ children = (
++ 1D6058910D05DD3D006BFB54 /* NetJackSlave.app */,
++ 4BFF45120F4D59DB00106083 /* libjacknet.a */,
++ 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */,
++ 4B0772380F54018C000DC657 /* NetJackMaster.app */,
++ 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */,
++ 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */,
++ 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */,
++ 4BDFCD57113DB6B700D77992 /* NetJackSlave.app */,
++ );
++ name = Products;
++ sourceTree = "<group>";
++ };
++ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
++ isa = PBXGroup;
++ children = (
++ 4BCB37D8112D64D8008C7BC1 /* iphone-faust.mm */,
++ 4BF15E2411356A3E00B36B9A /* CAHostTimeBase.cpp */,
++ 4BF15F7711357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp */,
++ 29B97315FDCFA39411CA2CEA /* Other Sources */,
++ 29B97323FDCFA39411CA2CEA /* Frameworks */,
++ 19C28FACFE9D520D11CA2CBB /* Products */,
++ );
++ name = CustomTemplate;
++ sourceTree = "<group>";
++ };
++ 29B97315FDCFA39411CA2CEA /* Other Sources */ = {
++ isa = PBXGroup;
++ children = (
++ 29B97317FDCFA39411CA2CEA /* Resources */,
++ 4BCF75F610BC30140082C526 /* audio_thru.mm */,
++ 4BBDC8F90F5420C000465F9C /* freeverb.mm */,
++ 4B0773840F541EE2000DC657 /* iPhoneNetAppDelegate.h */,
++ 4B0773850F541EE2000DC657 /* iPhoneNetAppDelegate.m */,
++ 4BF136540F4B0F9F00218A3F /* ringbuffer.c */,
++ 4BF1364B0F4B0F7700218A3F /* JackResampler.cpp */,
++ 4BF1364C0F4B0F7700218A3F /* JackResampler.h */,
++ 4BF1360E0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp */,
++ 4BF136120F4B0B5E00218A3F /* JackAudioAdapterInterface.h */,
++ 4B1A93870F49B0E300D3626B /* JackMachTime.c */,
++ 4B1A93540F49ACFC00D3626B /* JackMachThread.h */,
++ 4B1A93550F49ACFC00D3626B /* JackMachThread.cpp */,
++ 4B1A93510F49ACF300D3626B /* JackNetUnixSocket.cpp */,
++ 4B1A93520F49ACF300D3626B /* JackNetUnixSocket.h */,
++ 4B1A933B0F49AC4500D3626B /* JackPosixThread.cpp */,
++ 4B1A933C0F49AC4500D3626B /* JackPosixThread.h */,
++ 4B1A93110F49AB3400D3626B /* JackNetTool.cpp */,
++ 4B1A930F0F49AB2F00D3626B /* JackNetInterface.cpp */,
++ 4B1A930D0F49AB2A00D3626B /* JackNetAPI.cpp */,
++ 4B2791870F72570C000536B7 /* JackGlobals.cpp */,
++ 32CA4F630368D1EE00C91783 /* iPhoneNet_Prefix.pch */,
++ 4B0772490F54021B000DC657 /* main_slave.mm */,
++ 4B0772500F54022D000DC657 /* main_master.mm */,
++ );
++ name = "Other Sources";
++ sourceTree = "<group>";
++ };
++ 29B97317FDCFA39411CA2CEA /* Resources */ = {
++ isa = PBXGroup;
++ children = (
++ 4B9CB1361136CA99007DE01A /* icon.png */,
++ 28AD733E0D9D9553002E5188 /* MainWindow.xib */,
++ 8D1107310486CEB800E47090 /* Info.plist */,
++ 4BC9C1D31135AA1800D22670 /* iPhoneNetMasterAppl-Info.plist */,
++ );
++ name = Resources;
++ sourceTree = "<group>";
++ };
++ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
++ isa = PBXGroup;
++ children = (
++ 4B1A95750F49CEAB00D3626B /* AudioToolbox.framework */,
++ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
++ 1D30AB110D05D00D00671497 /* Foundation.framework */,
++ 288765FC0DF74451002DB57D /* CoreGraphics.framework */,
++ );
++ name = Frameworks;
++ sourceTree = "<group>";
++ };
++/* End PBXGroup section */
++
++/* Begin PBXHeadersBuildPhase section */
++ 4B1A940C0F49BDE000D3626B /* Headers */ = {
++ isa = PBXHeadersBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B1A94140F49BE2C00D3626B /* iPhoneNet_Prefix.pch in Headers */,
++ 4B1A94160F49BE3000D3626B /* JackMachThread.h in Headers */,
++ 4B1A941C0F49BE3500D3626B /* JackNetUnixSocket.h in Headers */,
++ 4B1A941E0F49BE3600D3626B /* JackPosixThread.h in Headers */,
++ 4BF136130F4B0B5E00218A3F /* JackAudioAdapterInterface.h in Headers */,
++ 4BF1364F0F4B0F7700218A3F /* JackResampler.h in Headers */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++/* End PBXHeadersBuildPhase section */
++
++/* Begin PBXNativeTarget section */
++ 1D6058900D05DD3D006BFB54 /* iPhoneNetSlave */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "iPhoneNetSlave" */;
++ buildPhases = (
++ 1D60588D0D05DD3D006BFB54 /* Resources */,
++ 1D60588E0D05DD3D006BFB54 /* Sources */,
++ 1D60588F0D05DD3D006BFB54 /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = iPhoneNetSlave;
++ productName = iPhoneNet;
++ productReference = 1D6058910D05DD3D006BFB54 /* NetJackSlave.app */;
++ productType = "com.apple.product-type.application";
++ };
++ 4B07721F0F54018C000DC657 /* iPhoneNetMaster */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4B0772350F54018C000DC657 /* Build configuration list for PBXNativeTarget "iPhoneNetMaster" */;
++ buildPhases = (
++ 4B0772200F54018C000DC657 /* Resources */,
++ 4B0772220F54018C000DC657 /* Sources */,
++ 4B0772300F54018C000DC657 /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = iPhoneNetMaster;
++ productName = iPhoneNet;
++ productReference = 4B0772380F54018C000DC657 /* NetJackMaster.app */;
++ productType = "com.apple.product-type.application";
++ };
++ 4B1A940F0F49BDE000D3626B /* libjacknet */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "libjacknet" */;
++ buildPhases = (
++ 4B1A940C0F49BDE000D3626B /* Headers */,
++ 4B1A940D0F49BDE000D3626B /* Sources */,
++ 4B1A940E0F49BDE000D3626B /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = libjacknet;
++ productName = jacknet;
++ productReference = 4BFF45120F4D59DB00106083 /* libjacknet.a */;
++ productType = "com.apple.product-type.library.static";
++ };
++ 4B41469610BD3C4300C12F0C /* iPhoneFaustNet Distribution */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4B4146AD10BD3C4300C12F0C /* Build configuration list for PBXNativeTarget "iPhoneFaustNet Distribution" */;
++ buildPhases = (
++ 4B41469710BD3C4300C12F0C /* Resources */,
++ 4B41469910BD3C4300C12F0C /* Sources */,
++ 4B4146A810BD3C4300C12F0C /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = "iPhoneFaustNet Distribution";
++ productName = iPhoneNet;
++ productReference = 4B4146B010BD3C4300C12F0C /* iPhoneFaustNet.app */;
++ productType = "com.apple.product-type.application";
++ };
++ 4BCB37B4112D647C008C7BC1 /* iPhoneFaust */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4BCB37CB112D647C008C7BC1 /* Build configuration list for PBXNativeTarget "iPhoneFaust" */;
++ buildPhases = (
++ 4BCB37B5112D647C008C7BC1 /* Resources */,
++ 4BCB37B7112D647C008C7BC1 /* Sources */,
++ 4BCB37C6112D647C008C7BC1 /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = iPhoneFaust;
++ productName = iPhoneNet;
++ productReference = 4BCB37CE112D647C008C7BC1 /* iPhoneFaust.app */;
++ productType = "com.apple.product-type.application";
++ };
++ 4BCF75D810BC2FD90082C526 /* iPhoneThruNet */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4BCF75EF10BC2FD90082C526 /* Build configuration list for PBXNativeTarget "iPhoneThruNet" */;
++ buildPhases = (
++ 4BCF75D910BC2FD90082C526 /* Resources */,
++ 4BCF75DB10BC2FD90082C526 /* Sources */,
++ 4BCF75EA10BC2FD90082C526 /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = iPhoneThruNet;
++ productName = iPhoneNet;
++ productReference = 4BCF75F210BC2FD90082C526 /* iPhoneThruNet.app */;
++ productType = "com.apple.product-type.application";
++ };
++ 4BDFCD3B113DB6B700D77992 /* iPhoneNetSlaveLib */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4BDFCD54113DB6B700D77992 /* Build configuration list for PBXNativeTarget "iPhoneNetSlaveLib" */;
++ buildPhases = (
++ 4BDFCD3C113DB6B700D77992 /* Resources */,
++ 4BDFCD3F113DB6B700D77992 /* Sources */,
++ 4BDFCD4F113DB6B700D77992 /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = iPhoneNetSlaveLib;
++ productName = iPhoneNet;
++ productReference = 4BDFCD57113DB6B700D77992 /* NetJackSlave.app */;
++ productType = "com.apple.product-type.application";
++ };
++ 4BFF455E0F4D5D9700106083 /* iPhoneFaustNet */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4BFF45740F4D5D9700106083 /* Build configuration list for PBXNativeTarget "iPhoneFaustNet" */;
++ buildPhases = (
++ 4BFF455F0F4D5D9700106083 /* Resources */,
++ 4BFF45610F4D5D9700106083 /* Sources */,
++ 4BFF456F0F4D5D9700106083 /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = iPhoneFaustNet;
++ productName = iPhoneNet;
++ productReference = 4BFF45770F4D5D9700106083 /* iPhoneFaustNet.app */;
++ productType = "com.apple.product-type.application";
++ };
++/* End PBXNativeTarget section */
++
++/* Begin PBXProject section */
++ 29B97313FDCFA39411CA2CEA /* Project object */ = {
++ isa = PBXProject;
++ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "iPhoneNet" */;
++ compatibilityVersion = "Xcode 3.1";
++ developmentRegion = English;
++ hasScannedForEncodings = 1;
++ knownRegions = (
++ English,
++ Japanese,
++ French,
++ German,
++ );
++ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
++ projectDirPath = "";
++ projectRoot = "";
++ targets = (
++ 4B07721F0F54018C000DC657 /* iPhoneNetMaster */,
++ 1D6058900D05DD3D006BFB54 /* iPhoneNetSlave */,
++ 4BDFCD3B113DB6B700D77992 /* iPhoneNetSlaveLib */,
++ 4BFF455E0F4D5D9700106083 /* iPhoneFaustNet */,
++ 4BCF75D810BC2FD90082C526 /* iPhoneThruNet */,
++ 4B41469610BD3C4300C12F0C /* iPhoneFaustNet Distribution */,
++ 4BCB37B4112D647C008C7BC1 /* iPhoneFaust */,
++ 4B1A940F0F49BDE000D3626B /* libjacknet */,
++ );
++ };
++/* End PBXProject section */
++
++/* Begin PBXResourcesBuildPhase section */
++ 1D60588D0D05DD3D006BFB54 /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */,
++ 4B9CB1381136CA99007DE01A /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B0772200F54018C000DC657 /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B0772210F54018C000DC657 /* MainWindow.xib in Resources */,
++ 4B9CB1371136CA99007DE01A /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B41469710BD3C4300C12F0C /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B41469810BD3C4300C12F0C /* MainWindow.xib in Resources */,
++ 4B9CB13B1136CA99007DE01A /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BCB37B5112D647C008C7BC1 /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BCB37B6112D647C008C7BC1 /* MainWindow.xib in Resources */,
++ 4B9CB13C1136CA99007DE01A /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BCF75D910BC2FD90082C526 /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BCF75DA10BC2FD90082C526 /* MainWindow.xib in Resources */,
++ 4B9CB13A1136CA99007DE01A /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BDFCD3C113DB6B700D77992 /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BDFCD3D113DB6B700D77992 /* MainWindow.xib in Resources */,
++ 4BDFCD3E113DB6B700D77992 /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BFF455F0F4D5D9700106083 /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BFF45600F4D5D9700106083 /* MainWindow.xib in Resources */,
++ 4B9CB1391136CA99007DE01A /* icon.png in Resources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++/* End PBXResourcesBuildPhase section */
++
++/* Begin PBXSourcesBuildPhase section */
++ 1D60588E0D05DD3D006BFB54 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B1A94540F49C03300D3626B /* JackMachThread.cpp in Sources */,
++ 4B1A94550F49C03300D3626B /* JackMachTime.c in Sources */,
++ 4B1A94560F49C03400D3626B /* JackNetAPI.cpp in Sources */,
++ 4B1A94570F49C03500D3626B /* JackNetInterface.cpp in Sources */,
++ 4B1A94580F49C03600D3626B /* JackNetTool.cpp in Sources */,
++ 4B1A94590F49C03600D3626B /* JackNetUnixSocket.cpp in Sources */,
++ 4B1A945A0F49C03600D3626B /* JackPosixThread.cpp in Sources */,
++ 4BF1360F0F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */,
++ 4BF1364D0F4B0F7700218A3F /* JackResampler.cpp in Sources */,
++ 4BF136550F4B0F9F00218A3F /* ringbuffer.c in Sources */,
++ 4B07724A0F54021B000DC657 /* main_slave.mm in Sources */,
++ 4B0773870F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */,
++ 4B27918A0F72570C000536B7 /* JackGlobals.cpp in Sources */,
++ 4BF15E2611356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */,
++ 4BF15F7911357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B0772220F54018C000DC657 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B0772240F54018C000DC657 /* JackMachThread.cpp in Sources */,
++ 4B0772250F54018C000DC657 /* JackMachTime.c in Sources */,
++ 4B0772260F54018C000DC657 /* JackNetAPI.cpp in Sources */,
++ 4B0772270F54018C000DC657 /* JackNetInterface.cpp in Sources */,
++ 4B0772280F54018C000DC657 /* JackNetTool.cpp in Sources */,
++ 4B0772290F54018C000DC657 /* JackNetUnixSocket.cpp in Sources */,
++ 4B07722A0F54018C000DC657 /* JackPosixThread.cpp in Sources */,
++ 4B07722C0F54018C000DC657 /* JackAudioAdapterInterface.cpp in Sources */,
++ 4B07722D0F54018C000DC657 /* JackResampler.cpp in Sources */,
++ 4B07722E0F54018C000DC657 /* ringbuffer.c in Sources */,
++ 4B0773860F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */,
++ 4B27918B0F72570C000536B7 /* JackGlobals.cpp in Sources */,
++ 4BF15E2511356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */,
++ 4BF15F7811357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ 4BC9C1F71135AB2800D22670 /* main_master.mm in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B1A940D0F49BDE000D3626B /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B1A94150F49BE2F00D3626B /* JackMachThread.cpp in Sources */,
++ 4B1A94170F49BE3100D3626B /* JackMachTime.c in Sources */,
++ 4B1A94180F49BE3100D3626B /* JackNetAPI.cpp in Sources */,
++ 4B1A94190F49BE3300D3626B /* JackNetInterface.cpp in Sources */,
++ 4B1A941A0F49BE3300D3626B /* JackNetTool.cpp in Sources */,
++ 4B1A941B0F49BE3400D3626B /* JackNetUnixSocket.cpp in Sources */,
++ 4B1A941D0F49BE3500D3626B /* JackPosixThread.cpp in Sources */,
++ 4BF136100F4B0B4C00218A3F /* JackAudioAdapterInterface.cpp in Sources */,
++ 4BF1364E0F4B0F7700218A3F /* JackResampler.cpp in Sources */,
++ 4BF136560F4B0F9F00218A3F /* ringbuffer.c in Sources */,
++ 4B2791890F72570C000536B7 /* JackGlobals.cpp in Sources */,
++ 4B6B712C114BAE9A00ED9788 /* CAHostTimeBase.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4B41469910BD3C4300C12F0C /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B41469A10BD3C4300C12F0C /* JackMachThread.cpp in Sources */,
++ 4B41469B10BD3C4300C12F0C /* JackMachTime.c in Sources */,
++ 4B41469C10BD3C4300C12F0C /* JackNetAPI.cpp in Sources */,
++ 4B41469D10BD3C4300C12F0C /* JackNetInterface.cpp in Sources */,
++ 4B41469E10BD3C4300C12F0C /* JackNetTool.cpp in Sources */,
++ 4B41469F10BD3C4300C12F0C /* JackNetUnixSocket.cpp in Sources */,
++ 4B4146A010BD3C4300C12F0C /* JackPosixThread.cpp in Sources */,
++ 4B4146A210BD3C4300C12F0C /* JackAudioAdapterInterface.cpp in Sources */,
++ 4B4146A310BD3C4300C12F0C /* JackResampler.cpp in Sources */,
++ 4B4146A410BD3C4300C12F0C /* ringbuffer.c in Sources */,
++ 4B4146A510BD3C4300C12F0C /* iPhoneNetAppDelegate.m in Sources */,
++ 4B4146A610BD3C4300C12F0C /* freeverb.mm in Sources */,
++ 4B4146A710BD3C4300C12F0C /* JackGlobals.cpp in Sources */,
++ 4BF15E2911356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */,
++ 4BF15F7C11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BCB37B7112D647C008C7BC1 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BCB37D9112D64D8008C7BC1 /* iphone-faust.mm in Sources */,
++ 4BF15E2A11356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */,
++ 4BF15F7D11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BCF75DB10BC2FD90082C526 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BCF75DC10BC2FD90082C526 /* JackMachThread.cpp in Sources */,
++ 4BCF75DD10BC2FD90082C526 /* JackMachTime.c in Sources */,
++ 4BCF75DE10BC2FD90082C526 /* JackNetAPI.cpp in Sources */,
++ 4BCF75DF10BC2FD90082C526 /* JackNetInterface.cpp in Sources */,
++ 4BCF75E010BC2FD90082C526 /* JackNetTool.cpp in Sources */,
++ 4BCF75E110BC2FD90082C526 /* JackNetUnixSocket.cpp in Sources */,
++ 4BCF75E210BC2FD90082C526 /* JackPosixThread.cpp in Sources */,
++ 4BCF75E410BC2FD90082C526 /* JackAudioAdapterInterface.cpp in Sources */,
++ 4BCF75E510BC2FD90082C526 /* JackResampler.cpp in Sources */,
++ 4BCF75E610BC2FD90082C526 /* ringbuffer.c in Sources */,
++ 4BCF75E710BC2FD90082C526 /* iPhoneNetAppDelegate.m in Sources */,
++ 4BCF75E910BC2FD90082C526 /* JackGlobals.cpp in Sources */,
++ 4BCF75F710BC30140082C526 /* audio_thru.mm in Sources */,
++ 4BF15E2811356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */,
++ 4BF15F7B11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BDFCD3F113DB6B700D77992 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BDFCD4A113DB6B700D77992 /* main_slave.mm in Sources */,
++ 4BDFCD4B113DB6B700D77992 /* iPhoneNetAppDelegate.m in Sources */,
++ 4BDFCD4D113DB6B700D77992 /* CAHostTimeBase.cpp in Sources */,
++ 4BDFCD4E113DB6B700D77992 /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++ 4BFF45610F4D5D9700106083 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4BFF45630F4D5D9700106083 /* JackMachThread.cpp in Sources */,
++ 4BFF45640F4D5D9700106083 /* JackMachTime.c in Sources */,
++ 4BFF45650F4D5D9700106083 /* JackNetAPI.cpp in Sources */,
++ 4BFF45660F4D5D9700106083 /* JackNetInterface.cpp in Sources */,
++ 4BFF45670F4D5D9700106083 /* JackNetTool.cpp in Sources */,
++ 4BFF45680F4D5D9700106083 /* JackNetUnixSocket.cpp in Sources */,
++ 4BFF45690F4D5D9700106083 /* JackPosixThread.cpp in Sources */,
++ 4BFF456B0F4D5D9700106083 /* JackAudioAdapterInterface.cpp in Sources */,
++ 4BFF456C0F4D5D9700106083 /* JackResampler.cpp in Sources */,
++ 4BFF456D0F4D5D9700106083 /* ringbuffer.c in Sources */,
++ 4B0773880F541EE2000DC657 /* iPhoneNetAppDelegate.m in Sources */,
++ 4BBDC8FA0F5420C000465F9C /* freeverb.mm in Sources */,
++ 4B2791880F72570C000536B7 /* JackGlobals.cpp in Sources */,
++ 4BF15E2711356A3E00B36B9A /* CAHostTimeBase.cpp in Sources */,
++ 4BF15F7A11357A0E00B36B9A /* TiPhoneCoreAudioRenderer.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
++/* End PBXSourcesBuildPhase section */
++
++/* Begin XCBuildConfiguration section */
++ 1D6058940D05DD3E006BFB54 /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ /usr/local/include,
++ ../../macosx/coreaudio,
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\"$(SRCROOT)/build/Debug-iphonesimulator\"",
++ );
++ OTHER_LDFLAGS = libcelt.a;
++ PRODUCT_NAME = NetJackSlave;
++ SDKROOT = iphoneos3.1.3;
++ };
++ name = Debug;
++ };
++ 1D6058950D05DD3E006BFB54 /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_OPTIMIZATION_LEVEL = 3;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ GCC_THUMB_SUPPORT = NO;
++ HEADER_SEARCH_PATHS = (
++ .,
++ /usr/local/include,
++ ../../macosx/coreaudio,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ ../../macosx,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\"$(SRCROOT)/build/Debug-iphonesimulator\"",
++ );
++ OTHER_LDFLAGS = libcelt.a;
++ PRODUCT_NAME = NetJackSlave;
++ SDKROOT = iphoneos3.1.3;
++ };
++ name = Release;
++ };
++ 4B0772360F54018C000DC657 /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ /usr/local/include,
++ ../../macosx/coreaudio,
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"",
++ );
++ OTHER_LDFLAGS = libcelt.a;
++ PRODUCT_NAME = NetJackMaster;
++ SDKROOT = iphoneos3.1.3;
++ };
++ name = Debug;
++ };
++ 4B0772370F54018C000DC657 /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ /usr/local/include,
++ ../../macosx/coreaudio,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ ../../macosx,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"",
++ );
++ OTHER_LDFLAGS = libcelt.a;
++ PRODUCT_NAME = NetJackMaster;
++ };
++ name = Release;
++ };
++ 4B1A94110F49BDE100D3626B /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ /usr/local/include,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ ../../macosx,
++ );
++ MACH_O_TYPE = staticlib;
++ PREBINDING = NO;
++ PRODUCT_NAME = jacknet;
++ SDKROOT = iphoneos3.1.3;
++ STANDARD_C_PLUS_PLUS_LIBRARY_TYPE = static;
++ };
++ name = Debug;
++ };
++ 4B1A94120F49BDE100D3626B /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
++ GCC_ENABLE_FIX_AND_CONTINUE = NO;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ /usr/local/include,
++ ../../macosx,
++ ../../posix,
++ ../../common,
++ ../../common/jack,
++ );
++ PREBINDING = NO;
++ PRODUCT_NAME = jacknet;
++ SDKROOT = iphoneos3.1.3;
++ ZERO_LINK = NO;
++ };
++ name = Release;
++ };
++ 4B4146AE10BD3C4300C12F0C /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: Stéphane Letz (8LJEY2RN3N)";
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = "Info copy 2.plist";
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"",
++ );
++ OTHER_LDFLAGS = "";
++ PRODUCT_NAME = iPhoneFaustNet;
++ "PROVISIONING_PROFILE[sdk=iphoneos*]" = "CEF78041-8E2A-499D-BF7C-8A1B22B6C2AC";
++ SDKROOT = iphoneos2.2.1;
++ };
++ name = Debug;
++ };
++ 4B4146AF10BD3C4300C12F0C /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"",
++ );
++ ONLY_ACTIVE_ARCH = NO;
++ PRODUCT_NAME = iPhoneFaustNet;
++ SDKROOT = iphoneos3.1.2;
++ };
++ name = Release;
++ };
++ 4BCB37CC112D647C008C7BC1 /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ GCC_THUMB_SUPPORT = NO;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = Info.plist;
++ IPHONEOS_DEPLOYMENT_TARGET = 3.1.3;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"",
++ );
++ OTHER_LDFLAGS = "";
++ PRODUCT_NAME = iPhoneFaust;
++ SDKROOT = iphoneos3.1.3;
++ };
++ name = Debug;
++ };
++ 4BCB37CD112D647C008C7BC1 /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ GCC_THUMB_SUPPORT = NO;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"",
++ );
++ ONLY_ACTIVE_ARCH = NO;
++ PRODUCT_NAME = iPhoneFaust;
++ SDKROOT = iphoneos3.1.3;
++ };
++ name = Release;
++ };
++ 4BCF75F010BC2FD90082C526 /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"",
++ );
++ OTHER_LDFLAGS = "";
++ PRODUCT_NAME = iPhoneThruNet;
++ SDKROOT = iphoneos2.2.1;
++ };
++ name = Debug;
++ };
++ 4BCF75F110BC2FD90082C526 /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ GCC_VERSION = "";
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\\\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\\\\\"",
++ );
++ ONLY_ACTIVE_ARCH = NO;
++ PRODUCT_NAME = iPhoneFaustNet;
++ };
++ name = Release;
++ };
++ 4BDFCD55113DB6B700D77992 /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx/coreaudio,
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"",
++ );
++ OTHER_LDFLAGS = "-ljacknet";
++ PRODUCT_NAME = NetJackSlave;
++ SDKROOT = iphoneos3.1.3;
++ };
++ name = Debug;
++ };
++ 4BDFCD56113DB6B700D77992 /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx/coreaudio,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ ../../macosx,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"",
++ );
++ OTHER_LDFLAGS = "-ljacknet";
++ PRODUCT_NAME = NetJackSlave;
++ };
++ name = Release;
++ };
++ 4BFF45750F4D5D9700106083 /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = NO;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../posix,
++ ../../common/jack,
++ ../../common,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"",
++ );
++ OTHER_LDFLAGS = "";
++ PRODUCT_NAME = iPhoneFaustNet;
++ SDKROOT = iphoneos2.2.1;
++ };
++ name = Debug;
++ };
++ 4BFF45760F4D5D9700106083 /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ALWAYS_SEARCH_USER_PATHS = NO;
++ COPY_PHASE_STRIP = YES;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = iPhoneNet_Prefix.pch;
++ HEADER_SEARCH_PATHS = (
++ ../../macosx,
++ ../../common/jack,
++ ../../common,
++ ../../posix,
++ );
++ INFOPLIST_FILE = Info.plist;
++ LIBRARY_SEARCH_PATHS = (
++ "$(inherited)",
++ "\\\"$(SRCROOT)/build/Debug-iphonesimulator\\\"",
++ );
++ ONLY_ACTIVE_ARCH = NO;
++ PRODUCT_NAME = iPhoneFaustNet;
++ };
++ name = Release;
++ };
++ C01FCF4F08A954540054247B /* Debug */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
++ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
++ GCC_C_LANGUAGE_STANDARD = c99;
++ GCC_WARN_ABOUT_RETURN_TYPE = YES;
++ GCC_WARN_UNUSED_VARIABLE = YES;
++ ONLY_ACTIVE_ARCH = YES;
++ PREBINDING = NO;
++ SDKROOT = iphoneos2.2.1;
++ };
++ name = Debug;
++ };
++ C01FCF5008A954540054247B /* Release */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = "$(ARCHS_STANDARD_32_BIT)";
++ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
++ GCC_C_LANGUAGE_STANDARD = c99;
++ GCC_WARN_ABOUT_RETURN_TYPE = YES;
++ GCC_WARN_UNUSED_VARIABLE = YES;
++ PREBINDING = NO;
++ SDKROOT = iphoneos2.2.1;
++ };
++ name = Release;
++ };
++/* End XCBuildConfiguration section */
++
++/* Begin XCConfigurationList section */
++ 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "iPhoneNetSlave" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 1D6058940D05DD3E006BFB54 /* Debug */,
++ 1D6058950D05DD3E006BFB54 /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4B0772350F54018C000DC657 /* Build configuration list for PBXNativeTarget "iPhoneNetMaster" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4B0772360F54018C000DC657 /* Debug */,
++ 4B0772370F54018C000DC657 /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4B1A94130F49BDFF00D3626B /* Build configuration list for PBXNativeTarget "libjacknet" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4B1A94110F49BDE100D3626B /* Debug */,
++ 4B1A94120F49BDE100D3626B /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4B4146AD10BD3C4300C12F0C /* Build configuration list for PBXNativeTarget "iPhoneFaustNet Distribution" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4B4146AE10BD3C4300C12F0C /* Debug */,
++ 4B4146AF10BD3C4300C12F0C /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4BCB37CB112D647C008C7BC1 /* Build configuration list for PBXNativeTarget "iPhoneFaust" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4BCB37CC112D647C008C7BC1 /* Debug */,
++ 4BCB37CD112D647C008C7BC1 /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4BCF75EF10BC2FD90082C526 /* Build configuration list for PBXNativeTarget "iPhoneThruNet" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4BCF75F010BC2FD90082C526 /* Debug */,
++ 4BCF75F110BC2FD90082C526 /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4BDFCD54113DB6B700D77992 /* Build configuration list for PBXNativeTarget "iPhoneNetSlaveLib" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4BDFCD55113DB6B700D77992 /* Debug */,
++ 4BDFCD56113DB6B700D77992 /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ 4BFF45740F4D5D9700106083 /* Build configuration list for PBXNativeTarget "iPhoneFaustNet" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4BFF45750F4D5D9700106083 /* Debug */,
++ 4BFF45760F4D5D9700106083 /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "iPhoneNet" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ C01FCF4F08A954540054247B /* Debug */,
++ C01FCF5008A954540054247B /* Release */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Release;
++ };
++/* End XCConfigurationList section */
++ };
++ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
++}
+--- /dev/null
++++ b/macosx/iphone/main_master.mm
+@@ -0,0 +1,155 @@
++//
++// main.m
++// iPhoneNet
++//
++// Created by Stéphane LETZ on 16/02/09.
++// Copyright Grame 2009. All rights reserved.
++//
++
++#import <UIKit/UIKit.h>
++#include <jack/net.h>
++
++#include "TiPhoneCoreAudioRenderer.h"
++
++#define NUM_INPUT 2
++#define NUM_OUTPUT 2
++
++jack_net_master_t* net;
++jack_adapter_t* adapter;
++
++float** audio_input_buffer = NULL;
++float** audio_output_buffer = NULL;
++
++int buffer_size = 1024;
++int sample_rate = 22050;
++//int sample_rate = 32000;
++
++jack_master_t request = { -1, -1, -1, -1, buffer_size, sample_rate, "master" };
++jack_slave_t result;
++
++static void MixAudio(float** dst, float** src1, float** src2, int channels, int buffer_size)
++{
++ for (int chan = 0; chan < channels; chan++) {
++ for (int frame = 0; frame < buffer_size; frame++) {
++ dst[chan][frame] = src1[chan][frame] + src2[chan][frame];
++ }
++ }
++}
++
++static void MasterAudioCallback(int frames, float** inputs, float** outputs, void* arg)
++{
++ int i;
++
++ // Copy from iPod input to network buffers
++ for (i = 0; i < result.audio_input; i++) {
++ memcpy(audio_input_buffer[i], inputs[i], buffer_size * sizeof(float));
++ }
++
++ /*
++ // Copy from network out buffers to network in buffers (audio thru)
++ for (i = 0; i < result.audio_input; i++) {
++ memcpy(audio_input_buffer[i], audio_output_buffer[i], buffer_size * sizeof(float));
++ }
++ */
++
++ // Mix iPod input and network in buffers to network out buffers
++ //MixAudio(audio_input_buffer, inputs, audio_output_buffer, result.audio_input, buffer_size);
++
++ // Send network buffers
++ if (jack_net_master_send(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) {
++ printf("jack_net_master_send error..\n");
++ }
++
++ // Recv network buffers
++ if (jack_net_master_recv(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) {
++ printf("jack_net_master_recv error..\n");
++ }
++
++ // Copy from network buffers to iPod output
++ for (i = 0; i < result.audio_output; i++) {
++ memcpy(outputs[i], audio_output_buffer[i], buffer_size * sizeof(float));
++ }
++}
++
++int main(int argc, char *argv[]) {
++
++ NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
++ int i;
++
++ if ((net = jack_net_master_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPhone", &request, &result)) == 0) {
++ printf("jack_net_master_open error..\n");
++ return -1;
++ }
++
++ TiPhoneCoreAudioRenderer audio_device(result.audio_input, result.audio_output);
++
++ // Allocate buffers
++ if (result.audio_input > 0) {
++ audio_input_buffer = (float**)calloc(result.audio_input, sizeof(float*));
++ for (i = 0; i < result.audio_input; i++) {
++ audio_input_buffer[i] = (float*)(calloc(buffer_size, sizeof(float)));
++ }
++ }
++
++ if (result.audio_output > 0) {
++ audio_output_buffer = (float**)calloc(result.audio_output, sizeof(float*));
++ for (i = 0; i < result.audio_output; i++) {
++ audio_output_buffer[i] = (float*)(calloc(buffer_size, sizeof(float)));
++ }
++ }
++
++ if (audio_device.Open(buffer_size, sample_rate) < 0) {
++ return -1;
++ }
++
++ audio_device.SetAudioCallback(MasterAudioCallback, NULL);
++
++ if (audio_device.Start() < 0) {
++ return -1;
++ }
++
++ /*
++ // Quite brutal way, the application actually does not start completely, the netjack audio processing loop is used instead...
++ // Run until interrupted
++
++ int wait_usec = (unsigned long)((((float)buffer_size) / ((float)sample_rate)) * 1000000.0f);
++
++ while (1) {
++
++ // Copy input to output
++ for (i = 0; i < result.audio_input; i++) {
++ memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float));
++ }
++
++ if (jack_net_master_send(net, result.audio_output, audio_output_buffer, 0, NULL) < 0) {
++ printf("jack_net_master_send error..\n");
++ }
++
++ if (jack_net_master_recv(net, result.audio_input, audio_input_buffer, 0, NULL) < 0) {
++ printf("jack_net_master_recv error..\n");
++ }
++ usleep(wait_usec);
++ };
++ */
++
++ int retVal = UIApplicationMain(argc, argv, nil, nil);
++
++ audio_device.Stop();
++ audio_device.Close();
++
++ // Wait for application end
++ jack_net_master_close(net);
++
++ for (i = 0; i < result.audio_input; i++) {
++ free(audio_input_buffer[i]);
++ }
++ free(audio_input_buffer);
++
++ for (i = 0; i < result.audio_output; i++) {
++ free(audio_output_buffer[i]);
++ }
++ free(audio_output_buffer);
++
++ [pool release];
++ return retVal;
++}
+--- /dev/null
++++ b/macosx/iphone/main_slave.mm
+@@ -0,0 +1,114 @@
++//
++// main.m
++// iPhoneNet
++//
++// Created by Stéphane LETZ on 16/02/09.
++// Copyright Grame 2009. All rights reserved.
++//
++
++#import <UIKit/UIKit.h>
++#include <jack/net.h>
++
++#include "TiPhoneCoreAudioRenderer.h"
++
++#define NUM_INPUT 0
++#define NUM_OUTPUT 2
++
++jack_net_slave_t* net = NULL;
++jack_adapter_t* adapter = NULL;
++
++int buffer_size;
++int sample_rate;
++
++static int net_process(jack_nframes_t buffer_size,
++ int audio_input,
++ float** audio_input_buffer,
++ int midi_input,
++ void** midi_input_buffer,
++ int audio_output,
++ float** audio_output_buffer,
++ int midi_output,
++ void** midi_output_buffer,
++ void* data)
++{
++ jack_adapter_pull_and_push(adapter, audio_output_buffer, audio_input_buffer, buffer_size);
++
++ // Process input, produce output
++ if (audio_input == audio_output) {
++ // Copy net input to net output
++ for (int i = 0; i < audio_input; i++) {
++ memcpy(audio_output_buffer[i], audio_input_buffer[i], buffer_size * sizeof(float));
++ }
++ }
++ return 0;
++}
++
++static void net_shutdown(void *arg)
++{
++ if (adapter)
++ jack_flush_adapter(adapter);
++}
++
++static void SlaveAudioCallback(int frames, float** inputs, float** outputs, void* arg)
++{
++ jack_adapter_push_and_pull(adapter, inputs, outputs, frames);
++}
++
++//http://www.securityfocus.com/infocus/1884
++
++#define WIFI_MTU 1500
++
++int main(int argc, char *argv[]) {
++
++ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
++
++ jack_slave_t request = { NUM_OUTPUT, NUM_INPUT, 0, 0, WIFI_MTU, -1, JackCeltEncoder, 128, 2 };
++ jack_master_t result;
++
++ //if ((net = jack_net_slave_open("169.254.112.119", DEFAULT_PORT, "iPhone", &request, &result)) == 0) {
++ if ((net = jack_net_slave_open(DEFAULT_MULTICAST_IP, DEFAULT_PORT, "iPod", &request, &result)) == 0) {
++ printf("jack_net_slave_open error...\n");
++ return -1;
++ }
++
++ if ((adapter = jack_create_adapter(NUM_INPUT,
++ NUM_OUTPUT,
++ result.buffer_size,
++ result.sample_rate,
++ result.buffer_size,
++ result.sample_rate)) == 0) {
++ return -1;
++ }
++
++ TiPhoneCoreAudioRenderer audio_device(NUM_INPUT, NUM_OUTPUT);
++
++ jack_set_net_slave_process_callback(net, net_process, NULL);
++ jack_set_net_slave_shutdown_callback(net, net_shutdown, NULL);
++
++ if (jack_net_slave_activate(net) != 0) {
++ printf("Cannot activate slave client\n");
++ return -1;
++ }
++
++ if (audio_device.Open(result.buffer_size, result.sample_rate) < 0) {
++ return -1;
++ }
++
++ audio_device.SetAudioCallback(SlaveAudioCallback, NULL);
++
++ if (audio_device.Start() < 0) {
++ return -1;
++ }
++
++ int retVal = UIApplicationMain(argc, argv, nil, nil);
++ [pool release];
++
++ audio_device.Stop();
++ audio_device.Close();
++
++ // Wait for application end
++ jack_net_slave_deactivate(net);
++ jack_net_slave_close(net);
++ jack_destroy_adapter(adapter);
++ return retVal;
++}
+--- /dev/null
++++ b/macosx/iphone/MainWindow.xib
+@@ -0,0 +1,440 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
++ <data>
++ <int key="IBDocument.SystemTarget">528</int>
++ <string key="IBDocument.SystemVersion">10C540</string>
++ <string key="IBDocument.InterfaceBuilderVersion">740</string>
++ <string key="IBDocument.AppKitVersion">1038.25</string>
++ <string key="IBDocument.HIToolboxVersion">458.00</string>
++ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
++ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
++ <string key="NS.object.0">62</string>
++ </object>
++ <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <integer value="2"/>
++ </object>
++ <object class="NSArray" key="IBDocument.PluginDependencies">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
++ </object>
++ <object class="NSMutableDictionary" key="IBDocument.Metadata">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="NSArray" key="dict.sortedKeys" id="0">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ </object>
++ <object class="NSMutableArray" key="dict.values">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ </object>
++ </object>
++ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBProxyObject" id="841351856">
++ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
++ </object>
++ <object class="IBProxyObject" id="427554174">
++ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
++ </object>
++ <object class="IBUICustomObject" id="664661524"/>
++ <object class="IBUIWindow" id="380026005">
++ <reference key="NSNextResponder"/>
++ <int key="NSvFlags">1316</int>
++ <object class="NSMutableArray" key="NSSubviews">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBUILabel" id="622412730">
++ <reference key="NSNextResponder" ref="380026005"/>
++ <int key="NSvFlags">1316</int>
++ <string key="NSFrame">{{25, 40}, {267, 21}}</string>
++ <reference key="NSSuperview" ref="380026005"/>
++ <bool key="IBUIOpaque">NO</bool>
++ <bool key="IBUIClipsSubviews">YES</bool>
++ <bool key="IBUIUserInteractionEnabled">NO</bool>
++ <string key="IBUIText">NetJack : client on JACK server </string>
++ <object class="NSFont" key="IBUIFont">
++ <string key="NSName">Helvetica-Bold</string>
++ <double key="NSSize">17</double>
++ <int key="NSfFlags">16</int>
++ </object>
++ <object class="NSColor" key="IBUITextColor">
++ <int key="NSColorSpace">1</int>
++ <bytes key="NSRGB">MCAwIDAAA</bytes>
++ </object>
++ <nil key="IBUIHighlightedColor"/>
++ <int key="IBUIBaselineAdjustment">1</int>
++ <float key="IBUIMinimumFontSize">10</float>
++ </object>
++ </object>
++ <object class="NSPSMatrix" key="NSFrameMatrix"/>
++ <string key="NSFrameSize">{320, 480}</string>
++ <reference key="NSSuperview"/>
++ <object class="NSColor" key="IBUIBackgroundColor">
++ <int key="NSColorSpace">1</int>
++ <bytes key="NSRGB">MSAxIDEAA</bytes>
++ </object>
++ <bool key="IBUIOpaque">NO</bool>
++ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
++ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
++ </object>
++ </object>
++ <object class="IBObjectContainer" key="IBDocument.Objects">
++ <object class="NSMutableArray" key="connectionRecords">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBConnectionRecord">
++ <object class="IBCocoaTouchOutletConnection" key="connection">
++ <string key="label">delegate</string>
++ <reference key="source" ref="841351856"/>
++ <reference key="destination" ref="664661524"/>
++ </object>
++ <int key="connectionID">4</int>
++ </object>
++ <object class="IBConnectionRecord">
++ <object class="IBCocoaTouchOutletConnection" key="connection">
++ <string key="label">window</string>
++ <reference key="source" ref="664661524"/>
++ <reference key="destination" ref="380026005"/>
++ </object>
++ <int key="connectionID">5</int>
++ </object>
++ </object>
++ <object class="IBMutableOrderedSet" key="objectRecords">
++ <object class="NSArray" key="orderedObjects">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBObjectRecord">
++ <int key="objectID">0</int>
++ <reference key="object" ref="0"/>
++ <reference key="children" ref="1000"/>
++ <nil key="parent"/>
++ </object>
++ <object class="IBObjectRecord">
++ <int key="objectID">2</int>
++ <reference key="object" ref="380026005"/>
++ <object class="NSMutableArray" key="children">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <reference ref="622412730"/>
++ </object>
++ <reference key="parent" ref="0"/>
++ </object>
++ <object class="IBObjectRecord">
++ <int key="objectID">-1</int>
++ <reference key="object" ref="841351856"/>
++ <reference key="parent" ref="0"/>
++ <string key="objectName">File's Owner</string>
++ </object>
++ <object class="IBObjectRecord">
++ <int key="objectID">3</int>
++ <reference key="object" ref="664661524"/>
++ <reference key="parent" ref="0"/>
++ </object>
++ <object class="IBObjectRecord">
++ <int key="objectID">-2</int>
++ <reference key="object" ref="427554174"/>
++ <reference key="parent" ref="0"/>
++ </object>
++ <object class="IBObjectRecord">
++ <int key="objectID">10</int>
++ <reference key="object" ref="622412730"/>
++ <reference key="parent" ref="380026005"/>
++ </object>
++ </object>
++ </object>
++ <object class="NSMutableDictionary" key="flattenedProperties">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="NSArray" key="dict.sortedKeys">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <string>-1.CustomClassName</string>
++ <string>-2.CustomClassName</string>
++ <string>10.IBPluginDependency</string>
++ <string>2.IBAttributePlaceholdersKey</string>
++ <string>2.IBEditorWindowLastContentRect</string>
++ <string>2.IBPluginDependency</string>
++ <string>2.IBUserGuides</string>
++ <string>3.CustomClassName</string>
++ <string>3.IBPluginDependency</string>
++ </object>
++ <object class="NSMutableArray" key="dict.values">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <string>UIApplication</string>
++ <string>UIResponder</string>
++ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
++ <object class="NSMutableDictionary">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <reference key="dict.sortedKeys" ref="0"/>
++ <object class="NSMutableArray" key="dict.values">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ </object>
++ </object>
++ <string>{{366, 320}, {320, 480}}</string>
++ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
++ <object class="NSMutableArray">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBUserGuide">
++ <reference key="view" ref="380026005"/>
++ <double key="location">153.5</double>
++ <int key="affinity">0</int>
++ </object>
++ </object>
++ <string>iPhoneNetAppDelegate</string>
++ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
++ </object>
++ </object>
++ <object class="NSMutableDictionary" key="unlocalizedProperties">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <reference key="dict.sortedKeys" ref="0"/>
++ <object class="NSMutableArray" key="dict.values">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ </object>
++ </object>
++ <nil key="activeLocalization"/>
++ <object class="NSMutableDictionary" key="localizations">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <reference key="dict.sortedKeys" ref="0"/>
++ <object class="NSMutableArray" key="dict.values">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ </object>
++ </object>
++ <nil key="sourceID"/>
++ <int key="maxID">11</int>
++ </object>
++ <object class="IBClassDescriber" key="IBDocument.Classes">
++ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBPartialClassDescription">
++ <string key="className">iPhoneNetAppDelegate</string>
++ <string key="superclassName">NSObject</string>
++ <object class="NSMutableDictionary" key="outlets">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="NSArray" key="dict.sortedKeys">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <string>navigationController</string>
++ <string>window</string>
++ </object>
++ <object class="NSMutableArray" key="dict.values">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <string>UINavigationController</string>
++ <string>UIWindow</string>
++ </object>
++ </object>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBProjectSource</string>
++ <string key="minorKey">iPhoneNetAppDelegate.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">iPhoneNetAppDelegate</string>
++ <string key="superclassName">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBUserSource</string>
++ <string key="minorKey"/>
++ </object>
++ </object>
++ </object>
++ <object class="NSMutableArray" key="referencedPartialClassDescriptionsV3.2+">
++ <bool key="EncodedWithXMLCoder">YES</bool>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSError.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSFileManager.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSKeyValueCoding.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSKeyValueObserving.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSKeyedArchiver.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSNetServices.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSObject.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSPort.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSRunLoop.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSStream.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSThread.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSURL.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSURLConnection.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">Foundation.framework/Headers/NSXMLParser.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UINibLoading.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIApplication</string>
++ <string key="superclassName">UIResponder</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UIApplication.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UILabel</string>
++ <string key="superclassName">UIView</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UILabel.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UINavigationController</string>
++ <string key="superclassName">UIViewController</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier" id="325457853">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UINavigationController.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIResponder</string>
++ <string key="superclassName">NSObject</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UIResponder.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UISearchBar</string>
++ <string key="superclassName">UIView</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UISearchBar.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIView</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UITextField.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIView</string>
++ <string key="superclassName">UIResponder</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UIView.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIViewController</string>
++ <reference key="sourceIdentifier" ref="325457853"/>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIViewController</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UITabBarController.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIViewController</string>
++ <string key="superclassName">UIResponder</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UIViewController.h</string>
++ </object>
++ </object>
++ <object class="IBPartialClassDescription">
++ <string key="className">UIWindow</string>
++ <string key="superclassName">UIView</string>
++ <object class="IBClassDescriptionSource" key="sourceIdentifier">
++ <string key="majorKey">IBFrameworkSource</string>
++ <string key="minorKey">UIKit.framework/Headers/UIWindow.h</string>
++ </object>
++ </object>
++ </object>
++ </object>
++ <int key="IBDocument.localizationMode">0</int>
++ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies">
++ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
++ <integer value="528" key="NS.object.0"/>
++ </object>
++ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults">
++ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS</string>
++ <integer value="544" key="NS.object.0"/>
++ </object>
++ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
++ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
++ <integer value="3000" key="NS.object.0"/>
++ </object>
++ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
++ <string key="IBDocument.LastKnownRelativeProjectPath">iPhoneNet.xcodeproj</string>
++ <int key="IBDocument.defaultPropertyAccessControl">3</int>
++ <string key="IBCocoaTouchPluginVersion">3.1</string>
++ </data>
++</archive>
+--- a/macosx/JackCompilerDeps_os.h
++++ b/macosx/JackCompilerDeps_os.h
+@@ -23,6 +23,8 @@
+ #include "JackConstants.h"
+
+ #if __GNUC__
++ #define PRE_PACKED_STRUCTURE
++
+ #ifndef POST_PACKED_STRUCTURE
+ /* POST_PACKED_STRUCTURE needs to be a macro which
+ expands into a compiler directive. The directive must
+@@ -38,17 +40,17 @@
+ #endif
+ #endif
+ #define MEM_ALIGN(x,y) x __attribute__((aligned(y)))
+- #define EXPORT __attribute__((visibility("default")))
++ #define LIB_EXPORT __attribute__((visibility("default")))
+ #ifdef SERVER_SIDE
+ #define SERVER_EXPORT __attribute__((visibility("default")))
+ #else
+- #define SERVER_EXPORT
++ #define SERVER_EXPORT
+ #endif
+ #else
+ #define MEM_ALIGN(x,y) x
+- #define EXPORT
++ #define LIB_EXPORT
+ #define SERVER_EXPORT
+- /* Add other things here for non-gcc platforms for POST_PACKED_STRUCTURE */
++ /* Add other things here for non-gcc platforms for PRE and POST_PACKED_STRUCTURE */
+ #endif
+
+ #endif
+--- a/macosx/Jackdmp.xcodeproj/project.pbxproj
++++ b/macosx/Jackdmp.xcodeproj/project.pbxproj
+@@ -15,6 +15,7 @@
+ dependencies = (
+ 4B35C6800D4733B9000DE7AE /* PBXTargetDependency */,
+ 4B35C6820D4733B9000DE7AE /* PBXTargetDependency */,
++ 4BB492A71372A393005F2601 /* PBXTargetDependency */,
+ 4B35C67E0D4733B9000DE7AE /* PBXTargetDependency */,
+ 4B35C6AC0D4733B9000DE7AE /* PBXTargetDependency */,
+ 4B35C6B00D4733B9000DE7AE /* PBXTargetDependency */,
+@@ -50,6 +51,7 @@
+ 4B66550E127C356E00753A79 /* PBXTargetDependency */,
+ 4B38120313269CCB00C61B14 /* PBXTargetDependency */,
+ 4B8F16FC1329169F0002AD73 /* PBXTargetDependency */,
++ 4B20220C133A9C370019E213 /* PBXTargetDependency */,
+ );
+ name = "All Universal 32/64 bits";
+ productName = All;
+@@ -107,6 +109,12 @@
+ /* Begin PBXBuildFile section */
+ 4B0A28ED0D520852002EFF74 /* tw.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0A28EC0D520852002EFF74 /* tw.c */; };
+ 4B0A29260D52108E002EFF74 /* tw.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B0A28EC0D520852002EFF74 /* tw.c */; };
++ 4B193991133F321500547810 /* JackFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193990133F321500547810 /* JackFilters.h */; };
++ 4B193992133F321500547810 /* JackFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193990133F321500547810 /* JackFilters.h */; };
++ 4B193993133F321500547810 /* JackFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193990133F321500547810 /* JackFilters.h */; };
++ 4B193994133F321500547810 /* JackFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193990133F321500547810 /* JackFilters.h */; };
++ 4B193995133F321500547810 /* JackFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193990133F321500547810 /* JackFilters.h */; };
++ 4B193996133F321500547810 /* JackFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193990133F321500547810 /* JackFilters.h */; };
+ 4B19B3130E2362E800DD4A82 /* JackAudioAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3060E2362E700DD4A82 /* JackAudioAdapter.cpp */; };
+ 4B19B3140E2362E800DD4A82 /* JackAudioAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19B3070E2362E700DD4A82 /* JackAudioAdapter.h */; };
+ 4B19B3150E2362E800DD4A82 /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3080E2362E700DD4A82 /* JackAudioAdapterInterface.cpp */; };
+@@ -114,6 +122,13 @@
+ 4B19B31B0E2362E800DD4A82 /* JackLibSampleRateResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B30E0E2362E700DD4A82 /* JackLibSampleRateResampler.cpp */; };
+ 4B19B31C0E2362E800DD4A82 /* JackLibSampleRateResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19B30F0E2362E700DD4A82 /* JackLibSampleRateResampler.h */; };
+ 4B19B31F0E2362E800DD4A82 /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3120E2362E700DD4A82 /* JackResampler.cpp */; };
++ 4B20220A133A9C1C0019E213 /* midi_latency_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B202209133A9C1C0019E213 /* midi_latency_test.c */; };
++ 4B21794F13E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */; };
++ 4B21795013E2EEA60095B3E5 /* JackTimedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */; };
++ 4B21795113E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */; };
++ 4B21795213E2EEA60095B3E5 /* JackTimedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */; };
++ 4B21795313E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */; };
++ 4B21795413E2EEA60095B3E5 /* JackTimedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */; };
+ 4B2209E112F6BBF300E5DC26 /* JackSocketServerChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B30E703B8D0066E42F /* JackSocketServerChannel.cpp */; };
+ 4B2209E212F6BBF400E5DC26 /* JackSocketServerChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B40E703B8D0066E42F /* JackSocketServerChannel.h */; };
+ 4B2209E312F6BBF500E5DC26 /* JackSocketServerNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B50E703B8D0066E42F /* JackSocketServerNotifyChannel.cpp */; };
+@@ -139,12 +154,8 @@
+ 4B32253510A3173D00838A8E /* netjack_packet.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224EC10A315C400838A8E /* netjack_packet.c */; };
+ 4B32253610A3173E00838A8E /* netjack_packet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3224ED10A315C400838A8E /* netjack_packet.h */; };
+ 4B32256410A318E300838A8E /* netsource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B32256310A318E300838A8E /* netsource.c */; };
+- 4B32256B10A318FA00838A8E /* netjack.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224EE10A315C400838A8E /* netjack.c */; };
+- 4B32256C10A318FB00838A8E /* netjack.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3224EF10A315C400838A8E /* netjack.h */; };
+ 4B32256D10A318FC00838A8E /* netjack_packet.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224EC10A315C400838A8E /* netjack_packet.c */; };
+ 4B32256E10A318FD00838A8E /* netjack_packet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3224ED10A315C400838A8E /* netjack_packet.h */; };
+- 4B32257D10A3195700838A8E /* netjack.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224EE10A315C400838A8E /* netjack.c */; };
+- 4B32257E10A3195800838A8E /* netjack.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3224EF10A315C400838A8E /* netjack.h */; };
+ 4B32257F10A3195900838A8E /* netjack_packet.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3224EC10A315C400838A8E /* netjack_packet.c */; };
+ 4B32258010A3195A00838A8E /* netjack_packet.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B3224ED10A315C400838A8E /* netjack_packet.h */; };
+ 4B32258110A3195B00838A8E /* netsource.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B32256310A318E300838A8E /* netsource.c */; };
+@@ -317,6 +328,38 @@
+ 4B363F230DEB0AB0001F72D9 /* monitor_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F220DEB0AB0001F72D9 /* monitor_client.c */; };
+ 4B363F3E0DEB0C31001F72D9 /* showtime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F3D0DEB0C31001F72D9 /* showtime.c */; };
+ 4B363F760DEB0D7D001F72D9 /* impulse_grabber.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B363F750DEB0D7D001F72D9 /* impulse_grabber.c */; };
++ 4B370A24133DD7E300237B68 /* JackCoreMidiInputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A14133DD7E200237B68 /* JackCoreMidiInputPort.cpp */; };
++ 4B370A25133DD7E300237B68 /* JackCoreMidiInputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A15133DD7E200237B68 /* JackCoreMidiInputPort.h */; };
++ 4B370A26133DD7E300237B68 /* JackCoreMidiOutputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A16133DD7E200237B68 /* JackCoreMidiOutputPort.cpp */; };
++ 4B370A27133DD7E300237B68 /* JackCoreMidiOutputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A17133DD7E200237B68 /* JackCoreMidiOutputPort.h */; };
++ 4B370A28133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A18133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.cpp */; };
++ 4B370A29133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A19133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.h */; };
++ 4B370A2A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A1A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp */; };
++ 4B370A2B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A1B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h */; };
++ 4B370A2C133DD7E300237B68 /* JackCoreMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A1C133DD7E300237B68 /* JackCoreMidiPort.cpp */; };
++ 4B370A2D133DD7E300237B68 /* JackCoreMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A1D133DD7E300237B68 /* JackCoreMidiPort.h */; };
++ 4B370A2E133DD7E300237B68 /* JackCoreMidiUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A1E133DD7E300237B68 /* JackCoreMidiUtil.cpp */; };
++ 4B370A2F133DD7E300237B68 /* JackCoreMidiUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A1F133DD7E300237B68 /* JackCoreMidiUtil.h */; };
++ 4B370A30133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A20133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp */; };
++ 4B370A31133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A21133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h */; };
++ 4B370A32133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A22133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp */; };
++ 4B370A33133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A23133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h */; };
++ 4B370A34133DD7E300237B68 /* JackCoreMidiInputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A14133DD7E200237B68 /* JackCoreMidiInputPort.cpp */; };
++ 4B370A35133DD7E300237B68 /* JackCoreMidiInputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A15133DD7E200237B68 /* JackCoreMidiInputPort.h */; };
++ 4B370A36133DD7E300237B68 /* JackCoreMidiOutputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A16133DD7E200237B68 /* JackCoreMidiOutputPort.cpp */; };
++ 4B370A37133DD7E300237B68 /* JackCoreMidiOutputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A17133DD7E200237B68 /* JackCoreMidiOutputPort.h */; };
++ 4B370A38133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A18133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.cpp */; };
++ 4B370A39133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A19133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.h */; };
++ 4B370A3A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A1A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp */; };
++ 4B370A3B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A1B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h */; };
++ 4B370A3C133DD7E300237B68 /* JackCoreMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A1C133DD7E300237B68 /* JackCoreMidiPort.cpp */; };
++ 4B370A3D133DD7E300237B68 /* JackCoreMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A1D133DD7E300237B68 /* JackCoreMidiPort.h */; };
++ 4B370A3E133DD7E300237B68 /* JackCoreMidiUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A1E133DD7E300237B68 /* JackCoreMidiUtil.cpp */; };
++ 4B370A3F133DD7E300237B68 /* JackCoreMidiUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A1F133DD7E300237B68 /* JackCoreMidiUtil.h */; };
++ 4B370A40133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A20133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp */; };
++ 4B370A41133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A21133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h */; };
++ 4B370A42133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B370A22133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp */; };
++ 4B370A43133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B370A23133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h */; };
+ 4B3811FB13269C8300C61B14 /* latent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3811FA13269C8300C61B14 /* latent_client.c */; };
+ 4B3811FC13269C8300C61B14 /* latent_client.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B3811FA13269C8300C61B14 /* latent_client.c */; };
+ 4B3814201327AA6800C61B14 /* iodelay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B38141F1327AA6800C61B14 /* iodelay.cpp */; };
+@@ -397,6 +440,20 @@
+ 4B47ACCE10B5890100469C67 /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF5FBC80E878D24003D2374 /* JackMachTime.c */; };
+ 4B47ACCF10B5890100469C67 /* JackProcessSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BECB2F30F4451C10091B70A /* JackProcessSync.cpp */; };
+ 4B47ACD210B5890100469C67 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BCC87950D57168300A7FEB1 /* Accelerate.framework */; };
++ 4B49D44214865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; };
++ 4B49D44314865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44414865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; };
++ 4B49D44514865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44614865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; };
++ 4B49D44714865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44814865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; };
++ 4B49D44914865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44A14865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; };
++ 4B49D44B14865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44C14865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; };
++ 4B49D44D14865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44E14865F22003390F8 /* net.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44014865F22003390F8 /* net.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B49D44F14865F22003390F8 /* session.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B49D44114865F22003390F8 /* session.h */; };
+ 4B4CA9750E02CF9600F4BFDA /* JackRestartThreadedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4CA9730E02CF9600F4BFDA /* JackRestartThreadedDriver.h */; };
+ 4B4CA9760E02CF9600F4BFDA /* JackRestartThreadedDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B4CA9740E02CF9600F4BFDA /* JackRestartThreadedDriver.cpp */; };
+ 4B4CA9770E02CF9600F4BFDA /* JackRestartThreadedDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4CA9730E02CF9600F4BFDA /* JackRestartThreadedDriver.h */; };
+@@ -553,12 +610,57 @@
+ 4B6C738A0CC60A85001AFFD4 /* thread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6C737D0CC60A6D001AFFD4 /* thread.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4B6C738B0CC60A86001AFFD4 /* transport.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6C737E0CC60A6D001AFFD4 /* transport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4B6F7AEE0CD0CDBD00F48A9D /* JackEngineControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6F7AEC0CD0CDBD00F48A9D /* JackEngineControl.cpp */; };
++ 4B6FE13A13DDABE000B4B943 /* JackSocketServerNotifyChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B60E703B8D0066E42F /* JackSocketServerNotifyChannel.h */; };
++ 4B6FE13B13DDABE700B4B943 /* JackSocketServerNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B50E703B8D0066E42F /* JackSocketServerNotifyChannel.cpp */; };
++ 4B6FE13C13DDABF100B4B943 /* JackSocketServerChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B40E703B8D0066E42F /* JackSocketServerChannel.h */; };
++ 4B6FE13D13DDABFA00B4B943 /* JackSocketServerChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B30E703B8D0066E42F /* JackSocketServerChannel.cpp */; };
++ 4B6FE13E13DDAC0500B4B943 /* JackSocketNotifyChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6B20E703B8D0066E42F /* JackSocketNotifyChannel.h */; };
++ 4B6FE13F13DDAC0C00B4B943 /* JackSocketNotifyChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B10E703B8D0066E42F /* JackSocketNotifyChannel.cpp */; };
++ 4B6FE14413DDAC4700B4B943 /* JackSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AD0E703B8D0066E42F /* JackSocket.cpp */; };
++ 4B6FE14513DDAC4C00B4B943 /* JackSocket.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6AE0E703B8D0066E42F /* JackSocket.h */; };
++ 4B6FE14D13DDACCC00B4B943 /* JackMidiAsyncQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193931133F311400547810 /* JackMidiAsyncQueue.cpp */; };
++ 4B6FE14E13DDACD200B4B943 /* JackMidiAsyncQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193932133F311400547810 /* JackMidiAsyncQueue.h */; };
++ 4B6FE15313DDACEF00B4B943 /* JackMidiBufferWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193968133F319000547810 /* JackMidiBufferWriteQueue.cpp */; };
++ 4B6FE15413DDACF300B4B943 /* JackMidiBufferWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193969133F319000547810 /* JackMidiBufferWriteQueue.h */; };
++ 4B6FE15B13DDAD3D00B4B943 /* JackMidiWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19397A133F31CB00547810 /* JackMidiWriteQueue.h */; };
++ 4B6FE15C13DDAD4600B4B943 /* JackMidiWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193979133F31CB00547810 /* JackMidiWriteQueue.cpp */; };
++ 4B6FE15D13DDAD4E00B4B943 /* JackMidiUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193978133F31CB00547810 /* JackMidiUtil.h */; };
++ 4B6FE15E13DDAD5300B4B943 /* JackMidiUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193977133F31CB00547810 /* JackMidiUtil.cpp */; };
++ 4B6FE15F13DDAD5900B4B943 /* JackMidiSendQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193976133F31CB00547810 /* JackMidiSendQueue.h */; };
++ 4B6FE16013DDAD5F00B4B943 /* JackMidiSendQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193975133F31CB00547810 /* JackMidiSendQueue.cpp */; };
++ 4B6FE16113DDAD6600B4B943 /* JackMidiReceiveQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193974133F31CB00547810 /* JackMidiReceiveQueue.h */; };
++ 4B6FE16213DDAD6F00B4B943 /* JackMidiReceiveQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193973133F31CB00547810 /* JackMidiReceiveQueue.cpp */; };
++ 4B6FE16313DDAD7700B4B943 /* JackMidiReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193946133F315200547810 /* JackMidiReadQueue.h */; };
++ 4B6FE16413DDAD7F00B4B943 /* JackMidiReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193945133F315200547810 /* JackMidiReadQueue.cpp */; };
++ 4B6FE16513DDAD8800B4B943 /* JackMidiBufferReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19395E133F317300547810 /* JackMidiBufferReadQueue.h */; };
++ 4B6FE16613DDAD8F00B4B943 /* JackMidiBufferReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19395D133F317300547810 /* JackMidiBufferReadQueue.cpp */; };
++ 4B6FE16713DDAD9700B4B943 /* JackMidiAsyncWaitQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19393C133F313000547810 /* JackMidiAsyncWaitQueue.h */; };
++ 4B6FE16813DDAD9F00B4B943 /* JackMidiAsyncWaitQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19393B133F313000547810 /* JackMidiAsyncWaitQueue.cpp */; };
+ 4B80D7E80BA0D17400F035BB /* JackMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */; };
+ 4B80D7E90BA0D17400F035BB /* JackMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */; };
+ 4B80D7EA0BA0D17400F035BB /* JackMidiAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E70BA0D17400F035BB /* JackMidiAPI.cpp */; };
+ 4B80D7EB0BA0D17400F035BB /* JackMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */; };
+ 4B80D7EC0BA0D17400F035BB /* JackMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */; };
+ 4B80D7ED0BA0D17400F035BB /* JackMidiAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E70BA0D17400F035BB /* JackMidiAPI.cpp */; };
++ 4B8692D61371DB4700D2D11B /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BCC87950D57168300A7FEB1 /* Accelerate.framework */; };
++ 4B8692F81371DC5200D2D11B /* JackAudioAdapterInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3080E2362E700DD4A82 /* JackAudioAdapterInterface.cpp */; };
++ 4B8692FA1371DC6300D2D11B /* JackAudioAdapterInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19B3090E2362E700DD4A82 /* JackAudioAdapterInterface.h */; };
++ 4B8692FB1371DC7100D2D11B /* JackGlobals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */; };
++ 4B8692FD1371DC8A00D2D11B /* JackGlobals.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BFB73F608AD291A00DB99B8 /* JackGlobals.h */; };
++ 4B8692FE1371DC9700D2D11B /* JackMachThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFB741E08AD2B9900DB99B8 /* JackMachThread.cpp */; };
++ 4B86930D1371DCB000D2D11B /* JackMachThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BFB741F08AD2B9900DB99B8 /* JackMachThread.h */; };
++ 4B8693141371DCCA00D2D11B /* JackMachTime.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BF5FBC80E878D24003D2374 /* JackMachTime.c */; };
++ 4B8693161371DD0A00D2D11B /* JackNetAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8693151371DD0A00D2D11B /* JackNetAPI.cpp */; };
++ 4B8693171371DD2400D2D11B /* JackNetInterface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B76C7680E5AB2DB00E2AC21 /* JackNetInterface.cpp */; };
++ 4B8693181371DD2A00D2D11B /* JackNetInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B76C7690E5AB2DB00E2AC21 /* JackNetInterface.h */; };
++ 4B8693191371DD3B00D2D11B /* JackNetTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BA222AD60DC88268001A17F4 /* JackNetTool.cpp */; };
++ 4B86931A1371DD4400D2D11B /* JackNetTool.h in Headers */ = {isa = PBXBuildFile; fileRef = BA222AD70DC88268001A17F4 /* JackNetTool.h */; };
++ 4B86931B1371DD4C00D2D11B /* JackNetUnixSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6B90E703BCC0066E42F /* JackNetUnixSocket.cpp */; };
++ 4B8693231371DD6000D2D11B /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6A20E703B2E0066E42F /* JackPosixThread.cpp */; };
++ 4B8693251371DD7E00D2D11B /* JackResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B3120E2362E700DD4A82 /* JackResampler.cpp */; };
++ 4B86932C1371DD9B00D2D11B /* ringbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B003AB008E2B2BA0060EFDC /* ringbuffer.c */; };
++ 4B86934D1371DEBA00D2D11B /* JackLibSampleRateResampler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19B30E0E2362E700DD4A82 /* JackLibSampleRateResampler.cpp */; };
++ 4B86934E1371DEBD00D2D11B /* JackLibSampleRateResampler.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19B30F0E2362E700DD4A82 /* JackLibSampleRateResampler.h */; };
+ 4B88D03B11298BEE007A87C1 /* weakjack.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B88D03911298BEE007A87C1 /* weakjack.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4B88D03C11298BEE007A87C1 /* weakmacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B88D03A11298BEE007A87C1 /* weakmacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4B88D03D11298BEE007A87C1 /* weakjack.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B88D03911298BEE007A87C1 /* weakjack.h */; settings = {ATTRIBUTES = (Public, ); }; };
+@@ -595,6 +697,42 @@
+ 4B94334A10A5E666002A187F /* systemdeps.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B94334910A5E666002A187F /* systemdeps.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4B94334B10A5E666002A187F /* systemdeps.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B94334910A5E666002A187F /* systemdeps.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4B95BCAE0D913073000F7695 /* control.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B95BCAD0D913073000F7695 /* control.h */; settings = {ATTRIBUTES = (Public, ); }; };
++ 4B97B6381344B3C100794F57 /* JackMidiAsyncQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193931133F311400547810 /* JackMidiAsyncQueue.cpp */; };
++ 4B97B6391344B3C300794F57 /* JackMidiAsyncQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193932133F311400547810 /* JackMidiAsyncQueue.h */; };
++ 4B97B63A1344B3C700794F57 /* JackMidiAsyncWaitQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19393B133F313000547810 /* JackMidiAsyncWaitQueue.cpp */; };
++ 4B97B63D1344B3EC00794F57 /* JackMidiAsyncWaitQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19393C133F313000547810 /* JackMidiAsyncWaitQueue.h */; };
++ 4B97B63E1344B3F100794F57 /* JackMidiBufferReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19395D133F317300547810 /* JackMidiBufferReadQueue.cpp */; };
++ 4B97B6411344B40C00794F57 /* JackMidiBufferReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19395E133F317300547810 /* JackMidiBufferReadQueue.h */; };
++ 4B97B6531344B41E00794F57 /* JackMidiBufferWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193968133F319000547810 /* JackMidiBufferWriteQueue.cpp */; };
++ 4B97B6541344B42400794F57 /* JackMidiBufferWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193969133F319000547810 /* JackMidiBufferWriteQueue.h */; };
++ 4B97B6561344B43600794F57 /* JackMidiReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193946133F315200547810 /* JackMidiReadQueue.h */; };
++ 4B97B6571344B43A00794F57 /* JackMidiReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193945133F315200547810 /* JackMidiReadQueue.cpp */; };
++ 4B97B6581344B43F00794F57 /* JackMidiReceiveQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193973133F31CB00547810 /* JackMidiReceiveQueue.cpp */; };
++ 4B97B6591344B44800794F57 /* JackMidiReceiveQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193974133F31CB00547810 /* JackMidiReceiveQueue.h */; };
++ 4B97B65A1344B44F00794F57 /* JackMidiSendQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193975133F31CB00547810 /* JackMidiSendQueue.cpp */; };
++ 4B97B65B1344B45600794F57 /* JackMidiSendQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193976133F31CB00547810 /* JackMidiSendQueue.h */; };
++ 4B97B65C1344B45D00794F57 /* JackMidiUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193977133F31CB00547810 /* JackMidiUtil.cpp */; };
++ 4B97B65D1344B46400794F57 /* JackMidiUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193978133F31CB00547810 /* JackMidiUtil.h */; };
++ 4B97B65E1344B46B00794F57 /* JackMidiWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193979133F31CB00547810 /* JackMidiWriteQueue.cpp */; };
++ 4B97B65F1344B47100794F57 /* JackMidiWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19397A133F31CB00547810 /* JackMidiWriteQueue.h */; };
++ 4B97B6601344B48F00794F57 /* JackMidiAsyncQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193931133F311400547810 /* JackMidiAsyncQueue.cpp */; };
++ 4B97B6611344B49500794F57 /* JackMidiAsyncQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193932133F311400547810 /* JackMidiAsyncQueue.h */; };
++ 4B97B6621344B49C00794F57 /* JackMidiAsyncWaitQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19393B133F313000547810 /* JackMidiAsyncWaitQueue.cpp */; };
++ 4B97B6631344B4A800794F57 /* JackMidiAsyncWaitQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19393C133F313000547810 /* JackMidiAsyncWaitQueue.h */; };
++ 4B97B6641344B4AE00794F57 /* JackMidiBufferReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B19395D133F317300547810 /* JackMidiBufferReadQueue.cpp */; };
++ 4B97B6651344B4B500794F57 /* JackMidiBufferReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19395E133F317300547810 /* JackMidiBufferReadQueue.h */; };
++ 4B97B6671344B4C700794F57 /* JackMidiBufferWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193969133F319000547810 /* JackMidiBufferWriteQueue.h */; };
++ 4B97B6691344B4CE00794F57 /* JackMidiBufferWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193968133F319000547810 /* JackMidiBufferWriteQueue.cpp */; };
++ 4B97B66E1344B4D500794F57 /* JackMidiReadQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193945133F315200547810 /* JackMidiReadQueue.cpp */; };
++ 4B97B66F1344B4DC00794F57 /* JackMidiReadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193946133F315200547810 /* JackMidiReadQueue.h */; };
++ 4B97B6701344B4E300794F57 /* JackMidiReceiveQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193973133F31CB00547810 /* JackMidiReceiveQueue.cpp */; };
++ 4B97B6711344B4EA00794F57 /* JackMidiReceiveQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193974133F31CB00547810 /* JackMidiReceiveQueue.h */; };
++ 4B97B6721344B4F000794F57 /* JackMidiSendQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193975133F31CB00547810 /* JackMidiSendQueue.cpp */; };
++ 4B97B6781344B50800794F57 /* JackMidiSendQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193976133F31CB00547810 /* JackMidiSendQueue.h */; };
++ 4B97B6791344B50F00794F57 /* JackMidiUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193977133F31CB00547810 /* JackMidiUtil.cpp */; };
++ 4B97B67A1344B51600794F57 /* JackMidiUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B193978133F31CB00547810 /* JackMidiUtil.h */; };
++ 4B97B67B1344B51D00794F57 /* JackMidiWriteQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B193979133F31CB00547810 /* JackMidiWriteQueue.cpp */; };
++ 4B97B67C1344B52800794F57 /* JackMidiWriteQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B19397A133F31CB00547810 /* JackMidiWriteQueue.h */; };
+ 4B9A25B50DBF8330006E9FBC /* JackError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9A25B30DBF8330006E9FBC /* JackError.cpp */; };
+ 4B9A25B60DBF8330006E9FBC /* JackError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B9A25B30DBF8330006E9FBC /* JackError.cpp */; };
+ 4B9A26010DBF8584006E9FBC /* jslist.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B9A26000DBF8584006E9FBC /* jslist.h */; settings = {ATTRIBUTES = (Public, ); }; };
+@@ -754,18 +892,6 @@
+ 4BC3B6A50E703B2E0066E42F /* JackPosixThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6A30E703B2E0066E42F /* JackPosixThread.h */; };
+ 4BC3B6A60E703B2E0066E42F /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6A20E703B2E0066E42F /* JackPosixThread.cpp */; };
+ 4BC3B6A70E703B2E0066E42F /* JackPosixThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6A30E703B2E0066E42F /* JackPosixThread.h */; };
+- 4BCBCE5D10C4FE3F00450FFE /* JackPhysicalMidiInput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCBCE5910C4FE3F00450FFE /* JackPhysicalMidiInput.cpp */; };
+- 4BCBCE5E10C4FE3F00450FFE /* JackPhysicalMidiInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCBCE5A10C4FE3F00450FFE /* JackPhysicalMidiInput.h */; };
+- 4BCBCE5F10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCBCE5B10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp */; };
+- 4BCBCE6010C4FE3F00450FFE /* JackPhysicalMidiOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCBCE5C10C4FE3F00450FFE /* JackPhysicalMidiOutput.h */; };
+- 4BCBCE6110C4FE3F00450FFE /* JackPhysicalMidiInput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCBCE5910C4FE3F00450FFE /* JackPhysicalMidiInput.cpp */; };
+- 4BCBCE6210C4FE3F00450FFE /* JackPhysicalMidiInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCBCE5A10C4FE3F00450FFE /* JackPhysicalMidiInput.h */; };
+- 4BCBCE6310C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCBCE5B10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp */; };
+- 4BCBCE6410C4FE3F00450FFE /* JackPhysicalMidiOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCBCE5C10C4FE3F00450FFE /* JackPhysicalMidiOutput.h */; };
+- 4BCBCE6510C4FE3F00450FFE /* JackPhysicalMidiInput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCBCE5910C4FE3F00450FFE /* JackPhysicalMidiInput.cpp */; };
+- 4BCBCE6610C4FE3F00450FFE /* JackPhysicalMidiInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCBCE5A10C4FE3F00450FFE /* JackPhysicalMidiInput.h */; };
+- 4BCBCE6710C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCBCE5B10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp */; };
+- 4BCBCE6810C4FE3F00450FFE /* JackPhysicalMidiOutput.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BCBCE5C10C4FE3F00450FFE /* JackPhysicalMidiOutput.h */; };
+ 4BCC87960D57168300A7FEB1 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BCC87950D57168300A7FEB1 /* Accelerate.framework */; };
+ 4BCC87970D57168300A7FEB1 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BCC87950D57168300A7FEB1 /* Accelerate.framework */; };
+ 4BCC87980D57168300A7FEB1 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BCC87950D57168300A7FEB1 /* Accelerate.framework */; };
+@@ -877,6 +1003,13 @@
+ remoteGlobalIDString = 4B19B2F60E23620F00DD4A82;
+ remoteInfo = audioadapter;
+ };
++ 4B20220B133A9C370019E213 /* PBXContainerItemProxy */ = {
++ isa = PBXContainerItemProxy;
++ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
++ proxyType = 1;
++ remoteGlobalIDString = 4B2021DC133A9BA40019E213;
++ remoteInfo = "jack_midi_latency 64 bits";
++ };
+ 4B224B330E65BA330066BE5B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+@@ -1234,6 +1367,13 @@
+ remoteGlobalIDString = 4BA7FEB90D8E76270017FF73;
+ remoteInfo = "jack_control Universal";
+ };
++ 4BB492A61372A393005F2601 /* PBXContainerItemProxy */ = {
++ isa = PBXContainerItemProxy;
++ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
++ proxyType = 1;
++ remoteGlobalIDString = 4B8692821371DB4700D2D11B;
++ remoteInfo = "Jacknet.framework 64 bits";
++ };
+ 4BD624D20CBCF55700DE782F /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+@@ -1430,33 +1570,31 @@
+ 4B05A0640DF72BC000840F4C /* usx2y.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = usx2y.c; path = ../linux/alsa/usx2y.c; sourceTree = SOURCE_ROOT; };
+ 4B05A0650DF72BC000840F4C /* usx2y.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = usx2y.h; path = ../linux/alsa/usx2y.h; sourceTree = SOURCE_ROOT; };
+ 4B05A07D0DF72BC000840F4C /* driver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = driver.h; path = ../linux/driver.h; sourceTree = SOURCE_ROOT; };
+- 4B05A07F0DF72BC000840F4C /* ffado_driver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ffado_driver.h; path = ../linux/firewire/ffado_driver.h; sourceTree = SOURCE_ROOT; };
+- 4B05A0800DF72BC000840F4C /* JackFFADODriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackFFADODriver.cpp; path = ../linux/firewire/JackFFADODriver.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A0810DF72BC000840F4C /* JackFFADODriver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackFFADODriver.h; path = ../linux/firewire/JackFFADODriver.h; sourceTree = SOURCE_ROOT; };
+ 4B05A0830DF72BC000840F4C /* freebob_driver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = freebob_driver.h; path = ../linux/freebob/freebob_driver.h; sourceTree = SOURCE_ROOT; };
+ 4B05A0840DF72BC000840F4C /* JackFreebobDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackFreebobDriver.cpp; path = ../linux/freebob/JackFreebobDriver.cpp; sourceTree = SOURCE_ROOT; };
+ 4B05A0850DF72BC000840F4C /* JackFreebobDriver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackFreebobDriver.h; path = ../linux/freebob/JackFreebobDriver.h; sourceTree = SOURCE_ROOT; };
+- 4B05A08B0DF72C3200840F4C /* JackWinEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinEvent.cpp; path = ../windows/JackWinEvent.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A08C0DF72C3200840F4C /* JackWinEvent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinEvent.h; path = ../windows/JackWinEvent.h; sourceTree = SOURCE_ROOT; };
+- 4B05A08D0DF72C3200840F4C /* JackWinNamedPipe.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipe.cpp; path = ../windows/JackWinNamedPipe.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A08E0DF72C3200840F4C /* JackWinNamedPipe.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipe.h; path = ../windows/JackWinNamedPipe.h; sourceTree = SOURCE_ROOT; };
+- 4B05A08F0DF72C3200840F4C /* JackWinNamedPipeClientChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeClientChannel.cpp; path = ../windows/JackWinNamedPipeClientChannel.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A0900DF72C3200840F4C /* JackWinNamedPipeClientChannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeClientChannel.h; path = ../windows/JackWinNamedPipeClientChannel.h; sourceTree = SOURCE_ROOT; };
+- 4B05A0910DF72C3200840F4C /* JackWinNamedPipeNotifyChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeNotifyChannel.cpp; path = ../windows/JackWinNamedPipeNotifyChannel.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A0920DF72C3200840F4C /* JackWinNamedPipeNotifyChannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeNotifyChannel.h; path = ../windows/JackWinNamedPipeNotifyChannel.h; sourceTree = SOURCE_ROOT; };
+- 4B05A0930DF72C3200840F4C /* JackWinNamedPipeServerChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeServerChannel.cpp; path = ../windows/JackWinNamedPipeServerChannel.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A0940DF72C3200840F4C /* JackWinNamedPipeServerChannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeServerChannel.h; path = ../windows/JackWinNamedPipeServerChannel.h; sourceTree = SOURCE_ROOT; };
+- 4B05A0950DF72C3200840F4C /* JackWinNamedPipeServerNotifyChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeServerNotifyChannel.cpp; path = ../windows/JackWinNamedPipeServerNotifyChannel.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A0960DF72C3200840F4C /* JackWinNamedPipeServerNotifyChannel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeServerNotifyChannel.h; path = ../windows/JackWinNamedPipeServerNotifyChannel.h; sourceTree = SOURCE_ROOT; };
+- 4B05A0970DF72C3200840F4C /* JackWinProcessSync.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinProcessSync.cpp; path = ../windows/JackWinProcessSync.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A0980DF72C3200840F4C /* JackWinProcessSync.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinProcessSync.h; path = ../windows/JackWinProcessSync.h; sourceTree = SOURCE_ROOT; };
+- 4B05A0990DF72C3200840F4C /* JackWinSemaphore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinSemaphore.cpp; path = ../windows/JackWinSemaphore.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A09A0DF72C3200840F4C /* JackWinSemaphore.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinSemaphore.h; path = ../windows/JackWinSemaphore.h; sourceTree = SOURCE_ROOT; };
+- 4B05A09B0DF72C3200840F4C /* JackWinThread.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinThread.cpp; path = ../windows/JackWinThread.cpp; sourceTree = SOURCE_ROOT; };
+- 4B05A09C0DF72C3200840F4C /* JackWinThread.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackWinThread.h; path = ../windows/JackWinThread.h; sourceTree = SOURCE_ROOT; };
+ 4B0A28E60D52073D002EFF74 /* jack_thread_wait */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_thread_wait; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B0A28EC0D520852002EFF74 /* tw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tw.c; path = "../example-clients/tw.c"; sourceTree = SOURCE_ROOT; };
+ 4B0A292D0D52108E002EFF74 /* jack_thread_wait */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_thread_wait; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B193931133F311400547810 /* JackMidiAsyncQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiAsyncQueue.cpp; path = ../common/JackMidiAsyncQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B193932133F311400547810 /* JackMidiAsyncQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiAsyncQueue.h; path = ../common/JackMidiAsyncQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B19393B133F313000547810 /* JackMidiAsyncWaitQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiAsyncWaitQueue.cpp; path = ../common/JackMidiAsyncWaitQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B19393C133F313000547810 /* JackMidiAsyncWaitQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiAsyncWaitQueue.h; path = ../common/JackMidiAsyncWaitQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B193945133F315200547810 /* JackMidiReadQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiReadQueue.cpp; path = ../common/JackMidiReadQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B193946133F315200547810 /* JackMidiReadQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiReadQueue.h; path = ../common/JackMidiReadQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B19395D133F317300547810 /* JackMidiBufferReadQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiBufferReadQueue.cpp; path = ../common/JackMidiBufferReadQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B19395E133F317300547810 /* JackMidiBufferReadQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiBufferReadQueue.h; path = ../common/JackMidiBufferReadQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B193968133F319000547810 /* JackMidiBufferWriteQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiBufferWriteQueue.cpp; path = ../common/JackMidiBufferWriteQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B193969133F319000547810 /* JackMidiBufferWriteQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiBufferWriteQueue.h; path = ../common/JackMidiBufferWriteQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B193973133F31CB00547810 /* JackMidiReceiveQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiReceiveQueue.cpp; path = ../common/JackMidiReceiveQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B193974133F31CB00547810 /* JackMidiReceiveQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiReceiveQueue.h; path = ../common/JackMidiReceiveQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B193975133F31CB00547810 /* JackMidiSendQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiSendQueue.cpp; path = ../common/JackMidiSendQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B193976133F31CB00547810 /* JackMidiSendQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiSendQueue.h; path = ../common/JackMidiSendQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B193977133F31CB00547810 /* JackMidiUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiUtil.cpp; path = ../common/JackMidiUtil.cpp; sourceTree = SOURCE_ROOT; };
++ 4B193978133F31CB00547810 /* JackMidiUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiUtil.h; path = ../common/JackMidiUtil.h; sourceTree = SOURCE_ROOT; };
++ 4B193979133F31CB00547810 /* JackMidiWriteQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiWriteQueue.cpp; path = ../common/JackMidiWriteQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B19397A133F31CB00547810 /* JackMidiWriteQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMidiWriteQueue.h; path = ../common/JackMidiWriteQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B193990133F321500547810 /* JackFilters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackFilters.h; path = ../common/JackFilters.h; sourceTree = SOURCE_ROOT; };
+ 4B19B3000E23620F00DD4A82 /* audioadapter.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = audioadapter.so; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B19B3060E2362E700DD4A82 /* JackAudioAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapter.cpp; path = ../common/JackAudioAdapter.cpp; sourceTree = SOURCE_ROOT; };
+ 4B19B3070E2362E700DD4A82 /* JackAudioAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioAdapter.h; path = ../common/JackAudioAdapter.h; sourceTree = SOURCE_ROOT; };
+@@ -1466,6 +1604,10 @@
+ 4B19B30E0E2362E700DD4A82 /* JackLibSampleRateResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackLibSampleRateResampler.cpp; path = ../common/JackLibSampleRateResampler.cpp; sourceTree = SOURCE_ROOT; };
+ 4B19B30F0E2362E700DD4A82 /* JackLibSampleRateResampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackLibSampleRateResampler.h; path = ../common/JackLibSampleRateResampler.h; sourceTree = SOURCE_ROOT; };
+ 4B19B3120E2362E700DD4A82 /* JackResampler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackResampler.cpp; path = ../common/JackResampler.cpp; sourceTree = SOURCE_ROOT; };
++ 4B2021E6133A9BA40019E213 /* jack_midi_latency_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midi_latency_test; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B202209133A9C1C0019E213 /* midi_latency_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = midi_latency_test.c; path = "../example-clients/midi_latency_test.c"; sourceTree = SOURCE_ROOT; };
++ 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackTimedDriver.cpp; path = ../common/JackTimedDriver.cpp; sourceTree = SOURCE_ROOT; };
++ 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackTimedDriver.h; path = ../common/JackTimedDriver.h; sourceTree = SOURCE_ROOT; };
+ 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; };
+ 4B3224E510A3156800838A8E /* jack_netone.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_netone.so; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B3224E810A315B100838A8E /* JackNetOneDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetOneDriver.cpp; path = ../common/JackNetOneDriver.cpp; sourceTree = SOURCE_ROOT; };
+@@ -1478,6 +1620,29 @@
+ 4B32256110A3187800838A8E /* jack_netsource */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_netsource; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B32256310A318E300838A8E /* netsource.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = netsource.c; path = "../example-clients/netsource.c"; sourceTree = SOURCE_ROOT; };
+ 4B32257B10A3190C00838A8E /* jack_netsource */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_netsource; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B349826133A6AF500D130AB /* JackALSARawMidiDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackALSARawMidiDriver.cpp; path = ../linux/alsarawmidi/JackALSARawMidiDriver.cpp; sourceTree = SOURCE_ROOT; };
++ 4B349827133A6AF500D130AB /* JackALSARawMidiDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackALSARawMidiDriver.h; path = ../linux/alsarawmidi/JackALSARawMidiDriver.h; sourceTree = SOURCE_ROOT; };
++ 4B349828133A6AF500D130AB /* JackALSARawMidiInputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackALSARawMidiInputPort.cpp; path = ../linux/alsarawmidi/JackALSARawMidiInputPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B349829133A6AF500D130AB /* JackALSARawMidiInputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackALSARawMidiInputPort.h; path = ../linux/alsarawmidi/JackALSARawMidiInputPort.h; sourceTree = SOURCE_ROOT; };
++ 4B34982A133A6AF500D130AB /* JackALSARawMidiOutputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackALSARawMidiOutputPort.cpp; path = ../linux/alsarawmidi/JackALSARawMidiOutputPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B34982B133A6AF500D130AB /* JackALSARawMidiOutputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackALSARawMidiOutputPort.h; path = ../linux/alsarawmidi/JackALSARawMidiOutputPort.h; sourceTree = SOURCE_ROOT; };
++ 4B34982C133A6AF500D130AB /* JackALSARawMidiPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackALSARawMidiPort.cpp; path = ../linux/alsarawmidi/JackALSARawMidiPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B34982D133A6AF500D130AB /* JackALSARawMidiPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackALSARawMidiPort.h; path = ../linux/alsarawmidi/JackALSARawMidiPort.h; sourceTree = SOURCE_ROOT; };
++ 4B34982E133A6AF500D130AB /* JackALSARawMidiReceiveQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackALSARawMidiReceiveQueue.cpp; path = ../linux/alsarawmidi/JackALSARawMidiReceiveQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B34982F133A6AF500D130AB /* JackALSARawMidiReceiveQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackALSARawMidiReceiveQueue.h; path = ../linux/alsarawmidi/JackALSARawMidiReceiveQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B349830133A6AF500D130AB /* JackALSARawMidiSendQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackALSARawMidiSendQueue.cpp; path = ../linux/alsarawmidi/JackALSARawMidiSendQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B349831133A6AF500D130AB /* JackALSARawMidiSendQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackALSARawMidiSendQueue.h; path = ../linux/alsarawmidi/JackALSARawMidiSendQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B349838133A6B6F00D130AB /* ffado_driver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ffado_driver.h; path = ../linux/firewire/ffado_driver.h; sourceTree = SOURCE_ROOT; };
++ 4B349839133A6B6F00D130AB /* JackFFADODriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackFFADODriver.cpp; path = ../linux/firewire/JackFFADODriver.cpp; sourceTree = SOURCE_ROOT; };
++ 4B34983A133A6B6F00D130AB /* JackFFADODriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackFFADODriver.h; path = ../linux/firewire/JackFFADODriver.h; sourceTree = SOURCE_ROOT; };
++ 4B34983B133A6B6F00D130AB /* JackFFADOMidiInputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackFFADOMidiInputPort.cpp; path = ../linux/firewire/JackFFADOMidiInputPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B34983C133A6B6F00D130AB /* JackFFADOMidiInputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackFFADOMidiInputPort.h; path = ../linux/firewire/JackFFADOMidiInputPort.h; sourceTree = SOURCE_ROOT; };
++ 4B34983D133A6B6F00D130AB /* JackFFADOMidiOutputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackFFADOMidiOutputPort.cpp; path = ../linux/firewire/JackFFADOMidiOutputPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B34983E133A6B6F00D130AB /* JackFFADOMidiOutputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackFFADOMidiOutputPort.h; path = ../linux/firewire/JackFFADOMidiOutputPort.h; sourceTree = SOURCE_ROOT; };
++ 4B34983F133A6B6F00D130AB /* JackFFADOMidiReceiveQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackFFADOMidiReceiveQueue.cpp; path = ../linux/firewire/JackFFADOMidiReceiveQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B349840133A6B6F00D130AB /* JackFFADOMidiReceiveQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackFFADOMidiReceiveQueue.h; path = ../linux/firewire/JackFFADOMidiReceiveQueue.h; sourceTree = SOURCE_ROOT; };
++ 4B349841133A6B6F00D130AB /* JackFFADOMidiSendQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackFFADOMidiSendQueue.cpp; path = ../linux/firewire/JackFFADOMidiSendQueue.cpp; sourceTree = SOURCE_ROOT; };
++ 4B349842133A6B6F00D130AB /* JackFFADOMidiSendQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackFFADOMidiSendQueue.h; path = ../linux/firewire/JackFFADOMidiSendQueue.h; sourceTree = SOURCE_ROOT; };
+ 4B35C4250D4731D1000DE7AE /* jackdmp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jackdmp; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B35C4830D4731D1000DE7AE /* Jackmp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackmp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackservermp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+@@ -1518,6 +1683,22 @@
+ 4B363F3D0DEB0C31001F72D9 /* showtime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = showtime.c; path = "../example-clients/showtime.c"; sourceTree = SOURCE_ROOT; };
+ 4B363F720DEB0D4E001F72D9 /* jack_impulse_grabber */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_impulse_grabber; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B363F750DEB0D7D001F72D9 /* impulse_grabber.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = impulse_grabber.c; path = "../example-clients/impulse_grabber.c"; sourceTree = SOURCE_ROOT; };
++ 4B370A14133DD7E200237B68 /* JackCoreMidiInputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiInputPort.cpp; path = ../../coremidi/JackCoreMidiInputPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A15133DD7E200237B68 /* JackCoreMidiInputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiInputPort.h; path = ../../coremidi/JackCoreMidiInputPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A16133DD7E200237B68 /* JackCoreMidiOutputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiOutputPort.cpp; path = ../../coremidi/JackCoreMidiOutputPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A17133DD7E200237B68 /* JackCoreMidiOutputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiOutputPort.h; path = ../../coremidi/JackCoreMidiOutputPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A18133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiPhysicalInputPort.cpp; path = ../../coremidi/JackCoreMidiPhysicalInputPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A19133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiPhysicalInputPort.h; path = ../../coremidi/JackCoreMidiPhysicalInputPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A1A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiPhysicalOutputPort.cpp; path = ../../coremidi/JackCoreMidiPhysicalOutputPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A1B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiPhysicalOutputPort.h; path = ../../coremidi/JackCoreMidiPhysicalOutputPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A1C133DD7E300237B68 /* JackCoreMidiPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiPort.cpp; path = ../../coremidi/JackCoreMidiPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A1D133DD7E300237B68 /* JackCoreMidiPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiPort.h; path = ../../coremidi/JackCoreMidiPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A1E133DD7E300237B68 /* JackCoreMidiUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiUtil.cpp; path = ../../coremidi/JackCoreMidiUtil.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A1F133DD7E300237B68 /* JackCoreMidiUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiUtil.h; path = ../../coremidi/JackCoreMidiUtil.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A20133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiVirtualInputPort.cpp; path = ../../coremidi/JackCoreMidiVirtualInputPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A21133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiVirtualInputPort.h; path = ../../coremidi/JackCoreMidiVirtualInputPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A22133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackCoreMidiVirtualOutputPort.cpp; path = ../../coremidi/JackCoreMidiVirtualOutputPort.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B370A23133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackCoreMidiVirtualOutputPort.h; path = ../../coremidi/JackCoreMidiVirtualOutputPort.h; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B37C20306DF1FBE0016E567 /* CALatencyLog.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CALatencyLog.cpp; path = /Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.cpp; sourceTree = "<absolute>"; };
+ 4B37C20406DF1FBE0016E567 /* CALatencyLog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CALatencyLog.h; path = /Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.h; sourceTree = "<absolute>"; };
+ 4B37C20906DF1FE20016E567 /* latency.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = latency.c; path = /Developer/Examples/CoreAudio/PublicUtility/latency.c; sourceTree = "<absolute>"; };
+@@ -1532,6 +1713,51 @@
+ 4B43A8E71014615800E52943 /* jack_loopback.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_loopback.so; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4B464301076CAC7700E5077C /* Jack-Info.plist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.plist.xml; path = "Jack-Info.plist"; sourceTree = SOURCE_ROOT; };
+ 4B47ACD710B5890100469C67 /* Jackmp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackmp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B49D3B314864D41003390F8 /* JackWinMMEDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinMMEDriver.cpp; path = ../windows/winmme/JackWinMMEDriver.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3B414864D41003390F8 /* JackWinMMEDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinMMEDriver.h; path = ../windows/winmme/JackWinMMEDriver.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3B514864D41003390F8 /* JackWinMMEInputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinMMEInputPort.cpp; path = ../windows/winmme/JackWinMMEInputPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3B614864D41003390F8 /* JackWinMMEInputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinMMEInputPort.h; path = ../windows/winmme/JackWinMMEInputPort.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3B714864D41003390F8 /* JackWinMMEOutputPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinMMEOutputPort.cpp; path = ../windows/winmme/JackWinMMEOutputPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3B814864D41003390F8 /* JackWinMMEOutputPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinMMEOutputPort.h; path = ../windows/winmme/JackWinMMEOutputPort.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3B914864D41003390F8 /* JackWinMMEPort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinMMEPort.cpp; path = ../windows/winmme/JackWinMMEPort.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3BA14864D41003390F8 /* JackWinMMEPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinMMEPort.h; path = ../windows/winmme/JackWinMMEPort.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3BC14864D49003390F8 /* JackPortAudioAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortAudioAdapter.cpp; path = ../windows/portaudio/JackPortAudioAdapter.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3BD14864D49003390F8 /* JackPortAudioAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPortAudioAdapter.h; path = ../windows/portaudio/JackPortAudioAdapter.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3BE14864D49003390F8 /* JackPortAudioDevices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortAudioDevices.cpp; path = ../windows/portaudio/JackPortAudioDevices.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3BF14864D49003390F8 /* JackPortAudioDevices.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPortAudioDevices.h; path = ../windows/portaudio/JackPortAudioDevices.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3C014864D49003390F8 /* JackPortAudioDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortAudioDriver.cpp; path = ../windows/portaudio/JackPortAudioDriver.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3C114864D49003390F8 /* JackPortAudioDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPortAudioDriver.h; path = ../windows/portaudio/JackPortAudioDriver.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3C214864D49003390F8 /* pa_asio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pa_asio.h; path = ../windows/portaudio/pa_asio.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3C314864D49003390F8 /* portaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = portaudio.h; path = ../windows/portaudio/portaudio.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3C914864DA7003390F8 /* JackLinuxTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = JackLinuxTime.c; path = ../linux/JackLinuxTime.c; sourceTree = SOURCE_ROOT; };
++ 4B49D3CB14864DB2003390F8 /* cycles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cycles.h; path = ../linux/cycles.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3D814864DEC003390F8 /* JackWinThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinThread.cpp; path = ../windows/JackWinThread.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3D914864DEC003390F8 /* JackWinServerLaunch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinServerLaunch.cpp; path = ../windows/JackWinServerLaunch.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3DA14864DEC003390F8 /* JackWinSemaphore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinSemaphore.cpp; path = ../windows/JackWinSemaphore.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3DB14864DEC003390F8 /* JackWinProcessSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinProcessSync.cpp; path = ../windows/JackWinProcessSync.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3DC14864DEC003390F8 /* JackWinNamedPipeServerNotifyChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeServerNotifyChannel.cpp; path = ../windows/JackWinNamedPipeServerNotifyChannel.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3DD14864DEC003390F8 /* JackWinNamedPipeServerChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeServerChannel.cpp; path = ../windows/JackWinNamedPipeServerChannel.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3DE14864DEC003390F8 /* JackWinNamedPipeNotifyChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeNotifyChannel.cpp; path = ../windows/JackWinNamedPipeNotifyChannel.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3DF14864DEC003390F8 /* JackWinNamedPipeClientChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipeClientChannel.cpp; path = ../windows/JackWinNamedPipeClientChannel.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3E014864DED003390F8 /* JackWinNamedPipe.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinNamedPipe.cpp; path = ../windows/JackWinNamedPipe.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3E114864DED003390F8 /* JackWinEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackWinEvent.cpp; path = ../windows/JackWinEvent.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3E214864DED003390F8 /* JackNetWinSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetWinSocket.cpp; path = ../windows/JackNetWinSocket.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3E314864DED003390F8 /* JackMMCSS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackMMCSS.cpp; path = ../windows/JackMMCSS.cpp; sourceTree = SOURCE_ROOT; };
++ 4B49D3E414864DED003390F8 /* JackWinTime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = JackWinTime.c; path = ../windows/JackWinTime.c; sourceTree = SOURCE_ROOT; };
++ 4B49D3EA14864DED003390F8 /* JackWinThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinThread.h; path = ../windows/JackWinThread.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3EB14864DED003390F8 /* JackWinSemaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinSemaphore.h; path = ../windows/JackWinSemaphore.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3EC14864DED003390F8 /* JackWinProcessSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinProcessSync.h; path = ../windows/JackWinProcessSync.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3ED14864DED003390F8 /* JackWinNamedPipeServerNotifyChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeServerNotifyChannel.h; path = ../windows/JackWinNamedPipeServerNotifyChannel.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3EE14864DED003390F8 /* JackWinNamedPipeServerChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeServerChannel.h; path = ../windows/JackWinNamedPipeServerChannel.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3EF14864DED003390F8 /* JackWinNamedPipeNotifyChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeNotifyChannel.h; path = ../windows/JackWinNamedPipeNotifyChannel.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3F014864DED003390F8 /* JackWinNamedPipeClientChannel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipeClientChannel.h; path = ../windows/JackWinNamedPipeClientChannel.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3F114864DED003390F8 /* JackWinNamedPipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinNamedPipe.h; path = ../windows/JackWinNamedPipe.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3F214864DED003390F8 /* JackWinMutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinMutex.h; path = ../windows/JackWinMutex.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3F314864DED003390F8 /* JackWinEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackWinEvent.h; path = ../windows/JackWinEvent.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3F814864DED003390F8 /* JackNetWinSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackNetWinSocket.h; path = ../windows/JackNetWinSocket.h; sourceTree = SOURCE_ROOT; };
++ 4B49D3F914864DED003390F8 /* JackMMCSS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMMCSS.h; path = ../windows/JackMMCSS.h; sourceTree = SOURCE_ROOT; };
++ 4B49D44014865F22003390F8 /* net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = net.h; path = ../common/jack/net.h; sourceTree = SOURCE_ROOT; };
++ 4B49D44114865F22003390F8 /* session.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = session.h; path = ../common/jack/session.h; sourceTree = SOURCE_ROOT; };
+ 4B4CA9730E02CF9600F4BFDA /* JackRestartThreadedDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackRestartThreadedDriver.h; path = ../common/JackRestartThreadedDriver.h; sourceTree = SOURCE_ROOT; };
+ 4B4CA9740E02CF9600F4BFDA /* JackRestartThreadedDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackRestartThreadedDriver.cpp; path = ../common/JackRestartThreadedDriver.cpp; sourceTree = SOURCE_ROOT; };
+ 4B4E9AF80E5F1090000A3278 /* JackControlAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackControlAPI.cpp; path = ../common/JackControlAPI.cpp; sourceTree = SOURCE_ROOT; };
+@@ -1582,6 +1808,8 @@
+ 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackMidiPort.h; path = ../common/JackMidiPort.h; sourceTree = SOURCE_ROOT; };
+ 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiPort.cpp; path = ../common/JackMidiPort.cpp; sourceTree = SOURCE_ROOT; };
+ 4B80D7E70BA0D17400F035BB /* JackMidiAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackMidiAPI.cpp; path = ../common/JackMidiAPI.cpp; sourceTree = SOURCE_ROOT; };
++ 4B8692DB1371DB4700D2D11B /* Jacknet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jacknet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
++ 4B8693151371DD0A00D2D11B /* JackNetAPI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetAPI.cpp; path = ../common/JackNetAPI.cpp; sourceTree = SOURCE_ROOT; };
+ 4B869B3D08C8D21C001CF041 /* driver_interface.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = driver_interface.h; path = ../common/driver_interface.h; sourceTree = SOURCE_ROOT; };
+ 4B869B4208C8D22F001CF041 /* JackDriverLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackDriverLoader.h; path = ../common/JackDriverLoader.h; sourceTree = SOURCE_ROOT; };
+ 4B869D7F08C9CB00001CF041 /* JackDriverLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackDriverLoader.cpp; path = ../common/JackDriverLoader.cpp; sourceTree = SOURCE_ROOT; };
+@@ -1598,7 +1826,7 @@
+ 4B98AE010931D30C0091932A /* JackDebugClient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackDebugClient.h; path = ../common/JackDebugClient.h; sourceTree = SOURCE_ROOT; };
+ 4B9A25B30DBF8330006E9FBC /* JackError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackError.cpp; path = ../common/JackError.cpp; sourceTree = SOURCE_ROOT; };
+ 4B9A26000DBF8584006E9FBC /* jslist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jslist.h; path = ../common/jack/jslist.h; sourceTree = SOURCE_ROOT; };
+- 4BA2574C132FB49B009F2D3F /* alsa_driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = alsa_driver.c; path = ../linux/alsa/alsa_driver.c; sourceTree = SOURCE_ROOT; };
++ 4BA2574C132FB49B009F2D3F /* alsa_driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = alsa_driver.c; sourceTree = "<group>"; };
+ 4BA339AC10B2E36800190E3B /* Jackservermp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackservermp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 4BA577BC08BF8BE200F82DE1 /* testSynchroClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroClient.cpp; path = ../tests/testSynchroClient.cpp; sourceTree = SOURCE_ROOT; };
+ 4BA577FB08BF8E4600F82DE1 /* testSynchroServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroServer.cpp; path = ../tests/testSynchroServer.cpp; sourceTree = SOURCE_ROOT; };
+@@ -1642,10 +1870,6 @@
+ 4BC3B6B90E703BCC0066E42F /* JackNetUnixSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetUnixSocket.cpp; path = ../posix/JackNetUnixSocket.cpp; sourceTree = SOURCE_ROOT; };
+ 4BC3B6BA0E703BCC0066E42F /* JackNetUnixSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackNetUnixSocket.h; path = ../posix/JackNetUnixSocket.h; sourceTree = SOURCE_ROOT; };
+ 4BC8326D0DF42C7D00DD1C93 /* JackMutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackMutex.h; path = ../common/JackMutex.h; sourceTree = SOURCE_ROOT; };
+- 4BCBCE5910C4FE3F00450FFE /* JackPhysicalMidiInput.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPhysicalMidiInput.cpp; path = ../common/JackPhysicalMidiInput.cpp; sourceTree = SOURCE_ROOT; };
+- 4BCBCE5A10C4FE3F00450FFE /* JackPhysicalMidiInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPhysicalMidiInput.h; path = ../common/JackPhysicalMidiInput.h; sourceTree = SOURCE_ROOT; };
+- 4BCBCE5B10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackPhysicalMidiOutput.cpp; path = ../common/JackPhysicalMidiOutput.cpp; sourceTree = SOURCE_ROOT; };
+- 4BCBCE5C10C4FE3F00450FFE /* JackPhysicalMidiOutput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackPhysicalMidiOutput.h; path = ../common/JackPhysicalMidiOutput.h; sourceTree = SOURCE_ROOT; };
+ 4BCC87950D57168300A7FEB1 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = /System/Library/Frameworks/Accelerate.framework; sourceTree = "<absolute>"; };
+ 4BD4B4D409BACD9600750C0F /* JackTransportEngine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackTransportEngine.h; path = ../common/JackTransportEngine.h; sourceTree = SOURCE_ROOT; };
+ 4BD4B4D509BACD9600750C0F /* JackTransportEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackTransportEngine.cpp; path = ../common/JackTransportEngine.cpp; sourceTree = SOURCE_ROOT; };
+@@ -1783,6 +2007,13 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B2021E0133A9BA40019E213 /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B3224E010A3156800838A8E /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+@@ -2234,6 +2465,14 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B8692D51371DB4700D2D11B /* Frameworks */ = {
++ isa = PBXFrameworksBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B8692D61371DB4700D2D11B /* Accelerate.framework in Frameworks */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B8F16DF13290DC80002AD73 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+@@ -2456,7 +2695,6 @@
+ 4BA3873B079479C2008D8992 /* Graph */,
+ 4BA550FA05E241F200569492 /* Ports */,
+ 4BD56D74079687D7006D44F9 /* Client */,
+- 4BA550FB05E2420000569492 /* Engine */,
+ 4B9B627005E60A9E001E19AA /* Server */,
+ );
+ name = Source;
+@@ -2559,6 +2797,8 @@
+ 4B3811971326884E00C61B14 /* jack_latent_client */,
+ 4B8F16E513290DC80002AD73 /* jack_midi_dump */,
+ 4B8F16F213290E0E0002AD73 /* jack_midi_dump */,
++ 4B2021E6133A9BA40019E213 /* jack_midi_latency_test */,
++ 4B8692DB1371DB4700D2D11B /* Jacknet.framework */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+@@ -2566,6 +2806,7 @@
+ 4B03383E0797E19900686131 /* Simple clients */ = {
+ isa = PBXGroup;
+ children = (
++ 4B202209133A9C1C0019E213 /* midi_latency_test.c */,
+ 4B8F16F41329161E0002AD73 /* midi_dump.c */,
+ 4B3811FA13269C8300C61B14 /* latent_client.c */,
+ 4B6654FB127C350100753A79 /* server_control.cpp */,
+@@ -2595,9 +2836,12 @@
+ 4B05A0420DF72B8500840F4C /* Linux */ = {
+ isa = PBXGroup;
+ children = (
+- 4B05A04C0DF72BC000840F4C /* alsa */,
+ 4B05A07D0DF72BC000840F4C /* driver.h */,
+- 4B05A07E0DF72BC000840F4C /* firewire */,
++ 4B49D3CB14864DB2003390F8 /* cycles.h */,
++ 4B49D3C914864DA7003390F8 /* JackLinuxTime.c */,
++ 4B349837133A6B6F00D130AB /* firewire */,
++ 4B349825133A6AF500D130AB /* alsarawmidi */,
++ 4B05A04C0DF72BC000840F4C /* alsa */,
+ 4B05A0820DF72BC000840F4C /* freebob */,
+ );
+ name = Linux;
+@@ -2606,6 +2850,7 @@
+ 4B05A04C0DF72BC000840F4C /* alsa */ = {
+ isa = PBXGroup;
+ children = (
++ 4BA2574C132FB49B009F2D3F /* alsa_driver.c */,
+ 4B05A04D0DF72BC000840F4C /* alsa_driver.h */,
+ 4B05A04E0DF72BC000840F4C /* alsa_midi.h */,
+ 4B05A04F0DF72BC000840F4C /* alsa_midi_impl.h */,
+@@ -2634,17 +2879,6 @@
+ path = ../linux/alsa;
+ sourceTree = SOURCE_ROOT;
+ };
+- 4B05A07E0DF72BC000840F4C /* firewire */ = {
+- isa = PBXGroup;
+- children = (
+- 4B05A07F0DF72BC000840F4C /* ffado_driver.h */,
+- 4B05A0800DF72BC000840F4C /* JackFFADODriver.cpp */,
+- 4B05A0810DF72BC000840F4C /* JackFFADODriver.h */,
+- );
+- name = firewire;
+- path = ../linux/firewire;
+- sourceTree = SOURCE_ROOT;
+- };
+ 4B05A0820DF72BC000840F4C /* freebob */ = {
+ isa = PBXGroup;
+ children = (
+@@ -2659,24 +2893,33 @@
+ 4B05A08A0DF72BF600840F4C /* Windows */ = {
+ isa = PBXGroup;
+ children = (
+- 4B05A08B0DF72C3200840F4C /* JackWinEvent.cpp */,
+- 4B05A08C0DF72C3200840F4C /* JackWinEvent.h */,
+- 4B05A08D0DF72C3200840F4C /* JackWinNamedPipe.cpp */,
+- 4B05A08E0DF72C3200840F4C /* JackWinNamedPipe.h */,
+- 4B05A08F0DF72C3200840F4C /* JackWinNamedPipeClientChannel.cpp */,
+- 4B05A0900DF72C3200840F4C /* JackWinNamedPipeClientChannel.h */,
+- 4B05A0910DF72C3200840F4C /* JackWinNamedPipeNotifyChannel.cpp */,
+- 4B05A0920DF72C3200840F4C /* JackWinNamedPipeNotifyChannel.h */,
+- 4B05A0930DF72C3200840F4C /* JackWinNamedPipeServerChannel.cpp */,
+- 4B05A0940DF72C3200840F4C /* JackWinNamedPipeServerChannel.h */,
+- 4B05A0950DF72C3200840F4C /* JackWinNamedPipeServerNotifyChannel.cpp */,
+- 4B05A0960DF72C3200840F4C /* JackWinNamedPipeServerNotifyChannel.h */,
+- 4B05A0970DF72C3200840F4C /* JackWinProcessSync.cpp */,
+- 4B05A0980DF72C3200840F4C /* JackWinProcessSync.h */,
+- 4B05A0990DF72C3200840F4C /* JackWinSemaphore.cpp */,
+- 4B05A09A0DF72C3200840F4C /* JackWinSemaphore.h */,
+- 4B05A09B0DF72C3200840F4C /* JackWinThread.cpp */,
+- 4B05A09C0DF72C3200840F4C /* JackWinThread.h */,
++ 4B49D3D814864DEC003390F8 /* JackWinThread.cpp */,
++ 4B49D3D914864DEC003390F8 /* JackWinServerLaunch.cpp */,
++ 4B49D3DA14864DEC003390F8 /* JackWinSemaphore.cpp */,
++ 4B49D3DB14864DEC003390F8 /* JackWinProcessSync.cpp */,
++ 4B49D3DC14864DEC003390F8 /* JackWinNamedPipeServerNotifyChannel.cpp */,
++ 4B49D3DD14864DEC003390F8 /* JackWinNamedPipeServerChannel.cpp */,
++ 4B49D3DE14864DEC003390F8 /* JackWinNamedPipeNotifyChannel.cpp */,
++ 4B49D3DF14864DEC003390F8 /* JackWinNamedPipeClientChannel.cpp */,
++ 4B49D3E014864DED003390F8 /* JackWinNamedPipe.cpp */,
++ 4B49D3E114864DED003390F8 /* JackWinEvent.cpp */,
++ 4B49D3E214864DED003390F8 /* JackNetWinSocket.cpp */,
++ 4B49D3E314864DED003390F8 /* JackMMCSS.cpp */,
++ 4B49D3E414864DED003390F8 /* JackWinTime.c */,
++ 4B49D3EA14864DED003390F8 /* JackWinThread.h */,
++ 4B49D3EB14864DED003390F8 /* JackWinSemaphore.h */,
++ 4B49D3EC14864DED003390F8 /* JackWinProcessSync.h */,
++ 4B49D3ED14864DED003390F8 /* JackWinNamedPipeServerNotifyChannel.h */,
++ 4B49D3EE14864DED003390F8 /* JackWinNamedPipeServerChannel.h */,
++ 4B49D3EF14864DED003390F8 /* JackWinNamedPipeNotifyChannel.h */,
++ 4B49D3F014864DED003390F8 /* JackWinNamedPipeClientChannel.h */,
++ 4B49D3F114864DED003390F8 /* JackWinNamedPipe.h */,
++ 4B49D3F214864DED003390F8 /* JackWinMutex.h */,
++ 4B49D3F314864DED003390F8 /* JackWinEvent.h */,
++ 4B49D3F814864DED003390F8 /* JackNetWinSocket.h */,
++ 4B49D3F914864DED003390F8 /* JackMMCSS.h */,
++ 4B49D3BB14864D49003390F8 /* portaudio */,
++ 4B49D3B214864D41003390F8 /* winmme */,
+ );
+ name = Windows;
+ sourceTree = "<group>";
+@@ -2684,7 +2927,6 @@
+ 4B05A09D0DF72C6000840F4C /* Additional */ = {
+ isa = PBXGroup;
+ children = (
+- 4BA2574C132FB49B009F2D3F /* alsa_driver.c */,
+ 4B05A08A0DF72BF600840F4C /* Windows */,
+ 4B05A0420DF72B8500840F4C /* Linux */,
+ );
+@@ -2709,6 +2951,45 @@
+ name = Adapter;
+ sourceTree = "<group>";
+ };
++ 4B349825133A6AF500D130AB /* alsarawmidi */ = {
++ isa = PBXGroup;
++ children = (
++ 4B349826133A6AF500D130AB /* JackALSARawMidiDriver.cpp */,
++ 4B349827133A6AF500D130AB /* JackALSARawMidiDriver.h */,
++ 4B349828133A6AF500D130AB /* JackALSARawMidiInputPort.cpp */,
++ 4B349829133A6AF500D130AB /* JackALSARawMidiInputPort.h */,
++ 4B34982A133A6AF500D130AB /* JackALSARawMidiOutputPort.cpp */,
++ 4B34982B133A6AF500D130AB /* JackALSARawMidiOutputPort.h */,
++ 4B34982C133A6AF500D130AB /* JackALSARawMidiPort.cpp */,
++ 4B34982D133A6AF500D130AB /* JackALSARawMidiPort.h */,
++ 4B34982E133A6AF500D130AB /* JackALSARawMidiReceiveQueue.cpp */,
++ 4B34982F133A6AF500D130AB /* JackALSARawMidiReceiveQueue.h */,
++ 4B349830133A6AF500D130AB /* JackALSARawMidiSendQueue.cpp */,
++ 4B349831133A6AF500D130AB /* JackALSARawMidiSendQueue.h */,
++ );
++ name = alsarawmidi;
++ path = ../linux/alsarawmidi;
++ sourceTree = SOURCE_ROOT;
++ };
++ 4B349837133A6B6F00D130AB /* firewire */ = {
++ isa = PBXGroup;
++ children = (
++ 4B349838133A6B6F00D130AB /* ffado_driver.h */,
++ 4B349839133A6B6F00D130AB /* JackFFADODriver.cpp */,
++ 4B34983A133A6B6F00D130AB /* JackFFADODriver.h */,
++ 4B34983B133A6B6F00D130AB /* JackFFADOMidiInputPort.cpp */,
++ 4B34983C133A6B6F00D130AB /* JackFFADOMidiInputPort.h */,
++ 4B34983D133A6B6F00D130AB /* JackFFADOMidiOutputPort.cpp */,
++ 4B34983E133A6B6F00D130AB /* JackFFADOMidiOutputPort.h */,
++ 4B34983F133A6B6F00D130AB /* JackFFADOMidiReceiveQueue.cpp */,
++ 4B349840133A6B6F00D130AB /* JackFFADOMidiReceiveQueue.h */,
++ 4B349841133A6B6F00D130AB /* JackFFADOMidiSendQueue.cpp */,
++ 4B349842133A6B6F00D130AB /* JackFFADOMidiSendQueue.h */,
++ );
++ name = firewire;
++ path = ../linux/firewire;
++ sourceTree = SOURCE_ROOT;
++ };
+ 4B37C20006DF1F900016E567 /* Latency */ = {
+ isa = PBXGroup;
+ children = (
+@@ -2719,6 +3000,38 @@
+ name = Latency;
+ sourceTree = "<group>";
+ };
++ 4B49D3B214864D41003390F8 /* winmme */ = {
++ isa = PBXGroup;
++ children = (
++ 4B49D3B314864D41003390F8 /* JackWinMMEDriver.cpp */,
++ 4B49D3B414864D41003390F8 /* JackWinMMEDriver.h */,
++ 4B49D3B514864D41003390F8 /* JackWinMMEInputPort.cpp */,
++ 4B49D3B614864D41003390F8 /* JackWinMMEInputPort.h */,
++ 4B49D3B714864D41003390F8 /* JackWinMMEOutputPort.cpp */,
++ 4B49D3B814864D41003390F8 /* JackWinMMEOutputPort.h */,
++ 4B49D3B914864D41003390F8 /* JackWinMMEPort.cpp */,
++ 4B49D3BA14864D41003390F8 /* JackWinMMEPort.h */,
++ );
++ name = winmme;
++ path = ../windows/winmme;
++ sourceTree = SOURCE_ROOT;
++ };
++ 4B49D3BB14864D49003390F8 /* portaudio */ = {
++ isa = PBXGroup;
++ children = (
++ 4B49D3BC14864D49003390F8 /* JackPortAudioAdapter.cpp */,
++ 4B49D3BD14864D49003390F8 /* JackPortAudioAdapter.h */,
++ 4B49D3BE14864D49003390F8 /* JackPortAudioDevices.cpp */,
++ 4B49D3BF14864D49003390F8 /* JackPortAudioDevices.h */,
++ 4B49D3C014864D49003390F8 /* JackPortAudioDriver.cpp */,
++ 4B49D3C114864D49003390F8 /* JackPortAudioDriver.h */,
++ 4B49D3C214864D49003390F8 /* pa_asio.h */,
++ 4B49D3C314864D49003390F8 /* portaudio.h */,
++ );
++ name = portaudio;
++ path = ../windows/portaudio;
++ sourceTree = SOURCE_ROOT;
++ };
+ 4B6BEB4A07A6CCDC00A5DBDA /* Tests */ = {
+ isa = PBXGroup;
+ children = (
+@@ -2738,6 +3051,8 @@
+ 4B6C73780CC60A6D001AFFD4 /* jack */ = {
+ isa = PBXGroup;
+ children = (
++ 4B49D44014865F22003390F8 /* net.h */,
++ 4B49D44114865F22003390F8 /* session.h */,
+ 4B94334910A5E666002A187F /* systemdeps.h */,
+ 4B9A26000DBF8584006E9FBC /* jslist.h */,
+ 4B95BCAD0D913073000F7695 /* control.h */,
+@@ -2852,6 +3167,8 @@
+ 4BF8D1B60834EEE400C94B91 /* JackDriver.cpp */,
+ 4BC3988A08B3CF6C00B6F371 /* JackDummyDriver.h */,
+ 4BC3988908B3CF6C00B6F371 /* JackDummyDriver.cpp */,
++ 4B21794E13E2EEA60095B3E5 /* JackTimedDriver.h */,
++ 4B21794D13E2EEA60095B3E5 /* JackTimedDriver.cpp */,
+ 4BF3390D0F8B86AF0080FB5B /* MIDI */,
+ 4B19B3010E23629800DD4A82 /* Adapter */,
+ BA222AEA0DC88379001A17F4 /* Net */,
+@@ -2875,6 +3192,7 @@
+ 4BA550FA05E241F200569492 /* Ports */ = {
+ isa = PBXGroup;
+ children = (
++ 4BA550FB05E2420000569492 /* Engine */,
+ 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */,
+ 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */,
+ 4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */,
+@@ -2889,6 +3207,7 @@
+ 4BA550FB05E2420000569492 /* Engine */ = {
+ isa = PBXGroup;
+ children = (
++ 4B193990133F321500547810 /* JackFilters.h */,
+ 4B5F253D0DEE9B8F0041E486 /* JackLockedEngine.h */,
+ 4BF8D2130834F02800C94B91 /* JackEngine.h */,
+ 4BF8D2140834F02800C94B91 /* JackEngine.cpp */,
+@@ -2994,10 +3313,40 @@
+ 4BF3390D0F8B86AF0080FB5B /* MIDI */ = {
+ isa = PBXGroup;
+ children = (
+- 4BCBCE5910C4FE3F00450FFE /* JackPhysicalMidiInput.cpp */,
+- 4BCBCE5A10C4FE3F00450FFE /* JackPhysicalMidiInput.h */,
+- 4BCBCE5B10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp */,
+- 4BCBCE5C10C4FE3F00450FFE /* JackPhysicalMidiOutput.h */,
++ 4B193973133F31CB00547810 /* JackMidiReceiveQueue.cpp */,
++ 4B193974133F31CB00547810 /* JackMidiReceiveQueue.h */,
++ 4B193975133F31CB00547810 /* JackMidiSendQueue.cpp */,
++ 4B193976133F31CB00547810 /* JackMidiSendQueue.h */,
++ 4B193977133F31CB00547810 /* JackMidiUtil.cpp */,
++ 4B193978133F31CB00547810 /* JackMidiUtil.h */,
++ 4B193979133F31CB00547810 /* JackMidiWriteQueue.cpp */,
++ 4B19397A133F31CB00547810 /* JackMidiWriteQueue.h */,
++ 4B193968133F319000547810 /* JackMidiBufferWriteQueue.cpp */,
++ 4B193969133F319000547810 /* JackMidiBufferWriteQueue.h */,
++ 4B19395D133F317300547810 /* JackMidiBufferReadQueue.cpp */,
++ 4B19395E133F317300547810 /* JackMidiBufferReadQueue.h */,
++ 4B193945133F315200547810 /* JackMidiReadQueue.cpp */,
++ 4B193946133F315200547810 /* JackMidiReadQueue.h */,
++ 4B19393B133F313000547810 /* JackMidiAsyncWaitQueue.cpp */,
++ 4B19393C133F313000547810 /* JackMidiAsyncWaitQueue.h */,
++ 4B193931133F311400547810 /* JackMidiAsyncQueue.cpp */,
++ 4B193932133F311400547810 /* JackMidiAsyncQueue.h */,
++ 4B370A14133DD7E200237B68 /* JackCoreMidiInputPort.cpp */,
++ 4B370A15133DD7E200237B68 /* JackCoreMidiInputPort.h */,
++ 4B370A16133DD7E200237B68 /* JackCoreMidiOutputPort.cpp */,
++ 4B370A17133DD7E200237B68 /* JackCoreMidiOutputPort.h */,
++ 4B370A18133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.cpp */,
++ 4B370A19133DD7E200237B68 /* JackCoreMidiPhysicalInputPort.h */,
++ 4B370A1A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp */,
++ 4B370A1B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h */,
++ 4B370A1C133DD7E300237B68 /* JackCoreMidiPort.cpp */,
++ 4B370A1D133DD7E300237B68 /* JackCoreMidiPort.h */,
++ 4B370A1E133DD7E300237B68 /* JackCoreMidiUtil.cpp */,
++ 4B370A1F133DD7E300237B68 /* JackCoreMidiUtil.h */,
++ 4B370A20133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp */,
++ 4B370A21133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h */,
++ 4B370A22133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp */,
++ 4B370A23133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h */,
+ 4BF3391F0F8B873E0080FB5B /* JackMidiDriver.cpp */,
+ 4BF339200F8B873E0080FB5B /* JackMidiDriver.h */,
+ 4BF339140F8B86DC0080FB5B /* JackCoreMidiDriver.h */,
+@@ -3026,6 +3375,7 @@
+ BA222AEA0DC88379001A17F4 /* Net */ = {
+ isa = PBXGroup;
+ children = (
++ 4B8693151371DD0A00D2D11B /* JackNetAPI.cpp */,
+ 4B32256310A318E300838A8E /* netsource.c */,
+ 4B3224EC10A315C400838A8E /* netjack_packet.c */,
+ 4B3224ED10A315C400838A8E /* netjack_packet.h */,
+@@ -3086,6 +3436,13 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B2021DD133A9BA40019E213 /* Headers */ = {
++ isa = PBXHeadersBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B3224D810A3156800838A8E /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+@@ -3110,7 +3467,6 @@
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+- 4B32256C10A318FB00838A8E /* netjack.h in Headers */,
+ 4B32256E10A318FD00838A8E /* netjack_packet.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+@@ -3119,7 +3475,6 @@
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+- 4B32257E10A3195800838A8E /* netjack.h in Headers */,
+ 4B32258010A3195A00838A8E /* netjack_packet.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+@@ -3181,6 +3536,9 @@
+ 4B8A38F0117B827900664E07 /* JackSocket.h in Headers */,
+ 4B8A38F7117B82B200664E07 /* JackSocketClientChannel.h in Headers */,
+ 4B5160A813215E8B00BB7DCB /* systemdeps.h in Headers */,
++ 4B193993133F321500547810 /* JackFilters.h in Headers */,
++ 4B49D44614865F22003390F8 /* net.h in Headers */,
++ 4B49D44714865F22003390F8 /* session.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -3243,8 +3601,6 @@
+ 4BF339220F8B873E0080FB5B /* JackMidiDriver.h in Headers */,
+ 4BDCDBD21001FD0200B15929 /* JackWaitThreadedDriver.h in Headers */,
+ 4BDCDC0A1001FDA800B15929 /* JackArgParser.h in Headers */,
+- 4BCBCE6210C4FE3F00450FFE /* JackPhysicalMidiInput.h in Headers */,
+- 4BCBCE6410C4FE3F00450FFE /* JackPhysicalMidiOutput.h in Headers */,
+ 4B88D04311298BEE007A87C1 /* weakjack.h in Headers */,
+ 4B88D04411298BEE007A87C1 /* weakmacros.h in Headers */,
+ 4BC2CA5A113C6CB80076717C /* JackNetInterface.h in Headers */,
+@@ -3254,6 +3610,19 @@
+ 4B8A38B0117B812500664E07 /* JackSocketServerChannel.h in Headers */,
+ 4B8A38C4117B814000664E07 /* JackSocketServerNotifyChannel.h in Headers */,
+ 4B5160AA13215ED900BB7DCB /* systemdeps.h in Headers */,
++ 4B193995133F321500547810 /* JackFilters.h in Headers */,
++ 4B97B6611344B49500794F57 /* JackMidiAsyncQueue.h in Headers */,
++ 4B97B6631344B4A800794F57 /* JackMidiAsyncWaitQueue.h in Headers */,
++ 4B97B6651344B4B500794F57 /* JackMidiBufferReadQueue.h in Headers */,
++ 4B97B6671344B4C700794F57 /* JackMidiBufferWriteQueue.h in Headers */,
++ 4B97B66F1344B4DC00794F57 /* JackMidiReadQueue.h in Headers */,
++ 4B97B6711344B4EA00794F57 /* JackMidiReceiveQueue.h in Headers */,
++ 4B97B6781344B50800794F57 /* JackMidiSendQueue.h in Headers */,
++ 4B97B67A1344B51600794F57 /* JackMidiUtil.h in Headers */,
++ 4B97B67C1344B52800794F57 /* JackMidiWriteQueue.h in Headers */,
++ 4B21795213E2EEA60095B3E5 /* JackTimedDriver.h in Headers */,
++ 4B49D44A14865F22003390F8 /* net.h in Headers */,
++ 4B49D44B14865F22003390F8 /* session.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -3549,6 +3918,9 @@
+ 4B88D04111298BEE007A87C1 /* weakjack.h in Headers */,
+ 4B88D04211298BEE007A87C1 /* weakmacros.h in Headers */,
+ 4B5160A913215EBF00BB7DCB /* systemdeps.h in Headers */,
++ 4B193994133F321500547810 /* JackFilters.h in Headers */,
++ 4B49D44814865F22003390F8 /* net.h in Headers */,
++ 4B49D44914865F22003390F8 /* session.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -3640,6 +4012,9 @@
+ 4B88D03C11298BEE007A87C1 /* weakmacros.h in Headers */,
+ 4B2209ED12F6BC2200E5DC26 /* JackSocket.h in Headers */,
+ 4B2209EF12F6BC2500E5DC26 /* JackSocketClientChannel.h in Headers */,
++ 4B193991133F321500547810 /* JackFilters.h in Headers */,
++ 4B49D44414865F22003390F8 /* net.h in Headers */,
++ 4B49D44514865F22003390F8 /* session.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -3706,8 +4081,6 @@
+ 4BECB2F60F4451C10091B70A /* JackProcessSync.h in Headers */,
+ 4BF339240F8B873E0080FB5B /* JackMidiDriver.h in Headers */,
+ 4B94334B10A5E666002A187F /* systemdeps.h in Headers */,
+- 4BCBCE5E10C4FE3F00450FFE /* JackPhysicalMidiInput.h in Headers */,
+- 4BCBCE6010C4FE3F00450FFE /* JackPhysicalMidiOutput.h in Headers */,
+ 4B88D03D11298BEE007A87C1 /* weakjack.h in Headers */,
+ 4B88D03E11298BEE007A87C1 /* weakmacros.h in Headers */,
+ 4BC2CA56113C6C940076717C /* JackNetInterface.h in Headers */,
+@@ -3716,6 +4089,19 @@
+ 4B2209E412F6BBF600E5DC26 /* JackSocketServerNotifyChannel.h in Headers */,
+ 4B2209E712F6BC0300E5DC26 /* JackSocket.h in Headers */,
+ 4B2209EA12F6BC1600E5DC26 /* JackSocketNotifyChannel.h in Headers */,
++ 4B193992133F321500547810 /* JackFilters.h in Headers */,
++ 4B97B6391344B3C300794F57 /* JackMidiAsyncQueue.h in Headers */,
++ 4B97B63D1344B3EC00794F57 /* JackMidiAsyncWaitQueue.h in Headers */,
++ 4B97B6411344B40C00794F57 /* JackMidiBufferReadQueue.h in Headers */,
++ 4B97B6541344B42400794F57 /* JackMidiBufferWriteQueue.h in Headers */,
++ 4B97B6561344B43600794F57 /* JackMidiReadQueue.h in Headers */,
++ 4B97B6591344B44800794F57 /* JackMidiReceiveQueue.h in Headers */,
++ 4B97B65B1344B45600794F57 /* JackMidiSendQueue.h in Headers */,
++ 4B97B65D1344B46400794F57 /* JackMidiUtil.h in Headers */,
++ 4B97B65F1344B47100794F57 /* JackMidiWriteQueue.h in Headers */,
++ 4B21795013E2EEA60095B3E5 /* JackTimedDriver.h in Headers */,
++ 4B49D44214865F22003390F8 /* net.h in Headers */,
++ 4B49D44314865F22003390F8 /* session.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -3819,6 +4205,21 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B8692831371DB4700D2D11B /* Headers */ = {
++ isa = PBXHeadersBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B8692FA1371DC6300D2D11B /* JackAudioAdapterInterface.h in Headers */,
++ 4B8692FD1371DC8A00D2D11B /* JackGlobals.h in Headers */,
++ 4B86930D1371DCB000D2D11B /* JackMachThread.h in Headers */,
++ 4B8693181371DD2A00D2D11B /* JackNetInterface.h in Headers */,
++ 4B86931A1371DD4400D2D11B /* JackNetTool.h in Headers */,
++ 4B86934E1371DEBD00D2D11B /* JackLibSampleRateResampler.h in Headers */,
++ 4B49D44E14865F22003390F8 /* net.h in Headers */,
++ 4B49D44F14865F22003390F8 /* session.h in Headers */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B8F16DC13290DC80002AD73 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+@@ -3901,13 +4302,28 @@
+ 4BA3396D10B2E36800190E3B /* JackMidiDriver.h in Headers */,
+ 4BA3396E10B2E36800190E3B /* JackWaitThreadedDriver.h in Headers */,
+ 4BA3396F10B2E36800190E3B /* JackArgParser.h in Headers */,
+- 4BCBCE6610C4FE3F00450FFE /* JackPhysicalMidiInput.h in Headers */,
+- 4BCBCE6810C4FE3F00450FFE /* JackPhysicalMidiOutput.h in Headers */,
+ 4B88D04511298BEE007A87C1 /* weakjack.h in Headers */,
+ 4B88D04611298BEE007A87C1 /* weakmacros.h in Headers */,
+ 4BC2CA5E113C6CCA0076717C /* JackNetInterface.h in Headers */,
+ 4BC2CA60113C6CD20076717C /* JackNetUnixSocket.h in Headers */,
+ 4B5160AE13215EF900BB7DCB /* systemdeps.h in Headers */,
++ 4B193996133F321500547810 /* JackFilters.h in Headers */,
++ 4B6FE13A13DDABE000B4B943 /* JackSocketServerNotifyChannel.h in Headers */,
++ 4B6FE13C13DDABF100B4B943 /* JackSocketServerChannel.h in Headers */,
++ 4B6FE13E13DDAC0500B4B943 /* JackSocketNotifyChannel.h in Headers */,
++ 4B6FE14513DDAC4C00B4B943 /* JackSocket.h in Headers */,
++ 4B6FE14E13DDACD200B4B943 /* JackMidiAsyncQueue.h in Headers */,
++ 4B6FE15413DDACF300B4B943 /* JackMidiBufferWriteQueue.h in Headers */,
++ 4B6FE15B13DDAD3D00B4B943 /* JackMidiWriteQueue.h in Headers */,
++ 4B6FE15D13DDAD4E00B4B943 /* JackMidiUtil.h in Headers */,
++ 4B6FE15F13DDAD5900B4B943 /* JackMidiSendQueue.h in Headers */,
++ 4B6FE16113DDAD6600B4B943 /* JackMidiReceiveQueue.h in Headers */,
++ 4B6FE16313DDAD7700B4B943 /* JackMidiReadQueue.h in Headers */,
++ 4B6FE16513DDAD8800B4B943 /* JackMidiBufferReadQueue.h in Headers */,
++ 4B6FE16713DDAD9700B4B943 /* JackMidiAsyncWaitQueue.h in Headers */,
++ 4B21795413E2EEA60095B3E5 /* JackTimedDriver.h in Headers */,
++ 4B49D44C14865F22003390F8 /* net.h in Headers */,
++ 4B49D44D14865F22003390F8 /* session.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -3944,6 +4360,14 @@
+ buildActionMask = 2147483647;
+ files = (
+ 4BDCDB951001FB9C00B15929 /* JackCoreMidiDriver.h in Headers */,
++ 4B370A35133DD7E300237B68 /* JackCoreMidiInputPort.h in Headers */,
++ 4B370A37133DD7E300237B68 /* JackCoreMidiOutputPort.h in Headers */,
++ 4B370A39133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.h in Headers */,
++ 4B370A3B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h in Headers */,
++ 4B370A3D133DD7E300237B68 /* JackCoreMidiPort.h in Headers */,
++ 4B370A3F133DD7E300237B68 /* JackCoreMidiUtil.h in Headers */,
++ 4B370A41133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h in Headers */,
++ 4B370A43133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -4004,6 +4428,14 @@
+ buildActionMask = 2147483647;
+ files = (
+ 4BF3391A0F8B86DC0080FB5B /* JackCoreMidiDriver.h in Headers */,
++ 4B370A25133DD7E300237B68 /* JackCoreMidiInputPort.h in Headers */,
++ 4B370A27133DD7E300237B68 /* JackCoreMidiOutputPort.h in Headers */,
++ 4B370A29133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.h in Headers */,
++ 4B370A2B133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.h in Headers */,
++ 4B370A2D133DD7E300237B68 /* JackCoreMidiPort.h in Headers */,
++ 4B370A2F133DD7E300237B68 /* JackCoreMidiUtil.h in Headers */,
++ 4B370A31133DD7E300237B68 /* JackCoreMidiVirtualInputPort.h in Headers */,
++ 4B370A33133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -4137,6 +4569,25 @@
+ productReference = 4B19B3000E23620F00DD4A82 /* audioadapter.so */;
+ productType = "com.apple.product-type.library.dynamic";
+ };
++ 4B2021DC133A9BA40019E213 /* jack_midi_latency 64 bits */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4B2021E2133A9BA40019E213 /* Build configuration list for PBXNativeTarget "jack_midi_latency 64 bits" */;
++ buildPhases = (
++ 4B2021DD133A9BA40019E213 /* Headers */,
++ 4B2021DE133A9BA40019E213 /* Sources */,
++ 4B2021E0133A9BA40019E213 /* Frameworks */,
++ 4B2021E1133A9BA40019E213 /* Rez */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = "jack_midi_latency 64 bits";
++ productInstallPath = /usr/local/bin;
++ productName = jack_metro;
++ productReference = 4B2021E6133A9BA40019E213 /* jack_midi_latency_test */;
++ productType = "com.apple.product-type.tool";
++ };
+ 4B3224D710A3156800838A8E /* jack_netone Universal */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4B3224E110A3156800838A8E /* Build configuration list for PBXNativeTarget "jack_netone Universal" */;
+@@ -5314,6 +5765,25 @@
+ productReference = 4B699DB0097D421700A18468 /* jack_dummy.so */;
+ productType = "com.apple.product-type.library.dynamic";
+ };
++ 4B8692821371DB4700D2D11B /* Jacknet.framework 64 bits */ = {
++ isa = PBXNativeTarget;
++ buildConfigurationList = 4B8692D71371DB4700D2D11B /* Build configuration list for PBXNativeTarget "Jacknet.framework 64 bits" */;
++ buildPhases = (
++ 4B8692831371DB4700D2D11B /* Headers */,
++ 4B8692B21371DB4700D2D11B /* Resources */,
++ 4B8692B31371DB4700D2D11B /* Sources */,
++ 4B8692D41371DB4700D2D11B /* Rez */,
++ 4B8692D51371DB4700D2D11B /* Frameworks */,
++ );
++ buildRules = (
++ );
++ dependencies = (
++ );
++ name = "Jacknet.framework 64 bits";
++ productName = Jack;
++ productReference = 4B8692DB1371DB4700D2D11B /* Jacknet.framework */;
++ productType = "com.apple.product-type.framework";
++ };
+ 4B8F16DB13290DC80002AD73 /* jack_midi_dump Universal */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 4B8F16E113290DC80002AD73 /* Build configuration list for PBXNativeTarget "jack_midi_dump Universal" */;
+@@ -5861,9 +6331,11 @@
+ 4B47AC8010B5890100469C67 /* Jackmp.framework 64 bits debugging */,
+ 4B35C4850D4731D1000DE7AE /* Jackservermp.framework 64 bits */,
+ 4BA3393310B2E36800190E3B /* Jackservermp.framework 64 bits profiling */,
++ 4B8692821371DB4700D2D11B /* Jacknet.framework 64 bits */,
+ 4B35C50A0D4731D1000DE7AE /* jack_midiseq 64 bits */,
+ 4B35C5160D4731D1000DE7AE /* jack_midisine 64 bits */,
+ 4B8F16E813290E0E0002AD73 /* jack_midi_dump 64 bits */,
++ 4B2021DC133A9BA40019E213 /* jack_midi_latency 64 bits */,
+ 4B35C5220D4731D1000DE7AE /* jack_metro 64 bits */,
+ 4B35C52E0D4731D1000DE7AE /* jack_lsp 64 bits */,
+ 4B35C53A0D4731D1000DE7AE /* jack_connect 64 bits */,
+@@ -5942,6 +6414,13 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B8692B21371DB4700D2D11B /* Resources */ = {
++ isa = PBXResourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4BA3397010B2E36800190E3B /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+@@ -5966,6 +6445,13 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B2021E1133A9BA40019E213 /* Rez */ = {
++ isa = PBXRezBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B32255C10A3187800838A8E /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+@@ -6330,6 +6816,13 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B8692D41371DB4700D2D11B /* Rez */ = {
++ isa = PBXRezBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B8F16E013290DC80002AD73 /* Rez */ = {
+ isa = PBXRezBuildPhase;
+ buildActionMask = 2147483647;
+@@ -6474,6 +6967,14 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B2021DE133A9BA40019E213 /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B20220A133A9C1C0019E213 /* midi_latency_test.c in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B3224DC10A3156800838A8E /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+@@ -6499,7 +7000,6 @@
+ buildActionMask = 2147483647;
+ files = (
+ 4B32256410A318E300838A8E /* netsource.c in Sources */,
+- 4B32256B10A318FA00838A8E /* netjack.c in Sources */,
+ 4B32256D10A318FC00838A8E /* netjack_packet.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+@@ -6508,7 +7008,6 @@
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+- 4B32257D10A3195700838A8E /* netjack.c in Sources */,
+ 4B32257F10A3195900838A8E /* netjack_packet.c in Sources */,
+ 4B32258110A3195B00838A8E /* netsource.c in Sources */,
+ );
+@@ -6610,14 +7109,22 @@
+ 4BF339210F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */,
+ 4BDCDBD11001FD0100B15929 /* JackWaitThreadedDriver.cpp in Sources */,
+ 4BDCDC091001FDA800B15929 /* JackArgParser.cpp in Sources */,
+- 4BCBCE6110C4FE3F00450FFE /* JackPhysicalMidiInput.cpp in Sources */,
+- 4BCBCE6310C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */,
+ 4BC2CA59113C6CB60076717C /* JackNetInterface.cpp in Sources */,
+ 4BC2CA5B113C6CBE0076717C /* JackNetUnixSocket.cpp in Sources */,
+ 4B8A38A7117B80D300664E07 /* JackSocket.cpp in Sources */,
+ 4B8A38AE117B811100664E07 /* JackSocketNotifyChannel.cpp in Sources */,
+ 4B8A38B1117B812D00664E07 /* JackSocketServerChannel.cpp in Sources */,
+ 4B8A38B2117B813400664E07 /* JackSocketServerNotifyChannel.cpp in Sources */,
++ 4B97B6601344B48F00794F57 /* JackMidiAsyncQueue.cpp in Sources */,
++ 4B97B6621344B49C00794F57 /* JackMidiAsyncWaitQueue.cpp in Sources */,
++ 4B97B6641344B4AE00794F57 /* JackMidiBufferReadQueue.cpp in Sources */,
++ 4B97B6691344B4CE00794F57 /* JackMidiBufferWriteQueue.cpp in Sources */,
++ 4B97B66E1344B4D500794F57 /* JackMidiReadQueue.cpp in Sources */,
++ 4B97B6701344B4E300794F57 /* JackMidiReceiveQueue.cpp in Sources */,
++ 4B97B6721344B4F000794F57 /* JackMidiSendQueue.cpp in Sources */,
++ 4B97B6791344B50F00794F57 /* JackMidiUtil.cpp in Sources */,
++ 4B97B67B1344B51D00794F57 /* JackMidiWriteQueue.cpp in Sources */,
++ 4B21795113E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -7064,14 +7571,22 @@
+ 4BBAE4110F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */,
+ 4BECB2F50F4451C10091B70A /* JackProcessSync.cpp in Sources */,
+ 4BF339230F8B873E0080FB5B /* JackMidiDriver.cpp in Sources */,
+- 4BCBCE5D10C4FE3F00450FFE /* JackPhysicalMidiInput.cpp in Sources */,
+- 4BCBCE5F10C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */,
+ 4BC2CA55113C6C930076717C /* JackNetInterface.cpp in Sources */,
+ 4BC2CA57113C6C9B0076717C /* JackNetUnixSocket.cpp in Sources */,
+ 4B2209E112F6BBF300E5DC26 /* JackSocketServerChannel.cpp in Sources */,
+ 4B2209E312F6BBF500E5DC26 /* JackSocketServerNotifyChannel.cpp in Sources */,
+ 4B2209E612F6BC0200E5DC26 /* JackSocket.cpp in Sources */,
+ 4B2209E912F6BC1500E5DC26 /* JackSocketNotifyChannel.cpp in Sources */,
++ 4B97B6381344B3C100794F57 /* JackMidiAsyncQueue.cpp in Sources */,
++ 4B97B63A1344B3C700794F57 /* JackMidiAsyncWaitQueue.cpp in Sources */,
++ 4B97B63E1344B3F100794F57 /* JackMidiBufferReadQueue.cpp in Sources */,
++ 4B97B6531344B41E00794F57 /* JackMidiBufferWriteQueue.cpp in Sources */,
++ 4B97B6571344B43A00794F57 /* JackMidiReadQueue.cpp in Sources */,
++ 4B97B6581344B43F00794F57 /* JackMidiReceiveQueue.cpp in Sources */,
++ 4B97B65A1344B44F00794F57 /* JackMidiSendQueue.cpp in Sources */,
++ 4B97B65C1344B45D00794F57 /* JackMidiUtil.cpp in Sources */,
++ 4B97B65E1344B46B00794F57 /* JackMidiWriteQueue.cpp in Sources */,
++ 4B21794F13E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -7186,6 +7701,25 @@
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
++ 4B8692B31371DB4700D2D11B /* Sources */ = {
++ isa = PBXSourcesBuildPhase;
++ buildActionMask = 2147483647;
++ files = (
++ 4B8692F81371DC5200D2D11B /* JackAudioAdapterInterface.cpp in Sources */,
++ 4B8692FB1371DC7100D2D11B /* JackGlobals.cpp in Sources */,
++ 4B8692FE1371DC9700D2D11B /* JackMachThread.cpp in Sources */,
++ 4B8693141371DCCA00D2D11B /* JackMachTime.c in Sources */,
++ 4B8693161371DD0A00D2D11B /* JackNetAPI.cpp in Sources */,
++ 4B8693171371DD2400D2D11B /* JackNetInterface.cpp in Sources */,
++ 4B8693191371DD3B00D2D11B /* JackNetTool.cpp in Sources */,
++ 4B86931B1371DD4C00D2D11B /* JackNetUnixSocket.cpp in Sources */,
++ 4B8693231371DD6000D2D11B /* JackPosixThread.cpp in Sources */,
++ 4B8693251371DD7E00D2D11B /* JackResampler.cpp in Sources */,
++ 4B86932C1371DD9B00D2D11B /* ringbuffer.c in Sources */,
++ 4B86934D1371DEBA00D2D11B /* JackLibSampleRateResampler.cpp in Sources */,
++ );
++ runOnlyForDeploymentPostprocessing = 0;
++ };
+ 4B8F16DD13290DC80002AD73 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+@@ -7260,10 +7794,22 @@
+ 4BA339A210B2E36800190E3B /* JackMidiDriver.cpp in Sources */,
+ 4BA339A310B2E36800190E3B /* JackWaitThreadedDriver.cpp in Sources */,
+ 4BA339A410B2E36800190E3B /* JackArgParser.cpp in Sources */,
+- 4BCBCE6510C4FE3F00450FFE /* JackPhysicalMidiInput.cpp in Sources */,
+- 4BCBCE6710C4FE3F00450FFE /* JackPhysicalMidiOutput.cpp in Sources */,
+ 4BC2CA5D113C6CC90076717C /* JackNetInterface.cpp in Sources */,
+ 4BC2CA5F113C6CD10076717C /* JackNetUnixSocket.cpp in Sources */,
++ 4B6FE13B13DDABE700B4B943 /* JackSocketServerNotifyChannel.cpp in Sources */,
++ 4B6FE13D13DDABFA00B4B943 /* JackSocketServerChannel.cpp in Sources */,
++ 4B6FE13F13DDAC0C00B4B943 /* JackSocketNotifyChannel.cpp in Sources */,
++ 4B6FE14413DDAC4700B4B943 /* JackSocket.cpp in Sources */,
++ 4B6FE14D13DDACCC00B4B943 /* JackMidiAsyncQueue.cpp in Sources */,
++ 4B6FE15313DDACEF00B4B943 /* JackMidiBufferWriteQueue.cpp in Sources */,
++ 4B6FE15C13DDAD4600B4B943 /* JackMidiWriteQueue.cpp in Sources */,
++ 4B6FE15E13DDAD5300B4B943 /* JackMidiUtil.cpp in Sources */,
++ 4B6FE16013DDAD5F00B4B943 /* JackMidiSendQueue.cpp in Sources */,
++ 4B6FE16213DDAD6F00B4B943 /* JackMidiReceiveQueue.cpp in Sources */,
++ 4B6FE16413DDAD7F00B4B943 /* JackMidiReadQueue.cpp in Sources */,
++ 4B6FE16613DDAD8F00B4B943 /* JackMidiBufferReadQueue.cpp in Sources */,
++ 4B6FE16813DDAD9F00B4B943 /* JackMidiAsyncWaitQueue.cpp in Sources */,
++ 4B21795313E2EEA60095B3E5 /* JackTimedDriver.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -7304,6 +7850,14 @@
+ buildActionMask = 2147483647;
+ files = (
+ 4BDCDB971001FB9C00B15929 /* JackCoreMidiDriver.cpp in Sources */,
++ 4B370A34133DD7E300237B68 /* JackCoreMidiInputPort.cpp in Sources */,
++ 4B370A36133DD7E300237B68 /* JackCoreMidiOutputPort.cpp in Sources */,
++ 4B370A38133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.cpp in Sources */,
++ 4B370A3A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp in Sources */,
++ 4B370A3C133DD7E300237B68 /* JackCoreMidiPort.cpp in Sources */,
++ 4B370A3E133DD7E300237B68 /* JackCoreMidiUtil.cpp in Sources */,
++ 4B370A40133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp in Sources */,
++ 4B370A42133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -7369,6 +7923,14 @@
+ buildActionMask = 2147483647;
+ files = (
+ 4BF3391B0F8B86DC0080FB5B /* JackCoreMidiDriver.cpp in Sources */,
++ 4B370A24133DD7E300237B68 /* JackCoreMidiInputPort.cpp in Sources */,
++ 4B370A26133DD7E300237B68 /* JackCoreMidiOutputPort.cpp in Sources */,
++ 4B370A28133DD7E300237B68 /* JackCoreMidiPhysicalInputPort.cpp in Sources */,
++ 4B370A2A133DD7E300237B68 /* JackCoreMidiPhysicalOutputPort.cpp in Sources */,
++ 4B370A2C133DD7E300237B68 /* JackCoreMidiPort.cpp in Sources */,
++ 4B370A2E133DD7E300237B68 /* JackCoreMidiUtil.cpp in Sources */,
++ 4B370A30133DD7E300237B68 /* JackCoreMidiVirtualInputPort.cpp in Sources */,
++ 4B370A32133DD7E300237B68 /* JackCoreMidiVirtualOutputPort.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+@@ -7470,6 +8032,11 @@
+ target = 4B19B2F60E23620F00DD4A82 /* audioadapter Universal */;
+ targetProxy = 4B19B32B0E23636E00DD4A82 /* PBXContainerItemProxy */;
+ };
++ 4B20220C133A9C370019E213 /* PBXTargetDependency */ = {
++ isa = PBXTargetDependency;
++ target = 4B2021DC133A9BA40019E213 /* jack_midi_latency 64 bits */;
++ targetProxy = 4B20220B133A9C370019E213 /* PBXContainerItemProxy */;
++ };
+ 4B224B340E65BA330066BE5B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4B5E08BF0E5B66EE00BEE4E0 /* netadapter Universal */;
+@@ -7725,6 +8292,11 @@
+ target = 4BA7FEB90D8E76270017FF73 /* jack_server_control Universal */;
+ targetProxy = 4BA7FECC0D8E76810017FF73 /* PBXContainerItemProxy */;
+ };
++ 4BB492A71372A393005F2601 /* PBXTargetDependency */ = {
++ isa = PBXTargetDependency;
++ target = 4B8692821371DB4700D2D11B /* Jacknet.framework 64 bits */;
++ targetProxy = 4BB492A61372A393005F2601 /* PBXContainerItemProxy */;
++ };
+ 4BD624D30CBCF55700DE782F /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 4BD623ED0CBCF0F000DE782F /* inprocess Universal */;
+@@ -8000,12 +8572,8 @@
+ 4B0A292C0D52108E002EFF74 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- ppc64,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -8054,7 +8622,7 @@
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
+ OTHER_LDFLAGS = (
+- /usr/local/lib/libsamplerate.a,
++ /opt/local/lib/libsamplerate.a,
+ "-framework",
+ Jackservermp,
+ "-framework",
+@@ -8173,6 +8741,97 @@
+ };
+ name = Default;
+ };
++ 4B2021E3133A9BA40019E213 /* Development */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ COPY_PHASE_STRIP = NO;
++ FRAMEWORK_SEARCH_PATHS = "";
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_ENABLE_FIX_AND_CONTINUE = YES;
++ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ HEADER_SEARCH_PATHS = ../common;
++ OTHER_CFLAGS = "";
++ OTHER_LDFLAGS = (
++ "-framework",
++ Jackmp,
++ "-framework",
++ CoreFoundation,
++ );
++ OTHER_REZFLAGS = "";
++ PRODUCT_NAME = jack_midi_latency_test;
++ REZ_EXECUTABLE = YES;
++ SDKROOT = "";
++ SECTORDER_FLAGS = "";
++ WARNING_CFLAGS = (
++ "-Wmost",
++ "-Wno-four-char-constants",
++ "-Wno-unknown-pragmas",
++ );
++ ZERO_LINK = YES;
++ };
++ name = Development;
++ };
++ 4B2021E4133A9BA40019E213 /* Deployment */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ COPY_PHASE_STRIP = YES;
++ FRAMEWORK_SEARCH_PATHS = "";
++ GCC_ENABLE_FIX_AND_CONTINUE = NO;
++ HEADER_SEARCH_PATHS = ../common;
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
++ OTHER_CFLAGS = "";
++ OTHER_LDFLAGS = (
++ "-framework",
++ Jackmp,
++ "-framework",
++ CoreFoundation,
++ );
++ OTHER_REZFLAGS = "";
++ PRODUCT_NAME = jack_midi_latency_test;
++ REZ_EXECUTABLE = YES;
++ SDKROOT = "";
++ SECTORDER_FLAGS = "";
++ WARNING_CFLAGS = (
++ "-Wmost",
++ "-Wno-four-char-constants",
++ "-Wno-unknown-pragmas",
++ );
++ ZERO_LINK = NO;
++ };
++ name = Deployment;
++ };
++ 4B2021E5133A9BA40019E213 /* Default */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ FRAMEWORK_SEARCH_PATHS = "";
++ HEADER_SEARCH_PATHS = ../common;
++ OTHER_CFLAGS = "";
++ OTHER_LDFLAGS = (
++ "-framework",
++ Jackmp,
++ "-framework",
++ CoreFoundation,
++ );
++ OTHER_REZFLAGS = "";
++ PRODUCT_NAME = jack_midisine;
++ REZ_EXECUTABLE = YES;
++ SDKROOT = "";
++ SECTORDER_FLAGS = "";
++ WARNING_CFLAGS = (
++ "-Wmost",
++ "-Wno-four-char-constants",
++ "-Wno-unknown-pragmas",
++ );
++ };
++ name = Default;
++ };
+ 4B3224E210A3156800838A8E /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+@@ -8481,15 +9140,19 @@
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+- HEADER_SEARCH_PATHS = ../common;
++ HEADER_SEARCH_PATHS = (
++ ../macosx,
++ ../common,
++ );
+ OTHER_CFLAGS = (
++ "-DNO_JACK_ERROR",
+ "-DHAVE_CELT",
+ "-DHAVE_CELT_API_0_7",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DNO_JACK_ERROR",
+ "-DHAVE_CELT",
+ "-DHAVE_CELT_API_0_7",
+- "$(OTHER_CFLAGS)",
+ );
+ OTHER_LDFLAGS = (
+ libcelt.a,
+@@ -8522,16 +9185,20 @@
+ COPY_PHASE_STRIP = YES;
+ FRAMEWORK_SEARCH_PATHS = "";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+- HEADER_SEARCH_PATHS = ../common;
++ HEADER_SEARCH_PATHS = (
++ ../macosx,
++ ../common,
++ );
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = (
++ "-DNO_JACK_ERROR",
+ "-DHAVE_CELT",
+ "-DHAVE_CELT_API_0_7",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DNO_JACK_ERROR",
+ "-DHAVE_CELT",
+ "-DHAVE_CELT_API_0_7",
+- "$(OTHER_CFLAGS)",
+ );
+ OTHER_LDFLAGS = (
+ libcelt.a,
+@@ -8599,8 +9266,12 @@
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+- HEADER_SEARCH_PATHS = ../common;
++ HEADER_SEARCH_PATHS = (
++ ../macosx,
++ ../common,
++ );
+ OTHER_CFLAGS = (
++ "-DNO_JACK_ERROR",
+ "-DHAVE_CELT",
+ "-DHAVE_CELT_API_0_7",
+ );
+@@ -8634,9 +9305,13 @@
+ COPY_PHASE_STRIP = YES;
+ FRAMEWORK_SEARCH_PATHS = "";
+ GCC_ENABLE_FIX_AND_CONTINUE = NO;
+- HEADER_SEARCH_PATHS = ../common;
++ HEADER_SEARCH_PATHS = (
++ ../macosx,
++ ../common,
++ );
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = (
++ "-DNO_JACK_ERROR",
+ "-DHAVE_CELT",
+ "-DHAVE_CELT_API_0_7",
+ );
+@@ -8665,10 +9340,8 @@
+ 4B32257A10A3190C00838A8E /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = (
+@@ -8734,7 +9407,7 @@
+ );
+ OTHER_LDFLAGS = (
+ "-framework",
+- Jackdmp,
++ Jackservermp,
+ "-framework",
+ CoreAudio,
+ "-framework",
+@@ -8815,12 +9488,8 @@
+ 4B35C4240D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ FRAMEWORK_SEARCH_PATHS = "";
+ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+@@ -9001,12 +9670,8 @@
+ 4B35C4820D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -9100,21 +9765,25 @@
+ "-DUSE_POSIX_SHM",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DSERVER_SIDE",
+ "-DJACK_32_64",
+ "-D__SMP__",
+ "-DMACH_RPC_MACH_SEMA",
+ "$(OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1)",
++ "$(OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2)",
+ );
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
+ "-framework",
+ Carbon,
+ "-framework",
+ CoreAudio,
+ );
+ OTHER_REZFLAGS = "";
+- PRODUCT_NAME = Jackdmp;
++ PRODUCT_NAME = Jackservermp;
+ REZ_EXECUTABLE = NO;
+ SDKROOT = "";
+ SECTORDER_FLAGS = "";
+@@ -9166,6 +9835,8 @@
+ "-DUSE_POSIX_SHM",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DSERVER_SIDE",
+ "-DJACK_32_64",
+ "-D__SMP__",
+@@ -9176,6 +9847,7 @@
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DLIB_DIR=\\\"lib\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
+ "-framework",
+ Carbon,
+ "-framework",
+@@ -9194,12 +9866,8 @@
+ 4B35C4FB0D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -9319,12 +9987,8 @@
+ 4B35C5130D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -9414,12 +10078,8 @@
+ 4B35C51F0D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -9509,12 +10169,8 @@
+ 4B35C52B0D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -9600,12 +10256,8 @@
+ 4B35C5370D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -9689,12 +10341,8 @@
+ 4B35C5430D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = (
+@@ -9776,12 +10424,8 @@
+ 4B35C54F0D4731D1000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = (
+@@ -9866,12 +10510,8 @@
+ 4B35C55D0D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = (
+@@ -9956,12 +10596,8 @@
+ 4B35C5690D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -10051,12 +10687,8 @@
+ 4B35C5750D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -10083,12 +10715,8 @@
+ 4B35C5830D4731D2000DE7AE /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+@@ -10164,12 +10792,8 @@
+ 4B35C5850D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PRECOMPILE_PREFIX_HEADER = YES;
+ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
+@@ -10197,12 +10821,8 @@
+ 4B35C5970D4731D2000DE7AE /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+@@ -10268,12 +10888,8 @@
+ 4B35C5990D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = (
+@@ -10358,12 +10974,8 @@
+ 4B35C5A50D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = (
+@@ -10446,12 +11058,8 @@
+ 4B35C5B10D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -10534,12 +11142,8 @@
+ 4B35C5BD0D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -10622,12 +11226,8 @@
+ 4B35C5C90D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -10710,12 +11310,8 @@
+ 4B35C5D50D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -10739,12 +11335,8 @@
+ 4B35C5E70D4731D2000DE7AE /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+@@ -10820,12 +11412,8 @@
+ 4B35C5E90D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
+@@ -10855,12 +11443,8 @@
+ 4B35C5FB0D4731D2000DE7AE /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+@@ -10935,12 +11519,8 @@
+ 4B35C5FD0D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
+@@ -10970,12 +11550,8 @@
+ 4B35C60F0D4731D2000DE7AE /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ COPY_PHASE_STRIP = NO;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_FIX_AND_CONTINUE = YES;
+@@ -11050,12 +11626,8 @@
+ 4B35C6110D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
+@@ -11107,11 +11679,15 @@
+ INSTALL_PATH = /usr/local/lib;
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+- OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CFLAGS = "-DJACK_32_64";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DSERVER_SIDE",
++ "-DMACH_RPC_MACH_SEMA",
++ "-DJACK_32_64",
++ );
+ OTHER_LDFLAGS = (
+ "-framework",
+- Jackdmp,
++ Jackservermp,
+ "-framework",
+ CoreAudio,
+ "-framework",
+@@ -11189,12 +11765,8 @@
+ 4B35C61D0D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = so;
+@@ -11235,12 +11807,8 @@
+ 4B35C6260D4731D2000DE7AE /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ COPY_PHASE_STRIP = NO;
+ DEBUGGING_SYMBOLS = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+@@ -11261,7 +11829,7 @@
+ OTHER_LDFLAGS = (
+ libportaudio.a,
+ "-framework",
+- Jackdmp,
++ Jackservermp,
+ "-framework",
+ AudioToolbox,
+ "-framework",
+@@ -11338,12 +11906,8 @@
+ 4B35C6280D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = so;
+@@ -11406,11 +11970,15 @@
+ INSTALL_PATH = /usr/local/lib;
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+- OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CFLAGS = "-DJACK_32_64";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DSERVER_SIDE",
++ "-DMACH_RPC_MACH_SEMA",
++ "-DJACK_32_64",
++ );
+ OTHER_LDFLAGS = (
+ "-framework",
+- Jackdmp,
++ Jackservermp,
+ "-framework",
+ CoreAudio,
+ "-framework",
+@@ -11483,12 +12051,8 @@
+ 4B35C6330D4731D2000DE7AE /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = so;
+@@ -11548,7 +12112,7 @@
+ OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
+ OTHER_LDFLAGS = (
+ "-framework",
+- Jackdmp,
++ Jackservermp,
+ "-framework",
+ CoreAudio,
+ "-framework",
+@@ -12573,10 +13137,8 @@
+ 4B3811961326884E00C61B14 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -12840,10 +13402,8 @@
+ 4B43A8E61014615800E52943 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = so;
+@@ -13014,12 +13574,8 @@
+ 4B47ACD610B5890100469C67 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -13292,7 +13848,10 @@
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT",
++ "-DMACH_RPC_MACH_SEMA",
++ );
+ OTHER_LDFLAGS = (
+ /usr/local/lib/libsamplerate.a,
+ "-framework",
+@@ -13343,7 +13902,10 @@
+ MACH_O_TYPE = mh_dylib;
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT",
++ "-DMACH_RPC_MACH_SEMA",
++ );
+ OTHER_LDFLAGS = (
+ /opt/local/lib/libsamplerate.a,
+ "-framework",
+@@ -13475,12 +14037,8 @@
+ 4B6654F6127C34AE00753A79 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ GCC_OPTIMIZATION_LEVEL = 3;
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -13755,6 +14313,7 @@
+ INFOPLIST_FILE = "Jack-Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3;
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = (
+ "-DUSE_POSIX_SHM",
+ "-D__SMP__",
+@@ -13869,6 +14428,7 @@
+ INFOPLIST_FILE = "Jack-Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3;
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = (
+ "-DUSE_POSIX_SHM",
+ "-D__SMP__",
+@@ -13901,8 +14461,10 @@
+ 4B699CA9097D421600A18468 /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+- ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ ARCHS = (
++ i386,
++ ppc,
++ );
+ COPY_PHASE_STRIP = NO;
+ DEBUGGING_SYMBOLS = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+@@ -13927,12 +14489,15 @@
+ INFOPLIST_FILE = "Jack-Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3;
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = (
+ "-DSERVER_SIDE",
+ "-D__SMP__",
+ "-DUSE_POSIX_SHM",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DSERVER_SIDE",
+ "-D__SMP__",
+ "-DMACH_RPC_MACH_SEMA",
+@@ -13940,6 +14505,7 @@
+ );
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
+ "-framework",
+ Carbon,
+ "-framework",
+@@ -13958,8 +14524,10 @@
+ 4B699CAA097D421600A18468 /* Deployment */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
+- ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ ARCHS = (
++ i386,
++ ppc,
++ );
+ COPY_PHASE_STRIP = YES;
+ DEAD_CODE_STRIPPING = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+@@ -13993,6 +14561,8 @@
+ "-DUSE_POSIX_SHM",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DSERVER_SIDE",
+ "-D__SMP__",
+ "-DMACH_RPC_MACH_SEMA",
+@@ -14002,6 +14572,7 @@
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DLIB_DIR=\\\"lib\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
+ "-framework",
+ Carbon,
+ "-framework",
+@@ -14040,6 +14611,7 @@
+ INFOPLIST_FILE = "Jack-Info.plist";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3;
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = (
+ "-D__SMP__",
+ "-DUSE_POSIX_SHM",
+@@ -15579,89 +16151,288 @@
+ .,
+ ../posix,
+ );
+- INSTALL_PATH = /usr/local/lib;
+- LIBRARY_STYLE = DYNAMIC;
+- MACH_O_TYPE = mh_dylib;
+- MACOSX_DEPLOYMENT_TARGET = 10.4;
+- OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ INSTALL_PATH = /usr/local/lib;
++ LIBRARY_STYLE = DYNAMIC;
++ MACH_O_TYPE = mh_dylib;
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
++ OTHER_CFLAGS = "";
++ OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_LDFLAGS = (
++ "-framework",
++ Jackservermp,
++ "-framework",
++ CoreServices,
++ );
++ OTHER_REZFLAGS = "";
++ PREBINDING = NO;
++ PRODUCT_NAME = jack_dummy;
++ SDKROOT = "";
++ SECTORDER_FLAGS = "";
++ WARNING_CFLAGS = (
++ "-Wmost",
++ "-Wno-four-char-constants",
++ "-Wno-unknown-pragmas",
++ );
++ ZERO_LINK = NO;
++ };
++ name = Deployment;
++ };
++ 4B699DAF097D421700A18468 /* Default */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = (
++ i386,
++ ppc,
++ );
++ DYLIB_COMPATIBILITY_VERSION = 1;
++ DYLIB_CURRENT_VERSION = 1;
++ EXECUTABLE_EXTENSION = so;
++ GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
++ GCC_MODEL_TUNING = G4;
++ INSTALL_PATH = /usr/local/lib;
++ LIBRARY_STYLE = DYNAMIC;
++ MACH_O_TYPE = mh_dylib;
++ OTHER_CFLAGS = "";
++ OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_LDFLAGS = (
++ "-framework",
++ Jackdmp,
++ "-framework",
++ AudioToolBox,
++ "-framework",
++ CoreAudio,
++ "-framework",
++ CoreServices,
++ "-framework",
++ AudioUnit,
++ );
++ OTHER_REZFLAGS = "";
++ PREBINDING = NO;
++ PRODUCT_NAME = jack_dummy;
++ SDKROOT = "";
++ SECTORDER_FLAGS = "";
++ WARNING_CFLAGS = (
++ "-Wmost",
++ "-Wno-four-char-constants",
++ "-Wno-unknown-pragmas",
++ );
++ };
++ name = Default;
++ };
++ 4B699DD6097D427F00A18468 /* Development */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ };
++ name = Development;
++ };
++ 4B699DD7097D427F00A18468 /* Deployment */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ };
++ name = Deployment;
++ };
++ 4B699DD8097D427F00A18468 /* Default */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ };
++ name = Default;
++ };
++ 4B8692D81371DB4700D2D11B /* Development */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ COPY_PHASE_STRIP = NO;
++ DEBUGGING_SYMBOLS = YES;
++ DEBUG_INFORMATION_FORMAT = dwarf;
++ DYLIB_COMPATIBILITY_VERSION = 1;
++ DYLIB_CURRENT_VERSION = 1;
++ FRAMEWORK_SEARCH_PATHS = (
++ "$(inherited)",
++ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
++ );
++ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Development\"";
++ FRAMEWORK_VERSION = A;
++ GCC_DYNAMIC_NO_PIC = NO;
++ GCC_ENABLE_FIX_AND_CONTINUE = YES;
++ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
++ GCC_OPTIMIZATION_LEVEL = 0;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
++ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
++ GCC_WARN_UNKNOWN_PRAGMAS = NO;
++ GENERATE_PKGINFO_FILE = NO;
++ HEADER_SEARCH_PATHS = (
++ /opt/local/include,
++ ../common,
++ ../posix,
++ RPC,
++ ../common/jack,
++ );
++ INFOPLIST_FILE = "Jack-Info.plist";
++ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
++ LIBRARY_SEARCH_PATHS = (
++ /opt/local/lib,
++ /usr/lib/gcc/darwin/3.3,
++ );
++ OTHER_CFLAGS = (
++ "-DUSE_POSIX_SHM",
++ "-DJACK_32_64",
++ "-D__SMP__",
++ );
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
++ "-DSERVER_SIDE",
++ "-DMACH_RPC_MACH_SEMA",
++ "-D__SMP__",
++ "-DJACK_32_64",
++ );
++ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DJACK_LOCATION=\\\"/usr/local/bin\\\"";
++ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
++ OTHER_LDFLAGS = (
++ libcelt.a,
++ /opt/local/lib/libsamplerate.a,
++ "-framework",
++ CoreAudio,
++ );
++ OTHER_REZFLAGS = "";
++ PRODUCT_NAME = Jacknet;
++ REZ_EXECUTABLE = NO;
++ SDKROOT = "";
++ SECTORDER_FLAGS = "";
++ WARNING_CFLAGS = "-Wmost";
++ ZERO_LINK = YES;
++ };
++ name = Development;
++ };
++ 4B8692D91371DB4700D2D11B /* Deployment */ = {
++ isa = XCBuildConfiguration;
++ buildSettings = {
++ ARCHS = (
++ x86_64,
++ i386,
++ );
++ COPY_PHASE_STRIP = YES;
++ DEAD_CODE_STRIPPING = YES;
++ DEBUG_INFORMATION_FORMAT = dwarf;
++ DYLIB_COMPATIBILITY_VERSION = 1;
++ DYLIB_CURRENT_VERSION = 1;
++ FRAMEWORK_SEARCH_PATHS = (
++ "$(inherited)",
++ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
++ );
++ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Development\"";
++ FRAMEWORK_VERSION = A;
++ GCC_AUTO_VECTORIZATION = YES;
++ GCC_ENABLE_FIX_AND_CONTINUE = NO;
++ GCC_ENABLE_SSE3_EXTENSIONS = YES;
++ GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS = YES;
++ GCC_OPTIMIZATION_LEVEL = 3;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
++ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
++ GCC_WARN_UNKNOWN_PRAGMAS = NO;
++ GENERATE_PKGINFO_FILE = NO;
++ HEADER_SEARCH_PATHS = (
++ /opt/local/include,
++ ../common,
++ ../posix,
++ RPC,
++ ../common/jack,
++ );
++ INFOPLIST_FILE = "Jack-Info.plist";
++ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
++ LIBRARY_SEARCH_PATHS = (
++ /opt/local/lib,
++ /usr/lib/gcc/darwin/3.3,
++ );
++ MACOSX_DEPLOYMENT_TARGET = 10.4;
++ OTHER_CFLAGS = (
++ "-DUSE_POSIX_SHM",
++ "-DJACK_32_64",
++ "-D__SMP__",
++ );
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
++ "-DSERVER_SIDE",
++ "-DMACH_RPC_MACH_SEMA",
++ "-DJACK_32_64",
++ "-D__SMP__",
++ );
++ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
++ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DJACK_LOCATION=\\\"/usr/local/bin\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
++ /opt/local/lib/libsamplerate.a,
+ "-framework",
+- Jackservermp,
+- "-framework",
+- CoreServices,
++ CoreAudio,
+ );
+ OTHER_REZFLAGS = "";
+- PREBINDING = NO;
+- PRODUCT_NAME = jack_dummy;
++ PRODUCT_NAME = Jacknet;
++ REZ_EXECUTABLE = NO;
+ SDKROOT = "";
+ SECTORDER_FLAGS = "";
+- WARNING_CFLAGS = (
+- "-Wmost",
+- "-Wno-four-char-constants",
+- "-Wno-unknown-pragmas",
+- );
++ WARNING_CFLAGS = "-Wmost";
+ ZERO_LINK = NO;
+ };
+ name = Deployment;
+ };
+- 4B699DAF097D421700A18468 /* Default */ = {
++ 4B8692DA1371DB4700D2D11B /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
++ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+- EXECUTABLE_EXTENSION = so;
+- GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+- GCC_MODEL_TUNING = G4;
+- INSTALL_PATH = /usr/local/lib;
+- LIBRARY_STYLE = DYNAMIC;
+- MACH_O_TYPE = mh_dylib;
+- OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ FRAMEWORK_SEARCH_PATHS = (
++ "$(inherited)",
++ "$(FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1)",
++ );
++ FRAMEWORK_SEARCH_PATHS_QUOTED_FOR_TARGET_1 = "\"$(SRCROOT)/build/Development\"";
++ FRAMEWORK_VERSION = A;
++ GCC_PRECOMPILE_PREFIX_HEADER = YES;
++ GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h";
++ GCC_WARN_FOUR_CHARACTER_CONSTANTS = NO;
++ GCC_WARN_UNKNOWN_PRAGMAS = NO;
++ GENERATE_PKGINFO_FILE = NO;
++ HEADER_SEARCH_PATHS = (
++ RPC,
++ ../common/jack,
++ );
++ INFOPLIST_FILE = "Jack-Info copy.plist";
++ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
++ LIBRARY_SEARCH_PATHS = /usr/lib/gcc/darwin/3.3;
++ OTHER_CFLAGS = (
++ "-DUSE_POSIX_SHM",
++ "-DJACK_32_64",
++ "-D__SMP__",
++ );
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DMACH_RPC_MACH_SEMA",
++ "-DJACK_32_64",
++ "-D__SMP__",
++ "$(OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1)",
++ "$(OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2)",
++ );
++ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DJACK_LOCATION=\\\"/usr/local/bin\\\"";
++ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_LDFLAGS = (
+ "-framework",
+- Jackdmp,
++ Carbon,
+ "-framework",
+ AudioToolBox,
+ "-framework",
+ CoreAudio,
+- "-framework",
+- CoreServices,
+- "-framework",
+- AudioUnit,
+ );
+ OTHER_REZFLAGS = "";
+- PREBINDING = NO;
+- PRODUCT_NAME = jack_dummy;
++ PRODUCT_NAME = Jackmp;
++ REZ_EXECUTABLE = NO;
+ SDKROOT = "";
+ SECTORDER_FLAGS = "";
+- WARNING_CFLAGS = (
+- "-Wmost",
+- "-Wno-four-char-constants",
+- "-Wno-unknown-pragmas",
+- );
+- };
+- name = Default;
+- };
+- 4B699DD6097D427F00A18468 /* Development */ = {
+- isa = XCBuildConfiguration;
+- buildSettings = {
+- };
+- name = Development;
+- };
+- 4B699DD7097D427F00A18468 /* Deployment */ = {
+- isa = XCBuildConfiguration;
+- buildSettings = {
+- };
+- name = Deployment;
+- };
+- 4B699DD8097D427F00A18468 /* Default */ = {
+- isa = XCBuildConfiguration;
+- buildSettings = {
++ WARNING_CFLAGS = "-Wmost";
+ };
+ name = Default;
+ };
+@@ -15829,12 +16600,8 @@
+ 4B8F16F113290E0E0002AD73 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -16045,6 +16812,8 @@
+ "-DUSE_POSIX_SHM",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DJACK_MONITOR",
+ "-DSERVER_SIDE",
+ "-DJACK_32_64",
+@@ -16054,13 +16823,14 @@
+ );
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
+ "-framework",
+ Carbon,
+ "-framework",
+ CoreAudio,
+ );
+ OTHER_REZFLAGS = "";
+- PRODUCT_NAME = Jackdmp;
++ PRODUCT_NAME = Jackservermp;
+ REZ_EXECUTABLE = NO;
+ SDKROOT = "";
+ SECTORDER_FLAGS = "";
+@@ -16113,6 +16883,8 @@
+ "-DUSE_POSIX_SHM",
+ );
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DJACK_MONITOR",
+ "-DSERVER_SIDE",
+ "-DJACK_32_64",
+@@ -16124,6 +16896,7 @@
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_1 = "-DADDON_DIR=\\\"/usr/local/lib/jackmp\\\"";
+ OTHER_CPLUSPLUSFLAGS_QUOTED_FOR_TARGET_2 = "-DLIB_DIR=\\\"lib\\\"";
+ OTHER_LDFLAGS = (
++ libcelt.a,
+ "-framework",
+ Carbon,
+ "-framework",
+@@ -16142,12 +16915,8 @@
+ 4BA339AB10B2E36800190E3B /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -16714,10 +17483,8 @@
+ 4BDCDB9C1001FB9C00B15929 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = so;
+@@ -16781,16 +17548,16 @@
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
++ "-DMACH_RPC_MACH_SEMA",
++ );
+ OTHER_LDFLAGS = (
+ "-framework",
+ Jackservermp,
+ "-framework",
+- CoreAudio,
+- "-framework",
+ CoreServices,
+- "-framework",
+- AudioUnit,
+ );
+ OTHER_REZFLAGS = "";
+ PREBINDING = NO;
+@@ -16830,6 +17597,8 @@
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = "-DJACK_32_64";
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
+ "-DSERVER_SIDE",
+ "-DMACH_RPC_MACH_SEMA",
+ "-DJACK_32_64",
+@@ -16857,10 +17626,8 @@
+ 4BDCDBC41001FCC000B15929 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ EXECUTABLE_EXTENSION = so;
+@@ -17046,7 +17813,10 @@
+ 4BDCDBFC1001FD7300B15929 /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = "$(NATIVE_ARCH_ACTUAL)";
++ ARCHS = (
++ i386,
++ x86_64,
++ );
+ COPY_PHASE_STRIP = NO;
+ DEBUGGING_SYMBOLS = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+@@ -17071,7 +17841,7 @@
+ OTHER_CFLAGS = "";
+ OTHER_CPLUSPLUSFLAGS = "$(OTHER_CFLAGS)";
+ OTHER_LDFLAGS = (
+- /usr/local/lib/libsamplerate.a,
++ /opt/local/lib/libsamplerate.a,
+ "-framework",
+ Jackservermp,
+ "-framework",
+@@ -17098,7 +17868,10 @@
+ 4BDCDBFD1001FD7300B15929 /* Deployment */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = "$(NATIVE_ARCH_ACTUAL)";
++ ARCHS = (
++ i386,
++ x86_64,
++ );
+ COPY_PHASE_STRIP = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -17153,7 +17926,7 @@
+ buildSettings = {
+ ARCHS = (
+ i386,
+- ppc,
++ x86_64,
+ );
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -17195,7 +17968,10 @@
+ 4BDCDC221001FDE300B15929 /* Development */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = "$(NATIVE_ARCH_ACTUAL)";
++ ARCHS = (
++ i386,
++ x86_64,
++ );
+ COPY_PHASE_STRIP = NO;
+ DEBUGGING_SYMBOLS = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+@@ -17217,10 +17993,15 @@
+ INSTALL_PATH = /usr/local/lib;
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+- OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CFLAGS = "-DJACK_32_64";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DJACK_32_64",
++ "-DHAVE_CELT",
++ "-DSERVER_SIDE",
++ "-DMACH_RPC_MACH_SEMA",
++ );
+ OTHER_LDFLAGS = (
+- /usr/local/lib/libsamplerate.a,
++ /opt/local/lib/libsamplerate.a,
+ "-framework",
+ Jackservermp,
+ "-framework",
+@@ -17247,7 +18028,10 @@
+ 4BDCDC231001FDE300B15929 /* Deployment */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = "$(NATIVE_ARCH_ACTUAL)";
++ ARCHS = (
++ i386,
++ x86_64,
++ );
+ COPY_PHASE_STRIP = YES;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -17269,9 +18053,10 @@
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = "-DJACK_32_64";
+ OTHER_CPLUSPLUSFLAGS = (
++ "-DJACK_32_64",
++ "-DHAVE_CELT",
+ "-DSERVER_SIDE",
+ "-DMACH_RPC_MACH_SEMA",
+- "-DJACK_32_64",
+ );
+ OTHER_LDFLAGS = (
+ /opt/local/lib/libsamplerate.a,
+@@ -17303,7 +18088,7 @@
+ buildSettings = {
+ ARCHS = (
+ i386,
+- ppc,
++ x86_64,
+ );
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+@@ -17852,12 +18637,8 @@
+ 4BFA828B0DF6A9E40087B4E1 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- ppc64,
+- ppc,
+- i386,
+- x86_64,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -17947,10 +18728,8 @@
+ 4BFA829E0DF6A9E40087B4E1 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -18050,10 +18829,8 @@
+ 4BFA82AA0DF6A9E40087B4E1 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -18143,10 +18920,8 @@
+ 4BFA82B60DF6A9E40087B4E1 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -18236,10 +19011,8 @@
+ 4BFA82C20DF6A9E40087B4E1 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -18329,10 +19102,8 @@
+ 4BFA82CE0DF6A9E40087B4E1 /* Default */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+- ARCHS = (
+- i386,
+- ppc,
+- );
++ ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
++ ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = ../common;
+ OTHER_CFLAGS = "";
+@@ -18473,7 +19244,11 @@
+ LIBRARY_STYLE = DYNAMIC;
+ MACH_O_TYPE = mh_dylib;
+ OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
++ "-DMACH_RPC_MACH_SEMA",
++ );
+ OTHER_LDFLAGS = (
+ "-framework",
+ Jackservermp,
+@@ -18523,7 +19298,11 @@
+ MACH_O_TYPE = mh_dylib;
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = "";
+- OTHER_CPLUSPLUSFLAGS = "-DMACH_RPC_MACH_SEMA";
++ OTHER_CPLUSPLUSFLAGS = (
++ "-DHAVE_CELT_API_0_7",
++ "-DHAVE_CELT",
++ "-DMACH_RPC_MACH_SEMA",
++ );
+ OTHER_LDFLAGS = (
+ "-framework",
+ Jackservermp,
+@@ -18767,6 +19546,16 @@
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Default;
+ };
++ 4B2021E2133A9BA40019E213 /* Build configuration list for PBXNativeTarget "jack_midi_latency 64 bits" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4B2021E3133A9BA40019E213 /* Development */,
++ 4B2021E4133A9BA40019E213 /* Deployment */,
++ 4B2021E5133A9BA40019E213 /* Default */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Default;
++ };
+ 4B3224E110A3156800838A8E /* Build configuration list for PBXNativeTarget "jack_netone Universal" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+@@ -19426,6 +20215,16 @@
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Default;
++ };
++ 4B8692D71371DB4700D2D11B /* Build configuration list for PBXNativeTarget "Jacknet.framework 64 bits" */ = {
++ isa = XCConfigurationList;
++ buildConfigurations = (
++ 4B8692D81371DB4700D2D11B /* Development */,
++ 4B8692D91371DB4700D2D11B /* Deployment */,
++ 4B8692DA1371DB4700D2D11B /* Default */,
++ );
++ defaultConfigurationIsVisible = 0;
++ defaultConfigurationName = Default;
+ };
+ 4B8F16E113290DC80002AD73 /* Build configuration list for PBXNativeTarget "jack_midi_dump Universal" */ = {
+ isa = XCConfigurationList;
+--- a/macosx/Jack-Info.plist
++++ b/macosx/Jack-Info.plist
+@@ -7,7 +7,7 @@
+ <key>CFBundleExecutable</key>
+ <string>Jackservermp</string>
+ <key>CFBundleGetInfoString</key>
+- <string>Jackdmp 1.9.7, @03-11 Paul Davis, Grame</string>
++ <string>Jackdmp 1.9.8, @03-11 Paul Davis, Grame</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.grame.Jackmp</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+@@ -19,6 +19,6 @@
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+- <string>1.9.7</string>
++ <string>1.9.8</string>
+ </dict>
+ </plist>
+--- a/macosx/JackMachSemaphore.cpp
++++ b/macosx/JackMachSemaphore.cpp
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -26,19 +26,17 @@
+ namespace Jack
+ {
+
+-mach_port_t JackMachSemaphore::fBootPort = 0;
+-
+-void JackMachSemaphore::BuildName(const char* client_name, const char* server_name, char* res)
++void JackMachSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
+ {
+ char ext_client_name[JACK_CLIENT_NAME_SIZE + 1];
+ JackTools::RewriteName(client_name, ext_client_name);
+- sprintf(res, "jack_mach_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
++ snprintf(res, size, "jack_mach_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
+ }
+
+ bool JackMachSemaphore::Signal()
+ {
+ if (!fSemaphore) {
+- jack_error("JackMachSemaphore::Signal name = %s already desallocated!!", fName);
++ jack_error("JackMachSemaphore::Signal name = %s already deallocated!!", fName);
+ return false;
+ }
+
+@@ -55,13 +53,13 @@
+ bool JackMachSemaphore::SignalAll()
+ {
+ if (!fSemaphore) {
+- jack_error("JackMachSemaphore::SignalAll name = %s already desallocated!!", fName);
++ jack_error("JackMachSemaphore::SignalAll name = %s already deallocated!!", fName);
+ return false;
+ }
+
+ if (fFlush)
+ return true;
+-
++
+ kern_return_t res;
+ // When signaled several times, do not accumulate signals...
+ if ((res = semaphore_signal_all(fSemaphore)) != KERN_SUCCESS) {
+@@ -73,7 +71,7 @@
+ bool JackMachSemaphore::Wait()
+ {
+ if (!fSemaphore) {
+- jack_error("JackMachSemaphore::Wait name = %s already desallocated!!", fName);
++ jack_error("JackMachSemaphore::Wait name = %s already deallocated!!", fName);
+ return false;
+ }
+
+@@ -87,10 +85,10 @@
+ bool JackMachSemaphore::TimedWait(long usec)
+ {
+ if (!fSemaphore) {
+- jack_error("JackMachSemaphore::TimedWait name = %s already desallocated!!", fName);
++ jack_error("JackMachSemaphore::TimedWait name = %s already deallocated!!", fName);
+ return false;
+ }
+-
++
+ kern_return_t res;
+ mach_timespec time;
+ time.tv_sec = usec / 1000000;
+@@ -105,7 +103,7 @@
+ // Server side : publish the semaphore in the global namespace
+ bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int value)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ mach_port_t task = mach_task_self();
+ kern_return_t res;
+
+@@ -149,7 +147,7 @@
+ // Client side : get the published semaphore from server
+ bool JackMachSemaphore::ConnectInput(const char* name, const char* server_name)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ kern_return_t res;
+
+ // Temporary... A REVOIR
+@@ -202,7 +200,7 @@
+ kern_return_t res;
+
+ if (fSemaphore > 0) {
+- jack_log("JackMachSemaphore::Destroy");
++ jack_log("JackMachSemaphore::Destroy name = %s", fName);
+ if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) {
+ jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res));
+ }
+--- a/macosx/JackMachSemaphore.h
++++ b/macosx/JackMachSemaphore.h
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -39,15 +39,15 @@
+ private:
+
+ semaphore_t fSemaphore;
+- static mach_port_t fBootPort;
++ mach_port_t fBootPort;
+
+ protected:
+
+- void BuildName(const char* name, const char* server_name, char* res);
++ void BuildName(const char* name, const char* server_name, char* res, int size);
+
+ public:
+
+- JackMachSemaphore():JackSynchro(), fSemaphore(0)
++ JackMachSemaphore():JackSynchro(), fSemaphore(0), fBootPort(0)
+ {}
+
+ bool Signal();
+--- a/macosx/JackMachThread.cpp
++++ b/macosx/JackMachThread.cpp
+@@ -18,9 +18,14 @@
+
+ */
+
++
+ #include "JackMachThread.h"
+ #include "JackError.h"
+
++#ifdef MY_TARGET_OS_IPHONE
++#include "/Developer/Extras/CoreAudio/PublicUtility/CAHostTimeBase.h"
++#endif
++
+ namespace Jack
+ {
+
+@@ -30,11 +35,17 @@
+ // REAL-TIME / TIME-CONSTRAINT THREAD
+ thread_time_constraint_policy_data_t theTCPolicy;
+
++#ifdef MY_TARGET_OS_IPHONE
++ theTCPolicy.period = CAHostTimeBase::ConvertFromNanos(period);
++ theTCPolicy.computation = CAHostTimeBase::ConvertFromNanos(computation);
++ theTCPolicy.constraint = CAHostTimeBase::ConvertFromNanos(constraint);
++#else
+ theTCPolicy.period = AudioConvertNanosToHostTime(period);
+ theTCPolicy.computation = AudioConvertNanosToHostTime(computation);
+ theTCPolicy.constraint = AudioConvertNanosToHostTime(constraint);
++#endif
+ theTCPolicy.preemptible = true;
+- kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) & theTCPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT);
++ kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_TIME_CONSTRAINT_POLICY, (thread_policy_t) &theTCPolicy, THREAD_TIME_CONSTRAINT_POLICY_COUNT);
+ jack_log("JackMachThread::thread_policy_set res = %ld", res);
+ return (res == KERN_SUCCESS) ? 0 : -1;
+ } else {
+@@ -57,7 +68,7 @@
+ relativePriority = inPriority - GetThreadSetPriority(pthread_self());
+
+ thePrecedencePolicy.importance = relativePriority;
+- kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) & thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
++ kern_return_t res = thread_policy_set(pthread_mach_thread_np(thread), THREAD_PRECEDENCE_POLICY, (thread_policy_t) &thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
+ jack_log("JackMachThread::thread_policy_set res = %ld", res);
+ return (res == KERN_SUCCESS) ? 0 : -1;
+ }
+@@ -130,9 +141,16 @@
+ &count,
+ &get_default);
+ if (res == KERN_SUCCESS) {
++ #ifdef MY_TARGET_OS_IPHONE
++ *period = CAHostTimeBase::ConvertToNanos(theTCPolicy.period);
++ *computation = CAHostTimeBase::ConvertToNanos(theTCPolicy.computation);
++ *constraint = CAHostTimeBase::ConvertToNanos(theTCPolicy.constraint);
++ #else
+ *period = AudioConvertHostTimeToNanos(theTCPolicy.period);
+ *computation = AudioConvertHostTimeToNanos(theTCPolicy.computation);
+ *constraint = AudioConvertHostTimeToNanos(theTCPolicy.constraint);
++ #endif
++
+ jack_log("JackMachThread::GetParams period = %ld computation = %ld constraint = %ld", long(*period / 1000.0f), long(*computation / 1000.0f), long(*constraint / 1000.0f));
+ return 0;
+ } else {
+@@ -164,7 +182,7 @@
+
+ int JackMachThread::AcquireSelfRealTime()
+ {
+- jack_log("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
++ jack_log("JackMachThread::AcquireSelfRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld",
+ long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000));
+ return AcquireRealTimeImp(pthread_self(), fPeriod, fComputation, fConstraint);
+ }
+--- a/macosx/JackMachThread.h
++++ b/macosx/JackMachThread.h
+@@ -61,12 +61,23 @@
+ #ifndef __JackMachThread__
+ #define __JackMachThread__
+
++#include <TargetConditionals.h>
++
++#ifdef MY_TARGET_OS_IPHONE
++typedef unsigned char Boolean;
++#endif
++
++
+ #include "JackPosixThread.h"
+-#import <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
++#ifndef MY_TARGET_OS_IPHONE
++#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacTypes.h>
++#endif
+
+ #include <mach/thread_policy.h>
+ #include <mach/thread_act.h>
++#ifndef MY_TARGET_OS_IPHONE
+ #include <CoreAudio/HostTime.h>
++#endif
+
+ #define THREAD_SET_PRIORITY 0
+ #define THREAD_SCHEDULED_PRIORITY 1
+@@ -122,6 +133,7 @@
+ return JackMachThread::AcquireRealTimeImp(thread, period, computation, constraint);
+ }
+ static int DropRealTimeImp(jack_native_thread_t thread);
++
+ };
+
+ } // end of namespace
+--- a/macosx/JackPlatformPlug_os.h
++++ b/macosx/JackPlatformPlug_os.h
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -20,25 +20,34 @@
+ #ifndef __JackPlatformPlug_APPLE__
+ #define __JackPlatformPlug_APPLE__
+
++#include <TargetConditionals.h>
++
+ #define jack_server_dir "/tmp"
+ #define jack_client_dir "/tmp"
+ #define JACK_DEFAULT_DRIVER "coreaudio"
+
+ namespace Jack
+-{
++{
+ struct JackRequest;
+ struct JackResult;
+-
++
+ class JackPosixMutex;
+ class JackMachThread;
+ class JackMachSemaphore;
+-
++
+ class JackSocketServerChannel;
+ class JackSocketClientChannel;
+ class JackSocketServerNotifyChannel;
+ class JackSocketNotifyChannel;
+-
++
+ class JackNetUnixSocket;
++
++#ifdef MY_TARGET_OS_IPHONE
++ class JackClient;
++ class JackGraphManager;
++ class JackEngineControl;
++ class JackSynchro;
++#endif
+ }
+
+ /* __JackPlatformMutex__ */
+@@ -50,8 +59,13 @@
+ namespace Jack { typedef JackMachThread JackThread; }
+
+ /* __JackPlatformSynchro__ client activation */
++#ifndef MY_TARGET_OS_IPHONE
+ #include "JackMachSemaphore.h"
+ namespace Jack { typedef JackMachSemaphore JackSynchro; }
++#endif
++
++#include "JackSocket.h"
++namespace Jack { typedef JackClientSocket JackChannelTransaction; }
+
+ #include "JackSocket.h"
+ namespace Jack { typedef JackClientSocket JackChannelTransaction; }
+@@ -60,7 +74,8 @@
+ #include "JackProcessSync.h"
+ /* Only on windows a special JackProcessSync is used. It is directly defined by including JackProcessSync.h here */
+
+-/* __JackPlatformServerChannel__ */
++#ifndef MY_TARGET_OS_IPHONE
++/* __JackPlatformServerChannel__ */
+ #include "JackSocketServerChannel.h"
+ namespace Jack { typedef JackSocketServerChannel JackServerChannel; }
+
+@@ -75,6 +90,7 @@
+ /* __JackPlatformNotifyChannel__ */
+ #include "JackSocketNotifyChannel.h"
+ namespace Jack { typedef JackSocketNotifyChannel JackNotifyChannel; }
++#endif
+
+ /* __JackPlatformNetSocket__ */
+ #include "JackNetUnixSocket.h"
+--- a/macosx/remove_jackdmp
++++ b/macosx/remove_jackdmp
+@@ -5,6 +5,7 @@
+ sudo rm "/usr/local/lib/libjackmp.dylib"
+ sudo rm -r "/Library/Frameworks/Jackmp.framework"
+ sudo rm -r "/Library/Frameworks/Jackservermp.framework"
++sudo rm -r "/Library/Frameworks/Jacknet.framework"
+ sudo rm -r "/Library/Audio/Plug-Ins/HAL/JackRouter.plugin"
+
+ # Tries to restore jack
+--- a/macosx/wscript
++++ b/macosx/wscript
+@@ -62,7 +62,18 @@
+
+ create_jack_audio_driver_obj(bld, 'coreaudio', 'coreaudio/JackCoreAudioDriver.cpp')
+
+- create_jack_midi_driver_obj(bld, 'coremidi', 'coremidi/JackCoreMidiDriver.cpp')
++ create_jack_midi_driver_obj(
++ bld,
++ 'coremidi',
++ ['coremidi/JackCoreMidiInputPort.cpp',
++ 'coremidi/JackCoreMidiOutputPort.cpp',
++ 'coremidi/JackCoreMidiPhysicalInputPort.cpp',
++ 'coremidi/JackCoreMidiPhysicalOutputPort.cpp',
++ 'coremidi/JackCoreMidiVirtualInputPort.cpp',
++ 'coremidi/JackCoreMidiVirtualOutputPort.cpp',
++ 'coremidi/JackCoreMidiPort.cpp',
++ 'coremidi/JackCoreMidiUtil.cpp',
++ 'coremidi/JackCoreMidiDriver.cpp'])
+
+ portaudio_src = [
+ '../windows/JackPortAudioDriver.cpp',
+--- a/man/jack_connect.0
++++ b/man/jack_connect.0
+@@ -5,7 +5,7 @@
+ \fB jack_connect\fR [ \fI-s\fR | \fI--server servername\fR ] [\fI-h\fR | \fI--help\fR ] port1 port2
+ \fB jack_disconnect\fR [ \fI-s\fR | \fI--server servername\fR ] [\fI-h\fR | \fI--help\fR ] port1 port2
+ .SH DESCRIPTION
+-\fBjack_connect\fR connects the two named ports. \fBjack_connect\fR disconnects the two named ports.
++\fBjack_connect\fR connects the two named ports. \fBjack_disconnect\fR disconnects the two named ports.
+ .SH RETURNS
+ The exit status is zero if successful, 1 otherwise
+
+--- a/man/jackd.0
++++ b/man/jackd.0
+@@ -215,13 +215,13 @@
+ software written to use the ALSA "sequencer" API.
+ .SS COREAUDIO BACKEND PARAMETERS
+ .TP
+-\fB\-c \-\-channel\fR
++\fB\-c \-\-channels\fR
+ Maximum number of channels (default: 2)
+ .TP
+-\fB\-i \-\-channelin\fR
++\fB\-i \-\-inchannels\fR
+ Maximum number of input channels (default: 2)
+ .TP
+-\fB\-o \-\-channelout\fR
++\fB\-o \-\-outchannels\fR
+ Maximum number of output channels (default: 2)
+ .TP
+ \fB\-C \-\-capture\fR
+@@ -230,6 +230,9 @@
+ \fB\-P \-\-playback\fR
+ Whether or not to playback (default: true)
+ .TP
++\fB\-D \-\-monitor\fR
++Provide monitor ports for the output (default: false)
++.TP
+ \fB\-D \-\-duplex\fR
+ Capture and playback (default: true)
+ .TP
+@@ -239,11 +242,29 @@
+ \fB\-p \-\-period\fR
+ Frames per period (default: 128). Must be a power of 2.
+ .TP
+-\fB\-n \-\-name\fR
+-Driver name (default: none)
++\fB\-d \-\-device\fR
++CoreAudio device name (default: none)
++.TP
++\fB\-I \-\-input\-latency\fR
++Extra input latency (frames) (default: 0)
++.TP
++\fB\-O \-\-output\-latency\fR
++Extra output latency (frames) (default: 0)
++.TP
++\fB\-l \-\-list\-devices \fR
++Display available CoreAudio devices (default: false)
++.TP
++\fB\-H \-\-hog \fR
++Take exclusive access of the audio device (default: false)
++.TP
++\fB\-L \-\-async\-latency \fR
++Extra output latency in asynchronous mode (percent) (default: 100)
++.TP
++\fB\-G \-\-grain \fR
++Computation grain in RT thread (percent) (default: 100)
+ .TP
+-\fB\-I \-\-id\fR
+-Audio Device ID (default: 0)
++\fB\-s \-\-clock\-drift \fR
++Whether to compensate clock drift in dynamically created aggregate device (default: false)
+ .SS DUMMY BACKEND PARAMETERS
+ .TP
+ \fB\-C, \-\-capture \fIint\fR
+@@ -267,7 +288,7 @@
+ The default value is 21333.
+
+
+-.SS NET BACKEND PARAMETERS
++.SS NETONE BACKEND PARAMETERS
+
+ .TP
+ \fB\-i, \-\-audio\-ins \fIint\fR
+--- a/man/jack_iodelay.0
++++ b/man/jack_iodelay.0
+@@ -15,17 +15,17 @@
+ corresponding hardware output connector to an input connector, and to
+ connect that corresponding hardware capture port to jack_iodelay's
+ input port. This creates a roundtrip that goes through any
+-analog-to-digital or digital-converters that are present in the audio
+-hardware.
++analog-to-digital and digital-to-analog converters that are present in
++the audio hardware.
+ .PP
+ Although the hardware loopback latency is the expected use, it is also
+ possible to use jack_iodelay to measure the latency along any fully
+ connected signal path, such as those involving other JACK clients.
+ .PP
+ Once jack_iodelay completes its measurement it will print the total
+-latency it has detected. This will include the JACK period length in
++latency it has detected. This will include the JACK buffer length in
+ addition to any other latency in the signal path. It will continue to
+-print the value every 0.5 seconds or so so that if you wish you can
++print the value every 0.5 seconds so that if you wish you can
+ vary aspects of the signal path to see their effect on the measured
+ latency.
+ .PP
+@@ -34,20 +34,27 @@
+ .PP
+ \fT Signal below threshold... .\fR
+ .PP
+-every second until this changes (e.g. until you establish the correct connections).
++every second until this changes (e.g. until you establish the correct
++connections).
+ .PP
+ To use the value measured by jack_iodelay with the -I and -O arguments
+ of a JACK backend (also called Input Latency and Output Latency in the
+-setup dialog of qjackctl), you must subtract the JACK period size from
+-the result. Then, if you believe that the latency is equally
+-distributed between the input and output parts of your audio hardware
+-(extremely likely), divide the result by two and use that for input
+-and/or output latency value. Doing this measurement will enable JACK
+-clients that use the JACK latency API to accurately position/delay
+-audio to keep signals synchronized even when there are inherent delays
+-in the end-to-end signal pathways.
++setup dialog of qjackctl), you must subtract the JACK buffer size from
++the result. The buffer size is determined by multiplying the number of
++frames per period (given to the jackd backend by the -p or --period
++option) by the number of periods per buffer (given to the jackd
++backend by the -n or --nperiods option). Note that JACK2 will add an
++implicit additional period when using the default asynchronous mode,
++so for JACK1 or JACK2 in synchronous mode, the buffer size is n*p, but
++for JACK2 in asynchronous mode the buffer size is (n+1)*p. Once the
++JACK buffer size is subtracted from the measured latency, the result
++is the "extra" latency due to the interface hardware. Then, if you
++believe that the latency is equally distributed between the input and
++output parts of your audio hardware (extremely likely), divide the
++result by two and use that for input and output latency
++values. Doing this measurement will enable JACK clients that use the
++JACK latency API to accurately position/delay audio to keep signals
++synchronized even when there are inherent delays in the end-to-end
++signal pathways.
+ .SH AUTHOR
+-Originally written in C++ by Fons Adriensen, ported to C by Torben Hohn.
+-
+-
+-
++Originally written in C++ by Fons Adriaensen, ported to C by Torben Hohn.
+--- a/posix/JackCompilerDeps_os.h
++++ b/posix/JackCompilerDeps_os.h
+@@ -23,7 +23,9 @@
+ #include "JackConstants.h"
+
+ #if __GNUC__
+- #ifndef POST_PACKED_STRUCTURE
++ #define PRE_PACKED_STRUCTURE
++
++ #ifndef POST_PACKED_STRUCTURE
+ /* POST_PACKED_STRUCTURE needs to be a macro which
+ expands into a compiler directive. The directive must
+ tell the compiler to arrange the preceding structure
+@@ -40,7 +42,7 @@
+ #endif
+ #endif
+ #define MEM_ALIGN(x,y) x __attribute__((aligned(y)))
+- #define EXPORT __attribute__((visibility("default")))
++ #define LIB_EXPORT __attribute__((visibility("default")))
+ #ifdef SERVER_SIDE
+ #if (__GNUC__< 4)
+ #define SERVER_EXPORT
+@@ -52,9 +54,9 @@
+ #endif
+ #else
+ #define MEM_ALIGN(x,y) x
+- #define EXPORT
++ #define LIB_EXPORT
+ #define SERVER_EXPORT
+- /* Add other things here for non-gcc platforms for POST_PACKED_STRUCTURE */
++ /* Add other things here for non-gcc platforms for PRE and POST_PACKED_STRUCTURE */
+ #endif
+
+ #endif
+--- a/posix/JackNetUnixSocket.cpp
++++ b/posix/JackNetUnixSocket.cpp
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -24,12 +24,11 @@
+ namespace Jack
+ {
+ //utility *********************************************************************************************************
+- int GetHostName ( char * name, int size )
++ int GetHostName(char * name, int size)
+ {
+- if ( gethostname ( name, size ) == SOCKET_ERROR )
+- {
+- jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) );
+- strcpy ( name, "default" );
++ if (gethostname(name, size) == SOCKET_ERROR) {
++ jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
++ strcpy(name, "default");
+ return SOCKET_ERROR;
+ }
+ return 0;
+@@ -42,29 +41,29 @@
+ fPort = 0;
+ fTimeOut = 0;
+ fSendAddr.sin_family = AF_INET;
+- fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fSendAddr.sin_zero, 0, 8 );
++ fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fSendAddr.sin_zero, 0, 8);
+ fRecvAddr.sin_family = AF_INET;
+- fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fRecvAddr.sin_zero, 0, 8 );
++ fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fRecvAddr.sin_zero, 0, 8);
+ }
+
+- JackNetUnixSocket::JackNetUnixSocket ( const char* ip, int port )
++ JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
+ {
+ fSockfd = 0;
+ fPort = port;
+ fTimeOut = 0;
+ fSendAddr.sin_family = AF_INET;
+- fSendAddr.sin_port = htons ( port );
+- inet_aton ( ip, &fSendAddr.sin_addr );
+- memset ( &fSendAddr.sin_zero, 0, 8 );
++ fSendAddr.sin_port = htons(port);
++ inet_aton(ip, &fSendAddr.sin_addr);
++ memset(&fSendAddr.sin_zero, 0, 8);
+ fRecvAddr.sin_family = AF_INET;
+- fRecvAddr.sin_port = htons ( port );
+- fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fRecvAddr.sin_zero, 0, 8 );
++ fRecvAddr.sin_port = htons(port);
++ fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fRecvAddr.sin_zero, 0, 8);
+ }
+
+- JackNetUnixSocket::JackNetUnixSocket ( const JackNetUnixSocket& socket )
++ JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
+ {
+ fSockfd = 0;
+ fTimeOut = 0;
+@@ -78,10 +77,9 @@
+ Close();
+ }
+
+- JackNetUnixSocket& JackNetUnixSocket::operator= ( const JackNetUnixSocket& socket )
++ JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
+ {
+- if ( this != &socket )
+- {
++ if (this != &socket) {
+ fSockfd = 0;
+ fPort = socket.fPort;
+ fSendAddr = socket.fSendAddr;
+@@ -93,84 +91,106 @@
+ //socket***********************************************************************************************************
+ int JackNetUnixSocket::NewSocket()
+ {
+- if ( fSockfd )
+- {
++ if (fSockfd) {
+ Close();
+ Reset();
+ }
+- fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 );
+-
++ fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
++
+ /* Enable address reuse */
+ int res, on = 1;
+- if ((res = setsockopt( fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
++ if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
+ StrError(NET_ERROR_CODE);
+ }
+-
+ return fSockfd;
+ }
+
++ bool JackNetUnixSocket::IsLocal(char* ip)
++ {
++ if (strcmp(ip, "127.0.0.1") == 0) {
++ return true;
++ }
++
++ char host_name[32];
++ gethostname(host_name, sizeof(host_name));
++
++ struct hostent* host = gethostbyname(host_name);
++ if (host) {
++ for (int i = 0; host->h_addr_list[i] != 0; ++i) {
++ struct in_addr addr;
++ memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
++ if (strcmp(inet_ntoa(addr), ip) == 0) {
++ return true;
++ }
++ }
++ return false;
++ } else {
++ return false;
++ }
++ }
++
+ int JackNetUnixSocket::Bind()
+ {
+- return bind ( fSockfd, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), sizeof ( socket_address_t ) );
++ return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
+ }
+
+- int JackNetUnixSocket::BindWith ( const char* ip )
++ int JackNetUnixSocket::BindWith(const char* ip)
+ {
+- int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr );
+- if ( addr_conv < 0 )
++ int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
++ if (addr_conv < 0)
+ return addr_conv;
+ return Bind();
+ }
+
+- int JackNetUnixSocket::BindWith ( int port )
++ int JackNetUnixSocket::BindWith(int port)
+ {
+- fRecvAddr.sin_port = htons ( port );
++ fRecvAddr.sin_port = htons(port);
+ return Bind();
+ }
+
+ int JackNetUnixSocket::Connect()
+ {
+- return connect ( fSockfd, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) );
++ return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
+ }
+
+- int JackNetUnixSocket::ConnectTo ( const char* ip )
++ int JackNetUnixSocket::ConnectTo(const char* ip)
+ {
+- int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
+- if ( addr_conv < 0 )
++ int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
++ if (addr_conv < 0)
+ return addr_conv;
+ return Connect();
+ }
+
+ void JackNetUnixSocket::Close()
+ {
+- if ( fSockfd )
+- close ( fSockfd );
++ if (fSockfd)
++ close(fSockfd);
+ fSockfd = 0;
+ }
+
+ void JackNetUnixSocket::Reset()
+ {
+ fSendAddr.sin_family = AF_INET;
+- fSendAddr.sin_port = htons ( fPort );
+- fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fSendAddr.sin_zero, 0, 8 );
++ fSendAddr.sin_port = htons(fPort);
++ fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fSendAddr.sin_zero, 0, 8);
+ fRecvAddr.sin_family = AF_INET;
+- fRecvAddr.sin_port = htons ( fPort );
+- fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fRecvAddr.sin_zero, 0, 8 );
++ fRecvAddr.sin_port = htons(fPort);
++ fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fRecvAddr.sin_zero, 0, 8);
+ }
+
+ bool JackNetUnixSocket::IsSocket()
+ {
+- return ( fSockfd ) ? true : false;
++ return(fSockfd) ? true : false;
+ }
+
+ //IP/PORT***********************************************************************************************************
+- void JackNetUnixSocket::SetPort ( int port )
++ void JackNetUnixSocket::SetPort(int port)
+ {
+ fPort = port;
+- fSendAddr.sin_port = htons ( port );
+- fRecvAddr.sin_port = htons ( port );
++ fSendAddr.sin_port = htons(port);
++ fRecvAddr.sin_port = htons(port);
+ }
+
+ int JackNetUnixSocket::GetPort()
+@@ -179,63 +199,63 @@
+ }
+
+ //address***********************************************************************************************************
+- int JackNetUnixSocket::SetAddress ( const char* ip, int port )
++ int JackNetUnixSocket::SetAddress(const char* ip, int port)
+ {
+- int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
+- if ( addr_conv < 0 )
++ int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
++ if (addr_conv < 0)
+ return addr_conv;
+- fSendAddr.sin_port = htons ( port );
++ fSendAddr.sin_port = htons(port);
+ return 0;
+ }
+
+ char* JackNetUnixSocket::GetSendIP()
+ {
+- return inet_ntoa ( fSendAddr.sin_addr );
++ return inet_ntoa(fSendAddr.sin_addr);
+ }
+
+ char* JackNetUnixSocket::GetRecvIP()
+ {
+- return inet_ntoa ( fRecvAddr.sin_addr );
++ return inet_ntoa(fRecvAddr.sin_addr);
+ }
+
+ //utility************************************************************************************************************
+- int JackNetUnixSocket::GetName ( char* name )
++ int JackNetUnixSocket::GetName(char* name)
+ {
+- return gethostname ( name, 255 );
++ return gethostname(name, 255);
+ }
+
+- int JackNetUnixSocket::JoinMCastGroup ( const char* ip )
++ int JackNetUnixSocket::JoinMCastGroup(const char* ip)
+ {
+ struct ip_mreq multicast_req;
+- inet_aton ( ip, &multicast_req.imr_multiaddr );
+- multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY );
+- return SetOption ( IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof ( multicast_req ) );
++ inet_aton(ip, &multicast_req.imr_multiaddr);
++ multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
++ return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
+ }
+
+ //options************************************************************************************************************
+- int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen )
++ int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
+ {
+- return setsockopt ( fSockfd, level, optname, optval, optlen );
++ return setsockopt(fSockfd, level, optname, optval, optlen);
+ }
+
+- int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen )
++ int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
+ {
+- return getsockopt ( fSockfd, level, optname, optval, optlen );
++ return getsockopt(fSockfd, level, optname, optval, optlen);
+ }
+
+ //timeout************************************************************************************************************
+
+ #if defined(__sun__) || defined(sun)
+- int JackNetUnixSocket::SetTimeOut ( int us )
++ int JackNetUnixSocket::SetTimeOut(int us)
+ {
+ int flags;
+ fTimeOut = us;
+-
++
+ if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
+ jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
+ return -1;
+ }
+-
++
+ flags |= O_NONBLOCK;
+ if (fcntl(fSockfd, F_SETFL, flags) < 0) {
+ jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
+@@ -252,17 +272,17 @@
+ struct timeval tv;
+ fd_set fdset;
+ ssize_t res;
+-
++
+ tv.tv_sec = fTimeOut / 1000000;
+ tv.tv_usec = fTimeOut % 1000000;
+-
++
+ FD_ZERO(&fdset);
+ FD_SET(fSockfd, &fdset);
+-
++
+ do {
+ res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
+- } while (res < 0 && errno == EINTR);
+-
++ } while(res < 0 && errno == EINTR);
++
+ if (res < 0) {
+ return res;
+ } else if (res == 0) {
+@@ -281,17 +301,17 @@
+ struct timeval tv;
+ fd_set fdset;
+ ssize_t res;
+-
++
+ tv.tv_sec = fTimeOut / 1000000;
+- tv.tv_usec = fTimeOut % 1000000;
+-
++ tv.tv_usec = fTimeOut % 1000000;
++
+ FD_ZERO(&fdset);
+ FD_SET(fSockfd, &fdset);
+-
++
+ do {
+ res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
+- } while (res < 0 && errno == EINTR);
+-
++ } while(res < 0 && errno == EINTR);
++
+ if (res < 0) {
+ return res;
+ } else if (res == 0) {
+@@ -304,30 +324,27 @@
+ }
+
+ #else
+- int JackNetUnixSocket::SetTimeOut ( int us )
++ int JackNetUnixSocket::SetTimeOut(int us)
+ {
+- jack_log ( "JackNetUnixSocket::SetTimeout %d usecs", us );
++ jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
+
+ //negative timeout, or exceding 10s, return
+- if ( ( us < 0 ) || ( us > 10000000 ) )
++ if ((us < 0) ||(us > 10000000))
+ return SOCKET_ERROR;
+ struct timeval timeout;
+
+ //less than 1sec
+- if ( us < 1000000 )
+- {
++ if (us < 1000000) {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = us;
+- }
++ } else {
+ //more than 1sec
+- else
+- {
+- float sec = static_cast<float> ( us ) / 1000000.f;
+- timeout.tv_sec = ( int ) sec;
+- float usec = ( sec - static_cast<float> ( timeout.tv_sec ) ) * 1000000;
+- timeout.tv_usec = ( int ) usec;
++ float sec = static_cast<float>(us) / 1000000.f;
++ timeout.tv_sec =(int) sec;
++ float usec = (sec - static_cast<float>(timeout.tv_sec)) * 1000000;
++ timeout.tv_usec =(int) usec;
+ }
+- return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) );
++ return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+ }
+ #endif
+
+@@ -335,77 +352,77 @@
+ int JackNetUnixSocket::SetLocalLoop()
+ {
+ char disable = 0;
+- return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) );
++ return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
+ }
+
+ //network operations**************************************************************************************************
+- int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags )
++ int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
+ {
+ #if defined(__sun__) || defined(sun)
+ if (WaitWrite() < 0)
+ return -1;
+ #endif
+- return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), sizeof ( socket_address_t ) );
++ return sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
+ }
+
+- int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip )
++ int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
+ {
+- int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr );
+- if ( addr_conv < 1 )
++ int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
++ if (addr_conv < 1)
+ return addr_conv;
+ #if defined(__sun__) || defined(sun)
+ if (WaitWrite() < 0)
+ return -1;
+ #endif
+- return SendTo ( buffer, nbytes, flags );
++ return SendTo(buffer, nbytes, flags);
+ }
+
+- int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags )
++ int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
+ {
+ #if defined(__sun__) || defined(sun)
+ if (WaitWrite() < 0)
+ return -1;
+ #endif
+- return send ( fSockfd, buffer, nbytes, flags );
++ return send(fSockfd, buffer, nbytes, flags);
+ }
+
+- int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags )
++ int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
+ {
+- socklen_t addr_len = sizeof ( socket_address_t );
++ socklen_t addr_len = sizeof(socket_address_t);
+ #if defined(__sun__) || defined(sun)
+ if (WaitRead() < 0)
+ return -1;
+- #endif
+- return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fRecvAddr ), &addr_len );
++ #endif
++ return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len);
+ }
+
+- int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags )
++ int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
+ {
+ #if defined(__sun__) || defined(sun)
+ if (WaitRead() < 0)
+ return -1;
+- #endif
+- return recv ( fSockfd, buffer, nbytes, flags );
++ #endif
++ return recv(fSockfd, buffer, nbytes, flags);
+ }
+
+- int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags )
++ int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
+ {
+- socklen_t addr_len = sizeof ( socket_address_t );
++ socklen_t addr_len = sizeof(socket_address_t);
+ #if defined(__sun__) || defined(sun)
+ if (WaitRead() < 0)
+ return -1;
+- #endif
+- return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*> ( &fSendAddr ), &addr_len );
++ #endif
++ return recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len);
+ }
+
+ net_error_t JackNetUnixSocket::GetError()
+ {
+- switch ( errno )
++ switch(errno)
+ {
+ case EAGAIN:
+ case ETIMEDOUT:
+ return NET_NO_DATA;
+-
++
+ case ECONNABORTED:
+ case ECONNREFUSED:
+ case ECONNRESET:
+@@ -415,9 +432,10 @@
+ case ENETDOWN:
+ case ENETUNREACH:
+ return NET_CONN_ERROR;
+-
++
+ default:
+- return NET_OP_ERROR;
++ //return NET_OP_ERROR;
++ return NET_CONN_ERROR;
+ }
+ }
+ }
+--- a/posix/JackNetUnixSocket.h
++++ b/posix/JackNetUnixSocket.h
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -40,6 +40,7 @@
+ class SERVER_EXPORT JackNetUnixSocket
+ {
+ private:
++
+ int fSockfd;
+ int fPort;
+ int fTimeOut;
+@@ -50,55 +51,59 @@
+ int WaitRead();
+ int WaitWrite();
+ #endif
++
+ public:
++
+ JackNetUnixSocket();
+- JackNetUnixSocket ( const char* ip, int port );
+- JackNetUnixSocket ( const JackNetUnixSocket& );
++ JackNetUnixSocket(const char* ip, int port);
++ JackNetUnixSocket(const JackNetUnixSocket&);
+ ~JackNetUnixSocket();
+
+- JackNetUnixSocket& operator= ( const JackNetUnixSocket& socket );
++ JackNetUnixSocket& operator=(const JackNetUnixSocket& socket);
+
+ //socket management
+ int NewSocket();
+ int Bind();
+- int BindWith ( const char* ip );
+- int BindWith ( int port );
++ int BindWith(const char* ip);
++ int BindWith(int port);
+ int Connect();
+- int ConnectTo ( const char* ip );
++ int ConnectTo(const char* ip);
+ void Close();
+ void Reset();
+ bool IsSocket();
+
+ //IP/PORT management
+- void SetPort ( int port );
++ void SetPort(int port);
+ int GetPort();
+
+ //address management
+- int SetAddress ( const char* ip, int port );
++ int SetAddress(const char* ip, int port);
+ char* GetSendIP();
+ char* GetRecvIP();
+
+ //utility
+- int GetName ( char* name );
+- int JoinMCastGroup ( const char* mcast_ip );
++ int GetName(char* name);
++ int JoinMCastGroup(const char* mcast_ip);
+
+ //options management
+- int SetOption ( int level, int optname, const void* optval, socklen_t optlen );
+- int GetOption ( int level, int optname, void* optval, socklen_t* optlen );
++ int SetOption(int level, int optname, const void* optval, socklen_t optlen);
++ int GetOption(int level, int optname, void* optval, socklen_t* optlen);
+
+ //timeout
+- int SetTimeOut ( int us );
++ int SetTimeOut(int us);
+
+ //disable local loop
+ int SetLocalLoop();
+
++ bool IsLocal(char* ip);
++
+ //network operations
+- int SendTo ( const void* buffer, size_t nbytes, int flags );
+- int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip );
+- int Send ( const void* buffer, size_t nbytes, int flags );
+- int RecvFrom ( void* buffer, size_t nbytes, int flags );
+- int Recv ( void* buffer, size_t nbytes, int flags );
+- int CatchHost ( void* buffer, size_t nbytes, int flags );
++ int SendTo(const void* buffer, size_t nbytes, int flags);
++ int SendTo(const void* buffer, size_t nbytes, int flags, const char* ip);
++ int Send(const void* buffer, size_t nbytes, int flags);
++ int RecvFrom(void* buffer, size_t nbytes, int flags);
++ int Recv(void* buffer, size_t nbytes, int flags);
++ int CatchHost(void* buffer, size_t nbytes, int flags);
+
+ //error management
+ net_error_t GetError();
+--- a/posix/JackPosixMutex.h
++++ b/posix/JackPosixMutex.h
+@@ -22,10 +22,11 @@
+ #ifndef __JackPosixMutex__
+ #define __JackPosixMutex__
+
++#include "JackError.h"
++#include "JackException.h"
+ #include <pthread.h>
+ #include <stdio.h>
+ #include <assert.h>
+-#include "JackError.h"
+
+ namespace Jack
+ {
+@@ -33,19 +34,20 @@
+ \brief Mutex abstraction.
+ */
+
+-
+ class JackBasePosixMutex
+ {
+
+ protected:
+
+ pthread_mutex_t fMutex;
++ pthread_t fOwner;
+
+ public:
+
+- JackBasePosixMutex()
++ JackBasePosixMutex():fOwner(0)
+ {
+- pthread_mutex_init(&fMutex, NULL);
++ int res = pthread_mutex_init(&fMutex, NULL);
++ ThrowIf(res != 0, JackException("JackBasePosixMutex: could not init the mutex"));
+ }
+
+ virtual ~JackBasePosixMutex()
+@@ -53,30 +55,64 @@
+ pthread_mutex_destroy(&fMutex);
+ }
+
+- void Lock()
++ bool Lock()
+ {
+- int res = pthread_mutex_lock(&fMutex);
+- if (res != 0)
+- jack_log("JackBasePosixMutex::Lock res = %d", res);
++ pthread_t current_thread = pthread_self();
++
++ if (!pthread_equal(current_thread, fOwner)) {
++ int res = pthread_mutex_lock(&fMutex);
++ if (res == 0) {
++ fOwner = current_thread;
++ return true;
++ } else {
++ jack_error("JackBasePosixMutex::Lock res = %d", res);
++ return false;
++ }
++ } else {
++ jack_error("JackBasePosixMutex::Lock mutex already locked by thread = %d", current_thread);
++ return false;
++ }
+ }
+
+ bool Trylock()
+ {
+- return (pthread_mutex_trylock(&fMutex) == 0);
++ pthread_t current_thread = pthread_self();
++
++ if (!pthread_equal(current_thread, fOwner)) {
++ int res = pthread_mutex_trylock(&fMutex);
++ if (res == 0) {
++ fOwner = current_thread;
++ return true;
++ } else {
++ return false;
++ }
++ } else {
++ jack_error("JackBasePosixMutex::Trylock mutex already locked by thread = %d", current_thread);
++ return false;
++ }
+ }
+
+- void Unlock()
++ bool Unlock()
+ {
+- int res = pthread_mutex_unlock(&fMutex);
+- if (res != 0)
+- jack_log("JackBasePosixMutex::Unlock res = %d", res);
++ if (pthread_equal(pthread_self(), fOwner)) {
++ fOwner = 0;
++ int res = pthread_mutex_unlock(&fMutex);
++ if (res == 0) {
++ return true;
++ } else {
++ jack_error("JackBasePosixMutex::Unlock res = %d", res);
++ return false;
++ }
++ } else {
++ jack_error("JackBasePosixMutex::Unlock mutex not locked by thread = %d owner %d", pthread_self(), fOwner);
++ return false;
++ }
+ }
+
+ };
+
+ class JackPosixMutex
+ {
+-
+ protected:
+
+ pthread_mutex_t fMutex;
+@@ -89,13 +125,12 @@
+ pthread_mutexattr_t mutex_attr;
+ int res;
+ res = pthread_mutexattr_init(&mutex_attr);
+- assert(res == 0);
++ ThrowIf(res != 0, JackException("JackBasePosixMutex: could not init the mutex attribute"));
+ res = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
+- assert(res == 0);
++ ThrowIf(res != 0, JackException("JackBasePosixMutex: could not settype the mutex"));
+ res = pthread_mutex_init(&fMutex, &mutex_attr);
+- assert(res == 0);
+- res = pthread_mutexattr_destroy(&mutex_attr);
+- assert(res == 0);
++ ThrowIf(res != 0, JackException("JackBasePosixMutex: could not init the mutex"));
++ pthread_mutexattr_destroy(&mutex_attr);
+ }
+
+ virtual ~JackPosixMutex()
+@@ -106,8 +141,9 @@
+ bool Lock()
+ {
+ int res = pthread_mutex_lock(&fMutex);
+- if (res != 0)
++ if (res != 0) {
+ jack_log("JackPosixMutex::Lock res = %d", res);
++ }
+ return (res == 0);
+ }
+
+@@ -119,8 +155,9 @@
+ bool Unlock()
+ {
+ int res = pthread_mutex_unlock(&fMutex);
+- if (res != 0)
++ if (res != 0) {
+ jack_log("JackPosixMutex::Unlock res = %d", res);
++ }
+ return (res == 0);
+ }
+
+--- a/posix/JackPosixSemaphore.cpp
++++ b/posix/JackPosixSemaphore.cpp
+@@ -28,11 +28,11 @@
+ namespace Jack
+ {
+
+-void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res)
++void JackPosixSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
+ {
+ char ext_client_name[JACK_CLIENT_NAME_SIZE + 1];
+ JackTools::RewriteName(client_name, ext_client_name);
+- sprintf(res, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
++ snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
+ }
+
+ bool JackPosixSemaphore::Signal()
+@@ -40,7 +40,7 @@
+ int res;
+
+ if (!fSemaphore) {
+- jack_error("JackPosixSemaphore::Signal name = %s already desallocated!!", fName);
++ jack_error("JackPosixSemaphore::Signal name = %s already deallocated!!", fName);
+ return false;
+ }
+
+@@ -58,7 +58,7 @@
+ int res;
+
+ if (!fSemaphore) {
+- jack_error("JackPosixSemaphore::SignalAll name = %s already desallocated!!", fName);
++ jack_error("JackPosixSemaphore::SignalAll name = %s already deallocated!!", fName);
+ return false;
+ }
+
+@@ -77,7 +77,7 @@
+ int res;
+
+ if (!fSemaphore) {
+- jack_error("JackPosixSemaphore::Wait name = %s already desallocated!!", fName);
++ jack_error("JackPosixSemaphore::Wait name = %s already deallocated!!", fName);
+ return false;
+ }
+
+@@ -102,14 +102,14 @@
+
+ #if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) // glibc feature test
+
+-bool JackPosixSemaphore::TimedWait(long usec)
++bool JackPosixSemaphore::TimedWait(long usec)
+ {
+ int res;
+ struct timeval now;
+ timespec time;
+
+ if (!fSemaphore) {
+- jack_error("JackPosixSemaphore::TimedWait name = %s already desallocated!!", fName);
++ jack_error("JackPosixSemaphore::TimedWait name = %s already deallocated!!", fName);
+ return false;
+ }
+ gettimeofday(&now, 0);
+@@ -140,7 +140,7 @@
+ // Server side : publish the semaphore in the global namespace
+ bool JackPosixSemaphore::Allocate(const char* name, const char* server_name, int value)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ jack_log("JackPosixSemaphore::Allocate name = %s val = %ld", fName, value);
+
+ if ((fSemaphore = sem_open(fName, O_CREAT, 0777, value)) == (sem_t*)SEM_FAILED) {
+@@ -154,8 +154,8 @@
+ // Client side : get the published semaphore from server
+ bool JackPosixSemaphore::ConnectInput(const char* name, const char* server_name)
+ {
+- BuildName(name, server_name, fName);
+- jack_log("JackPosixSemaphore::Connect %s", fName);
++ BuildName(name, server_name, fName, sizeof(fName));
++ jack_log("JackPosixSemaphore::Connect name = %s", fName);
+
+ // Temporary...
+ if (fSemaphore) {
+@@ -187,7 +187,7 @@
+ bool JackPosixSemaphore::Disconnect()
+ {
+ if (fSemaphore) {
+- jack_log("JackPosixSemaphore::Disconnect %s", fName);
++ jack_log("JackPosixSemaphore::Disconnect name = %s", fName);
+ if (sem_close(fSemaphore) != 0) {
+ jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno));
+ return false;
+@@ -204,7 +204,7 @@
+ void JackPosixSemaphore::Destroy()
+ {
+ if (fSemaphore != NULL) {
+- jack_log("JackPosixSemaphore::Destroy");
++ jack_log("JackPosixSemaphore::Destroy name = %s", fName);
+ sem_unlink(fName);
+ if (sem_close(fSemaphore) != 0) {
+ jack_error("Destroy: can't destroy semaphore name = %s err = %s", fName, strerror(errno));
+--- a/posix/JackPosixSemaphore.h
++++ b/posix/JackPosixSemaphore.h
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -42,7 +42,7 @@
+
+ protected:
+
+- void BuildName(const char* name, const char* server_name, char* res);
++ void BuildName(const char* name, const char* server_name, char* res, int size);
+
+ public:
+
+--- a/posix/JackPosixServerLaunch.cpp
++++ b/posix/JackPosixServerLaunch.cpp
+@@ -13,7 +13,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -209,6 +209,8 @@
+ JackClientChannel channel;
+ int res = channel.ServerCheck(server_name);
+ channel.Close();
++ JackSleep(2000); // Added by JE - 02-01-2009 (gives
++ // the channel some time to close)
+ return res;
+ }
+
+@@ -236,3 +238,4 @@
+
+ return 0;
+ }
++
+--- a/posix/JackPosixThread.cpp
++++ b/posix/JackPosixThread.cpp
+@@ -232,6 +232,8 @@
+ memset(&rtparam, 0, sizeof(rtparam));
+ rtparam.sched_priority = priority;
+
++ jack_log("JackPosixThread::AcquireRealTimeImp priority = %d", priority);
++
+ if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) != 0) {
+ jack_error("Cannot use real-time scheduling (RR/%d)"
+ "(%d: %s)", rtparam.sched_priority, res,
+--- a/posix/JackPosixThread.h
++++ b/posix/JackPosixThread.h
+@@ -72,7 +72,9 @@
+
+ static int AcquireRealTimeImp(jack_native_thread_t thread, int priority);
+ static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint)
+- { return JackPosixThread::AcquireRealTimeImp(thread, priority); }
++ {
++ return JackPosixThread::AcquireRealTimeImp(thread, priority);
++ }
+ static int DropRealTimeImp(jack_native_thread_t thread);
+ static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg);
+ static int StopImp(jack_native_thread_t thread);
+--- a/posix/JackProcessSync.cpp
++++ b/posix/JackProcessSync.cpp
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -30,6 +30,7 @@
+ jack_error("JackProcessSync::Signal error err = %s", strerror(res));
+ }
+
++// TO DO : check thread consistency?
+ void JackProcessSync::LockedSignal()
+ {
+ int res = pthread_mutex_lock(&fMutex);
+@@ -50,6 +51,7 @@
+ jack_error("JackProcessSync::SignalAll error err = %s", strerror(res));
+ }
+
++// TO DO : check thread consistency?
+ void JackProcessSync::LockedSignalAll()
+ {
+ int res = pthread_mutex_lock(&fMutex);
+@@ -65,11 +67,18 @@
+
+ void JackProcessSync::Wait()
+ {
+- int res;
+- if ((res = pthread_cond_wait(&fCond, &fMutex)) != 0)
++ ThrowIf(!pthread_equal(pthread_self(), fOwner), JackException("JackProcessSync::Wait: a thread has to have locked a mutex before it can wait"));
++ fOwner = 0;
++
++ int res = pthread_cond_wait(&fCond, &fMutex);
++ if (res != 0) {
+ jack_error("JackProcessSync::Wait error err = %s", strerror(res));
+- }
++ } else {
++ fOwner = pthread_self();
++ }
++}
+
++// TO DO : check thread consistency?
+ void JackProcessSync::LockedWait()
+ {
+ int res;
+@@ -85,6 +94,9 @@
+
+ bool JackProcessSync::TimedWait(long usec)
+ {
++ ThrowIf(!pthread_equal(pthread_self(), fOwner), JackException("JackProcessSync::TimedWait: a thread has to have locked a mutex before it can wait"));
++ fOwner = 0;
++
+ struct timeval T0, T1;
+ timespec time;
+ struct timeval now;
+@@ -97,17 +109,22 @@
+ unsigned int next_date_usec = now.tv_usec + usec;
+ time.tv_sec = now.tv_sec + (next_date_usec / 1000000);
+ time.tv_nsec = (next_date_usec % 1000000) * 1000;
++
+ res = pthread_cond_timedwait(&fCond, &fMutex, &time);
+- if (res != 0)
++ if (res != 0) {
+ jack_error("JackProcessSync::TimedWait error usec = %ld err = %s", usec, strerror(res));
++ } else {
++ fOwner = pthread_self();
++ }
+
+ gettimeofday(&T1, 0);
+ jack_log("JackProcessSync::TimedWait finished delta = %5.1lf",
+ (1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec));
+-
++
+ return (res == 0);
+ }
+
++// TO DO : check thread consistency?
+ bool JackProcessSync::LockedTimedWait(long usec)
+ {
+ struct timeval T0, T1;
+@@ -118,7 +135,7 @@
+ res1 = pthread_mutex_lock(&fMutex);
+ if (res1 != 0)
+ jack_error("JackProcessSync::LockedTimedWait error err = %s", usec, strerror(res1));
+-
++
+ jack_log("JackProcessSync::TimedWait time out = %ld", usec);
+ gettimeofday(&T0, 0);
+
+@@ -134,10 +151,10 @@
+ res1 = pthread_mutex_unlock(&fMutex);
+ if (res1 != 0)
+ jack_error("JackProcessSync::LockedTimedWait error err = %s", usec, strerror(res1));
+-
++
+ jack_log("JackProcessSync::TimedWait finished delta = %5.1lf",
+ (1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec));
+-
++
+ return (res2 == 0);
+ }
+
+--- a/posix/JackProcessSync.h
++++ b/posix/JackProcessSync.h
+@@ -12,7 +12,7 @@
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+-along with this program; if not, write to the Free Software
++along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ */
+@@ -22,6 +22,7 @@
+
+ #include "JackPlatformPlug.h"
+ #include "JackPosixMutex.h"
++#include "JackException.h"
+ #include <sys/time.h>
+ #include <unistd.h>
+
+@@ -43,7 +44,8 @@
+
+ JackProcessSync():JackBasePosixMutex()
+ {
+- pthread_cond_init(&fCond, NULL);
++ int res = pthread_cond_init(&fCond, NULL);
++ ThrowIf(res != 0, JackException("JackBasePosixMutex: could not init the cond variable"));
+ }
+
+ virtual ~JackProcessSync()
+@@ -53,16 +55,16 @@
+
+ bool TimedWait(long usec);
+ bool LockedTimedWait(long usec);
+-
++
+ void Wait();
+ void LockedWait();
+-
++
+ void Signal();
+ void LockedSignal();
+-
++
+ void SignalAll();
+ void LockedSignalAll();
+-
++
+ };
+
+ } // end of namespace
+--- a/posix/JackSocketClientChannel.cpp
++++ b/posix/JackSocketClientChannel.cpp
+@@ -62,13 +62,14 @@
+ }
+
+ // Check name in server
+- ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
++ ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true);
+ if (result < 0) {
+ int status1 = *status;
+- if (status1 & JackVersionError)
++ if (status1 & JackVersionError) {
+ jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
+- else
++ } else {
+ jack_error("Client name = %s conflits with another running client", name);
++ }
+ goto error;
+ }
+
+@@ -141,9 +142,9 @@
+ }
+ }
+
+-void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result)
++void JackSocketClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open)
+ {
+- JackClientCheckRequest req(name, protocol, options, uuid);
++ JackClientCheckRequest req(name, protocol, options, uuid, open);
+ JackClientCheckResult res;
+ ServerSyncCall(&req, &res, result);
+ *status = res.fStatus;
+@@ -258,24 +259,7 @@
+ JackSessionNotifyResult res;
+ int intresult;
+ ServerSyncCall(&req, &res, &intresult);
+-
+- jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1));
+- int i = 0;
+-
+- for (std::list<JackSessionCommand>::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) {
+- session_command[i].uuid = strdup( ci->fUUID );
+- session_command[i].client_name = strdup( ci->fClientName );
+- session_command[i].command = strdup( ci->fCommand );
+- session_command[i].flags = ci->fFlags;
+- i += 1;
+- }
+-
+- session_command[i].uuid = NULL;
+- session_command[i].client_name = NULL;
+- session_command[i].command = NULL;
+- session_command[i].flags = (jack_session_flags_t)0;
+-
+- *result = session_command;
++ *result = res.GetCommands();
+ }
+
+ void JackSocketClientChannel::SessionReply(int refnum, int* result)
+--- a/posix/JackSocketClientChannel.h
++++ b/posix/JackSocketClientChannel.h
+@@ -60,7 +60,7 @@
+
+ int ServerCheck(const char* server_name);
+
+- void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result);
++ void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open);
+ void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result);
+ void ClientOpen(const char* name, int* ref, int uuid, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result)
+ {}
+--- a/posix/JackSocket.cpp
++++ b/posix/JackSocket.cpp
+@@ -188,6 +188,7 @@
+ jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
+ return 0;
+ } else {
++ jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno));
+ return -1;
+ }
+ } else {
+@@ -232,6 +233,7 @@
+ jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
+ return 0;
+ } else {
++ jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno));
+ return -1;
+ }
+ } else {
+--- a/posix/JackSocketServerChannel.cpp
++++ b/posix/JackSocketServerChannel.cpp
+@@ -66,8 +66,7 @@
+
+ void JackSocketServerChannel::Close()
+ {
+- fThread.Stop();
+- fRequestListenSocket.Close();
++ fRequestListenSocket.Close();
+
+ // Close remaining client sockets
+ std::map<int, std::pair<int, JackClientSocket*> >::iterator it;
+@@ -85,9 +84,14 @@
+ if (fThread.Start() != 0) {
+ jack_error("Cannot start Jack server listener");
+ return -1;
++ } else {
++ return 0;
+ }
++}
+
+- return 0;
++void JackSocketServerChannel::Stop()
++{
++ fThread.Kill();
+ }
+
+ void JackSocketServerChannel::ClientCreate()
+@@ -164,7 +168,7 @@
+ JackRequest header;
+ if (header.Read(socket) < 0) {
+ jack_log("HandleRequest: cannot read header");
+- ClientKill(fd); // TO CHECK SOLARIS
++ ClientKill(fd);
+ return false;
+ }
+
+@@ -185,6 +189,9 @@
+ res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
+ if (res.Write(socket) < 0)
+ jack_error("JackRequest::ClientCheck write error name = %s", req.fName);
++ // Atomic ClientCheck followed by ClientOpen on same socket
++ if (req.fOpen)
++ HandleRequest(fd);
+ break;
+ }
+
+@@ -426,9 +433,8 @@
+ case JackRequest::kSessionNotify: {
+ jack_log("JackRequest::SessionNotify");
+ JackSessionNotifyRequest req;
+- JackSessionNotifyResult res;
+ if (req.Read(socket) == 0) {
+- fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket);
++ fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, socket, NULL);
+ }
+ break;
+ }
+@@ -487,7 +493,7 @@
+ JackClientHasSessionCallbackRequest req;
+ JackResult res;
+ if (req.Read(socket) == 0) {
+- fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult);
++ fServer->GetEngine()->ClientHasSessionCallback(req.fName, &res.fResult);
+ }
+ if (res.Write(socket) < 0)
+ jack_error("JackRequest::ClientHasSessionCallback write error");
+@@ -571,7 +577,7 @@
+ return true;
+
+ } catch (JackQuitException& e) {
+- jack_log("JackMachServerChannel::Execute JackQuitException");
++ jack_log("JackSocketServerChannel::Execute JackQuitException");
+ return false;
+ }
+ }
+--- a/posix/JackSocketServerChannel.h
++++ b/posix/JackSocketServerChannel.h
+@@ -63,6 +63,7 @@
+ void Close(); // Close the Server/Client connection
+
+ int Start();
++ void Stop();
+
+ // JackRunnableInterface interface
+ bool Init();
+--- a/README
++++ b/README
+@@ -20,7 +20,7 @@
+ Linux version
+ --------------
+
+-The published version still uses fifos for server/client synchronization. The use of POSIX named semaphore is implemented but still a bit unstable. Sockets are used for server/client communications. The ALSA backend derived from jackd implementation is used. To build jackdmp, a "waf" (http://code.google.com/p/waf/) based compilation system is available. The code has to be compiled on a machine where ALSA and possibly freeboot (FFADO) headers and libraries are corrected installed.
++The published version still uses fifos for server/client synchronization. The use of POSIX named semaphore is implemented but still a bit unstable. Sockets are used for server/client communications. The ALSA backend derived from jackd implementation is used. To build jackdmp, a "waf" (http://code.google.com/p/waf/) based compilation system is available. The code has to be compiled on a machine where ALSA and possibly freebob (FFADO) headers and libraries are corrected installed.
+
+ In the top folder do :
+
+@@ -212,7 +212,8 @@
+ 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.
+ 1.9.5 : Dynamic choice of maximum port number. More robust sample rate change handling code in JackCoreAudioDriver. Devin Anderson patch for Jack FFADO driver issues with lost MIDI bytes between periods (and more). Fix port_rename callback : now both old name and new name are given as parameters. Special code in JackCoreAudio driver to handle completely buggy Digidesign CoreAudio user-land driver. Ensure that client-side message buffer thread calls thread_init callback if/when it is set by the client (backport of JACK1 rev 3838). Check dynamic port-max value. Fix JackCoreMidiDriver::ReadProcAux when ring buffer is full (thanks Devin Anderson). Josh Green ALSA driver capture only patch. When threads are cancelled, the exception has to be rethrown. Use a QUIT notification to properly quit the server channel, the server channel thread can then be 'stopped' instead of 'canceled'. Mario Lang alsa_io time calculation overflow patch. Shared memory manager was calling abort in case of fatal error, now return an error in caller. Change JackEngineProfiling and JackAudioAdapterInterface gnuplot scripts to output SVG instead of PDF.
+ 1.9.6 : Improve JackCoreAudioDriver and JackCoreAudioAdapter : when no devices are described, takes default input and output and aggregate them.Correct JackGraphManager::DeactivatePort. Correct JackMachServerChannel::Execute : keep running even in error cases. Raise JACK_PROTOCOL_VERSION number. Arnold Krille firewire patch. Raise JACK_DRIVER_PARAM_STRING_MAX and JACK_PARAM_STRING_MAX to 127 otherwise some audio drivers cannot be loaded on OSX. Fix some file header to have library side code use LGPL. On Windows, now use TRE library for regexp (BSD license instead of GPL license). ffado-portname-sync.patch from ticket #163 applied. Remove call to exit in library code. Make jack_connect/jack_disconnect wait for effective port connection/disconnection. Add tests to validate intclient.h API. On Linux, inter-process synchronization primitive switched to POSIX semaphore. In JackCoreAudioDriver, move code called in MeasureCallback to be called once in IO thread. David Garcia Garzon netone patch. Fix from Fernando Lopez-Lezcano for compilation on fc13. Fix JackPosixSemaphore::TimedWait : same behavior as JackPosixSemaphore::Wait regarding EINTR. David Garcia Garzon unused_pkt_buf_field_jack2 netone patch. Arnold Krille firewire snooping patch. Jan Engelhardt patch for get_cycles on SPARC. Adrian Knoth hurd.patch, kfreebsd-fix.patch and alpha_ia64-sigsegv.patch from ticket 177. Adrian Knoth fix for linux cycle.h (ticket 188). In JackCoreAudioDriver, fix an issue when no value is given for input.
+-1.9.7 : Sync JackAlsaDriver::alsa_driver_check_card_type with JACK1 backend. Correct JackServer::Open to avoid a race when control API is used on OSX. Improve backend error handling: fatal error returned by Read/Write now cause a Process failure (so a thread exit for blocking backends). Recoverable ones (XRuns..) are now treated internally in ALSA, FreeBob and FFADO backends. In jackdmp.cpp, jackctl_setup_signals moved before jackctl_server_start. Correct symbols export in backends on OSX. ALSA backend : suspend/resume handling. Correct dummy driver. Adrian Knoth jack_lsp patch. Remove JackPortIsActive flag. New latency API implementation. ComputeTotalLatencies now a client/server call. Add latent test client for latency API. Also print playback and capture latency in jack_lsp. jack_client_has_session_callback implementation. Check requested buffer size and limit to 1..8192 - avoids weird behaviour caused by jack_bufsize foobar. jack_port_type_get_buffer_size implementation. Stop using alloca and allocate buffer on the heap for alsa_io. Rename jdelay to jack_iodelay as per Fons' request. Call buffer size callback in activate (actually this is done on client side in the RT thread Init method). Add jack_midi_dump client. Synchronize net JACK1 with JACK1 version. Synchronize jack_connect/jack_disconnect with JACK1 version. Correct JackNetMaster::SetBufferSize. Use jack_default_audio_sample_t instead of float consistently, fix ticket #201. -X now allows to add several slave backends, add -I to load several internal clients. Rework internal slave driver management, JackServerGlobals now handle same parameters as jackdmp. Correct JackEngine::NotifyGraphReorder, update JackDebugClient with latest API. Devin Anderson server-ctl-proposal branch merged on trunk: improved control API, slave backend reworked. Implement renaming in JackDriver::Open to avoid name collision (thanks Devin Anderson). Correct alsa_driver_restart (thanks Devin Anderson). Correction of jack_connect/jack_disconnect: use of jack_activate and volatile keyword for thread shared variable. Correction of JackNetOneDriver for latest CELT API. Synchronize JackWeakAPI.cpp with new APIs.
++1.9.7 : Sync JackAlsaDriver::alsa_driver_check_card_type with JACK1 backend. Correct JackServer::Open to avoid a race when control API is used on OSX. Improve backend error handling: fatal error returned by Read/Write now cause a Process failure (so a thread exit for blocking backends). Recoverable ones (XRuns..) are now treated internally in ALSA, FreeBob and FFADO backends. In jackdmp.cpp, jackctl_setup_signals moved before jackctl_server_start. Correct symbols export in backends on OSX. ALSA backend : suspend/resume handling. Correct dummy driver. Adrian Knoth jack_lsp patch. Remove JackPortIsActive flag. New latency API implementation. ComputeTotalLatencies now a client/server call. Add latent test client for latency API. Also print playback and capture latency in jack_lsp. jack_client_has_session_callback implementation. Check requested buffer size and limit to 1..8192 - avoids weird behaviour caused by jack_bufsize foobar. jack_port_type_get_buffer_size implementation. Stop using alloca and allocate buffer on the heap for alsa_io. Rename jdelay to jack_iodelay as per Fons' request. Call buffer size callback in activate (actually this is done on client side in the RT thread Init method). Add jack_midi_dump client. Synchronize net JACK1 with JACK1 version. Synchronize jack_connect/jack_disconnect with JACK1 version. Correct JackNetMaster::SetBufferSize. Use jack_default_audio_sample_t instead of float consistently, fix ticket #201. -X now allows to add several slave backends, add -I to load several internal clients. Rework internal slave driver management, JackServerGlobals now handle same parameters as jackdmp. Correct JackEngine::NotifyGraphReorder, update JackDebugClient with latest API. Devin Anderson server-ctl-proposal branch merged on trunk: improved control API, slave backend reworked. Implement renaming in JackDriver::Open to avoid name collision (thanks Devin Anderson). Correct alsa_driver_restart (thanks Devin Anderson). Correction of jack_connect/jack_disconnect: use of jack_activate and volatile keyword for thread shared variable. Correction of JackNetOneDriver for latest CELT API. Synchronize JackWeakAPI.cpp with new APIs.
++1.9.8 : Merge newer-midi branch (Devin Anderson redesign of the MIDI drivers: alsarawmidi, ffado, coremidi and winmme). Correction in jackdmp.cpp: notify_server_stop should be done after server destruction. Correct driver lifetime management. Add XRun detection in PortAudio driver. CELT code for NetJack2. Merge branch switch-master-port-registration-notifications: correct driver port registration. Libjacknet in progress. Correct MIDI in NetJack2. Correct OSX real-time thread setup. Correct rd_acquire in dbus code. Correct NetJack2 connection handling. SaveConnections/RestoreConnections in NetDriver and JackAudioDriver. Special version of jack_attach_shm/jack_release_shm on client side for POSIX shared memory, to solve a memory leak issue. Another round of code improvements to handle completely buggy Digidesign CoreAudio user-land driver. Special CATCH_CLOSE_EXCEPTION_RETURN to handle Close API calls. Add JACK_NETJACK_PORT and JACK_NETJACK_MULTICAST environment variables for NetJack2. NetJack2 now only send data on network only is ports are connected both sides. Fix for "starting two instances of same app in parallel does not work" bug. Enable explicit channel mapping in CoreAudio driver. New JackTimedDriver class to be used by JackDummyDriver, JackNetDriver and JackNetOneDriver classes. More robust code in synchronization primitives and in JackMessageBuffer. More robust Control API implementation. Add jackctl_driver_get_type in Control API. Singleton behaviour for JackCoreMidiDriver and JackWinMMEDriver. John Emmas patch for DSP CPU computation. John Emmas Windows server launching patch. Fix jack_set_port_name API. Enable local access in NetJack2 code.
+
+ 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...
+
+--- a/README_NETJACK2
++++ b/README_NETJACK2
+@@ -1,9 +1,9 @@
+ -------------------------------
+-NetJack for Jackmp
++NetJack2 for Jack2
+ -------------------------------
+
+
+-This release includes a version of netjack designed for jackmp. Indeed, the original concept has been completely redesigned to better fit to the jackmp architecture, but also in order to provide additional capabilities, and ultimately a greater robustness.
++This release includes a version of netjack designed for jack2. Indeed, the original concept has been completely redesigned to better fit to the Jack2 architecture, but also in order to provide additional capabilities, and ultimately a greater robustness.
+
+ This document describes the major changes between those two systems, then a simple how-to for setting up a basic usage of 'netjack2'.
+
+@@ -13,24 +13,24 @@
+ -------------------------------
+
+
+-The biggest difference between netjack and netjack2 is the way of slicing audio and midi streams into network packets. For one audio cycle, netjack used to take all audio and midi buffers (one per channel), put butt all of them, then send it over the network. The problem is that a network packet has a fixed maximum size, depending on the network infrastructure (for 100mb, it reaches 1500bytes - MTU of the network). The solution is then to slice those buffers into smaller ones, and then send as many packets as we need. This cutting up can be done by network equipments, but it's more efficient and secure to include it in the software data management. Still this slicing brings another issue : all the packets are not pleased with any emission order and are unfortunately received in a random order, thanks to UDP. So we can't deal with data as it comes, we need to re-bufferize incoming streams in order to rebuild complete audio buffers.
++The biggest difference between netjack1 and netjack2 is the way of slicing audio and midi streams into network packets. For one audio cycle, netjack1 used to take all audio and midi buffers (one per channel), put butt all of them, then send it over the network. The problem is that a network packet has a fixed maximum size, depending on the network infrastructure (for 100mb, it reaches 1500bytes - MTU of the network). The solution is then to slice those buffers into smaller ones, and then send as many packets as we need. This cutting up can be done by network equipments, but it's more efficient and secure to include it in the software data management. Still this slicing brings another issue : all the packets are not pleased with any emission order and are unfortunately received in a random order, thanks to UDP. So we can't deal with data as it comes, we need to re-bufferize incoming streams in order to rebuild complete audio buffers.
+
+-In netjack2, the main idea is to make this slicing depending on the network capabilities. If we can put only 128 complete audio frames (128 samples for all audio channels) in a network packet, the elementary packet will so carry 128 frames, and in one cycle, we will transmit as many packet as we need. We take the example of 128 frames because it's the current value for 2 channels. This value is determinated by taking the maximum 'power of 2' frames we can put in a packet. If we take 2 channels, 4 bytes per sample (float values), we get 8 bytes per frame, with 128 frames, we now have 1024 bytes, so we can put these 1024 bytes in one packet, and add a small header which identify the packet. This technique allows to separate the packets (in time) so they can be received in the order they have been emitted. If the master is running at 512 frames per second, four audio packets are sent per cycle and the slave deals with them as they arrive. With gigabytes networks, the MTU is larger, so we can put more data in one packet (in this example, we can even put the complete cycle in one packet).
++In netjack2, the main idea is to make this slicing depending on the network capabilities. If we can put only 128 complete audio frames (128 samples for all audio channels) in a network packet, the elementary packet will so carry 128 frames, and in one cycle, we will transmit as many packet as we need. We take the example of 128 frames because it's the current value for 2 channels. This value is determined by taking the maximum 'power of 2' frames we can put in a packet. If we take 2 channels, 4 bytes per sample (float values), we get 8 bytes per frame, with 128 frames, we now have 1024 bytes, so we can put these 1024 bytes in one packet, and add a small header which identify the packet. This technique allows to separate the packets (in time) so they can be received in the order they have been emitted. If the master is running at 512 frames per second, four audio packets are sent per cycle and the slave deals with them as they arrive. With gigabytes networks, the MTU is larger, so we can put more data in one packet (in this example, we can even put the complete cycle in one packet).
+
+-For midi data, netjack used to send the whole buffer, in this example, 512 frames * 4 bytes per sample and per midi port. Those 2048 bytes are in 99% of the time filled to a few bytes, but rarely more. This means that if we have 2 audio and 2 midi channels to transmit, everything happens as if we had 4 audio channels, which is quite a waste of bandwidth. In netjack2, the idea is to take into account that fact, by sending only the useful bytes, and not more. It's completely unappropriate to overload the network with useless data. So we now have : 99% of the time one midi packet (of a few dozen of bytes), followed by four audio packets (in this example).
++For midi data, netjack1 used to send the whole buffer, in this example, 512 frames * 4 bytes per sample and per midi port. Those 2048 bytes are in 99% of the time filled to a few bytes, but rarely more. This means that if we have 2 audio and 2 midi channels to transmit, everything happens as if we had 4 audio channels, which is quite a waste of bandwidth. In netjack2, the idea is to take into account that fact, by sending only the useful bytes, and not more. It's completely inappropriate to overload the network with useless data. So we now have : 99% of the time one midi packet (of a few dozen of bytes), followed by four audio packets (in this example).
+
+ This way of separating audio and midi is quite important. We deal here with network transmissions, and also need to be 'realtime'. We need a system which allow to carry as many audio and midi data streams as we need and can, as if the distant computer was in fact a simple jack client. With all those constraints, we can't avoid packets loss. The better thing to do is to deal with it. But to loose an audio packet is different from skipping a midi one. Indeed, an audio loss leads to audio click, or undesirable, but very short side effect. Whereas a midi data loss can be completely disastrous. Imagine that we play some notes, with sustain, and we loose the sustain 0 value, which stops the effect. The sustain keeps going on on all following notes until the next 'sustain off' event. A simple missing byte can put all the midi system offside (that's the purpose of all the big PANIC buttons on midi softwares...). That's why we need to separate audio (more than one per cycle) from midi (one packet at 99% of the time). If we loose an audio packet, we probably still have an available midi packet, so we can use what we received, even if some audio is missing.
+
+-Those audio and midi packets are preceded by a synchronization packet, which will make the slave directly synchronized on the master's cycle rythm. This packet also carries transport data. Thus it's actually possible to synchronize also transport. This feature goes a little further than in netjack. The idea here is to make every computer of the network fully synchronized on the master's transport. That means the master needs to know the state of every slow sync clients of each of its slaves. The master can now manage the transport state (especially the 'rolling' state) of each slave thus the main transport waits for the last slow sync client before turning 'rolling'. By doing this, the transport can start (roll) in the same cycle for every computers managed by the master.
++Those audio and midi packets are preceded by a synchronization packet, which will make the slave directly synchronized on the master's cycle rhythm. This packet also carries transport data. Thus it's actually possible to synchronize also transport. This feature goes a little further than in netjack1. The idea here is to make every computer of the network fully synchronized on the master's transport. That means the master needs to know the state of every slow sync clients of each of its slaves. The master can now manage the transport state (especially the 'rolling' state) of each slave thus the main transport waits for the last slow sync client before turning 'rolling'. By doing this, the transport can start (roll) in the same cycle for every computers managed by the master.
+
+
+-The second main difference between netjack and netjack2 is the way the two computers (master and slave) synchronise their parametering and launch. In netjack, once the slave configured (by the command line) and launched, it was waiting for the first incoming packet to synchronize (launch its first audio cycle) then run. The two computers needed to be configured separately but with the same parameters to run correctly.
++The second main difference between netjack1 and netjack2 is the way the two computers (master and slave) synchronize their parameters and launch. In netjack1, once the slave configured (by the command line) and launched, it was waiting for the first incoming packet to synchronize (launch its first audio cycle) then run. The two computers needed to be configured separately but with the same parameters to run correctly.
+
+-In netjack2, the only thing you have to set for the slave is its number of in/out midi and audio channels. No more need to choose and set parameters depending on the master, they are automatically determinated and communicated to the slave. This first synchronization step uses a multicast communication, no more need to know by advance all the IP addresses. The slave says on a multicast address "hey, I'm available". A master get the message, and communicate parametering to the slave. Once synchronization done, data transfers can start. Moreover, the master being still listening on the multicast address, it can catch other slaves and manage them (create a jack client to communicate with the slave, and neatily close everything when the slave is gone).
++In netjack2, the only thing you have to set for the slave is its number of in/out midi and audio channels. No more need to choose and set parameters depending on the master, they are automatically determined and communicated to the slave. This first synchronization step uses a multicast communication, no more need to know by advance all the IP addresses. The slave says on a multicast address "hey, I'm available". A master get the message, and communicate parameterers to the slave. Once synchronization done, data transfers can start. Moreover, the master being still listening on the multicast address, it can catch other slaves and manage them (create a jack client to communicate with the slave, and neatly close everything when the slave is gone).
+
+-The loaded internal client is no longer only an interface for the slave, like in netjack. It's now called 'network manager', it doesn't deal with audio or midi, just with some kind of 'network logistical messages'. The manager automatically create a new internal client as soon as a new slave is seen on the network (by sending messages on the multicast address the manager is listening on). This manager is also able to remove one of its internal client as soon as a slave has left the network. This conception allow a complete separation of audio exchanges from parametering and management.
++The loaded internal client is no longer only an interface for the slave, like in netjack1. It's now called 'network manager', it doesn't deal with audio or midi, just with some kind of 'network logistical messages'. The manager automatically create a new internal client as soon as a new slave is seen on the network (by sending messages on the multicast address the manager is listening on). This manager is also able to remove one of its internal client as soon as a slave has left the network. This conception allow a complete separation of audio exchanges from parameterers and management.
+
+-The 'unloading' of the internal client (the manager) will cause a full cleaning of the infrastructure. The jack clients are all removed from the server, the slave are all turned available again, ready to be cought by another master etc. When a slave quits, it's also automatically removed from the manager's slaves list.
++The 'unloading' of the internal client (the manager) will cause a full cleaning of the infrastructure. The jack clients are all removed from the server, the slave are all turned available again, ready to be caught by another master etc. When a slave quits, it's also automatically removed from the manager's slaves list.
+
+
+ -------------------------------
+@@ -40,13 +40,13 @@
+
+ Netjackmp is very simple to use. On the master's side, an internal client deals with the slaves, and the slaves themselves are classical jack servers running under a 'network audio driver'. The difference between the two versions is that the master now has a manager, which takes care of the slaves, while listening on the multicast address and create a new master as soon as a slave is available. But everything is transparent to the user, that's why it uses multicast (someone says "hello", and anyone who wants to hear it just has to listen).
+
+-So, just compile and install jackmp as you are used to, on linux, using './waf configure', './waf' and './waf install' as root. On macosx, you can use the xcode project. On Windows, you can use the Code::Blocks workspace (you also have a small script to make an all in one installer).
++So, just compile and install Jack2 as you are used to, on linux, using './waf configure', './waf' and './waf install' as root. On macosx, you can use the xcode project. On Windows, you can use the Code::Blocks workspace (you also have a small script to make an all in one installer).
+
+ On the master, just launch a classical jack server, the period size doesn't matter. Then, load the network manager using jack_load :
+
+ 'jack_load netmanager'
+
+-This will load the internal client, which will wait for an available slave (see the message window on qjackctl - or the console output). If you want to listen to a specific multicast socket, you can add some options. To spicify a complete command line, you can use :
++This will load the internal client, which will wait for an available slave (see the message window on QjackCtl - or the console output). If you want to listen to a specific multicast socket, you can add some options. To specify a complete command line, you can use :
+
+ 'jack_load netmanager -i"-a xxx.xxx.xxx.xxx -p udp_port"'
+
+@@ -56,7 +56,7 @@
+
+ 'jackd -R -d net'
+
+-As in a standard backend in Jackmp, you can use '-S' (synchronous mode). The asynchronous mode (without '-S') allows to send the computed data during the next cycle. In synchronous mode, data are sent back at the end of the cycle, that means after the process. You can specify some options, like '-n name' (will give a name to the slave, default is the network hostname), '-C input_ports' (the number of master-->slave channels), '-P output_ports' (the number of slave-->master channels), default is 2 ; or '-i midi_in_ports' and '-o midi_out_ports', default is 0. If you set multicast address or port on the master, you can add '-a xxx.xxx.xxx.xxx' and '-p udp_port'.
++As in a standard backend in Jack2, you can use '-S' (synchronous mode). The asynchronous mode (without '-S') allows to send the computed data during the next cycle. In synchronous mode, data are sent back at the end of the cycle, that means after the process. You can specify some options, like '-n name' (will give a name to the slave, default is the network hostname), '-C input_ports' (the number of master-->slave channels), '-P output_ports' (the number of slave-->master channels), default is 2 ; or '-i midi_in_ports' and '-o midi_out_ports', default is 0. If you set multicast address or port on the master, you can add '-a xxx.xxx.xxx.xxx' and '-p udp_port'.
+
+ You can also use others network mode, with '-m' option (fast, normal or slow). Fast mode allow a zero latency transmission. This mode means the master waits for its returned data from the slave in the current cycle. This mode is appropriated for 'small' transmissions (only a few channels with a light process on the slave). Normal mode brings one cycle latency. It allow a normal use of the network.
+
+@@ -69,6 +69,6 @@
+ What's next ?
+ -------------------------------
+
+-The development of netjack continues and some things are always moving... If you use it, please report encountered bugs, ideas or anything you think about.
++The development of netjack2 continues and some things are always moving... If you use it, please report encountered bugs, ideas or anything you think about.
+
+ If you have any question, you can subscribe the jackaudio developers mailing list at http://www.jackaudio.org/ or join the IRC channel '#jack' on FreeNode.
+--- a/solaris/oss/JackBoomerDriver.cpp
++++ b/solaris/oss/JackBoomerDriver.cpp
+@@ -106,14 +106,14 @@
+ case 24: {
+ signed int *s32dst = (signed int*)dst;
+ s32dst += channel;
+- sample_move_d24_sS((char*)s32dst, src, nframes, byte_skip, NULL);
++ sample_move_d24_sS((char*)s32dst, src, nframes, byte_skip, NULL);
+ break;
+- }
++ }
+ case 32: {
+ signed int *s32dst = (signed int*)dst;
+ s32dst += channel;
+ sample_move_d32u24_sS((char*)s32dst, src, nframes, byte_skip, NULL);
+- break;
++ break;
+ }
+ }
+ }
+@@ -127,7 +127,7 @@
+ fSampleSize = 4;
+ break;
+ case 32: /* native-endian 32-bit integer */
+- fSampleFormat = AFMT_S32_NE;
++ fSampleFormat = AFMT_S32_NE;
+ fSampleSize = 4;
+ break;
+ case 16: /* native-endian 16-bit integer */
+@@ -144,13 +144,13 @@
+ oss_audioinfo ai_in, ai_out;
+ memset(&info, 0, sizeof(audio_buf_info));
+ int cap = 0;
+-
++
+ // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
+ jack_info("Audio Interface Description :");
+ jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode);
+-
++
+ if (fRWMode & kWrite) {
+-
++
+ oss_sysinfo si;
+ if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
+ jack_error("JackBoomerDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -162,18 +162,18 @@
+ jack_info("OSS numaudioengines %d", si.numaudioengines);
+ jack_info("OSS numcards %d", si.numcards);
+ }
+-
++
+ jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
+ jack_info("Output block size = %d", fOutputBufferSize);
+-
++
+ if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
+ jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+- jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
++ jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
+ info.fragments, info.fragstotal, info.fragsize, info.bytes);
+ fFragmentSize = info.fragsize;
+ }
+-
++
+ if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
+ jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+@@ -186,10 +186,10 @@
+ if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
+ if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
+ }
+- }
+-
++ }
++
+ if (fRWMode & kRead) {
+-
++
+ oss_sysinfo si;
+ if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
+ jack_error("JackBoomerDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -201,14 +201,14 @@
+ jack_info("OSS numaudioengines %d", si.numaudioengines);
+ jack_info("OSS numcards %d", si.numcards);
+ }
+-
++
+ jack_info("Input capabilities - %d channels : ", fCaptureChannels);
+ jack_info("Input block size = %d", fInputBufferSize);
+-
+- if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
++
++ if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
+ jack_error("JackBoomerDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+- jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
++ jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
+ info.fragments, info.fragstotal, info.fragsize, info.bytes);
+ }
+
+@@ -225,31 +225,30 @@
+ if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
+ }
+ }
+-
++
+ if (ai_in.rate_source != ai_out.rate_source) {
+ jack_info("Warning : input and output are not necessarily driven by the same clock!");
+ }
+ }
+
+ JackBoomerDriver::JackBoomerDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+- : JackAudioDriver(name, alias, engine, table),
+- fInFD(-1), fOutFD(-1), fBits(0),
+- fSampleFormat(0), fNperiods(0), fSampleSize(0), fFragmentSize(0),
+- fRWMode(0), fExcl(false), fSyncIO(false),
+- fInputBufferSize(0), fOutputBufferSize(0),
+- fInputBuffer(NULL), fOutputBuffer(NULL),
+- fInputThread(&fInputHandler), fOutputThread(&fOutputHandler),
+- fInputHandler(this), fOutputHandler(this)
+-
++ : JackAudioDriver(name, alias, engine, table),
++ fInFD(-1), fOutFD(-1), fBits(0),
++ fSampleFormat(0), fNperiods(0), fSampleSize(0), fFragmentSize(0),
++ fRWMode(0), fExcl(false), fSyncIO(false),
++ fInputBufferSize(0), fOutputBufferSize(0),
++ fInputBuffer(NULL), fOutputBuffer(NULL),
++ fInputThread(&fInputHandler), fOutputThread(&fOutputHandler),
++ fInputHandler(this), fOutputHandler(this)
+ {
+- sem_init(&fReadSema, 0, 0);
+- sem_init(&fWriteSema, 0, 0);
++ sem_init(&fReadSema, 0, 0);
++ sem_init(&fWriteSema, 0, 0);
+ }
+
+ JackBoomerDriver::~JackBoomerDriver()
+ {
+- sem_destroy(&fReadSema);
+- sem_destroy(&fWriteSema);
++ sem_destroy(&fReadSema);
++ sem_destroy(&fWriteSema);
+ }
+
+ int JackBoomerDriver::OpenInput()
+@@ -260,8 +259,9 @@
+ int cur_sample_format;
+ jack_nframes_t cur_sample_rate;
+
+- if (fCaptureChannels == 0) fCaptureChannels = 2;
+-
++ if (fCaptureChannels == 0)
++ fCaptureChannels = 2;
++
+ if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
+ jack_error("JackBoomerDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+@@ -276,7 +276,7 @@
+ }
+ }
+
+- gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
++ gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
+ if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
+ jack_error("JackBoomerDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+@@ -290,7 +290,7 @@
+ if (cur_sample_format != fSampleFormat) {
+ jack_info("JackBoomerDriver::OpenInput driver forced the sample format %ld", fSampleFormat);
+ }
+-
++
+ cur_capture_channels = fCaptureChannels;
+ if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
+ jack_error("JackBoomerDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -299,7 +299,7 @@
+ if (cur_capture_channels != fCaptureChannels) {
+ jack_info("JackBoomerDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
+ }
+-
++
+ cur_sample_rate = fEngineControl->fSampleRate;
+ if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
+ jack_error("JackBoomerDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -315,7 +315,7 @@
+ fInputBuffer = (void*)calloc(fInputBufferSize, 1);
+ assert(fInputBuffer);
+ return 0;
+-
++
+ error:
+ ::close(fInFD);
+ return -1;
+@@ -329,28 +329,29 @@
+ int cur_playback_channels;
+ jack_nframes_t cur_sample_rate;
+
+- if (fPlaybackChannels == 0) fPlaybackChannels = 2;
+-
++ if (fPlaybackChannels == 0)
++ fPlaybackChannels = 2;
++
+ if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
+ jack_error("JackBoomerDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+ }
+
+ jack_log("JackBoomerDriver::OpenOutput output fOutFD = %d", fOutFD);
+-
++
+ if (fExcl) {
+ if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
+ jack_error("JackBoomerDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+- }
+- }
++ }
++ }
+
+- gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
++ gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
+ if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
+ jack_error("JackBoomerDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+ }
+-
++
+ cur_sample_format = fSampleFormat;
+ if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
+ jack_error("JackBoomerDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -359,7 +360,7 @@
+ if (cur_sample_format != fSampleFormat) {
+ jack_info("JackBoomerDriver::OpenOutput driver forced the sample format %ld", fSampleFormat);
+ }
+-
++
+ cur_playback_channels = fPlaybackChannels;
+ if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
+ jack_error("JackBoomerDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -380,33 +381,33 @@
+
+ // Just set the write size to the value we want...
+ fOutputBufferSize = fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels;
+-
++
+ fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
+ assert(fOutputBuffer);
+ return 0;
+-
++
+ error:
+ ::close(fOutFD);
+ return -1;
+ }
+
+ int JackBoomerDriver::Open(jack_nframes_t nframes,
+- int user_nperiods,
+- jack_nframes_t samplerate,
+- bool capturing,
+- bool playing,
+- int inchannels,
+- int outchannels,
+- bool excl,
+- bool monitor,
+- const char* capture_driver_uid,
+- const char* playback_driver_uid,
+- jack_nframes_t capture_latency,
+- jack_nframes_t playback_latency,
+- int bits, bool syncio)
++ int user_nperiods,
++ jack_nframes_t samplerate,
++ bool capturing,
++ bool playing,
++ int inchannels,
++ int outchannels,
++ bool excl,
++ bool monitor,
++ const char* capture_driver_uid,
++ const char* playback_driver_uid,
++ jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency,
++ int bits, bool syncio)
+ {
+ // Generic JackAudioDriver Open
+- if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
++ if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
+ capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
+ return -1;
+ } else {
+@@ -422,12 +423,12 @@
+ fExcl = excl;
+ fNperiods = (user_nperiods == 0) ? 1 : user_nperiods ;
+ fSyncIO = syncio;
+-
++
+ #ifdef JACK_MONITOR
+ // Force memory page in
+ memset(&gCycleTable, 0, sizeof(gCycleTable));
+ #endif
+-
++
+ if (OpenAux() < 0) {
+ Close();
+ return -1;
+@@ -441,14 +442,14 @@
+ {
+ #ifdef JACK_MONITOR
+ FILE* file = fopen("OSSProfiling.log", "w");
+-
++
+ if (file) {
+ jack_info("Writing OSS driver timing data....");
+ for (int i = 1; i < std::min(gCycleReadCount, gCycleWriteCount); i++) {
+ int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
+ int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
+ int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
+- int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
++ int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
+ fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
+ }
+ fclose(file);
+@@ -461,7 +462,7 @@
+ if (file == NULL) {
+ jack_error("JackBoomerDriver::Close cannot open TimingOSS.plot file");
+ } else {
+-
++
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"OSS audio driver timing\"\n");
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+@@ -470,10 +471,10 @@
+ \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
+ \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
+ \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
+-
++
+ fprintf(file, "set output 'TimingOSS.pdf\n");
+ fprintf(file, "set terminal pdf\n");
+-
++
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"OSS audio driver timing\"\n");
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+@@ -482,12 +483,12 @@
+ \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
+ \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
+ \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
+-
++
+ fclose(file);
+ }
+ #endif
+ int res = JackAudioDriver::Close();
+- CloseAux();
++ CloseAux();
+ return res;
+ }
+
+@@ -498,12 +499,12 @@
+ if ((fRWMode & kRead) && (OpenInput() < 0)) {
+ return -1;
+ }
+-
+- if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
++
++ if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
+ return -1;
+ }
+-
+- DisplayDeviceInfo();
++
++ DisplayDeviceInfo();
+ return 0;
+ }
+
+@@ -513,16 +514,16 @@
+ close(fInFD);
+ fInFD = -1;
+ }
+-
++
+ if (fRWMode & kWrite && fOutFD >= 0) {
+ close(fOutFD);
+ fOutFD = -1;
+ }
+-
++
+ if (fInputBuffer)
+ free(fInputBuffer);
+ fInputBuffer = NULL;
+-
++
+ if (fOutputBuffer)
+ free(fOutputBuffer);
+ fOutputBuffer = NULL;
+@@ -533,29 +534,29 @@
+ jack_log("JackBoomerDriver::Start");
+ JackAudioDriver::Start();
+
+- // Input/output synchronisation
++ // Input/output synchronisation
+ if (fInFD >= 0 && fOutFD >= 0 && fSyncIO) {
+
+- jack_log("JackBoomerDriver::Start sync input/output");
++ jack_log("JackBoomerDriver::Start sync input/output");
+
+ // Create and fill synch group
+ int id;
+ oss_syncgroup group;
+ group.id = 0;
+-
++
+ group.mode = PCM_ENABLE_INPUT;
+- if (ioctl(fInFD, SNDCTL_DSP_SYNCGROUP, &group) == -1)
++ if (ioctl(fInFD, SNDCTL_DSP_SYNCGROUP, &group) == -1)
+ jack_error("JackBoomerDriver::Start failed to use SNDCTL_DSP_SYNCGROUP : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+-
++
+ group.mode = PCM_ENABLE_OUTPUT;
+- if (ioctl(fOutFD, SNDCTL_DSP_SYNCGROUP, &group) == -1)
++ if (ioctl(fOutFD, SNDCTL_DSP_SYNCGROUP, &group) == -1)
+ jack_error("JackBoomerDriver::Start failed to use SNDCTL_DSP_SYNCGROUP : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+
+ // Prefill output buffer : 2 fragments of silence as described in http://manuals.opensound.com/developer/synctest.c.html#LOC6
+ char* silence_buf = (char*)malloc(fFragmentSize);
+ memset(silence_buf, 0, fFragmentSize);
+
+- jack_log ("JackBoomerDriver::Start prefill size = %d", fFragmentSize);
++ jack_log ("JackBoomerDriver::Start prefill size = %d", fFragmentSize);
+
+ for (int i = 0; i < 2; i++) {
+ ssize_t count = ::write(fOutFD, silence_buf, fFragmentSize);
+@@ -569,12 +570,12 @@
+ // Start input/output in sync
+ id = group.id;
+
+- if (ioctl(fInFD, SNDCTL_DSP_SYNCSTART, &id) == -1)
++ if (ioctl(fInFD, SNDCTL_DSP_SYNCSTART, &id) == -1)
+ jack_error("JackBoomerDriver::Start failed to use SNDCTL_DSP_SYNCSTART : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+
+ } else if (fOutFD >= 0) {
+-
+- // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
++
++ // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
+ memset(fOutputBuffer, 0, fOutputBufferSize);
+
+ // Prefill ouput buffer
+@@ -584,8 +585,8 @@
+ jack_error("JackBoomerDriver::Start error bytes written = %ld", count);
+ }
+ }
+- }
+-
++ }
++
+ // Start input thread only when needed
+ if (fInFD >= 0) {
+ if (fInputThread.StartSync() < 0) {
+@@ -627,44 +628,44 @@
+ if (fDriver->fInputThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
+ jack_error("AcquireRealTime error");
+ } else {
+- set_threaded_log_function();
++ set_threaded_log_function();
+ }
+ }
+-
++
+ return true;
+ }
+
+ // TODO : better error handling
+ bool JackBoomerDriver::JackBoomerDriverInput::Execute()
+ {
+-
++
+ #ifdef JACK_MONITOR
+ gCycleTable.fTable[gCycleReadCount].fBeforeRead = GetMicroSeconds();
+ #endif
+
+ audio_errinfo ei_in;
+- ssize_t count = ::read(fDriver->fInFD, fDriver->fInputBuffer, fDriver->fInputBufferSize);
+-
++ ssize_t count = ::read(fDriver->fInFD, fDriver->fInputBuffer, fDriver->fInputBufferSize);
++
+ #ifdef JACK_MONITOR
+ if (count > 0 && count != (int)fDriver->fInputBufferSize)
+ jack_log("JackBoomerDriverInput::Execute count = %ld", count / (fDriver->fSampleSize * fDriver->fCaptureChannels));
+ gCycleTable.fTable[gCycleReadCount].fAfterRead = GetMicroSeconds();
+ #endif
+-
++
+ // XRun detection
+ if (ioctl(fDriver->fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
+
+ if (ei_in.rec_overruns > 0 ) {
+ jack_error("JackBoomerDriverInput::Execute overruns");
+ jack_time_t cur_time = GetMicroSeconds();
+- fDriver->NotifyXRun(cur_time, float(cur_time - fDriver->fBeginDateUst)); // Better this value than nothing...
++ fDriver->NotifyXRun(cur_time, float(cur_time - fDriver->fBeginDateUst)); // Better this value than nothing...
+ }
+
+ if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
+ jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
+ }
+- }
+-
++ }
++
+ if (count < 0) {
+ jack_log("JackBoomerDriverInput::Execute error = %s", strerror(errno));
+ } else if (count < (int)fDriver->fInputBufferSize) {
+@@ -675,11 +676,11 @@
+ fDriver->CycleTakeBeginTime();
+ for (int i = 0; i < fDriver->fCaptureChannels; i++) {
+ if (fDriver->fGraphManager->GetConnectionsNum(fDriver->fCapturePortList[i]) > 0) {
+- CopyAndConvertIn(fDriver->GetInputBuffer(i),
+- fDriver->fInputBuffer,
+- fDriver->fEngineControl->fBufferSize,
+- i,
+- fDriver->fCaptureChannels * fDriver->fSampleSize,
++ CopyAndConvertIn(fDriver->GetInputBuffer(i),
++ fDriver->fInputBuffer,
++ fDriver->fEngineControl->fBufferSize,
++ i,
++ fDriver->fCaptureChannels * fDriver->fSampleSize,
+ fDriver->fBits);
+ }
+ }
+@@ -707,18 +708,18 @@
+ if (fDriver->fOutputThread.AcquireRealTime(GetEngineControl()->fServerPriority) < 0) {
+ jack_error("AcquireRealTime error");
+ } else {
+- set_threaded_log_function();
++ set_threaded_log_function();
+ }
+ }
+-
++
+ int delay;
+ if (ioctl(fDriver->fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
+ jack_error("JackBoomerDriverOutput::Init error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ }
+-
++
+ delay /= fDriver->fSampleSize * fDriver->fPlaybackChannels;
+ jack_info("JackBoomerDriverOutput::Init output latency frames = %ld", delay);
+-
++
+ return true;
+ }
+
+@@ -730,21 +731,21 @@
+ #ifdef JACK_MONITOR
+ gCycleTable.fTable[gCycleWriteCount].fBeforeWriteConvert = GetMicroSeconds();
+ #endif
+-
++
+ for (int i = 0; i < fDriver->fPlaybackChannels; i++) {
+ if (fDriver->fGraphManager->GetConnectionsNum(fDriver->fPlaybackPortList[i]) > 0) {
+- CopyAndConvertOut(fDriver->fOutputBuffer,
+- fDriver->GetOutputBuffer(i),
+- fDriver->fEngineControl->fBufferSize,
+- i,
+- fDriver->fPlaybackChannels * fDriver->fSampleSize,
++ CopyAndConvertOut(fDriver->fOutputBuffer,
++ fDriver->GetOutputBuffer(i),
++ fDriver->fEngineControl->fBufferSize,
++ i,
++ fDriver->fPlaybackChannels * fDriver->fSampleSize,
+ fDriver->fBits);
+ }
+ }
+-
++
+ #ifdef JACK_MONITOR
+ gCycleTable.fTable[gCycleWriteCount].fBeforeWrite = GetMicroSeconds();
+-#endif
++#endif
+
+ ssize_t count = ::write(fDriver->fOutFD, fDriver->fOutputBuffer, fDriver->fOutputBufferSize);
+
+@@ -762,20 +763,20 @@
+ if (ei_out.play_underruns > 0) {
+ jack_error("JackBoomerDriverOutput::Execute underruns");
+ jack_time_t cur_time = GetMicroSeconds();
+- fDriver->NotifyXRun(cur_time, float(cur_time - fDriver->fBeginDateUst)); // Better this value than nothing...
++ fDriver->NotifyXRun(cur_time, float(cur_time - fDriver->fBeginDateUst)); // Better this value than nothing...
+ }
+
+ if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
+ jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
+ }
+ }
+-
++
+ if (count < 0) {
+ jack_log("JackBoomerDriverOutput::Execute error = %s", strerror(errno));
+ } else if (count < (int)fDriver->fOutputBufferSize) {
+ jack_error("JackBoomerDriverOutput::Execute error bytes written = %ld", count);
+ }
+-
++
+ // Duplex : sync with read thread
+ if (fDriver->fInFD >= 0 && fDriver->fOutFD >= 0) {
+ fDriver->SynchronizeWrite();
+@@ -802,12 +803,11 @@
+
+ int JackBoomerDriver::SetBufferSize(jack_nframes_t buffer_size)
+ {
+- CloseAux();
+- JackAudioDriver::SetBufferSize(buffer_size); // never fails
++ CloseAux();
++ JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
+ return OpenAux();
+ }
+
+-
+ } // end of namespace
+
+ #ifdef __cplusplus
+@@ -817,119 +817,44 @@
+
+ SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "boomer"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "Boomer/OSS API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = OSS_DRIVER_N_PARAMS;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_FS;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "nperiods");
+- desc->params[i].character = 'n';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS;
+- strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "wordlength");
+- desc->params[i].character = 'w';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = OSS_DRIVER_DEF_BITS;
+- strcpy(desc->params[i].short_desc, "Word length");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_INS;
+- strcpy(desc->params[i].short_desc, "Capture channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS;
+- strcpy(desc->params[i].short_desc, "Playback channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "excl");
+- desc->params[i].character = 'e';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "Input device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "Output device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy (desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "OSS device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "input-latency");
+- desc->params[i].character = 'I';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra input latency");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "output-latency");
+- desc->params[i].character = 'O';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra output latency");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "sync-io");
+- desc->params[i].character = 'S';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy(desc->params[i].short_desc, "In duplex mode, synchronize input and output");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("boomer", JackDriverMaster, "Boomer/OSS API based audio backend", &filler);
++
++ value.ui = OSS_DRIVER_DEF_FS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = OSS_DRIVER_DEF_BLKSIZE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = OSS_DRIVER_DEF_NPERIODS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
++
++ value.i = OSS_DRIVER_DEF_BITS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
++
++ value.ui = OSS_DRIVER_DEF_INS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
++
++ value.ui = OSS_DRIVER_DEF_OUTS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL);
++
++ strcpy(value.str, OSS_DRIVER_DEF_DEV);
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "sync-io", 'S', JackDriverParamBool, &value, NULL, "In duplex mode, synchronize input and output", NULL);
+
+ return desc;
+ }
+@@ -953,13 +878,13 @@
+ const jack_driver_param_t *param;
+ jack_nframes_t systemic_input_latency = 0;
+ jack_nframes_t systemic_output_latency = 0;
+-
++
+ for (node = params; node; node = jack_slist_next(node)) {
+-
++
+ param = (const jack_driver_param_t *)node->data;
+
+ switch (param->character) {
+-
++
+ case 'r':
+ srate = param->value.ui;
+ break;
+@@ -983,7 +908,7 @@
+ case 'o':
+ chan_out = (int)param->value.ui;
+ break;
+-
++
+ case 'C':
+ capture = true;
+ if (strcmp(param->value.str, "none") != 0) {
+@@ -1002,11 +927,11 @@
+ playback_pcm_name = param->value.str;
+ capture_pcm_name = param->value.str;
+ break;
+-
++
+ case 'e':
+ excl = true;
+ break;
+-
++
+ case 'I':
+ systemic_input_latency = param->value.ui;
+ break;
+@@ -1028,9 +953,9 @@
+ }
+
+ Jack::JackBoomerDriver* boomer_driver = new Jack::JackBoomerDriver("system", "boomer", engine, table);
+-
++
+ // Special open for Boomer driver...
+- if (boomer_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out, excl,
++ if (boomer_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out, excl,
+ monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, syncio) == 0) {
+ return boomer_driver;
+ } else {
+--- a/solaris/oss/JackBoomerDriver.h
++++ b/solaris/oss/JackBoomerDriver.h
+@@ -30,7 +30,6 @@
+
+ typedef jack_default_audio_sample_t jack_sample_t;
+
+-#define OSS_DRIVER_N_PARAMS 13
+ #define OSS_DRIVER_DEF_DEV "/dev/dsp"
+ #define OSS_DRIVER_DEF_FS 48000
+ #define OSS_DRIVER_DEF_BLKSIZE 1024
+--- a/solaris/oss/JackOSSAdapter.cpp
++++ b/solaris/oss/JackOSSAdapter.cpp
+@@ -73,12 +73,12 @@
+ s32dst += channel;
+ sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now...
+ break;
+- }
++ }
+ case 32: {
+ signed int *s32dst = (signed int*)dst;
+ s32dst += channel;
+ sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
+- break;
++ break;
+ }
+ }
+ }
+@@ -92,7 +92,7 @@
+ fSampleSize = sizeof(int);
+ break;
+ case 32: /* native-endian 32-bit integer */
+- fSampleFormat = AFMT_S32_NE;
++ fSampleFormat = AFMT_S32_NE;
+ fSampleSize = sizeof(int);
+ break;
+ case 16: /* native-endian 16-bit integer */
+@@ -105,30 +105,30 @@
+
+ JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
+ :JackAudioAdapterInterface(buffer_size, sample_rate)
+- ,fThread(this),
+- fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS),
++ ,fThread(this),
++ fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS),
+ fSampleFormat(0), fNperiods(OSS_DRIVER_DEF_NPERIODS), fRWMode(0), fIgnoreHW(true), fExcl(false),
+ fInputBufferSize(0), fOutputBufferSize(0),
+ fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true)
+ {
+ const JSList* node;
+ const jack_driver_param_t* param;
+-
++
+ fCaptureChannels = 2;
+ fPlaybackChannels = 2;
+
+ strcpy(fCaptureDriverName, OSS_DRIVER_DEF_DEV);
+ strcpy(fPlaybackDriverName, OSS_DRIVER_DEF_DEV);
+-
++
+ for (node = params; node; node = jack_slist_next(node)) {
+ param = (const jack_driver_param_t*) node->data;
+-
++
+ switch (param->character) {
+
+ case 'r':
+ SetAdaptedSampleRate(param->value.ui);
+ break;
+-
++
+ case 'p':
+ SetAdaptedBufferSize(param->value.ui);
+ break;
+@@ -136,15 +136,15 @@
+ case 'n':
+ fNperiods = param->value.ui;
+ break;
+-
++
+ case 'w':
+ fBits = param->value.i;
+ break;
+-
++
+ case 'i':
+ fCaptureChannels = param->value.ui;
+ break;
+-
++
+ case 'o':
+ fPlaybackChannels = param->value.ui;
+ break;
+@@ -152,21 +152,21 @@
+ case 'e':
+ fExcl = true;
+ break;
+-
++
+ case 'C':
+ fRWMode |= kRead;
+ if (strcmp(param->value.str, "none") != 0) {
+ strcpy(fCaptureDriverName, param->value.str);
+ }
+ break;
+-
++
+ case 'P':
+ fRWMode |= kWrite;
+ if (strcmp(param->value.str, "none") != 0) {
+ strcpy(fPlaybackDriverName, param->value.str);
+ }
+ break;
+-
++
+ case 'd':
+ fRWMode |= kRead;
+ fRWMode |= kWrite;
+@@ -177,11 +177,11 @@
+ case 'b':
+ fIgnoreHW = true;
+ break;
+-
++
+ case 'q':
+ fQuality = param->value.ui;
+ break;
+-
++
+ case 'g':
+ fRingbufferCurSize = param->value.ui;
+ fAdaptative = false;
+@@ -200,14 +200,14 @@
+ oss_audioinfo ai_in, ai_out;
+ memset(&info, 0, sizeof(audio_buf_info));
+ int cap = 0;
+-
++
+ // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
+-
++
+ jack_info("Audio Interface Description :");
+ jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode);
+-
++
+ if (fRWMode & kWrite) {
+-
++
+ oss_sysinfo si;
+ if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
+ jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -219,17 +219,17 @@
+ jack_info("OSS numaudioengines %d", si.numaudioengines);
+ jack_info("OSS numcards %d", si.numcards);
+ }
+-
++
+ jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
+ jack_info("Output block size = %d", fOutputBufferSize);
+-
++
+ if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
+ jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+- jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
++ jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
+ info.fragments, info.fragstotal, info.fragsize, info.bytes);
+ }
+-
++
+ if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
+ jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+@@ -242,10 +242,10 @@
+ if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
+ if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
+ }
+- }
+-
++ }
++
+ if (fRWMode & kRead) {
+-
++
+ oss_sysinfo si;
+ if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
+ jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -257,14 +257,14 @@
+ jack_info("OSS numaudioengines %d", si.numaudioengines);
+ jack_info("OSS numcards %d", si.numcards);
+ }
+-
++
+ jack_info("Input capabilities - %d channels : ", fCaptureChannels);
+ jack_info("Input block size = %d", fInputBufferSize);
+-
+- if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
++
++ if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
+ jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+- jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
++ jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
+ info.fragments, info.fragstotal, info.fragsize, info.bytes);
+ }
+
+@@ -281,15 +281,15 @@
+ if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
+ }
+ }
+-
++
+ if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) {
+ jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name);
+ }
+-
++
+ if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) {
+ jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name);
+ }
+-
++
+ if (ai_in.rate_source != ai_out.rate_source) {
+ jack_info("Warning : input and output are not necessarily driven by the same clock!");
+ }
+@@ -301,9 +301,9 @@
+ int gFragFormat;
+ int cur_sample_format, cur_capture_channels;
+ jack_nframes_t cur_sample_rate;
+-
++
+ if (fCaptureChannels == 0) fCaptureChannels = 2;
+-
++
+ if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
+ jack_error("JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+@@ -316,7 +316,7 @@
+ }
+ }
+
+- gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels);
++ gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels);
+ if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
+ jack_error("JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+@@ -330,7 +330,7 @@
+ if (cur_sample_format != fSampleFormat) {
+ jack_info("JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat);
+ }
+-
++
+ cur_capture_channels = fCaptureChannels;
+ if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
+ jack_error("JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -339,7 +339,7 @@
+ if (cur_capture_channels != fCaptureChannels) {
+ jack_info("JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
+ }
+-
++
+ cur_sample_rate = fAdaptedSampleRate;
+ if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) {
+ jack_error("JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -354,7 +354,7 @@
+ jack_error("JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+ }
+-
++
+ if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) {
+ if (fIgnoreHW) {
+ jack_info("JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize);
+@@ -366,16 +366,16 @@
+
+ fInputBuffer = (void*)calloc(fInputBufferSize, 1);
+ assert(fInputBuffer);
+-
++
+ fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*));
+ assert(fInputSampleBuffer);
+-
++
+ for (int i = 0; i < fCaptureChannels; i++) {
+ fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
+ assert(fInputSampleBuffer[i]);
+ }
+ return 0;
+-
++
+ error:
+ ::close(fInFD);
+ return -1;
+@@ -387,22 +387,22 @@
+ int gFragFormat;
+ int cur_sample_format, cur_playback_channels;
+ jack_nframes_t cur_sample_rate;
+-
++
+ if (fPlaybackChannels == 0) fPlaybackChannels = 2;
+-
++
+ if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
+ jack_error("JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+ }
+-
++
+ if (fExcl) {
+ if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
+ jack_error("JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+- }
+- }
++ }
++ }
+
+- gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels);
++ gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels);
+ if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
+ jack_error("JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+@@ -416,7 +416,7 @@
+ if (cur_sample_format != fSampleFormat) {
+ jack_info("JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat);
+ }
+-
++
+ cur_playback_channels = fPlaybackChannels;
+ if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
+ jack_error("JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -440,7 +440,7 @@
+ jack_error("JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+ }
+-
++
+ if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) {
+ if (fIgnoreHW) {
+ jack_info("JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize);
+@@ -452,18 +452,18 @@
+
+ fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
+ assert(fOutputBuffer);
+-
++
+ fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*));
+ assert(fOutputSampleBuffer);
+-
++
+ for (int i = 0; i < fPlaybackChannels; i++) {
+ fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float));
+ assert(fOutputSampleBuffer[i]);
+ }
+-
++
+ fFirstCycle = true;
+ return 0;
+-
++
+ error:
+ ::close(fOutFD);
+ return -1;
+@@ -472,46 +472,46 @@
+ int JackOSSAdapter::Open()
+ {
+ SetSampleFormat();
+-
++
+ if ((fRWMode & kRead) && (OpenInput() < 0)) {
+ return -1;
+ }
+-
+- if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
++
++ if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
+ return -1;
+ }
+-
++
+ // In duplex mode, check that input and output use the same buffer size
+ if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) {
+ jack_error("JackOSSAdapter::OpenAux input and output buffer size are not the same!!");
+ goto error;
+ }
+
+- DisplayDeviceInfo();
++ DisplayDeviceInfo();
+
+ //start adapter thread
+ if (fThread.StartSync() < 0) {
+ jack_error ( "Cannot start audioadapter thread" );
+ return -1;
+ }
+-
++
+ //turn the thread realtime
+ fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority);
+ return 0;
+-
++
+ error:
+ CloseAux();
+ return -1;
+ }
+
+-
++
+ int JackOSSAdapter::Close()
+ {
+ #ifdef JACK_MONITOR
+ fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
+ #endif
+ fThread.Stop();
+- CloseAux();
++ CloseAux();
+ return 0;
+ }
+
+@@ -521,23 +521,23 @@
+ close(fInFD);
+ fInFD = -1;
+ }
+-
++
+ if (fRWMode & kWrite) {
+ close(fOutFD);
+ fOutFD = -1;
+ }
+-
++
+ free(fInputBuffer);
+ fInputBuffer = NULL;
+-
++
+ free(fOutputBuffer);
+ fOutputBuffer = NULL;
+-
++
+ for (int i = 0; i < fCaptureChannels; i++) {
+ free(fInputSampleBuffer[i]);
+ }
+ free(fInputSampleBuffer);
+-
++
+ for (int i = 0; i < fPlaybackChannels; i++) {
+ free(fOutputSampleBuffer[i]);
+ }
+@@ -547,13 +547,13 @@
+ int JackOSSAdapter::Read()
+ {
+ ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize);
+-
++
+ if (count < fInputBufferSize) {
+ jack_error("JackOSSAdapter::Read error bytes read = %ld", count);
+ return -1;
+ } else {
+ for (int i = 0; i < fCaptureChannels; i++) {
+- CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits);
++ CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits);
+ }
+ return 0;
+ }
+@@ -562,10 +562,10 @@
+ int JackOSSAdapter::Write()
+ {
+ ssize_t count;
+-
++
+ // Maybe necessay to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
+ if (fFirstCycle) {
+-
++
+ fFirstCycle = false;
+ memset(fOutputBuffer, 0, fOutputBufferSize);
+
+@@ -577,23 +577,23 @@
+ return -1;
+ }
+ }
+-
++
+ int delay;
+ if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
+ jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+ }
+-
++
+ delay /= fSampleSize * fPlaybackChannels;
+ jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
+ }
+-
++
+ for (int i = 0; i < fPlaybackChannels; i++) {
+ CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits);
+ }
+-
++
+ count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize);
+-
++
+ if (count < fOutputBufferSize) {
+ jack_error("JackOSSAdapter::Write error bytes written = %ld", count);
+ return -1;
+@@ -607,13 +607,13 @@
+ //read data from audio interface
+ if (Read() < 0)
+ return false;
+-
++
+ PushAndPull(fInputSampleBuffer, fOutputSampleBuffer, fAdaptedBufferSize);
+-
++
+ //write data to audio interface
+ if (Write() < 0)
+ return false;
+-
++
+ return true;
+ }
+
+@@ -623,7 +623,7 @@
+ Close();
+ return Open();
+ }
+-
++
+ } // namespace
+
+ #ifdef __cplusplus
+@@ -633,123 +633,50 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = OSS_DRIVER_N_PARAMS;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_FS;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "nperiods");
+- desc->params[i].character = 'n';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS;
+- strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "wordlength");
+- desc->params[i].character = 'w';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = OSS_DRIVER_DEF_BITS;
+- strcpy(desc->params[i].short_desc, "Word length");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_INS;
+- strcpy(desc->params[i].short_desc, "Capture channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS;
+- strcpy(desc->params[i].short_desc, "Playback channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "excl");
+- desc->params[i].character = 'e';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "Input device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "Output device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy (desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "OSS device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ignorehwbuf");
+- desc->params[i].character = 'b';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = true;
+- strcpy(desc->params[i].short_desc, "Ignore hardware period size");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "quality");
+- desc->params[i].character = 'q';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ring-buffer");
+- desc->params[i].character = 'g';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 32768;
+- strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
+- strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
+-
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
++
++ value.ui = OSS_DRIVER_DEF_FS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = OSS_DRIVER_DEF_BLKSIZE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = OSS_DRIVER_DEF_NPERIODS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
++
++ value.i = OSS_DRIVER_DEF_BITS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
++
++ value.ui = OSS_DRIVER_DEF_INS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
++
++ value.ui = OSS_DRIVER_DEF_OUTS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL);
++
++ strcpy(value.str, OSS_DRIVER_DEF_DEV);
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
++
++ value.i = true;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
++
++ value.i = 32768;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
++
+ return desc;
+ }
+-
++
+ #ifdef __cplusplus
+ }
+ #endif
+--- a/solaris/oss/JackOSSAdapter.h
++++ b/solaris/oss/JackOSSAdapter.h
+@@ -34,7 +34,6 @@
+
+ typedef jack_default_audio_sample_t jack_sample_t;
+
+-#define OSS_DRIVER_N_PARAMS 13
+ #define OSS_DRIVER_DEF_DEV "/dev/dsp"
+ #define OSS_DRIVER_DEF_FS 48000
+ #define OSS_DRIVER_DEF_BLKSIZE 1024
+@@ -51,17 +50,17 @@
+ {
+
+ enum { kRead = 1, kWrite = 2, kReadWrite = 3 };
+-
++
+ private:
+-
++
+ JackThread fThread;
+-
++
+ char fCaptureDriverName[JACK_CLIENT_NAME_SIZE + 1];
+ char fPlaybackDriverName[JACK_CLIENT_NAME_SIZE + 1];
+-
++
+ int fInFD;
+ int fOutFD;
+-
++
+ int fBits;
+ int fSampleFormat;
+ int fNperiods;
+@@ -69,38 +68,38 @@
+ int fRWMode;
+ bool fIgnoreHW;
+ bool fExcl;
+-
++
+ unsigned int fInputBufferSize;
+ unsigned int fOutputBufferSize;
+-
++
+ void* fInputBuffer;
+ void* fOutputBuffer;
+-
++
+ float** fInputSampleBuffer;
+ float** fOutputSampleBuffer;
+-
++
+ bool fFirstCycle;
+-
++
+ int OpenInput();
+ int OpenOutput();
+ void CloseAux();
+ void SetSampleFormat();
+ void DisplayDeviceInfo();
+-
++
+ public:
+-
++
+ JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params);
+ ~JackOSSAdapter()
+ {}
+-
++
+ int Open();
+ int Close();
+-
++
+ int Read();
+ int Write();
+-
++
+ int SetBufferSize(jack_nframes_t buffer_size);
+-
++
+ bool Execute();
+ };
+
+@@ -114,7 +113,7 @@
+ #include "JackCompilerDeps.h"
+ #include "driver_interface.h"
+
+-EXPORT jack_driver_desc_t* jack_get_descriptor();
++SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor();
+
+ #ifdef __cplusplus
+ }
+--- a/solaris/oss/JackOSSDriver.cpp
++++ b/solaris/oss/JackOSSDriver.cpp
+@@ -107,12 +107,12 @@
+ s32dst += channel;
+ sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now...
+ break;
+- }
++ }
+ case 32: {
+ signed int *s32dst = (signed int*)dst;
+ s32dst += channel;
+ sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL);
+- break;
++ break;
+ }
+ }
+ }
+@@ -126,7 +126,7 @@
+ fSampleSize = sizeof(int);
+ break;
+ case 32: /* native-endian 32-bit integer */
+- fSampleFormat = AFMT_S32_NE;
++ fSampleFormat = AFMT_S32_NE;
+ fSampleSize = sizeof(int);
+ break;
+ case 16: /* native-endian 16-bit integer */
+@@ -143,13 +143,13 @@
+ oss_audioinfo ai_in, ai_out;
+ memset(&info, 0, sizeof(audio_buf_info));
+ int cap = 0;
+-
++
+ // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html
+ jack_info("Audio Interface Description :");
+ jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode);
+-
++
+ if (fRWMode & kWrite) {
+-
++
+ oss_sysinfo si;
+ if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) {
+ jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -161,17 +161,17 @@
+ jack_info("OSS numaudioengines %d", si.numaudioengines);
+ jack_info("OSS numcards %d", si.numcards);
+ }
+-
++
+ jack_info("Output capabilities - %d channels : ", fPlaybackChannels);
+ jack_info("Output block size = %d", fOutputBufferSize);
+-
++
+ if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) {
+ jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+- jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
++ jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
+ info.fragments, info.fragstotal, info.fragsize, info.bytes);
+ }
+-
++
+ if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) {
+ jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+@@ -184,10 +184,10 @@
+ if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI");
+ if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
+ }
+- }
+-
++ }
++
+ if (fRWMode & kRead) {
+-
++
+ oss_sysinfo si;
+ if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) {
+ jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -199,14 +199,14 @@
+ jack_info("OSS numaudioengines %d", si.numaudioengines);
+ jack_info("OSS numcards %d", si.numcards);
+ }
+-
++
+ jack_info("Input capabilities - %d channels : ", fCaptureChannels);
+ jack_info("Input block size = %d", fInputBufferSize);
+-
+- if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
++
++ if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) {
+ jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ } else {
+- jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
++ jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d",
+ info.fragments, info.fragstotal, info.fragsize, info.bytes);
+ }
+
+@@ -223,7 +223,7 @@
+ if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND");
+ }
+ }
+-
++
+ if (ai_in.rate_source != ai_out.rate_source) {
+ jack_info("Warning : input and output are not necessarily driven by the same clock!");
+ }
+@@ -238,7 +238,7 @@
+ jack_nframes_t cur_sample_rate;
+
+ if (fCaptureChannels == 0) fCaptureChannels = 2;
+-
++
+ if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
+ jack_error("JackOSSDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+@@ -253,7 +253,7 @@
+ }
+ }
+
+- gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
++ gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels);
+ if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
+ jack_error("JackOSSDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+@@ -267,7 +267,7 @@
+ if (cur_sample_format != fSampleFormat) {
+ jack_info("JackOSSDriver::OpenInput driver forced the sample format %ld", fSampleFormat);
+ }
+-
++
+ cur_capture_channels = fCaptureChannels;
+ if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) {
+ jack_error("JackOSSDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -276,7 +276,7 @@
+ if (cur_capture_channels != fCaptureChannels) {
+ jack_info("JackOSSDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels);
+ }
+-
++
+ cur_sample_rate = fEngineControl->fSampleRate;
+ if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) {
+ jack_error("JackOSSDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -291,7 +291,7 @@
+ jack_error("JackOSSDriver::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+ }
+-
++
+ if (fInputBufferSize != fEngineControl->fBufferSize * fSampleSize * fCaptureChannels) {
+ if (fIgnoreHW) {
+ int new_buffer_size = fInputBufferSize / (fSampleSize * fCaptureChannels);
+@@ -306,7 +306,7 @@
+ fInputBuffer = (void*)calloc(fInputBufferSize, 1);
+ assert(fInputBuffer);
+ return 0;
+-
++
+ error:
+ ::close(fInFD);
+ return -1;
+@@ -321,27 +321,27 @@
+ jack_nframes_t cur_sample_rate;
+
+ if (fPlaybackChannels == 0) fPlaybackChannels = 2;
+-
++
+ if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) {
+ jack_error("JackOSSDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+ }
+
+ jack_log("JackOSSDriver::OpenOutput output fOutFD = %d", fOutFD);
+-
++
+ if (fExcl) {
+ if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) {
+ jack_error("JackOSSDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+- }
+- }
++ }
++ }
+
+- gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
++ gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels);
+ if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) {
+ jack_error("JackOSSDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+ }
+-
++
+ cur_sample_format = fSampleFormat;
+ if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) {
+ jack_error("JackOSSDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -350,7 +350,7 @@
+ if (cur_sample_format != fSampleFormat) {
+ jack_info("JackOSSDriver::OpenOutput driver forced the sample format %ld", fSampleFormat);
+ }
+-
++
+ cur_playback_channels = fPlaybackChannels;
+ if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) {
+ jack_error("JackOSSDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+@@ -374,7 +374,7 @@
+ jack_error("JackOSSDriver::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ goto error;
+ }
+-
++
+ if (fOutputBufferSize != fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels) {
+ if (fIgnoreHW) {
+ int new_buffer_size = fOutputBufferSize / (fSampleSize * fPlaybackChannels);
+@@ -385,19 +385,19 @@
+ goto error;
+ }
+ }
+-
++
+ fOutputBuffer = (void*)calloc(fOutputBufferSize, 1);
+ fFirstCycle = true;
+ assert(fOutputBuffer);
+ return 0;
+-
++
+ error:
+ ::close(fOutFD);
+ return -1;
+ }
+
+ int JackOSSDriver::Open(jack_nframes_t nframes,
+- int user_nperiods,
++ int user_nperiods,
+ jack_nframes_t samplerate,
+ bool capturing,
+ bool playing,
+@@ -413,7 +413,7 @@
+ bool ignorehwbuf)
+ {
+ // Generic JackAudioDriver Open
+- if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
++ if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor,
+ capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
+ return -1;
+ } else {
+@@ -422,7 +422,7 @@
+ jack_error("Cannot run in asynchronous mode, use the -S parameter for jackd");
+ return -1;
+ }
+-
++
+ fRWMode |= ((capturing) ? kRead : 0);
+ fRWMode |= ((playing) ? kWrite : 0);
+ fBits = bits;
+@@ -434,7 +434,7 @@
+ // Force memory page in
+ memset(&gCycleTable, 0, sizeof(gCycleTable));
+ #endif
+-
++
+ if (OpenAux() < 0) {
+ Close();
+ return -1;
+@@ -448,14 +448,14 @@
+ {
+ #ifdef JACK_MONITOR
+ FILE* file = fopen("OSSProfiling.log", "w");
+-
++
+ if (file) {
+ jack_info("Writing OSS driver timing data....");
+ for (int i = 1; i < gCycleCount; i++) {
+ int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead;
+ int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead;
+ int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite;
+- int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
++ int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert;
+ fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4);
+ }
+ fclose(file);
+@@ -468,7 +468,7 @@
+ if (file == NULL) {
+ jack_error("JackOSSDriver::Close cannot open TimingOSS.plot file");
+ } else {
+-
++
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"OSS audio driver timing\"\n");
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+@@ -477,10 +477,10 @@
+ \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
+ \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
+ \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
+-
++
+ fprintf(file, "set output 'TimingOSS.pdf\n");
+ fprintf(file, "set terminal pdf\n");
+-
++
+ fprintf(file, "set grid\n");
+ fprintf(file, "set title \"OSS audio driver timing\"\n");
+ fprintf(file, "set xlabel \"audio cycles\"\n");
+@@ -489,12 +489,12 @@
+ \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \
+ \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \
+ \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n");
+-
++
+ fclose(file);
+ }
+ #endif
+ int res = JackAudioDriver::Close();
+- CloseAux();
++ CloseAux();
+ return res;
+ }
+
+@@ -506,8 +506,8 @@
+ if ((fRWMode & kRead) && (OpenInput() < 0)) {
+ return -1;
+ }
+-
+- if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
++
++ if ((fRWMode & kWrite) && (OpenOutput() < 0)) {
+ return -1;
+ }
+
+@@ -522,7 +522,7 @@
+ }
+ */
+
+- DisplayDeviceInfo();
++ DisplayDeviceInfo();
+ return 0;
+ }
+
+@@ -532,16 +532,16 @@
+ close(fInFD);
+ fInFD = -1;
+ }
+-
++
+ if (fRWMode & kWrite && fOutFD > 0) {
+ close(fOutFD);
+ fOutFD = -1;
+ }
+-
++
+ if (fInputBuffer)
+ free(fInputBuffer);
+ fInputBuffer = NULL;
+-
++
+ if (fOutputBuffer)
+ free(fOutputBuffer);
+ fOutputBuffer = NULL;
+@@ -554,7 +554,7 @@
+ JackDriver::CycleTakeBeginTime();
+ return 0;
+ }
+-
++
+ ssize_t count;
+
+ #ifdef JACK_MONITOR
+@@ -562,28 +562,28 @@
+ #endif
+
+ audio_errinfo ei_in;
+- count = ::read(fInFD, fInputBuffer, fInputBufferSize);
+-
++ count = ::read(fInFD, fInputBuffer, fInputBufferSize);
++
+ #ifdef JACK_MONITOR
+ if (count > 0 && count != (int)fInputBufferSize)
+ jack_log("JackOSSDriver::Read count = %ld", count / (fSampleSize * fCaptureChannels));
+ gCycleTable.fTable[gCycleCount].fAfterRead = GetMicroSeconds();
+ #endif
+-
++
+ // XRun detection
+ if (ioctl(fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) {
+
+ if (ei_in.rec_overruns > 0 ) {
+ jack_error("JackOSSDriver::Read overruns");
+ jack_time_t cur_time = GetMicroSeconds();
+- NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
++ NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
+ }
+
+ if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) {
+ jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm);
+ }
+- }
+-
++ }
++
+ if (count < 0) {
+ jack_log("JackOSSDriver::Read error = %s", strerror(errno));
+ return -1;
+@@ -603,7 +603,7 @@
+ #ifdef JACK_MONITOR
+ gCycleTable.fTable[gCycleCount].fAfterReadConvert = GetMicroSeconds();
+ #endif
+-
++
+ return 0;
+ }
+ }
+@@ -618,10 +618,10 @@
+
+ ssize_t count;
+ audio_errinfo ei_out;
+-
+- // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
++
++ // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html
+ if (fFirstCycle) {
+-
++
+ fFirstCycle = false;
+ memset(fOutputBuffer, 0, fOutputBufferSize);
+
+@@ -633,17 +633,17 @@
+ return -1;
+ }
+ }
+-
++
+ int delay;
+ if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) {
+ jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno);
+ return -1;
+ }
+-
++
+ delay /= fSampleSize * fPlaybackChannels;
+ jack_info("JackOSSDriver::Write output latency frames = %ld", delay);
+ }
+-
++
+ #ifdef JACK_MONITOR
+ gCycleTable.fTable[gCycleCount].fBeforeWriteConvert = GetMicroSeconds();
+ #endif
+@@ -657,7 +657,7 @@
+
+ #ifdef JACK_MONITOR
+ gCycleTable.fTable[gCycleCount].fBeforeWrite = GetMicroSeconds();
+- #endif
++ #endif
+
+ // Keep end cycle time
+ JackDriver::CycleTakeEndTime();
+@@ -676,14 +676,14 @@
+ if (ei_out.play_underruns > 0) {
+ jack_error("JackOSSDriver::Write underruns");
+ jack_time_t cur_time = GetMicroSeconds();
+- NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
++ NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing...
+ }
+
+ if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) {
+ jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm);
+ }
+ }
+-
++
+ if (count < 0) {
+ jack_log("JackOSSDriver::Write error = %s", strerror(errno));
+ return -1;
+@@ -697,15 +697,15 @@
+
+ int JackOSSDriver::SetBufferSize(jack_nframes_t buffer_size)
+ {
+- CloseAux();
+- JackAudioDriver::SetBufferSize(buffer_size); // never fails
++ CloseAux();
++ JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
+ return OpenAux();
+ }
+
+ int JackOSSDriver::ProcessSync()
+ {
+ // Read input buffers for the current cycle
+- if (Read() < 0) {
++ if (Read() < 0) {
+ jack_error("ProcessSync: read error, skip cycle");
+ return 0; // Non fatal error here, skip cycle, but continue processing...
+ }
+@@ -715,13 +715,13 @@
+ } else {
+ fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable);
+ }
+-
++
+ // Write output buffers for the current cycle
+- if (Write() < 0) {
++ if (Write() < 0) {
+ jack_error("JackAudioDriver::ProcessSync: write error, skip cycle");
+ return 0; // Non fatal error here, skip cycle, but continue processing...
+ }
+-
++
+ return 0;
+ }
+
+@@ -734,119 +734,44 @@
+
+ SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "oss"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "OSS API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = OSS_DRIVER_N_PARAMS;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_FS;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "nperiods");
+- desc->params[i].character = 'n';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS;
+- strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "wordlength");
+- desc->params[i].character = 'w';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.i = OSS_DRIVER_DEF_BITS;
+- strcpy(desc->params[i].short_desc, "Word length");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_INS;
+- strcpy(desc->params[i].short_desc, "Capture channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS;
+- strcpy(desc->params[i].short_desc, "Playback channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "excl");
+- desc->params[i].character = 'e';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "Input device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "Output device");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy (desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV);
+- strcpy(desc->params[i].short_desc, "OSS device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ignorehwbuf");
+- desc->params[i].character = 'b';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = false;
+- strcpy(desc->params[i].short_desc, "Ignore hardware period size");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "input-latency");
+- desc->params[i].character = 'I';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra input latency");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "output-latency");
+- desc->params[i].character = 'O';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra output latency");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("oss", JackDriverMaster, "OSS API based audio backend", &filler);
++
++ value.ui = OSS_DRIVER_DEF_FS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = OSS_DRIVER_DEF_BLKSIZE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ value.ui = OSS_DRIVER_DEF_NPERIODS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "nperiods", 'n', JackDriverParamUInt, &value, NULL, "Number of periods to prefill output buffer", NULL);
++
++ value.i = OSS_DRIVER_DEF_BITS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "wordlength", 'w', JackDriverParamInt, &value, NULL, "Word length", NULL);
++
++ value.ui = OSS_DRIVER_DEF_INS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Capture channels", NULL);
++
++ value.ui = OSS_DRIVER_DEF_OUTS;
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Playback channels", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "excl", 'e', JackDriverParamBool, &value, NULL, "Exclusif (O_EXCL) access mode", NULL);
++
++ strcpy(value.str, OSS_DRIVER_DEF_DEV);
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output device", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "OSS device name", NULL);
++
++ value.i = false;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ignorehwbuf", 'b', JackDriverParamBool, &value, NULL, "Ignore hardware period size", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency", NULL);
+
+ return desc;
+ }
+@@ -870,13 +795,13 @@
+ bool ignorehwbuf = false;
+ jack_nframes_t systemic_input_latency = 0;
+ jack_nframes_t systemic_output_latency = 0;
+-
++
+ for (node = params; node; node = jack_slist_next(node)) {
+-
++
+ param = (const jack_driver_param_t *)node->data;
+
+ switch (param->character) {
+-
++
+ case 'r':
+ srate = param->value.ui;
+ break;
+@@ -900,7 +825,7 @@
+ case 'o':
+ chan_out = (int)param->value.ui;
+ break;
+-
++
+ case 'C':
+ capture = true;
+ if (strcmp(param->value.str, "none") != 0) {
+@@ -919,7 +844,7 @@
+ playback_pcm_name = param->value.str;
+ capture_pcm_name = param->value.str;
+ break;
+-
++
+ case 'b':
+ ignorehwbuf = true;
+ break;
+@@ -927,7 +852,7 @@
+ case 'e':
+ excl = true;
+ break;
+-
++
+ case 'I':
+ systemic_input_latency = param->value.ui;
+ break;
+@@ -946,9 +871,9 @@
+
+ Jack::JackOSSDriver* oss_driver = new Jack::JackOSSDriver("system", "oss", engine, table);
+ Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(oss_driver);
+-
++
+ // Special open for OSS driver...
+- if (oss_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out,
++ if (oss_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out,
+ excl, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, ignorehwbuf) == 0) {
+ return threaded_driver;
+ } else {
+--- a/solaris/oss/JackOSSDriver.h
++++ b/solaris/oss/JackOSSDriver.h
+@@ -28,7 +28,6 @@
+
+ typedef jack_default_audio_sample_t jack_sample_t;
+
+-#define OSS_DRIVER_N_PARAMS 13
+ #define OSS_DRIVER_DEF_DEV "/dev/dsp"
+ #define OSS_DRIVER_DEF_FS 48000
+ #define OSS_DRIVER_DEF_BLKSIZE 1024
+--- a/tests/cpu.c
++++ b/tests/cpu.c
+@@ -1,7 +1,7 @@
+ /*
+ Copyright (C) 2005 Samuel TRACOL
+- Copyright (C) 2008 Grame
+-
++ Copyright (C) 2008 Grame
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+@@ -21,7 +21,7 @@
+ /** @file jack_cpu.c
+ *
+ * @brief This client test the capacity for jackd to kick out a to heavy cpu client.
+- *
++ *
+ */
+
+ #include <stdio.h>
+@@ -80,23 +80,23 @@
+ {
+ jack_default_audio_sample_t *in, *out;
+ jack_nframes_t start_frame = jack_frame_time(client);
+-
++
+ in = (jack_default_audio_sample_t *) jack_port_get_buffer (input_port, nframes);
+ out = (jack_default_audio_sample_t *) jack_port_get_buffer (output_port, nframes);
+- memset(out, 0, sizeof (jack_default_audio_sample_t) * nframes);
+-
++ memset(out, 0, sizeof (jack_default_audio_sample_t) * nframes);
++
+ while ((client_state == Run) && (jack_frame_time(client) < (start_frame + idle_time))) {}
+- return 0;
++ return 0;
+ }
+
+ /**
+ * JACK calls this shutdown_callback if the server ever shuts down or
+ * decides to disconnect the client.
+ */
+-
++
+ void jack_shutdown(void *arg)
+ {
+- printf("Jack_cpu has been kicked out by jackd !\n");
++ fprintf(stderr, "JACK shut down, exiting ...\n");
+ exit (1);
+ }
+
+@@ -118,7 +118,7 @@
+ {"cpu", 1, 0, 'c'},
+ {0, 0, 0, 0}
+ };
+-
++
+ client_name = "jack-cpu";
+ while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) {
+ switch (opt) {
+@@ -136,35 +136,35 @@
+ got_time = 1;
+ break;
+ default:
+- fprintf(stderr, "unknown option %c\n", opt);
++ fprintf(stderr, "unknown option %c\n", opt);
+ usage();
+ }
+ }
+-
++
+ if (!got_time) {
+ fprintf(stderr, "CPU load not specified ! See usage as following :\n");
+ usage();
+ return -1;
+ }
+-
++
+ if (time_to_run != 0)
+ printf("Running jack-cpu for %d seconds...\n", time_to_run);
+-
++
+ /* open a client connection to the JACK server */
+
+ client = jack_client_open (client_name, JackNoStartServer, &status);
+-
++
+ if (client == NULL) {
+ fprintf(stderr, "jack_client_open() failed : is jack server running ?\n");
+ exit(1);
+ }
+-
++
+ cur_buffer_size = jack_get_buffer_size(client);
+ printf("engine buffer size = %d \n", cur_buffer_size);
+ printf("engine sample rate: %d Hz\n", jack_get_sample_rate(client));
+ idle_time = (jack_nframes_t) (cur_buffer_size * percent_cpu / 100);
+ printf("CPU load applies as %d sample delay.\n", idle_time);
+-
++
+ /* tell the JACK server to call `process()' whenever
+ there is work to be done.
+ */
+@@ -188,15 +188,15 @@
+ fprintf(stderr, "no more JACK ports available\n");
+ exit(1);
+ }
+-
++
+ if (jack_set_buffer_size_callback(client, update_buffer_size, 0) != 0) {
+ printf("Error when calling buffer_size_callback !");
+ return -1;
+ }
+-
++
+ /* Tell the JACK server that we are ready to roll. Our
+ * process() callback will start running now. */
+-
++
+ printf("Activating as jackd client...\n");
+ if (jack_activate(client)) {
+ fprintf(stderr, "cannot activate client");
+@@ -220,8 +220,8 @@
+ if (jack_connect(client, ports[0], jack_port_name(input_port))) {
+ fprintf (stderr, "cannot connect input ports\n");
+ }
+- free(ports);
+-
++ jack_free(ports);
++
+ ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
+ if (ports == NULL) {
+ fprintf(stderr, "no physical playback ports\n");
+@@ -231,16 +231,16 @@
+ if (jack_connect(client, jack_port_name (output_port), ports[0])) {
+ fprintf(stderr, "cannot connect output ports\n");
+ }
+- free(ports);
+-
++ jack_free(ports);
++
+ if (time_before_run == 0) {
+ client_state = Run;
+ printf("Activating cpu load...\n");
+ }
+-
+- if (time_to_run !=0)
++
++ if (time_to_run !=0)
+ time_before_exit = time_to_run + time_before_run;
+-
++
+ while (client_state != Exit) {
+ if ((time_before_run > 0) && (client_state == Init))
+ time_before_run--;
+@@ -252,7 +252,7 @@
+ if (time_to_run != 0)
+ time_before_exit--;
+ if (time_before_exit < 1)
+- client_state = Exit;
++ client_state = Exit;
+ }
+ jack_client_close(client);
+ printf("Exiting after a %d seconds run.\n", time_to_run);
+--- a/tests/iodelay.cpp
++++ b/tests/iodelay.cpp
+@@ -49,7 +49,6 @@
+ double del (void) { return _del; }
+ double err (void) { return _err; }
+
+-private:
+
+ double _del;
+ double _err;
+@@ -77,9 +76,9 @@
+
+ for (i = 0, F = _freq; i < 5; i++, F++)
+ {
+- F->p = 128;
+- F->xa = F->ya = 0.0f;
+- F->xf = F->yf = 0.0f;
++ F->p = 128;
++ F->xa = F->ya = 0.0f;
++ F->xf = F->yf = 0.0f;
+ }
+ }
+
+@@ -92,28 +91,28 @@
+ while (len--)
+ {
+ vop = 0.0f;
+- vip = *ip++;
+- for (i = 0, F = _freq; i < 5; i++, F++)
+- {
+- a = 2 * (float) M_PI * (F->p & 65535) / 65536.0;
+- F->p += F->f;
+- c = cosf (a);
+- s = -sinf (a);
+- vop += F->a * s;
+- F->xa += s * vip;
+- F->ya += c * vip;
+- }
+- *op++ = vop;
+- if (++_cnt == 16)
+- {
+- for (i = 0, F = _freq; i < 5; i++, F++)
+- {
+- F->xf += 1e-3f * (F->xa - F->xf + 1e-20);
+- F->yf += 1e-3f * (F->ya - F->yf + 1e-20);
+- F->xa = F->ya = 0.0f;
+- }
++ vip = *ip++;
++ for (i = 0, F = _freq; i < 5; i++, F++)
++ {
++ a = 2 * (float) M_PI * (F->p & 65535) / 65536.0;
++ F->p += F->f;
++ c = cosf (a);
++ s = -sinf (a);
++ vop += F->a * s;
++ F->xa += s * vip;
++ F->ya += c * vip;
++ }
++ *op++ = vop;
++ if (++_cnt == 16)
++ {
++ for (i = 0, F = _freq; i < 5; i++, F++)
++ {
++ F->xf += 1e-3f * (F->xa - F->xf + 1e-20);
++ F->yf += 1e-3f * (F->ya - F->yf + 1e-20);
++ F->xa = F->ya = 0.0f;
++ }
+ _cnt = 0;
+- }
++ }
+ }
+
+ return 0;
+@@ -134,17 +133,17 @@
+ _err = 0.0;
+ for (i = 0; i < 4; i++)
+ {
+- F++;
+- p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0;
++ F++;
++ p = atan2 (F->yf, F->xf) / (2 * M_PI) - d * F->f / f0;
+ if (_inv) p += 0.5f;
+- p -= floor (p);
+- p *= 8;
+- k = (int)(floor (p + 0.5));
+- e = fabs (p - k);
++ p -= floor (p);
++ p *= 8;
++ k = (int)(floor (p + 0.5));
++ e = fabs (p - k);
+ if (e > _err) _err = e;
+ if (e > 0.4) return 1;
+- d += m * (k & 7);
+- m *= 8;
++ d += m * (k & 7);
++ m *= 8;
+ }
+ _del = 16 * d;
+
+@@ -232,17 +231,22 @@
+ #else
+ usleep (250000);
+ #endif
+- if (mtdm.resolve () < 0) printf ("Signal below threshold...\n");
++ if (mtdm.resolve() < 0) printf ("Signal below threshold...\n");
+ else
+ {
++ jack_nframes_t systemic_latency;
+ if (mtdm.err () > 0.3)
+ {
+ mtdm.invert ();
+ mtdm.resolve ();
+ }
+- printf ("%10.3lf frames %10.3lf ms", mtdm.del (), mtdm.del () * t);
+- if (mtdm.err () > 0.2) printf (" ??");
+- if (mtdm.inv ()) printf (" Inv");
++ systemic_latency = (jack_nframes_t) floor (mtdm._del - (capture_latency.max + playback_latency.max));
++
++ printf("%10.3lf frames %10.3lf ms total roundtrip latency\n\textra loopback latency: %u frames\n\tuse %u for the backend arguments -I and -O"
++ , mtdm._del, mtdm._del * t,
++ systemic_latency, systemic_latency/2);
++ if (mtdm._err > 0.2) printf (" ??");
++ if (mtdm._inv) printf (" Inv");
+ printf ("\n");
+ }
+ }
+--- a/tests/test.cpp
++++ b/tests/test.cpp
+@@ -647,7 +647,7 @@
+ &status, "inprocess", "");
+
+ if (intclient == 0 || status & JackFailure) {
+- printf("!!! ERROR !!! cannot load internal client \"inprocess\" intclient %d status 0x%2.0x !\n", intclient, status);
++ printf("!!! ERROR !!! cannot load internal client \"inprocess\" intclient 0x%llX status 0x%2.0x !\n", (unsigned long long)intclient, status);
+ } else {
+
+ Log("\"inprocess\" server internal client loaded\n");
+@@ -663,7 +663,7 @@
+ if (intclient1 == intclient) {
+ Log("jack_internal_client_handle returns correct handle\n");
+ } else {
+- printf("!!! ERROR !!! jack_internal_client_handle returns incorrect handle %d\n", intclient1);
++ printf("!!! ERROR !!! jack_internal_client_handle returns incorrect handle 0x%llX\n", (unsigned long long)intclient1);
+ }
+
+ // Unload internal client
+@@ -745,7 +745,9 @@
+ }
+
+ jack_on_shutdown(client1, jack_shutdown, 0);
+- jack_on_info_shutdown(client1, jack_info_shutdown, 0);
++
++ if (jack_on_info_shutdown)
++ jack_on_info_shutdown(client1, jack_info_shutdown, 0);
+
+ if (jack_set_buffer_size_callback(client1, Jack_Update_Buffer_Size, 0) != 0) {
+ printf("Error when calling buffer_size_callback !\n");
+@@ -972,14 +974,14 @@
+
+ float factor = 0.5f;
+ old_buffer_size = jack_get_buffer_size(client1);
+- Log("Testing BufferSize change & Callback...\n--> Current buffer size : %i.\n", old_buffer_size);
++ Log("Testing BufferSize change & Callback...\n--> Current buffer size : %d.\n", old_buffer_size);
+ linebuf = linecount;
+ if (jack_set_buffer_size(client1, (jack_nframes_t)(old_buffer_size * factor)) < 0) {
+ printf("!!! ERROR !!! jack_set_buffer_size fails !\n");
+ }
+ jack_sleep(1 * 1000);
+ cur_buffer_size = jack_get_buffer_size(client1);
+- if ((old_buffer_size * factor) != cur_buffer_size) {
++ if (abs((old_buffer_size * factor) - cur_buffer_size) > 5) { // Tolerance needed for dummy driver...
+ printf("!!! ERROR !!! Buffer size has not been changed !\n");
+ printf("!!! Maybe jack was compiled without the '--enable-resize' flag...\n");
+ } else {
+--- a/tests/wscript
++++ b/tests/wscript
+@@ -27,8 +27,8 @@
+ if bld.env['IS_LINUX']:
+ prog.uselib = 'RT'
+ if bld.env['IS_MACOSX']:
+- prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc")
+- #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc")
++ prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc -arch x86_64")
++ #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64")
+ prog.env.append_value("LINKFLAGS", "")
+ prog.uselib_local = 'clientlib'
+ prog.target = test_program
+--- a/windows/jack_audioadapter.cbp
++++ b/windows/jack_audioadapter.cbp
+@@ -1,112 +1,209 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+-<CodeBlocks_project_file>
+- <FileVersion major="1" minor="6" />
+- <Project>
+- <Option title="jack_audioadapter" />
+- <Option pch_mode="2" />
+- <Option compiler="gcc" />
+- <Build>
+- <Target title="Win32 Release">
+- <Option output="Release\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Release\" />
+- <Option type="3" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-O2" />
+- <Add option="-Wall" />
+- <Add option="-DBUILD_DLL" />
+- <Add option="-D__SMP__" />
+- <Add option="-DSERVER_SIDE" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- <Add directory="portaudio" />
+- </Compiler>
+- <Linker>
+- <Add directory="Release\bin" />
+- </Linker>
+- </Target>
+- <Target title="Win32 Debug">
+- <Option output="Debug\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Debug\" />
+- <Option type="3" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-Wall" />
+- <Add option="-g" />
+- <Add option="-DBUILD_DLL" />
+- <Add option="-D__SMP__" />
+- <Add option="-DSERVER_SIDE" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- <Add directory="portaudio" />
+- </Compiler>
+- <Linker>
+- <Add directory="Debug\bin" />
+- </Linker>
+- </Target>
+- <Target title="Win32 Profiling">
+- <Option output="Release\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Release\" />
+- <Option type="3" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-O2" />
+- <Add option="-Wall" />
+- <Add option="-DBUILD_DLL" />
+- <Add option="-D__SMP__" />
+- <Add option="-DJACK_MONITOR" />
+- <Add option="-DSERVER_SIDE" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- <Add directory="portaudio" />
+- </Compiler>
+- <Linker>
+- <Add directory="Release\bin" />
+- </Linker>
+- </Target>
+- </Build>
+- <Compiler>
+- <Add option="-Wall" />
+- </Compiler>
+- <Linker>
+- <Add library="kernel32" />
+- <Add library="user32" />
+- <Add library="gdi32" />
+- <Add library="winspool" />
+- <Add library="comdlg32" />
+- <Add library="advapi32" />
+- <Add library="shell32" />
+- <Add library="ole32" />
+- <Add library="oleaut32" />
+- <Add library="uuid" />
+- <Add library="odbc32" />
+- <Add library="odbccp32" />
+- <Add library="libsamplerate-0" />
+- <Add library="libjackserver" />
+- <Add library="portaudio_x86" />
+- </Linker>
+- <Unit filename="..\common\JackAudioAdapter.cpp" />
+- <Unit filename="..\common\JackAudioAdapterFactory.cpp" />
+- <Unit filename="..\common\JackAudioAdapterInterface.cpp" />
+- <Unit filename="..\common\JackLibSampleRateResampler.cpp" />
+- <Unit filename="..\common\JackResampler.cpp" />
+- <Unit filename="jackaudioadapter.rc">
+- <Option compilerVar="WINDRES" />
+- </Unit>
+- <Unit filename="portaudio\JackPortAudioAdapter.cpp" />
+- <Unit filename="portaudio\JackPortAudioDevices.cpp" />
+- <Extensions>
+- <AutoVersioning>
+- <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
+- <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
+- <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
+- </AutoVersioning>
+- <code_completion />
+- <envvars />
+- <debugger />
+- </Extensions>
+- </Project>
+-</CodeBlocks_project_file>
++<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
++<CodeBlocks_project_file>
++ <FileVersion major="1" minor="6" />
++ <Project>
++ <Option title="jack_audioadapter" />
++ <Option pch_mode="2" />
++ <Option compiler="mingw_64" />
++ <Build>
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-D__SMP__" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add library="libsamplerate_x86_64" />
++ <Add library="libjackserver64" />
++ <Add library="portaudio_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-D__SMP__" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add library="libsamplerate_x86_64" />
++ <Add library="libjackserver64" />
++ <Add library="portaudio_x86_64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add library="libsamplerate_x86_64" />
++ <Add library="libjackserver64" />
++ <Add library="portaudio_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
++ <Option output="Release\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-D__SMP__" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libsamplerate_x86" />
++ <Add library="libjackserver" />
++ <Add library="portaudio_x86" />
++ <Add directory="Release\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackaudioadapter.res jackaudioadapter.rc" />
++ </ExtraCommands>
++ </Target>
++ <Target title="Win32 Debug 32bits">
++ <Option output="Debug\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-m32" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-D__SMP__" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libsamplerate_x86" />
++ <Add library="libjackserver" />
++ <Add library="portaudio_x86" />
++ <Add directory="Debug\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackaudioadapter.res jackaudioadapter.rc" />
++ </ExtraCommands>
++ </Target>
++ <Target title="Win32 Profiling 32bits">
++ <Option output="Release\bin\jack\audioadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libsamplerate_x86" />
++ <Add library="libjackserver" />
++ <Add library="portaudio_x86" />
++ <Add directory="Release\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackaudioadapter.res jackaudioadapter.rc" />
++ </ExtraCommands>
++ </Target>
++ </Build>
++ <Compiler>
++ <Add option="-Wall" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ </Linker>
++ <Unit filename="..\common\JackAudioAdapter.cpp" />
++ <Unit filename="..\common\JackAudioAdapterFactory.cpp" />
++ <Unit filename="..\common\JackAudioAdapterInterface.cpp" />
++ <Unit filename="..\common\JackLibSampleRateResampler.cpp" />
++ <Unit filename="..\common\JackResampler.cpp" />
++ <Unit filename="jackaudioadapter.rc">
++ <Option compilerVar="WINDRES" />
++ </Unit>
++ <Unit filename="portaudio\JackPortAudioAdapter.cpp" />
++ <Unit filename="portaudio\JackPortAudioDevices.cpp" />
++ <Extensions>
++ <AutoVersioning>
++ <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
++ <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
++ <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
++ </AutoVersioning>
++ <code_completion />
++ <envvars />
++ <debugger />
++ </Extensions>
++ </Project>
++</CodeBlocks_project_file>
+--- a/windows/JackCompilerDeps_os.h
++++ b/windows/JackCompilerDeps_os.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -22,6 +22,8 @@
+ #define __JackCompilerDeps_WIN32__
+
+ #if __GNUC__
++ #define PRE_PACKED_STRUCTURE
++
+ #ifndef POST_PACKED_STRUCTURE
+ /* POST_PACKED_STRUCTURE needs to be a macro which
+ expands into a compiler directive. The directive must
+@@ -39,20 +41,44 @@
+ #endif
+ #endif
+ #define MEM_ALIGN(x,y) x __attribute__((aligned(y)))
+- #define EXPORT __declspec(dllexport)
++ #define LIB_EXPORT __declspec(dllexport)
+ #ifdef SERVER_SIDE
+ #define SERVER_EXPORT __declspec(dllexport)
+ #else
+ #define SERVER_EXPORT
+ #endif
+ #else
+- #define MEM_ALIGN(x,y) x
+- #define EXPORT __declspec(dllexport)
++ #define MEM_ALIGN(x,y) x
++ #define LIB_EXPORT __declspec(dllexport)
+ #ifdef SERVER_SIDE
+ #define SERVER_EXPORT __declspec(dllexport)
+ #else
+ #define SERVER_EXPORT
+ #endif
++
++ #ifdef _MSC_VER
++ #if defined(JACK_32_64)
++ #define PRE_PACKED_STRUCTURE1 __pragma(pack(push,1))
++ #define PRE_PACKED_STRUCTURE PRE_PACKED_STRUCTURE1
++ /* PRE_PACKED_STRUCTURE needs to be a macro which
++ expands into a compiler directive. The directive must
++ tell the compiler to arrange the following structure
++ declaration so that it is packed on byte-boundaries rather
++ than use the natural alignment of the processor and/or
++ compiler.
++ */
++ #define POST_PACKED_STRUCTURE ;__pragma(pack(pop))
++ /* and POST_PACKED_STRUCTURE needs to be a macro which
++ restores the packing to its previous setting */
++ #else
++ #define PRE_PACKED_STRUCTURE
++ #define POST_PACKED_STRUCTURE
++ #endif
++ #else
++ /* Other Windows compilers to go here */
++ #define PRE_PACKED_STRUCTURE
++ #define POST_PACKED_STRUCTURE
++ #endif
+ #endif
+
+ #endif
+--- a/windows/jack_connect.cbp
++++ b/windows/jack_connect.cbp
+@@ -4,50 +4,112 @@
+ <Project>
+ <Option title="jack_connect" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_connect" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_connect" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release\bin64" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_connect" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_connect" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_connect" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_connect" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+@@ -55,7 +117,9 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -75,7 +139,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\connect.c">
+ <Option compilerVar="CC" />
+--- a/windows/jackd.cbp
++++ b/windows/jackd.cbp
+@@ -4,21 +4,96 @@
+ <Project>
+ <Option title="jackd" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jackd" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Option parameters="-R -S -d net" />
++ <Option host_application="jackdmp.exe" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-Wl,-subsystem,windows" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jackd" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Option parameters="-R -S -d net" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jackd" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Option parameters="-R -S -d net" />
++ <Option host_application="jackdmp.exe" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jackd" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option parameters="-R -S -d net" />
+ <Option host_application="jackdmp.exe" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-Wl,-subsystem,windows" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+- <Add option="-D_CONSOLE" />
++ <Add option="-D_WINDOWS" />
+ <Add option="-D_MBCS" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+@@ -26,18 +101,24 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackd.res jackd.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jackd" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option parameters="-R -S -d net" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-D_DEBUG" />
+ <Add option="-D_CONSOLE" />
+@@ -48,22 +129,28 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Debug\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackd.res jackd.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jackd" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option parameters="-R -S -d net" />
+ <Option host_application="jackdmp.exe" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+- <Add option="-D_CONSOLE" />
++ <Add option="-D_WINDOWS" />
+ <Add option="-D_MBCS" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="." />
+@@ -72,8 +159,13 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackd.res jackd.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -92,7 +184,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+ </Linker>
+ <Unit filename="..\common\Jackdmp.cpp" />
+ <Unit filename="getopt.c">
+--- a/windows/jack_disconnect.cbp
++++ b/windows/jack_disconnect.cbp
+@@ -4,50 +4,112 @@
+ <Project>
+ <Option title="jack_disconnect" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_disconnect" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_disconnect" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_disconnect" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_disconnect" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_disconnect" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Debug\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_disconnect" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+@@ -55,7 +117,9 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -79,7 +143,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\connect.c">
+ <Option compilerVar="CC" />
+--- a/windows/jack_dummy.cbp
++++ b/windows/jack_dummy.cbp
+@@ -1,98 +1,179 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+-<CodeBlocks_project_file>
+- <FileVersion major="1" minor="6" />
+- <Project>
+- <Option title="jack_dummy" />
+- <Option pch_mode="2" />
+- <Option compiler="gcc" />
+- <Build>
+- <Target title="Win32 Release">
+- <Option output="Release\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Release\" />
+- <Option type="3" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-O2" />
+- <Add option="-Wall" />
+- <Add option="-DBUILD_DLL" />
+- <Add option="-DSERVER_SIDE" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add directory="Release\bin" />
+- </Linker>
+- </Target>
+- <Target title="Win32 Debug">
+- <Option output="Debug\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Debug\" />
+- <Option type="3" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-Wall" />
+- <Add option="-g" />
+- <Add option="-DBUILD_DLL" />
+- <Add option="-DSERVER_SIDE" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add directory="Debug\bin" />
+- </Linker>
+- </Target>
+- <Target title="Win32 Profiling">
+- <Option output="Release\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Release\" />
+- <Option type="3" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-O2" />
+- <Add option="-Wall" />
+- <Add option="-DBUILD_DLL" />
+- <Add option="-DJACK_MONITOR" />
+- <Add option="-DSERVER_SIDE" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add directory="Release\bin" />
+- </Linker>
+- </Target>
+- </Build>
+- <Compiler>
+- <Add option="-Wall" />
+- </Compiler>
+- <Linker>
+- <Add library="kernel32" />
+- <Add library="user32" />
+- <Add library="gdi32" />
+- <Add library="winspool" />
+- <Add library="comdlg32" />
+- <Add library="advapi32" />
+- <Add library="shell32" />
+- <Add library="ole32" />
+- <Add library="oleaut32" />
+- <Add library="uuid" />
+- <Add library="odbc32" />
+- <Add library="odbccp32" />
+- <Add library="libjackserver" />
+- </Linker>
+- <Unit filename="jackdummydriver.rc">
+- <Option compilerVar="WINDRES" />
+- </Unit>
+- <Unit filename="..\common\JackDummyDriver.cpp" />
+- <Extensions>
+- <AutoVersioning>
+- <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
+- <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
+- <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
+- </AutoVersioning>
+- <code_completion />
+- <envvars />
+- <debugger />
+- </Extensions>
+- </Project>
+-</CodeBlocks_project_file>
++<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
++<CodeBlocks_project_file>
++ <FileVersion major="1" minor="6" />
++ <Project>
++ <Option title="jack_dummy" />
++ <Option pch_mode="2" />
++ <Option compiler="mingw_64" />
++ <Build>
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
++ <Option output="Release\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add directory="Release\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackdummydriver.res jackdummydriver.rc" />
++ </ExtraCommands>
++ </Target>
++ <Target title="Win32 Debug 32bits">
++ <Option output="Debug\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-m32" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add directory="Debug\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackdummydriver.res jackdummydriver.rc" />
++ </ExtraCommands>
++ </Target>
++ <Target title="Win32 Profiling 32bits">
++ <Option output="Release\bin\jack\jack_dummy" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add directory="Release\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackdummydriver.res jackdummydriver.rc" />
++ </ExtraCommands>
++ </Target>
++ </Build>
++ <Compiler>
++ <Add option="-Wall" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ </Linker>
++ <Unit filename="..\common\JackDummyDriver.cpp" />
++ <Unit filename="jackdummydriver.rc">
++ <Option compilerVar="WINDRES" />
++ </Unit>
++ <Extensions>
++ <AutoVersioning>
++ <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
++ <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
++ <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
++ </AutoVersioning>
++ <code_completion />
++ <envvars />
++ <debugger />
++ </Extensions>
++ </Project>
++</CodeBlocks_project_file>
+--- a/windows/jackd.workspace
++++ b/windows/jackd.workspace
+@@ -2,61 +2,29 @@
+ <CodeBlocks_workspace_file>
+ <Workspace title="jack">
+ <Project filename="libjackserver.cbp" />
+- <Project filename="jackd.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_portaudio.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_netdriver.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_netonedriver.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_dummy.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_netmanager.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_audioadapter.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
+- <Project filename="jack_netadapter.cbp">
+- <Depends filename="libjackserver.cbp" />
+- </Project>
++ <Project filename="jack_portaudio.cbp" />
++ <Project filename="jack_netdriver.cbp" active="1" />
++ <Project filename="jack_netonedriver.cbp" />
++ <Project filename="jack_dummy.cbp" />
++ <Project filename="jack_netmanager.cbp" />
++ <Project filename="jack_audioadapter.cbp" />
+ <Project filename="libjack.cbp" />
+- <Project filename="jack_load.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
+- <Project filename="jack_unload.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
+- <Project filename="jack_lsp.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
+- <Project filename="jack_latent_client.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
+- <Project filename="jack_netsource.cbp">
+- <Depends filename="libjack.cbp" />
+- <Depends filename="jack_netonedriver.cbp" />
+- </Project>
+- <Project filename="jack_metro.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
+- <Project filename="jack_connect.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
+- <Project filename="jack_disconnect.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
++ <Project filename="jack_load.cbp" />
++ <Project filename="jack_unload.cbp" />
++ <Project filename="jack_lsp.cbp" />
++ <Project filename="jack_latent_client.cbp" />
++ <Project filename="jack_metro.cbp" />
++ <Project filename="jack_connect.cbp" />
++ <Project filename="jack_disconnect.cbp" />
+ <Project filename="jack_test.cbp" />
+- <Project filename="multiple_metro.cbp">
+- <Depends filename="libjack.cbp" />
+- </Project>
++ <Project filename="multiple_metro.cbp" />
+ <Project filename="jack_winmme.cbp" />
+- <Project filename="jack_loopback.cbp" active="1" />
++ <Project filename="jack_loopback.cbp" />
++ <Project filename="jackd.cbp" />
++ <Project filename="jack_midi_latency_test.cbp" />
++ <Project filename="jack_netadapter.cbp" />
++ <Project filename="jack_netsource.cbp" />
++ <Project filename="libjacknet.cbp" />
++ <Project filename="jack_midi_dump.cbp" />
+ </Workspace>
+ </CodeBlocks_workspace_file>
+--- a/windows/jack_latent_client.cbp
++++ b/windows/jack_latent_client.cbp
+@@ -4,56 +4,118 @@
+ <Project>
+ <Option title="jack_latent_client" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_latent_client" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_latent_client" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug\bin64" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_latent_client" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_latent_client" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_latent_client" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Debug\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_latent_client" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -72,7 +134,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\latent_client.c">
+ <Option compilerVar="CC" />
+--- a/windows/jack_load.cbp
++++ b/windows/jack_load.cbp
+@@ -4,49 +4,110 @@
+ <Project>
+ <Option title="jack_load" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_load" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_load" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_load" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_load" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_load" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Debug\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_load" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+@@ -54,7 +115,9 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -74,7 +137,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\ipload.c">
+ <Option compilerVar="CC" />
+--- a/windows/jack_loopback.cbp
++++ b/windows/jack_loopback.cbp
+@@ -4,62 +4,144 @@
+ <Project>
+ <Option title="jack_loopback" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\jack_loopback" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\jack_loopback" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\jack_loopback" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\jack_loopback" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackloopbackdriver.res jackloopbackdriver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\jack_loopback" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Debug\bin" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackloopbackdriver.res jackloopbackdriver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\jack_loopback" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackloopbackdriver.res jackloopbackdriver.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -78,7 +160,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+ </Linker>
+ <Unit filename="jackloopbackdriver.rc">
+ <Option compilerVar="WINDRES" />
+--- a/windows/jack_lsp.cbp
++++ b/windows/jack_lsp.cbp
+@@ -4,55 +4,117 @@
+ <Project>
+ <Option title="jack_lsp" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_lsp" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_lsp" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_lsp" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_lsp" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
+ <Add directory="Release\bin" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_lsp" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
+ <Add directory="Debug\bin" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_lsp" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
+ <Add directory="Release\bin" />
+ </Linker>
+ </Target>
+@@ -72,7 +134,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\lsp.c">
+ <Option compilerVar="CC" />
+--- a/windows/jack_metro.cbp
++++ b/windows/jack_metro.cbp
+@@ -4,16 +4,72 @@
+ <Project>
+ <Option title="jack_metro" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_metro" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_metro" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_metro" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_metro" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -21,16 +77,19 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_metro" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -38,16 +97,19 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Debug\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_metro" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+@@ -56,6 +118,8 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -75,7 +139,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\metro.c">
+ <Option compilerVar="CC" />
+--- /dev/null
++++ b/windows/jack_midi_dump.cbp
+@@ -0,0 +1,152 @@
++<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
++<CodeBlocks_project_file>
++ <FileVersion major="1" minor="6" />
++ <Project>
++ <Option title="jack_midi_dump" />
++ <Option pch_mode="2" />
++ <Option compiler="mingw_64" />
++ <Build>
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_midi_dump" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_midi_dump" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_midi_dump" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
++ <Option output="Release\bin\jack_midi_dump" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add directory="Release\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 32bits">
++ <Option output="Debug\bin\jack_midi_dump" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add directory="Debug\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 32bits">
++ <Option output="Release\bin\jack_midi_dump" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add directory="Release\bin" />
++ </Linker>
++ </Target>
++ </Build>
++ <Compiler>
++ <Add option="-Wall" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ </Linker>
++ <Unit filename="..\example-clients\midi_dump.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Extensions>
++ <code_completion />
++ <envvars />
++ <debugger />
++ <AutoVersioning>
++ <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
++ <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
++ <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
++ </AutoVersioning>
++ </Extensions>
++ </Project>
++</CodeBlocks_project_file>
+--- /dev/null
++++ b/windows/jack_midi_latency_test.cbp
+@@ -0,0 +1,152 @@
++<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
++<CodeBlocks_project_file>
++ <FileVersion major="1" minor="6" />
++ <Project>
++ <Option title="jack_midi_latency_test" />
++ <Option pch_mode="2" />
++ <Option compiler="mingw_64" />
++ <Build>
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_midi_latency_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_midi_latency_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_midi_latency_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
++ <Option output="Release\bin\jack_midi_latency_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add directory="Release\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 32bits">
++ <Option output="Debug\bin\jack_midi_latency_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add directory="Debug\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 32bits">
++ <Option output="Release\bin\jack_midi_latency_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add directory="Release\bin" />
++ </Linker>
++ </Target>
++ </Build>
++ <Compiler>
++ <Add option="-Wall" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ </Linker>
++ <Unit filename="..\example-clients\midi_latency_test.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Extensions>
++ <code_completion />
++ <envvars />
++ <debugger />
++ <AutoVersioning>
++ <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
++ <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
++ <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
++ </AutoVersioning>
++ </Extensions>
++ </Project>
++</CodeBlocks_project_file>
+--- /dev/null
++++ b/windows/JackMMCSS.cpp
+@@ -0,0 +1,87 @@
++/*
++ Copyright (C) 2004-2008 Grame
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU Lesser General Public License as published by
++ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ */
++
++#include "JackMMCSS.h"
++#include "JackError.h"
++#include <assert.h>
++#include <stdio.h>
++
++namespace Jack
++{
++
++avSetMmThreadCharacteristics JackMMCSS::ffMMCSSFun1 = NULL;
++avSetMmThreadPriority JackMMCSS::ffMMCSSFun2 = NULL;
++avRevertMmThreadCharacteristics JackMMCSS::ffMMCSSFun3 = NULL;
++JACK_HANDLE JackMMCSS::fAvrtDll;
++
++std::map<jack_native_thread_t, HANDLE> JackMMCSS::fHandleTable;
++
++JackMMCSS::JackMMCSS()
++{
++ fAvrtDll = LoadJackModule("avrt.dll");
++
++ if (fAvrtDll != NULL) {
++ ffMMCSSFun1 = (avSetMmThreadCharacteristics)GetJackProc(fAvrtDll, "AvSetMmThreadCharacteristicsA");
++ ffMMCSSFun2 = (avSetMmThreadPriority)GetJackProc(fAvrtDll, "AvSetMmThreadPriority");
++ ffMMCSSFun3 = (avRevertMmThreadCharacteristics)GetJackProc(fAvrtDll, "AvRevertMmThreadCharacteristics");
++ }
++}
++
++JackMMCSS::~JackMMCSS()
++{}
++
++int JackMMCSS::MMCSSAcquireRealTime(jack_native_thread_t thread)
++{
++ if (fHandleTable.find(thread) != fHandleTable.end()) {
++ return 0;
++ }
++
++ if (ffMMCSSFun1) {
++ DWORD dummy = 0;
++ HANDLE task = ffMMCSSFun1("Pro Audio", &dummy);
++ if (task == NULL) {
++ jack_error("AvSetMmThreadCharacteristics error : %d", GetLastError());
++ } else if (ffMMCSSFun2(task, AVRT_PRIORITY_CRITICAL)) {
++ fHandleTable[thread] = task;
++ jack_log("AvSetMmThreadPriority success");
++ return 0;
++ } else {
++ jack_error("AvSetMmThreadPriority error : %d", GetLastError());
++ }
++ }
++
++ return -1;
++}
++
++int JackMMCSS::MMCSSDropRealTime(jack_native_thread_t thread)
++{
++ if (fHandleTable.find(thread) != fHandleTable.end()) {
++ HANDLE task = fHandleTable[thread];
++ if (ffMMCSSFun3(task) == 0) {
++ jack_error("AvRevertMmThreadCharacteristics error : %d", GetLastError());
++ } else {
++ jack_log("AvRevertMmThreadCharacteristics success");
++ }
++ return 0;
++ } else {
++ return -1;
++ }
++}
++
++}
+--- /dev/null
++++ b/windows/JackMMCSS.h
+@@ -0,0 +1,72 @@
++/*
++ Copyright (C) 2004-2008 Grame
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU Lesser General Public License as published by
++ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++
++ */
++
++
++
++#ifndef __JackMMCSS__
++#define __JackMMCSS__
++
++#include "JackSystemDeps.h"
++#include "JackCompilerDeps.h"
++#include <windows.h>
++#include <map>
++
++namespace Jack
++{
++
++typedef enum _AVRT_PRIORITY {
++ AVRT_PRIORITY_LOW = -1,
++ AVRT_PRIORITY_NORMAL, /* 0 */
++ AVRT_PRIORITY_HIGH, /* 1 */
++ AVRT_PRIORITY_CRITICAL /* 2 */
++} AVRT_PRIORITY, *PAVRT_PRIORITY;
++
++typedef HANDLE (WINAPI *avSetMmThreadCharacteristics)(LPCTSTR, LPDWORD);
++typedef BOOL (WINAPI *avRevertMmThreadCharacteristics)(HANDLE);
++typedef BOOL (WINAPI *avSetMmThreadPriority)(HANDLE, AVRT_PRIORITY);
++
++/*!
++\brief MMCSS services.
++*/
++
++class SERVER_EXPORT JackMMCSS
++{
++
++ private:
++
++ static JACK_HANDLE fAvrtDll;
++ static avSetMmThreadCharacteristics ffMMCSSFun1;
++ static avSetMmThreadPriority ffMMCSSFun2;
++ static avRevertMmThreadCharacteristics ffMMCSSFun3;
++ static std::map<jack_native_thread_t, HANDLE> fHandleTable;
++
++ public:
++
++ JackMMCSS();
++ ~JackMMCSS();
++
++ static int MMCSSAcquireRealTime(jack_native_thread_t thread);
++ static int MMCSSDropRealTime(jack_native_thread_t thread);
++
++};
++
++} // end of namespace
++
++#endif
++
+--- a/windows/jack_netadapter.cbp
++++ b/windows/jack_netadapter.cbp
+@@ -4,62 +4,150 @@
+ <Project>
+ <Option title="jack_netadapter" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\netadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\netadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\netadapter" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\netadapter" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add library="libsamplerate_x86" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetadapter.res jacknetadapter.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\netadapter" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add library="libsamplerate_x86" />
+ <Add directory="Debug\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jacknetadapter.res jacknetadapter.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\netadapter" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add library="libsamplerate_x86" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetadapter.res jacknetadapter.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -82,9 +170,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+- <Add library="libsamplerate-0" />
+- <Add directory="Release\bin" />
+ </Linker>
+ <Unit filename="..\common\JackAudioAdapter.cpp" />
+ <Unit filename="..\common\JackAudioAdapterInterface.cpp" />
+--- a/windows/jack_netdriver.cbp
++++ b/windows/jack_netdriver.cbp
+@@ -4,62 +4,144 @@
+ <Project>
+ <Option title="jack_netdriver" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\jack_net" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\jack_net" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\jack_net" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\jack_net" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetdriver.res jacknetdriver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\jack_net" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Debug\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jacknetdriver.res jacknetdriver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\jack_net" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetdriver.res jacknetdriver.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -79,7 +161,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+ <Add library="ws2_32" />
+ </Linker>
+ <Unit filename="..\common\JackNetDriver.cpp" />
+--- a/windows/jack_netmanager.cbp
++++ b/windows/jack_netmanager.cbp
+@@ -4,59 +4,138 @@
+ <Project>
+ <Option title="jack_netmanager" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\netmanager" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\netmanager" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\netmanager" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\netmanager" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetmanager.res jacknetmanager.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\netmanager" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
+ <Add directory="Debug\bin" />
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jacknetmanager.res jacknetmanager.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\netmanager" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetmanager.res jacknetmanager.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -77,8 +156,7 @@
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+ <Add library="ws2_32" />
+- <Add library="libjackserver" />
+- </Linker>
++ </Linker>
+ <Unit filename="..\common\JackNetManager.cpp" />
+ <Unit filename="jacknetmanager.rc">
+ <Option compilerVar="WINDRES" />
+--- a/windows/jack_netonedriver.cbp
++++ b/windows/jack_netonedriver.cbp
+@@ -4,62 +4,144 @@
+ <Project>
+ <Option title="jack_netonedriver" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\jack_netone" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\jack_netone" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\jack_netone" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DBUILD_DLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\jack_netone" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jacknetonedriver.res jacknetonedriver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\jack_netone" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Debug\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jacknetonedriver.res jacknetonedriver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\jack_netone" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DBUILD_DLL" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jacknetonedriver.res jacknetonedriver.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -79,7 +161,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+ <Add library="ws2_32" />
+ </Linker>
+ <Unit filename="..\common\JackNetOneDriver.cpp" />
+--- a/windows/jack_netsource.cbp
++++ b/windows/jack_netsource.cbp
+@@ -1,110 +1,177 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+-<CodeBlocks_project_file>
+- <FileVersion major="1" minor="6" />
+- <Project>
+- <Option title="jack_netsource" />
+- <Option pch_mode="2" />
+- <Option compiler="gcc" />
+- <Build>
+- <Target title="Win32 Release">
+- <Option output="Release\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Release\" />
+- <Option type="1" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-O2" />
+- <Add option="-Wall" />
+- <Add directory="..\example-clients" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add directory="Release\bin" />
+- </Linker>
+- </Target>
+- <Target title="Win32 Debug">
+- <Option output="Debug\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Debug\" />
+- <Option type="1" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-Wall" />
+- <Add option="-g" />
+- <Add directory="..\example-clients" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add directory="Debug\bin" />
+- </Linker>
+- </Target>
+- <Target title="Win32 Profiling">
+- <Option output="Release\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
+- <Option object_output="Release\" />
+- <Option type="1" />
+- <Option compiler="gcc" />
+- <Compiler>
+- <Add option="-O2" />
+- <Add option="-Wall" />
+- <Add option="-DJACK_MONITOR" />
+- <Add directory="..\example-clients" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add directory="Release\bin" />
+- </Linker>
+- </Target>
+- </Build>
+- <Compiler>
+- <Add option="-Wall" />
+- <Add directory="..\example-clients" />
+- <Add directory="..\windows" />
+- <Add directory="..\common\jack" />
+- <Add directory="..\common" />
+- </Compiler>
+- <Linker>
+- <Add library="kernel32" />
+- <Add library="user32" />
+- <Add library="gdi32" />
+- <Add library="winspool" />
+- <Add library="comdlg32" />
+- <Add library="advapi32" />
+- <Add library="shell32" />
+- <Add library="ole32" />
+- <Add library="oleaut32" />
+- <Add library="uuid" />
+- <Add library="odbc32" />
+- <Add library="odbccp32" />
+- <Add library="libjack" />
+- <Add library="libsamplerate-0" />
+- <Add library="ws2_32" />
+- <Add directory="Release\bin" />
+- </Linker>
+- <Unit filename="..\common\netjack_packet.c">
+- <Option compilerVar="CC" />
+- </Unit>
+- <Unit filename="..\example-clients\netsource.c">
+- <Option compilerVar="CC" />
+- </Unit>
+- <Unit filename="getopt.c">
+- <Option compilerVar="CC" />
+- </Unit>
+- <Unit filename="getopt1.c">
+- <Option compilerVar="CC" />
+- </Unit>
+- <Extensions>
+- <code_completion />
+- <envvars />
+- <debugger />
+- <AutoVersioning>
+- <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
+- <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
+- <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
+- </AutoVersioning>
+- </Extensions>
+- </Project>
+-</CodeBlocks_project_file>
++<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
++<CodeBlocks_project_file>
++ <FileVersion major="1" minor="6" />
++ <Project>
++ <Option title="jack_netsource" />
++ <Option pch_mode="2" />
++ <Option compiler="mingw_64" />
++ <Build>
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libjack64" />
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
++ <Option output="Release\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add library="libsamplerate_x86" />
++ <Add directory="Release\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 32bits">
++ <Option output="Debug\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-m32" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add library="libsamplerate_x86" />
++ <Add directory="Debug\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 32bits">
++ <Option output="Release\bin\jack_netsource" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libjack" />
++ <Add library="libsamplerate_x86" />
++ <Add directory="Release\bin" />
++ </Linker>
++ </Target>
++ </Build>
++ <Compiler>
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ <Add library="ws2_32" />
++ </Linker>
++ <Unit filename="..\common\netjack_packet.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Unit filename="..\example-clients\netsource.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Unit filename="getopt.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Unit filename="getopt1.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Extensions>
++ <code_completion />
++ <envvars />
++ <debugger />
++ <AutoVersioning>
++ <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
++ <Settings autoincrement="1" date_declarations="1" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
++ <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
++ </AutoVersioning>
++ </Extensions>
++ </Project>
++</CodeBlocks_project_file>
+--- a/windows/JackNetWinSocket.cpp
++++ b/windows/JackNetWinSocket.cpp
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -23,12 +23,11 @@
+ namespace Jack
+ {
+ //utility *********************************************************************************************************
+- SERVER_EXPORT int GetHostName ( char * name, int size )
++ SERVER_EXPORT int GetHostName(char * name, int size)
+ {
+- if ( gethostname ( name, size ) == SOCKET_ERROR )
+- {
+- jack_error ( "Can't get 'hostname' : %s", strerror ( NET_ERROR_CODE ) );
+- strcpy ( name, "default" );
++ if (gethostname(name, size) == SOCKET_ERROR) {
++ jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
++ strcpy(name, "default");
+ return -1;
+ }
+ return 0;
+@@ -36,68 +35,67 @@
+
+ win_net_error_t NetErrorList[] =
+ {
+- E ( 0, "No error" ),
+- E ( WSAEINTR, "Interrupted system call" ),
+- E ( WSAEBADF, "Bad file number" ),
+- E ( WSAEACCES, "Permission denied" ),
+- E ( WSAEFAULT, "Bad address" ),
+- E ( WSAEINVAL, "Invalid argument" ),
+- E ( WSAEMFILE, "Too many open sockets" ),
+- E ( WSAEWOULDBLOCK, "Operation would block" ),
+- E ( WSAEINPROGRESS, "Operation now in progress" ),
+- E ( WSAEALREADY, "Operation already in progress" ),
+- E ( WSAENOTSOCK, "Socket operation on non-socket" ),
+- E ( WSAEDESTADDRREQ, "Destination address required" ),
+- E ( WSAEMSGSIZE, "Message too long" ),
+- E ( WSAEPROTOTYPE, "Protocol wrong type for socket" ),
+- E ( WSAENOPROTOOPT, "Bad protocol option" ),
+- E ( WSAEPROTONOSUPPORT, "Protocol not supported" ),
+- E ( WSAESOCKTNOSUPPORT, "Socket type not supported" ),
+- E ( WSAEOPNOTSUPP, "Operation not supported on socket" ),
+- E ( WSAEPFNOSUPPORT, "Protocol family not supported" ),
+- E ( WSAEAFNOSUPPORT, "Address family not supported" ),
+- E ( WSAEADDRINUSE, "Address already in use" ),
+- E ( WSAEADDRNOTAVAIL, "Can't assign requested address" ),
+- E ( WSAENETDOWN, "Network is down" ),
+- E ( WSAENETUNREACH, "Network is unreachable" ),
+- E ( WSAENETRESET, "Net connection reset" ),
+- E ( WSAECONNABORTED, "Software caused connection abort" ),
+- E ( WSAECONNRESET, "Connection reset by peer" ),
+- E ( WSAENOBUFS, "No buffer space available" ),
+- E ( WSAEISCONN, "Socket is already connected" ),
+- E ( WSAENOTCONN, "Socket is not connected" ),
+- E ( WSAESHUTDOWN, "Can't send after socket shutdown" ),
+- E ( WSAETOOMANYREFS, "Too many references, can't splice" ),
+- E ( WSAETIMEDOUT, "Connection timed out" ),
+- E ( WSAECONNREFUSED, "Connection refused" ),
+- E ( WSAELOOP, "Too many levels of symbolic links" ),
+- E ( WSAENAMETOOLONG, "File name too long" ),
+- E ( WSAEHOSTDOWN, "Host is down" ),
+- E ( WSAEHOSTUNREACH, "No route to host" ),
+- E ( WSAENOTEMPTY, "Directory not empty" ),
+- E ( WSAEPROCLIM, "Too many processes" ),
+- E ( WSAEUSERS, "Too many users" ),
+- E ( WSAEDQUOT, "Disc quota exceeded" ),
+- E ( WSAESTALE, "Stale NFS file handle" ),
+- E ( WSAEREMOTE, "Too many levels of remote in path" ),
+- E ( WSASYSNOTREADY, "Network system is unavailable" ),
+- E ( WSAVERNOTSUPPORTED, "Winsock version out of range" ),
+- E ( WSANOTINITIALISED, "WSAStartup not yet called" ),
+- E ( WSAEDISCON, "Graceful shutdown in progress" ),
+- E ( WSAHOST_NOT_FOUND, "Host not found" ),
+- E ( WSANO_DATA, "No host data of that type was found" ),
++ E(0, "No error"),
++ E(WSAEINTR, "Interrupted system call"),
++ E(WSAEBADF, "Bad file number"),
++ E(WSAEACCES, "Permission denied"),
++ E(WSAEFAULT, "Bad address"),
++ E(WSAEINVAL, "Invalid argument"),
++ E(WSAEMFILE, "Too many open sockets"),
++ E(WSAEWOULDBLOCK, "Operation would block"),
++ E(WSAEINPROGRESS, "Operation now in progress"),
++ E(WSAEALREADY, "Operation already in progress"),
++ E(WSAENOTSOCK, "Socket operation on non-socket"),
++ E(WSAEDESTADDRREQ, "Destination address required"),
++ E(WSAEMSGSIZE, "Message too long"),
++ E(WSAEPROTOTYPE, "Protocol wrong type for socket"),
++ E(WSAENOPROTOOPT, "Bad protocol option"),
++ E(WSAEPROTONOSUPPORT, "Protocol not supported"),
++ E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
++ E(WSAEOPNOTSUPP, "Operation not supported on socket"),
++ E(WSAEPFNOSUPPORT, "Protocol family not supported"),
++ E(WSAEAFNOSUPPORT, "Address family not supported"),
++ E(WSAEADDRINUSE, "Address already in use"),
++ E(WSAEADDRNOTAVAIL, "Can't assign requested address"),
++ E(WSAENETDOWN, "Network is down"),
++ E(WSAENETUNREACH, "Network is unreachable"),
++ E(WSAENETRESET, "Net connection reset"),
++ E(WSAECONNABORTED, "Software caused connection abort"),
++ E(WSAECONNRESET, "Connection reset by peer"),
++ E(WSAENOBUFS, "No buffer space available"),
++ E(WSAEISCONN, "Socket is already connected"),
++ E(WSAENOTCONN, "Socket is not connected"),
++ E(WSAESHUTDOWN, "Can't send after socket shutdown"),
++ E(WSAETOOMANYREFS, "Too many references, can't splice"),
++ E(WSAETIMEDOUT, "Connection timed out"),
++ E(WSAECONNREFUSED, "Connection refused"),
++ E(WSAELOOP, "Too many levels of symbolic links"),
++ E(WSAENAMETOOLONG, "File name too long"),
++ E(WSAEHOSTDOWN, "Host is down"),
++ E(WSAEHOSTUNREACH, "No route to host"),
++ E(WSAENOTEMPTY, "Directory not empty"),
++ E(WSAEPROCLIM, "Too many processes"),
++ E(WSAEUSERS, "Too many users"),
++ E(WSAEDQUOT, "Disc quota exceeded"),
++ E(WSAESTALE, "Stale NFS file handle"),
++ E(WSAEREMOTE, "Too many levels of remote in path"),
++ E(WSASYSNOTREADY, "Network system is unavailable"),
++ E(WSAVERNOTSUPPORTED, "Winsock version out of range"),
++ E(WSANOTINITIALISED, "WSAStartup not yet called"),
++ E(WSAEDISCON, "Graceful shutdown in progress"),
++ E(WSAHOST_NOT_FOUND, "Host not found"),
++ E(WSANO_DATA, "No host data of that type was found"),
+ { -1, NULL },
+ };
+
+- SERVER_EXPORT const char* PrintError ( int error )
++ SERVER_EXPORT const char* PrintError(int error)
+ {
+ int i;
+- for ( i = 0; NetErrorList[i].code >= 0; ++i )
+- {
+- if ( error == NetErrorList[i].code )
++ for (i = 0; NetErrorList[i].code >= 0; ++i) {
++ if (error == NetErrorList[i].code)
+ return NetErrorList[i].msg;
+ }
+- return strerror ( error );
++ return strerror(error);
+ }
+
+ //construct/destruct***********************************************************************************************
+@@ -105,28 +103,28 @@
+ {
+ fSockfd = 0;
+ fSendAddr.sin_family = AF_INET;
+- fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fSendAddr.sin_zero, 0, 8 );
++ fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fSendAddr.sin_zero, 0, 8);
+ fRecvAddr.sin_family = AF_INET;
+- fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fRecvAddr.sin_zero, 0, 8 );
++ fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fRecvAddr.sin_zero, 0, 8);
+ }
+
+- JackNetWinSocket::JackNetWinSocket ( const char* ip, int port )
++ JackNetWinSocket::JackNetWinSocket(const char* ip, int port)
+ {
+ fSockfd = 0;
+ fPort = port;
+ fSendAddr.sin_family = AF_INET;
+- fSendAddr.sin_port = htons ( port );
+- fSendAddr.sin_addr.s_addr = inet_addr ( ip );
+- memset ( &fSendAddr.sin_zero, 0, 8 );
++ fSendAddr.sin_port = htons(port);
++ fSendAddr.sin_addr.s_addr = inet_addr(ip);
++ memset(&fSendAddr.sin_zero, 0, 8);
+ fRecvAddr.sin_family = AF_INET;
+- fRecvAddr.sin_port = htons ( port );
+- fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fRecvAddr.sin_zero, 0, 8 );
++ fRecvAddr.sin_port = htons(port);
++ fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fRecvAddr.sin_zero, 0, 8);
+ }
+
+- JackNetWinSocket::JackNetWinSocket ( const JackNetWinSocket& socket )
++ JackNetWinSocket::JackNetWinSocket(const JackNetWinSocket& socket)
+ {
+ fSockfd = 0;
+ fPort = socket.fPort;
+@@ -139,10 +137,9 @@
+ Close();
+ }
+
+- JackNetWinSocket& JackNetWinSocket::operator= ( const JackNetWinSocket& socket )
++ JackNetWinSocket& JackNetWinSocket::operator=(const JackNetWinSocket& socket)
+ {
+- if ( this != &socket )
+- {
++ if (this != &socket) {
+ fSockfd = 0;
+ fPort = socket.fPort;
+ fSendAddr = socket.fSendAddr;
+@@ -154,73 +151,96 @@
+ //socket***********************************************************************************************************
+ int JackNetWinSocket::NewSocket()
+ {
+- if ( fSockfd )
+- {
++ if (fSockfd) {
+ Close();
+ Reset();
+ }
+- fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 );
++ fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ return fSockfd;
+ }
+
++ bool JackNetWinSocket::IsLocal(char* ip)
++ {
++ if (strcmp(ip, "127.0.0.1") == 0) {
++ return true;
++ }
++
++ char host_name[32];
++ gethostname(host_name, sizeof(host_name));
++
++ struct hostent* host = gethostbyname(host_name);
++ if (host) {
++ for (int i = 0; host->h_addr_list[i] != 0; ++i) {
++ struct in_addr addr;
++ memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
++ if (strcmp(inet_ntoa(addr), ip) == 0) {
++ return true;
++ }
++ }
++ return false;
++ } else {
++ return false;
++ }
++ }
++
+ int JackNetWinSocket::Bind()
+ {
+- return bind ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), sizeof ( SOCKADDR ) );
++ return bind(fSockfd, reinterpret_cast<SOCKADDR*>(&fRecvAddr), sizeof(SOCKADDR));
+ }
+
+- int JackNetWinSocket::BindWith ( const char* ip )
++ int JackNetWinSocket::BindWith(const char* ip)
+ {
+- fRecvAddr.sin_addr.s_addr = inet_addr ( ip );
++ fRecvAddr.sin_addr.s_addr = inet_addr(ip);
+ return Bind();
+ }
+
+- int JackNetWinSocket::BindWith ( int port )
++ int JackNetWinSocket::BindWith(int port)
+ {
+- fRecvAddr.sin_port = htons ( port );
++ fRecvAddr.sin_port = htons(port);
+ return Bind();
+ }
+
+ int JackNetWinSocket::Connect()
+ {
+- return connect ( fSockfd, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) );
++ return connect(fSockfd, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
+ }
+
+- int JackNetWinSocket::ConnectTo ( const char* ip )
++ int JackNetWinSocket::ConnectTo(const char* ip)
+ {
+- fSendAddr.sin_addr.s_addr = inet_addr ( ip );
++ fSendAddr.sin_addr.s_addr = inet_addr(ip);
+ return Connect();
+ }
+
+ void JackNetWinSocket::Close()
+ {
+- if ( fSockfd )
+- closesocket ( fSockfd );
++ if (fSockfd)
++ closesocket(fSockfd);
+ fSockfd = 0;
+ }
+
+ void JackNetWinSocket::Reset()
+ {
+ fSendAddr.sin_family = AF_INET;
+- fSendAddr.sin_port = htons ( fPort );
+- fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fSendAddr.sin_zero, 0, 8 );
++ fSendAddr.sin_port = htons(fPort);
++ fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fSendAddr.sin_zero, 0, 8);
+ fRecvAddr.sin_family = AF_INET;
+- fRecvAddr.sin_port = htons ( fPort );
+- fRecvAddr.sin_addr.s_addr = htonl ( INADDR_ANY );
+- memset ( &fRecvAddr.sin_zero, 0, 8 );
++ fRecvAddr.sin_port = htons(fPort);
++ fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
++ memset(&fRecvAddr.sin_zero, 0, 8);
+ }
+
+ bool JackNetWinSocket::IsSocket()
+ {
+- return ( fSockfd ) ? true : false;
++ return(fSockfd) ? true : false;
+ }
+
+ //IP/PORT***********************************************************************************************************
+- void JackNetWinSocket::SetPort ( int port )
++ void JackNetWinSocket::SetPort(int port)
+ {
+ fPort = port;
+- fSendAddr.sin_port = htons ( port );
+- fRecvAddr.sin_port = htons ( port );
++ fSendAddr.sin_port = htons(port);
++ fRecvAddr.sin_port = htons(port);
+ }
+
+ int JackNetWinSocket::GetPort()
+@@ -229,59 +249,59 @@
+ }
+
+ //address***********************************************************************************************************
+- int JackNetWinSocket::SetAddress ( const char* ip, int port )
++ int JackNetWinSocket::SetAddress(const char* ip, int port)
+ {
+- fSendAddr.sin_addr.s_addr = inet_addr ( ip );
+- fSendAddr.sin_port = htons ( port );
++ fSendAddr.sin_addr.s_addr = inet_addr(ip);
++ fSendAddr.sin_port = htons(port);
+ return 0;
+ }
+
+ char* JackNetWinSocket::GetSendIP()
+ {
+- return inet_ntoa ( fSendAddr.sin_addr );
++ return inet_ntoa(fSendAddr.sin_addr);
+ }
+
+ char* JackNetWinSocket::GetRecvIP()
+ {
+- return inet_ntoa ( fRecvAddr.sin_addr );
++ return inet_ntoa(fRecvAddr.sin_addr);
+ }
+
+ //utility************************************************************************************************************
+- int JackNetWinSocket::GetName ( char* name )
++ int JackNetWinSocket::GetName(char* name)
+ {
+- return gethostname ( name, 255 );
++ return gethostname(name, 255);
+ }
+
+- int JackNetWinSocket::JoinMCastGroup ( const char* ip )
++ int JackNetWinSocket::JoinMCastGroup(const char* ip)
+ {
+ struct ip_mreq multicast_req;
+- multicast_req.imr_multiaddr.s_addr = inet_addr ( ip );
+- multicast_req.imr_interface.s_addr = htonl ( INADDR_ANY );
++ multicast_req.imr_multiaddr.s_addr = inet_addr(ip);
++ multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
+ //12 is IP_ADD_MEMBERSHIP in winsock2 (differs from winsock1...)
+- return SetOption ( IPPROTO_IP, 12, &multicast_req, sizeof ( multicast_req ) );
++ return SetOption(IPPROTO_IP, 12, &multicast_req, sizeof(multicast_req));
+ }
+
+ //options************************************************************************************************************
+- int JackNetWinSocket::SetOption ( int level, int optname, const void* optval, SOCKLEN optlen )
++ int JackNetWinSocket::SetOption(int level, int optname, const void* optval, SOCKLEN optlen)
+ {
+- return setsockopt ( fSockfd, level, optname, static_cast<const char*> ( optval ), optlen );
++ return setsockopt(fSockfd, level, optname, static_cast<const char*>(optval), optlen);
+ }
+
+- int JackNetWinSocket::GetOption ( int level, int optname, void* optval, SOCKLEN* optlen )
++ int JackNetWinSocket::GetOption(int level, int optname, void* optval, SOCKLEN* optlen)
+ {
+- return getsockopt ( fSockfd, level, optname, static_cast<char*> ( optval ), optlen );
++ return getsockopt(fSockfd, level, optname, static_cast<char*>(optval), optlen);
+ }
+
+ //tiemout************************************************************************************************************
+- int JackNetWinSocket::SetTimeOut ( int usec )
++ int JackNetWinSocket::SetTimeOut(int usec)
+ {
+- jack_log ( "JackNetWinSocket::SetTimeout %d usec", usec );
++ jack_log("JackNetWinSocket::SetTimeout %d usec", usec);
+
+ //negative timeout, or exceeding 10s, return
+- if ( ( usec < 0 ) || ( usec > 10000000 ) )
++ if (( usec < 0) || (usec > 10000000))
+ return SOCKET_ERROR;
+ int time = usec / 1000;
+- return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &time, sizeof ( time ) );
++ return SetOption(SOL_SOCKET, SO_RCVTIMEO, &time, sizeof(time));
+ }
+
+ //local loop*********************************************************************************************************
+@@ -294,46 +314,46 @@
+ which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer.
+ */
+ char disable = 1;
+- return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) );
++ return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
+ }
+
+ //network operations*************************************************************************************************
+- int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags )
++ int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags)
+ {
+- return sendto ( fSockfd, reinterpret_cast<const char*> ( buffer ), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), sizeof ( SOCKADDR ) );
++ return sendto(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), sizeof(SOCKADDR));
+ }
+
+- int JackNetWinSocket::SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip )
++ int JackNetWinSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
+ {
+- fSendAddr.sin_addr.s_addr = inet_addr ( ip );
+- return SendTo ( buffer, nbytes, flags );
++ fSendAddr.sin_addr.s_addr = inet_addr(ip);
++ return SendTo(buffer, nbytes, flags);
+ }
+
+- int JackNetWinSocket::Send ( const void* buffer, size_t nbytes, int flags )
++ int JackNetWinSocket::Send(const void* buffer, size_t nbytes, int flags)
+ {
+- return send ( fSockfd, reinterpret_cast<const char*> ( buffer ), nbytes, flags );
++ return send(fSockfd, reinterpret_cast<const char*>(buffer), nbytes, flags);
+ }
+
+- int JackNetWinSocket::RecvFrom ( void* buffer, size_t nbytes, int flags )
++ int JackNetWinSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
+ {
+- SOCKLEN addr_len = sizeof ( SOCKADDR );
+- return recvfrom ( fSockfd, reinterpret_cast<char*> ( buffer ), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fRecvAddr ), &addr_len );
++ SOCKLEN addr_len = sizeof(SOCKADDR);
++ return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fRecvAddr), &addr_len);
+ }
+
+- int JackNetWinSocket::Recv ( void* buffer, size_t nbytes, int flags )
++ int JackNetWinSocket::Recv(void* buffer, size_t nbytes, int flags)
+ {
+- return recv ( fSockfd, reinterpret_cast<char*> ( buffer ), nbytes, flags );
++ return recv(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags);
+ }
+
+- int JackNetWinSocket::CatchHost ( void* buffer, size_t nbytes, int flags )
++ int JackNetWinSocket::CatchHost(void* buffer, size_t nbytes, int flags)
+ {
+- SOCKLEN addr_len = sizeof ( SOCKADDR );
+- return recvfrom ( fSockfd, reinterpret_cast<char*> ( buffer ), nbytes, flags, reinterpret_cast<SOCKADDR*> ( &fSendAddr ), &addr_len );
++ SOCKLEN addr_len = sizeof(SOCKADDR);
++ return recvfrom(fSockfd, reinterpret_cast<char*>(buffer), nbytes, flags, reinterpret_cast<SOCKADDR*>(&fSendAddr), &addr_len);
+ }
+
+ net_error_t JackNetWinSocket::GetError()
+ {
+- switch ( NET_ERROR_CODE )
++ switch (NET_ERROR_CODE)
+ {
+ case WSABASEERR:
+ return NET_NO_ERROR;
+--- a/windows/JackNetWinSocket.h
++++ b/windows/JackNetWinSocket.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+ #ifndef __JackNetWinSocket__
+@@ -24,6 +24,7 @@
+ #ifdef __MINGW32__
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
++#include <stdint.h>
+ #endif
+
+
+@@ -43,7 +44,7 @@
+ const char* msg;
+ };
+
+- SERVER_EXPORT const char* PrintError ( int error );
++ SERVER_EXPORT const char* PrintError(int error);
+
+ //JeckNetWinSocket***************************************************************************
+ class SERVER_EXPORT JackNetWinSocket
+@@ -55,53 +56,55 @@
+ SOCKADDR_IN fRecvAddr;
+ public:
+ JackNetWinSocket();
+- JackNetWinSocket ( const char* ip, int port );
+- JackNetWinSocket ( const JackNetWinSocket& );
++ JackNetWinSocket(const char* ip, int port);
++ JackNetWinSocket(const JackNetWinSocket&);
+ ~JackNetWinSocket();
+
+- JackNetWinSocket& operator= ( const JackNetWinSocket& );
++ JackNetWinSocket& operator=(const JackNetWinSocket&);
+
+ //socket management
+ int NewSocket();
+ int Bind();
+- int BindWith ( const char* ip );
+- int BindWith ( int port );
++ int BindWith(const char* ip);
++ int BindWith(int port);
+ int Connect();
+- int ConnectTo ( const char* ip );
++ int ConnectTo(const char* ip);
+ void Close();
+ void Reset();
+ bool IsSocket();
+
+ //IP/PORT management
+- void SetPort ( int port );
++ void SetPort(int port);
+ int GetPort();
+
+ //address management
+- int SetAddress ( const char* ip, int port );
++ int SetAddress(const char* ip, int port);
+ char* GetSendIP();
+ char* GetRecvIP();
+
+ //utility
+- int GetName ( char* name );
+- int JoinMCastGroup ( const char* mcast_ip );
++ int GetName(char* name);
++ int JoinMCastGroup(const char* mcast_ip);
+
+ //options management
+- int SetOption ( int level, int optname, const void* optval, SOCKLEN optlen );
+- int GetOption ( int level, int optname, void* optval, SOCKLEN* optlen );
++ int SetOption(int level, int optname, const void* optval, SOCKLEN optlen);
++ int GetOption(int level, int optname, void* optval, SOCKLEN* optlen);
+
+ //timeout
+- int SetTimeOut ( int usec );
++ int SetTimeOut(int usec);
+
+ //disable local loop
+ int SetLocalLoop();
+
++ bool IsLocal(char* ip);
++
+ //network operations
+- int SendTo ( const void* buffer, size_t nbytes, int flags );
+- int SendTo ( const void* buffer, size_t nbytes, int flags, const char* ip );
+- int Send ( const void* buffer, size_t nbytes, int flags );
+- int RecvFrom ( void* buffer, size_t nbytes, int flags );
+- int Recv ( void* buffer, size_t nbytes, int flags );
+- int CatchHost ( void* buffer, size_t nbytes, int flags );
++ int SendTo(const void* buffer, size_t nbytes, int flags);
++ int SendTo(const void* buffer, size_t nbytes, int flags, const char* ip);
++ int Send(const void* buffer, size_t nbytes, int flags);
++ int RecvFrom(void* buffer, size_t nbytes, int flags);
++ int Recv(void* buffer, size_t nbytes, int flags);
++ int CatchHost(void* buffer, size_t nbytes, int flags);
+
+ //error management
+ net_error_t GetError();
+@@ -109,3 +112,4 @@
+ }
+
+ #endif
++
+--- a/windows/JackPlatformPlug_os.h
++++ b/windows/JackPlatformPlug_os.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -23,7 +23,12 @@
+
+ #define jack_server_dir "server"
+ #define jack_client_dir "client"
+-#define ADDON_DIR "jack"
++#define JACK_DEFAULT_DRIVER "portaudio"
++#define JACK_LOCATION "C:/Program Files/Jack"
++
++#ifndef ADDON_DIR
++ #define ADDON_DIR "jack"
++#endif
+
+ namespace Jack
+ {
+@@ -62,7 +67,7 @@
+ #include "JackWinProcessSync.h"
+ namespace Jack { typedef JackWinProcessSync JackProcessSync; }
+
+-/* __JackPlatformServerChannel__ */
++/* __JackPlatformServerChannel__ */
+ #include "JackWinNamedPipeServerChannel.h"
+ namespace Jack { typedef JackWinNamedPipeServerChannel JackServerChannel; }
+
+--- a/windows/jack_portaudio.cbp
++++ b/windows/jack_portaudio.cbp
+@@ -4,16 +4,105 @@
+ <Project>
+ <Option title="jack_portaudio" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\jack_portaudio" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DJACK_PORTAUDIO_EXPORTS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add library="portaudio_x86_64" />
++ <Add directory="..\windows" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\jack_portaudio" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-W" />
++ <Add option="-g" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DJACK_PORTAUDIO_EXPORTS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add library="portaudio_x86_64" />
++ <Add directory="Debug64\bin" />
++ <Add directory="..\windows" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\jack_portaudio" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DJACK_PORTAUDIO_EXPORTS" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="portaudio" />
++ </Compiler>
++ <Linker>
++ <Add library="libjackserver64" />
++ <Add library="portaudio_x86_64" />
++ <Add directory="Release64\bin" />
++ <Add directory="..\windows" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\jack_portaudio" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -21,6 +110,7 @@
+ <Add option="-D_USRDLL" />
+ <Add option="-DJACK_PORTAUDIO_EXPORTS" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -28,25 +118,33 @@
+ <Add directory="portaudio" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add library="portaudio_x86" />
+ <Add directory="..\windows" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackportaudio.res jackportaudio.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\jack_portaudio" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-W" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-D_DEBUG" />
+- <Add option="-D_WINDOWS" />
++ <Add option="-D_CONSOLE" />
+ <Add option="-D_MBCS" />
+ <Add option="-D_USRDLL" />
+ <Add option="-DJACK_PORTAUDIO_EXPORTS" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -54,18 +152,25 @@
+ <Add directory="portaudio" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add library="portaudio_x86" />
+ <Add directory="Debug\bin" />
+ <Add directory="..\windows" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackportaudio.res jackportaudio.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\jack_portaudio" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -74,6 +179,7 @@
+ <Add option="-DJACK_PORTAUDIO_EXPORTS" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -81,9 +187,15 @@
+ <Add directory="portaudio" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="libjackserver" />
++ <Add library="portaudio_x86" />
+ <Add directory="Release\bin" />
+ <Add directory="..\windows" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackportaudio.res jackportaudio.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -102,8 +214,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+- <Add library="portaudio_x86" />
+ </Linker>
+ <Unit filename="jackportaudio.rc">
+ <Option compilerVar="WINDRES" />
+--- a/windows/JackRouter/JackRouter.cpp
++++ b/windows/JackRouter/JackRouter.cpp
+@@ -1,19 +1,24 @@
+ /*
+-Copyright (C) 2006 Grame
++ Copyright (C) 2006-2011 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.
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
++ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
++ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
++ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ */
+
+@@ -29,13 +34,12 @@
+ #include "profport.h"
+
+ /*
+-
+- 08/07/2007 SL : USe jack_client_open instead of jack_client_new (automatic client renaming).
++ 08/07/2007 SL : Use jack_client_open instead of jack_client_new (automatic client renaming).
+ 09/08/2007 SL : Add JackRouter.ini parameter file.
+ 09/20/2007 SL : Better error report in DllRegisterServer (for Vista).
+ 09/27/2007 SL : Add AUDO_CONNECT property in JackRouter.ini file.
+ 10/10/2007 SL : Use ASIOSTInt32LSB instead of ASIOSTInt16LSB.
+-
++ 12/04/2011 SL : Compilation on Windows 64.
+ */
+
+ //------------------------------------------------------------------------------------------
+@@ -54,7 +58,13 @@
+ #if WINDOWS
+ #include "windows.h"
+ #include "mmsystem.h"
+-#include "psapi.h"
++#ifdef _WIN64
++#define JACK_ROUTER "JackRouter.dll"
++#include <psapi.h>
++#else
++#define JACK_ROUTER "JackRouter.dll"
++#include "./psapi.h"
++#endif
+
+ using namespace std;
+
+@@ -95,11 +105,11 @@
+ LONG rc;
+ char errstr[128];
+
+- rc = RegisterAsioDriver (IID_ASIO_DRIVER,"JackRouter.dll","JackRouter","JackRouter","Apartment");
++ rc = RegisterAsioDriver (IID_ASIO_DRIVER, JACK_ROUTER,"JackRouter","JackRouter","Apartment");
+
+ if (rc) {
+ memset(errstr,0,128);
+- sprintf(errstr,"Register Server failed ! (%d)",rc);
++ sprintf(errstr,"Register Server failed ! (%d)", rc);
+ MessageBox(0,(LPCTSTR)errstr,(LPCTSTR)"JackRouter",MB_OK);
+ return -1;
+ }
+@@ -115,7 +125,7 @@
+ LONG rc;
+ char errstr[128];
+
+- rc = UnregisterAsioDriver (IID_ASIO_DRIVER,"JackRouter.dll","JackRouter");
++ rc = UnregisterAsioDriver (IID_ASIO_DRIVER,JACK_ROUTER,"JackRouter");
+
+ if (rc) {
+ memset(errstr,0,128);
+@@ -175,7 +185,7 @@
+ printf("Constructor\n");
+
+ // Use "jackrouter.ini" parameters if available
+- HMODULE handle = LoadLibrary("JackRouter.dll");
++ HMODULE handle = LoadLibrary(JACK_ROUTER);
+
+ if (handle) {
+
+@@ -209,15 +219,11 @@
+ {
+ stop ();
+ disposeBuffers ();
+- printf("Destructor\n");
+ jack_client_close(fClient);
++ printf("Destructor\n");
+ }
+
+ //------------------------------------------------------------------------------------------
+-#include <windows.h>
+-#include <stdio.h>
+-#include <tchar.h>
+-#include "psapi.h"
+
+ static bool GetEXEName(DWORD dwProcessID, char* name)
+ {
+@@ -246,7 +252,7 @@
+ HMODULE hMod;
+ DWORD cbNeeded;
+
+- if(EnumProcessModules(hProcess, &hMod,
++ if (EnumProcessModules(hProcess, &hMod,
+ sizeof(hMod), &cbNeeded)) {
+ //Get the name of the exe file
+ GetModuleBaseName(hProcess, hMod, szEXEName,
+--- a/windows/JackRouter/JackRouter.h
++++ b/windows/JackRouter/JackRouter.h
+@@ -1,19 +1,24 @@
+ /*
+-Copyright (C) 2006 Grame
++ Copyright (C) 2006-2011 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.
++ Permission is hereby granted, free of charge, to any person obtaining
++ a copy of this software and associated documentation files
++ (the "Software"), to deal in the Software without restriction,
++ including without limitation the rights to use, copy, modify, merge,
++ publish, distribute, sublicense, and/or sell copies of the Software,
++ and to permit persons to whom the Software is furnished to do so,
++ subject to the following conditions:
++
++ The above copyright notice and this permission notice shall be
++ included in all copies or substantial portions of the Software.
++
++ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
++ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
++ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
++ CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
++ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ */
+
+@@ -22,13 +27,11 @@
+
+ #include "asiosys.h"
+
+-
+ // Globals
+ static int kBlockFrames = 256;
+ static int kNumInputs = 4;
+ static int kNumOutputs = 4;
+
+-
+ #if WINDOWS
+
+ #include "jack.h"
+@@ -44,9 +47,7 @@
+ #include "iasiodrv.h"
+
+ #define MAX_PORTS 32
+-
+ #define LONG_SAMPLE 1
+-
+ #define PATH_SEP "\\"
+
+ #include <list>
+@@ -77,7 +78,6 @@
+
+ #include "asiodrvr.h"
+
+-
+ //---------------------------------------------------------------------------------------------
+ class JackRouter : public AsioDriver
+ {
+--- /dev/null
++++ b/windows/JackRouter/JackRouter.vcxproj
+@@ -0,0 +1,280 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <ItemGroup Label="ProjectConfigurations">
++ <ProjectConfiguration Include="Debug|Win32">
++ <Configuration>Debug</Configuration>
++ <Platform>Win32</Platform>
++ </ProjectConfiguration>
++ <ProjectConfiguration Include="Debug|x64">
++ <Configuration>Debug</Configuration>
++ <Platform>x64</Platform>
++ </ProjectConfiguration>
++ <ProjectConfiguration Include="Release|Win32">
++ <Configuration>Release</Configuration>
++ <Platform>Win32</Platform>
++ </ProjectConfiguration>
++ <ProjectConfiguration Include="Release|x64">
++ <Configuration>Release</Configuration>
++ <Platform>x64</Platform>
++ </ProjectConfiguration>
++ </ItemGroup>
++ <PropertyGroup Label="Globals">
++ <SccProjectName />
++ <SccLocalPath />
++ </PropertyGroup>
++ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
++ <ConfigurationType>DynamicLibrary</ConfigurationType>
++ <UseOfMfc>false</UseOfMfc>
++ </PropertyGroup>
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
++ <ConfigurationType>DynamicLibrary</ConfigurationType>
++ <UseOfMfc>false</UseOfMfc>
++ </PropertyGroup>
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
++ <ConfigurationType>DynamicLibrary</ConfigurationType>
++ <UseOfMfc>false</UseOfMfc>
++ </PropertyGroup>
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
++ <ConfigurationType>DynamicLibrary</ConfigurationType>
++ <UseOfMfc>false</UseOfMfc>
++ </PropertyGroup>
++ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
++ <ImportGroup Label="ExtensionSettings">
++ </ImportGroup>
++ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
++ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
++ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
++ </ImportGroup>
++ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
++ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
++ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
++ </ImportGroup>
++ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
++ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
++ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
++ </ImportGroup>
++ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
++ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
++ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
++ </ImportGroup>
++ <PropertyGroup Label="UserMacros" />
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
++ <OutDir>.\Debug\</OutDir>
++ <IntDir>.\Debug\</IntDir>
++ <LinkIncremental>true</LinkIncremental>
++ </PropertyGroup>
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
++ <OutDir>.\Debug\</OutDir>
++ <IntDir>.\Debug\</IntDir>
++ <LinkIncremental>true</LinkIncremental>
++ </PropertyGroup>
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
++ <OutDir>.\Release\</OutDir>
++ <IntDir>.\Release\</IntDir>
++ <LinkIncremental>false</LinkIncremental>
++ </PropertyGroup>
++ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
++ <OutDir>.\Release64\</OutDir>
++ <IntDir>.\Release64\</IntDir>
++ <LinkIncremental>false</LinkIncremental>
++ </PropertyGroup>
++ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
++ <ClCompile>
++ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
++ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
++ <FunctionLevelLinking>false</FunctionLevelLinking>
++ <Optimization>Disabled</Optimization>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <WarningLevel>Level3</WarningLevel>
++ <MinimalRebuild>true</MinimalRebuild>
++ <AdditionalIncludeDirectories>..\..\..\..\..\ASIOSDK2\common;..\..\common;..\..\common\jack;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
++ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <AssemblerListingLocation>.\Debug\</AssemblerListingLocation>
++ <BrowseInformation>true</BrowseInformation>
++ <PrecompiledHeaderOutputFile>.\Debug\JackRouter.pch</PrecompiledHeaderOutputFile>
++ <ObjectFileName>.\Debug\</ObjectFileName>
++ <ProgramDataBaseFileName>.\Debug\</ProgramDataBaseFileName>
++ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
++ </ClCompile>
++ <Midl>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <TypeLibraryName>.\Debug\JackRouter.tlb</TypeLibraryName>
++ <MkTypLibCompatible>true</MkTypLibCompatible>
++ <TargetEnvironment>Win32</TargetEnvironment>
++ </Midl>
++ <ResourceCompile>
++ <Culture>0x0409</Culture>
++ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ </ResourceCompile>
++ <Bscmake>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <OutputFile>.\Debug\JackRouter.bsc</OutputFile>
++ </Bscmake>
++ <Link>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <LinkDLL>true</LinkDLL>
++ <GenerateDebugInformation>true</GenerateDebugInformation>
++ <SubSystem>Windows</SubSystem>
++ <OutputFile>Debug/JackRouter_debug.dll</OutputFile>
++ <ImportLibrary>.\Debug\JackRouter_debug.lib</ImportLibrary>
++ <AdditionalDependencies>odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
++ <ModuleDefinitionFile>.\JackRouter.def</ModuleDefinitionFile>
++ </Link>
++ </ItemDefinitionGroup>
++ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
++ <ClCompile>
++ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
++ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
++ <FunctionLevelLinking>false</FunctionLevelLinking>
++ <Optimization>Disabled</Optimization>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <WarningLevel>Level3</WarningLevel>
++ <AdditionalIncludeDirectories>..\..\..\..\..\ASIOSDK2\common;..\..\common;..\..\common\jack;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
++ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <AssemblerListingLocation>.\Debug\</AssemblerListingLocation>
++ <BrowseInformation>true</BrowseInformation>
++ <PrecompiledHeaderOutputFile>.\Debug\JackRouter.pch</PrecompiledHeaderOutputFile>
++ <ObjectFileName>.\Debug\</ObjectFileName>
++ <ProgramDataBaseFileName>.\Debug\</ProgramDataBaseFileName>
++ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
++ </ClCompile>
++ <Midl>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <TypeLibraryName>.\Debug\JackRouter.tlb</TypeLibraryName>
++ <MkTypLibCompatible>true</MkTypLibCompatible>
++ </Midl>
++ <ResourceCompile>
++ <Culture>0x0409</Culture>
++ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ </ResourceCompile>
++ <Bscmake>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <OutputFile>.\Debug\JackRouter.bsc</OutputFile>
++ </Bscmake>
++ <Link>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <LinkDLL>true</LinkDLL>
++ <GenerateDebugInformation>true</GenerateDebugInformation>
++ <SubSystem>Windows</SubSystem>
++ <OutputFile>Debug/JackRouter_debug.dll</OutputFile>
++ <ImportLibrary>.\Debug\JackRouter_debug.lib</ImportLibrary>
++ <AdditionalDependencies>odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
++ <ModuleDefinitionFile>.\JackRouter.def</ModuleDefinitionFile>
++ </Link>
++ </ItemDefinitionGroup>
++ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
++ <ClCompile>
++ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
++ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
++ <StringPooling>true</StringPooling>
++ <FunctionLevelLinking>true</FunctionLevelLinking>
++ <Optimization>MaxSpeed</Optimization>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <WarningLevel>Level3</WarningLevel>
++ <AdditionalIncludeDirectories>..\..\..\..\..\ASIOSDK2\common;..\..\common;..\..\common\jack;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
++ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <AssemblerListingLocation>.\Release\</AssemblerListingLocation>
++ <BrowseInformation>true</BrowseInformation>
++ <PrecompiledHeaderOutputFile>.\Release\JackRouter.pch</PrecompiledHeaderOutputFile>
++ <ObjectFileName>.\Release\</ObjectFileName>
++ <ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
++ </ClCompile>
++ <Midl>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <TypeLibraryName>.\Release\JackRouter.tlb</TypeLibraryName>
++ <MkTypLibCompatible>true</MkTypLibCompatible>
++ <TargetEnvironment>Win32</TargetEnvironment>
++ </Midl>
++ <ResourceCompile>
++ <Culture>0x0409</Culture>
++ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ </ResourceCompile>
++ <Bscmake>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <OutputFile>.\Release\JackRouter.bsc</OutputFile>
++ </Bscmake>
++ <Link>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <LinkDLL>true</LinkDLL>
++ <SubSystem>Windows</SubSystem>
++ <OutputFile>.\Release\JackRouter.dll</OutputFile>
++ <ImportLibrary>.\Release\JackRouter.lib</ImportLibrary>
++ <AdditionalDependencies>odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
++ <ModuleDefinitionFile>.\JackRouter.def</ModuleDefinitionFile>
++ </Link>
++ </ItemDefinitionGroup>
++ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
++ <ClCompile>
++ <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
++ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
++ <StringPooling>true</StringPooling>
++ <FunctionLevelLinking>true</FunctionLevelLinking>
++ <Optimization>MaxSpeed</Optimization>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <WarningLevel>Level3</WarningLevel>
++ <AdditionalIncludeDirectories>..\..\..\..\..\ASIOSDK2\common;..\..\common;..\..\common\jack;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
++ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;PSAPI_VERSION=2;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <AssemblerListingLocation>.\Release\</AssemblerListingLocation>
++ <BrowseInformation>true</BrowseInformation>
++ <PrecompiledHeaderOutputFile>.\Release\JackRouter.pch</PrecompiledHeaderOutputFile>
++ <ObjectFileName>.\Release\</ObjectFileName>
++ <ProgramDataBaseFileName>.\Release\</ProgramDataBaseFileName>
++ </ClCompile>
++ <Midl>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ <TypeLibraryName>.\Release\JackRouter.tlb</TypeLibraryName>
++ <MkTypLibCompatible>true</MkTypLibCompatible>
++ </Midl>
++ <ResourceCompile>
++ <Culture>0x0409</Culture>
++ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
++ </ResourceCompile>
++ <Bscmake>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <OutputFile>.\Release\JackRouter64.bsc</OutputFile>
++ </Bscmake>
++ <Link>
++ <SuppressStartupBanner>true</SuppressStartupBanner>
++ <LinkDLL>true</LinkDLL>
++ <SubSystem>Windows</SubSystem>
++ <OutputFile>.\Release64\JackRouter.dll</OutputFile>
++ <ImportLibrary>.\Release\JackRouter64.lib</ImportLibrary>
++ <AdditionalDependencies>odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
++ <ModuleDefinitionFile>.\JackRouter.def</ModuleDefinitionFile>
++ </Link>
++ </ItemDefinitionGroup>
++ <ItemGroup>
++ <ClCompile Include="..\..\..\..\..\ASIOSDK2\common\combase.cpp" />
++ <ClCompile Include="..\..\..\..\..\ASIOSDK2\common\dllentry.cpp" />
++ <ClCompile Include="JackRouter.cpp" />
++ <ClCompile Include="profport.cpp" />
++ <ClCompile Include="..\..\..\..\..\ASIOSDK2\common\register.cpp" />
++ </ItemGroup>
++ <ItemGroup>
++ <CustomBuild Include="JackRouter.def" />
++ </ItemGroup>
++ <ItemGroup>
++ <ResourceCompile Include="resource.rc" />
++ </ItemGroup>
++ <ItemGroup>
++ <ClInclude Include="..\..\..\common\asio.h" />
++ <ClInclude Include="..\..\Common\Asiodrvr.h" />
++ <ClInclude Include="..\asiosmpl.h" />
++ <ClInclude Include="..\..\..\common\asiosys.h" />
++ <ClInclude Include="..\..\..\common\combase.h" />
++ <ClInclude Include="..\..\..\common\iasiodrv.h" />
++ </ItemGroup>
++ <ItemGroup>
++ <Library Include="..\Release64\bin\libjack64.lib" />
++ <Library Include="..\Release\bin\libjack.lib" />
++ <Library Include="Psapi.Lib" />
++ </ItemGroup>
++ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
++ <ImportGroup Label="ExtensionTargets">
++ </ImportGroup>
++</Project>
+\ No newline at end of file
+--- /dev/null
++++ b/windows/JackRouter/JackRouter.vcxproj.filters
+@@ -0,0 +1,69 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <ItemGroup>
++ <Filter Include="Source Files">
++ <UniqueIdentifier>{72f2b2b0-dbea-4574-94fa-0c1ea89a3c8e}</UniqueIdentifier>
++ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
++ </Filter>
++ <Filter Include="Header Files">
++ <UniqueIdentifier>{9590ca0b-94c8-4c22-88b2-66724eb0ea21}</UniqueIdentifier>
++ <Extensions>h;hpp;hxx;hm;inl</Extensions>
++ </Filter>
++ <Filter Include="Resource Files">
++ <UniqueIdentifier>{9742e150-2741-4bf4-9b81-bea4aab464af}</UniqueIdentifier>
++ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
++ </Filter>
++ </ItemGroup>
++ <ItemGroup>
++ <ClCompile Include="..\..\..\..\..\ASIOSDK2\common\combase.cpp">
++ <Filter>Source Files</Filter>
++ </ClCompile>
++ <ClCompile Include="..\..\..\..\..\ASIOSDK2\common\dllentry.cpp">
++ <Filter>Source Files</Filter>
++ </ClCompile>
++ <ClCompile Include="JackRouter.cpp">
++ <Filter>Source Files</Filter>
++ </ClCompile>
++ <ClCompile Include="profport.cpp">
++ <Filter>Source Files</Filter>
++ </ClCompile>
++ <ClCompile Include="..\..\..\..\..\ASIOSDK2\common\register.cpp">
++ <Filter>Source Files</Filter>
++ </ClCompile>
++ </ItemGroup>
++ <ItemGroup>
++ <ResourceCompile Include="resource.rc">
++ <Filter>Source Files</Filter>
++ </ResourceCompile>
++ </ItemGroup>
++ <ItemGroup>
++ <ClInclude Include="..\..\..\common\asio.h">
++ <Filter>Header Files</Filter>
++ </ClInclude>
++ <ClInclude Include="..\..\Common\Asiodrvr.h">
++ <Filter>Header Files</Filter>
++ </ClInclude>
++ <ClInclude Include="..\asiosmpl.h">
++ <Filter>Header Files</Filter>
++ </ClInclude>
++ <ClInclude Include="..\..\..\common\asiosys.h">
++ <Filter>Header Files</Filter>
++ </ClInclude>
++ <ClInclude Include="..\..\..\common\combase.h">
++ <Filter>Header Files</Filter>
++ </ClInclude>
++ <ClInclude Include="..\..\..\common\iasiodrv.h">
++ <Filter>Header Files</Filter>
++ </ClInclude>
++ </ItemGroup>
++ <ItemGroup>
++ <Library Include="..\Release\bin\libjack.lib" />
++ <Library Include="..\Release64\bin\libjack64.lib" />
++ <Library Include="Psapi.Lib" />
++ </ItemGroup>
++ <ItemGroup>
++ <CustomBuild Include="JackRouter.def">
++ <Filter>Source Files</Filter>
++ </CustomBuild>
++ </ItemGroup>
++</Project>
+\ No newline at end of file
+--- /dev/null
++++ b/windows/JackRouter/JackRouter.vcxproj.user
+@@ -0,0 +1,6 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <PropertyGroup>
++ <ShowAllFiles>false</ShowAllFiles>
++ </PropertyGroup>
++</Project>
+\ No newline at end of file
+--- a/windows/JackRouter/README
++++ b/windows/JackRouter/README
+@@ -1,3 +1,7 @@
+ This folder contains the sources for ASIO/JACK bridge ASIO driver called "JackRouter". The included project is a Microsoft VC++ 6 one.
+ It requires some files (combase.cpp, dllentry.cpp, register.cpp) that are part on the ASIO driver SDK. The produced "JackRouter.dll" file
+-has to be registered in the system using the "regsvr32" tool.
+\ No newline at end of file
++has to be registered in the system using the "regsvr32" tool.
++
++64 bits compilation
++====================
++A Visual Studio 10 project has been added to compile 64 and 32 bits targets.
+\ No newline at end of file
+--- a/windows/JackShmMem_os.h
++++ b/windows/JackShmMem_os.h
+@@ -1,31 +1,53 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
+- */
+
++ */
+
+ #ifndef __JackShmMem_WIN32__
+ #define __JackShmMem_WIN32__
+
+ #include <windows.h>
+
+-// See GetProcessWorkingSetSize and SetProcessWorkingSetSize
++inline bool CHECK_MLOCK(void* ptr, size_t size)
++{
++ if (!VirtualLock((ptr), (size))) {
++ SIZE_T minWSS, maxWSS;
++ HANDLE hProc = GetCurrentProcess();
++ if (GetProcessWorkingSetSize(hProc, &minWSS, &maxWSS)) {
++ const size_t increase = size + (10 * 4096);
++ maxWSS += increase;
++ minWSS += increase;
++ if (!SetProcessWorkingSetSize(hProc, minWSS, maxWSS)) {
++ jack_error("SetProcessWorkingSetSize error = %d", GetLastError());
++ return false;
++ } else if (!VirtualLock((ptr), (size))) {
++ jack_error("VirtualLock error = %d", GetLastError());
++ return false;
++ } else {
++ return true;
++ }
++ } else {
++ return false;
++ }
++ } else {
++ return true;
++ }
++}
+
+-#define CHECK_MLOCK(ptr, size) (VirtualLock((ptr), (size)) != 0)
+ #define CHECK_MUNLOCK(ptr, size) (VirtualUnlock((ptr), (size)) != 0)
+ #define CHECK_MLOCKALL()(false)
+ #define CHECK_MUNLOCKALL()(false)
+--- a/windows/JackSystemDeps_os.h
++++ b/windows/JackSystemDeps_os.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -23,6 +23,10 @@
+
+ #include <windows.h>
+
++#ifndef PATH_MAX
++#define PATH_MAX 512
++#endif
++
+ #define UINT32_MAX 4294967295U
+
+ #define DRIVER_HANDLE HINSTANCE
+@@ -35,8 +39,19 @@
+ #define UnloadJackModule(handle) FreeLibrary((handle));
+ #define GetJackProc(handle, name) GetProcAddress((handle), (name));
+
++#ifndef ENOBUFS
+ #define ENOBUFS 55
++#endif
++
++#ifdef _DEBUG
++#define JACK_DEBUG true
++#else
+ #define JACK_DEBUG false
++#endif
++
++#if defined(_MSC_VER)
++#define snprintf _snprintf
++#endif
+
+ #endif
+
+--- a/windows/jack_test.cbp
++++ b/windows/jack_test.cbp
+@@ -4,50 +4,112 @@
+ <Project>
+ <Option title="jack_test" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_test" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_test" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_test" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Debug\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_test" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+@@ -55,7 +117,9 @@
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add directory="Release\bin" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -75,7 +139,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\tests\test.cpp">
+ <Option compilerVar="CC" />
+--- a/windows/jack_unload.cbp
++++ b/windows/jack_unload.cbp
+@@ -4,48 +4,107 @@
+ <Project>
+ <Option title="jack_unload" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack_unload" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack_unload" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug\64" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack_unload" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack_unload" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack_unload" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+ <Add directory="..\common" />
+ </Compiler>
+ <Linker>
+ <Add directory="Debug\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack_unload" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -53,6 +112,8 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -72,7 +133,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\example-clients\ipunload.c">
+ <Option compilerVar="CC" />
+--- a/windows/JackWinEvent.cpp
++++ b/windows/JackWinEvent.cpp
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -29,9 +29,9 @@
+ namespace Jack
+ {
+
+-void JackWinEvent::BuildName(const char* name, const char* server_name, char* res)
++void JackWinEvent::BuildName(const char* name, const char* server_name, char* res, int size)
+ {
+- sprintf(res, "jack_pipe.%s_%s", server_name, name);
++ snprintf(res, size, "jack_pipe.%s_%s", server_name, name);
+ }
+
+ bool JackWinEvent::Signal()
+@@ -89,7 +89,7 @@
+ // Client side : get the published semaphore from server
+ bool JackWinEvent::ConnectInput(const char* name, const char* server_name)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ jack_log("JackWinEvent::Connect %s", fName);
+
+ // Temporary...
+@@ -130,7 +130,7 @@
+
+ bool JackWinEvent::Allocate(const char* name, const char* server_name, int value)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ jack_log("JackWinEvent::Allocate name = %s val = %ld", fName, value);
+
+ /* create an auto reset event */
+--- a/windows/JackWinEvent.h
++++ b/windows/JackWinEvent.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+ #ifndef __JackWinEvent__
+@@ -41,7 +41,7 @@
+
+ protected:
+
+- void BuildName(const char* name, const char* server_name, char* res);
++ void BuildName(const char* name, const char* server_name, char* res, int size);
+
+ public:
+
+--- a/windows/jack_winmme.cbp
++++ b/windows/jack_winmme.cbp
+@@ -4,22 +4,106 @@
+ <Project>
+ <Option title="jack_winmme" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="winmme" />
++ </Compiler>
++ <Linker>
++ <Add directory="..\windows" />
++ <Add directory="Release64\bin" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-W" />
++ <Add option="-g" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="winmme" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add directory="..\windows" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="winmme" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add directory="..\windows" />
++ <Add library="libjackserver64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+ <Add option="-D_MBCS" />
+ <Add option="-D_USRDLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -29,22 +113,29 @@
+ <Linker>
+ <Add directory="..\windows" />
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/jackwinmme.res jackwinmme.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-W" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-D_DEBUG" />
+- <Add option="-D_WINDOWS" />
++ <Add option="-D_CONSOLE" />
+ <Add option="-D_MBCS" />
+ <Add option="-D_USRDLL" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -54,16 +145,22 @@
+ <Linker>
+ <Add directory="Debug\bin" />
+ <Add directory="..\windows" />
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackwinmme.res jackwinmme.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\jack\jack_winmme" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -71,6 +168,7 @@
+ <Add option="-D_USRDLL" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DSERVER_SIDE" />
++ <Add option="-DJACK_32_64" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -80,7 +178,12 @@
+ <Linker>
+ <Add directory="Release\bin" />
+ <Add directory="..\windows" />
++ <Add option="-m32" />
++ <Add library="libjackserver" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/jackwinmme.res jackwinmme.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -99,13 +202,18 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjackserver" />
+ <Add library="winmm" />
+ </Linker>
+ <Unit filename="jackwinmme.rc">
+ <Option compilerVar="WINDRES" />
+ </Unit>
+ <Unit filename="winmme\JackWinMMEDriver.cpp" />
++ <Unit filename="winmme\JackWinMMEDriver.h" />
++ <Unit filename="winmme\JackWinMMEInputPort.cpp" />
++ <Unit filename="winmme\JackWinMMEInputPort.h" />
++ <Unit filename="winmme\JackWinMMEOutputPort.cpp" />
++ <Unit filename="winmme\JackWinMMEOutputPort.h" />
++ <Unit filename="winmme\JackWinMMEPort.cpp" />
+ <Extensions>
+ <code_completion />
+ <envvars />
+--- a/windows/JackWinMutex.h
++++ b/windows/JackWinMutex.h
+@@ -1,26 +1,28 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+ #ifndef __JackWinMutex__
+ #define __JackWinMutex__
+-
++
++#include "JackError.h"
++#include "JackException.h"
+ #include <windows.h>
+
+ namespace Jack
+@@ -28,6 +30,81 @@
+ /*!
+ \brief Mutex abstraction.
+ */
++class JackBaseWinMutex
++{
++
++ protected:
++
++ HANDLE fMutex;
++ DWORD fOwner;
++
++ public:
++
++ JackBaseWinMutex():fOwner(0)
++ {
++ // In recursive mode by default
++ fMutex = (HANDLE)CreateMutex(0, FALSE, 0);
++ ThrowIf(fMutex == 0, JackException("JackWinMutex: could not init the mutex"));
++ }
++
++ virtual ~JackBaseWinMutex()
++ {
++ CloseHandle(fMutex);
++ }
++
++ bool Lock()
++ {
++ if (fOwner != GetCurrentThreadId()) {
++ DWORD res = WaitForSingleObject(fMutex, INFINITE);
++ if (res == WAIT_OBJECT_0) {
++ fOwner = GetCurrentThreadId();
++ return true;
++ } else {
++ jack_log("JackWinMutex::Lock res = %d", res);
++ return false;
++ }
++ } else {
++ jack_error("JackWinMutex::Lock mutex already locked by thread = %d", GetCurrentThreadId());
++ return false;
++ }
++ }
++
++ bool Trylock()
++ {
++ if (fOwner != GetCurrentThreadId()) {
++ DWORD res = WaitForSingleObject(fMutex, 0);
++ if (res == WAIT_OBJECT_0) {
++ fOwner = GetCurrentThreadId();
++ return true;
++ } else {
++ jack_log("JackWinMutex::Trylock res = %d", res);
++ return false;
++ }
++ } else {
++ jack_error("JackWinMutex::Trylock mutex already locked by thread = %d", GetCurrentThreadId());
++ return false;
++ }
++ }
++
++ bool Unlock()
++ {
++ if (fOwner == GetCurrentThreadId()) {
++ fOwner = 0;
++ int res = ReleaseMutex(fMutex);
++ if (res != 0) {
++ return true;
++ } else {
++ jack_log("JackWinMutex::Unlock res = %d", res);
++ return false;
++ }
++ } else {
++ jack_error("JackWinMutex::Unlock mutex not locked by thread = %d", GetCurrentThreadId());
++ return false;
++ }
++ }
++
++};
++
+ class JackWinMutex
+ {
+
+@@ -65,6 +142,7 @@
+
+ };
+
++
+ } // namespace
+
+ #endif
+--- a/windows/JackWinNamedPipeClientChannel.cpp
++++ b/windows/JackWinNamedPipeClientChannel.cpp
+@@ -55,10 +55,10 @@
+
+ /*
+ 16/08/07: was called before doing "fRequestPipe.Connect" .... still necessary?
+- if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) {
+- jack_error("Cannot bind pipe");
+- goto error;
+- }
++ if (fNotificationListenPipe.Bind(jack_client_dir, name, 0) < 0) {
++ jack_error("Cannot bind pipe");
++ goto error;
++ }
+ */
+
+ if (fRequestPipe.Connect(jack_server_dir, server_name, 0) < 0) {
+@@ -67,10 +67,14 @@
+ }
+
+ // Check name in server
+- ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result);
++ ClientCheck(name, uuid, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result, true);
+ if (result < 0) {
+- jack_error("Client name = %s conflits with another running client", name);
+- goto error;
++ int status1 = *status;
++ if (status1 & JackVersionError) {
++ jack_error("JACK protocol mismatch %d", JACK_PROTOCOL_VERSION);
++ } else {
++ jack_error("Client name = %s conflits with another running client", name);
++ }
+ }
+
+ if (fNotificationListenPipe.Bind(jack_client_dir, name_res, 0) < 0) {
+@@ -142,9 +146,9 @@
+ }
+ }
+
+-void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result)
++void JackWinNamedPipeClientChannel::ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open)
+ {
+- JackClientCheckRequest req(name, protocol, options, uuid);
++ JackClientCheckRequest req(name, protocol, options, uuid, open);
+ JackClientCheckResult res;
+ ServerSyncCall(&req, &res, result);
+ *status = res.fStatus;
+@@ -259,24 +263,7 @@
+ JackSessionNotifyResult res;
+ int intresult;
+ ServerSyncCall(&req, &res, &intresult);
+-
+- jack_session_command_t* session_command = (jack_session_command_t *)malloc(sizeof(jack_session_command_t) * (res.fCommandList.size() + 1));
+- int i = 0;
+-
+- for (std::list<JackSessionCommand>::iterator ci=res.fCommandList.begin(); ci!=res.fCommandList.end(); ci++) {
+- session_command[i].uuid = strdup( ci->fUUID );
+- session_command[i].client_name = strdup( ci->fClientName );
+- session_command[i].command = strdup( ci->fCommand );
+- session_command[i].flags = ci->fFlags;
+- i += 1;
+- }
+-
+- session_command[i].uuid = NULL;
+- session_command[i].client_name = NULL;
+- session_command[i].command = NULL;
+- session_command[i].flags = (jack_session_flags_t)0;
+-
+- *result = session_command;
++ *result = res.GetCommands();
+ }
+
+ void JackWinNamedPipeClientChannel::SessionReply(int refnum, int* result)
+--- a/windows/JackWinNamedPipeClientChannel.h
++++ b/windows/JackWinNamedPipeClientChannel.h
+@@ -59,7 +59,7 @@
+
+ int ServerCheck(const char* server_name);
+
+- void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result);
++ void ClientCheck(const char* name, int uuid, char* name_res, int protocol, int options, int* status, int* result, int open);
+ void ClientOpen(const char* name, int pid, int uuid, int* shared_engine, int* shared_client, int* shared_graph, int* result);
+ void ClientOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, int* result)
+ {}
+--- a/windows/JackWinNamedPipe.cpp
++++ b/windows/JackWinNamedPipe.cpp
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -54,7 +54,7 @@
+
+ int JackWinNamedPipeClient::Connect(const char* dir, int which)
+ {
+- sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
++ snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
+ jack_log("Connect: fName %s", fName);
+
+ fNamedPipe = CreateFile(fName, // pipe name
+@@ -76,7 +76,7 @@
+
+ int JackWinNamedPipeClient::Connect(const char* dir, const char* name, int which)
+ {
+- sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
++ snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
+ jack_log("Connect: fName %s", fName);
+
+ fNamedPipe = CreateFile(fName, // pipe name
+@@ -226,7 +226,7 @@
+
+ int JackWinNamedPipeServer::Bind(const char* dir, int which)
+ {
+- sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
++ snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
+ jack_log("Bind: fName %s", fName);
+
+ if ((fNamedPipe = CreateNamedPipe(fName,
+@@ -248,7 +248,7 @@
+
+ int JackWinNamedPipeServer::Bind(const char* dir, const char* name, int which)
+ {
+- sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
++ snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
+ jack_log("Bind: fName %s", fName);
+
+ if ((fNamedPipe = CreateNamedPipe(fName,
+@@ -322,7 +322,7 @@
+
+ int JackWinAsyncNamedPipeServer::Bind(const char* dir, int which)
+ {
+- sprintf(fName, "\\\\.\\pipe\\%s_jack_%d", dir, which);
++ snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%d", dir, which);
+ jack_log("Bind: fName %s", fName);
+
+ if ((fNamedPipe = CreateNamedPipe(fName,
+@@ -344,7 +344,7 @@
+
+ int JackWinAsyncNamedPipeServer::Bind(const char* dir, const char* name, int which)
+ {
+- sprintf(fName, "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
++ snprintf(fName, sizeof(fName), "\\\\.\\pipe\\%s_jack_%s_%d", dir, name, which);
+ jack_log("Bind: fName %s", fName);
+
+ if ((fNamedPipe = CreateNamedPipe(fName,
+--- a/windows/JackWinNamedPipeServerChannel.cpp
++++ b/windows/JackWinNamedPipeServerChannel.cpp
+@@ -71,7 +71,7 @@
+ /*
+ TODO : solve WIN32 thread Kill issue
+ This would hang.. since Close will be followed by a delete,
+- all ressources will be desallocated at the end.
++ all ressources will be deallocated at the end.
+ */
+
+ fThread.Kill();
+@@ -85,7 +85,7 @@
+ jack_log("JackClientPipeThread::Execute");
+ return (HandleRequest());
+ } catch (JackQuitException& e) {
+- jack_log("JackMachServerChannel::Execute JackQuitException");
++ jack_log("JackClientPipeThread::Execute JackQuitException");
+ return false;
+ }
+ }
+@@ -117,6 +117,9 @@
+ if (req.Read(fPipe) == 0)
+ res.fResult = fServer->GetEngine()->ClientCheck(req.fName, req.fUUID, res.fName, req.fProtocol, req.fOptions, &res.fStatus);
+ res.Write(fPipe);
++ // Atomic ClientCheck followed by ClientOpen on same pipe
++ if (req.fOpen)
++ HandleRequest();
+ break;
+ }
+
+@@ -339,11 +342,9 @@
+ case JackRequest::kSessionNotify: {
+ jack_log("JackRequest::SessionNotify");
+ JackSessionNotifyRequest req;
+- JackSessionNotifyResult res;
+ if (req.Read(fPipe) == 0) {
+- fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe);
++ fServer->GetEngine()->SessionNotify(req.fRefNum, req.fDst, req.fEventType, req.fPath, fPipe, NULL);
+ }
+- res.Write(fPipe);
+ break;
+ }
+
+@@ -397,7 +398,7 @@
+ JackClientHasSessionCallbackRequest req;
+ JackResult res;
+ if (req.Read(fPipe) == 0) {
+- fServer->GetEngine()->ClientHasSessionCallbackRequest(req.fName, &res.fResult);
++ fServer->GetEngine()->ClientHasSessionCallback(req.fName, &res.fResult);
+ }
+ res.Write(fPipe);
+ break;
+@@ -478,14 +479,13 @@
+ void JackWinNamedPipeServerChannel::Close()
+ {
+ /* TODO : solve WIN32 thread Kill issue
+- This would hang the server... since we are quitting it, its not really problematic,
+- all ressources will be desallocated at the end.
++ This would hang the server... since we are quitting it, its not really problematic,
++ all ressources will be deallocated at the end.
+
+- fRequestListenPipe.Close();
+- fThread.Stop();
++ fRequestListenPipe.Close();
++ fThread.Stop();
+ */
+
+- fThread.Kill();
+ fRequestListenPipe.Close();
+ }
+
+@@ -494,9 +494,14 @@
+ if (fThread.Start() != 0) {
+ jack_error("Cannot start Jack server listener");
+ return -1;
++ } else {
++ return 0;
+ }
++}
+
+- return 0;
++void JackWinNamedPipeServerChannel::Stop()
++{
++ fThread.Kill();
+ }
+
+ bool JackWinNamedPipeServerChannel::Init()
+--- a/windows/JackWinNamedPipeServerChannel.h
++++ b/windows/JackWinNamedPipeServerChannel.h
+@@ -93,6 +93,7 @@
+ void Close(); // Close the Server/Client connection
+
+ int Start();
++ void Stop();
+
+ // JackRunnableInterface interface
+ bool Init();
+--- a/windows/JackWinSemaphore.cpp
++++ b/windows/JackWinSemaphore.cpp
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+ #include "JackWinSemaphore.h"
+@@ -26,11 +26,11 @@
+ namespace Jack
+ {
+
+-void JackWinSemaphore::BuildName(const char* client_name, const char* server_name, char* res)
++void JackWinSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
+ {
+ char ext_client_name[JACK_CLIENT_NAME_SIZE + 1];
+ JackTools::RewriteName(client_name, ext_client_name);
+- sprintf(res, "jack_pipe.%s_%s", server_name, ext_client_name);
++ _snprintf(res, size, "jack_pipe.%s_%s", server_name, ext_client_name);
+ }
+
+ bool JackWinSemaphore::Signal()
+@@ -88,7 +88,7 @@
+ // Client side : get the published semaphore from server
+ bool JackWinSemaphore::ConnectInput(const char* name, const char* server_name)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ jack_log("JackWinSemaphore::Connect %s", fName);
+
+ // Temporary...
+@@ -129,7 +129,7 @@
+
+ bool JackWinSemaphore::Allocate(const char* name, const char* server_name, int value)
+ {
+- BuildName(name, server_name, fName);
++ BuildName(name, server_name, fName, sizeof(fName));
+ jack_log("JackWinSemaphore::Allocate name = %s val = %ld", fName, value);
+
+ if ((fSemaphore = CreateSemaphore(NULL, value, 32767, fName)) == NULL) {
+@@ -137,7 +137,7 @@
+ return false;
+ } else if (GetLastError() == ERROR_ALREADY_EXISTS) {
+ jack_error("Allocate: named semaphore already exist name = %s", fName);
+- // Try to open it
++ // Try to open it
+ fSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, fName);
+ return (fSemaphore != NULL);
+ } else {
+@@ -158,4 +158,3 @@
+
+
+ } // end of namespace
+-
+--- a/windows/JackWinSemaphore.h
++++ b/windows/JackWinSemaphore.h
+@@ -1,20 +1,20 @@
+ /*
+ Copyright (C) 2004-2008 Grame
+-
++
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
+-
++
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+-
++
+ */
+
+
+@@ -41,7 +41,7 @@
+
+ protected:
+
+- void BuildName(const char* name, const char* server_name, char* res);
++ void BuildName(const char* name, const char* server_name, char* res, int size);
+
+ public:
+
+--- a/windows/JackWinServerLaunch.cpp
++++ b/windows/JackWinServerLaunch.cpp
+@@ -1,6 +1,7 @@
+ /*
+ Copyright (C) 2001-2003 Paul Davis
+ Copyright (C) 2004-2008 Grame
++Copyright (C) 2011 John Emmas
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+@@ -18,9 +19,299 @@
+
+ */
+
++#include "JackChannel.h"
++#include "JackLibGlobals.h"
+ #include "JackServerLaunch.h"
++#include "JackPlatformPlug.h"
++
++using namespace Jack;
++
++#include <shlobj.h>
++#include <process.h>
++#include <string.h>
++#include <fcntl.h>
++#include <io.h>
++
++#if defined(_MSC_VER) || defined(__MINGW__) || defined(__MINGW32__)
++
++static char*
++find_path_to_jackdrc(char *path_to_jackdrc)
++{
++ char user_jackdrc[1024];
++ char *ptr = NULL;
++ char *ret = NULL;
++
++ user_jackdrc[0] = user_jackdrc[1] = 0; // Initialise
++
++ if (S_OK == SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, user_jackdrc))
++ {
++ // The above call should have given us the path to the user's home folder
++ char ch = user_jackdrc[strlen(user_jackdrc)-1];
++
++ if (('/' != ch) && ('\\' != ch))
++ strcat(user_jackdrc, "\\");
++
++ if (user_jackdrc[1] == ':')
++ {
++ // Assume we have a valid path
++ strcat(user_jackdrc, ".jackdrc");
++ strcpy(path_to_jackdrc, user_jackdrc);
++
++ ret = path_to_jackdrc;
++ }
++ else
++ path_to_jackdrc[0] = '\0';
++ }
++ else
++ path_to_jackdrc[0] = '\0';
++
++ return (ret);
++}
++
++#else
++
++static char*
++find_path_to_jackdrc(char *path_to_jackdrc)
++{
++ return 0;
++}
++
++#endif
++
++/* 'start_server_aux()' - this function might need to be modified (though probably
++ * not) to cope with compilers other than MSVC (e.g. MinGW). The function
++ * 'find_path_to_jackdrc()' might also need to be written for MinGW, though for
++ * Cygwin, JackPosixServerLaunch.cpp can be used instead of this file.
++ */
++
++#include <direct.h>
++
++static int start_server_aux(const char* server_name)
++{
++ FILE* fp = 0;
++ size_t pos = 0;
++ size_t result = 0;
++ int i = 0;
++ int good = 0;
++ int ret = 0;
++ char* command = 0;
++ char** argv = 0;
++ char* p;
++ char* back_slash;
++ char* forward_slash;
++ char arguments [256];
++ char buffer [MAX_PATH];
++ char filename [MAX_PATH];
++ char curr_wd [MAX_PATH];
++ char temp_wd [MAX_PATH];
++
++ curr_wd[0] = '\0';
++ if (find_path_to_jackdrc(filename))
++ fp = fopen(filename, "r");
++
++ /* if still not found, check old config name for backwards compatability */
++ /* JE - hopefully won't be needed for the Windows build
++ if (!fp) {
++ fp = fopen("/etc/jackd.conf", "r");
++ }
++ */
++
++ if (fp) {
++ arguments[0] = '\0';
++
++ fgets(filename, MAX_PATH, fp);
++ _strlwr(filename);
++ if (p = strstr(filename, ".exe")) {
++ p += 4;
++ *p = '\0';
++ pos = (size_t)(p - filename);
++ fseek(fp, 0, SEEK_SET);
++
++ if (command = (char*)malloc(pos+1))
++ ret = fread(command, 1, pos, fp);
++
++ if (ret && !ferror(fp)) {
++ command[pos] = '\0'; // NULL terminator
++ back_slash = strrchr(command, '\\');
++ forward_slash = strrchr(command, '/');
++ if (back_slash > forward_slash)
++ p = back_slash + 1;
++ else
++ p = forward_slash + 1;
++
++ strcpy(buffer, p);
++ while (ret != 0 && ret != EOF) {
++ strcat(arguments, buffer);
++ strcat(arguments, " ");
++ ret = fscanf(fp, "%s", buffer);
++ }
++
++ if (strlen(arguments) > 0) {
++ good = 1;
++ }
++ }
++ }
++
++ fclose(fp);
++ }
++
++ if (!good) {
++ strcpy(buffer, JACK_LOCATION "/jackd.exe");
++ command = (char*)malloc((strlen(buffer))+1);
++ strcpy(command, buffer);
++ strncpy(arguments, "jackd.exe -S -d " JACK_DEFAULT_DRIVER, 255);
++ }
++
++ int buffer_termination;
++ bool verbose_mode = false;
++ argv = (char**)malloc(255);
++ pos = 0;
++
++ while (1) {
++ /* insert -T and -n server_name in front of arguments */
++ if (i == 1) {
++ argv[i] = (char*)malloc(strlen ("-T") + 1);
++ strcpy (argv[i++], "-T");
++ if (server_name) {
++ size_t optlen = strlen("-n");
++ char* buf = (char*)malloc(optlen + strlen(server_name) + 1);
++ strcpy(buf, "-n");
++ strcpy(buf + optlen, server_name);
++ argv[i++] = buf;
++ }
++ }
++
++ // Only get the next character if there's more than 1 character
++ if ((pos < strlen(arguments)) && (arguments[pos+1]) && (arguments[pos+1] != ' ')) {
++ strncpy(buffer, arguments + pos++, 1);
++ buffer_termination = 1;
++ } else {
++ buffer[0] = '\0';
++ buffer_termination = 0;
++ }
++
++ buffer[1] = '\0';
++ if (buffer[0] == '\"')
++ result = strcspn(arguments + pos, "\"");
++ else
++ result = strcspn(arguments + pos, " ");
++
++ if (0 == result)
++ break;
++ else
++ {
++ strcat(buffer, arguments + pos);
++
++ // Terminate the buffer
++ buffer[result + buffer_termination] = '\0';
++ if (buffer[0] == '\"') {
++ strcat(buffer, "\"");
++ ++result;
++ }
++
++ argv[i] = (char*)malloc(strlen(buffer) + 1);
++ strcpy(argv[i], buffer);
++ pos += (result + 1);
++ ++i;
++
++ if ((0 == strcmp(buffer, "-v")) || (0 == strcmp(buffer, "--verbose")))
++ verbose_mode = true;
++ }
++ }
++
++ argv[i] = 0;
++
++#ifdef SUPPORT_PRE_1_9_8_SERVER
++ // Get the current working directory
++ if (_getcwd(curr_wd, MAX_PATH)) {
++ strcpy(temp_wd, command);
++ back_slash = strrchr(temp_wd, '\\');
++ forward_slash = strrchr(temp_wd, '/');
++ if (back_slash > forward_slash)
++ p = back_slash;
++ else
++ p = forward_slash;
++ *p = '\0';
++
++ // Accommodate older versions of Jack (pre v1.9.8) which
++ // might need to be started from their installation folder.
++ _chdir(temp_wd);
++ }
++#endif
++
++ if (verbose_mode) {
++ // Launch the server with a console... (note that
++ // if the client is a console app, the server might
++ // also use the client's console)
++ ret = _spawnv(_P_NOWAIT, command, argv);
++ } else {
++ // Launch the server silently... (without a console)
++ ret = _spawnv(_P_DETACH, command, argv);
++ }
++
++ Sleep(2500); // Give it some time to launch
++
++ if ((-1) == ret)
++ fprintf(stderr, "Execution of JACK server (command = \"%s\") failed: %s\n", command, strerror(errno));
++
++ if (strlen(curr_wd)) {
++ // Change the cwd back to its original setting
++ _chdir(curr_wd);
++ }
++
++ if (command)
++ free(command);
++
++ if (argv) {
++ for (i = 0; argv[i] != 0; i++)
++ free (argv[i]);
++
++ free(argv);
++ }
++
++ return (ret == (-1) ? false : true);
++}
++
++static int start_server(const char* server_name, jack_options_t options)
++{
++ if ((options & JackNoStartServer) || getenv("JACK_NO_START_SERVER")) {
++ return 1;
++ }
++
++ return (((-1) != (start_server_aux(server_name)) ? 0 : (-1)));
++}
++
++static int server_connect(const char* server_name)
++{
++ JackClientChannel channel;
++ int res = channel.ServerCheck(server_name);
++ channel.Close();
++ JackSleep(2000); // Added by JE - 02-01-2009 (gives
++ // the channel some time to close)
++ return res;
++}
+
+ int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status)
+ {
+- return 0;
++ if (server_connect(va->server_name) < 0) {
++ int trys;
++ if (start_server(va->server_name, options)) {
++ int my_status1 = *status | JackFailure | JackServerFailed;
++ *status = (jack_status_t)my_status1;
++ return -1;
++ }
++ trys = 5;
++ do {
++ Sleep(1000);
++ if (--trys < 0) {
++ int my_status1 = *status | JackFailure | JackServerFailed;
++ *status = (jack_status_t)my_status1;
++ return -1;
++ }
++ } while (server_connect(va->server_name) < 0);
++ int my_status1 = *status | JackServerStarted;
++ *status = (jack_status_t)my_status1;
++ }
++
++ return 0;
+ }
+--- a/windows/JackWinThread.cpp
++++ b/windows/JackWinThread.cpp
+@@ -17,11 +17,11 @@
+
+ */
+
+-
+ #include "JackWinThread.h"
+ #include "JackError.h"
+ #include "JackTime.h"
+ #include <assert.h>
++#include <stdio.h>
+
+ namespace Jack
+ {
+@@ -55,7 +55,7 @@
+ }
+
+ JackWinThread::JackWinThread(JackRunnableInterface* runnable)
+- : JackThreadInterface(runnable, 0, false, 0)
++ : JackMMCSS(), JackThreadInterface(runnable, 0, false, 0)
+ {
+ fEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+ fThread = (HANDLE)NULL;
+@@ -200,13 +200,19 @@
+
+ int JackWinThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority)
+ {
+- jack_log("JackWinThread::AcquireRealTime");
++ jack_log("JackWinThread::AcquireRealTimeImp priority = %d", priority);
+
+- if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) {
++ if (priority >= 90 && MMCSSAcquireRealTime(thread) == 0) {
++ jack_info("MMCSS API used to acquire RT for thread");
+ return 0;
+ } else {
+- jack_error("Cannot set thread priority = %d", GetLastError());
+- return -1;
++ jack_info("MMCSS API not used...");
++ if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) {
++ return 0;
++ } else {
++ jack_error("Cannot set thread priority = %d", GetLastError());
++ return -1;
++ }
+ }
+ }
+
+@@ -222,7 +228,10 @@
+
+ int JackWinThread::DropRealTimeImp(jack_native_thread_t thread)
+ {
+- if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) {
++ if (MMCSSDropRealTime(thread) == 0 ) {
++ jack_info("MMCSS API used to drop RT for thread");
++ return 0;
++ } else if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) {
+ return 0;
+ } else {
+ jack_error("Cannot set thread priority = %d", GetLastError());
+--- a/windows/JackWinThread.h
++++ b/windows/JackWinThread.h
+@@ -17,12 +17,11 @@
+
+ */
+
+-
+-
+ #ifndef __JackWinThread__
+ #define __JackWinThread__
+
+ #include "JackThread.h"
++#include "JackMMCSS.h"
+ #include "JackCompilerDeps.h"
+ #include "JackSystemDeps.h"
+ #include <windows.h>
+@@ -36,7 +35,7 @@
+ \brief Windows threads.
+ */
+
+-class SERVER_EXPORT JackWinThread : public detail::JackThreadInterface
++class SERVER_EXPORT JackWinThread : public JackMMCSS, public detail::JackThreadInterface
+ {
+
+ private:
+--- a/windows/libjack.cbp
++++ b/windows/libjack.cbp
+@@ -4,18 +4,152 @@
+ <Project>
+ <Option title="libjack" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\libjack64" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DHAVE_CONFIG_H" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="tre-0.8.0\win32" />
++ <Add directory="tre-0.8.0\lib" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ <Add library="psapi" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\libjack64" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DHAVE_CONFIG_H" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="tre-0.8.0\win32" />
++ <Add directory="tre-0.8.0\lib" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ <Add library="psapi" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\libjack64" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DHAVE_CONFIG_H" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="tre-0.8.0\win32" />
++ <Add directory="tre-0.8.0\lib" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ <Add library="psapi" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\libjack" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -25,6 +159,7 @@
+ <Add option="-DREGEX_MALLOC" />
+ <Add option="-DSTDC_HEADERS" />
+ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
+ <Add option="-DHAVE_CONFIG_H" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+@@ -34,6 +169,7 @@
+ <Add directory="tre-0.8.0\lib" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add library="kernel32" />
+ <Add library="user32" />
+ <Add library="gdi32" />
+@@ -46,27 +182,33 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
++ <Add library="psapi" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\libjack" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-D_DEBUG" />
+- <Add option="-D_WINDOWS" />
++ <Add option="-D_CONSOLE" />
+ <Add option="-D_MBCS" />
+ <Add option="-D_USRDLL" />
+ <Add option="-DLIBJACKMP_EXPORTS" />
+ <Add option="-DREGEX_MALLOC" />
+ <Add option="-DSTDC_HEADERS" />
+ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
+ <Add option="-DHAVE_CONFIG_H" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+@@ -76,6 +218,7 @@
+ <Add directory="tre-0.8.0\lib" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add library="kernel32" />
+ <Add library="user32" />
+ <Add library="gdi32" />
+@@ -88,18 +231,23 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
++ <Add library="psapi" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/libjack.res libjack.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\libjack" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -109,6 +257,7 @@
+ <Add option="-DREGEX_MALLOC" />
+ <Add option="-DSTDC_HEADERS" />
+ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DHAVE_CONFIG_H" />
+ <Add directory="." />
+@@ -119,6 +268,7 @@
+ <Add directory="tre-0.8.0\lib" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
+ <Add library="kernel32" />
+ <Add library="user32" />
+ <Add library="gdi32" />
+@@ -131,7 +281,11 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
++ <Add library="psapi" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -180,6 +334,7 @@
+ <Unit filename="..\common\shm.c">
+ <Option compilerVar="CC" />
+ </Unit>
++ <Unit filename="JackMMCSS.cpp" />
+ <Unit filename="JackWinNamedPipe.cpp" />
+ <Unit filename="JackWinNamedPipeClientChannel.cpp" />
+ <Unit filename="JackWinProcessSync.cpp" />
+--- /dev/null
++++ b/windows/libjacknet.cbp
+@@ -0,0 +1,264 @@
++<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
++<CodeBlocks_project_file>
++ <FileVersion major="1" minor="6" />
++ <Project>
++ <Option title="libjacknet" />
++ <Option pch_mode="2" />
++ <Option compiler="gcc" />
++ <Build>
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\libjacknet" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="gcc" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\libjacknet" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64" />
++ <Option type="3" />
++ <Option compiler="gcc" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Debug64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\libjacknet" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="gcc" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add library="libsamplerate_x86_64" />
++ <Add directory="Release64\bin" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
++ <Option output="Release\bin\libjacknet" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release" />
++ <Option type="3" />
++ <Option compiler="gcc" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libsamplerate_x86" />
++ <Add directory="Release\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" />
++ </ExtraCommands>
++ </Target>
++ <Target title="Win32 Debug 32bits">
++ <Option output="Debug\bin\libjacknet" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug" />
++ <Option type="3" />
++ <Option compiler="gcc" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-m32" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libsamplerate_x86" />
++ <Add directory="Debug\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/libjacknet.res libjacknet.rc" />
++ </ExtraCommands>
++ </Target>
++ <Target title="Win32 Profiling 32bits">
++ <Option output="Release\bin\libjacknet" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release" />
++ <Option type="3" />
++ <Option compiler="gcc" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-m32" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add option="-m32" />
++ <Add library="libsamplerate_x86" />
++ <Add directory="Release\bin" />
++ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" />
++ </ExtraCommands>
++ </Target>
++ </Build>
++ <Compiler>
++ <Add option="-Wall" />
++ <Add directory="." />
++ <Add directory="..\common" />
++ <Add directory="..\common\jack" />
++ </Compiler>
++ <Linker>
++ <Add library="kernel32" />
++ <Add library="user32" />
++ <Add library="gdi32" />
++ <Add library="winspool" />
++ <Add library="comdlg32" />
++ <Add library="advapi32" />
++ <Add library="shell32" />
++ <Add library="ole32" />
++ <Add library="oleaut32" />
++ <Add library="uuid" />
++ <Add library="odbc32" />
++ <Add library="odbccp32" />
++ <Add library="ws2_32" />
++ </Linker>
++ <Unit filename="..\common\JackAudioAdapterInterface.cpp" />
++ <Unit filename="..\common\JackGlobals.cpp" />
++ <Unit filename="..\common\JackLibSampleRateResampler.cpp" />
++ <Unit filename="..\common\JackNetAPI.cpp" />
++ <Unit filename="..\common\JackNetInterface.cpp" />
++ <Unit filename="..\common\JackNetTool.cpp" />
++ <Unit filename="..\common\JackResampler.cpp" />
++ <Unit filename="..\common\ringbuffer.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Unit filename="JackMMCSS.cpp" />
++ <Unit filename="JackNetWinSocket.cpp" />
++ <Unit filename="JackWinThread.cpp" />
++ <Unit filename="JackWinTime.c">
++ <Option compilerVar="CC" />
++ </Unit>
++ <Unit filename="libjacknet.rc">
++ <Option compilerVar="WINDRES" />
++ </Unit>
++ <Extensions>
++ <code_completion />
++ <envvars />
++ <debugger />
++ <AutoVersioning>
++ <Scheme minor_max="10" build_max="0" rev_max="0" rev_rand_max="10" build_times_to_increment_minor="100" />
++ <Settings autoincrement="0" date_declarations="0" do_auto_increment="0" ask_to_increment="0" language="C++" svn="0" svn_directory="" header_path="version.h" />
++ <Changes_Log show_changes_editor="0" app_title="released version %M.%m.%b of %p" changeslog_path="ChangesLog.txt" />
++ </AutoVersioning>
++ </Extensions>
++ </Project>
++</CodeBlocks_project_file>
+--- /dev/null
++++ b/windows/libjacknet.rc
+@@ -0,0 +1,41 @@
++// Generated by ResEdit 1.4.3
++// Copyright (C) 2006-2008
++// http://www.resedit.net
++
++#include "resource.h"
++#include "afxres.h"
++
++
++//
++// Version Information resources
++//
++LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT
++1 VERSIONINFO
++ FILEVERSION 1,9,8,0
++ PRODUCTVERSION 1,9,8,0
++ FILEOS VOS_UNKNOWN
++ FILETYPE VFT_DLL
++BEGIN
++ BLOCK "StringFileInfo"
++ BEGIN
++ BLOCK "040c04b0"
++ BEGIN
++ VALUE "Comments", "\0"
++ VALUE "CompanyName", "Grame\0"
++ VALUE "FileDescription", "Jack Net library for Windows\0"
++ VALUE "FileVersion", "1, 9, 8, 0\0"
++ VALUE "InternalName", "libjacknet\0"
++ VALUE "LegalCopyright", "Copyright Grame © 2006-2011\0"
++ VALUE "LegalTrademarks", "\0"
++ VALUE "OriginalFilename", "libjacknet.dll\0"
++ VALUE "PrivateBuild", "\0"
++ VALUE "ProductName", "libjacknet\0"
++ VALUE "ProductVersion", "1, 9, 8, 0\0"
++ VALUE "SpecialBuild", "\0"
++ END
++ END
++ BLOCK "VarFileInfo"
++ BEGIN
++ VALUE "Translation", 1036, 1200
++ END
++END
+--- a/windows/libjackserver.cbp
++++ b/windows/libjackserver.cbp
+@@ -4,18 +4,122 @@
+ <Project>
+ <Option title="libjackserver" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\libjackserver64" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DHAVE_CONFIG_H" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="tre-0.8.0\win32" />
++ <Add directory="tre-0.8.0\lib" />
++ </Compiler>
++ <Linker>
++ <Add library="psapi" />
++ <Add directory="Release\bin64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\libjackserver64" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-Wall" />
++ <Add option="-g" />
++ <Add option="-DWIN32" />
++ <Add option="-D_DEBUG" />
++ <Add option="-D_CONSOLE" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DHAVE_CONFIG_H" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="tre-0.8.0\win32" />
++ <Add directory="tre-0.8.0\lib" />
++ </Compiler>
++ <Linker>
++ <Add library="psapi" />
++ <Add directory="Debug\bin64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\libjackserver64" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64" />
++ <Option type="3" />
++ <Option compiler="mingw_64" />
++ <Option createDefFile="1" />
++ <Option createStaticLib="1" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DWIN32" />
++ <Add option="-DNDEBUG" />
++ <Add option="-D_WINDOWS" />
++ <Add option="-D_MBCS" />
++ <Add option="-D_USRDLL" />
++ <Add option="-DLIBJACKDMP_EXPORTS" />
++ <Add option="-DREGEX_MALLOC" />
++ <Add option="-DSTDC_HEADERS" />
++ <Add option="-DSERVER_SIDE" />
++ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
++ <Add option="-DJACK_MONITOR" />
++ <Add option="-DHAVE_CONFIG_H" />
++ <Add directory="." />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ <Add directory="tre-0.8.0\win32" />
++ <Add directory="tre-0.8.0\lib" />
++ </Compiler>
++ <Linker>
++ <Add library="psapi" />
++ <Add directory="Release\bin64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\libjackserver" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -26,6 +130,7 @@
+ <Add option="-DSTDC_HEADERS" />
+ <Add option="-DSERVER_SIDE" />
+ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
+ <Add option="-DHAVE_CONFIG_H" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+@@ -35,22 +140,28 @@
+ <Add directory="tre-0.8.0\lib" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="psapi" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/libjackserver.res libjackserver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\libjackserver" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-Wall" />
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-D_DEBUG" />
+- <Add option="-D_WINDOWS" />
++ <Add option="-D_CONSOLE" />
+ <Add option="-D_MBCS" />
+ <Add option="-D_USRDLL" />
+ <Add option="-DLIBJACKDMP_EXPORTS" />
+@@ -58,6 +169,7 @@
+ <Add option="-DSTDC_HEADERS" />
+ <Add option="-DSERVER_SIDE" />
+ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
+ <Add option="-DHAVE_CONFIG_H" />
+ <Add directory="." />
+ <Add directory="..\windows" />
+@@ -67,19 +179,25 @@
+ <Add directory="tre-0.8.0\lib" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="psapi" />
+ <Add directory="Debug\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Debug/libjackserver.res libjackserver.rc" />
++ </ExtraCommands>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\libjackserver" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release" />
+ <Option type="3" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Option createDefFile="1" />
+ <Option createStaticLib="1" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DWIN32" />
+ <Add option="-DNDEBUG" />
+ <Add option="-D_WINDOWS" />
+@@ -90,6 +208,7 @@
+ <Add option="-DSTDC_HEADERS" />
+ <Add option="-DSERVER_SIDE" />
+ <Add option="-D__SMP__" />
++ <Add option="-DJACK_32_64" />
+ <Add option="-DJACK_MONITOR" />
+ <Add option="-DHAVE_CONFIG_H" />
+ <Add directory="." />
+@@ -100,8 +219,13 @@
+ <Add directory="tre-0.8.0\lib" />
+ </Compiler>
+ <Linker>
++ <Add option="-m32" />
++ <Add library="psapi" />
+ <Add directory="Release\bin" />
+ </Linker>
++ <ExtraCommands>
++ <Add before="windres -F pe-i386 -O coff -o Release/libjackserver.res libjackserver.rc" />
++ </ExtraCommands>
+ </Target>
+ </Build>
+ <Compiler>
+@@ -150,12 +274,16 @@
+ <Unit filename="..\common\JackLoopbackDriver.cpp" />
+ <Unit filename="..\common\JackMessageBuffer.cpp" />
+ <Unit filename="..\common\JackMidiAPI.cpp" />
++ <Unit filename="..\common\JackMidiAsyncQueue.cpp" />
++ <Unit filename="..\common\JackMidiBufferReadQueue.cpp" />
++ <Unit filename="..\common\JackMidiBufferWriteQueue.cpp" />
+ <Unit filename="..\common\JackMidiDriver.cpp" />
+ <Unit filename="..\common\JackMidiPort.cpp" />
++ <Unit filename="..\common\JackMidiReadQueue.cpp" />
++ <Unit filename="..\common\JackMidiUtil.cpp" />
++ <Unit filename="..\common\JackMidiWriteQueue.cpp" />
+ <Unit filename="..\common\JackNetInterface.cpp" />
+ <Unit filename="..\common\JackNetTool.cpp" />
+- <Unit filename="..\common\JackPhysicalMidiInput.cpp" />
+- <Unit filename="..\common\JackPhysicalMidiOutput.cpp" />
+ <Unit filename="..\common\JackPort.cpp" />
+ <Unit filename="..\common\JackPortType.cpp" />
+ <Unit filename="..\common\JackRestartThreadedDriver.cpp" />
+@@ -164,6 +292,7 @@
+ <Unit filename="..\common\JackServerGlobals.cpp" />
+ <Unit filename="..\common\JackShmMem.cpp" />
+ <Unit filename="..\common\JackThreadedDriver.cpp" />
++ <Unit filename="..\common\JackTimedDriver.cpp" />
+ <Unit filename="..\common\JackTools.cpp" />
+ <Unit filename="..\common\JackTransportEngine.cpp" />
+ <Unit filename="..\common\JackWaitThreadedDriver.cpp" />
+@@ -173,6 +302,7 @@
+ <Unit filename="..\common\shm.c">
+ <Option compilerVar="CC" />
+ </Unit>
++ <Unit filename="JackMMCSS.cpp" />
+ <Unit filename="JackNetWinSocket.cpp" />
+ <Unit filename="JackWinNamedPipe.cpp" />
+ <Unit filename="JackWinNamedPipeClientChannel.cpp" />
+--- a/windows/multiple_metro.cbp
++++ b/windows/multiple_metro.cbp
+@@ -4,16 +4,71 @@
+ <Project>
+ <Option title="multiple_metro" />
+ <Option pch_mode="2" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Build>
+- <Target title="Win32 Release">
++ <Target title="Win32 Release 64bits">
++ <Option output="Release64\bin\multiple_metro" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add directory="..\example-clients" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Debug 64bits">
++ <Option output="Debug64\bin\multiple_metro" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Debug64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-g" />
++ <Add directory="..\tests" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Debug64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Profiling 64bits">
++ <Option output="Release64\bin\multiple_metro" prefix_auto="1" extension_auto="1" />
++ <Option object_output="Release64\" />
++ <Option type="1" />
++ <Option compiler="mingw_64" />
++ <Compiler>
++ <Add option="-O2" />
++ <Add option="-Wall" />
++ <Add option="-DJACK_MONITOR" />
++ <Add directory="..\tests" />
++ <Add directory="..\windows" />
++ <Add directory="..\common\jack" />
++ <Add directory="..\common" />
++ </Compiler>
++ <Linker>
++ <Add directory="Release64\bin" />
++ <Add library="libjack64" />
++ </Linker>
++ </Target>
++ <Target title="Win32 Release 32bits">
+ <Option output="Release\bin\multiple_metro" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add directory="..\example-clients" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -21,15 +76,18 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Debug">
++ <Target title="Win32 Debug 32bits">
+ <Option output="Debug\bin\multiple_metro" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Debug\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-g" />
++ <Add option="-m32" />
+ <Add directory="..\tests" />
+ <Add directory="..\windows" />
+ <Add directory="..\common\jack" />
+@@ -37,16 +95,19 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Debug\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+- <Target title="Win32 Profiling">
++ <Target title="Win32 Profiling 32bits">
+ <Option output="Release\bin\multiple_metro" prefix_auto="1" extension_auto="1" />
+ <Option object_output="Release\" />
+ <Option type="1" />
+- <Option compiler="gcc" />
++ <Option compiler="mingw_64" />
+ <Compiler>
+ <Add option="-O2" />
+ <Add option="-Wall" />
++ <Add option="-m32" />
+ <Add option="-DJACK_MONITOR" />
+ <Add directory="..\tests" />
+ <Add directory="..\windows" />
+@@ -55,6 +116,8 @@
+ </Compiler>
+ <Linker>
+ <Add directory="Release\bin" />
++ <Add option="-m32" />
++ <Add library="libjack" />
+ </Linker>
+ </Target>
+ </Build>
+@@ -74,7 +137,6 @@
+ <Add library="uuid" />
+ <Add library="odbc32" />
+ <Add library="odbccp32" />
+- <Add library="libjack" />
+ </Linker>
+ <Unit filename="..\tests\external_metro.cpp">
+ <Option compilerVar="CC" />
+--- a/windows/portaudio/JackPortAudioAdapter.cpp
++++ b/windows/portaudio/JackPortAudioAdapter.cpp
+@@ -17,10 +17,6 @@
+
+ */
+
+-#if defined(HAVE_CONFIG_H)
+-#include "config.h"
+-#endif
+-
+ #include "JackPortAudioAdapter.h"
+ #include "JackError.h"
+
+@@ -39,10 +35,10 @@
+ return paContinue;
+ }
+
+- JackPortAudioAdapter::JackPortAudioAdapter ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params )
+- : JackAudioAdapterInterface ( buffer_size, sample_rate )
++ JackPortAudioAdapter::JackPortAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
++ : JackAudioAdapterInterface(buffer_size, sample_rate)
+ {
+- jack_log ( "JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate );
++ jack_log("JackPortAudioAdapter::JackPortAudioAdapter buffer_size = %d, sample_rate = %d", buffer_size, sample_rate);
+
+ const JSList* node;
+ const jack_driver_param_t* param;
+@@ -52,8 +48,7 @@
+ fInputDevice = Pa_GetDefaultInputDevice();
+ fOutputDevice = Pa_GetDefaultOutputDevice();
+
+- for (node = params; node; node = jack_slist_next(node))
+- {
++ for (node = params; node; node = jack_slist_next(node)) {
+ param = (const jack_driver_param_t*) node->data;
+
+ switch (param->character)
+@@ -65,30 +60,28 @@
+ fPlaybackChannels = param->value.ui;
+ break;
+ case 'C' :
+- if ( fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0 )
+- {
+- jack_error ( "Can't use %s, taking default input device", param->value.str );
++ if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0) {
++ jack_error("Can't use %s, taking default input device", param->value.str);
+ fInputDevice = Pa_GetDefaultInputDevice();
+ }
+ break;
+ case 'P' :
+- if ( fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0 )
+- {
+- jack_error ( "Can't use %s, taking default output device", param->value.str );
++ if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0) {
++ jack_error("Can't use %s, taking default output device", param->value.str);
+ fOutputDevice = Pa_GetDefaultOutputDevice();
+ }
+ break;
+ case 'r' :
+- SetAdaptedSampleRate ( param->value.ui );
++ SetAdaptedSampleRate(param->value.ui);
+ break;
+ case 'p' :
+- SetAdaptedBufferSize ( param->value.ui );
++ SetAdaptedBufferSize(param->value.ui);
+ break;
+ case 'd' :
+- if ( fPaDevices.GetInputDeviceFromName ( param->value.str, fInputDevice, in_max ) < 0 )
+- jack_error ( "Can't use %s, taking default input device", param->value.str );
+- if ( fPaDevices.GetOutputDeviceFromName ( param->value.str, fOutputDevice, out_max ) < 0 )
+- jack_error ( "Can't use %s, taking default output device", param->value.str );
++ if (fPaDevices.GetInputDeviceFromName(param->value.str, fInputDevice, in_max) < 0)
++ jack_error("Can't use %s, taking default input device", param->value.str);
++ if (fPaDevices.GetOutputDeviceFromName(param->value.str, fOutputDevice, out_max) < 0)
++ jack_error("Can't use %s, taking default output device", param->value.str);
+ break;
+ case 'l' :
+ fPaDevices.DisplayDevicesNames();
+@@ -104,20 +97,20 @@
+ }
+
+ //max channels
+- if ( in_max == 0 )
+- in_max = fPaDevices.GetDeviceInfo ( fInputDevice )->maxInputChannels;
+- if ( out_max == 0 )
+- out_max = fPaDevices.GetDeviceInfo ( fOutputDevice )->maxOutputChannels;
++ if (in_max == 0 && fInputDevice != paNoDevice)
++ in_max = fPaDevices.GetDeviceInfo(fInputDevice)->maxInputChannels;
++ if (out_max == 0 && fOutputDevice != paNoDevice)
++ out_max = fPaDevices.GetDeviceInfo(fOutputDevice)->maxOutputChannels;
+
+ //effective channels
+- if ( ( fCaptureChannels == 0 ) || ( fCaptureChannels > in_max ) )
++ if ((fCaptureChannels == 0) || (fCaptureChannels > in_max))
+ fCaptureChannels = in_max;
+- if ( ( fPlaybackChannels == 0 ) || ( fPlaybackChannels > out_max ) )
++ if ((fPlaybackChannels == 0) || (fPlaybackChannels > out_max))
+ fPlaybackChannels = out_max;
+
+ //set adapter interface channels
+- SetInputs ( fCaptureChannels );
+- SetOutputs ( fPlaybackChannels );
++ SetInputs(fCaptureChannels);
++ SetOutputs(fPlaybackChannels);
+ }
+
+ int JackPortAudioAdapter::Open()
+@@ -126,8 +119,10 @@
+ PaStreamParameters inputParameters;
+ PaStreamParameters outputParameters;
+
+- if ( JackAudioAdapterInterface::Open() < 0 )
++ if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) {
++ jack_error("No input and output device!!");
+ return -1;
++ }
+
+ jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str());
+ jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str());
+@@ -136,7 +131,7 @@
+ inputParameters.device = fInputDevice;
+ inputParameters.channelCount = fCaptureChannels;
+ inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
+- inputParameters.suggestedLatency = ( fInputDevice != paNoDevice ) // TODO: check how to setup this on ASIO
++ inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
+ ? fPaDevices.GetDeviceInfo(fInputDevice)->defaultLowInputLatency
+ : 0;
+ inputParameters.hostApiSpecificStreamInfo = NULL;
+@@ -144,35 +139,33 @@
+ outputParameters.device = fOutputDevice;
+ outputParameters.channelCount = fPlaybackChannels;
+ outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
+- outputParameters.suggestedLatency = ( fOutputDevice != paNoDevice ) // TODO: check how to setup this on ASIO
++ outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
+ ? fPaDevices.GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
+ : 0;
+ outputParameters.hostApiSpecificStreamInfo = NULL;
+
+ err = Pa_OpenStream( &fStream,
+- ( fInputDevice == paNoDevice ) ? 0 : &inputParameters,
+- ( fOutputDevice == paNoDevice ) ? 0 : &outputParameters,
++ (fInputDevice == paNoDevice) ? 0 : &inputParameters,
++ (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
+ fAdaptedSampleRate,
+ fAdaptedBufferSize,
+ paNoFlag, // Clipping is on...
+ Render,
+- this );
++ this);
+
+- if ( err != paNoError )
+- {
+- jack_error ( "Pa_OpenStream error = %s", Pa_GetErrorText ( err ) );
++ if (err != paNoError) {
++ jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
+ return -1;
+ }
+
+- err = Pa_StartStream ( fStream );
++ err = Pa_StartStream(fStream);
+
+- if ( err != paNoError )
+- {
+- jack_error ( "Pa_StartStream error = %s", Pa_GetErrorText ( err ) );
++ if (err != paNoError) {
++ jack_error("Pa_StartStream error = %s", Pa_GetErrorText(err));
+ return -1;
+ }
+
+- jack_log ( "JackPortAudioAdapter::Open OK" );
++ jack_log("JackPortAudioAdapter::Open OK");
+ return 0;
+ }
+
+@@ -181,24 +174,24 @@
+ #ifdef JACK_MONITOR
+ fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
+ #endif
+- jack_log ( "JackPortAudioAdapter::Close" );
+- Pa_StopStream ( fStream );
+- jack_log ( "JackPortAudioAdapter:: Pa_StopStream" );
+- Pa_CloseStream ( fStream );
+- jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" );
+- return JackAudioAdapterInterface::Close();
++ jack_log("JackPortAudioAdapter::Close");
++ Pa_StopStream(fStream);
++ jack_log("JackPortAudioAdapter:: Pa_StopStream");
++ Pa_CloseStream(fStream);
++ jack_log("JackPortAudioAdapter:: Pa_CloseStream");
++ return 0;
+ }
+
+- int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate )
++ int JackPortAudioAdapter::SetSampleRate(jack_nframes_t sample_rate)
+ {
+- JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
++ JackAudioAdapterInterface::SetHostSampleRate(sample_rate);
+ Close();
+ return Open();
+ }
+
+- int JackPortAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size )
++ int JackPortAudioAdapter::SetBufferSize(jack_nframes_t buffer_size)
+ {
+- JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
++ JackAudioAdapterInterface::SetHostBufferSize(buffer_size);
+ Close();
+ return Open();
+ }
+@@ -212,96 +205,39 @@
+
+ SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 10;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Maximum number of input channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Maximum number of output channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, "default input device");
+- strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, "default output device");
+- strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 44100U;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "periodsize");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 512U;
+- strcpy(desc->params[i].short_desc, "Period size");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- desc->params[i].value.ui = 128U;
+- strcpy(desc->params[i].value.str, "default device");
+- strcpy(desc->params[i].short_desc, "PortAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "list-devices");
+- desc->params[i].character = 'l';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = true;
+- strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "quality");
+- desc->params[i].character = 'q';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "ring-buffer");
+- desc->params[i].character = 'g';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 32768;
+- strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
+- strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("audioadapter", JackDriverNone, "netjack audio <==> net backend adapter", &filler);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", NULL);
++
++ strcpy(value.str, "default input device");
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL);
++
++ strcpy(value.str, "default output device");
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set PortAudio device name", NULL);
++
++ value.ui = 44100U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = 512U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "periodsize", 'p', JackDriverParamUInt, &value, NULL, "Period size", NULL);
++
++ strcpy(value.str, "default device");
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL);
++
++ value.i = true;
++ jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available PortAudio devices", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "quality", 'q', JackDriverParamInt, &value, NULL, "Resample algorithm quality (0 - 4)", NULL);
++
++ value.ui = 32768;
++ jack_driver_descriptor_add_parameter(desc, &filler, "ring-buffer", 'g', JackDriverParamInt, &value, NULL, "Fixed ringbuffer size", "Fixed ringbuffer size (if not set => automatic adaptative)");
+
+ return desc;
+ }
+@@ -309,3 +245,4 @@
+ #ifdef __cplusplus
+ }
+ #endif
++
+--- a/windows/portaudio/JackPortAudioAdapter.h
++++ b/windows/portaudio/JackPortAudioAdapter.h
+@@ -71,7 +71,7 @@
+ #include "JackCompilerDeps.h"
+ #include "driver_interface.h"
+
+- EXPORT jack_driver_desc_t* jack_get_descriptor();
++SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor();
+
+ #ifdef __cplusplus
+ }
+--- a/windows/portaudio/JackPortAudioDevices.cpp
++++ b/windows/portaudio/JackPortAudioDevices.cpp
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -19,6 +19,7 @@
+
+ #include "JackPortAudioDevices.h"
+ #include "JackError.h"
++#include <stdlib.h>
+
+ using namespace std;
+
+@@ -27,19 +28,20 @@
+ PaError err;
+ PaDeviceIndex id;
+ jack_log("Initializing PortAudio...");
+- if ( ( err = Pa_Initialize() ) == paNoError )
+- {
++ if ((err = Pa_Initialize()) == paNoError) {
+ fNumHostApi = Pa_GetHostApiCount();
+ fNumDevice = Pa_GetDeviceCount();
+ fDeviceInfo = new PaDeviceInfo*[fNumDevice];
+- for ( id = 0; id < fNumDevice; id++ )
++ for (id = 0; id < fNumDevice; id++) {
+ fDeviceInfo[id] = const_cast<PaDeviceInfo*>(Pa_GetDeviceInfo(id));
++ }
+ fHostName = new string[fNumHostApi];
+- for ( id = 0; id < fNumHostApi; id++ )
+- fHostName[id] = string ( Pa_GetHostApiInfo(id)->name );
+- }
+- else
++ for (id = 0; id < fNumHostApi; id++) {
++ fHostName[id] = string (Pa_GetHostApiInfo(id)->name);
++ }
++ } else {
+ jack_error("JackPortAudioDriver::Pa_Initialize error = %s", Pa_GetErrorText(err));
++ }
+ }
+
+ PortAudioDevices::~PortAudioDevices()
+@@ -56,70 +58,73 @@
+ return fNumDevice;
+ }
+
+-PaDeviceInfo* PortAudioDevices::GetDeviceInfo ( PaDeviceIndex id )
++PaDeviceInfo* PortAudioDevices::GetDeviceInfo(PaDeviceIndex id)
+ {
+ return fDeviceInfo[id];
+ }
+
+-string PortAudioDevices::GetDeviceName ( PaDeviceIndex id )
++string PortAudioDevices::GetDeviceName(PaDeviceIndex id)
+ {
+- return string ( fDeviceInfo[id]->name );
++ return string(fDeviceInfo[id]->name);
+ }
+
+-string PortAudioDevices::GetHostFromDevice ( PaDeviceInfo* device )
++string PortAudioDevices::GetHostFromDevice(PaDeviceInfo* device)
+ {
+ return fHostName[device->hostApi];
+ }
+
+-string PortAudioDevices::GetHostFromDevice ( PaDeviceIndex id )
++string PortAudioDevices::GetHostFromDevice(PaDeviceIndex id)
+ {
+ return fHostName[fDeviceInfo[id]->hostApi];
+ }
+
+-string PortAudioDevices::GetFullName ( PaDeviceIndex id )
++string PortAudioDevices::GetFullName(PaDeviceIndex id)
+ {
+- string hostname = GetHostFromDevice ( id );
+- string devicename = GetDeviceName ( id );
++ string hostname = GetHostFromDevice(id);
++ string devicename = GetDeviceName(id);
+ //some hostname are quite long...use shortcuts
+- if ( hostname.compare ( "Windows DirectSound" ) == 0 )
+- hostname = string ( "DirectSound" );
+- return ( hostname + "::" + devicename );
++ if (hostname.compare("Windows DirectSound") == 0) {
++ hostname = string("DirectSound");
++ }
++ return (hostname + "::" + devicename);
+ }
+
+-string PortAudioDevices::GetFullName ( std::string hostname, std::string devicename )
++string PortAudioDevices::GetFullName(std::string hostname, std::string devicename)
+ {
+ //some hostname are quite long...use shortcuts
+- if ( hostname.compare ( "Windows DirectSound" ) == 0 )
+- hostname = string ( "DirectSound" );
+- return ( hostname + "::" + devicename );
++ if (hostname.compare("Windows DirectSound") == 0) {
++ hostname = string("DirectSound");
++ }
++ return (hostname + "::" + devicename);
+ }
+
+-PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName ( string fullname, PaDeviceIndex& id, bool isInput )
++PaDeviceInfo* PortAudioDevices::GetDeviceFromFullName (string fullname, PaDeviceIndex& id, bool isInput)
+ {
+ PaDeviceInfo* ret = NULL;
+ //no driver to find
+- if ( fullname.size() == 0 )
++ if (fullname.size() == 0) {
+ return NULL;
++ }
+ //first get host and device names from fullname
+- string::size_type separator = fullname.find ( "::", 0 );
+- if ( separator == 0 )
++ string::size_type separator = fullname.find ("::", 0);
++ if (separator == 0) {
+ return NULL;
++ }
+ char* hostname = (char*)malloc(separator + 9);
+- fill_n ( hostname, separator + 9, 0 );
+- fullname.copy ( hostname, separator );
++ fill_n (hostname, separator + 9, 0);
++ fullname.copy (hostname, separator);
+
+ //we need the entire hostname, replace shortcuts
+- if ( strcmp ( hostname, "DirectSound" ) == 0 )
+- strcpy ( hostname, "Windows DirectSound" );
+- string devicename = fullname.substr ( separator + 2 );
++ if (strcmp (hostname, "DirectSound") == 0) {
++ strcpy (hostname, "Windows DirectSound");
++ }
++ string devicename = fullname.substr (separator + 2);
+ //then find the corresponding device
+- for ( PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++ )
+- {
++ for (PaDeviceIndex dev_id = 0; dev_id < fNumDevice; dev_id++) {
+ bool flag = (isInput) ? (fDeviceInfo[dev_id]->maxInputChannels > 0) : (fDeviceInfo[dev_id]->maxOutputChannels > 0);
+- if ( ( GetHostFromDevice(dev_id).compare(hostname) == 0 )
+- && ( GetDeviceName(dev_id).compare(devicename) == 0 )
+- && flag )
+- {
++ if ((GetHostFromDevice(dev_id).compare(hostname) == 0)
++ && (GetDeviceName(dev_id).compare(devicename) == 0)
++ && flag) {
+ id = dev_id;
+ ret = fDeviceInfo[dev_id];
+ }
+@@ -139,23 +144,16 @@
+ PaError err;
+
+ printCount = 0;
+- for (i = 0; standardSampleRates[i] > 0; i++)
+- {
++ for (i = 0; standardSampleRates[i] > 0; i++) {
+ err = Pa_IsFormatSupported(inputParameters, outputParameters, standardSampleRates[i]);
+- if (err == paFormatIsSupported)
+- {
+- if (printCount == 0)
+- {
++ if (err == paFormatIsSupported) {
++ if (printCount == 0) {
+ jack_info("\t%8.2f", standardSampleRates[i]);
+ printCount = 1;
+- }
+- else if (printCount == 4)
+- {
++ } else if (printCount == 4) {
+ jack_info(",\n\t%8.2f", standardSampleRates[i]);
+ printCount = 1;
+- }
+- else
+- {
++ } else {
+ jack_info(", %8.2f", standardSampleRates[i]);
+ ++printCount;
+ }
+@@ -170,17 +168,18 @@
+
+ int PortAudioDevices::GetInputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_input)
+ {
+- string fullname = string ( devicename );
+- PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, true );
+- if ( device )
++ string fullname = string (devicename);
++ PaDeviceInfo* device = GetDeviceFromFullName (fullname, id, true);
++ if (device) {
+ max_input = device->maxInputChannels;
+- else
+- {
++ } else {
+ id = Pa_GetDefaultInputDevice();
+- if ( fullname.size() )
++ if (fullname.size()) {
+ jack_error("Can't open %s, PortAudio will use default input device.", devicename);
+- if ( id == paNoDevice )
++ }
++ if (id == paNoDevice) {
+ return -1;
++ }
+ max_input = GetDeviceInfo(id)->maxInputChannels;
+ }
+ return id;
+@@ -188,17 +187,18 @@
+
+ int PortAudioDevices::GetOutputDeviceFromName(const char* devicename, PaDeviceIndex& id, int& max_output)
+ {
+- string fullname = string ( devicename );
+- PaDeviceInfo* device = GetDeviceFromFullName ( fullname, id, false );
+- if ( device )
++ string fullname = string (devicename);
++ PaDeviceInfo* device = GetDeviceFromFullName (fullname, id, false);
++ if (device) {
+ max_output = device->maxOutputChannels;
+- else
+- {
++ } else {
+ id = Pa_GetDefaultOutputDevice();
+- if ( fullname.size() )
++ if (fullname.size()) {
+ jack_error("Can't open %s, PortAudio will use default output device.", devicename);
+- if ( id == paNoDevice )
++ }
++ if (id == paNoDevice) {
+ return -1;
++ }
+ max_output = GetDeviceInfo(id)->maxOutputChannels;
+ }
+ return id;
+@@ -208,57 +208,50 @@
+ {
+ PaDeviceIndex id;
+ PaStreamParameters inputParameters, outputParameters;
+- jack_info ( "********************** Devices list, %d detected **********************", fNumDevice );
++ jack_info ("********************** Devices list, %d detected **********************", fNumDevice);
+
+- for ( id = 0; id < fNumDevice; id++ )
+- {
+- jack_info ( "-------- device #%d ------------------------------------------------", id );
++ for (id = 0; id < fNumDevice; id++) {
++ jack_info ("-------- device #%d ------------------------------------------------", id);
+
+- if ( id == Pa_GetDefaultInputDevice() )
+- {
++ if (id == Pa_GetDefaultInputDevice()) {
+ jack_info("[ Default Input ]");
+- }
+- else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi)->defaultInputDevice )
+- {
+- const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
+- jack_info ( "[ Default %s Input ]", host_info->name );
++ } else if (id == Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi)->defaultInputDevice) {
++ const PaHostApiInfo *host_info = Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi);
++ jack_info("[ Default %s Input ]", host_info->name);
+ }
+
+- if ( id == Pa_GetDefaultOutputDevice() )
+- {
+- jack_info ( "[ Default Output ]" );
+- }
+- else if ( id == Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi )->defaultOutputDevice )
+- {
+- const PaHostApiInfo *host_info = Pa_GetHostApiInfo ( fDeviceInfo[id]->hostApi );
+- jack_info ( "[ Default %s Output ]", host_info->name );
++ if (id == Pa_GetDefaultOutputDevice()) {
++ jack_info ("[ Default Output ]");
++ } else if (id == Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi)->defaultOutputDevice) {
++ const PaHostApiInfo *host_info = Pa_GetHostApiInfo (fDeviceInfo[id]->hostApi);
++ jack_info("[ Default %s Output ]", host_info->name);
+ }
+
+ /* print device info fields */
+- jack_info ( "Name = %s", GetFullName ( id ).c_str() );
+- jack_info ( "Max inputs = %d", fDeviceInfo[id]->maxInputChannels );
+- jack_info ( "Max outputs = %d", fDeviceInfo[id]->maxOutputChannels );
++ jack_info ("Name = %s", GetFullName (id).c_str());
++ jack_info ("Max inputs = %d", fDeviceInfo[id]->maxInputChannels);
++ jack_info ("Max outputs = %d", fDeviceInfo[id]->maxOutputChannels);
+
+ #ifdef WIN32
+ /* ASIO specific latency information */
+- if ( Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO )
+- {
++ if (Pa_GetHostApiInfo(fDeviceInfo[id]->hostApi)->type == paASIO) {
+ long minLatency, maxLatency, preferredLatency, granularity;
+
+- PaAsio_GetAvailableLatencyValues ( id, &minLatency, &maxLatency, &preferredLatency, &granularity );
++ PaAsio_GetAvailableLatencyValues (id, &minLatency, &maxLatency, &preferredLatency, &granularity);
+
+- jack_info ( "ASIO minimum buffer size = %ld", minLatency );
+- jack_info ( "ASIO maximum buffer size = %ld", maxLatency );
+- jack_info ( "ASIO preferred buffer size = %ld", preferredLatency );
+-
+- if ( granularity == -1 )
+- jack_info ( "ASIO buffer granularity = power of 2" );
+- else
+- jack_info ( "ASIO buffer granularity = %ld", granularity );
++ jack_info ("ASIO minimum buffer size = %ld", minLatency);
++ jack_info ("ASIO maximum buffer size = %ld", maxLatency);
++ jack_info ("ASIO preferred buffer size = %ld", preferredLatency);
++
++ if (granularity == -1) {
++ jack_info ("ASIO buffer granularity = power of 2");
++ } else {
++ jack_info ("ASIO buffer granularity = %ld", granularity);
++ }
+ }
+ #endif
+
+- jack_info ( "Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate );
++ jack_info ("Default sample rate = %8.2f", fDeviceInfo[id]->defaultSampleRate);
+
+ /* poll for standard sample rates */
+ inputParameters.device = id;
+@@ -273,20 +266,25 @@
+ outputParameters.suggestedLatency = 0; /* ignored by Pa_IsFormatSupported() */
+ outputParameters.hostApiSpecificStreamInfo = NULL;
+ }
+- jack_info ( "**************************** End of list ****************************" );
++ jack_info("**************************** End of list ****************************");
+ }
+
+-bool PortAudioDevices::IsDuplex ( PaDeviceIndex id )
++bool PortAudioDevices::IsDuplex (PaDeviceIndex id)
+ {
+ //does the device has in and out facilities
+- if ( fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
++ if (fDeviceInfo[id]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels) {
+ return true;
++ }
+ //else is another complementary device ? (search in devices with the same name)
+- for ( PaDeviceIndex i = 0; i < fNumDevice; i++ )
+- if ( ( i != id ) && ( GetDeviceName ( i ) == GetDeviceName ( id ) ) )
+- if ( ( fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels )
+- || ( fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels ) )
++ for (PaDeviceIndex i = 0; i < fNumDevice; i++) {
++ if ((i != id) && (GetDeviceName (i) == GetDeviceName (id))) {
++ if ((fDeviceInfo[i]->maxInputChannels && fDeviceInfo[id]->maxOutputChannels)
++ || (fDeviceInfo[i]->maxOutputChannels && fDeviceInfo[id]->maxInputChannels)) {
+ return true;
++ }
++ }
++ }
+ //then the device isn't full duplex
+ return false;
+ }
++
+--- a/windows/portaudio/JackPortAudioDevices.h
++++ b/windows/portaudio/JackPortAudioDevices.h
+@@ -1,5 +1,5 @@
+ /*
+-Copyright (C) 2008 Romain Moret at Grame
++Copyright (C) 2008-2011 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
+@@ -33,11 +33,14 @@
+ class PortAudioDevices
+ {
+ private:
++
+ PaHostApiIndex fNumHostApi; //number of hosts
+ PaDeviceIndex fNumDevice; //number of devices
+ PaDeviceInfo** fDeviceInfo; //array of device info
+ std::string* fHostName; //array of host names (matched with host id's)
++
+ public:
++
+ PortAudioDevices();
+ ~PortAudioDevices();
+
+@@ -48,12 +51,13 @@
+ std::string GetHostFromDevice(PaDeviceIndex id);
+ std::string GetFullName(PaDeviceIndex id);
+ std::string GetFullName(std::string hostname, std::string devicename);
+- PaDeviceInfo* GetDeviceFromFullName(std::string fullname, PaDeviceIndex& id, bool isInput );
++ PaDeviceInfo* GetDeviceFromFullName(std::string fullname, PaDeviceIndex& id, bool isInput);
+ void PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters);
+ int GetInputDeviceFromName(const char* name, PaDeviceIndex& device, int& in_max);
+ int GetOutputDeviceFromName(const char* name, PaDeviceIndex& device, int& out_max);
+ void DisplayDevicesNames();
+- bool IsDuplex ( PaDeviceIndex id );
++ bool IsDuplex(PaDeviceIndex id);
++
+ };
+
+ #endif
+--- a/windows/portaudio/JackPortAudioDriver.cpp
++++ b/windows/portaudio/JackPortAudioDriver.cpp
+@@ -21,8 +21,10 @@
+ #include "driver_interface.h"
+ #include "JackPortAudioDriver.h"
+ #include "JackEngineControl.h"
++#include "JackGraphManager.h"
+ #include "JackError.h"
+ #include "JackTime.h"
++#include "JackTools.h"
+ #include "JackCompilerDeps.h"
+ #include <iostream>
+ #include <assert.h>
+@@ -31,236 +33,263 @@
+
+ namespace Jack
+ {
+- int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer,
+- unsigned long framesPerBuffer,
+- const PaStreamCallbackTimeInfo* timeInfo,
+- PaStreamCallbackFlags statusFlags,
+- void* userData)
+- {
+- JackPortAudioDriver* driver = (JackPortAudioDriver*)userData;
+- driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer;
+- driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer;
+- // Setup threadded based log function
+- set_threaded_log_function();
+- driver->CycleTakeBeginTime();
+- return (driver->Process() == 0) ? paContinue : paAbort;
++
++int JackPortAudioDriver::Render(const void* inputBuffer, void* outputBuffer,
++ unsigned long framesPerBuffer,
++ const PaStreamCallbackTimeInfo* timeInfo,
++ PaStreamCallbackFlags statusFlags,
++ void* userData)
++{
++ JackPortAudioDriver* driver = (JackPortAudioDriver*)userData;
++ driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer;
++ driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer;
++
++ MMCSSAcquireRealTime(GetCurrentThread());
++
++ if (statusFlags) {
++ if (statusFlags & paOutputUnderflow)
++ jack_error("JackPortAudioDriver::Render paOutputUnderflow");
++ if (statusFlags & paInputUnderflow)
++ jack_error("JackPortAudioDriver::Render paInputUnderflow");
++ if (statusFlags & paOutputOverflow)
++ jack_error("JackPortAudioDriver::Render paOutputOverflow");
++ if (statusFlags & paInputOverflow)
++ jack_error("JackPortAudioDriver::Render paInputOverflow");
++ if (statusFlags & paPrimingOutput)
++ jack_error("JackPortAudioDriver::Render paOutputUnderflow");
++
++ if (statusFlags != paPrimingOutput) {
++ jack_time_t cur_time = GetMicroSeconds();
++ driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst)); // Better this value than nothing...
++ }
+ }
+
+- int JackPortAudioDriver::Read()
+- {
+- for (int i = 0; i < fCaptureChannels; i++)
+- memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
+- return 0;
++ // Setup threadded based log function
++ set_threaded_log_function();
++ driver->CycleTakeBeginTime();
++ return (driver->Process() == 0) ? paContinue : paAbort;
++}
++
++int JackPortAudioDriver::Read()
++{
++ for (int i = 0; i < fCaptureChannels; i++) {
++ memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
+ }
++ return 0;
++}
+
+- int JackPortAudioDriver::Write()
+- {
+- for (int i = 0; i < fPlaybackChannels; i++)
+- memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
+- return 0;
++int JackPortAudioDriver::Write()
++{
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
+ }
++ return 0;
++}
+
+- int JackPortAudioDriver::Open(jack_nframes_t buffer_size,
+- jack_nframes_t samplerate,
+- bool capturing,
+- bool playing,
+- int inchannels,
+- int outchannels,
+- bool monitor,
+- const char* capture_driver_uid,
+- const char* playback_driver_uid,
+- jack_nframes_t capture_latency,
+- jack_nframes_t playback_latency)
+- {
+- PaError err = paNoError;
+- PaStreamParameters inputParameters;
+- PaStreamParameters outputParameters;
+- int in_max = 0;
+- int out_max = 0;
+-
+- jack_log("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld",
+- buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate);
+-
+- // Generic JackAudioDriver Open
+- if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0)
+- return -1;
++PaError JackPortAudioDriver::OpenStream(jack_nframes_t buffer_size)
++{
++ PaStreamParameters inputParameters;
++ PaStreamParameters outputParameters;
+
+- //get devices
+- if (capturing)
+- {
+- if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0)
+- goto error;
+- }
+- if (playing)
+- {
+- if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0)
+- goto error;
+- }
++ // Update parameters
++ inputParameters.device = fInputDevice;
++ inputParameters.channelCount = fCaptureChannels;
++ inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
++ inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
++ ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
++ : 0;
++ inputParameters.hostApiSpecificStreamInfo = NULL;
++
++ outputParameters.device = fOutputDevice;
++ outputParameters.channelCount = fPlaybackChannels;
++ outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
++ outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
++ ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
++ : 0;
++ outputParameters.hostApiSpecificStreamInfo = NULL;
++
++ return Pa_OpenStream(&fStream,
++ (fInputDevice == paNoDevice) ? 0 : &inputParameters,
++ (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
++ fEngineControl->fSampleRate,
++ buffer_size,
++ paNoFlag, // Clipping is on...
++ Render,
++ this);
++}
+
+- jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice);
++void JackPortAudioDriver::UpdateLatencies()
++{
++ jack_latency_range_t input_range;
++ jack_latency_range_t output_range;
++ jack_latency_range_t monitor_range;
++
++ const PaStreamInfo* info = Pa_GetStreamInfo(fStream);
++ assert(info);
++
++ for (int i = 0; i < fCaptureChannels; i++) {
++ input_range.max = input_range.min = fEngineControl->fBufferSize + (info->inputLatency * fEngineControl->fSampleRate) + fCaptureLatency;
++ fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
++ }
+
+- //default channels number required
+- if (inchannels == 0)
+- {
+- jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max);
+- inchannels = in_max;
+- }
+- if (outchannels == 0)
+- {
+- jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max);
+- outchannels = out_max;
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ output_range.max = output_range.min = (info->outputLatency * fEngineControl->fSampleRate) + fPlaybackLatency;
++ if (fEngineControl->fSyncMode) {
++ output_range.max = output_range.min += fEngineControl->fBufferSize;
++ } else {
++ output_range.max = output_range.min += fEngineControl->fBufferSize * 2;
++ }
++ fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
++ if (fWithMonitorPorts) {
++ monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
++ fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
+ }
++ }
++}
+
+- //too many channels required, take max available
+- if (inchannels > in_max)
+- {
+- jack_error("This device has only %d available input channels.", in_max);
+- inchannels = in_max;
+- }
+- if (outchannels > out_max)
+- {
+- jack_error("This device has only %d available output channels.", out_max);
+- outchannels = out_max;
+- }
++int JackPortAudioDriver::Open(jack_nframes_t buffer_size,
++ jack_nframes_t samplerate,
++ bool capturing,
++ bool playing,
++ int inchannels,
++ int outchannels,
++ bool monitor,
++ const char* capture_driver_uid,
++ const char* playback_driver_uid,
++ jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency)
++{
++ int in_max = 0;
++ int out_max = 0;
++ PaError err = paNoError;
++
++ fCaptureLatency = capture_latency;
++ fPlaybackLatency = playback_latency;
++
++ jack_log("JackPortAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s samplerate = %ld",
++ buffer_size, inchannels, outchannels, capture_driver_uid, playback_driver_uid, samplerate);
++
++ // Generic JackAudioDriver Open
++ if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor,
++ capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) {
++ return -1;
++ }
+
+- //in/out streams parametering
+- inputParameters.device = fInputDevice;
+- inputParameters.channelCount = inchannels;
+- inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
+- inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
+- ? fPaDevices->GetDeviceInfo(fInputDevice)->defaultLowInputLatency
+- : 0;
+- inputParameters.hostApiSpecificStreamInfo = NULL;
+-
+- outputParameters.device = fOutputDevice;
+- outputParameters.channelCount = outchannels;
+- outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
+- outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
+- ? fPaDevices->GetDeviceInfo(fOutputDevice)->defaultLowOutputLatency
+- : 0;
+- outputParameters.hostApiSpecificStreamInfo = NULL;
+-
+- err = Pa_OpenStream(&fStream,
+- (fInputDevice == paNoDevice) ? 0 : &inputParameters,
+- (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
+- samplerate,
+- buffer_size,
+- paNoFlag, // Clipping is on...
+- Render,
+- this);
+- if (err != paNoError)
+- {
+- jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
++ //get devices
++ if (capturing) {
++ if (fPaDevices->GetInputDeviceFromName(capture_driver_uid, fInputDevice, in_max) < 0) {
+ goto error;
+ }
++ }
++ if (playing) {
++ if (fPaDevices->GetOutputDeviceFromName(playback_driver_uid, fOutputDevice, out_max) < 0) {
++ goto error;
++ }
++ }
++
++ jack_log("JackPortAudioDriver::Open fInputDevice = %d, fOutputDevice %d", fInputDevice, fOutputDevice);
++
++ //default channels number required
++ if (inchannels == 0) {
++ jack_log("JackPortAudioDriver::Open setup max in channels = %ld", in_max);
++ inchannels = in_max;
++ }
++ if (outchannels == 0) {
++ jack_log("JackPortAudioDriver::Open setup max out channels = %ld", out_max);
++ outchannels = out_max;
++ }
++
++ //too many channels required, take max available
++ if (inchannels > in_max) {
++ jack_error("This device has only %d available input channels.", in_max);
++ inchannels = in_max;
++ }
++ if (outchannels > out_max) {
++ jack_error("This device has only %d available output channels.", out_max);
++ outchannels = out_max;
++ }
++
++ // Core driver may have changed the in/out values
++ fCaptureChannels = inchannels;
++ fPlaybackChannels = outchannels;
++
++ err = OpenStream(buffer_size);
++ if (err != paNoError) {
++ jack_error("Pa_OpenStream error %d = %s", err, Pa_GetErrorText(err));
++ goto error;
++ }
+
+ #ifdef __APPLE__
+- fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000;
+- fEngineControl->fComputation = 500 * 1000;
+- fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000;
++ fEngineControl->fPeriod = fEngineControl->fPeriodUsecs * 1000;
++ fEngineControl->fComputation = JackTools::ComputationMicroSec(fEngineControl->fBufferSize) * 1000;
++ fEngineControl->fConstraint = fEngineControl->fPeriodUsecs * 1000;
+ #endif
+
+- // Core driver may have changed the in/out values
+- fCaptureChannels = inchannels;
+- fPlaybackChannels = outchannels;
+-
+- assert(strlen(capture_driver_uid) < JACK_CLIENT_NAME_SIZE);
+- assert(strlen(playback_driver_uid) < JACK_CLIENT_NAME_SIZE);
++ assert(strlen(capture_driver_uid) < JACK_CLIENT_NAME_SIZE);
++ assert(strlen(playback_driver_uid) < JACK_CLIENT_NAME_SIZE);
+
+- strcpy(fCaptureDriverName, capture_driver_uid);
+- strcpy(fPlaybackDriverName, playback_driver_uid);
++ strcpy(fCaptureDriverName, capture_driver_uid);
++ strcpy(fPlaybackDriverName, playback_driver_uid);
+
+- return 0;
++ return 0;
+
+ error:
+- JackAudioDriver::Close();
+- jack_error("Can't open default PortAudio device : %s", Pa_GetErrorText(err));
+- return -1;
+- }
++ JackAudioDriver::Close();
++ jack_error("Can't open default PortAudio device");
++ return -1;
++}
+
+- int JackPortAudioDriver::Close()
+- {
+- // Generic audio driver close
+- int res = JackAudioDriver::Close();
+-
+- jack_log("JackPortAudioDriver::Close");
+- Pa_CloseStream(fStream);
+- return res;
+- }
++int JackPortAudioDriver::Close()
++{
++ // Generic audio driver close
++ int res = JackAudioDriver::Close();
++ jack_log("JackPortAudioDriver::Close");
++ Pa_CloseStream(fStream);
++ return res;
++}
+
+- int JackPortAudioDriver::Start()
+- {
+- jack_log("JackPortAudioDriver::Start");
+- if (JackAudioDriver::Start() >= 0) {
+- PaError err = Pa_StartStream(fStream);
+- if (err == paNoError) {
+- return 0;
+- }
+- JackAudioDriver::Stop();
++int JackPortAudioDriver::Start()
++{
++ jack_log("JackPortAudioDriver::Start");
++ if (JackAudioDriver::Start() >= 0) {
++ PaError err = Pa_StartStream(fStream);
++ if (err == paNoError) {
++ return 0;
+ }
+- return -1;
++ JackAudioDriver::Stop();
+ }
++ return -1;
++}
+
+- int JackPortAudioDriver::Stop()
+- {
+- jack_log("JackPortAudioDriver::Stop");
+- PaError err = Pa_StopStream(fStream);
+- int res = (err == paNoError) ? 0 : -1;
+- if (JackAudioDriver::Stop() < 0) {
+- res = -1;
+- }
+- return res;
++int JackPortAudioDriver::Stop()
++{
++ jack_log("JackPortAudioDriver::Stop");
++ PaError err = Pa_StopStream(fStream);
++ int res = (err == paNoError) ? 0 : -1;
++ if (JackAudioDriver::Stop() < 0) {
++ res = -1;
+ }
++ return res;
++}
+
+- int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
+- {
+- PaError err;
+- PaStreamParameters inputParameters;
+- PaStreamParameters outputParameters;
+-
+- if ((err = Pa_CloseStream(fStream)) != paNoError)
+- {
+- jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err));
+- return -1;
+- }
++int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
++{
++ PaError err;
+
+- //change parametering
+- inputParameters.device = fInputDevice;
+- inputParameters.channelCount = fCaptureChannels;
+- inputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
+- inputParameters.suggestedLatency = (fInputDevice != paNoDevice) // TODO: check how to setup this on ASIO
+- ? Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency
+- : 0;
+- inputParameters.hostApiSpecificStreamInfo = NULL;
+-
+- outputParameters.device = fOutputDevice;
+- outputParameters.channelCount = fPlaybackChannels;
+- outputParameters.sampleFormat = paFloat32 | paNonInterleaved; // 32 bit floating point output
+- outputParameters.suggestedLatency = (fOutputDevice != paNoDevice) // TODO: check how to setup this on ASIO
+- ? Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency
+- : 0;
+- outputParameters.hostApiSpecificStreamInfo = NULL;
+-
+- err = Pa_OpenStream(&fStream,
+- (fInputDevice == paNoDevice) ? 0 : &inputParameters,
+- (fOutputDevice == paNoDevice) ? 0 : &outputParameters,
+- fEngineControl->fSampleRate,
+- buffer_size,
+- paNoFlag, // Clipping is on...
+- Render,
+- this);
++ if ((err = Pa_CloseStream(fStream)) != paNoError) {
++ jack_error("Pa_CloseStream error = %s", Pa_GetErrorText(err));
++ return -1;
++ }
+
+- if (err != paNoError)
+- {
+- jack_error("Pa_OpenStream error = %s", Pa_GetErrorText(err));
+- return -1;
+- }
+- else
+- {
+- // Only done when success
+- return JackAudioDriver::SetBufferSize(buffer_size); // never fails
+- }
++ err = OpenStream(buffer_size);
++ if (err != paNoError) {
++ jack_error("Pa_OpenStream error %d = %s", err, Pa_GetErrorText(err));
++ return -1;
++ } else {
++ JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails
++ return 0;
+ }
++}
+
+ } // end of namespace
+
+@@ -273,119 +302,44 @@
+
+ SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
+ {
+- jack_driver_desc_t *desc;
+- unsigned int i;
+- desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
+-
+- strcpy(desc->name, "portaudio"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "PortAudio API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+-
+- desc->nparams = 13;
+- desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
+-
+- i = 0;
+- strcpy(desc->params[i].name, "channels");
+- desc->params[i].character = 'c';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Maximum number of channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "inchannels");
+- desc->params[i].character = 'i';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Maximum number of input channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "outchannels");
+- desc->params[i].character = 'o';
+- desc->params[i].type = JackDriverParamInt;
+- desc->params[i].value.ui = 0;
+- strcpy(desc->params[i].short_desc, "Maximum number of output channels");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "capture");
+- desc->params[i].character = 'C';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, "will take default PortAudio input device");
+- strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set PortAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "playback");
+- desc->params[i].character = 'P';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, "will take default PortAudio output device");
+- strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set PortAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy (desc->params[i].name, "monitor");
+- desc->params[i].character = 'm';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "duplex");
+- desc->params[i].character = 'D';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = TRUE;
+- strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "rate");
+- desc->params[i].character = 'r';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 44100U;
+- strcpy(desc->params[i].short_desc, "Sample rate");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "period");
+- desc->params[i].character = 'p';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.ui = 128U;
+- strcpy(desc->params[i].short_desc, "Frames per period");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "device");
+- desc->params[i].character = 'd';
+- desc->params[i].type = JackDriverParamString;
+- strcpy(desc->params[i].value.str, "will take default PortAudio device name");
+- strcpy(desc->params[i].short_desc, "PortAudio device name");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "input-latency");
+- desc->params[i].character = 'I';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra input latency");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "output-latency");
+- desc->params[i].character = 'O';
+- desc->params[i].type = JackDriverParamUInt;
+- desc->params[i].value.i = 0;
+- strcpy(desc->params[i].short_desc, "Extra output latency");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
+-
+- i++;
+- strcpy(desc->params[i].name, "list-devices");
+- desc->params[i].character = 'l';
+- desc->params[i].type = JackDriverParamBool;
+- desc->params[i].value.i = TRUE;
+- strcpy(desc->params[i].short_desc, "Display available PortAudio devices");
+- strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
++ jack_driver_desc_t * desc;
++ jack_driver_desc_filler_t filler;
++ jack_driver_param_value_t value;
++
++ desc = jack_driver_descriptor_construct("portaudio", JackDriverMaster, "PortAudio API based audio backend", &filler);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamUInt, &value, NULL, "Maximum number of channels", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "inchannels", 'i', JackDriverParamUInt, &value, NULL, "Maximum number of input channels", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "outchannels", 'o', JackDriverParamUInt, &value, NULL, "Maximum number of output channels", NULL);
++
++ strcpy(value.str, "will take default PortAudio input device");
++ jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set PortAudio device name", NULL);
++
++ strcpy(value.str, "will take default PortAudio output device");
++ jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Provide playback ports. Optionally set PortAudio device name", NULL);
++
++ value.i = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
++
++ value.i = TRUE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
++
++ value.ui = 44100U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
++
++ value.ui = 512U;
++ jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
++
++ strcpy(value.str, "will take default PortAudio device name");
++ jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "PortAudio device name", NULL);
++
++ value.ui = 0;
++ jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency", NULL);
++ jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency", NULL);
++
++ value.i = TRUE;
++ jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available PortAudio devices", NULL);
+
+ return desc;
+ }
+@@ -411,8 +365,7 @@
+ {
+ param = (const jack_driver_param_t *) node->data;
+
+- switch (param->character)
+- {
++ switch (param->character) {
+
+ case 'd':
+ capture_pcm_name = param->value.str;
+@@ -483,12 +436,12 @@
+ }
+
+ Jack::JackDriverClientInterface* driver = new Jack::JackPortAudioDriver("system", "portaudio", engine, table, pa_devices);
+- if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency) == 0)
+- {
++ if (driver->Open(frames_per_interrupt, srate, capture, playback,
++ chan_in, chan_out, monitor, capture_pcm_name,
++ playback_pcm_name, systemic_input_latency,
++ systemic_output_latency) == 0) {
+ return driver;
+- }
+- else
+- {
++ } else {
+ delete driver;
+ return NULL;
+ }
+--- a/windows/portaudio/JackPortAudioDriver.h
++++ b/windows/portaudio/JackPortAudioDriver.h
+@@ -22,6 +22,7 @@
+
+ #include "JackAudioDriver.h"
+ #include "JackPortAudioDevices.h"
++#include "JackMMCSS.h"
+
+ namespace Jack
+ {
+@@ -30,7 +31,7 @@
+ \brief The PortAudio driver.
+ */
+
+-class JackPortAudioDriver : public JackAudioDriver
++class JackPortAudioDriver : public JackMMCSS, public JackAudioDriver
+ {
+
+ private:
+@@ -48,10 +49,13 @@
+ PaStreamCallbackFlags statusFlags,
+ void* userData);
+
++ PaError OpenStream(jack_nframes_t buffer_size);
++ void UpdateLatencies();
++
+ public:
+
+ JackPortAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, PortAudioDevices* pa_devices)
+- : JackAudioDriver(name, alias, engine, table), fStream(NULL), fInputBuffer(NULL), fOutputBuffer(NULL),
++ : JackMMCSS(), JackAudioDriver(name, alias, engine, table), fStream(NULL), fInputBuffer(NULL), fOutputBuffer(NULL),
+ fInputDevice(paNoDevice), fOutputDevice(paNoDevice)
+ {
+ fPaDevices = pa_devices;
+--- /dev/null
++++ b/windows/Setup/jack64.ci
+@@ -0,0 +1,158 @@
++<*project
++ version = 4 civer = "Free v4.14.5" winver = "2.8/6.1.7600" >
++ <output> .</>
++ <exename> Jack_v1.9.8_64_setup.exe</>
++ <digitsign> </>
++ <appname> Jack</>
++ <password> </>
++ <addlang> </>
++ <icon> Default - 2</>
++ <selfextr> 1</>
++ <voltype> nolimit</>
++ <volsize> </>
++ <volpattern> disk%i.pak</>
++ <load> </>
++ <loadtime> 1000</>
++ <checktype> admin</>
++ <chkname> </>
++ <chkmsg> </>
++ <dlgfont> Verdana,8</>
++ <lang> English</>
++ <theme> Green</>
++ <iface> leftlogo</>
++ <leftlogo> .\src\logo_installer.bmp</>
++ <logo> </>
++ <vb> </>
++ <dao> </>
++ <background> 0</>
++ <dlgwelcome> 1</>
++ <dlgreadme> .\src\README</>
++ <dlglic> .\src\gpl_installer.rtf</>
++ <dlgcustpath> </>
++ <dlgenfpath> 0</>
++ <dlgsavepath> 1</>
++ <dlgautoprog> 1</>
++ <dlgfinish> 1</>
++ <comptype> defnorm</>
++ <solid> 0</>
++ <srcfolder> </>
++ <ifexist> over</>
++ <runafter> </>
++ <runconfirm> 1</>
++ <uninclude> 1</>
++ <unicon> Uninstall - 2</>
++ <unshortcut> 1</>
++ <unrun> </>
++ <silent> 0</>
++ <unfeed> </>
++ <unautoclose> 1</>
++ <unfinish> 1</>
++ <bl> My Demo</>
++ <blurl> </>
++ <bghead> </>
++ <bgfoot> </>
++ <bgback> </>
++ <files listview >
++<_><src>..\Release64\bin\libjack64.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjack64.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjack64.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjack64.dll</><dest>win</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjackserver64.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjackserver64.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjackserver64.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libjackserver64.dll</><dest>win</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjack.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjack.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjack.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjack.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjackserver.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjackserver.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjackserver.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjackserver.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\portaudio_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_connect.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_disconnect.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_load.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_lsp.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_metro.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_unload.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_midi_latency_test.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jackd.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\libsamplerate_x86_64.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\portaudio_x86_64.dll</><dest>win</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\jack_net.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\jack_netone.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_netsource.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\jack_dummy.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\jack_loopback.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\jack_winmme.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\jack_portaudio.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\netmanager.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\audioadapter.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack\netadapter.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release64\bin\jack_midi_dump.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\control.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\intclient.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\jack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\jslist.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\midiport.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\ringbuffer.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\statistics.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\thread.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\transport.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\types.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\..\common\jack\systemdeps.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></>
++<_><src>..\..\common\jack\weakjack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></>
++<_><src>..\..\common\jack\weakmacros.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></>
++<_><src>.\src\32bits\JackRouter.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\JackRouter.ini</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\msvcr100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\msvcp100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\64bits\JackRouter.dll</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\64bits\JackRouter.ini</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\64bits\msvcr100.dll</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\64bits\msvcp100.dll</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\64bits\portaudio_x86_64.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\qjackctl\mingwm10.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\qjackctl\qjackctl.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\qjackctl\QtCore4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\qjackctl\QtGui4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\qjackctl\QtXml4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\COPYING</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\README</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++
++ </files>
++ <runx listview >
++ </runx>
++ <registry listview >
++
++ </registry>
++ <shcut listview >
++ <_><shpath>prog</><shname>Jack NetDriver</><tarpath>inst</><tarname>jackd.exe</><cmdline>-R -S -d net</><workpath>inst</><workcust></><icon></></>
++<_><shpath>prog</><shname>Jack PortAudio</><tarpath>inst</><tarname>jackd.exe</><cmdline>-R -S -d portaudio</><workpath>inst</><workcust></><icon></></>
++<_><shpath>prog</><shname>Jack Control</><tarpath>inst</><tarname>qjackctl.exe</><cmdline></><workpath>inst</><workcust></><icon>jackdmp.exe</></>
++<_><shpath>prog</><shname>Jack Command</><tarpath>sys</><tarname>cmd.exe</><cmdline></><workpath>inst</><workcust></><icon></></>
++
++ </shcut>
++ <ini listview >
++
++ </ini>
++ <copy listview >
++
++ </copy>
++ <activex listview >
++ <_><path>inst</><name>32bits\JackRouter.dll</></>
++ <_><path>inst</><name>64bits\JackRouter.dll</></>
++
++ </activex>
++ <font listview >
++
++ </font>
++ <ext listview >
++
++ </ext>
++ <mreg listview >
++
++ </mreg>
++ <macros> Pathadd=</>
++</project>
+\ No newline at end of file
+--- a/windows/Setup/jack.ci
++++ b/windows/Setup/jack.ci
+@@ -1,9 +1,9 @@
+ <*project
+ version = 4 civer = "Free v4.14.5" winver = "2.6/5.1.2600" >
+ <output> .</>
+- <exename> Jack_v1.9.7_setup.exe</>
++ <exename> Jack_v1.9.8_32_setup.exe</>
+ <digitsign> </>
+- <appname> Jack v1.9.7</>
++ <appname> Jack</>
+ <password> </>
+ <addlang> </>
+ <icon> Default - 2</>
+@@ -53,8 +53,7 @@
+ <bgfoot> </>
+ <bgback> </>
+ <files listview >
+- <_><src>..\Release\bin\libjack.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
+-<_><src>.\src\vcredist_x86.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libjack.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\libjack.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\libjack.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\libjackserver.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
+@@ -66,11 +65,12 @@
+ <_><src>..\Release\bin\jack_lsp.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack_metro.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack_unload.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\jack_midi_latency_test.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jackd.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\libjack.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\libjackserver.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></>
+-<_><src>..\Release\bin\libsamplerate-0.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+-<_><src>..\Release\bin\portaudio_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\libsamplerate_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\portaudio_x86.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack\jack_net.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack\jack_netone.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack_netsource.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+@@ -81,6 +81,7 @@
+ <_><src>..\Release\bin\jack\netmanager.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack\audioadapter.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\Release\bin\jack\netadapter.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></>
++<_><src>..\Release\bin\jack_midi_dump.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\..\common\jack\control.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\..\common\jack\intclient.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
+ <_><src>..\..\common\jack\jack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>0</></>
+@@ -94,8 +95,11 @@
+ <_><src>..\..\common\jack\systemdeps.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></>
+ <_><src>..\..\common\jack\weakjack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></>
+ <_><src>..\..\common\jack\weakmacros.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></>
+-<_><src>.\JackRouter.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+-<_><src>.\JackRouter.ini</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\JackRouter.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\JackRouter.ini</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\msvcr100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\msvcp100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></>
++<_><src>.\src\32bits\portaudio_x86.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></>
+ <_><src>.\qjackctl\mingwm10.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>.\qjackctl\qjackctl.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+ <_><src>.\qjackctl\QtCore4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></>
+@@ -106,15 +110,13 @@
+
+ </files>
+ <runx listview >
+- <_><type>app</><path>inst</><file>vcredist_x86.exe</><cmdline></><wait>1</><workdir>inst</><custdir></><when>end</></>
+-
+ </runx>
+ <registry listview >
+
+ </registry>
+ <shcut listview >
+ <_><shpath>prog</><shname>Jack NetDriver</><tarpath>inst</><tarname>jackd.exe</><cmdline>-R -S -d net</><workpath>inst</><workcust></><icon></></>
+-<_><shpath>prog</><shname>Jack Portaudio</><tarpath>inst</><tarname>jackd.exe</><cmdline>-R -S -d portaudio</><workpath>inst</><workcust></><icon></></>
++<_><shpath>prog</><shname>Jack PortAudio</><tarpath>inst</><tarname>jackd.exe</><cmdline>-R -S -d portaudio</><workpath>inst</><workcust></><icon></></>
+ <_><shpath>prog</><shname>Jack Control</><tarpath>inst</><tarname>qjackctl.exe</><cmdline></><workpath>inst</><workcust></><icon>jackdmp.exe</></>
+ <_><shpath>prog</><shname>Jack Command</><tarpath>sys</><tarname>cmd.exe</><cmdline></><workpath>inst</><workcust></><icon></></>
+
+@@ -126,7 +128,7 @@
+
+ </copy>
+ <activex listview >
+- <_><path>inst</><name>JackRouter.dll</></>
++ <_><path>inst</><name>32bits\JackRouter.dll</></>
+
+ </activex>
+ <font listview >
+--- a/windows/Setup/README
++++ b/windows/Setup/README
+@@ -14,4 +14,11 @@
+
+ Once all binaries are available, just execute the script in 'CreateInstall' to make 'setup.exe'.
+ The setup will copy all binaries to a specified folder, register the JackRouter (in order to have it in the ASIO drivers list) and create some shortcuts in the start menu.
+-It's a good and proper way to get jack installed on windows.
+\ No newline at end of file
++It's a good and proper way to get jack installed on windows.
++
++64 bits compilation
++====================
++
++- for some reasons CodeBlocks create libjack.dll.a and libjack.dll.def names. So the ".dll" part has to be removed before using "lib" tool to create ".lib" files.
++
++- to create 64 bits ".lib" files, the "/MACHINE:X64 option has to be used.
+--- /dev/null
++++ b/windows/Setup/src/32bits/JackRouter.ini
+@@ -0,0 +1,7 @@
++[IO]
++input=4
++output=4
++
++[AUTO_CONNECT]
++input=1
++output=1
+--- /dev/null
++++ b/windows/Setup/src/64bits/JackRouter.ini
+@@ -0,0 +1,7 @@
++[IO]
++input=4
++output=4
++
++[AUTO_CONNECT]
++input=1
++output=1
+--- a/windows/winmme/JackWinMMEDriver.cpp
++++ b/windows/winmme/JackWinMMEDriver.cpp
+@@ -1,5 +1,6 @@
+ /*
+ Copyright (C) 2009 Grame
++Copyright (C) 2011 Devin Anderson
+
+ 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
+@@ -17,419 +18,353 @@
+
+ */
+
+-#include "JackWinMMEDriver.h"
+-#include "JackGraphManager.h"
+-#include "JackEngineControl.h"
+-#include "JackDriverLoader.h"
+-
+-#include <assert.h>
+-#include <iostream>
+-#include <sstream>
+-#include <string>
+-
+-#include <windows.h>
+-#include <windowsx.h>
+-#include <mmsystem.h>
++#include <cmath>
+
+-namespace Jack
+-{
+-
+-static bool InitHeaders(MidiSlot* slot)
+-{
+- slot->fHeader = (LPMIDIHDR)GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT, sizeof(MIDIHDR) + kBuffSize);
+- if (!slot->fHeader)
+- return false;
+-
+- slot->fHeader->lpData = (LPSTR)((LPBYTE)slot->fHeader + sizeof(MIDIHDR));
+- slot->fHeader->dwBufferLength = kBuffSize;
+- slot->fHeader->dwFlags = 0;
+- slot->fHeader->dwUser = 0;
+- slot->fHeader->lpNext = 0;
+- slot->fHeader->dwBytesRecorded = 0;
+- return true;
+-}
++#include "JackEngineControl.h"
++#include "JackWinMMEDriver.h"
+
+-void CALLBACK JackWinMMEDriver::MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD userData, DWORD dwParam1, DWORD dwParam2)
+-{
+- jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)userData;
+- //jack_info("JackWinMMEDriver::MidiInProc 0\n");
++using Jack::JackWinMMEDriver;
+
+- switch (wMsg) {
+- case MIM_OPEN:
+- break;
+-
+- case MIM_ERROR:
+- case MIM_DATA: {
+-
+- //jack_info("JackWinMMEDriver::MidiInProc");
+-
+- // One event
+- unsigned int num_packet = 1;
+- jack_ringbuffer_write(ringbuffer, (char*)&num_packet, sizeof(unsigned int));
+-
+- // Write event actual data
+- jack_ringbuffer_write(ringbuffer, (char*)&dwParam1, 3);
+- break;
+- }
+-
+- case MIM_LONGERROR:
+- case MIM_LONGDATA:
+- /*
+- Nothing for now
+- */
+- break;
+- }
++JackWinMMEDriver::JackWinMMEDriver(const char *name, const char *alias,
++ JackLockedEngine *engine,
++ JackSynchro *table):
++ JackMidiDriver(name, alias, engine, table)
++{
++ input_ports = 0;
++ output_ports = 0;
++ period = 0;
+ }
+
+-JackWinMMEDriver::JackWinMMEDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
+- : JackMidiDriver(name, alias, engine, table),
+- fRealCaptureChannels(0),
+- fRealPlaybackChannels(0),
+- fMidiSource(NULL),
+- fMidiDestination(NULL)
+-{}
+-
+ JackWinMMEDriver::~JackWinMMEDriver()
+ {}
+
+-int JackWinMMEDriver::Open(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
++JackWinMMEDriver::Attach()
+ {
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ jack_port_id_t index;
++ jack_nframes_t latency = buffer_size;
++ jack_latency_range_t latency_range;
++ const char *name;
++ JackPort *port;
++ latency_range.max = latency +
++ ((jack_nframes_t) std::ceil((period / 1000.0) *
++ fEngineControl->fSampleRate));
++ latency_range.min = latency;
++
++ jack_info("JackWinMMEDriver::Attach - fCaptureChannels %d", fCaptureChannels);
++ jack_info("JackWinMMEDriver::Attach - fPlaybackChannels %d", fPlaybackChannels);
++
++ // Inputs
++ for (int i = 0; i < fCaptureChannels; i++) {
++ JackWinMMEInputPort *input_port = input_ports[i];
++ name = input_port->GetName();
++ if (fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ CaptureDriverFlags, buffer_size, &index) < 0) {
++ jack_error("JackWinMMEDriver::Attach - cannot register input port "
++ "with name '%s'.", name);
++ // X: Do we need to deallocate ports?
++ return -1;
++ }
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(input_port->GetAlias());
++ port->SetLatencyRange(JackCaptureLatency, &latency_range);
++ fCapturePortList[i] = index;
++ }
++
++ if (! fEngineControl->fSyncMode) {
++ latency += buffer_size;
++ latency_range.max = latency;
++ latency_range.min = latency;
++ }
++
++ // Outputs
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ JackWinMMEOutputPort *output_port = output_ports[i];
++ name = output_port->GetName();
++ if (fEngine->PortRegister(fClientControl.fRefNum, name,
++ JACK_DEFAULT_MIDI_TYPE,
++ PlaybackDriverFlags, buffer_size, &index) < 0) {
++ jack_error("JackWinMMEDriver::Attach - cannot register output "
++ "port with name '%s'.", name);
++ // X: Do we need to deallocate ports?
++ return -1;
++ }
++ port = fGraphManager->GetPort(index);
++ port->SetAlias(output_port->GetAlias());
++ port->SetLatencyRange(JackPlaybackLatency, &latency_range);
++ fPlaybackPortList[i] = index;
++ }
+
+- jack_log("JackWinMMEDriver::Open");
++ return 0;
++}
+
+- fRealCaptureChannels = midiInGetNumDevs();
+- fRealPlaybackChannels = midiOutGetNumDevs();
++int
++JackWinMMEDriver::Close()
++{
++ // Generic MIDI driver close
++ int result = JackMidiDriver::Close();
+
+- // Generic JackMidiDriver Open
+- if (JackMidiDriver::Open(capturing, playing, fRealCaptureChannels, fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0)
+- return -1;
+-
+- fMidiDestination = new MidiSlot[fRealCaptureChannels];
+- assert(fMidiDestination);
+-
+- // Real input
+- int devindex = 0;
+- for (int i = 0; i < fRealCaptureChannels; i++) {
+-
+- HMIDIIN handle;
+- fMidiDestination[devindex].fIndex = i;
+- MMRESULT ret = midiInOpen(&handle, fMidiDestination[devindex].fIndex, (DWORD)MidiInProc, (DWORD)fRingBuffer[devindex], CALLBACK_FUNCTION);
+-
+- if (ret == MMSYSERR_NOERROR) {
+- fMidiDestination[devindex].fHandle = handle;
+- if (!InitHeaders(&fMidiDestination[devindex])) {
+- jack_error("memory allocation failed");
+- midiInClose(handle);
+- continue;
+- }
+- ret = midiInPrepareHeader(handle, fMidiDestination[devindex].fHeader, sizeof(MIDIHDR));
++ if (input_ports) {
++ for (int i = 0; i < fCaptureChannels; i++) {
++ delete input_ports[i];
++ }
++ delete[] input_ports;
++ input_ports = 0;
++ }
++ if (output_ports) {
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ delete output_ports[i];
++ }
++ delete[] output_ports;
++ output_ports = 0;
++ }
++ if (period) {
++ if (timeEndPeriod(period) != TIMERR_NOERROR) {
++ jack_error("JackWinMMEDriver::Close - failed to unset timer "
++ "resolution.");
++ result = -1;
++ }
++ }
++ return result;
++}
+
+- if (ret == MMSYSERR_NOERROR) {
+- fMidiDestination[devindex].fHeader->dwUser = 1;
+- ret = midiInAddBuffer(handle, fMidiDestination[devindex].fHeader, sizeof(MIDIHDR));
+- if (ret == MMSYSERR_NOERROR) {
+- ret = midiInStart(handle);
+- if (ret != MMSYSERR_NOERROR) {
+- jack_error("midiInStart error");
+- CloseInput(&fMidiDestination[devindex]);
+- continue;
+- }
+- } else {
+- jack_error ("midiInAddBuffer error");
+- CloseInput(&fMidiDestination[devindex]);
+- continue;
+- }
+- } else {
+- jack_error("midiInPrepareHeader error");
+- midiInClose(handle);
+- continue;
+- }
++int
++JackWinMMEDriver::Open(bool capturing, bool playing, int in_channels,
++ int out_channels, bool monitor,
++ const char* capture_driver_name,
++ const char* playback_driver_name,
++ jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency)
++{
++ const char *client_name = fClientControl.fName;
++ int input_count = 0;
++ int output_count = 0;
++ int num_potential_inputs = midiInGetNumDevs();
++ int num_potential_outputs = midiOutGetNumDevs();
++
++ jack_info("JackWinMMEDriver::Open - num_potential_inputs %d", num_potential_inputs);
++ jack_info("JackWinMMEDriver::Open - num_potential_outputs %d", num_potential_outputs);
++
++ period = 0;
++ TIMECAPS caps;
++ if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
++ jack_error("JackWinMMEDriver::Open - could not get timer device "
++ "capabilities. Continuing anyway ...");
++ } else {
++ period = caps.wPeriodMin;
++ if (timeBeginPeriod(period) != TIMERR_NOERROR) {
++ jack_error("JackWinMMEDriver::Open - could not set minimum timer "
++ "resolution. Continuing anyway ...");
++ period = 0;
+ } else {
+- jack_error ("midiInOpen error");
+- continue;
++
++ jack_info("JackWinMMEDriver::Open - multimedia timer resolution "
++ "set to %d milliseconds.", period);
++
+ }
+- devindex += 1;
+ }
+- fRealCaptureChannels = devindex;
+- fCaptureChannels = devindex;
+
+- fMidiSource = new MidiSlot[fRealPlaybackChannels];
+- assert(fMidiSource);
+-
+- // Real output
+- devindex = 0;
+- for (int i = 0; i < fRealPlaybackChannels; i++) {
+- MMRESULT res;
+- HMIDIOUT handle;
+- fMidiSource[devindex].fIndex = i;
+- UINT ret = midiOutOpen(&handle, fMidiSource[devindex].fIndex, 0L, 0L, CALLBACK_NULL);
+- if (ret == MMSYSERR_NOERROR) {
+- fMidiSource[devindex].fHandle = handle;
+- if (!InitHeaders(&fMidiSource[devindex])) {
+- jack_error("memory allocation failed");
+- midiOutClose(handle);
++ if (num_potential_inputs) {
++ try {
++ input_ports = new JackWinMMEInputPort *[num_potential_inputs];
++ } catch (std::exception e) {
++ jack_error("JackWinMMEDriver::Open - while creating input port "
++ "array: %s", e.what());
++ goto unset_timer_resolution;
++ }
++ for (int i = 0; i < num_potential_inputs; i++) {
++ try {
++ input_ports[input_count] =
++ new JackWinMMEInputPort(fAliasName, client_name,
++ capture_driver_name, i);
++ } catch (std::exception e) {
++ jack_error("JackWinMMEDriver::Open - while creating input "
++ "port: %s", e.what());
+ continue;
+ }
+- res = midiOutPrepareHeader(handle, fMidiSource[devindex].fHeader, sizeof(MIDIHDR));
+- if (res != MMSYSERR_NOERROR) {
+- jack_error("midiOutPrepareHeader error %d %d %d", i, handle, res);
++ input_count++;
++ }
++ }
++ if (num_potential_outputs) {
++ try {
++ output_ports = new JackWinMMEOutputPort *[num_potential_outputs];
++ } catch (std::exception e) {
++ jack_error("JackWinMMEDriver::Open - while creating output port "
++ "array: %s", e.what());
++ goto destroy_input_ports;
++ }
++ for (int i = 0; i < num_potential_outputs; i++) {
++ try {
++ output_ports[output_count] =
++ new JackWinMMEOutputPort(fAliasName, client_name,
++ playback_driver_name, i);
++ } catch (std::exception e) {
++ jack_error("JackWinMMEDriver::Open - while creating output "
++ "port: %s", e.what());
+ continue;
+- } else {
+- fMidiSource[devindex].fHeader->dwUser = 1;
+ }
+- } else {
+- jack_error("midiOutOpen error");
+- continue;
++ output_count++;
+ }
+- devindex += 1;
+ }
+- fRealPlaybackChannels = devindex;
+- fPlaybackChannels = devindex;
+- return 0;
+-}
+
+-void JackWinMMEDriver::CloseInput(MidiSlot* slot)
+-{
+- MMRESULT res;
+- int retry = 0;
+-
+- if (slot->fHandle == 0)
+- return;
+-
+- HMIDIIN handle = (HMIDIIN)slot->fHandle;
+- slot->fHeader->dwUser = 0;
+- res = midiInStop(handle);
+- if (res != MMSYSERR_NOERROR) {
+- jack_error("midiInStop error");
+- }
+- res = midiInReset(handle);
+- if (res != MMSYSERR_NOERROR) {
+- jack_error("midiInReset error");
+- }
+- res = midiInUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR));
+- if (res != MMSYSERR_NOERROR) {
+- jack_error("midiInUnprepareHeader error");
+- }
+- do {
+- res = midiInClose(handle);
+- if (res != MMSYSERR_NOERROR) {
+- jack_error("midiInClose error");
+- }
+- if (res == MIDIERR_STILLPLAYING)
+- midiInReset(handle);
+- Sleep (10);
+- retry++;
+- } while ((res == MIDIERR_STILLPLAYING) && (retry < 10));
++ jack_info("JackWinMMEDriver::Open - input_count %d", input_count);
++ jack_info("JackWinMMEDriver::Open - output_count %d", output_count);
+
+- if (slot->fHeader) {
+- GlobalFreePtr(slot->fHeader);
++ if (! (input_count || output_count)) {
++ jack_error("JackWinMMEDriver::Open - no WinMME inputs or outputs "
++ "allocated.");
++ } else if (! JackMidiDriver::Open(capturing, playing, input_count,
++ output_count, monitor,
++ capture_driver_name,
++ playback_driver_name, capture_latency,
++ playback_latency)) {
++ return 0;
+ }
+-}
+
+-void JackWinMMEDriver::CloseOutput(MidiSlot* slot)
+-{
+- MMRESULT res;
+- int retry = 0;
+-
+- if (slot->fHandle == 0)
+- return;
+-
+- HMIDIOUT handle = (HMIDIOUT)slot->fHandle;
+- res = midiOutReset(handle);
+- if (res != MMSYSERR_NOERROR)
+- jack_error("midiOutReset error");
+- midiOutUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR));
+- do {
+- res = midiOutClose(handle);
+- if (res != MMSYSERR_NOERROR)
+- jack_error("midiOutClose error");
+- Sleep(10);
+- retry++;
+- } while ((res == MIDIERR_STILLPLAYING) && (retry < 10));
+-
+- if (slot->fHeader) {
+- GlobalFreePtr(slot->fHeader);
++ if (output_ports) {
++ for (int i = 0; i < output_count; i++) {
++ delete output_ports[i];
++ }
++ delete[] output_ports;
++ output_ports = 0;
+ }
+-}
+-
+-int JackWinMMEDriver::Close()
+-{
+- jack_log("JackWinMMEDriver::Close");
+-
+- // Generic midi driver close
+- int res = JackMidiDriver::Close();
+-
+- // Close input
+- if (fMidiDestination) {
+- for (int i = 0; i < fRealCaptureChannels; i++) {
+- CloseInput(&fMidiDestination[i]);
++ destroy_input_ports:
++ if (input_ports) {
++ for (int i = 0; i < input_count; i++) {
++ delete input_ports[i];
+ }
+- delete[] fMidiDestination;
++ delete[] input_ports;
++ input_ports = 0;
+ }
+-
+- // Close output
+- if (fMidiSource) {
+- for (int i = 0; i < fRealPlaybackChannels; i++) {
+- CloseOutput(&fMidiSource[i]);
++ unset_timer_resolution:
++ if (period) {
++ if (timeEndPeriod(period) != TIMERR_NOERROR) {
++ jack_error("JackWinMMEDriver::Open - failed to unset timer "
++ "resolution.");
+ }
+- delete[] fMidiSource;
+ }
+-
+- return res;
++ return -1;
+ }
+
+-int JackWinMMEDriver::Attach()
++int
++JackWinMMEDriver::Read()
+ {
+- JackPort* port;
+- jack_port_id_t port_index;
+- char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
+- MMRESULT res;
+- int i;
+-
+- jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
+-
+- for (i = 0; i < fCaptureChannels; i++) {
+- MIDIINCAPS caps;
+- res = midiInGetDevCaps(fMidiDestination[i].fIndex, &caps, sizeof(caps));
+- if (res == MMSYSERR_NOERROR) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1);
+- } else {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1);
+- }
+- snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ for (int i = 0; i < fCaptureChannels; i++) {
++ input_ports[i]->ProcessJack(GetInputBuffer(i), buffer_size);
++ }
+
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
+- jack_error("driver: cannot register port for %s", name);
+- return -1;
+- }
+- port = fGraphManager->GetPort(port_index);
+- port->SetAlias(alias);
+- fCapturePortList[i] = port_index;
+- jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index);
+- }
+-
+- for (i = 0; i < fPlaybackChannels; i++) {
+- MIDIOUTCAPS caps;
+- res = midiOutGetDevCaps(fMidiSource[i].fIndex, &caps, sizeof(caps));
+- if (res == MMSYSERR_NOERROR) {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1);
+- } else {
+- snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fPlaybackDriverName, i + 1);
+- }
+- snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
++ return 0;
++}
+
+- if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) {
+- jack_error("driver: cannot register port for %s", name);
+- return -1;
+- }
+- port = fGraphManager->GetPort(port_index);
+- port->SetAlias(alias);
+- fPlaybackPortList[i] = port_index;
+- jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index);
++int
++JackWinMMEDriver::Write()
++{
++ jack_nframes_t buffer_size = fEngineControl->fBufferSize;
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ output_ports[i]->ProcessJack(GetOutputBuffer(i), buffer_size);
+ }
+
+ return 0;
+ }
+
+-int JackWinMMEDriver::Read()
++int
++JackWinMMEDriver::Start()
+ {
+- size_t size;
++ jack_info("JackWinMMEDriver::Start - Starting driver.");
+
+- for (int chan = 0; chan < fCaptureChannels; chan++) {
++ JackMidiDriver::Start();
+
+- if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) {
++ int input_count = 0;
++ int output_count = 0;
+
+- JackMidiBuffer* midi_buffer = GetInputBuffer(chan);
++ jack_info("JackWinMMEDriver::Start - Enabling input ports.");
+
+- if (jack_ringbuffer_read_space (fRingBuffer[chan]) == 0) {
+- // Reset buffer
+- midi_buffer->Reset(midi_buffer->nframes);
+- } else {
++ for (; input_count < fCaptureChannels; input_count++) {
++ if (input_ports[input_count]->Start() < 0) {
++ jack_error("JackWinMMEDriver::Start - Failed to enable input "
++ "port.");
++ goto stop_input_ports;
++ }
++ }
+
+- while ((size = jack_ringbuffer_read_space (fRingBuffer[chan])) > 0) {
++ jack_info("JackWinMMEDriver::Start - Enabling output ports.");
+
+- //jack_info("jack_ringbuffer_read_space %d", size);
+- int ev_count = 0;
+- jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int));
+-
+- if (ev_count > 0) {
+- for (int j = 0; j < ev_count; j++) {
+- unsigned int event_len = 3;
+- // Read event actual data
+- jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len);
+- jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len);
+- }
+- }
+- }
+- }
+- } else {
+- //jack_info("Consume ring buffer");
+- jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan]));
++ for (; output_count < fPlaybackChannels; output_count++) {
++ if (output_ports[output_count]->Start() < 0) {
++ jack_error("JackWinMMEDriver::Start - Failed to enable output "
++ "port.");
++ goto stop_output_ports;
+ }
+ }
++
++ jack_info("JackWinMMEDriver::Start - Driver started.");
++
+ return 0;
++
++ stop_output_ports:
++ for (int i = 0; i < output_count; i++) {
++ if (output_ports[i]->Stop() < 0) {
++ jack_error("JackWinMMEDriver::Start - Failed to disable output "
++ "port.");
++ }
++ }
++ stop_input_ports:
++ for (int i = 0; i < input_count; i++) {
++ if (input_ports[i]->Stop() < 0) {
++ jack_error("JackWinMMEDriver::Start - Failed to disable input "
++ "port.");
++ }
++ }
++
++ return -1;
+ }
+
+-int JackWinMMEDriver::Write()
++int
++JackWinMMEDriver::Stop()
+ {
+- for (int chan = 0; chan < fPlaybackChannels; chan++) {
++ int result = 0;
+
+- if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) {
++ JackMidiDriver::Stop();
+
+- JackMidiBuffer* midi_buffer = GetOutputBuffer(chan);
++ jack_info("JackWinMMEDriver::Stop - disabling input ports.");
+
+- // TODO : use timestamp
++ for (int i = 0; i < fCaptureChannels; i++) {
++ if (input_ports[i]->Stop() < 0) {
++ jack_error("JackWinMMEDriver::Stop - Failed to disable input "
++ "port.");
++ result = -1;
++ }
++ }
+
+- for (unsigned int j = 0; j < midi_buffer->event_count; j++) {
+- JackMidiEvent* ev = &midi_buffer->events[j];
+- if (ev->size <= 3) {
+- jack_midi_data_t *d = ev->GetData(midi_buffer);
+- DWORD winev = 0;
+- if (ev->size > 0) winev |= d[0];
+- if (ev->size > 1) winev |= (d[1] << 8);
+- if (ev->size > 2) winev |= (d[2] << 16);
+- MMRESULT res = midiOutShortMsg((HMIDIOUT)fMidiSource[chan].fHandle, winev);
+- if (res != MMSYSERR_NOERROR)
+- jack_error ("midiOutShortMsg error res %d", res);
+- } else {
++ jack_info("JackWinMMEDriver::Stop - disabling output ports.");
+
+- }
+- }
++ for (int i = 0; i < fPlaybackChannels; i++) {
++ if (output_ports[i]->Stop() < 0) {
++ jack_error("JackWinMMEDriver::Stop - Failed to disable output "
++ "port.");
++ result = -1;
+ }
+ }
+
+- return 0;
++ return result;
+ }
+
+-} // end of namespace
+-
+ #ifdef __cplusplus
+ extern "C"
+ {
+ #endif
+
++ // singleton kind of driver
++ static Jack::JackDriverClientInterface* driver = NULL;
++
+ SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor()
+ {
+ jack_driver_desc_t * desc;
+- //unsigned int i;
+-
+- desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t));
+- strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
+- strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
+
+- desc->nparams = 0;
+- desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t));
+-
+- return desc;
++ return jack_driver_descriptor_construct("winmme", JackDriverSlave, "WinMME API based MIDI backend", NULL);
+ }
+
+ SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
+@@ -474,13 +409,20 @@
+ }
+ */
+
+- Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table);
+- if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
+- return driver;
++ // singleton kind of driver
++ if (!driver) {
++ driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table);
++ if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) {
++ return driver;
++ } else {
++ delete driver;
++ return NULL;
++ }
+ } else {
+- delete driver;
++ jack_info("JackWinMMEDriver already allocated, cannot be loaded twice");
+ return NULL;
+ }
++
+ }
+
+ #ifdef __cplusplus
+@@ -504,3 +446,4 @@
+ jack_connect system_midi:capture_1 system_midi:playback_1
+
+ */
++
+--- a/windows/winmme/JackWinMMEDriver.h
++++ b/windows/winmme/JackWinMMEDriver.h
+@@ -1,5 +1,6 @@
+ /*
+ Copyright (C) 2009 Grame
++Copyright (C) 2011 Devin Anderson
+
+ 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
+@@ -21,67 +22,52 @@
+ #define __JackWinMMEDriver__
+
+ #include "JackMidiDriver.h"
+-#include "JackTime.h"
++#include "JackWinMMEInputPort.h"
++#include "JackWinMMEOutputPort.h"
+
+-namespace Jack
+-{
++namespace Jack {
+
+-/*!
+-\brief The WinMME driver.
+-*/
+-
+-#define kBuffSize 512
+-
+-struct MidiSlot {
+-
+- LPVOID fHandle; // MMSystem handler
+- short fIndex; // MMSystem dev index
+- LPMIDIHDR fHeader; // for long msg output
+-
+- MidiSlot():fHandle(0),fIndex(0)
+- {}
++ class JackWinMMEDriver : public JackMidiDriver {
+
+-};
++ private:
+
+-class JackWinMMEDriver : public JackMidiDriver
+-{
++ JackWinMMEInputPort **input_ports;
++ JackWinMMEOutputPort **output_ports;
++ UINT period;
+
+- private:
++ public:
+
+- int fRealCaptureChannels;
+- int fRealPlaybackChannels;
++ JackWinMMEDriver(const char* name, const char* alias,
++ JackLockedEngine* engine, JackSynchro* table);
+
+- MidiSlot* fMidiSource;
+- MidiSlot* fMidiDestination;
++ ~JackWinMMEDriver();
+
+- void CloseInput(MidiSlot* slot);
+- void CloseOutput(MidiSlot* slot);
++ int
++ Attach();
+
+- static void CALLBACK MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
++ int
++ Close();
+
+- public:
++ int
++ Open(bool capturing, bool playing, int num_inputs, int num_outputs,
++ bool monitor, const char* capture_driver_name,
++ const char* playback_driver_name, jack_nframes_t capture_latency,
++ jack_nframes_t playback_latency);
+
+- JackWinMMEDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table);
+- virtual ~JackWinMMEDriver();
++ int
++ Read();
+
+- int Open(bool capturing,
+- bool playing,
+- int chan_in,
+- int chan_out,
+- 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
++ Start();
+
+- int Attach();
++ int
++ Stop();
+
+- int Read();
+- int Write();
++ int
++ Write();
+
+-};
++ };
+
+-} // end of namespace
++}
+
+ #endif
+--- /dev/null
++++ b/windows/winmme/JackWinMMEInputPort.cpp
+@@ -0,0 +1,312 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <cassert>
++#include <memory>
++#include <stdexcept>
++
++#include "JackError.h"
++#include "JackTime.h"
++#include "JackMidiUtil.h"
++#include "JackWinMMEInputPort.h"
++#include "JackMidiWriteQueue.h"
++
++using Jack::JackWinMMEInputPort;
++
++///////////////////////////////////////////////////////////////////////////////
++// Static callbacks
++///////////////////////////////////////////////////////////////////////////////
++
++void CALLBACK
++JackWinMMEInputPort::HandleMidiInputEvent(HMIDIIN handle, UINT message,
++ DWORD port, DWORD param1,
++ DWORD param2)
++{
++ ((JackWinMMEInputPort *) port)->ProcessWinMME(message, param1, param2);
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Class
++///////////////////////////////////////////////////////////////////////////////
++
++JackWinMMEInputPort::JackWinMMEInputPort(const char *alias_name,
++ const char *client_name,
++ const char *driver_name, UINT index,
++ size_t max_bytes, size_t max_messages)
++{
++ thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
++ std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
++ write_queue = new JackMidiBufferWriteQueue();
++ std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
++ sysex_buffer = new jack_midi_data_t[max_bytes];
++ char error_message[MAXERRORLENGTH];
++ MMRESULT result = midiInOpen(&handle, index,
++ (DWORD_PTR) HandleMidiInputEvent,
++ (DWORD_PTR)this,
++ CALLBACK_FUNCTION | MIDI_IO_STATUS);
++ if (result != MMSYSERR_NOERROR) {
++ GetInErrorString(result, error_message);
++ goto delete_sysex_buffer;
++ }
++ sysex_header.dwBufferLength = max_bytes;
++ sysex_header.dwFlags = 0;
++ sysex_header.lpData = (LPSTR)sysex_buffer;
++ result = midiInPrepareHeader(handle, &sysex_header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ GetInErrorString(result, error_message);
++ goto close_handle;
++ }
++ result = midiInAddBuffer(handle, &sysex_header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ GetInErrorString(result, error_message);
++ goto unprepare_header;
++ }
++
++ MIDIINCAPS capabilities;
++ char *name_tmp;
++ result = midiInGetDevCaps(index, &capabilities, sizeof(capabilities));
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort [constructor]", "midiInGetDevCaps",
++ result);
++ name_tmp = (char*) driver_name;
++ } else {
++ name_tmp = capabilities.szPname;
++ }
++
++ snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", alias_name, name_tmp,
++ index + 1);
++ snprintf(name, sizeof(name) - 1, "%s:capture_%d", client_name, index + 1);
++ jack_event = 0;
++ started = false;
++ write_queue_ptr.release();
++ thread_queue_ptr.release();
++ return;
++
++ unprepare_header:
++ result = midiInUnprepareHeader(handle, &sysex_header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort [constructor]",
++ "midiInUnprepareHeader", result);
++ }
++ close_handle:
++ result = midiInClose(handle);
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort [constructor]", "midiInClose",
++ result);
++ }
++ delete_sysex_buffer:
++ delete[] sysex_buffer;
++ throw std::runtime_error(error_message);
++}
++
++JackWinMMEInputPort::~JackWinMMEInputPort()
++{
++ MMRESULT result = midiInReset(handle);
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort [destructor]", "midiInReset", result);
++ }
++ result = midiInUnprepareHeader(handle, &sysex_header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort [destructor]",
++ "midiInUnprepareHeader", result);
++ }
++ result = midiInClose(handle);
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort [destructor]", "midiInClose", result);
++ }
++ delete[] sysex_buffer;
++ delete thread_queue;
++ delete write_queue;
++}
++
++void
++JackWinMMEInputPort::EnqueueMessage(DWORD timestamp, size_t length,
++ jack_midi_data_t *data)
++{
++ jack_nframes_t frame =
++ GetFramesFromTime(start_time + (((jack_time_t) timestamp) * 1000));
++
++ // Debugging code
++ jack_time_t current_time = GetMicroSeconds();
++ jack_log("JackWinMMEInputPort::EnqueueMessage - enqueueing event at %f "
++ "(frame: %d) with start offset '%d' scheduled for frame '%d'",
++ ((double) current_time) / 1000.0, GetFramesFromTime(current_time),
++ timestamp, frame);
++ // End debugging code
++
++ switch (thread_queue->EnqueueEvent(frame, length, data)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++ jack_error("JackWinMMEInputPort::EnqueueMessage - The thread queue "
++ "cannot currently accept a %d-byte event. Dropping event.",
++ length);
++ break;
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackWinMMEInputPort::EnqueueMessage - The thread queue "
++ "buffer is too small to enqueue a %d-byte event. Dropping "
++ "event.", length);
++ break;
++ default:
++ ;
++ }
++}
++
++void
++JackWinMMEInputPort::GetInErrorString(MMRESULT error, LPTSTR text)
++{
++ MMRESULT result = midiInGetErrorText(error, text, MAXERRORLENGTH);
++ if (result != MMSYSERR_NOERROR) {
++ snprintf(text, MAXERRORLENGTH, "Unknown error code '%d'", error);
++ }
++}
++
++void
++JackWinMMEInputPort::ProcessJack(JackMidiBuffer *port_buffer,
++ jack_nframes_t frames)
++{
++ write_queue->ResetMidiBuffer(port_buffer, frames);
++ if (! jack_event) {
++ jack_event = thread_queue->DequeueEvent();
++ }
++ for (; jack_event; jack_event = thread_queue->DequeueEvent()) {
++ switch (write_queue->EnqueueEvent(jack_event, frames)) {
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackWinMMEMidiInputPort::Process - The buffer write "
++ "queue couldn't enqueue a %d-byte event. Dropping "
++ "event.", jack_event->size);
++ // Fallthrough on purpose
++ case JackMidiWriteQueue::OK:
++ continue;
++ }
++ break;
++ }
++}
++
++void
++JackWinMMEInputPort::ProcessWinMME(UINT message, DWORD param1, DWORD param2)
++{
++ set_threaded_log_function();
++ switch (message) {
++ case MIM_CLOSE:
++ jack_info("JackWinMMEInputPort::ProcessWinMME - MIDI device closed.");
++ break;
++ case MIM_MOREDATA:
++ jack_info("JackWinMMEInputPort::ProcessWinMME - The MIDI input device "
++ "driver thinks that JACK is not processing messages fast "
++ "enough.");
++ // Fallthrough on purpose.
++ case MIM_DATA: {
++ jack_midi_data_t message_buffer[3];
++ jack_midi_data_t status = param1 & 0xff;
++ int length = GetMessageLength(status);
++
++ switch (length) {
++ case 3:
++ message_buffer[2] = (param1 >> 16) & 0xff;
++ // Fallthrough on purpose.
++ case 2:
++ message_buffer[1] = (param1 >> 8) & 0xff;
++ // Fallthrough on purpose.
++ case 1:
++ message_buffer[0] = status;
++ break;
++ case 0:
++ jack_error("JackWinMMEInputPort::ProcessWinMME - **BUG** MIDI "
++ "input driver sent an MIM_DATA message with a sysex "
++ "status byte.");
++ return;
++ case -1:
++ jack_error("JackWinMMEInputPort::ProcessWinMME - **BUG** MIDI "
++ "input driver sent an MIM_DATA message with an invalid "
++ "status byte.");
++ return;
++ }
++ EnqueueMessage(param2, (size_t) length, message_buffer);
++ break;
++ }
++ case MIM_LONGDATA: {
++ LPMIDIHDR header = (LPMIDIHDR) param1;
++ size_t byte_count = header->dwBytesRecorded;
++ if (! byte_count) {
++ jack_info("JackWinMMEInputPort::ProcessWinMME - WinMME driver has "
++ "returned sysex header to us with no bytes. The JACK "
++ "driver is probably being stopped.");
++ break;
++ }
++ jack_midi_data_t *data = (jack_midi_data_t *) header->lpData;
++ if ((data[0] != 0xf0) || (data[byte_count - 1] != 0xf7)) {
++ jack_error("JackWinMMEInputPort::ProcessWinMME - Discarding "
++ "%d-byte sysex chunk.", byte_count);
++ } else {
++ EnqueueMessage(param2, byte_count, data);
++ }
++ // Is this realtime-safe? This function isn't run in the JACK thread,
++ // but we still want it to perform as quickly as possible. Even if
++ // this isn't realtime safe, it may not be avoidable.
++ MMRESULT result = midiInAddBuffer(handle, &sysex_header,
++ sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ WriteInError("JackWinMMEInputPort::ProcessWinMME",
++ "midiInAddBuffer", result);
++ }
++ break;
++ }
++ case MIM_LONGERROR:
++ jack_error("JackWinMMEInputPort::ProcessWinMME - Invalid or "
++ "incomplete sysex message received.");
++ break;
++ case MIM_OPEN:
++ jack_info("JackWinMMEInputPort::ProcessWinMME - MIDI device opened.");
++ }
++}
++
++bool
++JackWinMMEInputPort::Start()
++{
++ if (! started) {
++ start_time = GetMicroSeconds();
++ MMRESULT result = midiInStart(handle);
++ started = result == MMSYSERR_NOERROR;
++ if (! started) {
++ WriteInError("JackWinMMEInputPort::Start", "midiInStart", result);
++ }
++ }
++ return started;
++}
++
++bool
++JackWinMMEInputPort::Stop()
++{
++ if (started) {
++ MMRESULT result = midiInStop(handle);
++ started = result != MMSYSERR_NOERROR;
++ if (started) {
++ WriteInError("JackWinMMEInputPort::Stop", "midiInStop", result);
++ }
++ }
++ return ! started;
++}
++
++void
++JackWinMMEInputPort::WriteInError(const char *jack_func, const char *mm_func,
++ MMRESULT result)
++{
++ char error_message[MAXERRORLENGTH];
++ GetInErrorString(result, error_message);
++ jack_error("%s - %s: %s", jack_func, mm_func, error_message);
++}
+--- /dev/null
++++ b/windows/winmme/JackWinMMEInputPort.h
+@@ -0,0 +1,82 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackWinMMEInputPort__
++#define __JackWinMMEInputPort__
++
++#include <mmsystem.h>
++
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiBufferWriteQueue.h"
++#include "JackWinMMEPort.h"
++
++namespace Jack {
++
++ class JackWinMMEInputPort : public JackWinMMEPort {
++
++ private:
++
++ static void CALLBACK
++ HandleMidiInputEvent(HMIDIIN handle, UINT message, DWORD port,
++ DWORD param1, DWORD param2);
++
++ void
++ EnqueueMessage(DWORD timestamp, size_t length, jack_midi_data_t *data);
++
++ void
++ GetInErrorString(MMRESULT error, LPTSTR text);
++
++ void
++ ProcessWinMME(UINT message, DWORD param1, DWORD param2);
++
++ void
++ WriteInError(const char *jack_func, const char *mm_func,
++ MMRESULT result);
++
++ HMIDIIN handle;
++ jack_midi_event_t *jack_event;
++ jack_time_t start_time;
++ bool started;
++ jack_midi_data_t *sysex_buffer;
++ MIDIHDR sysex_header;
++ JackMidiAsyncQueue *thread_queue;
++ JackMidiBufferWriteQueue *write_queue;
++
++ public:
++
++ JackWinMMEInputPort(const char *alias_name, const char *client_name,
++ const char *driver_name, UINT index,
++ size_t max_bytes=4096, size_t max_messages=1024);
++
++ ~JackWinMMEInputPort();
++
++ void
++ ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames);
++
++ bool
++ Start();
++
++ bool
++ Stop();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/windows/winmme/JackWinMMEOutputPort.cpp
+@@ -0,0 +1,400 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <memory>
++#include <stdexcept>
++
++#include "JackMidiUtil.h"
++#include "JackTime.h"
++#include "JackWinMMEOutputPort.h"
++#include "JackGlobals.h"
++#include "JackEngineControl.h"
++
++using Jack::JackWinMMEOutputPort;
++
++///////////////////////////////////////////////////////////////////////////////
++// Static callbacks
++///////////////////////////////////////////////////////////////////////////////
++
++void CALLBACK
++JackWinMMEOutputPort::HandleMessageEvent(HMIDIOUT handle, UINT message,
++ DWORD_PTR port, DWORD_PTR param1,
++ DWORD_PTR param2)
++{
++ ((JackWinMMEOutputPort *) port)->HandleMessage(message, param1, param2);
++}
++
++///////////////////////////////////////////////////////////////////////////////
++// Class
++///////////////////////////////////////////////////////////////////////////////
++
++JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name,
++ const char *client_name,
++ const char *driver_name,
++ UINT index,
++ size_t max_bytes,
++ size_t max_messages)
++{
++ read_queue = new JackMidiBufferReadQueue();
++ std::auto_ptr<JackMidiBufferReadQueue> read_queue_ptr(read_queue);
++ thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
++ std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
++ thread = new JackThread(this);
++ std::auto_ptr<JackThread> thread_ptr(thread);
++ char error_message[MAXERRORLENGTH];
++ MMRESULT result = midiOutOpen(&handle, index, (DWORD_PTR)HandleMessageEvent,
++ (DWORD_PTR)this, CALLBACK_FUNCTION);
++ if (result != MMSYSERR_NOERROR) {
++ GetOutErrorString(result, error_message);
++ goto raise_exception;
++ }
++ thread_queue_semaphore = CreateSemaphore(NULL, 0, max_messages, NULL);
++ if (thread_queue_semaphore == NULL) {
++ GetOSErrorString(error_message);
++ goto close_handle;
++ }
++ sysex_semaphore = CreateSemaphore(NULL, 0, 1, NULL);
++ if (sysex_semaphore == NULL) {
++ GetOSErrorString(error_message);
++ goto destroy_thread_queue_semaphore;
++ }
++ MIDIOUTCAPS capabilities;
++ char *name_tmp;
++ result = midiOutGetDevCaps(index, &capabilities, sizeof(capabilities));
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort [constructor]", "midiOutGetDevCaps",
++ result);
++ name_tmp = (char*)driver_name;
++ } else {
++ name_tmp = capabilities.szPname;
++ }
++ snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", alias_name, name_tmp,
++ index + 1);
++ snprintf(name, sizeof(name) - 1, "%s:playback_%d", client_name, index + 1);
++ read_queue_ptr.release();
++ thread_queue_ptr.release();
++ thread_ptr.release();
++ return;
++
++ destroy_thread_queue_semaphore:
++ if (! CloseHandle(thread_queue_semaphore)) {
++ WriteOSError("JackWinMMEOutputPort [constructor]", "CloseHandle");
++ }
++ close_handle:
++ result = midiOutClose(handle);
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort [constructor]", "midiOutClose",
++ result);
++ }
++ raise_exception:
++ throw std::runtime_error(error_message);
++}
++
++JackWinMMEOutputPort::~JackWinMMEOutputPort()
++{
++ MMRESULT result = midiOutReset(handle);
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort [destructor]", "midiOutReset",
++ result);
++ }
++ result = midiOutClose(handle);
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort [destructor]", "midiOutClose",
++ result);
++ }
++ if (! CloseHandle(sysex_semaphore)) {
++ WriteOSError("JackWinMMEOutputPort [destructor]", "CloseHandle");
++ }
++ if (! CloseHandle(thread_queue_semaphore)) {
++ WriteOSError("JackWinMMEOutputPort [destructor]", "CloseHandle");
++ }
++ delete read_queue;
++ delete thread_queue;
++ delete thread;
++}
++
++bool
++JackWinMMEOutputPort::Execute()
++{
++ for (;;) {
++ if (! Wait(thread_queue_semaphore)) {
++ jack_log("JackWinMMEOutputPort::Execute BREAK");
++
++ break;
++ }
++ jack_midi_event_t *event = thread_queue->DequeueEvent();
++ if (! event) {
++ break;
++ }
++ jack_time_t frame_time = GetTimeFromFrames(event->time);
++ jack_time_t current_time = GetMicroSeconds();
++ if (frame_time > current_time) {
++ LARGE_INTEGER due_time;
++
++ // 100 ns resolution
++ due_time.QuadPart =
++ -((LONGLONG) ((frame_time - current_time) * 10));
++ if (! SetWaitableTimer(timer, &due_time, 0, NULL, NULL, 0)) {
++ WriteOSError("JackWinMMEOutputPort::Execute",
++ "SetWaitableTimer");
++ break;
++ }
++
++ // Debugging code
++ jack_log("JackWinMMEOutputPort::Execute - waiting at %f for %f "
++ "milliseconds before sending message (current frame: %d, "
++ "send frame: %d)",
++ ((double) current_time) / 1000.0,
++ ((double) (frame_time - current_time)) / 1000.0,
++ GetFramesFromTime(current_time), event->time);
++ // End debugging code
++
++ if (! Wait(timer)) {
++ break;
++ }
++
++ // Debugging code
++ jack_time_t wakeup_time = GetMicroSeconds();
++ jack_log("JackWinMMEOutputPort::Execute - woke up at %f.",
++ ((double) wakeup_time) / 1000.0);
++ if (wakeup_time > frame_time) {
++ jack_log("JackWinMMEOutputPort::Execute - overslept by %f "
++ "milliseconds.",
++ ((double) (wakeup_time - frame_time)) / 1000.0);
++ } else if (wakeup_time < frame_time) {
++ jack_log("JackWinMMEOutputPort::Execute - woke up %f "
++ "milliseconds too early.",
++ ((double) (frame_time - wakeup_time)) / 1000.0);
++ }
++ // End debugging code
++
++ }
++ jack_midi_data_t *data = event->buffer;
++ DWORD message = 0;
++ MMRESULT result;
++ size_t size = event->size;
++ switch (size) {
++ case 3:
++ message |= (((DWORD) data[2]) << 16);
++ // Fallthrough on purpose.
++ case 2:
++ message |= (((DWORD) data[1]) << 8);
++ // Fallthrough on purpose.
++ case 1:
++ message |= (DWORD) data[0];
++ result = midiOutShortMsg(handle, message);
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort::Execute",
++ "midiOutShortMsg", result);
++ }
++ continue;
++ }
++ MIDIHDR header;
++ header.dwBufferLength = size;
++ header.dwFlags = 0;
++ header.lpData = (LPSTR) data;
++ result = midiOutPrepareHeader(handle, &header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort::Execute",
++ "midiOutPrepareHeader", result);
++ continue;
++ }
++ result = midiOutLongMsg(handle, &header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort::Execute", "midiOutLongMsg",
++ result);
++ continue;
++ }
++
++ // System exclusive messages may be sent synchronously or
++ // asynchronously. The choice is up to the WinMME driver. So, we wait
++ // until the message is sent, regardless of the driver's choice.
++ if (! Wait(sysex_semaphore)) {
++ break;
++ }
++
++ result = midiOutUnprepareHeader(handle, &header, sizeof(MIDIHDR));
++ if (result != MMSYSERR_NOERROR) {
++ WriteOutError("JackWinMMEOutputPort::Execute",
++ "midiOutUnprepareHeader", result);
++ break;
++ }
++ }
++ return false;
++}
++
++void
++JackWinMMEOutputPort::GetOutErrorString(MMRESULT error, LPTSTR text)
++{
++ MMRESULT result = midiOutGetErrorText(error, text, MAXERRORLENGTH);
++ if (result != MMSYSERR_NOERROR) {
++ snprintf(text, MAXERRORLENGTH, "Unknown MM error code '%d'", error);
++ }
++}
++
++void
++JackWinMMEOutputPort::HandleMessage(UINT message, DWORD_PTR param1,
++ DWORD_PTR param2)
++{
++ set_threaded_log_function();
++ switch (message) {
++ case MOM_CLOSE:
++ jack_info("JackWinMMEOutputPort::HandleMessage - MIDI device closed.");
++ break;
++ case MOM_DONE:
++ Signal(sysex_semaphore);
++ break;
++ case MOM_OPEN:
++ jack_info("JackWinMMEOutputPort::HandleMessage - MIDI device opened.");
++ break;
++ case MOM_POSITIONCB:
++ LPMIDIHDR header = (LPMIDIHDR) param1;
++ jack_info("JackWinMMEOutputPort::HandleMessage - %d bytes out of %d "
++ "bytes of the current sysex message have been sent.",
++ header->dwOffset, header->dwBytesRecorded);
++ }
++}
++
++bool
++JackWinMMEOutputPort::Init()
++{
++ set_threaded_log_function();
++ // XX: Can more be done? Ideally, this thread should have the JACK server
++ // thread priority + 1.
++ if (thread->AcquireSelfRealTime(GetEngineControl()->fServerPriority)) {
++ jack_error("JackWinMMEOutputPort::Init - could not acquire realtime "
++ "scheduling. Continuing anyway.");
++ }
++ return true;
++}
++
++void
++JackWinMMEOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
++ jack_nframes_t frames)
++{
++ read_queue->ResetMidiBuffer(port_buffer);
++ for (jack_midi_event_t *event = read_queue->DequeueEvent(); event;
++ event = read_queue->DequeueEvent()) {
++
++ switch (thread_queue->EnqueueEvent(event, frames)) {
++ case JackMidiWriteQueue::BUFFER_FULL:
++ jack_error("JackWinMMEOutputPort::ProcessJack - The thread queue "
++ "buffer is full. Dropping event.");
++ break;
++ case JackMidiWriteQueue::BUFFER_TOO_SMALL:
++ jack_error("JackWinMMEOutputPort::ProcessJack - The thread queue "
++ "couldn't enqueue a %d-byte event. Dropping event.",
++ event->size);
++ break;
++ default:
++ Signal(thread_queue_semaphore);
++ }
++ }
++}
++
++bool
++JackWinMMEOutputPort::Signal(HANDLE semaphore)
++{
++ bool result = (bool) ReleaseSemaphore(semaphore, 1, NULL);
++ if (! result) {
++ WriteOSError("JackWinMMEOutputPort::Signal", "ReleaseSemaphore");
++ }
++ return result;
++}
++
++bool
++JackWinMMEOutputPort::Start()
++{
++ if (thread->GetStatus() != JackThread::kIdle) {
++ return true;
++ }
++ timer = CreateWaitableTimer(NULL, FALSE, NULL);
++ if (! timer) {
++ WriteOSError("JackWinMMEOutputPort::Start", "CreateWaitableTimer");
++ return false;
++ }
++ if (! thread->StartSync()) {
++ return true;
++ }
++ jack_error("JackWinMMEOutputPort::Start - failed to start MIDI processing "
++ "thread.");
++ if (! CloseHandle(timer)) {
++ WriteOSError("JackWinMMEOutputPort::Start", "CloseHandle");
++ }
++ return false;
++}
++
++bool
++JackWinMMEOutputPort::Stop()
++{
++ jack_info("JackWinMMEOutputPort::Stop - stopping MIDI output port "
++ "processing thread.");
++
++ int result;
++ const char *verb;
++ switch (thread->GetStatus()) {
++ case JackThread::kIniting:
++ case JackThread::kStarting:
++ result = thread->Kill();
++ verb = "kill";
++ break;
++ case JackThread::kRunning:
++ Signal(thread_queue_semaphore);
++ result = thread->Stop();
++ verb = "stop";
++ break;
++ default:
++ return true;
++ }
++ if (result) {
++ jack_error("JackWinMMEOutputPort::Stop - could not %s MIDI processing "
++ "thread.", verb);
++ }
++ if (! CloseHandle(timer)) {
++ WriteOSError("JackWinMMEOutputPort::Stop", "CloseHandle");
++ result = -1;
++ }
++ return ! result;
++}
++
++bool
++JackWinMMEOutputPort::Wait(HANDLE semaphore)
++{
++ DWORD result = WaitForSingleObject(semaphore, INFINITE);
++ switch (result) {
++ case WAIT_FAILED:
++ WriteOSError("JackWinMMEOutputPort::Wait", "WaitForSingleObject");
++ break;
++ case WAIT_OBJECT_0:
++ return true;
++ default:
++ jack_error("JackWinMMEOutputPort::Wait - unexpected result from "
++ "'WaitForSingleObject'.");
++ }
++ return false;
++}
++
++void
++JackWinMMEOutputPort::WriteOutError(const char *jack_func, const char *mm_func,
++ MMRESULT result)
++{
++ char error_message[MAXERRORLENGTH];
++ GetOutErrorString(result, error_message);
++ jack_error("%s - %s: %s", jack_func, mm_func, error_message);
++}
+--- /dev/null
++++ b/windows/winmme/JackWinMMEOutputPort.h
+@@ -0,0 +1,90 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackWinMMEOutputPort__
++#define __JackWinMMEOutputPort__
++
++#include "JackMidiAsyncQueue.h"
++#include "JackMidiBufferReadQueue.h"
++#include "JackThread.h"
++#include "JackWinMMEPort.h"
++
++namespace Jack {
++
++ class JackWinMMEOutputPort :
++ public JackWinMMEPort, public JackRunnableInterface {
++
++ private:
++
++ static void CALLBACK
++ HandleMessageEvent(HMIDIOUT handle, UINT message, DWORD_PTR port,
++ DWORD_PTR param1, DWORD_PTR param2);
++
++ void
++ GetOutErrorString(MMRESULT error, LPTSTR text);
++
++ void
++ HandleMessage(UINT message, DWORD_PTR param1, DWORD_PTR param2);
++
++ bool
++ Signal(HANDLE semaphore);
++
++ bool
++ Wait(HANDLE semaphore);
++
++ void
++ WriteOutError(const char *jack_func, const char *mm_func,
++ MMRESULT result);
++
++ HMIDIOUT handle;
++ JackMidiBufferReadQueue *read_queue;
++ HANDLE sysex_semaphore;
++ JackThread *thread;
++ JackMidiAsyncQueue *thread_queue;
++ HANDLE thread_queue_semaphore;
++ HANDLE timer;
++
++ public:
++
++ JackWinMMEOutputPort(const char *alias_name, const char *client_name,
++ const char *driver_name, UINT index,
++ size_t max_bytes=4096, size_t max_messages=1024);
++
++ ~JackWinMMEOutputPort();
++
++ bool
++ Execute();
++
++ bool
++ Init();
++
++ void
++ ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames);
++
++ bool
++ Start();
++
++ bool
++ Stop();
++
++ };
++
++}
++
++#endif
+--- /dev/null
++++ b/windows/winmme/JackWinMMEPort.cpp
+@@ -0,0 +1,69 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 <memory>
++#include <stdexcept>
++#include <stdio.h>
++
++#include "JackWinMMEPort.h"
++#include "JackError.h"
++
++using Jack::JackWinMMEPort;
++
++///////////////////////////////////////////////////////////////////////////////
++// Class
++///////////////////////////////////////////////////////////////////////////////
++
++JackWinMMEPort::JackWinMMEPort()
++{}
++
++JackWinMMEPort::~JackWinMMEPort()
++{}
++
++const char *
++JackWinMMEPort::GetAlias()
++{
++ return alias;
++}
++
++const char *
++JackWinMMEPort::GetName()
++{
++ return name;
++}
++
++void
++JackWinMMEPort::GetOSErrorString(LPTSTR text)
++{
++ DWORD error = GetLastError();
++ if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error,
++ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), text,
++ MAXERRORLENGTH, NULL)) {
++ snprintf(text, MAXERRORLENGTH, "Unknown OS error code '%d'", error);
++ }
++}
++
++void
++JackWinMMEPort::WriteOSError(const char *jack_func, const char *os_func)
++{
++ char error_message[MAXERRORLENGTH];
++ GetOSErrorString(error_message);
++ jack_error("%s - %s: %s", jack_func, os_func, error_message);
++}
++
+--- /dev/null
++++ b/windows/winmme/JackWinMMEPort.h
+@@ -0,0 +1,59 @@
++/*
++Copyright (C) 2011 Devin Anderson
++
++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 __JackWinMMEPort__
++#define __JackWinMMEPort__
++
++#include <windows.h>
++#include <mmsystem.h>
++
++#include "JackConstants.h"
++
++namespace Jack {
++
++ class JackWinMMEPort {
++
++ protected:
++
++ char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
++ char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
++
++ public:
++
++ JackWinMMEPort();
++
++ ~JackWinMMEPort();
++
++ const char *
++ GetAlias();
++
++ const char *
++ GetName();
++
++ void
++ GetOSErrorString(LPTSTR text);
++
++ void
++ WriteOSError(const char *jack_func, const char *os_func);
++
++ };
++
++}
++
++#endif
+--- a/wscript
++++ b/wscript
+@@ -11,7 +11,7 @@
+ import re
+ import Logs
+
+-VERSION='1.9.7'
++VERSION='1.9.8'
+ APPNAME='jack'
+ JACK_API_VERSION = '0.1.0'
+
+@@ -127,6 +127,12 @@
+ conf.sub_config('dbus')
+ if conf.env['BUILD_JACKDBUS'] != True:
+ conf.fatal('jackdbus was explicitly requested but cannot be built')
++
++ conf.check_cc(header_name='samplerate.h', define_name="HAVE_SAMPLERATE")
++
++ if conf.is_defined('HAVE_SAMPLERATE'):
++ conf.env['LIB_SAMPLERATE'] = ['samplerate']
++
+ conf.sub_config('example-clients')
+
+ if conf.check_cfg(package='celt', atleast_version='0.11.0', args='--cflags --libs'):
--
jackd2 packaging
More information about the pkg-multimedia-commits
mailing list