From 3e01068967e8bff63f27e36ea76eacbcd17bfb38 Mon Sep 17 00:00:00 2001 From: sletz Date: Fri, 5 Sep 2008 13:36:28 +0000 Subject: Merge Michael Voigt drops branch after reorganization step. git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2880 0c269be4-1314-0410-8aa9-9f06e86f4224 --- ChangeLog | 16 +- common/JackAPI.cpp | 2 +- common/JackActivationCount.h | 2 +- common/JackAtomic.h | 166 +-- common/JackAudioAdapter.cpp | 2 +- common/JackAudioAdapterFactory.cpp | 10 +- common/JackAudioAdapterInterface.cpp | 4 +- common/JackAudioDriver.cpp | 4 +- common/JackClient.h | 3 +- common/JackClientInterface.h | 2 +- common/JackCompilerDeps.h | 25 + common/JackConnectionManager.h | 2 +- common/JackControlAPI.h | 2 +- common/JackDriver.cpp | 4 +- common/JackDriver.h | 2 +- common/JackDriverLoader.cpp | 4 +- common/JackDriverLoader.h | 2 +- common/JackDummyDriver.cpp | 2 +- common/JackEngine.cpp | 5 +- common/JackEngine.h | 3 +- common/JackEngineControl.cpp | 21 +- common/JackError.h | 2 +- common/JackException.h | 2 +- common/JackExports.h | 30 - common/JackExternalClient.h | 2 +- common/JackFifo.cpp | 226 ---- common/JackFifo.h | 71 - common/JackFrameTimer.h | 2 +- common/JackFreewheelDriver.cpp | 4 +- common/JackGlobals.h | 2 +- common/JackGraphManager.cpp | 7 +- common/JackGraphManager.h | 4 +- common/JackInternalClient.cpp | 4 +- common/JackLibAPI.cpp | 2 +- common/JackLibClient.cpp | 2 +- common/JackLibGlobals.h | 9 +- common/JackLoopbackDriver.cpp | 4 +- common/JackMessageBuffer.h | 3 +- common/JackMidiAPI.cpp | 7 +- common/JackMutex.h | 94 +- common/JackNetAdapter.h | 2 +- common/JackNetSocket.h | 2 +- common/JackNetTool.h | 2 +- common/JackNetUnixSocket.cpp | 306 ----- common/JackNetUnixSocket.h | 103 -- common/JackPlatformChannelTransaction.h | 45 - common/JackPlatformClientChannel.h | 59 - common/JackPlatformNetSocket.h | 50 - common/JackPlatformNotifyChannel.h | 59 - common/JackPlatformPlug.h | 25 + common/JackPlatformProcessSync.h | 51 - common/JackPlatformServerChannel.h | 59 - common/JackPlatformServerNotifyChannel.h | 59 - common/JackPlatformSynchro.h | 64 - common/JackPlatformThread.h | 59 - common/JackPort.h | 12 +- common/JackPosixSemaphore.cpp | 219 --- common/JackPosixSemaphore.h | 69 - common/JackPosixThread.cpp | 311 ----- common/JackPosixThread.h | 78 -- common/JackProcessSync.cpp | 79 -- common/JackProcessSync.h | 142 -- common/JackRequest.h | 2 +- common/JackRestartThreadedDriver.cpp | 4 +- common/JackServer.cpp | 4 +- common/JackServer.h | 5 +- common/JackServerAPI.cpp | 6 +- common/JackServerLaunch.cpp | 2 +- common/JackShmMem.h | 17 +- common/JackSocket.cpp | 290 ---- common/JackSocket.h | 99 -- common/JackSocketClientChannel.cpp | 348 ----- common/JackSocketClientChannel.h | 102 -- common/JackSocketNotifyChannel.cpp | 84 -- common/JackSocketNotifyChannel.h | 54 - common/JackSocketServerChannel.cpp | 474 ------- common/JackSocketServerChannel.h | 72 - common/JackSocketServerNotifyChannel.cpp | 64 - common/JackSocketServerNotifyChannel.h | 53 - common/JackSynchro.h | 1 + common/JackSystemDeps.h | 26 + common/JackThread.h | 39 +- common/JackThreadedDriver.cpp | 4 +- common/JackThreadedDriver.h | 2 +- common/JackTime.h | 80 +- common/JackTools.h | 2 +- common/JackTransportEngine.h | 2 +- common/JackTypes.h | 9 +- common/JackWaitThreadedDriver.cpp | 4 +- common/cycles.h | 94 -- common/driver_interface.h | 9 +- common/jack/control.h | 5 +- common/jack/jack.h | 8 +- common/jack/jslist.h | 290 +--- common/jack/systemdeps.h | 62 + common/jack/thread.h | 8 +- common/jack/types.h | 38 +- common/ringbuffer.c | 2 +- common/shm.h | 2 +- common/wscript | 40 +- dbus/controller.c | 423 ++++++ dbus/controller.h | 31 + dbus/controller_iface_configure.c | 1108 +++++++++++++++ dbus/controller_iface_control.c | 324 +++++ dbus/controller_iface_introspectable.c | 156 +++ dbus/controller_iface_patchbay.c | 1851 ++++++++++++++++++++++++++ dbus/controller_iface_transport.c | 38 + dbus/controller_internal.h | 211 +++ dbus/jackdbus.c | 885 ++++++++++++ dbus/jackdbus.h | 292 ++++ dbus/list.h | 874 ++++++++++++ dbus/org.jackaudio.service.in | 3 + dbus/sigsegv.c | 192 +++ dbus/sigsegv.h | 9 + dbus/wscript | 102 ++ dbus/xml.c | 382 ++++++ dbus/xml.h | 36 + dbus/xml_expat.c | 369 +++++ dbus/xml_libxml.c | 797 +++++++++++ dbus/xml_nop.c | 62 + dbus/xml_write_raw.c | 327 +++++ example-clients/wscript | 12 +- linux/JackAtomic_os.h | 77 ++ linux/JackPlatformPlug_os.h | 75 ++ linux/JackTime_os.h | 61 + linux/alsa/JackAlsaAdapter.h | 4 +- linux/alsa/JackAlsaDriver.cpp | 2 +- linux/cycles.h | 94 ++ linux/dbus/controller.c | 423 ------ linux/dbus/controller.h | 31 - linux/dbus/controller_iface_configure.c | 1108 --------------- linux/dbus/controller_iface_control.c | 324 ----- linux/dbus/controller_iface_introspectable.c | 156 --- linux/dbus/controller_iface_patchbay.c | 1851 -------------------------- linux/dbus/controller_iface_transport.c | 38 - linux/dbus/controller_internal.h | 211 --- linux/dbus/jackdbus.c | 885 ------------ linux/dbus/jackdbus.h | 292 ---- linux/dbus/list.h | 874 ------------ linux/dbus/org.jackaudio.service.in | 3 - linux/dbus/sigsegv.c | 192 --- linux/dbus/sigsegv.h | 9 - linux/dbus/wscript | 97 -- linux/dbus/xml.c | 382 ------ linux/dbus/xml.h | 36 - linux/dbus/xml_expat.c | 369 ----- linux/dbus/xml_libxml.c | 797 ----------- linux/dbus/xml_nop.c | 62 - linux/dbus/xml_write_raw.c | 327 ----- linux/firewire/JackFFADODriver.cpp | 2 +- linux/wscript | 4 +- macosx/JackAtomic_os.h | 77 ++ macosx/JackCoreAudioAdapter.h | 2 +- macosx/JackCoreAudioDriver.cpp | 2 +- macosx/JackMacLibClientRPC.cpp | 4 +- macosx/JackMachClientChannel.cpp | 10 +- macosx/JackMachClientChannel.h | 6 +- macosx/JackMachSemaphore.h | 2 +- macosx/JackMachServerChannel.h | 2 +- macosx/JackPlatformPlug_os.h | 67 + macosx/JackTime_os.h | 52 + macosx/Jackdmp.xcodeproj/project.pbxproj | 406 +++--- macosx/wscript | 6 +- posix/JackCompilerDeps_os.h | 32 + posix/JackFifo.cpp | 226 ++++ posix/JackFifo.h | 71 + posix/JackMutex_os.h | 89 ++ posix/JackNetUnixSocket.cpp | 306 +++++ posix/JackNetUnixSocket.h | 103 ++ posix/JackPosixSemaphore.cpp | 219 +++ posix/JackPosixSemaphore.h | 69 + posix/JackPosixThread.cpp | 311 +++++ posix/JackPosixThread.h | 78 ++ posix/JackProcessSync.cpp | 79 ++ posix/JackProcessSync.h | 142 ++ posix/JackShmMem_os.h | 32 + posix/JackSocket.cpp | 290 ++++ posix/JackSocket.h | 99 ++ posix/JackSocketClientChannel.cpp | 348 +++++ posix/JackSocketClientChannel.h | 102 ++ posix/JackSocketNotifyChannel.cpp | 84 ++ posix/JackSocketNotifyChannel.h | 54 + posix/JackSocketServerChannel.cpp | 474 +++++++ posix/JackSocketServerChannel.h | 72 + posix/JackSocketServerNotifyChannel.cpp | 64 + posix/JackSocketServerNotifyChannel.h | 53 + posix/JackSystemDeps_os.h | 27 + posix/JackTypes_os.h | 29 + tests/testSem.cpp | 2 +- tests/testSynchroClient.cpp | 2 +- tests/testSynchroServer.cpp | 2 +- tests/testSynchroServerClient.cpp | 4 +- tests/wscript | 5 +- windows/JackAtomic_os.h | 80 ++ windows/JackCompilerDeps_os.h | 32 + windows/JackMutex_os.h | 75 ++ windows/JackPlatformPlug_os.h | 75 ++ windows/JackPortAudioAdapter.h | 2 +- windows/JackPortAudioDriver.cpp | 4 +- windows/JackShmMem_os.h | 31 + windows/JackSystemDeps_os.h | 31 + windows/JackTime_os.h | 46 + windows/JackTypes_os.h | 30 + windows/JackWinNamedPipeClientChannel.h | 2 +- windows/JackWinNamedPipeServerChannel.h | 2 +- windows/JackWinThread.cpp | 2 +- windows/JackWinThread.h | 8 +- windows/jack_audioadapter.cbp | 12 +- windows/jack_connect.cbp | 15 +- windows/jack_disconnect.cbp | 19 +- windows/jack_dummy.cbp | 12 +- windows/jack_load.cbp | 12 +- windows/jack_lsp.cbp | 9 +- windows/jack_metro.cbp | 12 +- windows/jack_netadapter.cbp | 16 +- windows/jack_netdriver.cbp | 12 +- windows/jack_netmanager.cbp | 12 +- windows/jack_portaudio.cbp | 9 +- windows/jack_unload.cbp | 12 +- windows/jackd.cbp | 9 +- windows/libjack.cbp | 9 +- windows/libjackserver.cbp | 9 +- wscript | 12 +- 223 files changed, 13477 insertions(+), 13530 deletions(-) create mode 100644 common/JackCompilerDeps.h delete mode 100644 common/JackExports.h delete mode 100644 common/JackFifo.cpp delete mode 100644 common/JackFifo.h delete mode 100644 common/JackNetUnixSocket.cpp delete mode 100644 common/JackNetUnixSocket.h delete mode 100644 common/JackPlatformChannelTransaction.h delete mode 100644 common/JackPlatformClientChannel.h delete mode 100644 common/JackPlatformNetSocket.h delete mode 100644 common/JackPlatformNotifyChannel.h create mode 100644 common/JackPlatformPlug.h delete mode 100644 common/JackPlatformProcessSync.h delete mode 100644 common/JackPlatformServerChannel.h delete mode 100644 common/JackPlatformServerNotifyChannel.h delete mode 100644 common/JackPlatformSynchro.h delete mode 100644 common/JackPlatformThread.h delete mode 100644 common/JackPosixSemaphore.cpp delete mode 100644 common/JackPosixSemaphore.h delete mode 100644 common/JackPosixThread.cpp delete mode 100644 common/JackPosixThread.h delete mode 100644 common/JackProcessSync.cpp delete mode 100644 common/JackProcessSync.h delete mode 100644 common/JackSocket.cpp delete mode 100644 common/JackSocket.h delete mode 100644 common/JackSocketClientChannel.cpp delete mode 100644 common/JackSocketClientChannel.h delete mode 100644 common/JackSocketNotifyChannel.cpp delete mode 100644 common/JackSocketNotifyChannel.h delete mode 100644 common/JackSocketServerChannel.cpp delete mode 100644 common/JackSocketServerChannel.h delete mode 100644 common/JackSocketServerNotifyChannel.cpp delete mode 100644 common/JackSocketServerNotifyChannel.h create mode 100644 common/JackSystemDeps.h delete mode 100644 common/cycles.h create mode 100644 common/jack/systemdeps.h create mode 100644 dbus/controller.c create mode 100644 dbus/controller.h create mode 100644 dbus/controller_iface_configure.c create mode 100644 dbus/controller_iface_control.c create mode 100644 dbus/controller_iface_introspectable.c create mode 100644 dbus/controller_iface_patchbay.c create mode 100644 dbus/controller_iface_transport.c create mode 100644 dbus/controller_internal.h create mode 100644 dbus/jackdbus.c create mode 100644 dbus/jackdbus.h create mode 100644 dbus/list.h create mode 100644 dbus/org.jackaudio.service.in create mode 100644 dbus/sigsegv.c create mode 100644 dbus/sigsegv.h create mode 100644 dbus/wscript create mode 100644 dbus/xml.c create mode 100644 dbus/xml.h create mode 100644 dbus/xml_expat.c create mode 100644 dbus/xml_libxml.c create mode 100644 dbus/xml_nop.c create mode 100644 dbus/xml_write_raw.c create mode 100644 linux/JackAtomic_os.h create mode 100644 linux/JackPlatformPlug_os.h create mode 100644 linux/JackTime_os.h create mode 100644 linux/cycles.h delete mode 100644 linux/dbus/controller.c delete mode 100644 linux/dbus/controller.h delete mode 100644 linux/dbus/controller_iface_configure.c delete mode 100644 linux/dbus/controller_iface_control.c delete mode 100644 linux/dbus/controller_iface_introspectable.c delete mode 100644 linux/dbus/controller_iface_patchbay.c delete mode 100644 linux/dbus/controller_iface_transport.c delete mode 100644 linux/dbus/controller_internal.h delete mode 100644 linux/dbus/jackdbus.c delete mode 100644 linux/dbus/jackdbus.h delete mode 100644 linux/dbus/list.h delete mode 100644 linux/dbus/org.jackaudio.service.in delete mode 100644 linux/dbus/sigsegv.c delete mode 100644 linux/dbus/sigsegv.h delete mode 100644 linux/dbus/wscript delete mode 100644 linux/dbus/xml.c delete mode 100644 linux/dbus/xml.h delete mode 100644 linux/dbus/xml_expat.c delete mode 100644 linux/dbus/xml_libxml.c delete mode 100644 linux/dbus/xml_nop.c delete mode 100644 linux/dbus/xml_write_raw.c create mode 100644 macosx/JackAtomic_os.h create mode 100644 macosx/JackPlatformPlug_os.h create mode 100644 macosx/JackTime_os.h create mode 100644 posix/JackCompilerDeps_os.h create mode 100644 posix/JackFifo.cpp create mode 100644 posix/JackFifo.h create mode 100644 posix/JackMutex_os.h create mode 100644 posix/JackNetUnixSocket.cpp create mode 100644 posix/JackNetUnixSocket.h create mode 100644 posix/JackPosixSemaphore.cpp create mode 100644 posix/JackPosixSemaphore.h create mode 100644 posix/JackPosixThread.cpp create mode 100644 posix/JackPosixThread.h create mode 100644 posix/JackProcessSync.cpp create mode 100644 posix/JackProcessSync.h create mode 100644 posix/JackShmMem_os.h create mode 100644 posix/JackSocket.cpp create mode 100644 posix/JackSocket.h create mode 100644 posix/JackSocketClientChannel.cpp create mode 100644 posix/JackSocketClientChannel.h create mode 100644 posix/JackSocketNotifyChannel.cpp create mode 100644 posix/JackSocketNotifyChannel.h create mode 100644 posix/JackSocketServerChannel.cpp create mode 100644 posix/JackSocketServerChannel.h create mode 100644 posix/JackSocketServerNotifyChannel.cpp create mode 100644 posix/JackSocketServerNotifyChannel.h create mode 100644 posix/JackSystemDeps_os.h create mode 100644 posix/JackTypes_os.h create mode 100644 windows/JackAtomic_os.h create mode 100644 windows/JackCompilerDeps_os.h create mode 100644 windows/JackMutex_os.h create mode 100644 windows/JackPlatformPlug_os.h create mode 100644 windows/JackShmMem_os.h create mode 100644 windows/JackSystemDeps_os.h create mode 100644 windows/JackTime_os.h create mode 100644 windows/JackTypes_os.h diff --git a/ChangeLog b/ChangeLog index 1a8468d2..64abde55 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,8 +22,13 @@ Florian Faber Jackdmp changes log --------------------------- -2008-09-04 Stephane Letz +2008-08-05 Stephane Letz + * Merge Michael Voigt "drops" branch after reorganization step. + +2008-08-04 Stephane Letz + + * Michael Voigt 4th source reorganization patch. * Correct JackNetDriver initialization. 2008-09-03 Stephane Letz @@ -33,8 +38,17 @@ Florian Faber 2008-09-01 Stephane Letz + * Michael Voigt third source reorganization patch. * Add new jack_set_port_rename_callback API, jack_port_set_name is now a server request that call port rename callbacks. +2008-08-31 Stephane Letz + + * Michael Voigt second source reorganization patch. + +2008-08-28 Stephane Letz + + * Michael Voigt first source reorganization patch. + 2008-08-26 Stephane Letz * Better parameter handling in JackCoreAudioAdapter. diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index d90558bb..b651d897 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackClientControl.h" #include "JackGlobals.h" #include "JackTime.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackPortType.h" #ifdef __APPLE__ diff --git a/common/JackActivationCount.h b/common/JackActivationCount.h index 9b48c10a..c9824937 100644 --- a/common/JackActivationCount.h +++ b/common/JackActivationCount.h @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackActivationCount__ #define __JackActivationCount__ -#include "JackPlatformSynchro.h" +#include "JackPlatformPlug.h" #include "JackTime.h" #include "JackTypes.h" diff --git a/common/JackAtomic.h b/common/JackAtomic.h index 0f037b8a..1da0cb63 100644 --- a/common/JackAtomic.h +++ b/common/JackAtomic.h @@ -22,171 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackTypes.h" -#if defined(__APPLE__) - -#if defined(__ppc__) || defined(__ppc64__) - -static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr) -{ - register int result; - asm volatile ( - "# CAS \n" - " lwarx r0, 0, %1 \n" // creates a reservation on addr - " cmpw r0, %2 \n" // test value at addr - " bne- 1f \n" - " sync \n" // synchronize instructions - " stwcx. %3, 0, %1 \n" // if the reservation is not altered - // stores the new value at addr - " bne- 1f \n" - " li %0, 1 \n" - " b 2f \n" - "1: \n" - " li %0, 0 \n" - "2: \n" - : "=r" (result) - : "r" (addr), "r" (value), "r" (newvalue) - : "r0" - ); - return result; -} - -#endif - -#if defined(__i386__) || defined(__x86_64__) - -#ifdef __SMP__ -# define LOCK "lock ; " -#else -# define LOCK "" -#endif - -static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) -{ - register char ret; - __asm__ __volatile__ ( - "# CAS \n\t" - LOCK "cmpxchg %2, (%1) \n\t" - "sete %0 \n\t" - : "=a" (ret) - : "c" (addr), "d" (newvalue), "a" (value) - ); - return ret; -} - -#endif - -#endif - -#ifdef __linux__ - -#ifdef __PPC__ - -static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr) -{ - register int result; - register UInt32 tmp; - asm volatile ( - "# CAS \n" - " lwarx %4, 0, %1 \n" // creates a reservation on addr - " cmpw %4, %2 \n" // test value at addr - " bne- 1f \n" - " sync \n" // synchronize instructions - " stwcx. %3, 0, %1 \n" // if the reservation is not altered - // stores the new value at addr - " bne- 1f \n" - " li %0, 1 \n" - " b 2f \n" - "1: \n" - " li %0, 0 \n" - "2: \n" - : "=r" (result) - : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp) - ); - return result; -} - -#endif - -#if defined(__i386__) || defined(__x86_64__) - -#ifdef __SMP__ -# define LOCK "lock ; " -#else -# define LOCK "" -#endif - -static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) -{ - register char ret; - __asm__ __volatile__ ( - "# CAS \n\t" - LOCK "cmpxchg %2, (%1) \n\t" - "sete %0 \n\t" - : "=a" (ret) - : "c" (addr), "d" (newvalue), "a" (value) - ); - return ret; -} - -#endif - -#endif - -#ifdef WIN32 - -#ifndef __MINGW32__ -#ifdef __SMP__ -# define LOCK lock -#else -# define LOCK -#endif - -#define inline __inline - -//---------------------------------------------------------------- -// CAS functions -//---------------------------------------------------------------- -inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void * addr) -{ - register char c; - __asm { - push ebx - push esi - mov esi, addr - mov eax, value - mov ebx, newvalue - LOCK cmpxchg dword ptr [esi], ebx - sete c - pop esi - pop ebx - } - return c; -} - -#else - -#ifdef __SMP__ -# define LOCK "lock ; " -#else -# define LOCK "" -#endif - -static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) -{ - register char ret; - __asm__ __volatile__ ( - "# CAS \n\t" - LOCK "cmpxchg %2, (%1) \n\t" - "sete %0 \n\t" - : "=a" (ret) - : "c" (addr), "d" (newvalue), "a" (value) - ); - return ret; -} - -#endif - -#endif +#include "JackAtomic_os.h" static inline long INC_ATOMIC(volatile SInt32* val) { diff --git a/common/JackAudioAdapter.cpp b/common/JackAudioAdapter.cpp index 988dc519..64a57c5a 100644 --- a/common/JackAudioAdapter.cpp +++ b/common/JackAudioAdapter.cpp @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackAudioAdapter.h" #include "JackLibSampleRateResampler.h" #include "JackError.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackTools.h" #include "jslist.h" #include diff --git a/common/JackAudioAdapterFactory.cpp b/common/JackAudioAdapterFactory.cpp index 85d14d97..5e4db60c 100644 --- a/common/JackAudioAdapterFactory.cpp +++ b/common/JackAudioAdapterFactory.cpp @@ -23,11 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include -#ifdef __cplusplus -extern "C" -{ -#endif - #include "driver_interface.h" #ifdef __linux__ @@ -40,6 +35,11 @@ extern "C" #ifdef WIN32 #include "JackPortAudioAdapter.h" +#endif + +#ifdef __cplusplus +extern "C" +{ #endif using namespace Jack; diff --git a/common/JackAudioAdapterInterface.cpp b/common/JackAudioAdapterInterface.cpp index 6e940b79..fe9b00ef 100644 --- a/common/JackAudioAdapterInterface.cpp +++ b/common/JackAudioAdapterInterface.cpp @@ -41,8 +41,8 @@ namespace Jack char buffer[1024]; FILE* file = fopen("JackAudioAdapter.log", "w"); - int MAX = (fCount) % TABLE_MAX - 1; - for (int i = 1; i < MAX; i++) + int max = (fCount) % TABLE_MAX - 1; + 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+1].time1 - fTable[i].time1, diff --git a/common/JackAudioDriver.cpp b/common/JackAudioDriver.cpp index 43d0d266..14df7bc0 100644 --- a/common/JackAudioDriver.cpp +++ b/common/JackAudioDriver.cpp @@ -22,9 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackAudioDriver.h" #include "JackTime.h" diff --git a/common/JackClient.h b/common/JackClient.h index 3a7abe03..6ab6decc 100644 --- a/common/JackClient.h +++ b/common/JackClient.h @@ -29,8 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "varargs.h" #include -#include "JackPlatformSynchro.h" -#include "JackPlatformThread.h" +#include "JackPlatformPlug.h" #include "JackChannel.h" namespace Jack diff --git a/common/JackClientInterface.h b/common/JackClientInterface.h index dcea6fe8..2e7ec0f7 100644 --- a/common/JackClientInterface.h +++ b/common/JackClientInterface.h @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackClientInterface__ #define __JackClientInterface__ -#include "JackExports.h" +#include "JackCompilerDeps.h" namespace Jack { diff --git a/common/JackCompilerDeps.h b/common/JackCompilerDeps.h new file mode 100644 index 00000000..04f87c19 --- /dev/null +++ b/common/JackCompilerDeps.h @@ -0,0 +1,25 @@ +/* +Copyright (C) 2004-2005 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 __JackCompilerDeps__ +#define __JackCompilerDeps__ + +#include "JackCompilerDeps_os.h" + +#endif diff --git a/common/JackConnectionManager.h b/common/JackConnectionManager.h index 2db347bf..13b3aa03 100644 --- a/common/JackConnectionManager.h +++ b/common/JackConnectionManager.h @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackConstants.h" #include "JackActivationCount.h" #include "JackError.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include diff --git a/common/JackControlAPI.h b/common/JackControlAPI.h index 0255e5c9..032e0e9a 100644 --- a/common/JackControlAPI.h +++ b/common/JackControlAPI.h @@ -23,7 +23,7 @@ #define __JackControlAPI__ #include "jslist.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #ifdef WIN32 #ifdef __MINGW32__ diff --git a/common/JackDriver.cpp b/common/JackDriver.cpp index f231d5dd..d9b47c7c 100644 --- a/common/JackDriver.cpp +++ b/common/JackDriver.cpp @@ -22,9 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackDriver.h" #include "JackTime.h" diff --git a/common/JackDriver.h b/common/JackDriver.h index 7e6b27a0..3b188b4f 100644 --- a/common/JackDriver.h +++ b/common/JackDriver.h @@ -24,7 +24,7 @@ #include "types.h" #include "JackClientInterface.h" #include "JackConstants.h" -#include "JackPlatformSynchro.h" +#include "JackPlatformPlug.h" #include "JackClientControl.h" #include diff --git a/common/JackDriverLoader.cpp b/common/JackDriverLoader.cpp index 52d41d0e..d743070b 100644 --- a/common/JackDriverLoader.cpp +++ b/common/JackDriverLoader.cpp @@ -22,9 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" /* #ifndef WIN32 diff --git a/common/JackDriverLoader.h b/common/JackDriverLoader.h index e1c86685..b6025115 100644 --- a/common/JackDriverLoader.h +++ b/common/JackDriverLoader.h @@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "driver_interface.h" #include "JackControlAPI.h" -#include "JackPlatformSynchro.h" +#include "JackPlatformPlug.h" #ifdef WIN32 diff --git a/common/JackDummyDriver.cpp b/common/JackDummyDriver.cpp index 746ce835..b1f294f8 100644 --- a/common/JackDummyDriver.cpp +++ b/common/JackDummyDriver.cpp @@ -27,7 +27,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackGraphManager.h" #include "JackDriverLoader.h" #include "JackThreadedDriver.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include #include diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index 9d8aed55..bd878a20 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -25,10 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include -#ifndef WIN32 -#include -#include -#endif +#include "JackSystemDeps.h" #include "JackLockedEngine.h" #include "JackExternalClient.h" diff --git a/common/JackEngine.h b/common/JackEngine.h index da3d6d19..dd61b74e 100644 --- a/common/JackEngine.h +++ b/common/JackEngine.h @@ -24,8 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackGraphManager.h" #include "JackSynchro.h" #include "JackTransportEngine.h" -#include "JackPlatformProcessSync.h" -#include "JackPlatformServerNotifyChannel.h" +#include "JackPlatformPlug.h" namespace Jack { diff --git a/common/JackEngineControl.cpp b/common/JackEngineControl.cpp index 0743eec0..67b7deff 100644 --- a/common/JackEngineControl.cpp +++ b/common/JackEngineControl.cpp @@ -32,6 +32,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { +static inline _jack_time_t JACK_MAX(_jack_time_t a, _jack_time_t b) +{ + return (a < b) ? b : a; +} + void JackEngineControl::CycleIncTime(jack_time_t callback_usecs) { // Timer @@ -67,16 +72,6 @@ void JackEngineControl::ReadFrameTime(JackTimer* timer) fFrameTimer.ReadFrameTime(timer); } -// Private -#ifdef WIN32 -inline jack_time_t MAX(jack_time_t a, jack_time_t b) -{ - return (a < b) ? b : a; -} -#else -#define MAX(a,b) std::max((a),(b)) -#endif - void JackEngineControl::CalcCPULoad(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, @@ -92,7 +87,7 @@ void JackEngineControl::CalcCPULoad(JackClientInterface** table, JackClientInterface* client = table[i]; JackClientTiming* timing = manager->GetClientTiming(i); if (client && client->GetClientControl()->fActive && timing->fStatus == Finished) - last_cycle_end = MAX(last_cycle_end, timing->fFinishedAt); + last_cycle_end = JACK_MAX(last_cycle_end, timing->fFinishedAt); } } @@ -108,9 +103,9 @@ void JackEngineControl::CalcCPULoad(JackClientInterface** table, jack_time_t max_usecs = 0; for (int i = 0; i < JACK_ENGINE_ROLLING_COUNT; i++) - max_usecs = MAX(fRollingClientUsecs[i], max_usecs); + max_usecs = JACK_MAX(fRollingClientUsecs[i], max_usecs); - fMaxUsecs = MAX(fMaxUsecs, max_usecs); + fMaxUsecs = JACK_MAX(fMaxUsecs, max_usecs); fSpareUsecs = jack_time_t((max_usecs < fPeriodUsecs) ? fPeriodUsecs - max_usecs : 0); fCPULoad = ((1.f - (float(fSpareUsecs) / float(fPeriodUsecs))) * 50.f + (fCPULoad * 0.5f)); } diff --git a/common/JackError.h b/common/JackError.h index 492e023e..309d588d 100644 --- a/common/JackError.h +++ b/common/JackError.h @@ -25,7 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "types.h" #ifdef __cplusplus diff --git a/common/JackException.h b/common/JackException.h index f084d7a1..86ecc055 100644 --- a/common/JackException.h +++ b/common/JackException.h @@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include #include -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackError.h" namespace Jack diff --git a/common/JackExports.h b/common/JackExports.h deleted file mode 100644 index 39849c23..00000000 --- a/common/JackExports.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright (C) 2004-2005 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 __JackExports__ -#define __JackExports__ - -#ifdef WIN32 -#define EXPORT __declspec(dllexport) -#else -#define EXPORT __attribute__ ((visibility("default"))) -#endif - -#endif - diff --git a/common/JackExternalClient.h b/common/JackExternalClient.h index 6e54aedf..daafb199 100644 --- a/common/JackExternalClient.h +++ b/common/JackExternalClient.h @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #define __JackExternalClient__ #include "JackClientInterface.h" -#include "JackPlatformNotifyChannel.h" +#include "JackPlatformPlug.h" namespace Jack { diff --git a/common/JackFifo.cpp b/common/JackFifo.cpp deleted file mode 100644 index 9b11527a..00000000 --- a/common/JackFifo.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackFifo.h" -#include "JackError.h" -#include "JackConstants.h" -#include -#include -#include -#include -#include - -namespace Jack -{ - -void JackFifo::BuildName(const char* name, const char* server_name, char* res) -{ - sprintf(res, "%s/jack_fifo.%s_%s", jack_client_dir, server_name, name); -} - -bool JackFifo::Signal() -{ - bool res; - char c = 0; - - if (fFifo < 0) { - jack_error("JackFifo::Signal name = %s already desallocated!!", fName); - return false; - } - - if (fFlush) - return true; - - if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) { - jack_error("JackFifo::Signal name = %s err = %s", fName, strerror(errno)); - } - return !res; -} - -bool JackFifo::SignalAll() -{ - bool res; - char c = 0; - - if (fFifo < 0) { - jack_error("JackFifo::SignalAll name = %s already desallocated!!", fName); - return false; - } - - if (fFlush) - return true; - - if ((res = (write(fFifo, &c, sizeof(c)) != sizeof(c)))) { - jack_error("JackFifo::SignalAll name = %s err = %s", fName, strerror(errno)); - } - return !res; -} - -bool JackFifo::Wait() -{ - bool res; - char c; - - if (fFifo < 0) { - jack_error("JackFifo::Wait name = %s already desallocated!!", fName); - return false; - } - - if ((res = (read(fFifo, &c, sizeof(c)) != sizeof(c)))) { - jack_error("JackFifo::Wait name = %s err = %s", fName, strerror(errno)); - } - return !res; -} - -#ifdef __APPLE__ -#warning JackFifo::TimedWait not available : synchronous mode may not work correctly if FIFO are used -bool JackFifo::TimedWait(long usec) -{ - return Wait(); -} -#else -// Does not work on OSX ?? -bool JackFifo::TimedWait(long usec) -{ - assert(fFifo >= 0); - - if ((poll(&fPoll, 1, usec / 1000) < 0) && (errno != EINTR)) { - jack_error("JackFifo::TimedWait name = %s err = %s", fName, strerror(errno)); - return false; - } - - if (fPoll.revents & POLLIN) { - return Wait(); - } else { - jack_error("JackFifo::TimedWait name = %s usec = %ld err = %s", fName, usec, strerror(errno)); - // Wait failure but we still continue... - return true; - } -} -#endif - -// Server side -bool JackFifo::Allocate(const char* name, const char* server_name, int value) -{ - struct stat statbuf; - BuildName(name, server_name, fName); - - jack_log("JackFifo::Allocate name = %s", fName); - - if (stat(fName, &statbuf)) { - if (errno == ENOENT) { - if (mkfifo(fName, 0666) < 0) { - jack_error("Cannot create inter-client FIFO [%s] (%s)\n", name, strerror(errno)); - return false; - } - } else { - jack_error("Cannot check on FIFO %s\n", name); - return false; - } - } else { - if (!S_ISFIFO(statbuf.st_mode)) { - jack_error("FIFO (%s) already exists, but is not a FIFO!\n", name); - return false; - } - } - - if ((fFifo = open(fName, O_RDWR | O_CREAT, 0666)) < 0) { - jack_error("Cannot open fifo [%s] (%s)", name, strerror(errno)); - return false; - } else { - fPoll.fd = fFifo; - fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL; - return true; - } -} - -// Client side -bool JackFifo::ConnectAux(const char* name, const char* server_name, int access) -{ - BuildName(name, server_name, fName); - jack_log("JackFifo::ConnectAux name = %s", fName); - - // Temporary... - if (fFifo >= 0) { - jack_log("Already connected name = %s", name); - return true; - } - - if ((fFifo = open(fName, access)) < 0) { - jack_error("Connect: can't connect named fifo name = %s err = %s", fName, strerror(errno)); - return false; - } else { - fPoll.fd = fFifo; - fPoll.events = POLLERR | POLLIN | POLLHUP | POLLNVAL; - return true; - } -} - -bool JackFifo::Connect(const char* name, const char* server_name) -{ - return ConnectAux(name, server_name, O_RDWR); -} - -bool JackFifo::ConnectOutput(const char* name, const char* server_name) -{ - return ConnectAux(name, server_name, O_WRONLY | O_NONBLOCK); -} - -bool JackFifo::ConnectInput(const char* name, const char* server_name) -{ - return ConnectAux(name, server_name, O_RDONLY); -} - -bool JackFifo::Disconnect() -{ - if (fFifo >= 0) { - jack_log("JackFifo::Disconnect %s", fName); - if (close(fFifo) != 0) { - jack_error("Disconnect: can't disconnect named fifo name = %s err = %s", fName, strerror(errno)); - return false; - } else { - fFifo = -1; - return true; - } - } else { - return true; - } -} - -// Server side : destroy the fifo -void JackFifo::Destroy() -{ - if (fFifo > 0) { - jack_log("JackFifo::Destroy name = %s", fName); - unlink(fName); - if (close(fFifo) != 0) { - jack_error("Destroy: can't destroy fifo name = %s err = %s", fName, strerror(errno)); - } - fFifo = -1; - } else { - jack_error("JackFifo::Destroy fifo < 0"); - } -} - -} // end of namespace - diff --git a/common/JackFifo.h b/common/JackFifo.h deleted file mode 100644 index b0534ea0..00000000 --- a/common/JackFifo.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -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 __JackFifo__ -#define __JackFifo__ - -#include "JackSynchro.h" -#include "JackExports.h" -#include -#include - -namespace Jack -{ - -/*! -\brief Inter process synchronization using Fifo. -*/ - -class EXPORT JackFifo : public detail::JackSynchro -{ - - private: - - int fFifo; - pollfd fPoll; - - bool ConnectAux(const char* name, const char* server_name, int access); - - protected: - - void BuildName(const char* name, const char* server_name, char* res); - - public: - - JackFifo(): fFifo( -1) - {} - - bool Signal(); - bool SignalAll(); - bool Wait(); - bool TimedWait(long usec); - - bool Allocate(const char* name, const char* server_name, int value); - bool Connect(const char* name, const char* server_name); - bool ConnectInput(const char* name, const char* server_name); - bool ConnectOutput(const char* name, const char* server_name); - bool Disconnect(); - void Destroy(); -}; - -} // end of namespace - - -#endif - diff --git a/common/JackFrameTimer.h b/common/JackFrameTimer.h index 68ae3fa9..80b8cf34 100644 --- a/common/JackFrameTimer.h +++ b/common/JackFrameTimer.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define __JackFrameTimer__ #include "JackAtomicState.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "types.h" namespace Jack diff --git a/common/JackFreewheelDriver.cpp b/common/JackFreewheelDriver.cpp index 96311365..5c4c713e 100644 --- a/common/JackFreewheelDriver.cpp +++ b/common/JackFreewheelDriver.cpp @@ -22,9 +22,7 @@ #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackFreewheelDriver.h" #include "JackEngineControl.h" diff --git a/common/JackGlobals.h b/common/JackGlobals.h index a19e8616..9ef2df28 100644 --- a/common/JackGlobals.h +++ b/common/JackGlobals.h @@ -20,7 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef __JackGlobals__ #define __JackGlobals__ -#include "JackPlatformThread.h" +#include "JackPlatformPlug.h" extern jack_tls_key gRealTime; extern jack_tls_key g_key_log_function; diff --git a/common/JackGraphManager.cpp b/common/JackGraphManager.cpp index 1c71e82e..5b935060 100644 --- a/common/JackGraphManager.cpp +++ b/common/JackGraphManager.cpp @@ -33,11 +33,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { -static inline jack_nframes_t MAX(jack_nframes_t a, jack_nframes_t b) -{ - return (a < b) ? b : a; -} - static void AssertPort(jack_port_id_t port_index) { if (port_index >= PORT_NUM) { @@ -240,7 +235,7 @@ jack_nframes_t JackGraphManager::ComputeTotalLatencyAux(jack_port_id_t port_inde jack_nframes_t this_latency = (dst_port->fFlags & JackPortIsTerminal) ? dst_port->GetLatency() : ComputeTotalLatencyAux(dst_index, port_index, manager, hop_count + 1); - max_latency = MAX(max_latency, this_latency); + max_latency = ((max_latency > this_latency) ? max_latency : this_latency); } } diff --git a/common/JackGraphManager.h b/common/JackGraphManager.h index 5c111d14..0eee54ba 100644 --- a/common/JackGraphManager.h +++ b/common/JackGraphManager.h @@ -26,7 +26,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackConstants.h" #include "JackConnectionManager.h" #include "JackAtomicState.h" -#include "JackPlatformSynchro.h" +#include "JackPlatformPlug.h" +#include "JackSystemDeps.h" + namespace Jack { diff --git a/common/JackInternalClient.cpp b/common/JackInternalClient.cpp index 50b3c42a..93f60f6e 100644 --- a/common/JackInternalClient.cpp +++ b/common/JackInternalClient.cpp @@ -22,9 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #ifndef WIN32 #ifndef ADDON_DIR diff --git a/common/JackLibAPI.cpp b/common/JackLibAPI.cpp index ac415a7f..d22a0834 100644 --- a/common/JackLibAPI.cpp +++ b/common/JackLibAPI.cpp @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackLibGlobals.h" #include "JackGlobals.h" #include "JackServerLaunch.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackTools.h" using namespace Jack; diff --git a/common/JackLibClient.cpp b/common/JackLibClient.cpp index 6134a175..ed3d6fdb 100644 --- a/common/JackLibClient.cpp +++ b/common/JackLibClient.cpp @@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackTime.h" #include "JackLibGlobals.h" #include "JackGlobals.h" -#include "JackPlatformClientChannel.h" +#include "JackPlatformPlug.h" #include "JackTools.h" namespace Jack diff --git a/common/JackLibGlobals.h b/common/JackLibGlobals.h index 484648f7..8c458505 100644 --- a/common/JackLibGlobals.h +++ b/common/JackLibGlobals.h @@ -22,12 +22,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackShmMem.h" #include "JackEngineControl.h" -#ifdef __APPLE__ -#include "JackMachPort.h" -#include -#endif #include "JackGlobals.h" -#include "JackPlatformSynchro.h" +#include "JackPlatformPlug.h" #include "JackGraphManager.h" #include "JackMessageBuffer.h" #include "JackTime.h" @@ -48,9 +44,6 @@ struct JackLibGlobals JackShmReadWritePtr fGraphManager; /*! Shared memory Port manager */ JackShmReadWritePtr fEngineControl; /*! Shared engine control */ // transport engine has to be writable JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */ -#ifdef __APPLE__ - std::map fClientTable; /*! Client table */ -#endif static int fClientCount; static JackLibGlobals* fGlobals; diff --git a/common/JackLoopbackDriver.cpp b/common/JackLoopbackDriver.cpp index f676225a..868d67d3 100644 --- a/common/JackLoopbackDriver.cpp +++ b/common/JackLoopbackDriver.cpp @@ -22,9 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackLoopbackDriver.h" #include "JackEngineControl.h" diff --git a/common/JackMessageBuffer.h b/common/JackMessageBuffer.h index d9d76973..9225dec3 100644 --- a/common/JackMessageBuffer.h +++ b/common/JackMessageBuffer.h @@ -30,10 +30,9 @@ #ifndef __JackMessageBuffer__ #define __JackMessageBuffer__ -#include "JackPlatformThread.h" +#include "JackPlatformPlug.h" #include "JackMutex.h" #include "JackAtomic.h" -#include "JackPlatformProcessSync.h" namespace Jack { diff --git a/common/JackMidiAPI.cpp b/common/JackMidiAPI.cpp index 445827ac..1367302d 100644 --- a/common/JackMidiAPI.cpp +++ b/common/JackMidiAPI.cpp @@ -24,13 +24,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackError.h" #include "JackMidiPort.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include #include - -#ifdef WIN32 -#define ENOBUFS 55 -#endif +#include "JackSystemDeps.h" #ifdef __cplusplus extern "C" diff --git a/common/JackMutex.h b/common/JackMutex.h index 33b71255..bfa32bf4 100644 --- a/common/JackMutex.h +++ b/common/JackMutex.h @@ -22,105 +22,13 @@ #ifndef __JackMutex__ #define __JackMutex__ -#ifdef WIN32 -#include -#else -#include -#endif +#include "JackMutex_os.h" #include #include "JackError.h" namespace Jack { - -/*! -\brief Mutex abstraction. -*/ - -class JackMutex -{ - - private: - -#ifdef WIN32 - HANDLE fMutex; -#else - pthread_mutex_t fMutex; -#endif - - public: - -#ifdef WIN32 - - JackMutex() - { - // In recursive mode by default - fMutex = (HANDLE)CreateMutex(0, FALSE, 0); - } - ~JackMutex() - { - CloseHandle(fMutex); - } - - void Lock() - { - DWORD dwWaitResult = WaitForSingleObject(fMutex, INFINITE); - } - - bool Trylock() - { - return (WAIT_OBJECT_0 == WaitForSingleObject(fMutex, 0)); - } - - void Unlock() - { - ReleaseMutex(fMutex); - } - -#else - - JackMutex() - { - // Use recursive mutex - pthread_mutexattr_t mutex_attr; - int res; - res = pthread_mutexattr_init(&mutex_attr); - assert(res == 0); - res = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); - assert(res == 0); - res = pthread_mutex_init(&fMutex, &mutex_attr); - assert(res == 0); - res = pthread_mutexattr_destroy(&mutex_attr); - assert(res == 0); - } - ~JackMutex() - { - pthread_mutex_destroy(&fMutex); - } - - void Lock() - { - int res = pthread_mutex_lock(&fMutex); - if (res != 0) - jack_error("JackMutex::Lock res = %d", res); - } - - bool Trylock() - { - return (pthread_mutex_trylock(&fMutex) == 0); - } - - void Unlock() - { - int res = pthread_mutex_unlock(&fMutex); - if (res != 0) - jack_error("JackMutex::Unlock res = %d", res); - } - -#endif -}; - /*! \brief Base class for "lockable" objects. */ diff --git a/common/JackNetAdapter.h b/common/JackNetAdapter.h index b6028b96..69da0ac7 100644 --- a/common/JackNetAdapter.h +++ b/common/JackNetAdapter.h @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include "JackAudioAdapterInterface.h" -#include "JackPlatformThread.h" +#include "JackPlatformPlug.h" #include "JackNetInterface.h" namespace Jack diff --git a/common/JackNetSocket.h b/common/JackNetSocket.h index b7f7f3d5..fdd6c91e 100644 --- a/common/JackNetSocket.h +++ b/common/JackNetSocket.h @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __JackNetSocket__ #define __JackNetSocket__ -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackError.h" #include #include diff --git a/common/JackNetTool.h b/common/JackNetTool.h index a1944a7f..65122b16 100644 --- a/common/JackNetTool.h +++ b/common/JackNetTool.h @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackConstants.h" #include "JackMidiPort.h" #include "JackTools.h" -#include "JackPlatformNetSocket.h" +#include "JackPlatformPlug.h" #include "types.h" #include "transport.h" #include diff --git a/common/JackNetUnixSocket.cpp b/common/JackNetUnixSocket.cpp deleted file mode 100644 index 301e4bc5..00000000 --- a/common/JackNetUnixSocket.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* -Copyright (C) 2008 Romain Moret at Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "JackNetUnixSocket.h" - -namespace Jack -{ - //utility ********************************************************************************************************* - 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" ); - return SOCKET_ERROR; - } - return 0; - } - - //construct/destruct*********************************************************************************************** - JackNetUnixSocket::JackNetUnixSocket() - { - fSockfd = 0; - fPort = 0; - fSendAddr.sin_family = AF_INET; - 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 ); - } - - JackNetUnixSocket::JackNetUnixSocket ( const char* ip, int port ) - { - fSockfd = 0; - fPort = port; - fSendAddr.sin_family = AF_INET; - 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 ); - } - - JackNetUnixSocket::JackNetUnixSocket ( const JackNetUnixSocket& socket ) - { - fSockfd = 0; - fPort = socket.fPort; - fSendAddr = socket.fSendAddr; - fRecvAddr = socket.fRecvAddr; - } - - JackNetUnixSocket::~JackNetUnixSocket() - { - Close(); - } - - JackNetUnixSocket& JackNetUnixSocket::operator= ( const JackNetUnixSocket& socket ) - { - if ( this != &socket ) - { - fSockfd = 0; - fPort = socket.fPort; - fSendAddr = socket.fSendAddr; - fRecvAddr = socket.fRecvAddr; - } - return *this; - } - - //socket*********************************************************************************************************** - int JackNetUnixSocket::NewSocket() - { - if ( fSockfd ) - { - Close(); - Reset(); - } - fSockfd = socket ( AF_INET, SOCK_DGRAM, 0 ); - return fSockfd; - } - - int JackNetUnixSocket::Bind() - { - return bind ( fSockfd, reinterpret_cast ( &fRecvAddr ), sizeof ( socket_address_t ) ); - } - - int JackNetUnixSocket::BindWith ( const char* ip ) - { - int addr_conv = inet_aton ( ip, &fRecvAddr.sin_addr ); - if ( addr_conv < 0 ) - return addr_conv; - return Bind(); - } - - int JackNetUnixSocket::BindWith ( int port ) - { - fRecvAddr.sin_port = htons ( port ); - return Bind(); - } - - int JackNetUnixSocket::Connect() - { - return connect ( fSockfd, reinterpret_cast ( &fSendAddr ), sizeof ( socket_address_t ) ); - } - - int JackNetUnixSocket::ConnectTo ( const char* ip ) - { - 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 ); - 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 ); - fRecvAddr.sin_family = AF_INET; - 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; - } - - //IP/PORT*********************************************************************************************************** - void JackNetUnixSocket::SetPort ( int port ) - { - fPort = port; - fSendAddr.sin_port = htons ( port ); - fRecvAddr.sin_port = htons ( port ); - } - - int JackNetUnixSocket::GetPort() - { - return fPort; - } - - //address*********************************************************************************************************** - int JackNetUnixSocket::SetAddress ( const char* ip, int port ) - { - int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); - if ( addr_conv < 0 ) - return addr_conv; - fSendAddr.sin_port = htons ( port ); - return 0; - } - - char* JackNetUnixSocket::GetSendIP() - { - return inet_ntoa ( fSendAddr.sin_addr ); - } - - char* JackNetUnixSocket::GetRecvIP() - { - return inet_ntoa ( fRecvAddr.sin_addr ); - } - - //utility************************************************************************************************************ - int JackNetUnixSocket::GetName ( char* name ) - { - return gethostname ( name, 255 ); - } - - 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 ) ); - } - - //options************************************************************************************************************ - int JackNetUnixSocket::SetOption ( int level, int optname, const void* optval, socklen_t optlen ) - { - return setsockopt ( fSockfd, level, optname, optval, optlen ); - } - - int JackNetUnixSocket::GetOption ( int level, int optname, void* optval, socklen_t* optlen ) - { - return getsockopt ( fSockfd, level, optname, optval, optlen ); - } - - //timeout************************************************************************************************************ - int JackNetUnixSocket::SetTimeOut ( int us ) - { - jack_log ( "JackNetUnixSocket::SetTimeout %d usecs", us ); - - //negative timeout, or exceding 10s, return - if ( ( us < 0 ) || ( us > 10000000 ) ) - return SOCKET_ERROR; - struct timeval timeout; - - //less than 1sec - if ( us < 1000000 ) - { - timeout.tv_sec = 0; - timeout.tv_usec = us; - } - //more than 1sec - else - { - float sec = static_cast ( us ) / 1000000.f; - timeout.tv_sec = ( int ) sec; - float usec = ( sec - static_cast ( timeout.tv_sec ) ) * 1000000; - timeout.tv_usec = ( int ) usec; - } - return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); - } - - //local loop********************************************************************************************************** - int JackNetUnixSocket::SetLocalLoop() - { - char disable = 0; - return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) ); - } - - //network operations************************************************************************************************** - int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) - { - return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast ( &fSendAddr ), sizeof ( socket_address_t ) ); - } - - 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 ) - return addr_conv; - return SendTo ( buffer, nbytes, flags ); - } - - int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags ) - { - return send ( fSockfd, buffer, nbytes, flags ); - } - - int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) - { - socklen_t addr_len = sizeof ( socket_address_t ); - return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast ( &fRecvAddr ), &addr_len ); - } - - int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags ) - { - return recv ( fSockfd, buffer, nbytes, flags ); - } - - int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) - { - socklen_t addr_len = sizeof ( socket_address_t ); - return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast ( &fSendAddr ), &addr_len ); - } - - net_error_t JackNetUnixSocket::GetError() - { - switch ( errno ) - { - case EAGAIN: - return NET_NO_DATA; - case ECONNABORTED: - return NET_CONN_ERROR; - case EINVAL: - return NET_CONN_ERROR; - case ECONNREFUSED: - return NET_CONN_ERROR; - case ECONNRESET: - return NET_CONN_ERROR; - case EHOSTDOWN: - return NET_CONN_ERROR; - case EHOSTUNREACH: - return NET_CONN_ERROR; - default: - return NET_OP_ERROR; - } - } -} diff --git a/common/JackNetUnixSocket.h b/common/JackNetUnixSocket.h deleted file mode 100644 index 00988897..00000000 --- a/common/JackNetUnixSocket.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright (C) 2008 Romain Moret at Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __JackNetUnixSocket__ -#define __JackNetUnixSocket__ - -#include "JackNetSocket.h" -#include -#include -#include -#include -#include - -namespace Jack -{ -#define NET_ERROR_CODE errno -#define SOCKET_ERROR -1 -#define StrError strerror - - typedef struct sockaddr socket_address_t; - typedef struct in_addr address_t; - - //JackNetUnixSocket******************************************** - class EXPORT JackNetUnixSocket - { - private: - int fSockfd; - int fPort; - - struct sockaddr_in fSendAddr; - struct sockaddr_in fRecvAddr; - public: - JackNetUnixSocket(); - JackNetUnixSocket ( const char* ip, int port ); - JackNetUnixSocket ( const JackNetUnixSocket& ); - ~JackNetUnixSocket(); - - JackNetUnixSocket& operator= ( const JackNetUnixSocket& socket ); - - //socket management - int NewSocket(); - int Bind(); - int BindWith ( const char* ip ); - int BindWith ( int port ); - int Connect(); - int ConnectTo ( const char* ip ); - void Close(); - void Reset(); - bool IsSocket(); - - //IP/PORT management - void SetPort ( int port ); - int GetPort(); - - //address management - int SetAddress ( const char* ip, int port ); - char* GetSendIP(); - char* GetRecvIP(); - - //utility - 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 ); - - //timeout - int SetTimeOut ( int us ); - - //disable local loop - int SetLocalLoop(); - - //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 ); - - //error management - net_error_t GetError(); - }; -} - -#endif diff --git a/common/JackPlatformChannelTransaction.h b/common/JackPlatformChannelTransaction.h deleted file mode 100644 index a287c030..00000000 --- a/common/JackPlatformChannelTransaction.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -Copyright (C) 2004-2006 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 __JackPlatformChannelTransaction__ -#define __JackPlatformChannelTransaction__ - -#ifdef WIN32 -#include "JackWinNamedPipe.h" -#else -#include "JackSocket.h" -#endif - -namespace Jack -{ - -/*! -\brief Channel input/output communication. -*/ - -#ifdef WIN32 -typedef JackWinNamedPipe JackChannelTransaction; -#else -typedef JackClientSocket JackChannelTransaction; -#endif - -} // end of namespace - -#endif - diff --git a/common/JackPlatformClientChannel.h b/common/JackPlatformClientChannel.h deleted file mode 100644 index a47a44ff..00000000 --- a/common/JackPlatformClientChannel.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 __JackPlatformClientChannel__ -#define __JackPlatformClientChannel___ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackMachClientChannel.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinNamedPipeClientChannel.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackSocketClientChannel.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinNamedPipeClientChannel JackClientChannel; - -#elif defined(SOCKET_RPC_POSIX_SEMA) || defined(SOCKET_RPC_FIFO_SEMA) || defined(SOCKET_RPC_FIFO_SEMA_DUMMY) \ - || defined(SOCKET_RPC_MACH_SEMA) -typedef JackSocketClientChannel JackClientChannel; - -#elif defined(MACH_RPC_MACH_SEMA) || defined(MACH_RPC_FIFO_SEMA) || defined(MACH_RPC_POSIX_SEMA) -typedef JackMachClientChannel JackClientChannel; - -#endif - -} // end of namespace - -#endif /* __JackPlatformClientChannel__ */ diff --git a/common/JackPlatformNetSocket.h b/common/JackPlatformNetSocket.h deleted file mode 100644 index c17a5f0f..00000000 --- a/common/JackPlatformNetSocket.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright (C) 2008 Romain Moret at Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __JackPlatformNetSocket__ -#define __JackPlatformNetSocket__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX and LINUX -#if defined(__APPLE__) || defined (__linux__) -#include "JackNetUnixSocket.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackNetWinSocket.h" -#endif - -namespace Jack -{ - -#if defined(__APPLE__) || defined(__linux__) - typedef JackNetUnixSocket JackNetSocket; -#endif - -#ifdef WIN32 - typedef JackNetWinSocket JackNetSocket; -#endif - -} // end of namespace - -#endif /* __JackPlatformNetSocket__ */ diff --git a/common/JackPlatformNotifyChannel.h b/common/JackPlatformNotifyChannel.h deleted file mode 100644 index c45c68de..00000000 --- a/common/JackPlatformNotifyChannel.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 __JackPlatformNotifyChannel__ -#define __JackPlatformNotifyChannel__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackMachNotifyChannel.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinNamedPipeNotifyChannel.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackSocketNotifyChannel.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinNamedPipeNotifyChannel JackNotifyChannel; - -#elif defined(SOCKET_RPC_POSIX_SEMA) || defined(SOCKET_RPC_FIFO_SEMA) || defined(SOCKET_RPC_FIFO_SEMA_DUMMY) \ - || defined(SOCKET_RPC_MACH_SEMA) -typedef JackSocketNotifyChannel JackNotifyChannel; - -#elif defined(MACH_RPC_MACH_SEMA) || defined(MACH_RPC_FIFO_SEMA) || defined(MACH_RPC_POSIX_SEMA) -typedef JackMachNotifyChannel JackNotifyChannel; - -#endif - -} // end of namespace - -#endif /* __JackPlatformNotifyChannel__ */ diff --git a/common/JackPlatformPlug.h b/common/JackPlatformPlug.h new file mode 100644 index 00000000..560755b6 --- /dev/null +++ b/common/JackPlatformPlug.h @@ -0,0 +1,25 @@ +/* +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 __JackPlatformPlug__ +#define __JackPlatformPlug__ + +#include "JackPlatformPlug_os.h" + +#endif diff --git a/common/JackPlatformProcessSync.h b/common/JackPlatformProcessSync.h deleted file mode 100644 index 8c4c62c0..00000000 --- a/common/JackPlatformProcessSync.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -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 __JackPlatformProcessSync__ -#define __JackPlatformProcessSync__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackProcessSync.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinProcessSync.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackProcessSync.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinProcessSync JackProcessSync; -#endif - -} // end of namespace - -#endif /* __JackPlatformProcessSync__ */ diff --git a/common/JackPlatformServerChannel.h b/common/JackPlatformServerChannel.h deleted file mode 100644 index 98a47f56..00000000 --- a/common/JackPlatformServerChannel.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 __JackPlatformServerChannel__ -#define __JackPlatformServerChannel___ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackMachServerChannel.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinNamedPipeServerChannel.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackSocketServerChannel.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinNamedPipeServerChannel JackServerChannel; - -#elif defined(SOCKET_RPC_POSIX_SEMA) || defined(SOCKET_RPC_FIFO_SEMA) || defined(SOCKET_RPC_FIFO_SEMA_DUMMY) \ - || defined(SOCKET_RPC_MACH_SEMA) -typedef JackSocketServerChannel JackServerChannel; - -#elif defined(MACH_RPC_MACH_SEMA) || defined(MACH_RPC_FIFO_SEMA) || defined(MACH_RPC_POSIX_SEMA) -typedef JackMachServerChannel JackServerChannel; - -#endif - -} // end of namespace - -#endif /* __JackPlatformServerChannel__ */ diff --git a/common/JackPlatformServerNotifyChannel.h b/common/JackPlatformServerNotifyChannel.h deleted file mode 100644 index dcc5c15e..00000000 --- a/common/JackPlatformServerNotifyChannel.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 __JackPlatformServerNotifyChannel__ -#define __JackPlatformServerNotifyChannel___ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackMachServerNotifyChannel.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinNamedPipeServerNotifyChannel.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackSocketServerNotifyChannel.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinNamedPipeServerNotifyChannel JackServerNotifyChannel; - -#elif defined(SOCKET_RPC_POSIX_SEMA) || defined(SOCKET_RPC_FIFO_SEMA) || defined(SOCKET_RPC_FIFO_SEMA_DUMMY) \ - || defined(SOCKET_RPC_MACH_SEMA) -typedef JackSocketServerNotifyChannel JackServerNotifyChannel; - -#elif defined(MACH_RPC_MACH_SEMA) || defined(MACH_RPC_FIFO_SEMA) || defined(MACH_RPC_POSIX_SEMA) -typedef JackMachServerNotifyChannel JackServerNotifyChannel; - -#endif - -} // end of namespace - -#endif /* __JackPlatformServerNotifyChannel__ */ diff --git a/common/JackPlatformSynchro.h b/common/JackPlatformSynchro.h deleted file mode 100644 index 3ee1ab91..00000000 --- a/common/JackPlatformSynchro.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -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 __JackPlatformSynchro__ -#define __JackPlatformSynchro__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackMachSemaphore.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinSemaphore.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackPosixSemaphore.h" -#include "JackFifo.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinSemaphore JackSynchro; -#endif - -#if defined(MACH_RPC_MACH_SEMA) || defined(SOCKET_RPC_MACH_SEMA) -typedef JackMachSemaphore JackSynchro; -#endif - -#if defined(SOCKET_RPC_POSIX_SEMA) || defined(MACH_RPC_POSIX_SEMA) -typedef JackPosixSemaphore JackSynchro; -#endif - -#if defined(SOCKET_RPC_FIFO_SEMA) || defined(SOCKET_RPC_FIFO_SEMA_DUMMY) || defined(MACH_RPC_FIFO_SEMA) -typedef JackFifo JackSynchro; -#endif - -} // end of namespace - -#endif /* __JackPlatformSynchro__ */ diff --git a/common/JackPlatformThread.h b/common/JackPlatformThread.h deleted file mode 100644 index 86f43b9a..00000000 --- a/common/JackPlatformThread.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -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 __JackPlatformThread__ -#define __JackPlatformThread__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -// OSX -#if defined(__APPLE__) -#include "JackMachThread.h" -#endif - -// WINDOWS -#ifdef WIN32 -#include "JackWinThread.h" -#endif - -// LINUX -#ifdef __linux__ -#include "JackPosixThread.h" -#endif - -namespace Jack -{ - -#ifdef WIN32 -typedef JackWinThread JackThread; -#endif - -#ifdef __linux__ -typedef JackPosixThread JackThread; -#endif - -#if defined(__APPLE__) -typedef JackMachThread JackThread; -#endif - -} // end of namespace - -#endif /* __JackPlatformThread__ */ diff --git a/common/JackPort.h b/common/JackPort.h index 86ed86e5..999f18ea 100644 --- a/common/JackPort.h +++ b/common/JackPort.h @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "types.h" #include "JackConstants.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" namespace Jack { @@ -56,15 +56,7 @@ class EXPORT JackPort bool fInUse; jack_port_id_t fTied; // Locally tied source port -#ifdef WIN32 - //__declspec(align(16)) float fBuffer[BUFFER_SIZE_MAX]; - float fBuffer[BUFFER_SIZE_MAX]; -#elif __GNUC__ - float fBuffer[BUFFER_SIZE_MAX] __attribute__((aligned(64))); // 16 bytes alignment for vector code, 64 bytes better for cache loads/stores -#else -#warning Buffer will not be aligned on 16 bytes boundaries : vector based code (Altivec of SSE) will fail - float fBuffer[BUFFER_SIZE_MAX]; -#endif + MEM_ALIGN(float fBuffer[BUFFER_SIZE_MAX], 64); // 16 bytes alignment for vector code, 64 bytes better for cache loads/stores bool IsUsed() const; diff --git a/common/JackPosixSemaphore.cpp b/common/JackPosixSemaphore.cpp deleted file mode 100644 index b836217c..00000000 --- a/common/JackPosixSemaphore.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackPosixSemaphore.h" -#include "JackConstants.h" -#include "JackError.h" -#include -#include -#include - -namespace Jack -{ - -void JackPosixSemaphore::BuildName(const char* name, const char* server_name, char* res) -{ - sprintf(res, "jack_sem.%s_%s", server_name, name); -} - -bool JackPosixSemaphore::Signal() -{ - int res; - - if (!fSemaphore) { - jack_error("JackPosixSemaphore::Signal name = %s already desallocated!!", fName); - return false; - } - - if (fFlush) - return true; - - if ((res = sem_post(fSemaphore)) != 0) { - jack_error("JackPosixSemaphore::Signal name = %s err = %s", fName, strerror(errno)); - } - return (res == 0); -} - -bool JackPosixSemaphore::SignalAll() -{ - int res; - - if (!fSemaphore) { - jack_error("JackPosixSemaphore::SignalAll name = %s already desallocated!!", fName); - return false; - } - - if (fFlush) - return true; - - if ((res = sem_post(fSemaphore)) != 0) { - jack_error("JackPosixSemaphore::SignalAll name = %s err = %s", fName, strerror(errno)); - } - return (res == 0); -} - -/* -bool JackPosixSemaphore::Wait() -{ - int res; - - if (!fSemaphore) { - jack_error("JackPosixSemaphore::Wait name = %s already desallocated!!", fName); - return false; - } - - if ((res = sem_wait(fSemaphore)) != 0) { - jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); - } - return (res == 0); -} -*/ - -bool JackPosixSemaphore::Wait() -{ - int res; - - while ((res = sem_wait(fSemaphore) < 0)) { - jack_error("JackPosixSemaphore::Wait name = %s err = %s", fName, strerror(errno)); - if (errno != EINTR) - break; - } - return (res == 0); -} - -#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) // glibc feature test - -bool JackPosixSemaphore::TimedWait(long usec) -{ - int res; - struct timeval now; - timespec time; - - if (!fSemaphore) { - jack_error("JackPosixSemaphore::TimedWait name = %s already desallocated!!", fName); - return false; - } - gettimeofday(&now, 0); - time.tv_sec = now.tv_sec + usec / 1000000; - long tv_usec = (now.tv_usec + (usec % 1000000)); - time.tv_sec += tv_usec / 1000000; - time.tv_nsec = (tv_usec % 1000000) * 1000; - - if ((res = sem_timedwait(fSemaphore, &time)) != 0) { - jack_error("JackPosixSemaphore::TimedWait err = %s", strerror(errno)); - jack_log("now %ld %ld ", now.tv_sec, now.tv_usec); - jack_log("next %ld %ld ", time.tv_sec, time.tv_nsec/1000); - } - return (res == 0); -} - -#else -#warning "JackPosixSemaphore::TimedWait is not supported: Jack in SYNC mode with JackPosixSemaphore will not run properly !!" - -bool JackPosixSemaphore::TimedWait(long usec) -{ - return Wait(); -} -#endif - -// 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); - jack_log("JackPosixSemaphore::Allocate name = %s val = %ld", fName, value); - - if ((fSemaphore = sem_open(fName, O_CREAT, 0777, value)) == (sem_t*)SEM_FAILED) { - jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); - return false; - } else { - return true; - } -} - -// 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); - - // Temporary... - if (fSemaphore) { - jack_log("Already connected name = %s", name); - return true; - } - - if ((fSemaphore = sem_open(fName, O_CREAT)) == (sem_t*)SEM_FAILED) { - jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno)); - return false; - } else { - int val = 0; - sem_getvalue(fSemaphore, &val); - jack_log("JackPosixSemaphore::Connect sem_getvalue %ld", val); - return true; - } -} - -bool JackPosixSemaphore::Connect(const char* name, const char* server_name) -{ - return ConnectInput(name, server_name); -} - -bool JackPosixSemaphore::ConnectOutput(const char* name, const char* server_name) -{ - return ConnectInput(name, server_name); -} - -bool JackPosixSemaphore::Disconnect() -{ - jack_log("JackPosixSemaphore::Disconnect %s", fName); - - if (fSemaphore) { - if (sem_close(fSemaphore) != 0) { - jack_error("Disconnect: can't disconnect named semaphore name = %s err = %s", fName, strerror(errno)); - return false; - } else { - fSemaphore = NULL; - return true; - } - } else { - return true; - } -} - -// Server side : destroy the semaphore -void JackPosixSemaphore::Destroy() -{ - if (fSemaphore != NULL) { - jack_log("JackPosixSemaphore::Destroy"); - sem_unlink(fName); - if (sem_close(fSemaphore) != 0) { - jack_error("Destroy: can't destroy semaphore name = %s err = %s", fName, strerror(errno)); - } - fSemaphore = NULL; - } else { - jack_error("JackPosixSemaphore::Destroy semaphore == NULL"); - } -} - -} // end of namespace - diff --git a/common/JackPosixSemaphore.h b/common/JackPosixSemaphore.h deleted file mode 100644 index 0a20ed84..00000000 --- a/common/JackPosixSemaphore.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -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 __JackPosixSemaphore__ -#define __JackPosixSemaphore__ - -#include "JackSynchro.h" -#include "JackExports.h" -#include -#include -#include - -namespace Jack -{ - -/*! -\brief Inter process synchronization using POSIX semaphore. -*/ - -class EXPORT JackPosixSemaphore : public detail::JackSynchro -{ - - private: - - sem_t* fSemaphore; - - protected: - - void BuildName(const char* name, const char* server_name, char* res); - - public: - - JackPosixSemaphore(): fSemaphore(NULL) - {} - - bool Signal(); - bool SignalAll(); - bool Wait(); - bool TimedWait(long usec); - - bool Allocate(const char* name, const char* server_name, int value); - bool Connect(const char* name, const char* server_name); - bool ConnectInput(const char* name, const char* server_name); - bool ConnectOutput(const char* name, const char* server_name); - bool Disconnect(); - void Destroy(); -}; - -} // end of namespace - - -#endif - diff --git a/common/JackPosixThread.cpp b/common/JackPosixThread.cpp deleted file mode 100644 index 0427b059..00000000 --- a/common/JackPosixThread.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* -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 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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackPosixThread.h" -#include "JackError.h" -#include "JackTime.h" -#include // for memset - -namespace Jack -{ - -void* JackPosixThread::ThreadHandler(void* arg) -{ - JackPosixThread* obj = (JackPosixThread*)arg; - JackRunnableInterface* runnable = obj->fRunnable; - int err; - - if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) { - jack_error("pthread_setcanceltype err = %s", strerror(err)); - } - - // Signal creation thread when started with StartSync - jack_log("ThreadHandler: start"); - obj->fStatus = kIniting; - - // Call Init method - if (!runnable->Init()) { - jack_error("Thread init fails: thread quits"); - return 0; - } - - obj->fStatus = kRunning; - - // If Init succeed, start the thread loop - bool res = true; - while (obj->fStatus == kRunning && res) { - res = runnable->Execute(); - } - - jack_log("ThreadHandler: exit"); - pthread_exit(0); - return 0; // never reached -} - -int JackPosixThread::Start() -{ - fStatus = kStarting; - - // Check if the thread was correctly started - if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { - fStatus = kIdle; - return -1; - } else { - return 0; - } -} - -int JackPosixThread::StartSync() -{ - fStatus = kStarting; - - if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { - fStatus = kIdle; - return -1; - } else { - int count = 0; - while (fStatus == kStarting && ++count < 1000) { - JackSleep(1000); - } - return (count == 1000) ? -1 : 0; - } -} - -int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) -{ - pthread_attr_t attributes; - struct sched_param rt_param; - pthread_attr_init(&attributes); - int res; - - if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) { - jack_error("Cannot request joinable thread creation for RT thread res = %d err = %s", res, strerror(errno)); - return -1; - } - - if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) { - jack_error("Cannot set scheduling scope for RT thread res = %d err = %s", res, strerror(errno)); - return -1; - } - - if (realtime) { - - jack_log("Create RT thread"); - - if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) { - jack_error("Cannot request explicit scheduling for RT thread res = %d err = %s", res, strerror(errno)); - return -1; - } - - //if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO))) { - if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) { - jack_error("Cannot set RR scheduling class for RT thread res = %d err = %s", res, strerror(errno)); - return -1; - } - } else { - jack_log("Create non RT thread"); - } - - memset(&rt_param, 0, sizeof(rt_param)); - rt_param.sched_priority = priority; - - if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) { - jack_error("Cannot set scheduling priority for RT thread res = %d err = %s", res, strerror(errno)); - return -1; - } - - if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) { - jack_error("Cannot set thread stack size res = %d err = %s", res, strerror(errno)); - return -1; - } - - if ((res = pthread_create(thread, &attributes, start_routine, arg))) { - jack_error("Cannot create thread res = %d err = %s", res, strerror(errno)); - return -1; - } - - return 0; -} - -int JackPosixThread::Kill() -{ - if (fThread != (pthread_t)NULL) { // If thread has been started - jack_log("JackPosixThread::Kill"); - void* status; - pthread_cancel(fThread); - pthread_join(fThread, &status); - fStatus = kIdle; - fThread = (pthread_t)NULL; - return 0; - } else { - return -1; - } -} - -int JackPosixThread::Stop() -{ - if (fThread != (pthread_t)NULL) { // If thread has been started - jack_log("JackPosixThread::Stop"); - void* status; - fStatus = kIdle; // Request for the thread to stop - pthread_join(fThread, &status); - fThread = (pthread_t)NULL; - return 0; - } else { - return -1; - } -} - -int JackPosixThread::KillImp(pthread_t thread) -{ - if (thread != (pthread_t)NULL) { // If thread has been started - jack_log("JackPosixThread::Kill"); - void* status; - pthread_cancel(thread); - pthread_join(thread, &status); - return 0; - } else { - return -1; - } -} - -int JackPosixThread::StopImp(pthread_t thread) -{ - if (thread != (pthread_t)NULL) { // If thread has been started - jack_log("JackPosixThread::Stop"); - void* status; - pthread_join(thread, &status); - return 0; - } else { - return -1; - } -} - -int JackPosixThread::AcquireRealTime() -{ - return (fThread != (pthread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1; -} - -int JackPosixThread::AcquireRealTime(int priority) -{ - fPriority = priority; - return AcquireRealTime(); -} - -int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority) -{ - struct sched_param rtparam; - int res; - memset(&rtparam, 0, sizeof(rtparam)); - rtparam.sched_priority = priority; - - //if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) { - - if ((res = pthread_setschedparam(thread, SCHED_RR, &rtparam)) != 0) { - jack_error("Cannot use real-time scheduling (RR/%d) " - "(%d: %s)", rtparam.sched_priority, res, - strerror(res)); - return -1; - } - return 0; -} - -int JackPosixThread::DropRealTime() -{ - return (fThread != (pthread_t)NULL) ? DropRealTimeImp(fThread) : -1; -} - -int JackPosixThread::DropRealTimeImp(pthread_t thread) -{ - struct sched_param rtparam; - int res; - memset(&rtparam, 0, sizeof(rtparam)); - rtparam.sched_priority = 0; - - if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) { - jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno)); - return -1; - } - return 0; -} - -pthread_t JackPosixThread::GetThreadID() -{ - return fThread; -} - -void JackPosixThread::Terminate() -{ - jack_log("JackPosixThread::Terminate"); - pthread_exit(0); -} - -} // end of namespace - -EXPORT bool jack_tls_allocate_key(jack_tls_key *key_ptr) -{ - int ret; - - ret = pthread_key_create(key_ptr, NULL); - if (ret != 0) - { - jack_error("pthread_key_create() failed with error %d errno %s", ret, strerror(errno)); - return false; - } - - return true; -} - -EXPORT bool jack_tls_free_key(jack_tls_key key) -{ - int ret; - - ret = pthread_key_delete(key); - if (ret != 0) - { - jack_error("pthread_key_delete() failed with error %d errno %s", ret, strerror(errno)); - return false; - } - - return true; -} - -EXPORT bool jack_tls_set(jack_tls_key key, void *data_ptr) -{ - int ret; - - ret = pthread_setspecific(key, (const void *)data_ptr); - if (ret != 0) - { - jack_error("pthread_setspecific() failed with error %d errno %s", ret, strerror(errno)); - return false; - } - - return true; -} - -EXPORT void *jack_tls_get(jack_tls_key key) -{ - return pthread_getspecific(key); -} diff --git a/common/JackPosixThread.h b/common/JackPosixThread.h deleted file mode 100644 index bb7a39bc..00000000 --- a/common/JackPosixThread.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -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 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 __JackPosixThread__ -#define __JackPosixThread__ - -#include "JackThread.h" -#include - -namespace Jack -{ - -/* use 512KB stack per thread - the default is way too high to be feasible - * with mlockall() on many systems */ -#define THREAD_STACK 524288 - -/*! -\brief The POSIX thread base class. -*/ - -class EXPORT JackPosixThread : public detail::JackThread -{ - - protected: - - pthread_t fThread; - static void* ThreadHandler(void* arg); - - public: - - JackPosixThread(JackRunnableInterface* runnable, bool real_time, int priority, int cancellation) - : JackThread(runnable, priority, real_time, cancellation), fThread((pthread_t)NULL) - {} - JackPosixThread(JackRunnableInterface* runnable, int cancellation = PTHREAD_CANCEL_ASYNCHRONOUS) - : JackThread(runnable, 0, false, cancellation), fThread((pthread_t)NULL) - {} - - int Start(); - int StartSync(); - int Kill(); - int Stop(); - void Terminate(); - - int AcquireRealTime(); - int AcquireRealTime(int priority); - int DropRealTime(); - - pthread_t GetThreadID(); - - static int AcquireRealTimeImp(pthread_t thread, int priority); - static int DropRealTimeImp(pthread_t thread); - static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); - static int StopImp(pthread_t thread); - static int KillImp(pthread_t thread); - -}; - -} // end of namespace - - -#endif diff --git a/common/JackProcessSync.cpp b/common/JackProcessSync.cpp deleted file mode 100644 index 8a488310..00000000 --- a/common/JackProcessSync.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackProcessSync.h" -#include "JackError.h" - -namespace Jack -{ - -bool JackProcessSync::TimedWait(long usec) -{ - struct timeval T0, T1; - timespec time; - struct timeval now; - int res; - - pthread_mutex_lock(&fLock); - jack_log("JackProcessSync::TimedWait time out = %ld", usec); - gettimeofday(&T0, 0); - - gettimeofday(&now, 0); - 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, &fLock, &time); - if (res != 0) - jack_error("pthread_cond_timedwait error usec = %ld err = %s", usec, strerror(res)); - - gettimeofday(&T1, 0); - pthread_mutex_unlock(&fLock); - 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); -} - -void JackProcessSync::Wait() -{ - int res; - pthread_mutex_lock(&fLock); - //jack_log("JackProcessSync::Wait..."); - if ((res = pthread_cond_wait(&fCond, &fLock)) != 0) - jack_error("pthread_cond_wait error err = %s", strerror(errno)); - pthread_mutex_unlock(&fLock); - //jack_log("JackProcessSync::Wait finished"); -} - -bool JackInterProcessSync::TimedWait(long usec) -{ - struct timeval T0, T1; - //jack_log("JackInterProcessSync::TimedWait..."); - gettimeofday(&T0, 0); - bool res = fSynchro->TimedWait(usec); - gettimeofday(&T1, 0); - //jack_log("JackInterProcessSync::TimedWait finished delta = %5.1lf", (1e6 * T1.tv_sec - 1e6 * T0.tv_sec + T1.tv_usec - T0.tv_usec)); - return res; -} - -} // end of namespace - diff --git a/common/JackProcessSync.h b/common/JackProcessSync.h deleted file mode 100644 index 82d3e65f..00000000 --- a/common/JackProcessSync.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -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 __JackProcessSync__ -#define __JackProcessSync__ - -#include "JackPlatformSynchro.h" -#include -#include -#include - -namespace Jack -{ - -/*! -\brief A synchronization primitive built using a condition variable. -*/ - -class JackProcessSync -{ - - private: - - pthread_mutex_t fLock; // Mutex - pthread_cond_t fCond; // Condition variable - - public: - - JackProcessSync() - { - pthread_mutex_init(&fLock, NULL); - pthread_cond_init(&fCond, NULL); - } - - ~JackProcessSync() - { - pthread_mutex_destroy(&fLock); - pthread_cond_destroy(&fCond); - } - - bool Allocate(const char* name) - { - return true; - } - - bool Connect(const char* name) - { - return true; - } - - void Destroy() - {} - - bool TimedWait(long usec); - - void Wait(); - - void Signal() - { - pthread_mutex_lock(&fLock); - pthread_cond_signal(&fCond); - pthread_mutex_unlock(&fLock); - } - - void SignalAll() - { - //pthread_mutex_lock(&fLock); - pthread_cond_broadcast(&fCond); - //pthread_mutex_unlock(&fLock); - } - -}; - -/*! -\brief A synchronization primitive built using an inter-process synchronization object. -*/ - -class JackInterProcessSync -{ - - private: - - JackSynchro* fSynchro; - - public: - - JackInterProcessSync(JackSynchro* synchro): fSynchro(synchro) - {} - ~JackInterProcessSync() - { - delete fSynchro; - } - - bool Allocate(const char* name) - { - return fSynchro->Allocate(name, "", 0); - } - - void Destroy() - { - fSynchro->Destroy(); - } - - bool Connect(const char* name) - { - return fSynchro->Connect(name, ""); - } - - bool TimedWait(long usec); - - void Wait() - { - fSynchro->Wait(); - } - - void SignalAll() - { - fSynchro->SignalAll(); - } -}; - - -} // end of namespace - -#endif - diff --git a/common/JackRequest.h b/common/JackRequest.h index eacb28e9..a94ed7b3 100644 --- a/common/JackRequest.h +++ b/common/JackRequest.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define __JackRequest__ #include "JackConstants.h" -#include "JackPlatformChannelTransaction.h" +#include "JackPlatformPlug.h" #include "types.h" #include #include diff --git a/common/JackRestartThreadedDriver.cpp b/common/JackRestartThreadedDriver.cpp index 8719beea..5bc7feac 100644 --- a/common/JackRestartThreadedDriver.cpp +++ b/common/JackRestartThreadedDriver.cpp @@ -22,9 +22,7 @@ #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackRestartThreadedDriver.h" #include "JackException.h" diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 9aeaad24..667e236e 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -22,9 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackServer.h" #include "JackTime.h" diff --git a/common/JackServer.h b/common/JackServer.h index 8d96fc8f..5fbcb455 100644 --- a/common/JackServer.h +++ b/common/JackServer.h @@ -21,15 +21,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef __JackServer__ #define __JackServer__ -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "driver_interface.h" #include "JackDriverLoader.h" #include "JackConnectionManager.h" #include "jslist.h" #include "JackGlobals.h" -#include "JackPlatformSynchro.h" -#include "JackPlatformServerChannel.h" +#include "JackPlatformPlug.h" namespace Jack diff --git a/common/JackServerAPI.cpp b/common/JackServerAPI.cpp index f047c4e8..8aaee585 100644 --- a/common/JackServerAPI.cpp +++ b/common/JackServerAPI.cpp @@ -22,9 +22,7 @@ This program is free software; you can redistribute it and/or modify #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackGraphManager.h" #include "JackInternalClient.h" @@ -33,7 +31,7 @@ This program is free software; you can redistribute it and/or modify #include "JackServerGlobals.h" #include "JackServerLaunch.h" #include "JackTools.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackLockedEngine.h" #ifdef __cplusplus diff --git a/common/JackServerLaunch.cpp b/common/JackServerLaunch.cpp index acbf87d0..11a95a61 100644 --- a/common/JackServerLaunch.cpp +++ b/common/JackServerLaunch.cpp @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackChannel.h" #include "JackLibGlobals.h" #include "JackServerLaunch.h" -#include "JackPlatformClientChannel.h" +#include "JackPlatformPlug.h" using namespace Jack; diff --git a/common/JackShmMem.h b/common/JackShmMem.h index d713bf70..17fe0cc7 100644 --- a/common/JackShmMem.h +++ b/common/JackShmMem.h @@ -23,26 +23,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "shm.h" #include "JackError.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include // GCC 4.0 #include #include -#ifdef WIN32 -#include -#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) -#else -#include -#include -#define CHECK_MLOCK(ptr, size) (mlock((ptr), (size)) == 0) -#define CHECK_MUNLOCK(ptr, size) (munlock((ptr), (size)) == 0) -#define CHECK_MLOCKALL() (mlockall(MCL_CURRENT | MCL_FUTURE) == 0) -#define CHECK_MUNLOCKALL() (munlockall() == 0) -#endif +#include "JackShmMem_os.h" namespace Jack { diff --git a/common/JackSocket.cpp b/common/JackSocket.cpp deleted file mode 100644 index db700f08..00000000 --- a/common/JackSocket.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackSocket.h" -#include "JackError.h" -#include -#include -#include - -namespace Jack -{ - -JackClientSocket::JackClientSocket(int socket): fSocket(socket) -{} - -void JackClientSocket::SetReadTimeOut(long sec) -{ - struct timeval timout; - timout.tv_sec = sec; - timout.tv_usec = 0; - if (setsockopt(fSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timout, sizeof(timeval)) < 0) { - jack_error("SetReadTimeOut fd = %ld err = %s", fSocket, strerror(errno)); - } -} - -void JackClientSocket::SetWriteTimeOut(long sec) -{ - struct timeval timout; - timout.tv_sec = sec ; - timout.tv_usec = 0; - if (setsockopt(fSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&timout, sizeof(timeval)) < 0) { - jack_error("SetWriteTimeOut fd = %ld err = %s", fSocket, strerror(errno)); - } -} - -void JackClientSocket::SetNonBlocking(bool onoff) -{ - int flag = (onoff) ? 1 : 0; - if (ioctl(fSocket, FIONBIO, &flag) < 0) { - jack_error("SetNonBlocking fd = %ld err = %s", fSocket, strerror(errno)); - } -} - -int JackClientSocket::Connect(const char* dir, const char* name, int which) // A revoir : utilisation de "which" -{ - struct sockaddr_un addr; - - if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - jack_error("Cannot create socket err = %s", strerror(errno)); - return -1; - } - - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s/jack_%s_%d", dir, name, which); - jack_log("Connect: addr.sun_path %s", addr.sun_path); - - if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - jack_error("Cannot connect to server socket err = %s", strerror(errno)); - close(fSocket); - return -1; - } - -#ifdef __APPLE__ - int on = 1 ; - if (setsockopt(fSocket, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) { - jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket, strerror(errno)); - } -#endif - - return 0; -} - -int JackClientSocket::Connect(const char* dir, int which) -{ - struct sockaddr_un addr; - - if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - jack_error("Cannot create socket err = %s", strerror(errno)); - return -1; - } - - addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "%s/jack_%d", dir, which); - jack_log("Connect: addr.sun_path %s", addr.sun_path); - - if (connect(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - jack_error("Cannot connect to server socket err = %s", strerror(errno)); - close(fSocket); - return -1; - } - -#ifdef __APPLE__ - int on = 1 ; - if (setsockopt(fSocket, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) < 0) { - jack_log("setsockopt SO_NOSIGPIPE fd = %ld err = %s", fSocket, strerror(errno)); - } -#endif - - return 0; -} - -int JackClientSocket::Close() -{ - jack_log("JackClientSocket::Close"); - if (fSocket > 0) { - shutdown(fSocket, SHUT_RDWR); - close(fSocket); - fSocket = -1; - return 0; - } else { - return -1; - } -} - -int JackClientSocket::Read(void* data, int len) -{ - if (read(fSocket, data, len) != len) { - jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); - if (errno == EWOULDBLOCK) { - jack_error("JackClientSocket::Read time out"); - return 0; // For a non blocking socket, a read failure is not considered as an error - } else { - return -1; - } - } else { - return 0; - } -} - -int JackClientSocket::Write(void* data, int len) -{ - if (write(fSocket, data, len) != len) { - jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); - if (errno == EWOULDBLOCK) { - jack_log("JackClientSocket::Write time out"); - return 0; // For a non blocking socket, a write failure is not considered as an error - } else { - return -1; - } - } else { - return 0; - } -} - -int JackServerSocket::Bind(const char* dir, const char* name, int which) // A revoir : utilisation de "which" -{ - struct sockaddr_un addr; - - if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - jack_error("Cannot create server socket err = %s", strerror(errno)); - return -1; - } - - addr.sun_family = AF_UNIX; - - // TO CORRECT: always reuse the same name for now... - snprintf(fName, sizeof(addr.sun_path) - 1, "%s/jack_%s_%d", dir, name, which); - strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); - /* - if (access(addr.sun_path, F_OK) == 0) { - goto error; - } - */ - - jack_log("Bind: addr.sun_path %s", addr.sun_path); - unlink(fName); // Security... - - if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - jack_error("Cannot bind server to socket err = %s", strerror(errno)); - goto error; - } - - if (listen(fSocket, 1) < 0) { - jack_error("Cannot enable listen on server socket err = %s", strerror(errno)); - goto error; - } - - return 0; - -error: - unlink(fName); - close(fSocket); - return -1; -} - -int JackServerSocket::Bind(const char* dir, int which) // A revoir : utilisation de "which" -{ - struct sockaddr_un addr; - - if ((fSocket = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - jack_error("Cannot create server socket err = %s", strerror(errno)); - return -1; - } - - addr.sun_family = AF_UNIX; - - /* - for (int i = 0; i < 999; i++) { - snprintf(addr.sun_path, sizeof(addr.sun_path) - 1,"%s/jack_%d", dir, i); - snprintf(fName, sizeof(addr.sun_path) - 1,"%s/jack_%d", dir, i); - if (access(addr.sun_path, F_OK) != 0) { - break; - } - } - */ - - // TO CORRECT: always reuse the same name for now... - snprintf(fName, sizeof(addr.sun_path) - 1, "%s/jack_%d", dir, which); - strncpy(addr.sun_path, fName, sizeof(addr.sun_path) - 1); - /* - if (access(addr.sun_path, F_OK) == 0) { - goto error; - } - */ - - jack_log("Bind: addr.sun_path %s", addr.sun_path); - unlink(fName); // Security... - - if (bind(fSocket, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - jack_error("Cannot bind server to socket err = %s", strerror(errno)); - goto error; - } - - if (listen(fSocket, 1) < 0) { - jack_error("Cannot enable listen on server socket err = %s", strerror(errno)); - goto error; - } - - return 0; - -error: - unlink(fName); - close(fSocket); - return -1; -} - -JackClientSocket* JackServerSocket::Accept() -{ - struct sockaddr_un client_addr; - socklen_t client_addrlen; - - memset(&client_addr, 0, sizeof(client_addr)); - client_addrlen = sizeof(client_addr); - - int fd = accept(fSocket, (struct sockaddr*) & client_addr, &client_addrlen); - if (fd < 0) { - jack_error("Cannot accept new connection err = %s", strerror(errno)); - return 0; - } else { - return new JackClientSocket(fd); - } -} - -int JackServerSocket::Close() -{ - if (fSocket > 0) { - jack_log("JackServerSocket::Close %s", fName); - shutdown(fSocket, SHUT_RDWR); - close(fSocket); - unlink(fName); - fSocket = -1; - return 0; - } else { - return -1; - } -} - -} // end of namespace - - diff --git a/common/JackSocket.h b/common/JackSocket.h deleted file mode 100644 index 04074b0b..00000000 --- a/common/JackSocket.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -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 __JackSocket__ -#define __JackSocket__ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Jack -{ - -/*! -\brief Client socket. -*/ - -class JackClientSocket -{ - - private: - - int fSocket; - - public: - - JackClientSocket(): fSocket( -1) - {} - JackClientSocket(int socket); - - int Connect(const char* dir, int which); - int Connect(const char* dir, const char* name, int which); - int Close(); - int Read(void* data, int len); - int Write(void* data, int len); - int GetFd() - { - return fSocket; - } - void SetReadTimeOut(long sec); - void SetWriteTimeOut(long sec); - - void SetNonBlocking(bool onoff); -}; - -/*! -\brief Server socket. -*/ - -class JackServerSocket -{ - - private: - - int fSocket; - char fName[256]; - - public: - - JackServerSocket(): fSocket( -1) - {} - ~JackServerSocket() - {} - - int Bind(const char* dir, int which); - int Bind(const char* dir, const char* name, int which); - JackClientSocket* Accept(); - int Close(); - int GetFd() - { - return fSocket; - } -}; - -} // end of namespace - -#endif - diff --git a/common/JackSocketClientChannel.cpp b/common/JackSocketClientChannel.cpp deleted file mode 100644 index b9c578b7..00000000 --- a/common/JackSocketClientChannel.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackSocketClientChannel.h" -#include "JackRequest.h" -#include "JackClient.h" -#include "JackGlobals.h" - -namespace Jack -{ - -JackSocketClientChannel::JackSocketClientChannel(): - fThread(this) -{ - fNotificationSocket = NULL; - fClient = NULL; -} - -JackSocketClientChannel::~JackSocketClientChannel() -{ - delete fNotificationSocket; -} - -int JackSocketClientChannel::ServerCheck(const char* server_name) -{ - jack_log("JackSocketClientChannel::ServerCheck = %s", server_name); - - // Connect to server - if (fRequestSocket.Connect(jack_server_dir, server_name, 0) < 0) { - jack_error("Cannot connect to server socket"); - fRequestSocket.Close(); - return -1; - } else { - return 0; - } -} - -int JackSocketClientChannel::Open(const char* server_name, const char* name, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status) -{ - int result = 0; - jack_log("JackSocketClientChannel::Open name = %s", name); - - if (fRequestSocket.Connect(jack_server_dir, server_name, 0) < 0) { - jack_error("Cannot connect to server socket"); - goto error; - } - - // Check name in server - ClientCheck(name, name_res, JACK_PROTOCOL_VERSION, (int)options, (int*)status, &result); - if (result < 0) { - 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); - goto error; - } - - if (fNotificationListenSocket.Bind(jack_client_dir, name_res, 0) < 0) { - jack_error("Cannot bind socket"); - goto error; - } - - fClient = obj; - return 0; - -error: - fRequestSocket.Close(); - fNotificationListenSocket.Close(); - return -1; -} - -void JackSocketClientChannel::Close() -{ - fRequestSocket.Close(); - fNotificationListenSocket.Close(); - if (fNotificationSocket) - fNotificationSocket->Close(); -} - -int JackSocketClientChannel::Start() -{ - jack_log("JackSocketClientChannel::Start"); - /* - To be sure notification thread is started before ClientOpen is called. - */ - if (fThread.StartSync() != 0) { - jack_error("Cannot start Jack client listener"); - return -1; - } else { - return 0; - } -} - - -void JackSocketClientChannel::Stop() -{ - jack_log("JackSocketClientChannel::Stop"); - fThread.Kill(); -} - -void JackSocketClientChannel::ServerSyncCall(JackRequest* req, JackResult* res, int* result) -{ - if (req->Write(&fRequestSocket) < 0) { - jack_error("Could not write request type = %ld", req->fType); - *result = -1; - return; - } - - if (res->Read(&fRequestSocket) < 0) { - jack_error("Could not read result type = %ld", req->fType); - *result = -1; - return; - } - - *result = res->fResult; -} - -void JackSocketClientChannel::ServerAsyncCall(JackRequest* req, JackResult* res, int* result) -{ - if (req->Write(&fRequestSocket) < 0) { - jack_error("Could not write request type = %ld", req->fType); - *result = -1; - } else { - *result = 0; - } -} - -void JackSocketClientChannel::ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result) -{ - JackClientCheckRequest req(name, protocol, options); - JackClientCheckResult res; - ServerSyncCall(&req, &res, result); - *status = res.fStatus; - strcpy(name_res, res.fName); -} - -void JackSocketClientChannel::ClientOpen(const char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result) -{ - JackClientOpenRequest req(name, pid); - JackClientOpenResult res; - ServerSyncCall(&req, &res, result); - *shared_engine = res.fSharedEngine; - *shared_client = res.fSharedClient; - *shared_graph = res.fSharedGraph; -} - -void JackSocketClientChannel::ClientClose(int refnum, int* result) -{ - JackClientCloseRequest req(refnum); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::ClientActivate(int refnum, int state, int* result) -{ - JackActivateRequest req(refnum, state); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::ClientDeactivate(int refnum, int* result) -{ - JackDeactivateRequest req(refnum); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, unsigned int* port_index, int* result) -{ - JackPortRegisterRequest req(refnum, name, type, flags, buffer_size); - JackPortRegisterResult res; - ServerSyncCall(&req, &res, result); - *port_index = res.fPortIndex; -} - -void JackSocketClientChannel::PortUnRegister(int refnum, jack_port_id_t port_index, int* result) -{ - JackPortUnRegisterRequest req(refnum, port_index); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::PortConnect(int refnum, const char* src, const char* dst, int* result) -{ - JackPortConnectNameRequest req(refnum, src, dst); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::PortDisconnect(int refnum, const char* src, const char* dst, int* result) -{ - JackPortDisconnectNameRequest req(refnum, src, dst); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) -{ - JackPortConnectRequest req(refnum, src, dst); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result) -{ - JackPortDisconnectRequest req(refnum, src, dst); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::PortRename(int refnum, jack_port_id_t port, const char* name, int* result) -{ - JackPortRenameRequest req(refnum, port, name); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::SetBufferSize(jack_nframes_t buffer_size, int* result) -{ - JackSetBufferSizeRequest req(buffer_size); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::SetFreewheel(int onoff, int* result) -{ - JackSetFreeWheelRequest req(onoff); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::ReleaseTimebase(int refnum, int* result) -{ - JackReleaseTimebaseRequest req(refnum); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::SetTimebaseCallback(int refnum, int conditional, int* result) -{ - JackSetTimebaseCallbackRequest req(refnum, conditional); - JackResult res; - ServerSyncCall(&req, &res, result); -} - -void JackSocketClientChannel::GetInternalClientName(int refnum, int int_ref, char* name_res, int* result) -{ - JackGetInternalClientNameRequest req(refnum, int_ref); - JackGetInternalClientNameResult res; - ServerSyncCall(&req, &res, result); - strcpy(name_res, res.fName); -} - -void JackSocketClientChannel::InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result) -{ - JackInternalClientHandleRequest req(refnum, client_name); - JackInternalClientHandleResult res; - ServerSyncCall(&req, &res, result); - *int_ref = res.fIntRefNum; - *status = res.fStatus; -} - -void JackSocketClientChannel::InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int* result) -{ - JackInternalClientLoadRequest req(refnum, client_name, so_name, objet_data, options); - JackInternalClientLoadResult res; - ServerSyncCall(&req, &res, result); - *int_ref = res.fIntRefNum; - *status = res.fStatus; -} - -void JackSocketClientChannel::InternalClientUnload(int refnum, int int_ref, int* status, int* result) -{ - JackInternalClientUnloadRequest req(refnum, int_ref); - JackInternalClientUnloadResult res; - ServerSyncCall(&req, &res, result); - *status = res.fStatus; -} - -bool JackSocketClientChannel::Init() -{ - jack_log("JackSocketClientChannel::Init"); - fNotificationSocket = fNotificationListenSocket.Accept(); - // No more needed - fNotificationListenSocket.Close(); - - if (!fNotificationSocket) { - jack_error("JackSocketClientChannel: cannot establish notication socket"); - return false; - } else { - return fClient->Init(); - } -} - -bool JackSocketClientChannel::Execute() -{ - JackClientNotification event; - JackResult res; - - if (event.Read(fNotificationSocket) < 0) { - fNotificationSocket->Close(); - jack_error("JackSocketClientChannel read fail"); - goto error; - } - - res.fResult = fClient->ClientNotify(event.fRefNum, event.fName, event.fNotify, event.fSync, event.fValue1, event.fValue2); - - if (event.fSync) { - if (res.Write(fNotificationSocket) < 0) { - fNotificationSocket->Close(); - jack_error("JackSocketClientChannel write fail"); - goto error; - } - } - return true; - -error: - fClient->ShutDown(); - return false; -} - -} // end of namespace - - - - - diff --git a/common/JackSocketClientChannel.h b/common/JackSocketClientChannel.h deleted file mode 100644 index e13619bc..00000000 --- a/common/JackSocketClientChannel.h +++ /dev/null @@ -1,102 +0,0 @@ -/* -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 __JackSocketClientChannel__ -#define __JackSocketClientChannel__ - -#include "JackChannel.h" -#include "JackSocket.h" -#include "JackPlatformThread.h" -#include "JackRequest.h" -#include "JackError.h" - -namespace Jack -{ - -/*! -\brief JackClientChannel using sockets. -*/ - -class JackSocketClientChannel : public detail::JackClientChannelInterface, public JackRunnableInterface -{ - - private: - - JackClientSocket fRequestSocket; // Socket to communicate with the server - JackServerSocket fNotificationListenSocket; // Socket listener for server notification - JackClientSocket* fNotificationSocket; // Socket for server notification - JackThread fThread; // Thread to execute the event loop - JackClient* fClient; - - void ServerSyncCall(JackRequest* req, JackResult* res, int* result); - void ServerAsyncCall(JackRequest* req, JackResult* res, int* result); - - public: - - JackSocketClientChannel(); - virtual ~JackSocketClientChannel(); - - int Open(const char* server_name, const char* name, char* name_res, JackClient* obj, jack_options_t options, jack_status_t* status); - void Close(); - - int Start(); - void Stop(); - - int ServerCheck(const char* server_name); - - void ClientCheck(const char* name, char* name_res, int protocol, int options, int* status, int* result); - void ClientOpen(const char* name, int pid, 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) - {} - void ClientClose(int refnum, int* result); - - void ClientActivate(int refnum, int state, int* result); - void ClientDeactivate(int refnum, int* result); - - void PortRegister(int refnum, const char* name, const char* type, unsigned int flags, unsigned int buffer_size, unsigned int* port_index, int* result); - void PortUnRegister(int refnum, jack_port_id_t port_index, int* result); - - void PortConnect(int refnum, const char* src, const char* dst, int* result); - void PortDisconnect(int refnum, const char* src, const char* dst, int* result); - - void PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result); - void PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst, int* result); - - void PortRename(int refnum, jack_port_id_t port, const char* name, int* result); - - void SetBufferSize(jack_nframes_t buffer_size, int* result); - void SetFreewheel(int onoff, int* result); - - void ReleaseTimebase(int refnum, int* result); - void SetTimebaseCallback(int refnum, int conditional, int* result); - - void GetInternalClientName(int refnum, int int_ref, char* name_res, int* result); - void InternalClientHandle(int refnum, const char* client_name, int* status, int* int_ref, int* result); - void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int* result); - void InternalClientUnload(int refnum, int int_ref, int* status, int* result); - - // JackRunnableInterface interface - bool Init(); - bool Execute(); -}; - -} // end of namespace - -#endif - diff --git a/common/JackSocketNotifyChannel.cpp b/common/JackSocketNotifyChannel.cpp deleted file mode 100644 index 196c849f..00000000 --- a/common/JackSocketNotifyChannel.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackRequest.h" -#include "JackSocketNotifyChannel.h" -#include "JackError.h" -#include "JackConstants.h" - -namespace Jack -{ - -// Server to client -int JackSocketNotifyChannel::Open(const char* name) -{ - jack_log("JackSocketNotifyChannel::Open name = %s", name); - - // Connect to client listen socket - if (fNotifySocket.Connect(jack_client_dir, name, 0) < 0) { - jack_error("Cannot connect client socket"); - return -1; - } - - // Use a time out for notifications - fNotifySocket.SetReadTimeOut(SOCKET_TIME_OUT); - return 0; -} - -void JackSocketNotifyChannel::Close() -{ - jack_log("JackSocketNotifyChannel::Close"); - fNotifySocket.Close(); -} - -void JackSocketNotifyChannel::ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2, int* result) -{ - JackClientNotification event(name, refnum, notify, sync, value1, value2); - JackResult res; - - // Send notification - if (event.Write(&fNotifySocket) < 0) { - jack_error("Could not write notification"); - fNotifySocket.Close(); - *result = -1; - return; - } - - // Read the result in "synchronous" mode only - if (sync) { - // Get result : use a time out - if (res.Read(&fNotifySocket) < 0) { - jack_error("Could not read result"); - fNotifySocket.Close(); - *result = -1; - } else { - *result = res.fResult; - } - } else { - *result = 0; - } -} - -} // end of namespace - - diff --git a/common/JackSocketNotifyChannel.h b/common/JackSocketNotifyChannel.h deleted file mode 100644 index 9a40bbcb..00000000 --- a/common/JackSocketNotifyChannel.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -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 __JackSocketNotifyChannel__ -#define __JackSocketNotifyChannel__ - -#include "JackChannel.h" -#include "JackSocket.h" - -namespace Jack -{ - -/*! -\brief JackNotifyChannel using sockets. -*/ - -class JackSocketNotifyChannel -{ - - private: - - JackClientSocket fNotifySocket; // Socket to communicate with the server : from server to client - - public: - - JackSocketNotifyChannel() - {} - - int Open(const char* name); // Open the Server/Client connection - void Close(); // Close the Server/Client connection - - void ClientNotify(int refnum, const char* name, int notify, int sync, int value1, int value2, int* result); -}; - -} // end of namespace - -#endif - diff --git a/common/JackSocketServerChannel.cpp b/common/JackSocketServerChannel.cpp deleted file mode 100644 index ae415bc0..00000000 --- a/common/JackSocketServerChannel.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackSocketServerChannel.h" -#include "JackRequest.h" -#include "JackServer.h" -#include "JackLockedEngine.h" -#include "JackGlobals.h" -#include "JackClient.h" -#include "JackNotification.h" -#include -#include - -using namespace std; - -namespace Jack -{ - -JackSocketServerChannel::JackSocketServerChannel(): - fThread(this) -{ - fPollTable = NULL; - fRebuild = true; -} - -JackSocketServerChannel::~JackSocketServerChannel() -{ - delete[] fPollTable; -} - -int JackSocketServerChannel::Open(const char* server_name, JackServer* server) -{ - jack_log("JackSocketServerChannel::Open "); - fServer = server; - - // Prepare request socket - if (fRequestListenSocket.Bind(jack_server_dir, server_name, 0) < 0) { - jack_log("JackSocketServerChannel::Open : cannot create result listen socket"); - return -1; - } - - // Prepare for poll - BuildPoolTable(); - - // Start listening - if (fThread.Start() != 0) { - jack_error("Cannot start Jack server listener"); - goto error; - } - - return 0; - -error: - fRequestListenSocket.Close(); - return -1; -} - -void JackSocketServerChannel::Close() -{ - fThread.Kill(); - fRequestListenSocket.Close(); - - // Close remaining client sockets - std::map >::iterator it; - for (it = fSocketTable.begin(); it != fSocketTable.end(); it++) { - pair elem = (*it).second; - JackClientSocket* socket = elem.second; - assert(socket); - socket->Close(); - delete socket; - } -} - -void JackSocketServerChannel::ClientCreate() -{ - jack_log("JackSocketServerChannel::ClientCreate socket"); - JackClientSocket* socket = fRequestListenSocket.Accept(); - if (socket) { - fSocketTable[socket->GetFd()] = make_pair( -1, socket); - fRebuild = true; - } else { - jack_error("Client socket cannot be created"); - } -} - -void JackSocketServerChannel::ClientAdd(int fd, char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result) -{ - jack_log("JackSocketServerChannel::ClientAdd"); - int refnum = -1; - *result = fServer->GetEngine()->ClientExternalOpen(name, pid, &refnum, shared_engine, shared_client, shared_graph); - if (*result == 0) { - fSocketTable[fd].first = refnum; - fRebuild = true; - } else { - jack_error("Cannot create new client"); - } -} - -void JackSocketServerChannel::ClientRemove(int fd, int refnum) -{ - pair elem = fSocketTable[fd]; - JackClientSocket* socket = elem.second; - assert(socket); - jack_log("JackSocketServerChannel::ClientRemove ref = %d", refnum); - fSocketTable.erase(fd); - socket->Close(); - delete socket; - fRebuild = true; -} - -void JackSocketServerChannel::ClientKill(int fd) -{ - pair elem = fSocketTable[fd]; - JackClientSocket* socket = elem.second; - int refnum = elem.first; - - assert(socket); - jack_log("JackSocketServerChannel::ClientKill ref = %d", refnum); - - if (refnum == -1) { // Should never happen... correspond to a client that started the socket but never opened... - jack_log("Client was not opened : probably correspond to server_check"); - } else { - fServer->ClientKill(refnum); - } - - fSocketTable.erase(fd); - socket->Close(); - delete socket; - fRebuild = true; -} - -bool JackSocketServerChannel::HandleRequest(int fd) -{ - pair elem = fSocketTable[fd]; - JackClientSocket* socket = elem.second; - assert(socket); - - // Read header - JackRequest header; - if (header.Read(socket) < 0) { - jack_error("HandleRequest: cannot read header"); - return false; - } - - // Read data - switch (header.fType) { - - case JackRequest::kClientCheck: { - jack_log("JackRequest::kClientCheck"); - JackClientCheckRequest req; - JackClientCheckResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->ClientCheck(req.fName, res.fName, req.fProtocol, req.fOptions, &res.fStatus); - if (res.Write(socket) < 0) - jack_error("JackRequest::kClientCheck write error name = %s", req.fName); - break; - } - - case JackRequest::kClientOpen: { - jack_log("JackRequest::ClientOpen"); - JackClientOpenRequest req; - JackClientOpenResult res; - if (req.Read(socket) == 0) - ClientAdd(fd, req.fName, req.fPID, &res.fSharedEngine, &res.fSharedClient, &res.fSharedGraph, &res.fResult); - if (res.Write(socket) < 0) - jack_error("JackRequest::ClientOpen write error name = %s", req.fName); - break; - } - - case JackRequest::kClientClose: { - jack_log("JackRequest::ClientClose"); - JackClientCloseRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->ClientExternalClose(req.fRefNum); - if (res.Write(socket) < 0) - jack_error("JackRequest::ClientClose write error ref = %d", req.fRefNum); - ClientRemove(fd, req.fRefNum); - break; - } - - case JackRequest::kActivateClient: { - JackActivateRequest req; - JackResult res; - jack_log("JackRequest::ActivateClient"); - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->ClientActivate(req.fRefNum, req.fState); - if (res.Write(socket) < 0) - jack_error("JackRequest::ActivateClient write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kDeactivateClient: { - jack_log("JackRequest::DeactivateClient"); - JackDeactivateRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->ClientDeactivate(req.fRefNum); - if (res.Write(socket) < 0) - jack_error("JackRequest::DeactivateClient write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kRegisterPort: { - jack_log("JackRequest::RegisterPort"); - JackPortRegisterRequest req; - JackPortRegisterResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortRegister(req.fRefNum, req.fName, req.fPortType, req.fFlags, req.fBufferSize, &res.fPortIndex); - if (res.Write(socket) < 0) - jack_error("JackRequest::RegisterPort write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kUnRegisterPort: { - jack_log("JackRequest::UnRegisterPort"); - JackPortUnRegisterRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortUnRegister(req.fRefNum, req.fPortIndex); - if (res.Write(socket) < 0) - jack_error("JackRequest::UnRegisterPort write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kConnectNamePorts: { - jack_log("JackRequest::ConnectPorts"); - JackPortConnectNameRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); - if (res.Write(socket) < 0) - jack_error("JackRequest::ConnectNamePorts write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kDisconnectNamePorts: { - jack_log("JackRequest::DisconnectPorts"); - JackPortDisconnectNameRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); - if (res.Write(socket) < 0) - jack_error("JackRequest::DisconnectNamePorts write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kConnectPorts: { - jack_log("JackRequest::ConnectPorts"); - JackPortConnectRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortConnect(req.fRefNum, req.fSrc, req.fDst); - if (res.Write(socket) < 0) - jack_error("JackRequest::ConnectPorts write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kDisconnectPorts: { - jack_log("JackRequest::DisconnectPorts"); - JackPortDisconnectRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortDisconnect(req.fRefNum, req.fSrc, req.fDst); - if (res.Write(socket) < 0) - jack_error("JackRequest::DisconnectPorts write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kPortRename: { - jack_log("JackRequest::kPortRename"); - JackPortRenameRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->PortRename(req.fRefNum, req.fPort, req.fName); - if (res.Write(socket) < 0) - jack_error("JackRequest::PortRename write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kSetBufferSize: { - jack_log("JackRequest::SetBufferSize"); - JackSetBufferSizeRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->SetBufferSize(req.fBufferSize); - if (res.Write(socket) < 0) - jack_error("JackRequest::SetBufferSize write error"); - break; - } - - case JackRequest::kSetFreeWheel: { - jack_log("JackRequest::SetFreeWheel"); - JackSetFreeWheelRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->SetFreewheel(req.fOnOff); - if (res.Write(socket) < 0) - jack_error("JackRequest::SetFreeWheel write error"); - break; - } - - case JackRequest::kReleaseTimebase: { - jack_log("JackRequest::kReleaseTimebase"); - JackReleaseTimebaseRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->ReleaseTimebase(req.fRefNum); - if (res.Write(socket) < 0) - jack_error("JackRequest::kReleaseTimebase write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kSetTimebaseCallback: { - jack_log("JackRequest::kSetTimebaseCallback"); - JackSetTimebaseCallbackRequest req; - JackResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->SetTimebaseCallback(req.fRefNum, req.fConditionnal); - if (res.Write(socket) < 0) - jack_error("JackRequest::SetTimebaseCallback write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kGetInternalClientName: { - jack_log("JackRequest::kGetInternalClientName"); - JackGetInternalClientNameRequest req; - JackGetInternalClientNameResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->GetInternalClientName(req.fIntRefNum, res.fName); - if (res.Write(socket) < 0) - jack_error("JackRequest::GetInternalClientName write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kInternalClientHandle: { - jack_log("JackRequest::kInternalClientHandle"); - JackInternalClientHandleRequest req; - JackInternalClientHandleResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->InternalClientHandle(req.fName, &res.fStatus, &res.fIntRefNum); - if (res.Write(socket) < 0) - jack_error("JackRequest::InternalClientHandle write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kInternalClientLoad: { - jack_log("JackRequest::kInternalClientLoad"); - JackInternalClientLoadRequest req; - JackInternalClientLoadResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, &res.fStatus); - if (res.Write(socket) < 0) - jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName); - break; - } - - case JackRequest::kInternalClientUnload: { - jack_log("JackRequest::kInternalClientUnload"); - JackInternalClientUnloadRequest req; - JackInternalClientUnloadResult res; - if (req.Read(socket) == 0) - res.fResult = fServer->GetEngine()->InternalClientUnload(req.fIntRefNum, &res.fStatus); - if (res.Write(socket) < 0) - jack_error("JackRequest::InternalClientUnload write error ref = %d", req.fRefNum); - break; - } - - case JackRequest::kNotification: { - jack_log("JackRequest::Notification"); - JackClientNotificationRequest req; - if (req.Read(socket) == 0) - fServer->Notify(req.fRefNum, req.fNotify, req.fValue); - break; - } - - default: - jack_log("Unknown request %ld", header.fType); - break; - } - - return true; -} - -void JackSocketServerChannel::BuildPoolTable() -{ - if (fRebuild) { - fRebuild = false; - delete[] fPollTable; - fPollTable = new pollfd[fSocketTable.size() + 1]; - - jack_log("JackSocketServerChannel::BuildPoolTable size = %d", fSocketTable.size() + 1); - - // First fd is the server request socket - fPollTable[0].fd = fRequestListenSocket.GetFd(); - fPollTable[0].events = POLLIN | POLLERR; - - // Next fd for clients - map >::iterator it; - int i; - - for (i = 1, it = fSocketTable.begin(); it != fSocketTable.end(); it++, i++) { - jack_log("fSocketTable i = %ld fd = %ld", i, it->first); - fPollTable[i].fd = it->first; - fPollTable[i].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL; - } - } -} - -bool JackSocketServerChannel::Init() -{ - sigset_t set; - sigemptyset(&set); - sigaddset(&set, SIGPIPE); - pthread_sigmask(SIG_BLOCK, &set, 0); - return true; -} - -bool JackSocketServerChannel::Execute() -{ - // Global poll - if ((poll(fPollTable, fSocketTable.size() + 1, 10000) < 0) && (errno != EINTR)) { - jack_error("Engine poll failed err = %s request thread quits...", strerror(errno)); - return false; - } else { - - // Poll all clients - for (unsigned int i = 1; i < fSocketTable.size() + 1; i++) { - int fd = fPollTable[i].fd; - jack_log("fPollTable i = %ld fd = %ld", i, fd); - if (fPollTable[i].revents & ~POLLIN) { - jack_log("Poll client error err = %s", strerror(errno)); - ClientKill(fd); - } else if (fPollTable[i].revents & POLLIN) { - if (!HandleRequest(fd)) - jack_error("Could not handle external client request"); - } - } - - // Check the server request socket */ - if (fPollTable[0].revents & POLLERR) - jack_error("Error on server request socket err = %s", strerror(errno)); - - if (fPollTable[0].revents & POLLIN) - ClientCreate(); - } - - BuildPoolTable(); - return true; -} - -} // end of namespace - - diff --git a/common/JackSocketServerChannel.h b/common/JackSocketServerChannel.h deleted file mode 100644 index b5025ada..00000000 --- a/common/JackSocketServerChannel.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -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 __JackSocketServerChannel__ -#define __JackSocketServerChannel__ - -#include "JackChannel.h" -#include "JackSocket.h" -#include "JackPlatformThread.h" -#include -#include - -namespace Jack -{ - -/*! -\brief JackServerChannel using sockets. -*/ - -class JackSocketServerChannel : public JackRunnableInterface -{ - - private: - - JackServerSocket fRequestListenSocket; // Socket to create request socket for the client - JackThread fThread; // Thread to execute the event loop - JackServer* fServer; - pollfd* fPollTable; - bool fRebuild; - std::map > fSocketTable; - - bool HandleRequest(int fd); - void BuildPoolTable(); - - void ClientCreate(); - void ClientAdd(int fd, char* name, int pid, int* shared_engine, int* shared_client, int* shared_graph, int* result); - void ClientRemove(int fd, int refnum); - void ClientKill(int fd); - - public: - - JackSocketServerChannel(); - ~JackSocketServerChannel(); - - int Open(const char* server_name, JackServer* server); // Open the Server/Client connection - void Close(); // Close the Server/Client connection - - // JackRunnableInterface interface - bool Init(); - bool Execute(); -}; - -} // end of namespace - -#endif - diff --git a/common/JackSocketServerNotifyChannel.cpp b/common/JackSocketServerNotifyChannel.cpp deleted file mode 100644 index c5758967..00000000 --- a/common/JackSocketServerNotifyChannel.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* -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. - -*/ - -#if defined(HAVE_CONFIG_H) -#include "config.h" -#endif - -#include "JackSocketServerNotifyChannel.h" -#include "JackError.h" -#include "JackRequest.h" -#include "JackConstants.h" - -namespace Jack -{ - -int JackSocketServerNotifyChannel::Open(const char* server_name) -{ - if (fRequestSocket.Connect(jack_server_dir, server_name, 0) < 0) { - jack_error("Cannot connect to server socket"); - return -1; - } else { - fRequestSocket.SetNonBlocking(true); - return 0; - } -} - -void JackSocketServerNotifyChannel::Close() -{ - fRequestSocket.Close(); -} - -/* -The requirement is that the Notification from RT thread can be delivered... not sure using a socket is adequate here... -Can the write operation block? -A non blocking write operation shoud be used : check if write can succeed, and ignore the notification otherwise -(since its mainly used for XRun, ignoring a notification is OK, successive XRun will come...) -*/ -void JackSocketServerNotifyChannel::Notify(int refnum, int notify, int value) -{ - JackClientNotificationRequest req(refnum, notify, value); - if (req.Write(&fRequestSocket) < 0) { - jack_error("Could not write request ref = %ld notify = %ld", refnum, notify); - } -} - -} // end of namespace - - diff --git a/common/JackSocketServerNotifyChannel.h b/common/JackSocketServerNotifyChannel.h deleted file mode 100644 index 4d8afa54..00000000 --- a/common/JackSocketServerNotifyChannel.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -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 __JackSocketServerNotifyChannel__ -#define __JackSocketServerNotifyChannel__ - -#include "JackChannel.h" -#include "JackSocket.h" - -namespace Jack -{ - -/*! -\brief JackServerNotifyChannel using sockets. -*/ - -class JackSocketServerNotifyChannel -{ - private: - - JackClientSocket fRequestSocket; - - public: - - JackSocketServerNotifyChannel() - {} - - int Open(const char* server_name); - void Close(); - - void Notify(int refnum, int notify, int value); -}; - -} // end of namespace - -#endif - diff --git a/common/JackSynchro.h b/common/JackSynchro.h index 114f240e..34bcb5fd 100644 --- a/common/JackSynchro.h +++ b/common/JackSynchro.h @@ -94,6 +94,7 @@ class JackSynchro } }; + } } // end of namespace diff --git a/common/JackSystemDeps.h b/common/JackSystemDeps.h new file mode 100644 index 00000000..adcc51fa --- /dev/null +++ b/common/JackSystemDeps.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 2004-2006 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 __JackSystemDeps__ +#define __JackSystemDeps__ + +#include "systemdeps.h" +#include "JackSystemDeps_os.h" + +#endif diff --git a/common/JackThread.h b/common/JackThread.h index 2ded4825..b0eeb25d 100644 --- a/common/JackThread.h +++ b/common/JackThread.h @@ -21,16 +21,8 @@ #ifndef __JackThread__ #define __JackThread__ -#include "JackExports.h" - -#ifdef WIN32 -#include -typedef HANDLE pthread_t; -typedef ULONGLONG UInt64; -#else -#include -typedef unsigned long long UInt64; -#endif +#include "JackCompilerDeps.h" +#include "JackTypes.h" namespace Jack { @@ -65,7 +57,7 @@ class JackRunnableInterface namespace detail { -class EXPORT JackThread +class EXPORT JackThreadInterface { public: @@ -82,7 +74,7 @@ class EXPORT JackThread public: - JackThread(JackRunnableInterface* runnable, int priority, bool real_time, int cancellation): + JackThreadInterface(JackRunnableInterface* runnable, int priority, bool real_time, int cancellation): fRunnable(runnable), fPriority(priority), fRealTime(real_time), fStatus(kIdle), fCancellation(cancellation) {} @@ -98,18 +90,29 @@ class EXPORT JackThread void SetParams(UInt64 period, UInt64 computation, UInt64 constraint) // Empty implementation, will only make sense on OSX... {} + int Start(); + int StartSync(); + int Kill(); + int Stop(); + void Terminate(); + + int AcquireRealTime(); + int AcquireRealTime(int priority); + int DropRealTime(); + + pthread_t GetThreadID(); + + static int AcquireRealTimeImp(pthread_t thread, int priority); + static int DropRealTimeImp(pthread_t thread); + static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); + static int StopImp(pthread_t thread); + static int KillImp(pthread_t thread); }; } } // end of namespace -#if defined(WIN32) -typedef DWORD jack_tls_key; -#else -typedef pthread_key_t jack_tls_key; -#endif - EXPORT bool jack_tls_allocate_key(jack_tls_key *key_ptr); EXPORT bool jack_tls_free_key(jack_tls_key key); diff --git a/common/JackThreadedDriver.cpp b/common/JackThreadedDriver.cpp index 3eaa37c2..cde17da4 100644 --- a/common/JackThreadedDriver.cpp +++ b/common/JackThreadedDriver.cpp @@ -22,9 +22,7 @@ #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackThreadedDriver.h" #include "JackError.h" diff --git a/common/JackThreadedDriver.h b/common/JackThreadedDriver.h index f0a430b3..cb066175 100644 --- a/common/JackThreadedDriver.h +++ b/common/JackThreadedDriver.h @@ -22,7 +22,7 @@ #define __JackThreadedDriver__ #include "JackDriver.h" -#include "JackPlatformThread.h" +#include "JackPlatformPlug.h" namespace Jack { diff --git a/common/JackTime.h b/common/JackTime.h index 8cee88cb..3afbadfe 100644 --- a/common/JackTime.h +++ b/common/JackTime.h @@ -22,86 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define __JackTime__ #include "types.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include -#ifdef __cplusplus -extern "C" -{ -#endif - -#if defined(__APPLE__) - -#include -#include - - extern EXPORT double __jack_time_ratio; - - static inline jack_time_t GetMicroSeconds(void) - { - return (jack_time_t) (mach_absolute_time () * __jack_time_ratio); - } - - /* This should only be called ONCE per process. */ - void InitTime(); - - static inline void JackSleep(int usec) - { - usleep(usec); - } - -#endif - -#ifdef WIN32 - - extern EXPORT LARGE_INTEGER _jack_freq; - - EXPORT jack_time_t GetMicroSeconds(void) ; - - void InitTime(); - - static void JackSleep(int usec) - { - Sleep(usec / 1000); - } - -#endif - -#ifdef linux - -#include - - static inline void JackSleep(long usec) - { - usleep(usec); - } - -#ifdef GETCYCLE_TIME -#include "cycles.h" - extern jack_time_t __jack_cpu_mhz; - jack_time_t GetMhz(); - void InitTime(); - static inline jack_time_t GetMicroSeconds(void) - { - return get_cycles() / __jack_cpu_mhz; - } -#else -#include - void InitTime(); - static inline jack_time_t GetMicroSeconds(void) - { - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (jack_time_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000; - } -#endif - -#endif - -#ifdef __cplusplus -} -#endif - +#include "JackTime_os.h" #endif diff --git a/common/JackTools.h b/common/JackTools.h index 5cbf381e..2c89202b 100644 --- a/common/JackTools.h +++ b/common/JackTools.h @@ -40,7 +40,7 @@ #include "jslist.h" #include "driver_interface.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "JackError.h" namespace Jack diff --git a/common/JackTransportEngine.h b/common/JackTransportEngine.h index a7a8d7b0..018e5754 100644 --- a/common/JackTransportEngine.h +++ b/common/JackTransportEngine.h @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define __JackTransportEngine__ #include "JackAtomicArrayState.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #include "types.h" namespace Jack diff --git a/common/JackTypes.h b/common/JackTypes.h index 561bd4bc..00c09aad 100644 --- a/common/JackTypes.h +++ b/common/JackTypes.h @@ -30,14 +30,7 @@ typedef unsigned long UInt32; typedef signed long SInt32; #endif -#ifdef WIN32 -#include -typedef ULONGLONG UInt64; -typedef unsigned short uint16_t; -#else -#include -typedef unsigned long long UInt64; -#endif +#include "JackTypes_os.h" typedef uint16_t jack_int_t; // Internal type for ports and refnum diff --git a/common/JackWaitThreadedDriver.cpp b/common/JackWaitThreadedDriver.cpp index 49b08121..6cd6fc96 100644 --- a/common/JackWaitThreadedDriver.cpp +++ b/common/JackWaitThreadedDriver.cpp @@ -22,9 +22,7 @@ #include "config.h" #endif -#ifdef WIN32 -#pragma warning (disable : 4786) -#endif +#include "JackSystemDeps.h" #include "JackWaitThreadedDriver.h" #include "JackGlobals.h" diff --git a/common/cycles.h b/common/cycles.h deleted file mode 100644 index 2913b1da..00000000 --- a/common/cycles.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (C) 2001 Paul Davis - Code derived from various headers from the Linux kernel - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - $Id: cycles.h,v 1.4.2.1 2006/06/20 14:44:00 letz Exp $ -*/ - -#ifndef __jack_cycles_h__ -#define __jack_cycles_h__ - -/* - * Standard way to access the cycle counter on i586+ CPUs. - * Currently only used on SMP. - * - * If you really have a SMP machine with i486 chips or older, - * compile for that, and this will just always return zero. - * That's ok, it just means that the nicer scheduling heuristics - * won't work for you. - * - * We only use the low 32 bits, and we'd simply better make sure - * that we reschedule before that wraps. Scheduling at least every - * four billion cycles just basically sounds like a good idea, - * regardless of how fast the machine is. - */ - -#ifdef __linux__ - -#ifdef __PPC__ - -/* PowerPC */ - -#define CPU_FTR_601 0x00000100 - -typedef unsigned long cycles_t; - -/* For the "cycle" counter we use the timebase lower half. */ - -extern cycles_t cacheflush_time; - -static inline cycles_t get_cycles(void) -{ - cycles_t ret = 0; - - __asm__ __volatile__( - "98: mftb %0\n" - "99:\n" - ".section __ftr_fixup,\"a\"\n" - " .long %1\n" - " .long 0\n" - " .long 98b\n" - " .long 99b\n" - ".previous" - : "=r" (ret) : "i" (CPU_FTR_601)); - return ret; -} - -#endif - -#ifdef __i386__ - -typedef unsigned long long cycles_t; - -extern cycles_t cacheflush_time; - -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - -static inline cycles_t get_cycles (void) -{ - unsigned long long ret; - - rdtscll(ret); - return ret; -} - -#endif - -#endif - -#endif /* __jack_cycles_h__ */ diff --git a/common/driver_interface.h b/common/driver_interface.h index bbf5d9a9..5a6138e6 100644 --- a/common/driver_interface.h +++ b/common/driver_interface.h @@ -27,14 +27,9 @@ extern "C" #include #include "jslist.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" -#ifdef WIN32 -#include "types.h" -#define PATH_MAX 1024 -#else -#include -#endif +#include "JackSystemDeps.h" #define JACK_DRIVER_NAME_MAX 15 #define JACK_DRIVER_PARAM_NAME_MAX 15 diff --git a/common/jack/control.h b/common/jack/control.h index dfb87b16..96cf3e14 100644 --- a/common/jack/control.h +++ b/common/jack/control.h @@ -30,10 +30,7 @@ #define JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED #include - -#ifdef WIN32 -typedef unsigned long sigset_t; -#endif +#include /** Parameter types, intentionally similar to jack_driver_param_type_t */ typedef enum diff --git a/common/jack/jack.h b/common/jack/jack.h index d5336259..b77661b2 100644 --- a/common/jack/jack.h +++ b/common/jack/jack.h @@ -26,13 +26,7 @@ extern "C" { #endif -#ifdef WIN32 - #include - typedef HANDLE pthread_t; -#else - #include -#endif - +#include #include #include diff --git a/common/jack/jslist.h b/common/jack/jslist.h index 1f9814e9..c3a501ee 100644 --- a/common/jack/jslist.h +++ b/common/jack/jslist.h @@ -27,9 +27,7 @@ #include -#ifdef WIN32 -#define __inline__ inline -#endif +#include typedef struct _JSList JSList; @@ -285,290 +283,4 @@ jack_slist_sort (JSList *list, } #endif /* __jack_jslist_h__ */ -/* - Based on gslist.c from glib-1.2.9 (LGPL). - - Adaption to JACK, Copyright (C) 2002 Kai Vehmanen. - - replaced use of gtypes with normal ANSI C types - - glib's memory allocation routines replaced with - malloc/free calls - - 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_jslist_h__ -#define __jack_jslist_h__ - -#include - -#ifdef WIN32 -#define __inline__ inline -#endif - -typedef struct _JSList JSList; - -typedef int (*JCompareFunc) (void* a, void* b); -struct _JSList -{ - void *data; - JSList *next; -}; - -static __inline__ -JSList* -jack_slist_alloc (void) -{ - JSList *new_list; - - new_list = (JSList*)malloc(sizeof(JSList)); - new_list->data = NULL; - new_list->next = NULL; - - return new_list; -} - -static __inline__ -JSList* -jack_slist_prepend (JSList* list, void* data) -{ - JSList *new_list; - - new_list = (JSList*)malloc(sizeof(JSList)); - new_list->data = data; - new_list->next = list; - - return new_list; -} - -#define jack_slist_next(slist) ((slist) ? (((JSList *)(slist))->next) : NULL) -static __inline__ -JSList* -jack_slist_last (JSList *list) -{ - if (list) { - while (list->next) - list = list->next; - } - - return list; -} - -static __inline__ -JSList* -jack_slist_remove_link (JSList *list, - JSList *link) -{ - JSList *tmp; - JSList *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp == link) { - if (prev) - prev->next = tmp->next; - if (list == tmp) - list = list->next; - - tmp->next = NULL; - break; - } - - prev = tmp; - tmp = tmp->next; - } - return list; -} - -static __inline__ -void -jack_slist_free (JSList *list) -{ - while (list) { - JSList *next = list->next; - free(list); - list = next; - } -} - -static __inline__ -void -jack_slist_free_1 (JSList *list) -{ - if (list) { - free(list); - } -} - -static __inline__ -JSList* -jack_slist_remove (JSList *list, - void *data) -{ - JSList *tmp; - JSList *prev; - - prev = NULL; - tmp = list; - - while (tmp) { - if (tmp->data == data) { - if (prev) - prev->next = tmp->next; - if (list == tmp) - list = list->next; - - tmp->next = NULL; - jack_slist_free (tmp); - - break; - } - - prev = tmp; - tmp = tmp->next; - } - - return list; -} - -static __inline__ -unsigned int -jack_slist_length (JSList *list) -{ - unsigned int length; - - length = 0; - while (list) { - length++; - list = list->next; - } - - return length; -} - -static __inline__ -JSList* -jack_slist_find (JSList *list, - void *data) -{ - while (list) { - if (list->data == data) - break; - list = list->next; - } - - return list; -} - -static __inline__ -JSList* -jack_slist_copy (JSList *list) -{ - JSList *new_list = NULL; - - if (list) { - JSList *last; - - new_list = jack_slist_alloc (); - new_list->data = list->data; - last = new_list; - list = list->next; - while (list) { - last->next = jack_slist_alloc (); - last = last->next; - last->data = list->data; - list = list->next; - } - } - - return new_list; -} - -static __inline__ -JSList* -jack_slist_append (JSList *list, - void *data) -{ - JSList *new_list; - JSList *last; - - new_list = jack_slist_alloc (); - new_list->data = data; - - if (list) { - last = jack_slist_last (list); - last->next = new_list; - - return list; - } else - return new_list; -} - -static __inline__ -JSList* -jack_slist_sort_merge (JSList *l1, - JSList *l2, - JCompareFunc compare_func) -{ - JSList list, *l; - - l = &list; - - while (l1 && l2) { - if (compare_func(l1->data, l2->data) < 0) { - l = l->next = l1; - l1 = l1->next; - } else { - l = l->next = l2; - l2 = l2->next; - } - } - l->next = l1 ? l1 : l2; - - return list.next; -} - -static __inline__ -JSList* -jack_slist_sort (JSList *list, - JCompareFunc compare_func) -{ - JSList *l1, *l2; - - if (!list) - return NULL; - if (!list->next) - return list; - - l1 = list; - l2 = list->next; - - while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) - break; - l1 = l1->next; - } - l2 = l1->next; - l1->next = NULL; - - return jack_slist_sort_merge (jack_slist_sort (list, compare_func), - jack_slist_sort (l2, compare_func), - compare_func); -} - -#endif /* __jack_jslist_h__ */ diff --git a/common/jack/systemdeps.h b/common/jack/systemdeps.h new file mode 100644 index 00000000..3d453828 --- /dev/null +++ b/common/jack/systemdeps.h @@ -0,0 +1,62 @@ +/* +Copyright (C) 2004-2006 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 __jack_systemdeps_h__ +#define __jack_systemdeps_h__ + +#ifdef WIN32 + +#include + +#ifdef __MINGW32__ + #include + #include +#else + #define __inline__ inline + #define vsnprintf _vsnprintf + #define snprintf _snprintf + + typedef char int8_t; + typedef unsigned char uint8_t; + typedef short int16_t; + typedef unsigned short uint16_t; + typedef long int32_t; + typedef unsigned long uint32_t; + typedef LONGLONG int64_t; + typedef ULONGLONG uint64_t; + +#endif + + typedef HANDLE pthread_t; + typedef int64_t _jack_time_t; + +#endif // WIN32 */ + +#if defined(__APPLE__) || defined(__linux__) + +#include +#include +#include + +typedef uint64_t _jack_time_t; + +#endif // __APPLE__ || __linux__ */ + + +#endif diff --git a/common/jack/thread.h b/common/jack/thread.h index f04fb24b..14066006 100644 --- a/common/jack/thread.h +++ b/common/jack/thread.h @@ -25,13 +25,7 @@ extern "C" { #endif -#ifdef WIN32 - #include - typedef HANDLE pthread_t; -#else - #include -#endif - +#include /** @file thread.h * diff --git a/common/jack/types.h b/common/jack/types.h index 8bfcc798..30e0d9db 100644 --- a/common/jack/types.h +++ b/common/jack/types.h @@ -21,26 +21,8 @@ #ifndef __jack_types_h__ #define __jack_types_h__ -#ifdef WIN32 -#include -#ifndef __MINGW32__ - #define vsnprintf _vsnprintf - #define snprintf _snprintf - typedef char int8_t; - typedef unsigned char uint8_t; - typedef short int16_t; - typedef unsigned short uint16_t; - typedef long int32_t; - typedef unsigned long uint32_t; - typedef LONGLONG int64_t; - typedef ULONGLONG uint64_t; -#else - #include -#endif +#include -#else - #include -#endif typedef int32_t jack_shmsize_t; @@ -59,11 +41,7 @@ typedef uint32_t jack_nframes_t; * monotonic clock with units of microseconds. */ -#ifdef WIN32 -typedef int64_t jack_time_t; -#else -typedef uint64_t jack_time_t; -#endif +typedef _jack_time_t jack_time_t; /** * Maximum size of @a load_init string passed to an internal client @@ -475,7 +453,7 @@ typedef enum { #define EXTENDED_TIME_INFO typedef struct { - + /* these four cannot be set from clients: the server sets them */ jack_unique_t unique_1; /**< unique ID */ jack_time_t usecs; /**< monotonic, free-rolling */ @@ -488,7 +466,7 @@ typedef struct { int32_t bar; /**< current bar */ int32_t beat; /**< current beat-within-bar */ int32_t tick; /**< current tick-within-beat */ - double bar_start_tick; + double bar_start_tick; float beats_per_bar; /**< time signature "numerator" */ float beat_type; /**< time signature "denominator" */ @@ -499,15 +477,15 @@ typedef struct { double frame_time; /**< current time in seconds */ double next_time; /**< next sequential frame_time (unless repositioned) */ - + /* JackBBTFrameOffset fields: */ jack_nframes_t bbt_offset; /**< frame offset for the BBT fields (the given bar, beat, and tick values actually refer to a time frame_offset frames before the - start of the cycle), should - be assumed to be 0 if - JackBBTFrameOffset is not + start of the cycle), should + be assumed to be 0 if + JackBBTFrameOffset is not set. If JackBBTFrameOffset is set and this value is zero, the BBT time refers to the first frame of this diff --git a/common/ringbuffer.c b/common/ringbuffer.c index 92639079..a495eb75 100644 --- a/common/ringbuffer.c +++ b/common/ringbuffer.c @@ -30,7 +30,7 @@ #include #endif /* USE_MLOCK */ #include "jack/ringbuffer.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" /* 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. */ diff --git a/common/shm.h b/common/shm.h index e2bac1cf..b6195948 100644 --- a/common/shm.h +++ b/common/shm.h @@ -4,7 +4,7 @@ #include #include #include "types.h" -#include "JackExports.h" +#include "JackCompilerDeps.h" #define TRUE 1 diff --git a/common/wscript b/common/wscript index 698668e0..27a9e544 100644 --- a/common/wscript +++ b/common/wscript @@ -42,7 +42,11 @@ def create_jack_process_obj(bld, target, sources, uselib = None): process = bld.create_obj('cpp', 'shlib') process.env['shlib_PATTERN'] = '%s.so' process.defines = 'HAVE_CONFIG_H' - process.includes = ['./jack', '.', '..', '../macosx','../windows', '../linux/alsa'] + if bld.env()['IS_MACOSX']: + env_includes = ['../macosx', '../posix'] + if bld.env()['IS_LINUX']: + env_includes = ['../linux', '../posix', '../linux/alsa'] + process.includes = ['.'] + env_includes + ['jack', '..'] process.name = target process.target = target process.source = sources @@ -72,10 +76,8 @@ def build(bld): 'JackMidiPort.cpp', 'JackMidiAPI.cpp', 'JackEngineControl.cpp', - 'JackPosixThread.cpp', 'JackShmMem.cpp', 'shm.c', - 'JackSocket.cpp', 'JackTime.c', 'JackGlobals.cpp', 'JackDebugClient.cpp', @@ -83,7 +85,6 @@ def build(bld): 'timestamps.c', 'JackTools.cpp', 'JackMessageBuffer.cpp', - 'JackProcessSync.cpp', ] includes = ['.', './jack', '..'] @@ -91,20 +92,25 @@ def build(bld): if bld.env()['IS_LINUX']: common_libsources += [ - 'JackPosixSemaphore.cpp', - 'JackFifo.cpp', + '../posix/JackPosixThread.cpp', + '../posix/JackPosixSemaphore.cpp', + '../posix/JackFifo.cpp', + '../posix/JackProcessSync.cpp', + '../posix/JackSocket.cpp', ] - includes.append('../linux') + includes = ['../linux', '../posix'] + includes uselib.append('RT') uselib.append('DL') if bld.env()['IS_MACOSX']: common_libsources += [ - '../macosx/JackMachSemaphore.cpp', + '../posix/JackProcessSync.cpp', + '../posix/JackPosixThread.cpp', '../macosx/JackMachThread.cpp', + '../macosx/JackMachSemaphore.cpp', '../macosx/JackMachPort.cpp', ] - includes += ['../macosx', '../macosx/RPC'] + includes = ['../macosx', '../macosx/RPC', '../posix'] + includes serverlib = bld.create_obj('cpp', 'shlib') serverlib.features.append('cc') @@ -124,8 +130,8 @@ def build(bld): 'JackLoopbackDriver.cpp', 'JackServer.cpp', 'JackThreadedDriver.cpp', - 'JackRestartThreadedDriver.cpp', - 'JackWaitThreadedDriver.cpp', + 'JackRestartThreadedDriver.cpp', + 'JackWaitThreadedDriver.cpp', 'JackServerAPI.cpp', 'JackDriverLoader.cpp', 'JackServerGlobals.cpp', @@ -136,10 +142,10 @@ def build(bld): if bld.env()['IS_LINUX']: serverlib.source += [ - 'JackSocketServerChannel.cpp', - 'JackSocketNotifyChannel.cpp', - 'JackSocketServerNotifyChannel.cpp', - 'JackNetUnixSocket.cpp', + '../posix/JackSocketServerChannel.cpp', + '../posix/JackSocketNotifyChannel.cpp', + '../posix/JackSocketServerNotifyChannel.cpp', + '../posix/JackNetUnixSocket.cpp', ] if bld.env()['IS_MACOSX']: @@ -149,7 +155,7 @@ def build(bld): '../macosx/JackMachServerNotifyChannel.cpp', '../macosx/JackMacEngineRPC.cpp', '../macosx/RPC/JackRPCClientUser.c', - 'JackNetUnixSocket.cpp', + '../posix/JackNetUnixSocket.cpp', ] serverlib.vnum = bld.env()['JACK_API_VERSION'] @@ -178,7 +184,7 @@ def build(bld): if bld.env()['IS_LINUX']: clientlib.source += [ - 'JackSocketClientChannel.cpp', + '../posix/JackSocketClientChannel.cpp', ] if bld.env()['IS_MACOSX']: diff --git a/dbus/controller.c b/dbus/controller.c new file mode 100644 index 00000000..01bc3b3b --- /dev/null +++ b/dbus/controller.c @@ -0,0 +1,423 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + + 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 +#include +#include + +#include "controller.h" +#include "controller_internal.h" +#include "xml.h" + +struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] = +{ + &g_jack_controller_iface_introspectable, + &g_jack_controller_iface_control, + &g_jack_controller_iface_configure, + &g_jack_controller_iface_patchbay, + &g_jack_controller_iface_transport, + NULL +}; + +jackctl_driver_t * +jack_controller_find_driver( + jackctl_server_t *server, + const char *driver_name) +{ + const JSList * node_ptr; + + node_ptr = jackctl_server_get_drivers_list(server); + + while (node_ptr) + { + if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0) + { + return node_ptr->data; + } + + node_ptr = jack_slist_next(node_ptr); + } + + return NULL; +} + +jackctl_internal_t * +jack_controller_find_internal( + jackctl_server_t *server, + const char *internal_name) +{ + const JSList * node_ptr; + + node_ptr = jackctl_server_get_internals_list(server); + + while (node_ptr) + { + if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0) + { + return node_ptr->data; + } + + node_ptr = jack_slist_next(node_ptr); + } + + 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) + { + return false; + } + + jack_info("driver \"%s\" selected", driver_name); + + controller_ptr->driver = driver; + + return true; +} + +static +int +jack_controller_xrun(void * arg) +{ + ((struct jack_controller *)arg)->xruns++; + + return 0; +} + +bool +jack_controller_start_server( + struct jack_controller * controller_ptr, + void *dbus_call_context_ptr) +{ + int ret; + + jack_info("Starting jack server..."); + + if (controller_ptr->started) + { + jack_info("Already started."); + return TRUE; + } + + 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_start( + controller_ptr->server, + controller_ptr->driver)) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); + goto fail; + } + + controller_ptr->client = jack_client_open( + "dbusapi", + JackNoStartServer, + NULL); + if (controller_ptr->client == NULL) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client"); + + goto fail_stop_server; + } + + ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr); + if (ret != 0) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret); + + goto fail_close_client; + } + + if (!jack_controller_patchbay_init(controller_ptr)) + { + jack_error("Failed to initialize patchbay district"); + goto fail_close_client; + } + + ret = jack_activate(controller_ptr->client); + if (ret != 0) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret); + + goto fail_patchbay_uninit; + } + + controller_ptr->started = true; + + return TRUE; + +fail_patchbay_uninit: + jack_controller_patchbay_uninit(controller_ptr); + +fail_close_client: + ret = jack_client_close(controller_ptr->client); + if (ret != 0) + { + jack_error("jack_client_close() failed with error %d", ret); + } + + controller_ptr->client = NULL; + +fail_stop_server: + if (!jackctl_server_stop(controller_ptr->server)) + { + jack_error("failed to stop jack server"); + } + +fail: + return FALSE; +} + +bool +jack_controller_stop_server( + struct jack_controller * controller_ptr, + void *dbus_call_context_ptr) +{ + int ret; + + jack_info("Stopping jack server..."); + + if (!controller_ptr->started) + { + jack_info("Already stopped."); + return TRUE; + } + + ret = jack_deactivate(controller_ptr->client); + if (ret != 0) + { + jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret); + } + + jack_controller_patchbay_uninit(controller_ptr); + + ret = jack_client_close(controller_ptr->client); + if (ret != 0) + { + jack_error("jack_client_close() failed with error %d", ret); + } + + controller_ptr->client = NULL; + + if (!jackctl_server_stop(controller_ptr->server)) + { + return FALSE; + } + + controller_ptr->started = false; + + return TRUE; +} + +void * +jack_controller_create( + DBusConnection *connection) +{ + struct jack_controller *controller_ptr; + const JSList * node_ptr; + const char ** driver_name_target; + const char ** internal_name_target; + JSList * drivers; + JSList * internals; + DBusObjectPathVTable vtable = + { + jack_dbus_message_handler_unregister, + jack_dbus_message_handler, + NULL + }; + + controller_ptr = malloc(sizeof(struct jack_controller)); + if (!controller_ptr) + { + jack_error("Ran out of memory trying to allocate struct jack_controller"); + goto fail; + } + + controller_ptr->server = jackctl_server_create(); + if (controller_ptr->server == NULL) + { + jack_error("Failed to create server object"); + goto fail_free; + } + + controller_ptr->client = NULL; + controller_ptr->started = false; + controller_ptr->driver = NULL; + + 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) + { + jack_error("Ran out of memory trying to allocate driver names array"); + goto fail_destroy_server; + } + + driver_name_target = controller_ptr->driver_names; + node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); + while (node_ptr != NULL) + { + *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data); + 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; + } + + 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++; + } + + controller_ptr->dbus_descriptor.context = controller_ptr; + controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; + + if (!dbus_connection_register_object_path( + connection, + JACK_CONTROLLER_OBJECT_PATH, + &vtable, + &controller_ptr->dbus_descriptor)) + { + jack_error("Ran out of memory trying to register D-Bus object path"); + goto fail_free_internal_names_array; + } + + 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_server: + jackctl_server_destroy(controller_ptr->server); + +fail_free: + free(controller_ptr); + +fail: + return NULL; +} + +bool +jack_controller_load_internal( + struct jack_controller *controller_ptr, + const char * internal_name) +{ + jackctl_internal_t *internal; + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + return false; + } + + jack_info("internal \"%s\" selected", internal_name); + + return jackctl_server_load_internal(controller_ptr->server, internal); +} + +bool +jack_controller_unload_internal( + struct jack_controller *controller_ptr, + const char * internal_name) +{ + jackctl_internal_t *internal; + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + return false; + } + + jack_info("internal \"%s\" selected", internal_name); + + return jackctl_server_unload_internal(controller_ptr->server, internal); +} + +#define controller_ptr ((struct jack_controller *)context) + +void +jack_controller_destroy( + void * context) +{ + if (controller_ptr->started) + { + jack_controller_stop_server(controller_ptr, NULL); + } + + free(controller_ptr->driver_names); + free(controller_ptr->internal_names); + + jackctl_server_destroy(controller_ptr->server); + + free(controller_ptr); +} + diff --git a/dbus/controller.h b/dbus/controller.h new file mode 100644 index 00000000..19887b4f --- /dev/null +++ b/dbus/controller.h @@ -0,0 +1,31 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007 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 CONTROLLER_H__2CC80B1E_8D5D_45E3_A9D8_9086DDF68BB5__INCLUDED +#define CONTROLLER_H__2CC80B1E_8D5D_45E3_A9D8_9086DDF68BB5__INCLUDED + +void * +jack_controller_create( + DBusConnection *connection); + +void +jack_controller_destroy( + void *controller_ptr); + +#endif /* #ifndef CONTROLLER_H__2CC80B1E_8D5D_45E3_A9D8_9086DDF68BB5__INCLUDED */ diff --git a/dbus/controller_iface_configure.c b/dbus/controller_iface_configure.c new file mode 100644 index 00000000..804b19b2 --- /dev/null +++ b/dbus/controller_iface_configure.c @@ -0,0 +1,1108 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + + 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 +#include +#include +#include + +#include "jackdbus.h" +#include "controller_internal.h" +#include "xml.h" + +unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] = +{ + [JackParamInt] = DBUS_TYPE_INT32, + [JackParamUInt] = DBUS_TYPE_UINT32, + [JackParamChar] = DBUS_TYPE_BYTE, + [JackParamString] = DBUS_TYPE_STRING, + [JackParamBool] = DBUS_TYPE_BOOLEAN, +}; + +const char *jack_controller_dbus_type_signatures[JACK_PARAM_MAX] = +{ + [JackParamInt] = DBUS_TYPE_INT32_AS_STRING, + [JackParamUInt] = DBUS_TYPE_UINT32_AS_STRING, + [JackParamChar] = DBUS_TYPE_BYTE_AS_STRING, + [JackParamString] = DBUS_TYPE_STRING_AS_STRING, + [JackParamBool] = DBUS_TYPE_BOOLEAN_AS_STRING, +}; + +#define PARAM_TYPE_JACK_TO_DBUS(_) jack_controller_dbus_types[_] +#define PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(_) jack_controller_dbus_type_signatures[_] + +static +bool +jack_controller_jack_to_dbus_variant( + jackctl_param_type_t type, + const union jackctl_parameter_value *value_ptr, + message_arg_t *dbusv_ptr) +{ + switch (type) + { + case JackParamInt: + dbusv_ptr->int32 = (dbus_int32_t)value_ptr->i; + return true; + case JackParamUInt: + dbusv_ptr->uint32 = (dbus_uint32_t)value_ptr->ui; + return true; + case JackParamChar: + dbusv_ptr->byte = value_ptr->c; + return true; + case JackParamString: + dbusv_ptr->string = value_ptr->str; + return true; + case JackParamBool: + dbusv_ptr->boolean = (dbus_bool_t)value_ptr->b; + return true; + } + + jack_error("Unknown JACK parameter type %i", (int)type); + assert(0); + return false; +} + +static +bool +jack_controller_dbus_to_jack_variant( + int type, + const message_arg_t *dbusv_ptr, + union jackctl_parameter_value *value_ptr) +{ + size_t len; + + switch (type) + { + case DBUS_TYPE_INT32: + value_ptr->i = dbusv_ptr->int32; + return true; + case DBUS_TYPE_UINT32: + value_ptr->ui = dbusv_ptr->uint32; + return true; + case DBUS_TYPE_BYTE: + value_ptr->c = dbusv_ptr->byte; + return true; + case DBUS_TYPE_STRING: + len = strlen(dbusv_ptr->string); + if (len > JACK_PARAM_STRING_MAX) + { + jack_error("Parameter string value is too long (%u)", (unsigned int)len); + return false; + } + memcpy(value_ptr->str, dbusv_ptr->string, len + 1); + + return true; + case DBUS_TYPE_BOOLEAN: + value_ptr->b = dbusv_ptr->boolean; + return true; + } + + jack_error("Unknown D-Bus parameter type %i", (int)type); + return false; +} + +/* + * Construct a return message for a Get[Driver|Engine]ParameterValue method call. + * + * The operation can only fail due to lack of memory, in which case + * there's no sense in trying to construct an error return. Instead, + * call->reply will be set to NULL and handled in send_method_return(). + */ +static void +jack_dbus_construct_method_return_parameter( + struct jack_dbus_method_call *call, + dbus_bool_t is_set, + int type, + const char *signature, + message_arg_t default_value, + message_arg_t value) +{ + DBusMessageIter iter; + + /* Create a new method return message. */ + call->reply = dbus_message_new_method_return (call->message); + if (!call->reply) + { + goto fail; + } + + dbus_message_iter_init_append (call->reply, &iter); + + /* Append the is_set argument. */ + if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, (const void *) &is_set)) + { + goto fail_unref; + } + + /* Append the 'default' and 'value' arguments. */ + if (!jack_dbus_message_append_variant(&iter, type, signature, &default_value)) + { + goto fail_unref; + } + if (!jack_dbus_message_append_variant(&iter, type, signature, &value)) + { + goto fail_unref; + } + + return; + +fail_unref: + dbus_message_unref (call->reply); + call->reply = NULL; + +fail: + jack_error ("Ran out of memory trying to construct method return"); +} + +#define controller_ptr ((struct jack_controller *)call->context) + +static +void +jack_controller_dbus_get_available_drivers( + struct jack_dbus_method_call *call) +{ + jack_dbus_construct_method_return_array_of_strings( + call, + controller_ptr->drivers_count, + controller_ptr->driver_names); +} + +static +void +jack_controller_dbus_get_selected_driver( + struct jack_dbus_method_call *call) +{ + message_arg_t arg; + + if (controller_ptr->driver != NULL) + { + arg.string = jackctl_driver_get_name(controller_ptr->driver); + } + else + { + arg.string = NULL; + } + + jack_dbus_construct_method_return_single(call, DBUS_TYPE_STRING, arg); +} + +static +void +jack_controller_dbus_select_driver( + struct jack_dbus_method_call *call) +{ + const char *driver_name; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &driver_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + if (!jack_controller_select_driver(controller_ptr, driver_name)) + { + /* Couldn't find driver with the specified name. */ + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER, + "Unknown driver \"%s\"", + driver_name); + return; + } + + jack_controller_settings_save_auto(controller_ptr); + + jack_dbus_construct_method_return_empty(call); +} + +static +void +jack_controller_get_parameters_info( + struct jack_dbus_method_call *call, + const JSList *parameters_list) +{ + DBusMessageIter iter, array_iter, struct_iter; + unsigned char type; + const char *str; + + call->reply = dbus_message_new_method_return (call->message); + if (!call->reply) + { + goto fail; + } + + dbus_message_iter_init_append (call->reply, &iter); + + /* Open the array. */ + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "(ysss)", &array_iter)) + { + goto fail_unref; + } + + /* Append parameter descriptions to the array. */ + while (parameters_list != NULL) + { + /* Open the struct. */ + if (!dbus_message_iter_open_container (&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) + { + goto fail_close_unref; + } + + /* Append parameter type. */ + type = PARAM_TYPE_JACK_TO_DBUS(jackctl_parameter_get_type((jackctl_parameter_t *)parameters_list->data)); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, + (const void *) &type)) + { + goto fail_close2_unref; + } + + /* Append parameter name. */ + str = jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, + (const void *) &str)) + { + goto fail_close2_unref; + } + + /* Append parameter short description. */ + str = jackctl_parameter_get_short_description((jackctl_parameter_t *)parameters_list->data); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, + (const void *) &str)) + { + goto fail_close2_unref; + } + + /* Append parameter long description. */ + str = jackctl_parameter_get_long_description((jackctl_parameter_t *)parameters_list->data); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, + (const void *) &str)) + { + goto fail_close2_unref; + } + + /* Close the struct. */ + if (!dbus_message_iter_close_container (&array_iter, &struct_iter)) + { + goto fail_close_unref; + } + + parameters_list = jack_slist_next(parameters_list); + } + + /* Close the array. */ + if (!dbus_message_iter_close_container (&iter, &array_iter)) + { + goto fail_unref; + } + + return; + +fail_close2_unref: + dbus_message_iter_close_container (&iter, &struct_iter); + +fail_close_unref: + dbus_message_iter_close_container (&iter, &array_iter); + +fail_unref: + dbus_message_unref (call->reply); + call->reply = NULL; + +fail: + jack_error ("Ran out of memory trying to construct method return"); +} + +static +void +jack_controller_get_parameter_info( + struct jack_dbus_method_call *call, + jackctl_parameter_t *parameter) +{ + DBusMessageIter iter, struct_iter; + unsigned char type; + const char *str; + + 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(jackctl_parameter_get_type(parameter)); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_BYTE, + (const void *) &type)) + { + goto fail_close_unref; + } + + /* Append parameter name. */ + str = jackctl_parameter_get_name(parameter); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, + (const void *) &str)) + { + goto fail_close_unref; + } + + /* Append parameter short description. */ + str = jackctl_parameter_get_short_description(parameter); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, + (const void *) &str)) + { + goto fail_close_unref; + } + + /* Append parameter long description. */ + str = jackctl_parameter_get_long_description(parameter); + if (!dbus_message_iter_append_basic (&struct_iter, DBUS_TYPE_STRING, + (const void *) &str)) + { + goto fail_close_unref; + } + + /* Close the struct. */ + if (!dbus_message_iter_close_container (&iter, &struct_iter)) + { + 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; + +fail: + jack_error ("Ran out of memory trying to construct method return"); +} + +/* + * Execute GetDriverParametersInfo method call. + */ +static +void +jack_controller_dbus_get_driver_parameters_info( + struct jack_dbus_method_call *call) +{ + if (controller_ptr->driver == NULL) + { + jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, + "No driver selected"); + return; + } + + jack_controller_get_parameters_info( + call, + jackctl_driver_get_parameters(controller_ptr->driver)); +} + +/* + * Execute GetDriverParameterInfo method call. + */ +static +void +jack_controller_dbus_get_driver_parameter_info( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + jackctl_parameter_t *parameter; + + if (controller_ptr->driver == NULL) + { + jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, + "No driver selected"); + return; + } + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter_name, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + jack_controller_get_parameter_info(call, parameter); +} + + +/* + * Execute GetDriverParameterValue method call. + */ +static void +jack_controller_dbus_get_driver_parameter_value( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + 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; + + if (controller_ptr->driver == NULL) + { + jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, + "No driver selected"); + return; + } + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + 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_dbus_set_driver_parameter_value( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + message_arg_t arg; + int arg_type; + jackctl_parameter_t *parameter; + jackctl_param_type_t type; + union jackctl_parameter_value value; + + if (controller_ptr->driver == NULL) + { + jack_dbus_error (call, JACK_DBUS_ERROR_NEED_DRIVER, + "No driver selected"); + return; + } + + if (!jack_dbus_get_method_args_string_and_variant(call, ¶meter_name, &arg, &arg_type)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args_string_and_variant() has constructed + * an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + type = jackctl_parameter_get_type(parameter); + + if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Engine 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, + &value)) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Cannot convert engine parameter value"); + return; + } + + jackctl_parameter_set_value(parameter, &value); + + jack_controller_settings_save_auto(controller_ptr); + + jack_dbus_construct_method_return_empty(call); +} + +/* + * Execute GetEngineParametersInfo method call. + */ +static +void +jack_controller_dbus_get_engine_parameters_info( + struct jack_dbus_method_call *call) +{ + jack_controller_get_parameters_info( + call, + jackctl_server_get_parameters(controller_ptr->server)); +} + +/* + * Execute GetEngineParameterInfo method call. + */ +static +void +jack_controller_dbus_get_engine_parameter_info( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + jackctl_parameter_t *parameter; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, + "Unknown engine parameter \"%s\"", + parameter); + return; + } + + jack_controller_get_parameter_info(call, parameter); +} + +/* + * Execute GetDriverParameterValue method call. + */ +static +void +jack_controller_dbus_get_engine_parameter_value( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + jackctl_parameter_t *parameter; + jackctl_param_type_t type; + union jackctl_parameter_value jackctl_value; + union jackctl_parameter_value jackctl_default_value; + message_arg_t value; + message_arg_t default_value; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, + "Unknown engine parameter \"%s\"", + parameter); + return; + } + + 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_dbus_set_engine_parameter_value( + struct jack_dbus_method_call *call) +{ + const char *parameter_name; + message_arg_t arg; + int arg_type; + jackctl_parameter_t *parameter; + jackctl_param_type_t type; + union jackctl_parameter_value value; + + if (!jack_dbus_get_method_args_string_and_variant (call, ¶meter_name, &arg, &arg_type)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args_string_and_variant() has constructed + * an error for us. + */ + return; + } + + parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER, + "Unknown engine parameter \"%s\"", + parameter); + return; + } + + type = jackctl_parameter_get_type(parameter); + + if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Engine 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, + &value)) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Cannot convert engine 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_dbus_get_available_internals( + struct jack_dbus_method_call *call) +{ + jack_dbus_construct_method_return_array_of_strings( + call, + controller_ptr->internals_count, + controller_ptr->internal_names); +} + +/* + * Execute GetInternalParametersInfo method call. + */ +static +void +jack_controller_dbus_get_internal_parameters_info( + struct jack_dbus_method_call *call) +{ + const char *internal_name; + jackctl_internal_t * internal; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + return; + } + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_INTERNAL, + "Unknown internal \"%s\"", + internal_name); + return; + } + + jack_controller_get_parameters_info(call, jackctl_internal_get_parameters(internal)); +} + +/* + * Execute GetInternalParameterInfo method call. + */ +static +void +jack_controller_dbus_get_internal_parameter_info( + struct jack_dbus_method_call *call) +{ + const char *internal_name; + const char *parameter_name; + jackctl_parameter_t *parameter; + jackctl_internal_t * internal; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + return; + } + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_INTERNAL, + "Unknown internal \"%s\"", + internal_name); + return; + } + + parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter_name, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + jack_controller_get_parameter_info(call, parameter); +} + +/* + * Execute GetInternalParameterValue method call. + */ +static void +jack_controller_dbus_get_internal_parameter_value( + struct jack_dbus_method_call *call) +{ + const char *internal_name; + const char *parameter_name; + jackctl_parameter_t *parameter; + jackctl_internal_t * internal; + int type; + union jackctl_parameter_value jackctl_value; + union jackctl_parameter_value jackctl_default_value; + message_arg_t value; + message_arg_t default_value; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_STRING, ¶meter_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + return; + } + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_INTERNAL, + "Unknown internal \"%s\"", + internal_name); + return; + } + + parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + 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_dbus_set_internal_parameter_value( + struct jack_dbus_method_call *call) +{ + const char *internal_name; + const char *parameter_name; + jackctl_internal_t * internal; + message_arg_t arg; + int arg_type; + jackctl_parameter_t *parameter; + jackctl_param_type_t type; + union jackctl_parameter_value value; + + if (!jack_dbus_get_method_args_two_strings_and_variant(call, &internal_name, ¶meter_name, &arg, &arg_type)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args_two_strings_and_variant() has constructed + * an error for us. + */ + return; + } + + internal = jack_controller_find_internal(controller_ptr->server, internal_name); + if (internal == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_INTERNAL, + "Unknown internal \"%s\"", + internal_name); + return; + } + + parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), parameter_name); + if (parameter == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER, + "Unknown parameter \"%s\" for driver \"%s\"", + parameter, + jackctl_driver_get_name(controller_ptr->driver)); + return; + } + + type = jackctl_parameter_get_type(parameter); + + if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Engine 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, + &value)) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Cannot convert engine parameter value"); + return; + } + + jackctl_parameter_set_value(parameter, &value); + + jack_controller_settings_save_auto(controller_ptr); + + jack_dbus_construct_method_return_empty(call); +} + + +#undef controller_ptr + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAvailableDrivers) + JACK_DBUS_METHOD_ARGUMENT("drivers_list", "as", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSelectedDriver) + JACK_DBUS_METHOD_ARGUMENT("driver", "s", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SelectDriver) + JACK_DBUS_METHOD_ARGUMENT("driver", "s", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParametersInfo) + JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterInfo) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetDriverParameterValue) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) + JACK_DBUS_METHOD_ARGUMENT("default", "v", true) + JACK_DBUS_METHOD_ARGUMENT("value", "v", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetDriverParameterValue) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("value", "v", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParametersInfo) + JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterInfo) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetEngineParameterValue) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) + JACK_DBUS_METHOD_ARGUMENT("default", "v", true) + JACK_DBUS_METHOD_ARGUMENT("value", "v", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetEngineParameterValue) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("value", "v", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAvailableInternals) + JACK_DBUS_METHOD_ARGUMENT("internals_list", "as", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetInternalParametersInfo) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter_info_array", "a(ysss)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetInternalParameterInfo) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter_info", "(ysss)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetInternalParameterValue) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("is_set", "b", true) + JACK_DBUS_METHOD_ARGUMENT("default", "v", true) + JACK_DBUS_METHOD_ARGUMENT("value", "v", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetInternalParameterValue) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) + JACK_DBUS_METHOD_ARGUMENT("parameter", "s", false) + JACK_DBUS_METHOD_ARGUMENT("value", "v", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHODS_BEGIN + JACK_DBUS_METHOD_DESCRIBE(GetAvailableDrivers, jack_controller_dbus_get_available_drivers) + JACK_DBUS_METHOD_DESCRIBE(GetSelectedDriver, jack_controller_dbus_get_selected_driver) + JACK_DBUS_METHOD_DESCRIBE(SelectDriver, jack_controller_dbus_select_driver) + JACK_DBUS_METHOD_DESCRIBE(GetDriverParametersInfo, jack_controller_dbus_get_driver_parameters_info) + JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterInfo, jack_controller_dbus_get_driver_parameter_info) + JACK_DBUS_METHOD_DESCRIBE(GetDriverParameterValue, jack_controller_dbus_get_driver_parameter_value) + JACK_DBUS_METHOD_DESCRIBE(SetDriverParameterValue, jack_controller_dbus_set_driver_parameter_value) + JACK_DBUS_METHOD_DESCRIBE(GetEngineParametersInfo, jack_controller_dbus_get_engine_parameters_info) + JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterInfo, jack_controller_dbus_get_engine_parameter_info) + JACK_DBUS_METHOD_DESCRIBE(GetEngineParameterValue, jack_controller_dbus_get_engine_parameter_value) + JACK_DBUS_METHOD_DESCRIBE(SetEngineParameterValue, jack_controller_dbus_set_engine_parameter_value) + JACK_DBUS_METHOD_DESCRIBE(GetAvailableInternals, jack_controller_dbus_get_available_internals) + JACK_DBUS_METHOD_DESCRIBE(GetInternalParametersInfo, jack_controller_dbus_get_internal_parameters_info) + JACK_DBUS_METHOD_DESCRIBE(GetInternalParameterInfo, jack_controller_dbus_get_internal_parameter_info) + JACK_DBUS_METHOD_DESCRIBE(GetInternalParameterValue, jack_controller_dbus_get_internal_parameter_value) + JACK_DBUS_METHOD_DESCRIBE(SetInternalParameterValue, jack_controller_dbus_set_internal_parameter_value) +JACK_DBUS_METHODS_END + +JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_configure, "org.jackaudio.JackConfigure") + JACK_DBUS_IFACE_EXPOSE_METHODS +JACK_DBUS_IFACE_END diff --git a/dbus/controller_iface_control.c b/dbus/controller_iface_control.c new file mode 100644 index 00000000..317aa00e --- /dev/null +++ b/dbus/controller_iface_control.c @@ -0,0 +1,324 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + + 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 +#include +#include +#include +#include + +#include "jackdbus.h" +#include "controller_internal.h" + +#define JACK_DBUS_IFACE_NAME "org.jackaudio.JackControl" + +void +jack_controller_control_send_signal_server_started() +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "ServerStarted", + DBUS_TYPE_INVALID); +} + +void +jack_controller_control_send_signal_server_stopped() +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "ServerStopped", + DBUS_TYPE_INVALID); +} + +#define controller_ptr ((struct jack_controller *)call->context) + +/* + * Check if the supplied method name exists in org.jackaudio.JackControl, + * if it does execute it and return true. Otherwise return false. + */ +static +bool +jack_control_run_method( + struct jack_dbus_method_call * call, + const struct jack_dbus_interface_method_descriptor * methods) +{ + int ret; + int type; + message_arg_t arg; + + /* use empty reply if not overriden in the code that follows */ + type = DBUS_TYPE_INVALID; + + if (strcmp (call->method_name, "Exit") == 0) + { + g_exit_command = TRUE; + } + else if (strcmp (call->method_name, "IsStarted") == 0) + { + type = DBUS_TYPE_BOOLEAN; + arg.boolean = (dbus_bool_t) (controller_ptr->started ? TRUE : FALSE); + } + else if (strcmp (call->method_name, "StartServer") == 0) + { + if (!jack_controller_start_server(controller_ptr, call)) + { + jack_error ("Failed to start server"); + } + else + { + jack_controller_control_send_signal_server_started(); + } + } + else if (strcmp (call->method_name, "StopServer") == 0) + { + if (!jack_controller_stop_server(controller_ptr, call)) + { + jack_error ("Failed to stop server"); + } + else + { + jack_controller_control_send_signal_server_stopped(); + } + } + else if (strcmp (call->method_name, "GetLoad") == 0) + { + if (!controller_ptr->started) + { + goto not_started; + } + + type = DBUS_TYPE_DOUBLE; + arg.doubl = jack_cpu_load(controller_ptr->client); + } + else if (strcmp (call->method_name, "GetXruns") == 0) + { + type = DBUS_TYPE_UINT32; + arg.uint32 = controller_ptr->xruns; + } + else if (strcmp (call->method_name, "GetSampleRate") == 0) + { + if (!controller_ptr->started) + { + goto not_started; + } + + type = DBUS_TYPE_UINT32; + arg.uint32 = jack_get_sample_rate(controller_ptr->client); + } + else if (strcmp (call->method_name, "GetLatency") == 0) + { + if (!controller_ptr->started) + { + goto not_started; + } + + type = DBUS_TYPE_DOUBLE; + arg.doubl = ((float)jack_get_buffer_size(controller_ptr->client) / (float)jack_get_sample_rate(controller_ptr->client)) * 1000.0f; + } + else if (strcmp (call->method_name, "GetBufferSize") == 0) + { + if (!controller_ptr->started) + { + goto not_started; + } + + type = DBUS_TYPE_UINT32; + arg.uint32 = jack_get_buffer_size(controller_ptr->client); + } + else if (strcmp (call->method_name, "SetBufferSize") == 0) + { + dbus_uint32_t buffer_size; + + if (!controller_ptr->started) + { + goto not_started; + } + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT32, &buffer_size, DBUS_TYPE_INVALID)) + { + /* jack_dbus_get_method_args() has set reply for us */ + goto exit; + } + + ret = jack_set_buffer_size(controller_ptr->client, buffer_size); + if (ret != 0) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_GENERIC, + "jack_set_buffer_size(%u) failed with error %d", (unsigned int)buffer_size, ret); + + goto exit; + } + } + else if (strcmp (call->method_name, "IsRealtime") == 0) + { + type = DBUS_TYPE_BOOLEAN; + arg.boolean = jack_is_realtime(controller_ptr->client) ? TRUE : FALSE; + } + else if (strcmp (call->method_name, "ResetXruns") == 0) + { + controller_ptr->xruns = 0; + } + else if (strcmp (call->method_name, "LoadInternal") == 0) + { + const char *internal_name; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + goto exit; + } + + if (!jack_controller_load_internal(controller_ptr, internal_name)) { + jack_dbus_error( + call, + JACK_DBUS_ERROR_GENERIC, + "jack_controller_load_internal failed for internal (%s)", internal_name); + } + } + else if (strcmp (call->method_name, "UnloadInternal") == 0) + { + const char *internal_name; + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_STRING, &internal_name, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * get_method_args() has constructed an error for us. + */ + goto exit; + } + + if (!jack_controller_unload_internal(controller_ptr, internal_name)) { + jack_dbus_error( + call, + JACK_DBUS_ERROR_GENERIC, + "jack_controller_unload_internal failed for internal (%s)", internal_name); + } + } + else + { + return false; + } + + jack_dbus_construct_method_return_single(call, type, arg); + + return true; + +not_started: + jack_dbus_error (call, JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute method '%s' with stopped JACK server", call->method_name); + +exit: + return true; +} + +#undef controller_ptr + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsStarted) + JACK_DBUS_METHOD_ARGUMENT("started", "b", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StartServer) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(StopServer) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLoad) + JACK_DBUS_METHOD_ARGUMENT("load", "d", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetXruns) + JACK_DBUS_METHOD_ARGUMENT("xruns_count", "u", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetSampleRate) + JACK_DBUS_METHOD_ARGUMENT("sample_rate", "u", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetLatency) + JACK_DBUS_METHOD_ARGUMENT("latency_ms", "d", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetBufferSize) + JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(SetBufferSize) + JACK_DBUS_METHOD_ARGUMENT("buffer_size_frames", "u", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(IsRealtime) + JACK_DBUS_METHOD_ARGUMENT("realtime", "b", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ResetXruns) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(LoadInternal) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(UnlooadInternal) + JACK_DBUS_METHOD_ARGUMENT("internal", "s", false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHODS_BEGIN + JACK_DBUS_METHOD_DESCRIBE(IsStarted, NULL) + JACK_DBUS_METHOD_DESCRIBE(StartServer, NULL) + JACK_DBUS_METHOD_DESCRIBE(StopServer, NULL) + JACK_DBUS_METHOD_DESCRIBE(GetLoad, NULL) + JACK_DBUS_METHOD_DESCRIBE(GetXruns, NULL) + JACK_DBUS_METHOD_DESCRIBE(GetSampleRate, NULL) + JACK_DBUS_METHOD_DESCRIBE(GetLatency, NULL) + JACK_DBUS_METHOD_DESCRIBE(GetBufferSize, NULL) + JACK_DBUS_METHOD_DESCRIBE(SetBufferSize, NULL) + JACK_DBUS_METHOD_DESCRIBE(IsRealtime, NULL) + JACK_DBUS_METHOD_DESCRIBE(ResetXruns, NULL) + JACK_DBUS_METHOD_DESCRIBE(LoadInternal, NULL) + JACK_DBUS_METHOD_DESCRIBE(UnlooadInternal, NULL) +JACK_DBUS_METHODS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ServerStarted) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ServerStopped) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNALS_BEGIN + JACK_DBUS_SIGNAL_DESCRIBE(ServerStarted) + JACK_DBUS_SIGNAL_DESCRIBE(ServerStopped) +JACK_DBUS_SIGNALS_END + +JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_control, JACK_DBUS_IFACE_NAME) + JACK_DBUS_IFACE_HANDLER(jack_control_run_method) + JACK_DBUS_IFACE_EXPOSE_METHODS +JACK_DBUS_IFACE_END diff --git a/dbus/controller_iface_introspectable.c b/dbus/controller_iface_introspectable.c new file mode 100644 index 00000000..8b1a644c --- /dev/null +++ b/dbus/controller_iface_introspectable.c @@ -0,0 +1,156 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007-2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + + 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 +#include +#include +#include +#include + +#include "jackdbus.h" + +static char g_xml_data[102400]; + +static +void +jack_controller_dbus_introspect( + struct jack_dbus_method_call * call) +{ + jack_dbus_construct_method_return_single( + call, + DBUS_TYPE_STRING, + (message_arg_t)(const char *)g_xml_data); +} + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(Introspect) + JACK_DBUS_METHOD_ARGUMENT("xml_data", "s", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHODS_BEGIN + JACK_DBUS_METHOD_DESCRIBE(Introspect, jack_controller_dbus_introspect) +JACK_DBUS_METHODS_END + +JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_introspectable, "org.freedesktop.DBus.Introspectable") + JACK_DBUS_IFACE_EXPOSE_METHODS +JACK_DBUS_IFACE_END + +static char * g_buffer_ptr; + +static +void +write_line_format(const char * format, ...) +{ + va_list ap; + + va_start(ap, format); + g_buffer_ptr += vsprintf(g_buffer_ptr, format, ap); + va_end(ap); +} + +static +void +write_line(const char * line) +{ + write_line_format("%s\n", line); +} + +void jack_controller_introspect_init() __attribute__((constructor)); + +void +jack_controller_introspect_init() +{ + struct jack_dbus_interface_descriptor ** interface_ptr_ptr; + const struct jack_dbus_interface_method_descriptor * method_ptr; + const struct jack_dbus_interface_method_argument_descriptor * method_argument_ptr; + const struct jack_dbus_interface_signal_descriptor * signal_ptr; + const struct jack_dbus_interface_signal_argument_descriptor * signal_argument_ptr; + + g_buffer_ptr = g_xml_data; + + write_line(""); + + write_line(""); + + interface_ptr_ptr = g_jackcontroller_interfaces; + + while (*interface_ptr_ptr != NULL) + { + write_line_format(" \n", (*interface_ptr_ptr)->name); + + if ((*interface_ptr_ptr)->methods != NULL) + { + method_ptr = (*interface_ptr_ptr)->methods; + while (method_ptr->name != NULL) + { + write_line_format(" \n", method_ptr->name); + + method_argument_ptr = method_ptr->arguments; + + while (method_argument_ptr->name != NULL) + { + write_line_format( + " \n", + method_argument_ptr->name, + method_argument_ptr->type, + method_argument_ptr->direction_out ? "out" : "in"); + method_argument_ptr++; + } + + write_line(" "); + method_ptr++; + } + } + + if ((*interface_ptr_ptr)->signals != NULL) + { + signal_ptr = (*interface_ptr_ptr)->signals; + while (signal_ptr->name != NULL) + { + write_line_format(" \n", signal_ptr->name); + + signal_argument_ptr = signal_ptr->arguments; + + while (signal_argument_ptr->name != NULL) + { + write_line_format( + " \n", + signal_argument_ptr->name, + signal_argument_ptr->type); + signal_argument_ptr++; + } + + write_line(" "); + signal_ptr++; + } + } + + write_line(" "); + interface_ptr_ptr++; + } + + write_line(""); + + *g_buffer_ptr = 0; +} diff --git a/dbus/controller_iface_patchbay.c b/dbus/controller_iface_patchbay.c new file mode 100644 index 00000000..84391404 --- /dev/null +++ b/dbus/controller_iface_patchbay.c @@ -0,0 +1,1851 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2008 Nedko Arnaudov + Copyright (C) 2008 Juuso Alasuutari + + 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 + +#define _GNU_SOURCE /* PTHREAD_MUTEX_RECURSIVE */ + +#include +#include +#include +#include +#include +#include +#include + +#include "jackdbus.h" +#include "controller_internal.h" +#include "list.h" + +#define JACK_DBUS_IFACE_NAME "org.jackaudio.JackPatchbay" + +/* FIXME: these need to be retrieved from common headers */ +#define JACK_CLIENT_NAME_SIZE 64 +#define JACK_PORT_NAME_SIZE 256 + +struct jack_graph +{ + uint64_t version; + struct list_head clients; + struct list_head ports; + struct list_head connections; +}; + +struct jack_graph_client +{ + uint64_t id; + char * name; + int pid; + struct list_head siblings; + struct list_head ports; +}; + +struct jack_graph_port +{ + uint64_t id; + char * name; + uint32_t flags; + uint32_t type; + struct list_head siblings_graph; + struct list_head siblings_client; + struct jack_graph_client * client; +}; + +struct jack_graph_connection +{ + uint64_t id; + struct jack_graph_port * port1; + struct jack_graph_port * port2; + struct list_head siblings; +}; + +struct jack_controller_patchbay +{ + pthread_mutex_t lock; + struct jack_graph graph; + uint64_t next_client_id; + uint64_t next_port_id; + uint64_t next_connection_id; +}; + +void +jack_controller_patchbay_send_signal_graph_changed( + dbus_uint64_t new_graph_version) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "GraphChanged", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_INVALID); +} + +void +jack_controller_patchbay_send_signal_client_appeared( + dbus_uint64_t new_graph_version, + dbus_uint64_t client_id, + const char * client_name) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "ClientAppeared", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_INVALID); +} + +void +jack_controller_patchbay_send_signal_client_disappeared( + dbus_uint64_t new_graph_version, + dbus_uint64_t client_id, + const char * client_name) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "ClientDisappeared", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_INVALID); +} + +void +jack_controller_patchbay_send_signal_port_appeared( + dbus_uint64_t new_graph_version, + dbus_uint64_t client_id, + const char * client_name, + dbus_uint64_t port_id, + const char * port_name, + dbus_uint32_t port_flags, + dbus_uint32_t port_type) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "PortAppeared", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_UINT64, + &port_id, + DBUS_TYPE_STRING, + &port_name, + DBUS_TYPE_UINT32, + &port_flags, + DBUS_TYPE_UINT32, + &port_type, + DBUS_TYPE_INVALID); +} + +void +jack_controller_patchbay_send_signal_port_disappeared( + dbus_uint64_t new_graph_version, + dbus_uint64_t client_id, + const char * client_name, + dbus_uint64_t port_id, + const char * port_name) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "PortDisappeared", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_STRING, + &client_name, + DBUS_TYPE_UINT64, + &port_id, + DBUS_TYPE_STRING, + &port_name, + DBUS_TYPE_INVALID); +} + +void +jack_controller_patchbay_send_signal_ports_connected( + dbus_uint64_t new_graph_version, + dbus_uint64_t client1_id, + const char * client1_name, + dbus_uint64_t port1_id, + const char * port1_name, + dbus_uint64_t client2_id, + const char * client2_name, + dbus_uint64_t port2_id, + const char * port2_name, + dbus_uint64_t connection_id) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "PortsConnected", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client1_id, + DBUS_TYPE_STRING, + &client1_name, + DBUS_TYPE_UINT64, + &port1_id, + DBUS_TYPE_STRING, + &port1_name, + DBUS_TYPE_UINT64, + &client2_id, + DBUS_TYPE_STRING, + &client2_name, + DBUS_TYPE_UINT64, + &port2_id, + DBUS_TYPE_STRING, + &port2_name, + DBUS_TYPE_UINT64, + &connection_id, + DBUS_TYPE_INVALID); +} + +void +jack_controller_patchbay_send_signal_ports_disconnected( + dbus_uint64_t new_graph_version, + dbus_uint64_t client1_id, + const char * client1_name, + dbus_uint64_t port1_id, + const char * port1_name, + dbus_uint64_t client2_id, + const char * client2_name, + dbus_uint64_t port2_id, + const char * port2_name, + dbus_uint64_t connection_id) +{ + + jack_dbus_send_signal( + JACK_CONTROLLER_OBJECT_PATH, + JACK_DBUS_IFACE_NAME, + "PortsDisconnected", + DBUS_TYPE_UINT64, + &new_graph_version, + DBUS_TYPE_UINT64, + &client1_id, + DBUS_TYPE_STRING, + &client1_name, + DBUS_TYPE_UINT64, + &port1_id, + DBUS_TYPE_STRING, + &port1_name, + DBUS_TYPE_UINT64, + &client2_id, + DBUS_TYPE_STRING, + &client2_name, + DBUS_TYPE_UINT64, + &port2_id, + DBUS_TYPE_STRING, + &port2_name, + DBUS_TYPE_UINT64, + &connection_id, + DBUS_TYPE_INVALID); +} + +static +struct jack_graph_client * +jack_controller_patchbay_find_client( + struct jack_controller_patchbay *patchbay_ptr, + const char *client_name, /* not '\0' terminated */ + size_t client_name_len) /* without terminating '\0' */ +{ + struct list_head *node_ptr; + struct jack_graph_client *client_ptr; + + list_for_each(node_ptr, &patchbay_ptr->graph.clients) + { + client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); + if (strncmp(client_ptr->name, client_name, client_name_len) == 0) + { + return client_ptr; + } + } + + return NULL; +} + +static +struct jack_graph_client * +jack_controller_patchbay_find_client_by_id( + struct jack_controller_patchbay *patchbay_ptr, + uint64_t id) +{ + struct list_head *node_ptr; + struct jack_graph_client *client_ptr; + + list_for_each(node_ptr, &patchbay_ptr->graph.clients) + { + client_ptr = list_entry(node_ptr, struct jack_graph_client, siblings); + if (client_ptr->id == id) + { + return client_ptr; + } + } + + return NULL; +} + +static +struct jack_graph_client * +jack_controller_patchbay_create_client( + struct jack_controller_patchbay *patchbay_ptr, + const char *client_name, /* not '\0' terminated */ + size_t client_name_len) /* without terminating '\0' */ +{ + struct jack_graph_client * client_ptr; + + client_ptr = malloc(sizeof(struct jack_graph_client)); + if (client_ptr == NULL) + { + jack_error("Memory allocation of jack_graph_client structure failed."); + goto fail; + } + + client_ptr->name = malloc(client_name_len + 1); + if (client_ptr->name == NULL) + { + jack_error("malloc() failed to allocate memory for client name."); + goto fail_free_client; + } + + memcpy(client_ptr->name, client_name, client_name_len); + client_ptr->name[client_name_len] = 0; + + client_ptr->pid = jack_get_client_pid(client_ptr->name); + jack_info("New client '%s' with PID %d", client_ptr->name, client_ptr->pid); + + client_ptr->id = patchbay_ptr->next_client_id++; + INIT_LIST_HEAD(&client_ptr->ports); + + + pthread_mutex_lock(&patchbay_ptr->lock); + list_add_tail(&client_ptr->siblings, &patchbay_ptr->graph.clients); + patchbay_ptr->graph.version++; + jack_controller_patchbay_send_signal_client_appeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); + jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); + + return client_ptr; + +fail_free_client: + free(client_ptr); + +fail: + return NULL; +} + +static +void +jack_controller_patchbay_destroy_client( + struct jack_controller_patchbay *patchbay_ptr, + struct jack_graph_client *client_ptr) +{ + jack_info("Client '%s' with PID %d is out", client_ptr->name, client_ptr->pid); + + pthread_mutex_lock(&patchbay_ptr->lock); + list_del(&client_ptr->siblings); + patchbay_ptr->graph.version++; + jack_controller_patchbay_send_signal_client_disappeared(patchbay_ptr->graph.version, client_ptr->id, client_ptr->name); + jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); + + free(client_ptr->name); + free(client_ptr); +} + +static +void +jack_controller_patchbay_destroy_client_by_name( + struct jack_controller_patchbay *patchbay_ptr, + const char *client_name) /* '\0' terminated */ +{ + struct jack_graph_client *client_ptr; + + client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); + if (client_ptr == NULL) + { + jack_error("Cannot destroy unknown client '%s'", client_name); + return; + } + + jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); +} + +static +void +jack_controller_patchbay_new_port( + struct jack_controller_patchbay *patchbay_ptr, + const char *port_full_name, + uint32_t port_flags, + uint32_t port_type) +{ + struct jack_graph_client *client_ptr; + struct jack_graph_port *port_ptr; + const char *port_short_name; + size_t client_name_len; + + //jack_info("name: %s", port_full_name); + + port_short_name = strchr(port_full_name, ':'); + if (port_short_name == NULL) + { + jack_error("port name '%s' does not contain ':' separator char", port_full_name); + return; + } + + port_short_name++; /* skip ':' separator char */ + + client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ + + client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); + if (client_ptr == NULL) + { + client_ptr = jack_controller_patchbay_create_client(patchbay_ptr, port_full_name, client_name_len); + if (client_ptr == NULL) + { + jack_error("Creation of new jack_graph client failed."); + return; + } + } + + port_ptr = malloc(sizeof(struct jack_graph_port)); + if (port_ptr == NULL) + { + jack_error("Memory allocation of jack_graph_port structure failed."); + return; + } + + port_ptr->name = strdup(port_short_name); + if (port_ptr->name == NULL) + { + jack_error("strdup() call for port name '%s' failed.", port_short_name); + free(port_ptr); + return; + } + + port_ptr->id = patchbay_ptr->next_port_id++; + port_ptr->flags = port_flags; + port_ptr->type = port_type; + port_ptr->client = client_ptr; + + pthread_mutex_lock(&patchbay_ptr->lock); + list_add_tail(&port_ptr->siblings_client, &client_ptr->ports); + list_add_tail(&port_ptr->siblings_graph, &patchbay_ptr->graph.ports); + patchbay_ptr->graph.version++; + jack_controller_patchbay_send_signal_port_appeared( + patchbay_ptr->graph.version, + client_ptr->id, + client_ptr->name, + port_ptr->id, + port_ptr->name, + port_ptr->flags, + port_ptr->type); + jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +static +void +jack_controller_patchbay_remove_port( + struct jack_controller_patchbay *patchbay_ptr, + struct jack_graph_port *port_ptr) +{ + pthread_mutex_lock(&patchbay_ptr->lock); + list_del(&port_ptr->siblings_client); + list_del(&port_ptr->siblings_graph); + patchbay_ptr->graph.version++; + jack_controller_patchbay_send_signal_port_disappeared(patchbay_ptr->graph.version, port_ptr->client->id, port_ptr->client->name, port_ptr->id, port_ptr->name); + jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); + + free(port_ptr->name); + free(port_ptr); +} + +static +struct jack_graph_port * +jack_controller_patchbay_find_port_by_id( + struct jack_controller_patchbay *patchbay_ptr, + uint64_t port_id) +{ + struct list_head *node_ptr; + struct jack_graph_port *port_ptr; + + list_for_each(node_ptr, &patchbay_ptr->graph.ports) + { + port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_graph); + if (port_ptr->id == port_id) + { + return port_ptr; + } + } + + return NULL; +} + +static +struct jack_graph_port * +jack_controller_patchbay_find_client_port_by_name( + struct jack_controller_patchbay *patchbay_ptr, + struct jack_graph_client *client_ptr, + const char *port_name) +{ + struct list_head *node_ptr; + struct jack_graph_port *port_ptr; + + list_for_each(node_ptr, &client_ptr->ports) + { + port_ptr = list_entry(node_ptr, struct jack_graph_port, siblings_client); + if (strcmp(port_ptr->name, port_name) == 0) + { + return port_ptr; + } + } + + return NULL; +} + +static +struct jack_graph_port * +jack_controller_patchbay_find_port_by_full_name( + struct jack_controller_patchbay *patchbay_ptr, + const char *port_full_name) +{ + const char *port_short_name; + size_t client_name_len; + struct jack_graph_client *client_ptr; + + //jack_info("name: %s", port_full_name); + + port_short_name = strchr(port_full_name, ':'); + if (port_short_name == NULL) + { + jack_error("port name '%s' does not contain ':' separator char", port_full_name); + return NULL; + } + + port_short_name++; /* skip ':' separator char */ + + client_name_len = port_short_name - port_full_name - 1; /* without terminating '\0' */ + + client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, port_full_name, client_name_len); + if (client_ptr == NULL) + { + jack_error("cannot find client of port '%s'", port_full_name); + return NULL; + } + + return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_short_name); +} + +static +struct jack_graph_port * +jack_controller_patchbay_find_port_by_names( + struct jack_controller_patchbay *patchbay_ptr, + const char *client_name, + const char *port_name) +{ + struct jack_graph_client *client_ptr; + + client_ptr = jack_controller_patchbay_find_client(patchbay_ptr, client_name, strlen(client_name)); + if (client_ptr == NULL) + { + jack_error("cannot find client '%s'", client_name); + return NULL; + } + + return jack_controller_patchbay_find_client_port_by_name(patchbay_ptr, client_ptr, port_name); +} + +static +struct jack_graph_connection * +jack_controller_patchbay_create_connection( + struct jack_controller_patchbay *patchbay_ptr, + struct jack_graph_port *port1_ptr, + struct jack_graph_port *port2_ptr) +{ + struct jack_graph_connection * connection_ptr; + + connection_ptr = malloc(sizeof(struct jack_graph_connection)); + if (connection_ptr == NULL) + { + jack_error("Memory allocation of jack_graph_connection structure failed."); + return NULL; + } + + connection_ptr->id = patchbay_ptr->next_connection_id++; + connection_ptr->port1 = port1_ptr; + connection_ptr->port2 = port2_ptr; + + pthread_mutex_lock(&patchbay_ptr->lock); + list_add_tail(&connection_ptr->siblings, &patchbay_ptr->graph.connections); + patchbay_ptr->graph.version++; + jack_controller_patchbay_send_signal_ports_connected( + patchbay_ptr->graph.version, + port1_ptr->client->id, + port1_ptr->client->name, + port1_ptr->id, + port1_ptr->name, + port2_ptr->client->id, + port2_ptr->client->name, + port2_ptr->id, + port2_ptr->name, + connection_ptr->id); + jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); + + return connection_ptr; +} + +static +void +jack_controller_patchbay_destroy_connection( + struct jack_controller_patchbay *patchbay_ptr, + struct jack_graph_connection *connection_ptr) +{ + pthread_mutex_lock(&patchbay_ptr->lock); + list_del(&connection_ptr->siblings); + patchbay_ptr->graph.version++; + jack_controller_patchbay_send_signal_ports_disconnected( + patchbay_ptr->graph.version, + connection_ptr->port1->client->id, + connection_ptr->port1->client->name, + connection_ptr->port1->id, + connection_ptr->port1->name, + connection_ptr->port2->client->id, + connection_ptr->port2->client->name, + connection_ptr->port2->id, + connection_ptr->port2->name, + connection_ptr->id); + jack_controller_patchbay_send_signal_graph_changed(patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); + + free(connection_ptr); +} + +static +struct jack_graph_connection * +jack_controller_patchbay_find_connection( + struct jack_controller_patchbay *patchbay_ptr, + struct jack_graph_port *port1_ptr, + struct jack_graph_port *port2_ptr) +{ + struct list_head *node_ptr; + struct jack_graph_connection *connection_ptr; + + list_for_each(node_ptr, &patchbay_ptr->graph.connections) + { + connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); + if ((connection_ptr->port1 == port1_ptr && + connection_ptr->port2 == port2_ptr) || + (connection_ptr->port1 == port2_ptr && + connection_ptr->port2 == port1_ptr)) + { + return connection_ptr; + } + } + + return NULL; +} + +static +struct jack_graph_connection * +jack_controller_patchbay_find_connection_by_id( + struct jack_controller_patchbay *patchbay_ptr, + uint64_t connection_id) +{ + struct list_head *node_ptr; + struct jack_graph_connection *connection_ptr; + + list_for_each(node_ptr, &patchbay_ptr->graph.connections) + { + connection_ptr = list_entry(node_ptr, struct jack_graph_connection, siblings); + if (connection_ptr->id == connection_id) + { + return connection_ptr; + } + } + + return NULL; +} + +static +bool +jack_controller_patchbay_connect( + struct jack_dbus_method_call *dbus_call_ptr, + struct jack_controller *controller_ptr, + struct jack_graph_port *port1_ptr, + struct jack_graph_port *port2_ptr) +{ + int ret; + char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + + sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); + sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); + + ret = jack_connect(controller_ptr->client, port1_name, port2_name); + if (ret != 0) + { + jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); + return false; + } + + return true; +} + +static +bool +jack_controller_patchbay_disconnect( + struct jack_dbus_method_call *dbus_call_ptr, + struct jack_controller *controller_ptr, + struct jack_graph_port *port1_ptr, + struct jack_graph_port *port2_ptr) +{ + int ret; + char port1_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + char port2_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + + sprintf(port1_name, "%s:%s", port1_ptr->client->name, port1_ptr->name); + sprintf(port2_name, "%s:%s", port2_ptr->client->name, port2_ptr->name); + + ret = jack_disconnect(controller_ptr->client, port1_name, port2_name); + if (ret != 0) + { + jack_dbus_error(dbus_call_ptr, JACK_DBUS_ERROR_GENERIC, "jack_connect() failed with %d", ret); + return false; + } + + return true; +} + +#define controller_ptr ((struct jack_controller *)call->context) +#define patchbay_ptr ((struct jack_controller_patchbay *)controller_ptr->patchbay_context) + +static +void +jack_controller_dbus_get_all_ports( + struct jack_dbus_method_call * call) +{ + struct list_head * client_node_ptr; + struct list_head * port_node_ptr; + struct jack_graph_client * client_ptr; + struct jack_graph_port * port_ptr; + DBusMessageIter iter, sub_iter; + char fullname[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + char *fullname_var = fullname; + + if (!controller_ptr->started) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute this method with stopped JACK server"); + return; + } + + call->reply = dbus_message_new_method_return (call->message); + if (!call->reply) + { + goto fail; + } + + dbus_message_iter_init_append (call->reply, &iter); + + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) + { + goto fail_unref; + } + + pthread_mutex_lock(&patchbay_ptr->lock); + + list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) + { + client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); + + list_for_each(port_node_ptr, &client_ptr->ports) + { + port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); + + jack_info("%s:%s", client_ptr->name, port_ptr->name); + sprintf(fullname, "%s:%s", client_ptr->name, port_ptr->name); + if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, &fullname_var)) + { + pthread_mutex_unlock(&patchbay_ptr->lock); + dbus_message_iter_close_container (&iter, &sub_iter); + goto fail_unref; + } + } + } + + pthread_mutex_unlock(&patchbay_ptr->lock); + + if (!dbus_message_iter_close_container (&iter, &sub_iter)) + { + goto fail_unref; + } + + return; + +fail_unref: + dbus_message_unref (call->reply); + call->reply = NULL; + +fail: + jack_error ("Ran out of memory trying to construct method return"); +} + +static +void +jack_controller_dbus_get_graph( + struct jack_dbus_method_call * call) +{ + struct list_head * client_node_ptr; + struct list_head * port_node_ptr; + struct list_head * connection_node_ptr; + struct jack_graph_client * client_ptr; + struct jack_graph_port * port_ptr; + struct jack_graph_connection * connection_ptr; + DBusMessageIter iter; + DBusMessageIter clients_array_iter; + DBusMessageIter client_struct_iter; + DBusMessageIter ports_array_iter; + DBusMessageIter port_struct_iter; + dbus_uint64_t version; + DBusMessageIter connections_array_iter; + DBusMessageIter connection_struct_iter; + + if (!controller_ptr->started) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute this method with stopped JACK server"); + return; + } + + if (!jack_dbus_get_method_args(call, DBUS_TYPE_UINT64, &version, DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + goto exit; + } + + //jack_info("Getting graph, know version is %" PRIu32, version); + + call->reply = dbus_message_new_method_return(call->message); + if (!call->reply) + { + jack_error("Ran out of memory trying to construct method return"); + goto exit; + } + + dbus_message_iter_init_append (call->reply, &iter); + + pthread_mutex_lock(&patchbay_ptr->lock); + + if (version > patchbay_ptr->graph.version) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "known graph version %" PRIu64 " is newer than actual version %" PRIu64, + version, + patchbay_ptr->graph.version); + pthread_mutex_unlock(&patchbay_ptr->lock); + goto exit; + } + + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT64, &patchbay_ptr->graph.version)) + { + goto nomem_unlock; + } + + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tsa(tsuu))", &clients_array_iter)) + { + goto nomem_unlock; + } + + if (version < patchbay_ptr->graph.version) + { + list_for_each(client_node_ptr, &patchbay_ptr->graph.clients) + { + client_ptr = list_entry(client_node_ptr, struct jack_graph_client, siblings); + + if (!dbus_message_iter_open_container (&clients_array_iter, DBUS_TYPE_STRUCT, NULL, &client_struct_iter)) + { + goto nomem_close_clients_array; + } + + if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_UINT64, &client_ptr->id)) + { + goto nomem_close_client_struct; + } + + if (!dbus_message_iter_append_basic(&client_struct_iter, DBUS_TYPE_STRING, &client_ptr->name)) + { + goto nomem_close_client_struct; + } + + if (!dbus_message_iter_open_container(&client_struct_iter, DBUS_TYPE_ARRAY, "(tsuu)", &ports_array_iter)) + { + goto nomem_close_client_struct; + } + + list_for_each(port_node_ptr, &client_ptr->ports) + { + port_ptr = list_entry(port_node_ptr, struct jack_graph_port, siblings_client); + + if (!dbus_message_iter_open_container(&ports_array_iter, DBUS_TYPE_STRUCT, NULL, &port_struct_iter)) + { + goto nomem_close_ports_array; + } + + if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT64, &port_ptr->id)) + { + goto nomem_close_port_struct; + } + + if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_STRING, &port_ptr->name)) + { + goto nomem_close_port_struct; + } + + if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->flags)) + { + goto nomem_close_port_struct; + } + + if (!dbus_message_iter_append_basic(&port_struct_iter, DBUS_TYPE_UINT32, &port_ptr->type)) + { + goto nomem_close_port_struct; + } + + if (!dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter)) + { + goto nomem_close_ports_array; + } + } + + if (!dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter)) + { + goto nomem_close_client_struct; + } + + if (!dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter)) + { + goto nomem_close_clients_array; + } + } + } + + if (!dbus_message_iter_close_container(&iter, &clients_array_iter)) + { + goto nomem_unlock; + } + + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(tstststst)", &connections_array_iter)) + { + goto nomem_unlock; + } + + if (version < patchbay_ptr->graph.version) + { + list_for_each(connection_node_ptr, &patchbay_ptr->graph.connections) + { + connection_ptr = list_entry(connection_node_ptr, struct jack_graph_connection, siblings); + + if (!dbus_message_iter_open_container(&connections_array_iter, DBUS_TYPE_STRUCT, NULL, &connection_struct_iter)) + { + goto nomem_close_connections_array; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->client->id)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->client->name)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port1->id)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port1->name)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->client->id)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->client->name)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->port2->id)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_STRING, &connection_ptr->port2->name)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_append_basic(&connection_struct_iter, DBUS_TYPE_UINT64, &connection_ptr->id)) + { + goto nomem_close_connection_struct; + } + + if (!dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter)) + { + goto nomem_close_connections_array; + } + } + } + + if (!dbus_message_iter_close_container(&iter, &connections_array_iter)) + { + goto nomem_unlock; + } + + pthread_mutex_unlock(&patchbay_ptr->lock); + + return; + +nomem_close_connection_struct: + dbus_message_iter_close_container(&connections_array_iter, &connection_struct_iter); + +nomem_close_connections_array: + dbus_message_iter_close_container(&iter, &connections_array_iter); + goto nomem_unlock; + +nomem_close_port_struct: + dbus_message_iter_close_container(&ports_array_iter, &port_struct_iter); + +nomem_close_ports_array: + dbus_message_iter_close_container(&client_struct_iter, &ports_array_iter); + +nomem_close_client_struct: + dbus_message_iter_close_container(&clients_array_iter, &client_struct_iter); + +nomem_close_clients_array: + dbus_message_iter_close_container(&iter, &clients_array_iter); + +nomem_unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); + +//nomem: + dbus_message_unref(call->reply); + call->reply = NULL; + jack_error("Ran out of memory trying to construct method return"); + +exit: + return; +} + +static +void +jack_controller_dbus_connect_ports_by_name( + struct jack_dbus_method_call * call) +{ + const char * client1_name; + const char * port1_name; + const char * client2_name; + const char * port2_name; + struct jack_graph_port *port1_ptr; + struct jack_graph_port *port2_ptr; + +/* jack_info("jack_controller_dbus_connect_ports_by_name() called."); */ + + if (!controller_ptr->started) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute this method with stopped JACK server"); + return; + } + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &client1_name, + DBUS_TYPE_STRING, + &port1_name, + DBUS_TYPE_STRING, + &client2_name, + DBUS_TYPE_STRING, + &port2_name, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + +/* jack_info("connecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ + + pthread_mutex_lock(&patchbay_ptr->lock); + + port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); + if (port1_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); + goto unlock; + } + + port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); + if (port2_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); + goto unlock; + } + + if (!jack_controller_patchbay_connect( + call, + controller_ptr, + port1_ptr, + port2_ptr)) + { + /* jack_controller_patchbay_connect() constructed error reply */ + goto unlock; + } + + jack_dbus_construct_method_return_empty(call); + +unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +static +void +jack_controller_dbus_connect_ports_by_id( + struct jack_dbus_method_call * call) +{ + dbus_uint64_t port1_id; + dbus_uint64_t port2_id; + struct jack_graph_port *port1_ptr; + struct jack_graph_port *port2_ptr; + +/* jack_info("jack_controller_dbus_connect_ports_by_id() called."); */ + + if (!controller_ptr->started) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute this method with stopped JACK server"); + return; + } + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_UINT64, + &port1_id, + DBUS_TYPE_UINT64, + &port2_id, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + pthread_mutex_lock(&patchbay_ptr->lock); + + port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); + if (port1_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); + goto unlock; + } + + port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); + if (port2_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); + goto unlock; + } + + if (!jack_controller_patchbay_connect( + call, + controller_ptr, + port1_ptr, + port2_ptr)) + { + /* jack_controller_patchbay_connect() constructed error reply */ + goto unlock; + } + + jack_dbus_construct_method_return_empty(call); + +unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +static +void +jack_controller_dbus_disconnect_ports_by_name( + struct jack_dbus_method_call * call) +{ + const char * client1_name; + const char * port1_name; + const char * client2_name; + const char * port2_name; + struct jack_graph_port *port1_ptr; + struct jack_graph_port *port2_ptr; + +/* jack_info("jack_controller_dbus_disconnect_ports_by_name() called."); */ + + if (!controller_ptr->started) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute this method with stopped JACK server"); + return; + } + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_STRING, + &client1_name, + DBUS_TYPE_STRING, + &port1_name, + DBUS_TYPE_STRING, + &client2_name, + DBUS_TYPE_STRING, + &port2_name, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + +/* jack_info("disconnecting %s:%s and %s:%s", client1_name, port1_name, client2_name, port2_name); */ + + pthread_mutex_lock(&patchbay_ptr->lock); + + port1_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client1_name, port1_name); + if (port1_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client1_name, port1_name); + goto unlock; + } + + port2_ptr = jack_controller_patchbay_find_port_by_names(patchbay_ptr, client2_name, port2_name); + if (port2_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port '%s':'%s'", client2_name, port2_name); + goto unlock; + } + + if (!jack_controller_patchbay_disconnect( + call, + controller_ptr, + port1_ptr, + port2_ptr)) + { + /* jack_controller_patchbay_connect() constructed error reply */ + goto unlock; + } + + jack_dbus_construct_method_return_empty(call); + +unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +static +void +jack_controller_dbus_disconnect_ports_by_id( + struct jack_dbus_method_call * call) +{ + dbus_uint64_t port1_id; + dbus_uint64_t port2_id; + struct jack_graph_port *port1_ptr; + struct jack_graph_port *port2_ptr; + +/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ + + if (!controller_ptr->started) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_SERVER_NOT_RUNNING, + "Can't execute this method with stopped JACK server"); + return; + } + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_UINT64, + &port1_id, + DBUS_TYPE_UINT64, + &port2_id, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + pthread_mutex_lock(&patchbay_ptr->lock); + + port1_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port1_id); + if (port1_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port1_id); + return; + } + + port2_ptr = jack_controller_patchbay_find_port_by_id(patchbay_ptr, port2_id); + if (port2_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find port %" PRIu64, port2_id); + return; + } + + if (!jack_controller_patchbay_disconnect( + call, + controller_ptr, + port1_ptr, + port2_ptr)) + { + /* jack_controller_patchbay_connect() constructed error reply */ + goto unlock; + } + + jack_dbus_construct_method_return_empty(call); + +unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +static +void +jack_controller_dbus_disconnect_ports_by_connection_id( + struct jack_dbus_method_call * call) +{ + dbus_uint64_t connection_id; + struct jack_graph_connection *connection_ptr; + +/* jack_info("jack_controller_dbus_disconnect_ports_by_id() called."); */ + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_UINT64, + &connection_id, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + pthread_mutex_lock(&patchbay_ptr->lock); + + connection_ptr = jack_controller_patchbay_find_connection_by_id(patchbay_ptr, connection_id); + if (connection_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find connection %" PRIu64, connection_id); + goto unlock; + } + + if (!jack_controller_patchbay_disconnect( + call, + controller_ptr, + connection_ptr->port1, + connection_ptr->port2)) + { + /* jack_controller_patchbay_connect() constructed error reply */ + goto unlock; + } + + jack_dbus_construct_method_return_empty(call); + +unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +static +void +jack_controller_dbus_get_client_pid( + struct jack_dbus_method_call * call) +{ + dbus_uint64_t client_id; + struct jack_graph_client *client_ptr; + message_arg_t arg; + +/* jack_info("jack_controller_dbus_get_client_pid() called."); */ + + if (!jack_dbus_get_method_args( + call, + DBUS_TYPE_UINT64, + &client_id, + DBUS_TYPE_INVALID)) + { + /* The method call had invalid arguments meaning that + * jack_dbus_get_method_args() has constructed an error for us. + */ + return; + } + + pthread_mutex_lock(&patchbay_ptr->lock); + + client_ptr = jack_controller_patchbay_find_client_by_id(patchbay_ptr, client_id); + if (client_ptr == NULL) + { + jack_dbus_error(call, JACK_DBUS_ERROR_INVALID_ARGS, "cannot find client %" PRIu64, client_id); + goto unlock; + } + + arg.int64 = client_ptr->pid; + + jack_dbus_construct_method_return_single(call, DBUS_TYPE_INT64, arg); + +unlock: + pthread_mutex_unlock(&patchbay_ptr->lock); +} + +#undef controller_ptr +#define controller_ptr ((struct jack_controller *)context) + +static +int +jack_controller_graph_order_callback( + void *context) +{ + const char **ports; + int i; + jack_port_t *port_ptr; + + if (patchbay_ptr->graph.version > 1) + { + /* we use this only for initial catchup */ + return 0; + } + + ports = jack_get_ports(controller_ptr->client, NULL, NULL, 0); + if (ports) + { + for (i = 0; ports[i]; ++i) + { + jack_info("graph reorder: new port '%s'", ports[i]); + port_ptr = jack_port_by_name(controller_ptr->client, ports[i]);; + jack_controller_patchbay_new_port(patchbay_ptr, ports[i], jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); + } + + free(ports); + } + + if (patchbay_ptr->graph.version == 1) + { + /* we have empty initial graph, increment graph version, + so we dont do jack_get_ports() again, + on next next graph change */ + patchbay_ptr->graph.version++; + } + + return 0; +} + +void +jack_controller_client_registration_callback( + const char *client_name, + int created, + void *context) +{ + if (created) + { + jack_log("client '%s' created", client_name); + jack_controller_patchbay_create_client(patchbay_ptr, client_name, strlen(client_name)); + } + else + { + jack_log("client '%s' destroyed", client_name); + jack_controller_patchbay_destroy_client_by_name(patchbay_ptr, client_name); + } +} + +void +jack_controller_port_registration_callback( + jack_port_id_t port_id, + int created, + void *context) +{ + jack_port_t *port_ptr; + struct jack_graph_port *graph_port_ptr; + const char *port_name; + + port_ptr = jack_port_by_id(controller_ptr->client, port_id); + port_name = jack_port_name(port_ptr); + + if (created) + { + jack_log("port '%s' created", port_name); + jack_controller_patchbay_new_port(patchbay_ptr, port_name, jack_port_flags(port_ptr), jack_port_type_id(port_ptr)); + } + else + { + jack_log("port '%s' destroyed", port_name); + graph_port_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port_name); + if (graph_port_ptr == NULL) + { + jack_error("Failed to find port '%s' to destroy", port_name); + return; + } + + jack_controller_patchbay_remove_port(patchbay_ptr, graph_port_ptr); + } +} + +void +jack_controller_port_connect_callback( + jack_port_id_t port1_id, + jack_port_id_t port2_id, + int connect, + void *context) +{ + jack_port_t *port1; + jack_port_t *port2; + const char *port1_name; + const char *port2_name; + struct jack_graph_port *port1_ptr; + struct jack_graph_port *port2_ptr; + struct jack_graph_connection *connection_ptr; + + port1 = jack_port_by_id(controller_ptr->client, port1_id); + port2 = jack_port_by_id(controller_ptr->client, port2_id); + + port1_name = jack_port_name(port1); + port2_name = jack_port_name(port2); + + port1_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port1_name); + if (port1_ptr == NULL) + { + jack_error("Failed to find port '%s' to [dis]connect", port1_name); + return; + } + + port2_ptr = jack_controller_patchbay_find_port_by_full_name(patchbay_ptr, port2_name); + if (port2_ptr == NULL) + { + jack_error("Failed to find port '%s' to [dis]connect", port2_name); + return; + } + + if (connect) + { + jack_info("Connecting '%s' to '%s'", port1_name, port2_name); + connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); + if (connection_ptr != NULL) + { + jack_error("'%s' and '%s' are already connected", port1_name, port2_name); + return; + } + + jack_controller_patchbay_create_connection(patchbay_ptr, port1_ptr, port2_ptr); + } + else + { + jack_info("Disonnecting '%s' from '%s'", port1_name, port2_name); + connection_ptr = jack_controller_patchbay_find_connection(patchbay_ptr, port1_ptr, port2_ptr); + if (connection_ptr == NULL) + { + jack_error("Cannot find connection being removed"); + return; + } + + jack_controller_patchbay_destroy_connection(patchbay_ptr, connection_ptr); + } +} + +#undef controller_ptr + +void +jack_controller_patchbay_uninit( + struct jack_controller * controller_ptr) +{ + struct jack_graph_client *client_ptr; + struct jack_graph_port *port_ptr; + +/* jack_info("jack_controller_patchbay_uninit() called"); */ + + while (!list_empty(&patchbay_ptr->graph.ports)) + { + port_ptr = list_entry(patchbay_ptr->graph.ports.next, struct jack_graph_port, siblings_graph); + jack_controller_patchbay_remove_port(patchbay_ptr, port_ptr); + } + + while (!list_empty(&patchbay_ptr->graph.clients)) + { + client_ptr = list_entry(patchbay_ptr->graph.clients.next, struct jack_graph_client, siblings); + jack_controller_patchbay_destroy_client(patchbay_ptr, client_ptr); + } + + pthread_mutex_destroy(&patchbay_ptr->lock); +} + +#undef patchbay_ptr + +bool +jack_controller_patchbay_init( + struct jack_controller * controller_ptr) +{ + int ret; + struct jack_controller_patchbay * patchbay_ptr; + pthread_mutexattr_t attr; + +/* jack_info("jack_controller_patchbay_init() called"); */ + + patchbay_ptr = malloc(sizeof(struct jack_controller_patchbay)); + if (patchbay_ptr == NULL) + { + jack_error("Memory allocation of jack_controller_patchbay structure failed."); + goto fail; + } + + ret = pthread_mutexattr_init(&attr); + if (ret != 0) + { + goto fail; + } + + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + if (ret != 0) + { + goto fail; + } + + pthread_mutex_init(&patchbay_ptr->lock, &attr); + INIT_LIST_HEAD(&patchbay_ptr->graph.clients); + INIT_LIST_HEAD(&patchbay_ptr->graph.ports); + INIT_LIST_HEAD(&patchbay_ptr->graph.connections); + patchbay_ptr->graph.version = 1; + patchbay_ptr->next_client_id = 1; + patchbay_ptr->next_port_id = 1; + patchbay_ptr->next_connection_id = 1; + + controller_ptr->patchbay_context = patchbay_ptr; + + ret = jack_set_graph_order_callback(controller_ptr->client, jack_controller_graph_order_callback, controller_ptr); + if (ret != 0) + { + jack_error("jack_set_graph_order_callback() failed with error %d", ret); + goto fail_uninit_mutex; + } + + ret = jack_set_client_registration_callback(controller_ptr->client, jack_controller_client_registration_callback, controller_ptr); + if (ret != 0) + { + jack_error("jack_set_client_registration_callback() failed with error %d", ret); + goto fail_uninit_mutex; + } + + ret = jack_set_port_registration_callback(controller_ptr->client, jack_controller_port_registration_callback, controller_ptr); + if (ret != 0) + { + jack_error("jack_set_port_registration_callback() failed with error %d", ret); + goto fail_uninit_mutex; + } + + ret = jack_set_port_connect_callback(controller_ptr->client, jack_controller_port_connect_callback, controller_ptr); + if (ret != 0) + { + jack_error("jack_set_port_connect_callback() failed with error %d", ret); + goto fail_uninit_mutex; + } + + return true; + +fail_uninit_mutex: + pthread_mutex_destroy(&patchbay_ptr->lock); + +fail: + return false; +} + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetAllPorts) + JACK_DBUS_METHOD_ARGUMENT("ports_list", "as", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetGraph) + JACK_DBUS_METHOD_ARGUMENT("known_graph_version", DBUS_TYPE_UINT64_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("current_graph_version", DBUS_TYPE_UINT64_AS_STRING, true) + JACK_DBUS_METHOD_ARGUMENT("clients_and_ports", "a(tsa(tsuu))", true) + JACK_DBUS_METHOD_ARGUMENT("connections", "a(tstststst)", true) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByName) + JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(ConnectPortsByID) + JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByName) + JACK_DBUS_METHOD_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByID) + JACK_DBUS_METHOD_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING, false) + JACK_DBUS_METHOD_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(DisconnectPortsByConnectionID) + JACK_DBUS_METHOD_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHOD_ARGUMENTS_BEGIN(GetClientPID) + JACK_DBUS_METHOD_ARGUMENT("client_id", DBUS_TYPE_INT64_AS_STRING, false) +JACK_DBUS_METHOD_ARGUMENTS_END + +JACK_DBUS_METHODS_BEGIN + JACK_DBUS_METHOD_DESCRIBE(GetAllPorts, jack_controller_dbus_get_all_ports) + JACK_DBUS_METHOD_DESCRIBE(GetGraph, jack_controller_dbus_get_graph) + JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByName, jack_controller_dbus_connect_ports_by_name) + JACK_DBUS_METHOD_DESCRIBE(ConnectPortsByID, jack_controller_dbus_connect_ports_by_id) + JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByName, jack_controller_dbus_disconnect_ports_by_name) + JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByID, jack_controller_dbus_disconnect_ports_by_id) + JACK_DBUS_METHOD_DESCRIBE(DisconnectPortsByConnectionID, jack_controller_dbus_disconnect_ports_by_connection_id) + JACK_DBUS_METHOD_DESCRIBE(GetClientPID, jack_controller_dbus_get_client_pid) +JACK_DBUS_METHODS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(GraphChanged) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientAppeared) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(ClientDisappeared) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortAppeared) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port_flags", DBUS_TYPE_UINT32_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port_type", DBUS_TYPE_UINT32_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortDisappeared) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port_name", DBUS_TYPE_STRING_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsConnected) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(PortsDisconnected) + JACK_DBUS_SIGNAL_ARGUMENT("new_graph_version", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client1_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client1_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port1_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port1_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client2_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("client2_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port2_id", DBUS_TYPE_UINT64_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("port2_name", DBUS_TYPE_STRING_AS_STRING) + JACK_DBUS_SIGNAL_ARGUMENT("connection_id", DBUS_TYPE_UINT64_AS_STRING) +JACK_DBUS_SIGNAL_ARGUMENTS_END + +JACK_DBUS_SIGNALS_BEGIN + JACK_DBUS_SIGNAL_DESCRIBE(GraphChanged) + JACK_DBUS_SIGNAL_DESCRIBE(ClientAppeared) + JACK_DBUS_SIGNAL_DESCRIBE(ClientDisappeared) + JACK_DBUS_SIGNAL_DESCRIBE(PortAppeared) + JACK_DBUS_SIGNAL_DESCRIBE(PortDisappeared) + JACK_DBUS_SIGNAL_DESCRIBE(PortsConnected) + JACK_DBUS_SIGNAL_DESCRIBE(PortsDisconnected) +JACK_DBUS_SIGNALS_END + +JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_patchbay, JACK_DBUS_IFACE_NAME) + JACK_DBUS_IFACE_EXPOSE_METHODS + JACK_DBUS_IFACE_EXPOSE_SIGNALS +JACK_DBUS_IFACE_END diff --git a/dbus/controller_iface_transport.c b/dbus/controller_iface_transport.c new file mode 100644 index 00000000..546a9602 --- /dev/null +++ b/dbus/controller_iface_transport.c @@ -0,0 +1,38 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2008 Nedko Arnaudov + Copyright (C) 2008 Juuso Alasuutari + + 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 +#include +#include +#include +#include + +#include "jackdbus.h" + +JACK_DBUS_METHODS_BEGIN +JACK_DBUS_METHODS_END + +JACK_DBUS_IFACE_BEGIN(g_jack_controller_iface_transport, "org.jackaudio.JackTransport") + JACK_DBUS_IFACE_EXPOSE_METHODS +JACK_DBUS_IFACE_END diff --git a/dbus/controller_internal.h b/dbus/controller_internal.h new file mode 100644 index 00000000..df875bca --- /dev/null +++ b/dbus/controller_internal.h @@ -0,0 +1,211 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + + 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 CONTROLLER_INTERNAL_H__04D54D51_3D79_49A2_A1DA_F8587E9E7F42__INCLUDED +#define CONTROLLER_INTERNAL_H__04D54D51_3D79_49A2_A1DA_F8587E9E7F42__INCLUDED + +#include +#include "jslist.h" +#include "jack/control.h" +#include "jack/jack.h" +#include "jackdbus.h" + +struct jack_controller +{ + jackctl_server_t *server; + + void *patchbay_context; + + bool started; + jack_client_t *client; + unsigned int xruns; + + const char **driver_names; + unsigned int drivers_count; + + const char **internal_names; + unsigned int internals_count; + + /* current driver, NULL if not driver is selected */ + jackctl_driver_t *driver; + + struct jack_dbus_object_descriptor dbus_descriptor; +}; + +#define JACK_CONF_HEADER_TEXT \ + "JACK settings, as persisted by D-Bus object.\n" \ + "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); + +bool +jack_controller_start_server( + struct jack_controller *controller_ptr, + void *dbus_call_context_ptr); + +bool +jack_controller_stop_server( + struct jack_controller *controller_ptr, + void *dbus_call_context_ptr); + +bool +jack_controller_select_driver( + struct jack_controller *controller_ptr, + const char * driver_name); + +bool +jack_controller_load_internal( + struct jack_controller *controller_ptr, + const char * internal_name); + +bool +jack_controller_unload_internal( + struct jack_controller *controller_ptr, + 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, + struct jack_controller *controller_ptr, + void *dbus_call_context_ptr); + +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); + +bool +jack_controller_patchbay_init( + struct jack_controller *controller_ptr); + +void +jack_controller_patchbay_uninit( + struct jack_controller *controller_ptr); + +void * +jack_controller_patchbay_client_appeared_callback( + void * server_context, + uint64_t client_id, + const char *client_name); + +void +jack_controller_patchbay_client_disappeared_callback( + void *server_context, + uint64_t client_id, + void *client_context); + +void * +jack_controller_patchbay_port_appeared_callback( + void *server_context, + uint64_t client_id, + void *client_context, + uint64_t port_id, + const char *port_name, + uint32_t port_flags, + uint32_t port_type); + +void +jack_controller_patchbay_port_disappeared_callback( + void *server_context, + uint64_t client_id, + void *client_context, + uint64_t port_id, + void *port_context); + +void * +jack_controller_patchbay_ports_connected_callback( + void *server_context, + uint64_t client1_id, + void *client1_context, + uint64_t port1_id, + void *port1_context, + uint64_t client2_id, + void *client2_context, + uint64_t port2_id, + void *port2_context, + uint64_t connection_id); + +void +jack_controller_patchbay_ports_disconnected_callback( + void *server_context, + uint64_t client1_id, + void *client1_context, + uint64_t port1_id, + void *port1_context, + uint64_t client2_id, + void *client2_context, + uint64_t port2_id, + void *port2_context, + uint64_t connection_id, + void *connection_context); + +extern struct jack_dbus_interface_descriptor g_jack_controller_iface_introspectable; +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_transport; + +#endif /* #ifndef CONTROLLER_INTERNAL_H__04D54D51_3D79_49A2_A1DA_F8587E9E7F42__INCLUDED */ diff --git a/dbus/jackdbus.c b/dbus/jackdbus.c new file mode 100644 index 00000000..186741e5 --- /dev/null +++ b/dbus/jackdbus.c @@ -0,0 +1,885 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + Copyright (C) 2008 Marc-Olivier Barre + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" + +#include "jackdbus.h" +#include "controller.h" +#include "jack/jack.h" +#include "jack/jslist.h" +#include "jack/control.h" +#include "sigsegv.h" +#include "svnversion.h" + +FILE *g_logfile; +char *g_jackdbus_config_dir; +size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */ +char *g_jackdbus_log_dir; +size_t g_jackdbus_log_dir_len; /* without terminating '\0' char */ +int g_exit_command; +DBusConnection *g_connection; + +void +jack_dbus_send_signal( + const char *sender_object_path, + const char *iface, + const char *signal_name, + int first_arg_type, + ...) +{ + DBusMessage *message_ptr; + va_list ap; + + va_start(ap, first_arg_type); + + message_ptr = dbus_message_new_signal(sender_object_path, iface, signal_name); + if (message_ptr == NULL) + { + jack_error("dbus_message_new_signal() failed."); + goto exit; + } + + if (!dbus_message_append_args_valist(message_ptr, first_arg_type, ap)) + { + jack_error("dbus_message_append_args_valist() failed."); + goto unref; + } + + /* Add message to outgoing message queue */ + if (!dbus_connection_send(g_connection, message_ptr, NULL)) + { + jack_error("dbus_connection_send() failed."); + goto unref; + } + +unref: + dbus_message_unref(message_ptr); + +exit: + va_end(ap); +} + +/* + * Send a method return. + * + * If call->reply is NULL (i.e. a message construct method failed + * due to lack of memory) attempt to send a void method return. + */ +static +void +jack_dbus_send_method_return( + struct jack_dbus_method_call * call) +{ + if (call->reply) + { + retry_send: + if (!dbus_connection_send (call->connection, call->reply, NULL)) + { + jack_error ("Ran out of memory trying to queue method return"); + } + + dbus_connection_flush (call->connection); + dbus_message_unref (call->reply); + call->reply = NULL; + } + else + { + jack_error ("send_method_return() called with a NULL message," + " trying to construct a void return..."); + + if ((call->reply = dbus_message_new_method_return (call->message))) + { + goto retry_send; + } + else + { + jack_error ("Failed to construct method return!"); + } + } +} + +#define object_ptr ((struct jack_dbus_object_descriptor *)data) + +/* + * The D-Bus message handler for object path /org/jackaudio/Controller. + */ +DBusHandlerResult +jack_dbus_message_handler( + DBusConnection *connection, + DBusMessage *message, + void *data) +{ + struct jack_dbus_method_call call; + const char *interface_name; + struct jack_dbus_interface_descriptor ** interface_ptr_ptr; + + /* Check if the message is a method call. If not, ignore it. */ + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) + { + goto handled; + } + + /* Get the invoked method's name and make sure it's non-NULL. */ + if (!(call.method_name = dbus_message_get_member (message))) + { + jack_dbus_error( + &call, + JACK_DBUS_ERROR_UNKNOWN_METHOD, + "Received method call with empty method name"); + goto send_return; + } + + /* Initialize our data. */ + call.context = object_ptr->context; + call.connection = connection; + call.message = message; + call.reply = NULL; + + /* Check if there's an interface specified for this method call. */ + interface_name = dbus_message_get_interface (message); + if (interface_name != NULL) + { + /* Check if we can match the interface and method. + * The inteface handler functions only return false if the + * method name was unknown, otherwise they run the specified + * method and return TRUE. + */ + + interface_ptr_ptr = object_ptr->interfaces; + + while (*interface_ptr_ptr != NULL) + { + if (strcmp(interface_name, (*interface_ptr_ptr)->name) == 0) + { + if (!(*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) + { + break; + } + + goto send_return; + } + + interface_ptr_ptr++; + } + } + else + { + /* No interface was specified so we have to try them all. This is + * dictated by the D-Bus specification which states that method calls + * omitting the interface must never be rejected. + */ + + interface_ptr_ptr = object_ptr->interfaces; + + while (*interface_ptr_ptr != NULL) + { + if ((*interface_ptr_ptr)->handler(&call, (*interface_ptr_ptr)->methods)) + { + goto send_return; + } + + interface_ptr_ptr++; + } + } + + jack_dbus_error( + &call, + JACK_DBUS_ERROR_UNKNOWN_METHOD, + "Method \"%s\" with signature \"%s\" on interface \"%s\" doesn't exist", + call.method_name, + dbus_message_get_signature(message), + interface_name); + +send_return: + jack_dbus_send_method_return(&call); + +handled: + return DBUS_HANDLER_RESULT_HANDLED; +} + +void +jack_dbus_message_handler_unregister( + DBusConnection *connection, + void *data) +{ + jack_info ("Message handler was unregistered"); +} + +#undef object_ptr + +/* + * Check if the supplied method name exists in org.jackaudio.JackConfigure, + * if it does execute it and return TRUE. Otherwise return FALSE. + */ +bool +jack_dbus_run_method( + struct jack_dbus_method_call *call, + const struct jack_dbus_interface_method_descriptor * methods) +{ + const struct jack_dbus_interface_method_descriptor * method_ptr; + + method_ptr = methods; + + while (method_ptr->name != NULL) + { + if (strcmp(call->method_name, method_ptr->name) == 0) + { + method_ptr->handler(call); + return TRUE; + } + + method_ptr++; + } + + return FALSE; +} + +/* + * Read arguments from a method call. + * If the operation fails construct an error and return false, + * otherwise return true. + */ +bool +jack_dbus_get_method_args( + struct jack_dbus_method_call *call, + int type, + ...) +{ + va_list args; + DBusError error; + bool retval = true; + + va_start (args, type); + dbus_error_init (&error); + + if (!dbus_message_get_args_valist (call->message, &error, type, args)) + { + jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid arguments to method \"%s\"", + call->method_name); + retval = false; + } + + dbus_error_free (&error); + va_end (args); + + return retval; +} + +/* + * Read a string and a variant argument from a method call. + * If the operation fails construct an error and return false, + * otherwise return true. + */ +bool +jack_dbus_get_method_args_string_and_variant( + struct jack_dbus_method_call *call, + const char **arg1, + message_arg_t *arg2, + int *type_ptr) +{ + DBusMessageIter iter, sub_iter; + + /* First we want a string... */ + if (dbus_message_iter_init (call->message, &iter) + && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic (&iter, arg1); + dbus_message_iter_next (&iter); + + /* ...and then a variant. */ + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT) + { + dbus_message_iter_recurse (&iter, &sub_iter); + dbus_message_iter_get_basic (&sub_iter, arg2); + *type_ptr = dbus_message_iter_get_arg_type (&sub_iter); + + /* Got what we wanted. */ + return true; + } + } + + jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid arguments to method \"%s\"", + call->method_name); + + return false; +} + +/* + * Read two strings and a variant argument from a method call. + * If the operation fails construct an error and return false, + * otherwise return true. + */ +bool +jack_dbus_get_method_args_two_strings_and_variant( + struct jack_dbus_method_call *call, + const char **arg1, + const char **arg2, + message_arg_t *arg3, + int *type_ptr) +{ + DBusMessageIter iter, sub_iter; + + /* First we want a string... */ + if (dbus_message_iter_init (call->message, &iter) + && dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_STRING) + { + dbus_message_iter_get_basic (&iter, arg1); + dbus_message_iter_next (&iter); + + /* ...and then a second string. */ + if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) + { + return false; + } + + /* Got what we wanted. */ + dbus_message_iter_get_basic (&iter, arg2); + dbus_message_iter_next (&iter); + + /* ...and then a variant. */ + if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_VARIANT) + { + dbus_message_iter_recurse (&iter, &sub_iter); + dbus_message_iter_get_basic (&sub_iter, arg3); + *type_ptr = dbus_message_iter_get_arg_type (&sub_iter); + + /* Got what we wanted. */ + return true; + } + } + + jack_dbus_error (call, JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid arguments to method \"%s\"", + call->method_name); + + return false; +} + +/* + * Append a variant type to a D-Bus message. + * Return false if something fails, true otherwise. + */ +bool +jack_dbus_message_append_variant( + DBusMessageIter *iter, + int type, + const char *signature, + message_arg_t *arg) +{ + DBusMessageIter sub_iter; + + /* Open a variant container. */ + if (!dbus_message_iter_open_container (iter, DBUS_TYPE_VARIANT, signature, &sub_iter)) + { + goto fail; + } + + /* Append the supplied value. */ + if (!dbus_message_iter_append_basic (&sub_iter, type, (const void *) arg)) + { + dbus_message_iter_close_container (iter, &sub_iter); + goto fail; + } + + /* Close the container. */ + if (!dbus_message_iter_close_container (iter, &sub_iter)) + { + goto fail; + } + + return true; + +fail: + return false; +} + +/* + * Construct an empty method return message. + * + * The operation can only fail due to lack of memory, in which case + * there's no sense in trying to construct an error return. Instead, + * call->reply will be set to NULL and handled in send_method_return(). + */ +void +jack_dbus_construct_method_return_empty( + struct jack_dbus_method_call * call) +{ + call->reply = dbus_message_new_method_return (call->message); + + if (call->reply == NULL) + { + jack_error ("Ran out of memory trying to construct method return"); + } +} + +/* + * Construct a method return which holds a single argument or, if + * the type parameter is DBUS_TYPE_INVALID, no arguments at all + * (a void message). + * + * The operation can only fail due to lack of memory, in which case + * there's no sense in trying to construct an error return. Instead, + * call->reply will be set to NULL and handled in send_method_return(). + */ +void +jack_dbus_construct_method_return_single( + struct jack_dbus_method_call *call, + int type, + message_arg_t arg) +{ + DBusMessageIter iter; + call->reply = dbus_message_new_method_return (call->message); + + if (call->reply == NULL) + { + goto fail_no_mem; + } + + /* Void method return requested by caller. */ + if (type == DBUS_TYPE_INVALID) + { + return; + } + + /* Prevent crash on NULL input string. */ + else if (type == DBUS_TYPE_STRING && arg.string == NULL) + { + arg.string = ""; + } + + dbus_message_iter_init_append (call->reply, &iter); + + if (!dbus_message_iter_append_basic (&iter, type, (const void *) &arg)) + { + dbus_message_unref (call->reply); + call->reply = NULL; + goto fail_no_mem; + } + + return; + +fail_no_mem: + jack_error ("Ran out of memory trying to construct method return"); +} + +/* + * Construct a method return which holds an array of strings. + * + * The operation can only fail due to lack of memory, in which case + * there's no sense in trying to construct an error return. Instead, + * call->reply will be set to NULL and handled in send_method_return(). + */ +void +jack_dbus_construct_method_return_array_of_strings( + struct jack_dbus_method_call *call, + unsigned int num_members, + const char **array) +{ + DBusMessageIter iter, sub_iter; + unsigned int i; + + call->reply = dbus_message_new_method_return (call->message); + if (!call->reply) + { + goto fail; + } + + dbus_message_iter_init_append (call->reply, &iter); + + if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) + { + goto fail_unref; + } + + for (i = 0; i < num_members; ++i) + { + if (!dbus_message_iter_append_basic (&sub_iter, DBUS_TYPE_STRING, (const void *) &array[i])) + { + dbus_message_iter_close_container (&iter, &sub_iter); + goto fail_unref; + } + } + + if (!dbus_message_iter_close_container (&iter, &sub_iter)) + { + goto fail_unref; + } + + return; + +fail_unref: + dbus_message_unref (call->reply); + call->reply = NULL; + +fail: + jack_error ("Ran out of memory trying to construct method return"); +} + +void +jack_dbus_info_callback(const char *msg) +{ + time_t timestamp; + char timestamp_str[26]; + + time(×tamp); + ctime_r(×tamp, timestamp_str); + timestamp_str[24] = 0; + + fprintf(g_logfile, "%s: %s\n", timestamp_str, msg); + fflush(g_logfile); +} + +#define ANSI_BOLD_ON "\033[1m" +#define ANSI_BOLD_OFF "\033[22m" +#define ANSI_COLOR_RED "\033[31m" +#define ANSI_RESET "\033[0m" + +void +jack_dbus_error_callback(const char *msg) +{ + time_t timestamp; + char timestamp_str[26]; + + time(×tamp); + ctime_r(×tamp, timestamp_str); + timestamp_str[24] = 0; + + fprintf(g_logfile, "%s: " ANSI_BOLD_ON ANSI_COLOR_RED "ERROR: %s" ANSI_RESET "\n", timestamp_str, msg); + fflush(g_logfile); +} + +bool +ensure_dir_exist(const char *dirname, int mode) +{ + struct stat st; + if (stat(dirname, &st) != 0) + { + if (errno == ENOENT) + { + printf("Directory \"%s\" does not exist. Creating...\n", dirname); + if (mkdir(dirname, mode) != 0) + { + fprintf(stderr, "Failed to create \"%s\" directory: %d (%s)\n", dirname, errno, strerror(errno)); + return false; + } + } + else + { + fprintf(stderr, "Failed to stat \"%s\": %d (%s)\n", dirname, errno, strerror(errno)); + return false; + } + } + else + { + if (!S_ISDIR(st.st_mode)) + { + fprintf(stderr, "\"%s\" exists but is not directory.\n", dirname); + return false; + } + } + return true; +} + +char * +pathname_cat(const char *pathname_a, const char *pathname_b) +{ + char *pathname; + int pathname_a_len, pathname_b_len, pathname_len; + pathname_a_len = strlen(pathname_a); + pathname_b_len = strlen(pathname_b); + pathname = malloc(pathname_a_len + pathname_b_len + 1); + if (pathname == NULL) + { + fprintf(stderr, "Out of memory\n"); + return NULL; + } + memcpy(pathname, pathname_a, pathname_a_len); + memcpy(pathname + pathname_a_len, pathname_b, pathname_b_len); + pathname_len = pathname_a_len + pathname_b_len; + pathname[pathname_len] = 0; + return pathname; +} + +bool +paths_init() +{ + const char *home_dir, *xdg_config_home, *xdg_log_home; + + home_dir = getenv("HOME"); + if (home_dir == NULL) + { + fprintf(stderr, "Environment variable HOME not set\n"); + goto fail; + } + + xdg_config_home = getenv("XDG_CONFIG_HOME"); + if (xdg_config_home == NULL) + { + if (!(xdg_config_home = pathname_cat(home_dir, DEFAULT_XDG_CONFIG))) goto fail; + } + + if (!(xdg_log_home = pathname_cat(home_dir, DEFAULT_XDG_LOG))) goto fail; + + if (!(g_jackdbus_config_dir = pathname_cat(xdg_config_home, JACKDBUS_DIR))) goto fail; + if (!(g_jackdbus_log_dir = pathname_cat(xdg_log_home, JACKDBUS_DIR))) goto fail; + + if (!ensure_dir_exist(xdg_config_home, 0700)) + { + goto fail; + } + + if (!ensure_dir_exist(xdg_log_home, 0700)) + { + goto fail; + } + + if (!ensure_dir_exist(g_jackdbus_config_dir, 0700)) + { + free(g_jackdbus_config_dir); + goto fail; + } + g_jackdbus_config_dir_len = strlen(g_jackdbus_config_dir); + + if (!ensure_dir_exist(g_jackdbus_log_dir, 0700)) + { + free(g_jackdbus_log_dir); + goto fail; + } + g_jackdbus_log_dir_len = strlen(g_jackdbus_log_dir); + + return true; + +fail: + return false; +} + +void +paths_uninit() +{ + free(g_jackdbus_config_dir); + free(g_jackdbus_log_dir); +} + +int +log_init() +{ + char *log_filename; + size_t log_len; + + log_len = strlen(JACKDBUS_LOG); + + log_filename = malloc(g_jackdbus_log_dir_len + log_len + 1); + if (log_filename == NULL) + { + fprintf(stderr, "Out of memory\n"); + return FALSE; + } + + memcpy(log_filename, g_jackdbus_log_dir, g_jackdbus_log_dir_len); + memcpy(log_filename + g_jackdbus_log_dir_len, JACKDBUS_LOG, log_len); + log_filename[g_jackdbus_log_dir_len + log_len] = 0; + + g_logfile = fopen(log_filename, "a"); + if (g_logfile == NULL) + { + fprintf(stderr, "Cannot open jackdbus log file \"%s\": %d (%s)\n", log_filename, errno, strerror(errno)); + free(log_filename); + return FALSE; + } + + free(log_filename); + + return TRUE; +} + +void +log_uninit() +{ + fclose(g_logfile); +} + +void +jack_dbus_error( + void *dbus_call_context_ptr, + const char *error_name, + const char *format, + ...) +{ + va_list ap; + char buffer[300]; + + va_start(ap, format); + + vsnprintf(buffer, sizeof(buffer), format, ap); + + jack_error_callback(buffer); + if (dbus_call_context_ptr != NULL) + { + ((struct jack_dbus_method_call *)dbus_call_context_ptr)->reply = dbus_message_new_error( + ((struct jack_dbus_method_call *)dbus_call_context_ptr)->message, + error_name, + buffer); + } + + va_end(ap); +} + +int +main (int argc, char **argv) +{ + DBusError error; + int ret; + void *controller_ptr; + struct stat st; + char timestamp_str[26]; + + st.st_mtime = 0; + stat(argv[0], &st); + ctime_r(&st.st_mtime, timestamp_str); + timestamp_str[24] = 0; + + if (!jack_controller_settings_init()) + { + ret = 1; + goto fail; + } + + if (argc != 2 || strcmp(argv[1], "auto") != 0) + { + ret = 0; + fprintf( + stderr, + "jackdbus should be auto-executed by D-Bus message bus daemon.\n" + "If you want to run it manually anyway, specify \"auto\" as only parameter\n"); + goto fail_uninit_xml; + } + + if (!paths_init()) + { + ret = 1; + goto fail_uninit_xml; + } + + if (!log_init()) + { + ret = 1; + goto fail_uninit_paths; + } + +#if !defined(DISABLE_SIGNAL_MAGIC) + jackctl_setup_signals(0); +#endif + + jack_set_error_function(jack_dbus_error_callback); + jack_set_info_function(jack_dbus_info_callback); + + /* setup our SIGSEGV magic that prints nice stack in our logfile */ + setup_sigsegv(); + + jack_info("------------------"); + jack_info("Controller activated. Version %s (%s) built on %s", jack_get_version_string(), SVN_VERSION, timestamp_str); + + if (!dbus_threads_init_default()) + { + jack_error("dbus_threads_init_default() failed"); + ret = 1; + goto fail_uninit_log; + } + + dbus_error_init (&error); + g_connection = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (dbus_error_is_set (&error)) + { + jack_error("Cannot connect to D-Bus session bus: %s", error.message); + ret = 1; + goto fail_uninit_log; + } + + ret = dbus_bus_request_name( + g_connection, + "org.jackaudio.service", + DBUS_NAME_FLAG_DO_NOT_QUEUE, + &error); + if (ret == -1) + { + jack_error("Cannot request service name: %s", error.message); + dbus_error_free(&error); + ret = 1; + goto fail_unref_connection; + } + else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS) + { + jack_error("Requested D-Bus service name already exists"); + ret = 1; + goto fail_unref_connection; + } + + controller_ptr = jack_controller_create(g_connection); + + if (controller_ptr == NULL) + { + ret = 1; + goto fail_unref_connection; + } + + jack_info("Listening for D-Bus messages"); + + g_exit_command = FALSE; + while (!g_exit_command && dbus_connection_read_write_dispatch (g_connection, 200)); + + jack_controller_destroy(controller_ptr); + + jack_info("Controller deactivated."); + + ret = 0; + +fail_unref_connection: + dbus_connection_unref(g_connection); + +fail_uninit_log: + log_uninit(); + +fail_uninit_paths: + paths_uninit(); + +fail_uninit_xml: + jack_controller_settings_uninit(); + +fail: + return ret; +} diff --git a/dbus/jackdbus.h b/dbus/jackdbus.h new file mode 100644 index 00000000..e2ebef2c --- /dev/null +++ b/dbus/jackdbus.h @@ -0,0 +1,292 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007-2008 Juuso Alasuutari + Copyright (C) 2008 Marc-Olivier Barre + + 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 DBUS_H__3DB2458F_44B2_43EA_882A_9F888DF71A88__INCLUDED +#define DBUS_H__3DB2458F_44B2_43EA_882A_9F888DF71A88__INCLUDED + +#include + +#define JACK_DBUS_DEBUG + +//#define DISABLE_SIGNAL_MAGIC + +#define DEFAULT_XDG_CONFIG "/.config" +#define DEFAULT_XDG_LOG "/.log" +#define JACKDBUS_DIR "/jack" +#define JACKDBUS_LOG "/jackdbus.log" +#define JACKDBUS_CONF "/conf.xml" + +extern char *g_jackdbus_config_dir; +extern size_t g_jackdbus_config_dir_len; /* without terminating '\0' char */ +extern int g_exit_command; + +bool +jack_controller_settings_init(); + +void +jack_controller_settings_uninit(); + +#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_UNKNOWN_DRIVER "org.jackaudio.Error.UnknownDriver" +#define JACK_DBUS_ERROR_NEED_DRIVER "org.jackaudio.Error.NeedDriver" +#define JACK_DBUS_ERROR_UNKNOWN_DRIVER_PARAMETER "org.jackaudio.Error.UnknownDriverParameter" +#define JACK_DBUS_ERROR_UNKNOWN_ENGINE_PARAMETER "org.jackaudio.Error.UnknownEngineParameter" +#define JACK_DBUS_ERROR_UNKNOWN_INTERNAL "org.jackaudio.Error.UnknownInternal" +#define JACK_DBUS_ERROR_INVALID_ARGS "org.jackaudio.Error.InvalidArgs" +#define JACK_DBUS_ERROR_GENERIC "org.jackaudio.Error.Generic" +#define JACK_DBUS_ERROR_FATAL "org.jackaudio.Error.Fatal" + +struct jack_dbus_method_call +{ + void *context; + DBusConnection *connection; + const char *method_name; + DBusMessage *message; + DBusMessage *reply; +}; + +struct jack_dbus_interface_method_argument_descriptor +{ + const char * name; + const char * type; + bool direction_out; /* true - out, false - in */ +}; + +struct jack_dbus_interface_method_descriptor +{ + const char * name; + const struct jack_dbus_interface_method_argument_descriptor * arguments; + void (* handler)(struct jack_dbus_method_call * call); +}; + +struct jack_dbus_interface_signal_argument_descriptor +{ + const char * name; + const char * type; +}; + +struct jack_dbus_interface_signal_descriptor +{ + const char * name; + const struct jack_dbus_interface_signal_argument_descriptor * arguments; +}; + +struct jack_dbus_interface_descriptor +{ + const char * name; + + bool + (* handler)( + struct jack_dbus_method_call * call, + const struct jack_dbus_interface_method_descriptor * methods); + + const struct jack_dbus_interface_method_descriptor * methods; + const struct jack_dbus_interface_signal_descriptor * signals; +}; + +struct jack_dbus_object_descriptor +{ + struct jack_dbus_interface_descriptor ** interfaces; + void * context; +}; + +typedef union +{ + unsigned char byte; + dbus_bool_t boolean; + dbus_int16_t int16; + dbus_uint16_t uint16; + dbus_int32_t int32; + dbus_uint32_t uint32; + dbus_int64_t int64; + dbus_uint64_t uint64; + double doubl; + const char *string; +} message_arg_t; + +#define JACK_DBUS_METHOD_ARGUMENTS_BEGIN(method_name) \ +static const \ +struct jack_dbus_interface_method_argument_descriptor method_name ## _arguments[] = \ +{ + +#define JACK_DBUS_METHOD_ARGUMENT(argument_name, argument_type, argument_direction_out) \ + { \ + .name = argument_name, \ + .type = argument_type, \ + .direction_out = argument_direction_out \ + }, + +#define JACK_DBUS_METHOD_ARGUMENTS_END \ + JACK_DBUS_METHOD_ARGUMENT(NULL, NULL, false) \ +}; + +#define JACK_DBUS_METHODS_BEGIN \ +static const \ +struct jack_dbus_interface_method_descriptor methods_dtor[] = \ +{ + +#define JACK_DBUS_METHOD_DESCRIBE(method_name, handler_name) \ + { \ + .name = # method_name, \ + .arguments = method_name ## _arguments, \ + .handler = handler_name \ + }, + +#define JACK_DBUS_METHODS_END \ + { \ + .name = NULL, \ + .arguments = NULL, \ + .handler = NULL \ + } \ +}; + +#define JACK_DBUS_SIGNAL_ARGUMENTS_BEGIN(signal_name) \ +static const \ +struct jack_dbus_interface_signal_argument_descriptor signal_name ## _arguments[] = \ +{ + +#define JACK_DBUS_SIGNAL_ARGUMENT(argument_name, argument_type) \ + { \ + .name = argument_name, \ + .type = argument_type \ + }, + +#define JACK_DBUS_SIGNAL_ARGUMENTS_END \ + JACK_DBUS_SIGNAL_ARGUMENT(NULL, NULL) \ +}; + +#define JACK_DBUS_SIGNALS_BEGIN \ +static const \ +struct jack_dbus_interface_signal_descriptor signals_dtor[] = \ +{ + +#define JACK_DBUS_SIGNAL_DESCRIBE(signal_name) \ + { \ + .name = # signal_name, \ + .arguments = signal_name ## _arguments \ + }, + +#define JACK_DBUS_SIGNALS_END \ + { \ + .name = NULL, \ + .arguments = NULL, \ + } \ +}; + +#define JACK_DBUS_IFACE_BEGIN(iface_var, iface_name) \ +struct jack_dbus_interface_descriptor iface_var = \ +{ \ + .name = iface_name, \ + .handler = jack_dbus_run_method, + +#define JACK_DBUS_IFACE_HANDLER(handler_func) \ + .handler = handler_func, + +#define JACK_DBUS_IFACE_EXPOSE_METHODS \ + .methods = methods_dtor, + +#define JACK_DBUS_IFACE_EXPOSE_SIGNALS \ + .signals = signals_dtor, + +#define JACK_DBUS_IFACE_END \ +}; + +DBusHandlerResult +jack_dbus_message_handler( + DBusConnection *connection, + DBusMessage *message, + void *data); + +void +jack_dbus_message_handler_unregister( + DBusConnection *connection, + void *data); + +bool +jack_dbus_run_method( + struct jack_dbus_method_call * call, + const struct jack_dbus_interface_method_descriptor * methods); + +void +jack_dbus_error( + void *dbus_call_context_ptr, + const char *error_name, + const char *format, + ...); + +bool +jack_dbus_get_method_args( + struct jack_dbus_method_call *call, + int type, + ...); + +bool +jack_dbus_get_method_args_string_and_variant( + struct jack_dbus_method_call *call, + const char **arg1, + message_arg_t *arg2, + int *type_ptr); + +bool +jack_dbus_get_method_args_two_strings_and_variant( + struct jack_dbus_method_call *call, + const char **arg1, + const char **arg2, + message_arg_t *arg3, + int *type_ptr); + +bool +jack_dbus_message_append_variant( + DBusMessageIter *iter, + int type, + const char *signature, + message_arg_t *arg); + +void +jack_dbus_construct_method_return_empty( + struct jack_dbus_method_call * call); + +void +jack_dbus_construct_method_return_single( + struct jack_dbus_method_call *call, + int type, + message_arg_t arg); + +void +jack_dbus_construct_method_return_array_of_strings( + struct jack_dbus_method_call *call, + unsigned int num_members, + const char **array); + +void +jack_dbus_send_signal( + const char *sender_object_path, + const char *iface, + const char *signal_name, + int first_arg_type, + ...); + +#define JACK_CONTROLLER_OBJECT_PATH "/org/jackaudio/Controller" + +extern struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[]; + +#endif /* #ifndef DBUS_H__3DB2458F_44B2_43EA_882A_9F888DF71A88__INCLUDED */ diff --git a/dbus/list.h b/dbus/list.h new file mode 100644 index 00000000..fee6e73b --- /dev/null +++ b/dbus/list.h @@ -0,0 +1,874 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/***************************************************************************** + * + * Linux kernel header adapted for user-mode + * The 2.6.17-rt1 version was used. + * + * Original copyright holders of this code are unknown, they were not + * mentioned in the original file. + * + * 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; 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + *****************************************************************************/ + +#ifndef _LINUX_LIST_H +#define _LINUX_LIST_H + +#include + +#if !defined(offsetof) +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define prefetch(x) (x = x) + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add_rcu(struct list_head * new, + struct list_head * prev, struct list_head * next) +{ + new->next = next; + new->prev = prev; +// smp_wmb(); + next->prev = new; + prev->next = new; +} + +/** + * list_add_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_rcu(struct list_head *new, struct list_head *head) +{ + __list_add_rcu(new, head, head->next); +} + +/** + * list_add_tail_rcu - add a new entry to rcu-protected list + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_add_tail_rcu() + * or list_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + */ +static inline void list_add_tail_rcu(struct list_head *new, + struct list_head *head) +{ + __list_add_rcu(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_del_rcu - deletes entry from list without re-initialization + * @entry: the element to delete from the list. + * + * Note: list_empty on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as list_del_rcu() + * or list_add_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * list_for_each_entry_rcu(). + * + * Note that the caller is not permitted to immediately free + * the newly deleted entry. Instead, either synchronize_rcu() + * or call_rcu() must be used to defer freeing until an RCU + * grace period has elapsed. + */ +static inline void list_del_rcu(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->prev = LIST_POISON2; +} + +/* + * list_replace_rcu - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * The old entry will be replaced with the new entry atomically. + */ +static inline void list_replace_rcu(struct list_head *old, + struct list_head *new) +{ + new->next = old->next; + new->prev = old->prev; +// smp_wmb(); + new->next->prev = new; + new->prev->next = new; + old->prev = LIST_POISON2; +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is + * empty _and_ checks that no other CPU might be + * in the process of still modifying either member + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + * + * @head: the list to test. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +static inline void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; prefetch(pos->next), pos != (head); \ + pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + prefetch(pos->member.prev), &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use as a start point in + * list_for_each_entry_continue + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - iterate over list of given type + * continuing after existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type + * continuing from existing point + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue - iterate over list of given type + * continuing after existing point safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from - iterate over list of given type + * from existing point safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against + * removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +/** + * list_for_each_rcu - iterate over an rcu-protected list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_rcu(pos, head) \ + for (pos = (head)->next; \ + prefetch(rcu_dereference(pos)->next), pos != (head); \ + pos = pos->next) + +#define __list_for_each_rcu(pos, head) \ + for (pos = (head)->next; \ + rcu_dereference(pos) != (head); \ + pos = pos->next) + +/** + * list_for_each_safe_rcu - iterate over an rcu-protected list safe + * against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_safe_rcu(pos, n, head) \ + for (pos = (head)->next; \ + n = rcu_dereference(pos)->next, pos != (head); \ + pos = n) + +/** + * list_for_each_entry_rcu - iterate over rcu list of given type + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_entry_rcu(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + prefetch(rcu_dereference(pos)->member.next), \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + + +/** + * list_for_each_continue_rcu - iterate over an rcu-protected list + * continuing after existing point. + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as list_add_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define list_for_each_continue_rcu(pos, head) \ + for ((pos) = (pos)->next; \ + prefetch(rcu_dereference((pos))->next), (pos) != (head); \ + (pos) = (pos)->next) + +/* + * Double linked lists with a single pointer list head. + * Mostly useful for hash tables where the two pointer list head is + * too wasteful. + * You lose the ability to access the tail in O(1). + */ + +struct hlist_head { + struct hlist_node *first; +}; + +struct hlist_node { + struct hlist_node *next, **pprev; +}; + +#define HLIST_HEAD_INIT { .first = NULL } +#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } +#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) +static inline void INIT_HLIST_NODE(struct hlist_node *h) +{ + h->next = NULL; + h->pprev = NULL; +} + +static inline int hlist_unhashed(const struct hlist_node *h) +{ + return !h->pprev; +} + +static inline int hlist_empty(const struct hlist_head *h) +{ + return !h->first; +} + +static inline void __hlist_del(struct hlist_node *n) +{ + struct hlist_node *next = n->next; + struct hlist_node **pprev = n->pprev; + *pprev = next; + if (next) + next->pprev = pprev; +} + +static inline void hlist_del(struct hlist_node *n) +{ + __hlist_del(n); + n->next = LIST_POISON1; + n->pprev = LIST_POISON2; +} + +/** + * hlist_del_rcu - deletes entry from hash list without re-initialization + * @n: the element to delete from the hash list. + * + * Note: list_unhashed() on entry does not return true after this, + * the entry is in an undefined state. It is useful for RCU based + * lockfree traversal. + * + * In particular, it means that we can not poison the forward + * pointers that may still be used for walking the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry(). + */ +static inline void hlist_del_rcu(struct hlist_node *n) +{ + __hlist_del(n); + n->pprev = LIST_POISON2; +} + +static inline void hlist_del_init(struct hlist_node *n) +{ + if (!hlist_unhashed(n)) { + __hlist_del(n); + INIT_HLIST_NODE(n); + } +} + +/* + * hlist_replace_rcu - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * The old entry will be replaced with the new entry atomically. + */ +static inline void hlist_replace_rcu(struct hlist_node *old, + struct hlist_node *new) +{ + struct hlist_node *next = old->next; + + new->next = next; + new->pprev = old->pprev; +// smp_wmb(); + if (next) + new->next->pprev = &new->next; + *new->pprev = new; + old->pprev = LIST_POISON2; +} + +static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + if (first) + first->pprev = &n->next; + h->first = n; + n->pprev = &h->first; +} + + +/** + * hlist_add_head_rcu - adds the specified element to the specified hlist, + * while permitting racing traversals. + * @n: the element to add to the hash list. + * @h: the list to add to. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry_rcu(), used to prevent memory-consistency + * problems on Alpha CPUs. Regardless of the type of CPU, the + * list-traversal primitive must be guarded by rcu_read_lock(). + */ +static inline void hlist_add_head_rcu(struct hlist_node *n, + struct hlist_head *h) +{ + struct hlist_node *first = h->first; + n->next = first; + n->pprev = &h->first; +// smp_wmb(); + if (first) + first->pprev = &n->next; + h->first = n; +} + +/* next must be != NULL */ +static inline void hlist_add_before(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; + next->pprev = &n->next; + *(n->pprev) = n; +} + +static inline void hlist_add_after(struct hlist_node *n, + struct hlist_node *next) +{ + next->next = n->next; + n->next = next; + next->pprev = &n->next; + + if(next->next) + next->next->pprev = &next->next; +} + +/** + * hlist_add_before_rcu - adds the specified element to the specified hlist + * before the specified node while permitting racing traversals. + * @n: the new element to add to the hash list. + * @next: the existing element to add the new element before. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry_rcu(), used to prevent memory-consistency + * problems on Alpha CPUs. + */ +static inline void hlist_add_before_rcu(struct hlist_node *n, + struct hlist_node *next) +{ + n->pprev = next->pprev; + n->next = next; +// smp_wmb(); + next->pprev = &n->next; + *(n->pprev) = n; +} + +/** + * hlist_add_after_rcu - adds the specified element to the specified hlist + * after the specified node while permitting racing traversals. + * @prev: the existing element to add the new element after. + * @n: the new element to add to the hash list. + * + * The caller must take whatever precautions are necessary + * (such as holding appropriate locks) to avoid racing + * with another list-mutation primitive, such as hlist_add_head_rcu() + * or hlist_del_rcu(), running on this same list. + * However, it is perfectly legal to run concurrently with + * the _rcu list-traversal primitives, such as + * hlist_for_each_entry_rcu(), used to prevent memory-consistency + * problems on Alpha CPUs. + */ +static inline void hlist_add_after_rcu(struct hlist_node *prev, + struct hlist_node *n) +{ + n->next = prev->next; + n->pprev = &prev->next; +// smp_wmb(); + prev->next = n; + if (n->next) + n->next->pprev = &n->next; +} + +#define hlist_entry(ptr, type, member) container_of(ptr,type,member) + +#define hlist_for_each(pos, head) \ + for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \ + pos = pos->next) + +#define hlist_for_each_safe(pos, n, head) \ + for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ + pos = n) + +/** + * hlist_for_each_entry - iterate over list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry(tpos, pos, head, member) \ + for (pos = (head)->first; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_continue(tpos, pos, member) \ + for (pos = (pos)->next; \ + pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_from - iterate over a hlist continuing from existing point + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_from(tpos, pos, member) \ + for (; pos && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +/** + * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @n: another &struct hlist_node to use as temporary storage + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + */ +#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \ + for (pos = (head)->first; \ + pos && ({ n = pos->next; 1; }) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = n) + +/** + * hlist_for_each_entry_rcu - iterate over rcu list of given type + * @tpos: the type * to use as a loop counter. + * @pos: the &struct hlist_node to use as a loop counter. + * @head: the head for your list. + * @member: the name of the hlist_node within the struct. + * + * This list-traversal primitive may safely run concurrently with + * the _rcu list-mutation primitives such as hlist_add_head_rcu() + * as long as the traversal is guarded by rcu_read_lock(). + */ +#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ + for (pos = (head)->first; \ + rcu_dereference(pos) && ({ prefetch(pos->next); 1;}) && \ + ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \ + pos = pos->next) + +#endif diff --git a/dbus/org.jackaudio.service.in b/dbus/org.jackaudio.service.in new file mode 100644 index 00000000..91b777ac --- /dev/null +++ b/dbus/org.jackaudio.service.in @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.jackaudio.service +Exec=${BINDIR}/jackdbus auto diff --git a/dbus/sigsegv.c b/dbus/sigsegv.c new file mode 100644 index 00000000..46645408 --- /dev/null +++ b/dbus/sigsegv.c @@ -0,0 +1,192 @@ +/** + * This source file is used to print out a stack-trace when your program + * segfaults. It is relatively reliable and spot-on accurate. + * + * This code is in the public domain. Use it as you see fit, some credit + * would be appreciated, but is not a prerequisite for usage. Feedback + * on it's use would encourage further development and maintenance. + * + * Author: Jaco Kroon + * + * Copyright (C) 2005 - 2008 Jaco Kroon + */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +//#define NO_CPP_DEMANGLE +#define SIGSEGV_NO_AUTO_INIT + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef NO_CPP_DEMANGLE +//#include +char * __cxa_demangle(const char * __mangled_name, char * __output_buffer, size_t * __length, int * __status); +#endif + +#include "JackError.h" + +#if defined(REG_RIP) +# define SIGSEGV_STACK_IA64 +# define REGFORMAT "%016lx" +#elif defined(REG_EIP) +# define SIGSEGV_STACK_X86 +# define REGFORMAT "%08x" +#else +# define SIGSEGV_STACK_GENERIC +# define REGFORMAT "%x" +#endif + +#ifdef __APPLE__ + +// TODO : does not compile yet on OSX +static void signal_segv(int signum, siginfo_t* info, void*ptr) +{} + +#else + +static void signal_segv(int signum, siginfo_t* info, void*ptr) { + static const char *si_codes[3] = {"", "SEGV_MAPERR", "SEGV_ACCERR"}; + + size_t i; + ucontext_t *ucontext = (ucontext_t*)ptr; + +#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) + int f = 0; + Dl_info dlinfo; + void **bp = 0; + void *ip = 0; +#else + void *bt[20]; + char **strings; + size_t sz; +#endif + + if (signum == SIGSEGV) + { + jack_error("Segmentation Fault!"); + } + else if (signum == SIGABRT) + { + jack_error("Abort!"); + } + else if (signum == SIGILL) + { + jack_error("Illegal instruction!"); + } + else if (signum == SIGFPE) + { + jack_error("Floating point exception!"); + } + else + { + jack_error("Unknown bad signal catched!"); + } + + jack_error("info.si_signo = %d", signum); + jack_error("info.si_errno = %d", info->si_errno); + jack_error("info.si_code = %d (%s)", info->si_code, si_codes[info->si_code]); + jack_error("info.si_addr = %p", info->si_addr); + for(i = 0; i < NGREG; i++) + jack_error("reg[%02d] = 0x" REGFORMAT, i, ucontext->uc_mcontext.gregs[i]); + +#if defined(SIGSEGV_STACK_X86) || defined(SIGSEGV_STACK_IA64) +# if defined(SIGSEGV_STACK_IA64) + ip = (void*)ucontext->uc_mcontext.gregs[REG_RIP]; + bp = (void**)ucontext->uc_mcontext.gregs[REG_RBP]; +# elif defined(SIGSEGV_STACK_X86) + ip = (void*)ucontext->uc_mcontext.gregs[REG_EIP]; + bp = (void**)ucontext->uc_mcontext.gregs[REG_EBP]; +# endif + + jack_error("Stack trace:"); + while(bp && ip) { + if(!dladdr(ip, &dlinfo)) + break; + + const char *symname = dlinfo.dli_sname; +#ifndef NO_CPP_DEMANGLE + int status; + char *tmp = __cxa_demangle(symname, NULL, 0, &status); + + if(status == 0 && tmp) + symname = tmp; +#endif + + jack_error("% 2d: %p <%s+%u> (%s)", + ++f, + ip, + symname, + (unsigned)(ip - dlinfo.dli_saddr), + dlinfo.dli_fname); + +#ifndef NO_CPP_DEMANGLE + if(tmp) + free(tmp); +#endif + + if(dlinfo.dli_sname && !strcmp(dlinfo.dli_sname, "main")) + break; + + ip = bp[1]; + bp = (void**)bp[0]; + } +#else + jack_error("Stack trace (non-dedicated):"); + sz = backtrace(bt, 20); + strings = backtrace_symbols(bt, sz); + + for(i = 0; i < sz; ++i) + jack_error("%s", strings[i]); +#endif + jack_error("End of stack trace"); + exit (-1); +} + +#endif + +int setup_sigsegv() { + struct sigaction action; + + memset(&action, 0, sizeof(action)); + action.sa_sigaction = signal_segv; + action.sa_flags = SA_SIGINFO; + if(sigaction(SIGSEGV, &action, NULL) < 0) { + jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); + return 0; + } + + if(sigaction(SIGILL, &action, NULL) < 0) { + jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); + return 0; + } + + if(sigaction(SIGABRT, &action, NULL) < 0) { + jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); + return 0; + } + + if(sigaction(SIGFPE, &action, NULL) < 0) { + jack_error("sigaction failed. errno is %d (%s)", errno, strerror(errno)); + return 0; + } + + return 1; +} + +#ifndef SIGSEGV_NO_AUTO_INIT +static void __attribute((constructor)) init(void) { + setup_sigsegv(); +} +#endif diff --git a/dbus/sigsegv.h b/dbus/sigsegv.h new file mode 100644 index 00000000..55b4f214 --- /dev/null +++ b/dbus/sigsegv.h @@ -0,0 +1,9 @@ +#ifndef __SIGSEGV_H__ +#define __SIGSEGV_H__ + +#ifdef __cplusplus +extern "C" +#endif +int setup_sigsegv(); + +#endif diff --git a/dbus/wscript b/dbus/wscript new file mode 100644 index 00000000..deec89e2 --- /dev/null +++ b/dbus/wscript @@ -0,0 +1,102 @@ +#! /usr/bin/env python +# encoding: utf-8 + +import Params +import os.path +import re # subst_func + +def set_options(opt): + opt.add_option('--enable-pkg-config-dbus-service-dir', action='store_true', default=False, help='force D-Bus service install dir to be one returned by pkg-config') + +def configure(conf): + conf.check_pkg('dbus-1', pkgvars=['session_bus_services_dir']) + + if Params.g_options.enable_pkg_config_dbus_service_dir: + conf.env['DBUS_SERVICES_DIR'] = conf.env['DBUS-1_SESSION_BUS_SERVICES_DIR'][0] + else: + conf.env['DBUS_SERVICES_DIR'] = os.path.normpath(conf.env['PREFIX'] + '/share/dbus-1/services') + + conf.check_tool('misc') + + e = conf.create_header_configurator() + e.name = 'expat.h' + e.define = 'HAVE_EXPAT' + e.run() + + if conf.is_defined('HAVE_EXPAT'): + conf.env['LIB_EXPAT'] = ['expat'] + + conf.env['BUILD_JACKDBUS'] = conf.is_defined('HAVE_EXPAT') and conf.is_defined('HAVE_DBUS_1') + +# by default waf subst tool uses @VAR@ while scons legacy is ${VAR} +# so we use same template as scons for now +def subst_func(tsk): + "Substitutes variables in a .in file" + + m4_re = re.compile('\$\{(\w+)\}', re.M) + + env = tsk.env() + infile = tsk.m_inputs[0].abspath(env) + outfile = tsk.m_outputs[0].abspath(env) + + file = open(infile, 'r') + code = file.read() + file.close() + + s = m4_re.sub(r'%(\1)s', code) + + dict = tsk.dict + if not dict: + names = m4_re.findall(code) + for i in names: + if env[i] and type(env[i]) is types.ListType : + dict[i] = " ".join(env[i]) + else: dict[i] = env[i] + + file = open(outfile, 'w') + file.write(s % dict) + file.close() + + return 0 + +def build(bld): + if bld.env()["BUILD_JACKDBUS"] != True: + return + + obj = bld.create_obj('cc', 'program') + if bld.env()['IS_LINUX']: + sysdeps_dbus_include = ['../linux', '../posix'] + if bld.env()['IS_MACOSX']: + sysdeps_dbus_include = ['../macosx', '../posix'] + + obj.includes = sysdeps_dbus_include + ['.', '../', '../common', '../common/jack'] + obj.source = [ + 'jackdbus.c', + 'controller.c', + 'controller_iface_configure.c', + 'controller_iface_control.c', + 'controller_iface_introspectable.c', + 'controller_iface_patchbay.c', + 'controller_iface_transport.c', + 'xml.c', + 'xml_expat.c', + #'xml_libxml.c', + #'xml_nop.c', + 'xml_write_raw.c', + 'sigsegv.c', + ] + if bld.env()['IS_LINUX']: + obj.uselib = 'PTHREAD DL RT DBUS-1 EXPAT' + if bld.env()['IS_MACOSX']: + obj.uselib = 'PTHREAD DL DBUS-1 EXPAT' + obj.uselib_local = 'serverlib' + obj.target = 'jackdbus' + + # process org.jackaudio.service.in -> org.jackaudio.service + obj = bld.create_obj('subst') + obj.source = 'org.jackaudio.service.in' + obj.target = 'org.jackaudio.service' + obj.dict = {'BINDIR': bld.env()['PREFIX'] + '/bin'} + obj.inst_var = bld.env()['DBUS_SERVICES_DIR'] + obj.inst_dir = '/' + obj.fun = subst_func # @VAR@ -> ${VAR} diff --git a/dbus/xml.c b/dbus/xml.c new file mode 100644 index 00000000..182b60ff --- /dev/null +++ b/dbus/xml.c @@ -0,0 +1,382 @@ +/* -*- 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 +#include +#include +#include +#include + +#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) +{ + jackctl_parameter_t *parameter; + jackctl_param_type_t type; + int value_int; + unsigned int value_uint; + union jackctl_parameter_value value; + + 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) + { + jack_error( + "Unknown parameter \"%s\" of driver \"%s\"", + option_name, + jackctl_driver_get_name(driver)); + 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 driver \"%s\" is of unknown type %d", + jackctl_parameter_get_name(parameter), + jackctl_driver_get_name(driver), + type); + } + + 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; + unsigned int value_uint; + 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) + { + 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); + } + + jackctl_parameter_set_value(parameter, &value); +} + +void +jack_controller_settings_set_engine_option( + struct jack_controller *controller_ptr, + const char *option_name, + const char *option_value) +{ + jackctl_parameter_t *parameter; + jackctl_param_type_t type; + int value_int; + unsigned int value_uint; + union jackctl_parameter_value value; + + jack_info("setting engine option \"%s\" to value \"%s\"", option_name, option_value); + + 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) + { + 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("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; + } + } + + 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); +} diff --git a/dbus/xml.h b/dbus/xml.h new file mode 100644 index 00000000..956e7943 --- /dev/null +++ b/dbus/xml.h @@ -0,0 +1,36 @@ +/* -*- 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. + +*/ + +#ifndef XML_H__4F102BD2_3354_41C9_B842_DC00E1557A0F__INCLUDED +#define XML_H__4F102BD2_3354_41C9_B842_DC00E1557A0F__INCLUDED + +bool +jack_controller_settings_save( + struct jack_controller * controller_ptr, + void *dbus_call_context_ptr); + +void +jack_controller_settings_load( + struct jack_controller * controller_ptr); + +void +jack_controller_settings_save_auto( + struct jack_controller * controller_ptr); + +#endif /* #ifndef XML_H__4F102BD2_3354_41C9_B842_DC00E1557A0F__INCLUDED */ diff --git a/dbus/xml_expat.c b/dbus/xml_expat.c new file mode 100644 index 00000000..1ee1bd2e --- /dev/null +++ b/dbus/xml_expat.c @@ -0,0 +1,369 @@ +/* -*- 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "controller_internal.h" +#include "jackdbus.h" + +bool +jack_controller_settings_init() +{ + return true; +} + +void +jack_controller_settings_uninit() +{ +} + +#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; + char option[JACK_PARAM_STRING_MAX+1]; + int option_used; + char *name; +}; + +#define context_ptr ((struct parse_context *)data) + +void +jack_controller_settings_callback_chrdata(void *data, const XML_Char *s, int len) +{ + if (context_ptr->error) + { + return; + } + + if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_OPTION) + { + if (context_ptr->option_used + len >= JACK_PARAM_STRING_MAX) + { + jack_error("xml parse max char data length reached"); + context_ptr->error = XML_TRUE; + return; + } + + memcpy(context_ptr->option + context_ptr->option_used, s, len); + context_ptr->option_used += len; + } +} + +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) + { + jack_error("xml parse max stack depth reached"); + context_ptr->error = XML_TRUE; + return; + } + + if (strcmp(el, "jack") == 0) + { + //jack_info(""); + context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK; + return; + } + + if (strcmp(el, "engine") == 0) + { + //jack_info(""); + context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_ENGINE; + return; + } + + if (strcmp(el, "drivers") == 0) + { + //jack_info(""); + context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVERS; + return; + } + + if (strcmp(el, "internals") == 0) + { + //jack_info(""); + context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_INTERNALS; + return; + } + + if (strcmp(el, "driver") == 0) + { + if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0) + { + jack_error(" XML element must contain exactly one attribute, named \"name\""); + context_ptr->error = XML_TRUE; + return; + } + + //jack_info(""); + 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) + { + jack_error(" XML element must contain exactly one attribute, named \"name\""); + context_ptr->error = XML_TRUE; + return; + } + + //jack_info(""); + 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; + + return; + } + + + if (strcmp(el, "option") == 0) + { + //jack_info("