git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@4239 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
@@ -34,9 +34,38 @@ Valerio Pilo | |||||
Jackdmp changes log | Jackdmp changes log | ||||
--------------------------- | --------------------------- | ||||
2011-03-29 Stephane Letz <letz@grame.fr> | |||||
* Synchronize JackWeakAPI.cpp with new APIs. | |||||
2011-03-28 Stephane Letz <letz@grame.fr> | |||||
* Correction of jack_connect/jack_disconnect: use of jack_activate and volatile keyword for thread shared variable. | |||||
* Correction of JackNetOneDriver for latest CELT API. | |||||
2011-03-24 Stephane Letz <letz@grame.fr> | |||||
* Implement renaming in JackDriver::Open to avoid name collision (thanks Devin Anderson). | |||||
* Correct alsa_driver_restart (thanks Devin Anderson). | |||||
2011-03-23 Stephane Letz <letz@grame.fr> | |||||
* Devin Anderson server-ctl-proposal branch merged on trunk: improved control API, slave backend reworked. | |||||
2011-03-14 Stephane Letz <letz@grame.fr> | |||||
* Correct JackEngine::NotifyGraphReorder, update JackDebugClient with latest API. | |||||
2011-03-13 Stephane Letz <letz@grame.fr> | |||||
* Rework internal slave driver management, JackServerGlobals now handle same parameters as jackdmp. | |||||
2011-03-11 Stephane Letz <letz@grame.fr> | 2011-03-11 Stephane Letz <letz@grame.fr> | ||||
* Correct JackNetMaster::SetBufferSize. | * Correct JackNetMaster::SetBufferSize. | ||||
* Use jack_default_audio_sample_t instead of float consistently, fix ticket #201." | |||||
* -X now allows to add several slave backends, add -I to load several internal clients. | |||||
2011-03-10 Stephane Letz <letz@grame.fr> | 2011-03-10 Stephane Letz <letz@grame.fr> | ||||
@@ -1,14 +1,14 @@ | |||||
----------------------------------------------- | |||||
jackdmp for Linux, MacOSX, Windows and Solaris | |||||
----------------------------------------------- | |||||
----------------------------------------------------------- | |||||
jackdmp (aka JACK2) for Linux, MacOSX, Windows and Solaris | |||||
----------------------------------------------------------- | |||||
jackdmp is a C++ version of the JACK low-latency audio server for multi-processor machines. It is a new implementation of the JACK server core features that aims in removing some limitations of the current design. The activation system has been changed for a data flow model and lock-free programming techniques for graph access have been used to have a more dynamic and robust system. | |||||
jackdmp is a C++ version of the JACK low-latency audio server for multi-processor machines. It is a new implementation of the JACK server core features that aims in removing some limitations of the JACK1 design. The activation system has been changed for a data flow model and lock-free programming techniques for graph access have been used to have a more dynamic and robust system. | |||||
- jackdmp use a new client activation model that allows simultaneous client execution (on a smp machine) when parallel clients exist in the graph (client that have the same inputs). This activation model allows to better use available CPU on a smp machine, but also works on mono-processor machine. | - jackdmp use a new client activation model that allows simultaneous client execution (on a smp machine) when parallel clients exist in the graph (client that have the same inputs). This activation model allows to better use available CPU on a smp machine, but also works on mono-processor machine. | ||||
- jackdmp use a lock-free way to access (read/write) the client graph, thus allowing connections/disconnection to be done without interrupting the audio stream. The result is that connections/disconnections are glitch-free. | - jackdmp use a lock-free way to access (read/write) the client graph, thus allowing connections/disconnection to be done without interrupting the audio stream. The result is that connections/disconnections are glitch-free. | ||||
- jackdmp can work in 2 different mode at the server level : | |||||
- jackdmp can work in 2 different modes at the server level : | |||||
- synchronous activation : in a given cycle, the server waits for all clients to be finished (similar to normal jackd) | - synchronous activation : in a given cycle, the server waits for all clients to be finished (similar to normal jackd) | ||||
@@ -20,7 +20,7 @@ The audible result of this mode is that if a client is not activated during one | |||||
Linux version | Linux version | ||||
-------------- | -------------- | ||||
The published version still uses fifos for server/client synchronization. The use of POSIX named semaphore is implemented but still a bit unstable. Sockets are used for server/client communications. The ALSA backend derived from jackd implementation is used. To build jackdmp, a "waf" (http://code.google.com/p/waf/) based compilation system is available. The code has to be compiled on a machine where ALSA and possibly frebob (FFADO) headers and libraries are corrected installed. | |||||
The published version still uses fifos for server/client synchronization. The use of POSIX named semaphore is implemented but still a bit unstable. Sockets are used for server/client communications. The ALSA backend derived from jackd implementation is used. To build jackdmp, a "waf" (http://code.google.com/p/waf/) based compilation system is available. The code has to be compiled on a machine where ALSA and possibly freeboot (FFADO) headers and libraries are corrected installed. | |||||
In the top folder do : | In the top folder do : | ||||
@@ -54,7 +54,7 @@ In the top folder do : | |||||
./waf build | ./waf build | ||||
sudo ./waf install | sudo ./waf install | ||||
(Note : you may have to use "pfexec" instead of "sudo" on systems where sudo is not there.) | |||||
(Note : you may have to use "pfexec" instead of "sudo" on systems where sudo is not there). | |||||
Various compilation options can be seen using ./waf --help. | Various compilation options can be seen using ./waf --help. | ||||
@@ -68,43 +68,37 @@ Starting the server : | |||||
- for best performances, the server has to be started with privileges that allows to use "real-time" threads, for example using the "pfexec" command (or configurating the system with "priocntl" first), for instance : pfexec jackd -R -S -P59 -d oss | - for best performances, the server has to be started with privileges that allows to use "real-time" threads, for example using the "pfexec" command (or configurating the system with "priocntl" first), for instance : pfexec jackd -R -S -P59 -d oss | ||||
- audio cards info can be retrieved using "ossinfo" tool (for instance ossinfo -v3). Some card needs to be configurated first using "ossxmix" then the correct buffer size has to be used, for instance : pfexec jackd -R -S -P59 -d oss -p 512 | |||||
- audio cards info can be retrieved using "ossinfo" tool (for instance ossinfo -v3). Some card needs to be configured first using "ossxmix" then the correct buffer size has to be used, for instance : pfexec jackd -R -S -P59 -d oss -p 512 | |||||
------------ | ------------ | ||||
OSX version | OSX version | ||||
------------ | ------------ | ||||
The published version uses Mach semaphores for server/client synchronization. MIG generated Remote Procedure Calls (RPC) are used for server/client communications. The CoreAudio backend derived from jackd implementation is used. | |||||
The package contains : | |||||
- the compiled binaries with "install" and "remove" scripts located in bin/osx | |||||
- the source code with an XCode project | |||||
- the component needed to use CoreAudio applications with JACK (the JackRouter JACK/CoreAudio bridge) | |||||
The published version uses Mach semaphores for server/client synchronization. Sockets are used for server/client communications. The CoreAudio backend derived from JACK1 implementation is used. | |||||
Starting with 0.70 version, the OSX project can compile 32/64 bits binaries for PPC and Intel machines. On a 64 bits machine, using the "jackdmp" in a terminal will start the 64 bits version. Using the "arch" command possibly allows to force starting in 32 bits (see man arch). The JackPilot and JackRouter binaries are now also released as 32/64 bits versions for PPC and Intel machines. By default the JackPilot application will start in 32 bits mode (even on a 64 bits machine) and launch the 32 bits jackdmp. Unchecking the "Launch in 32 bits mode" box in the JackPilot info (GetInfo = %I in the Finder...) allows to start JackPilot in 64 bits then launch the 64 bits jackdmp version. Very few audio applications are already 64 bits aware: Apple AU Lab (included in Developer tools) can be launched in 64 bit, here again by unchecking the "Launch in 32 bits mode" box in the AU Lab info. | Starting with 0.70 version, the OSX project can compile 32/64 bits binaries for PPC and Intel machines. On a 64 bits machine, using the "jackdmp" in a terminal will start the 64 bits version. Using the "arch" command possibly allows to force starting in 32 bits (see man arch). The JackPilot and JackRouter binaries are now also released as 32/64 bits versions for PPC and Intel machines. By default the JackPilot application will start in 32 bits mode (even on a 64 bits machine) and launch the 32 bits jackdmp. Unchecking the "Launch in 32 bits mode" box in the JackPilot info (GetInfo = %I in the Finder...) allows to start JackPilot in 64 bits then launch the 64 bits jackdmp version. Very few audio applications are already 64 bits aware: Apple AU Lab (included in Developer tools) can be launched in 64 bit, here again by unchecking the "Launch in 32 bits mode" box in the AU Lab info. | ||||
WARNING !! WARNING !! | |||||
Users of the "official" JackOSX package (found at www.jackosx.com) MUST uninstall JackOSX (using the script located in /Applications/Jack) before installing and testing jackdmp. The "official" JackOSX package can then be re-installed by using the JackOSX installer again. | |||||
JackOSX package (found at www.jackosx.com) is the preferred way to Jackdmp on OSX. | |||||
--------------------------------- | --------------------------------- | ||||
Mac Intel special considerations | Mac Intel special considerations | ||||
--------------------------------- | --------------------------------- | ||||
- New Mac Intel use 2 different coreaudio device for input/output. Jackdmp cannot directly handle 2 devices to do duplex processing. An "aggregate" device has to be built in this case. | |||||
- New Mac Intel use 2 different CoreAudio device for input/output. Jackdmp cannot directly handle 2 devices to do duplex processing. An "aggregate" device has to be built in this case. | |||||
Use the "/Applications/Utilities/Audio MIDI Setup" tool to build and aggregate device that combine both input and output in a single duplex device, then select it when launching jackdmp, with something like : | Use the "/Applications/Utilities/Audio MIDI Setup" tool to build and aggregate device that combine both input and output in a single duplex device, then select it when launching jackdmp, with something like : | ||||
jackdmp -R -d coreaudio -n "~:Aggregate:0" | jackdmp -R -d coreaudio -n "~:Aggregate:0" | ||||
or directly with the JackPilot tool. | |||||
or directly with the JackPilot tool. | |||||
Starting from 1.9.6 version, the CoreAudio diver can now dynamically aggregate devices. So using "Audio MIDI Setup" tool is not mandatory anymore. | |||||
- CoreAudio applications running under Rosetta emulator cannot access an Intel version of Jackdmp. | - CoreAudio applications running under Rosetta emulator cannot access an Intel version of Jackdmp. | ||||
Using Jackdmp with Qjackctl : | |||||
Using jackdmp with QjackCtl : | |||||
To start jackdmp server in Qjackctl, the complete server path has to be added, like /usr/local/bin/jackdmp in Setup/Server Path. | |||||
To start jackdmp server in QjackCtl, the complete server path has to be added, like /usr/local/bin/jackdmp in Setup/Server Path. | |||||
---------------- | ---------------- | ||||
Windows version | Windows version | ||||
@@ -124,7 +118,9 @@ The binary elements are : | |||||
- jack_dummy.dll : the "dummy" driver. | - jack_dummy.dll : the "dummy" driver. | ||||
- jack_net.dll : the NetJack driver. | |||||
- jack_net.dll : the NetJack2 driver. | |||||
- jack_netone.dll : the NetJack1 driver. | |||||
- netmanager.dll : the "in server" client NetJack Manager. | - netmanager.dll : the "in server" client NetJack Manager. | ||||
@@ -132,13 +128,13 @@ The binary elements are : | |||||
- netadapter.dll : the network to audio card adapter (to be used on a slave machine started with an audio driver). | - netadapter.dll : the network to audio card adapter (to be used on a slave machine started with an audio driver). | ||||
- jack_connect.exe, jack_disconnect.exe, jack_lsp.exe, jack_metro.exe, jack_load.exe, jack_unload.exe tools. | |||||
- jack_connect.exe, jack_disconnect.exe, jack_lsp.exe, jack_metro.exe, jack_load.exe, jack_unload.exe, jack_netsource.exe tools. | |||||
- JackRouter.dll : an ASIO/JACK driver that allows ASIO compatible applications to become JACK clients and access the JACK server. ASIO "jackified" applications appear with their names. Ableton Live, Samplitude, Reason, Arturia applications have been successfully tested. To install it, use "regsvr32 JackRouter.dll" in a terminal (use regsvr32 /u JackRouter.dll to uninstall). [VISTA special note: regsvr32 has to be used with "administrator" priviledges to properly register JackRouter.dll (Start Menu -> All Programs -> Accessories -> Right Click on Command Prompt -> Run As Administrator)]. A JackRouter.ini file is used by the driver to read parameters : an [IO] section allows to setup the number of input/output jack ports for the application and a [AUTO_CONNECT] section allows to setup jack ports autoconnection mode to machine input/output. | |||||
- JackRouter.dll : an ASIO/JACK driver that allows ASIO compatible applications to become JACK clients and access the JACK server. ASIO "jackified" applications appear with their names. Ableton Live, Samplitude, Reason, Arturia applications have been successfully tested. To install it, use "regsvr32 JackRouter.dll" in a terminal (use regsvr32 /u JackRouter.dll to uninstall). [VISTA special note: regsvr32 has to be used with "administrator" rights to properly register JackRouter.dll (Start Menu -> All Programs -> Accessories -> Right Click on Command Prompt -> Run As Administrator)]. A JackRouter.ini file is used by the driver to read parameters : an [IO] section allows to setup the number of input/output jack ports for the application and a [AUTO_CONNECT] section allows to setup jack ports auto connection mode to machine input/output. | |||||
WARNING !! WARNING !! | WARNING !! WARNING !! | ||||
Depending of the used interface and driver settings, the PortAudio layer may add additionnal buffering between the real card interrupt and the jack server callback. This usually result in *unregular* calls of the jack server callback (for example if jack server used a 256 frames buffer and the card used a 512 frames, the jack server callback will be called twice every card interrupt). For proper functionning of jack server and clients in this case, the jack server has to be started in "synchronous" mode, using the "-S" parameter. | |||||
Depending of the used interface and driver settings, the PortAudio layer may add additional buffering between the real card interrupt and the jack server callback. This usually result in *unregular* calls of the jack server callback (for example if jack server used a 256 frames buffer and the card used a 512 frames, the jack server callback will be called twice every card interrupt). For proper functioning of jack server and clients in this case, the jack server has to be started in "synchronous" mode, using the "-S" parameter. | |||||
---------------------------- | ---------------------------- | ||||
Known problems, limitations | Known problems, limitations | ||||
@@ -150,7 +146,7 @@ Known problems, limitations | |||||
Automatic server launch | Automatic server launch | ||||
---------------------------- | ---------------------------- | ||||
Starting from the 0.64 version, automatic server launch from client is implemented : when the server is not yet running, and if the client uses the "jack_client_open" API, the server will be started automatically. The server configuration is saved in a ".jackdrc" file located in the user home folder. The Qjackctl tool allows to save its configuration in this . jackdrc (setting can be done in Qjackctl Setup/Misc). If no configuration file is found, a default setup will be used. | |||||
Starting from the 0.64 version, automatic server launch from client is implemented : when the server is not yet running, QjackCtl if the client uses the "jack_client_open" API, the server will be started automatically. The server configuration is saved in a ".jackdrc" file located in the user home folder. The QjackCtl tool allows to save its configuration in this .jackdrc (setting can be done in QjackCtl Setup/Misc). If no configuration file is found, a default setup will be used. | |||||
WARNING : automatic server launch is not implemented on Windows | WARNING : automatic server launch is not implemented on Windows | ||||
@@ -158,7 +154,7 @@ WARNING : automatic server launch is not implemented on Windows | |||||
Validations tools | Validations tools | ||||
------------------ | ------------------ | ||||
jackdmp can possibly validate client applications by checking they are using the API in a correct manner (calling functions in the right order, correctly desallocating ressources....) and produce a log file. A JACK_CLIENT_DEBUG environment variable must be used to activate client validation : use "export JACK_CLIENT_DEBUG=on". | |||||
jackdmp can possibly validate client applications by checking they are using the API in a correct manner (calling functions in the right order, correctly deallocating resources....) and produce a log file. A JACK_CLIENT_DEBUG environment variable must be used to activate client validation : use "export JACK_CLIENT_DEBUG=on". | |||||
-------------- | -------------- | ||||
Documentation | Documentation | ||||
@@ -182,7 +178,7 @@ Note : To experiment with the -S option, jackdmp must be launched in a console. | |||||
0.42 : Patch from Nick Mainsbridge. Correct default mode for ALSA driver. Correct XCode project. | 0.42 : Patch from Nick Mainsbridge. Correct default mode for ALSA driver. Correct XCode project. | ||||
0.43 : Correct freewheel mode. Optimize ALSA and coreaudio drivers. Correct OSX installation script. | 0.43 : Correct freewheel mode. Optimize ALSA and coreaudio drivers. Correct OSX installation script. | ||||
0.44 : Patch from Dmitry Daikov : use clock_gettime by default for timing. Correct dirty buffer issue in CoreAudio driver. Updated doc. | 0.44 : Patch from Dmitry Daikov : use clock_gettime by default for timing. Correct dirty buffer issue in CoreAudio driver. Updated doc. | ||||
0.45 : Script to remove the OSX binary stuff. Correct an export symbol issue that was preventing Qjacktcl to work on OSX. Fix the consequences of the asynchronous semantic of connections/disconnections. | |||||
0.45 : Script to remove the OSX binary stuff. Correct an export symbol issue that was preventing QjackCtl to work on OSX. Fix the consequences of the asynchronous semantic of connections/disconnections. | |||||
0.46 : Fix a bug in loop management. Fix a bug in driver loading/unloading code. Internal code cleanup for better 64 bits architecture support. Compilation on OSX/Intel. Add the -d option for coreaudio driver (display CoreAudio devices internal name). | 0.46 : Fix a bug in loop management. Fix a bug in driver loading/unloading code. Internal code cleanup for better 64 bits architecture support. Compilation on OSX/Intel. Add the -d option for coreaudio driver (display CoreAudio devices internal name). | ||||
0.47 : More fix for 64 bits compilation. Correct ALSA driver. Create a specific folder for jackdmp drivers. Use /dev/shm as default for fifo and sockets. "Install" and "Remove" script for smoother use with regular jack. | 0.47 : More fix for 64 bits compilation. Correct ALSA driver. Create a specific folder for jackdmp drivers. Use /dev/shm as default for fifo and sockets. "Install" and "Remove" script for smoother use with regular jack. | ||||
0.48 : Finish software monitoring implementation for ALSA and CoreAudio drivers. Simpler shared library management on OSX. | 0.48 : Finish software monitoring implementation for ALSA and CoreAudio drivers. Simpler shared library management on OSX. | ||||
@@ -199,25 +195,26 @@ Note : To experiment with the -S option, jackdmp must be launched in a console. | |||||
0.59 : Various fixes in Windows version. Signal handling in the Windows server. Improved JackRouter ASIO/Jack bridge on Windows. Rename global "verbose" in "jack_verbose" to avoid symbol clash with PureData. Add a new cpu testing/loading client. Correct server SetBufferSize in case of failure. Correct PortAudio driver help. Use -D to setup ADDON_DIR on OSX and Linux. Synchronize ALSA backend with jack one. | 0.59 : Various fixes in Windows version. Signal handling in the Windows server. Improved JackRouter ASIO/Jack bridge on Windows. Rename global "verbose" in "jack_verbose" to avoid symbol clash with PureData. Add a new cpu testing/loading client. Correct server SetBufferSize in case of failure. Correct PortAudio driver help. Use -D to setup ADDON_DIR on OSX and Linux. Synchronize ALSA backend with jack one. | ||||
0.60 : Improve audio driver synchronous code to better handle possible time-out cases. Correct JackWinEnvent::Allocate (handle the ERROR_ALREADY_EXISTS case). Correct JackEngine::ClientExternalNew. | 0.60 : Improve audio driver synchronous code to better handle possible time-out cases. Correct JackWinEnvent::Allocate (handle the ERROR_ALREADY_EXISTS case). Correct JackEngine::ClientExternalNew. | ||||
0.61 : Tom Szilagyi memory leak fix in ringbuffer.c. Move client refnum management in JackEngine. Shared_ports renamed to shared_graph. Add call to the init callback (set up using the jack_set_thread_init_callback API) in Real-Time and Notification threads. Define a new 'kActivateClient' notification. New server/client data transfer model to fix a 64 bits system bug. Fix a device name reversal bug in ALSA driver. Implement thread.h API. | 0.61 : Tom Szilagyi memory leak fix in ringbuffer.c. Move client refnum management in JackEngine. Shared_ports renamed to shared_graph. Add call to the init callback (set up using the jack_set_thread_init_callback API) in Real-Time and Notification threads. Define a new 'kActivateClient' notification. New server/client data transfer model to fix a 64 bits system bug. Fix a device name reversal bug in ALSA driver. Implement thread.h API. | ||||
0.62 : More client debug code : check if the client is still valid in every JackDebugClient method, check if the library context is still valid in every API call. Uses a time out value of 10 sec in freewheel mode (like jack). More robust activation/deactivation code, especially in case of client crash. New LockAllMemory and UnlockAllMemory functions. Use pthread_attr_setstacksize in JackPosixThread class. Add Pieter Palmers FreeBob driver. Thibault LeMeur ALSA driver patch. Thom Johansen fix for port buffer alignment issues. Better error checking in PortAudio driver. | |||||
0.62 : More client debug code : check if the client is still valid in every JackDebugClient method, check if the library context is still valid in every API call. Uses a time out value of 10 sec in freewheel mode (like jack). More robust activation/deactivation code, especially in case of client crash. New LockAllMemory and UnlockAllMemory functions. Use pthread_attr_setstacksize in JackPosixThread class. Add Pieter Palmers FreeBob driver. Thibault LeMeur ALSA driver patch. Thom Johansen fix for port buffer alignment issues. Better error checking in PortAudio driver. | |||||
0.63 : Correct back JackAlsaDriver::Read method. Dmitry Baikov patch for JackGraphManager.cpp. Merge JackGraphManager Remove and Release method in a unique Release method. Dmitry Baikov jackmp-time patch : add jack_get_time, jack_time_to_frames, jack_frames_to_time. Add missing -D__SMP__in OSX project. Add new jack_port_set_alias, jack_port_unset_alias and jack_port_get_aliases API. Steven Chamberlain patch to fix jack_port_by_id export. Steven Chamberlain patch to fix jack_port_type. Test for jack_port_type behaviour in jack_test.cpp tool. Add jack_set_client_registration_callback API. Add "callback exiting" and "jack_frame_time" tests in jack_test. | 0.63 : Correct back JackAlsaDriver::Read method. Dmitry Baikov patch for JackGraphManager.cpp. Merge JackGraphManager Remove and Release method in a unique Release method. Dmitry Baikov jackmp-time patch : add jack_get_time, jack_time_to_frames, jack_frames_to_time. Add missing -D__SMP__in OSX project. Add new jack_port_set_alias, jack_port_unset_alias and jack_port_get_aliases API. Steven Chamberlain patch to fix jack_port_by_id export. Steven Chamberlain patch to fix jack_port_type. Test for jack_port_type behaviour in jack_test.cpp tool. Add jack_set_client_registration_callback API. Add "callback exiting" and "jack_frame_time" tests in jack_test. | ||||
0.64 : Checking in the server to avoid calling the clients if no callback are registered. Correct deprecated jack_set_sample_rate_callback to return 0 instead of -1. Dmitry Baikov buffer size patch. Correct notification for kActivateClient event. Correct JackEngine::ClientCloseAux (when called from JackEngine::ClientExternalOpen). Correct JackWinEvent::Allocate. Automatic client renaming. Add "systemic" latencies management in CoreAudio driver. Automatic server launch. Removes unneeded 'volatile' for JackTransportEngine::fWriteCounter. | 0.64 : Checking in the server to avoid calling the clients if no callback are registered. Correct deprecated jack_set_sample_rate_callback to return 0 instead of -1. Dmitry Baikov buffer size patch. Correct notification for kActivateClient event. Correct JackEngine::ClientCloseAux (when called from JackEngine::ClientExternalOpen). Correct JackWinEvent::Allocate. Automatic client renaming. Add "systemic" latencies management in CoreAudio driver. Automatic server launch. Removes unneeded 'volatile' for JackTransportEngine::fWriteCounter. | ||||
0.65 : Fix backend port alias management (renaming in system:xxx). Fix a bug in JackLibClient::Open introduced when adding automatic client renaming. Fix a bug in jack_test. Correct JackShmMem destructor. Correct end case in JackClient::Execute. Correct JackMachSemaphore::Disconnect. Implement server temporary (-T) mode. Make "Rename" a method of JackPort class, call it from driver Attach method. Server/library protocol checking implementation. | 0.65 : Fix backend port alias management (renaming in system:xxx). Fix a bug in JackLibClient::Open introduced when adding automatic client renaming. Fix a bug in jack_test. Correct JackShmMem destructor. Correct end case in JackClient::Execute. Correct JackMachSemaphore::Disconnect. Implement server temporary (-T) mode. Make "Rename" a method of JackPort class, call it from driver Attach method. Server/library protocol checking implementation. | ||||
0.66 : Internal cleanup. Windows JackRouter.dll version 0.16 : use of "jack_client_open" API to allow automatic client renaming, better Windows VISTA support, new JackRouter.ini file. | 0.66 : Internal cleanup. Windows JackRouter.dll version 0.16 : use of "jack_client_open" API to allow automatic client renaming, better Windows VISTA support, new JackRouter.ini file. | ||||
0.67 : Correct jack_client_open "status" management. Rename server_name from "default" to "jackdmp_default" to avoid conflict with regular jackd server. Fix a resource leak issue in JackCoreAudioDriver::Close(). Better implement "jack_client_open" when linking a client with the server library. Correct "jack_register_server" in shm.c. Add missing timestamps.c and timestamps.h files. Correctly export public headers in OSX frameworks. Suppress JackEngine::ClientInternalCloseIm method. Use .jackdrc file (instead of .jackdmprc). Install script now creates a link "jackd ==> jackdmp" so that automatic launch can work correctly. Paul Davis patch for -r (--replace-registry) feature. Internal loadable client implementation. Fix JackEngine::Close() method. Windows JackRouter.dll version 0.17: 32 integer sample format. | 0.67 : Correct jack_client_open "status" management. Rename server_name from "default" to "jackdmp_default" to avoid conflict with regular jackd server. Fix a resource leak issue in JackCoreAudioDriver::Close(). Better implement "jack_client_open" when linking a client with the server library. Correct "jack_register_server" in shm.c. Add missing timestamps.c and timestamps.h files. Correctly export public headers in OSX frameworks. Suppress JackEngine::ClientInternalCloseIm method. Use .jackdrc file (instead of .jackdmprc). Install script now creates a link "jackd ==> jackdmp" so that automatic launch can work correctly. Paul Davis patch for -r (--replace-registry) feature. Internal loadable client implementation. Fix JackEngine::Close() method. Windows JackRouter.dll version 0.17: 32 integer sample format. | ||||
0.68 : Internal loadable client implementation, winpipe version added. Reorganize jack headers. Improve Linux install/remove scripts. Use LIB_DIR variable for 64 bits related compilation (drivers location). More generic Linux script. Correct jack_acquire_real_time_scheduling on OSX. Merge of Dmitry Baikov MIDI branch. Correct JackGraphManager::GetPortsAux to use port type. Remove JackEngineTiming class: code moved in JackEngineControl. Add midiseq and midisine examples. Cleanup old zombification code. Linux Makefile now install jack headers. Use of JACK_CLIENT_DEBUG environment variable to activate debug client mode. Definition of JACK_LOCATION variable using -D in the Makefile. Restore jack 0.103.0 MIDI API version. Fix a bug in freewheel management in async mode: drivers now receive the kStartFreewheelCallback and kStopFreewheelCallback notifications. Server and user directory related code moved in a JackTools file. Client name rewritting to remove path characters (used in fifo naming). Correct ALSA driver Attach method: internal driver may have changed the buffer_size and sample_rate values. Add JackWinSemaphore class. Add an implementation for obsolete jack_internal_client_new and jack_internal_client_close. Add missing jack_port_type_size. Use of JackWinSemaphore instead of JackWinEvent for inter-process synchronization. Correct types.h for use with MINGW on Windows. Move OSX start/stop notification mechanism in Jackdmp.cpp. Correct CheckPort in JackAPI.cpp. | |||||
0.68 : Internal loadable client implementation, winpipe version added. Reorganize jack headers. Improve Linux install/remove scripts. Use LIB_DIR variable for 64 bits related compilation (drivers location). More generic Linux script. Correct jack_acquire_real_time_scheduling on OSX. Merge of Dmitry Baikov MIDI branch. Correct JackGraphManager::GetPortsAux to use port type. Remove JackEngineTiming class: code moved in JackEngineControl. Add midiseq and midisine examples. Cleanup old zombification code. Linux Makefile now install jack headers. Use of JACK_CLIENT_DEBUG environment variable to activate debug client mode. Definition of JACK_LOCATION variable using -D in the Makefile. Restore jack 0.103.0 MIDI API version. Fix a bug in freewheel management in async mode: drivers now receive the kStartFreewheelCallback and kStopFreewheelCallback notifications. Server and user directory related code moved in a JackTools file. Client name rewriting to remove path characters (used in fifo naming). Correct ALSA driver Attach method: internal driver may have changed the buffer_size and sample_rate values. Add JackWinSemaphore class. Add an implementation for obsolete jack_internal_client_new and jack_internal_client_close. Add missing jack_port_type_size. Use of JackWinSemaphore instead of JackWinEvent for inter-process synchronization. Correct types.h for use with MINGW on Windows. Move OSX start/stop notification mechanism in Jackdmp.cpp. Correct CheckPort in JackAPI.cpp. | |||||
0.69 : On OSX, use CFNotificationCenterPostNotificationWithOptions with kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions for server ==> JackRouter plugin notification. On OSX, use jack server name in notification system. Correct fPeriodUsecs computation in JackAudioDriver::SetBufferSize and JackAudioDriver::SetSampleRate. Correct JackMachNotifyChannel::ClientNotify. Correct bug in CoreAudio driver sample rate management. Add a sample_rate change listener in CoreAudio driver. Correct sample_rate management in JackCoreAudioDriver::Open. Better handling in sample_rate change listener. Pieter Palmers FFADO driver and scons based build. Pieter Palmers second new build system: scons and Makefile based build. Tim Blechmann scons patch. Change string management for proper compilation with gcc 4.2.2. JackLog cleanup. Cleanup in CoreAudio driver. Tim Blechmann patch for JackGraphManager::GetPortsAux memory leak, Tim Blechmann patch for scons install. Dmitry Baikov MIDI patch : alsa_seqmidi and alsa_rammidi drivers. CoreAudio driver improvement : detect and notify abnormal situations (stopped driver in case of SR change...). | 0.69 : On OSX, use CFNotificationCenterPostNotificationWithOptions with kCFNotificationDeliverImmediately | kCFNotificationPostToAllSessions for server ==> JackRouter plugin notification. On OSX, use jack server name in notification system. Correct fPeriodUsecs computation in JackAudioDriver::SetBufferSize and JackAudioDriver::SetSampleRate. Correct JackMachNotifyChannel::ClientNotify. Correct bug in CoreAudio driver sample rate management. Add a sample_rate change listener in CoreAudio driver. Correct sample_rate management in JackCoreAudioDriver::Open. Better handling in sample_rate change listener. Pieter Palmers FFADO driver and scons based build. Pieter Palmers second new build system: scons and Makefile based build. Tim Blechmann scons patch. Change string management for proper compilation with gcc 4.2.2. JackLog cleanup. Cleanup in CoreAudio driver. Tim Blechmann patch for JackGraphManager::GetPortsAux memory leak, Tim Blechmann patch for scons install. Dmitry Baikov MIDI patch : alsa_seqmidi and alsa_rammidi drivers. CoreAudio driver improvement : detect and notify abnormal situations (stopped driver in case of SR change...). | ||||
0.70 : Updated API to match jack 0.109.0 version. Update in usx2y.c and JackPort.cpp to match jackd 0.109.2. Latest jack_lsp code from jack SVN. Add jack_mp_thread_wait client example. Add jack_thread_wait client example. Remove checking thread in CoreAudio driver, better device state change recovery strategy: the driver is stopped and restarted. Move transport related methods from JackEngine to JackServer. Tim Blechmann sse optimization patch for JackaudioPort::MixAudioBuffer, use of Apple Accelerate framework on OSX. Remove use of assert in JackFifo, JackMachSemaphore, and JackPosixSemaphore: print an error instead. Correct "server_connect": close the communication channel. More robust external API. Use SetAlias for port naming. Use jackd midi port naming scheme. Notify ports unregistration in JackEngine::ClientCloseAux. Fix in JackClient::Error(): when RT thread is failing and calling Shutdown, Shutdown was not desactivating the client correctly. | 0.70 : Updated API to match jack 0.109.0 version. Update in usx2y.c and JackPort.cpp to match jackd 0.109.2. Latest jack_lsp code from jack SVN. Add jack_mp_thread_wait client example. Add jack_thread_wait client example. Remove checking thread in CoreAudio driver, better device state change recovery strategy: the driver is stopped and restarted. Move transport related methods from JackEngine to JackServer. Tim Blechmann sse optimization patch for JackaudioPort::MixAudioBuffer, use of Apple Accelerate framework on OSX. Remove use of assert in JackFifo, JackMachSemaphore, and JackPosixSemaphore: print an error instead. Correct "server_connect": close the communication channel. More robust external API. Use SetAlias for port naming. Use jackd midi port naming scheme. Notify ports unregistration in JackEngine::ClientCloseAux. Fix in JackClient::Error(): when RT thread is failing and calling Shutdown, Shutdown was not desactivating the client correctly. | ||||
0.71 : Add port register/unregister notification in JackAlsaDriver. Correct JACK_port_unregister in MIDI backend. Add TimeCallback in JackDebugClient class. Correct jack_get_time propotype. Correct JackSocketClientChannel::ClientClose to use ServerSyncCall instead of ServerAsyncCall. Better documentation in jack.h. libjackdmp.so renamed to libjackservermp.so and same for OSX framework. Define an internal jack_client_open_aux needed for library wrapper feature. Remove unneeded jack_port_connect API. Correct jack_port_get_connections function (should return NULL when no connections). In thread model, execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished). Fix engine real-time notification (was broken since ??). Implements wrapper layer. Correct jack_port_get_total_latency. Correct all backend playback port latency in case of "asynchronous" mode (1 buffer more). Add test for jack_cycle_wait, jack_cycle_wait and jack_set_process_thread API. RT scheduling for OSX thread (when used in dummy driver). Add -L (extra output latency in aynchronous mode) in CoreAudio driver. New JackLockedEngine decorator class to serialize access from ALSA Midi thread, command thread and in-server clients. Use engine in JackAlsaDriver::port_register and JackAlsaDriver::port_unregister. Fix connect notification to deliver *one* notification only. Correct JackClient::Activate so that first kGraphOrderCallback can be received by the client notification thread. New jack_server_control client to test notifications when linked to the server library. Synchronise transport.h with latest jackd version (Video handling). Transport timebase fix. Dmitry Baikov patch for alsa_rawmidi driver. Pieter Palmers patch for FFADO driver. Add an Init method for blocking drivers to be decorated using JackThreadedDriver class. Correct PortRegister, port name checking must be done on server side. Correct a missing parameter in the usage message of jack_midiseq. New SetNonBlocking method for JackSocket. Correct a dirty port array issue in JackGraphManager::GetPortsAux. | 0.71 : Add port register/unregister notification in JackAlsaDriver. Correct JACK_port_unregister in MIDI backend. Add TimeCallback in JackDebugClient class. Correct jack_get_time propotype. Correct JackSocketClientChannel::ClientClose to use ServerSyncCall instead of ServerAsyncCall. Better documentation in jack.h. libjackdmp.so renamed to libjackservermp.so and same for OSX framework. Define an internal jack_client_open_aux needed for library wrapper feature. Remove unneeded jack_port_connect API. Correct jack_port_get_connections function (should return NULL when no connections). In thread model, execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished). Fix engine real-time notification (was broken since ??). Implements wrapper layer. Correct jack_port_get_total_latency. Correct all backend playback port latency in case of "asynchronous" mode (1 buffer more). Add test for jack_cycle_wait, jack_cycle_wait and jack_set_process_thread API. RT scheduling for OSX thread (when used in dummy driver). Add -L (extra output latency in aynchronous mode) in CoreAudio driver. New JackLockedEngine decorator class to serialize access from ALSA Midi thread, command thread and in-server clients. Use engine in JackAlsaDriver::port_register and JackAlsaDriver::port_unregister. Fix connect notification to deliver *one* notification only. Correct JackClient::Activate so that first kGraphOrderCallback can be received by the client notification thread. New jack_server_control client to test notifications when linked to the server library. Synchronise transport.h with latest jackd version (Video handling). Transport timebase fix. Dmitry Baikov patch for alsa_rawmidi driver. Pieter Palmers patch for FFADO driver. Add an Init method for blocking drivers to be decorated using JackThreadedDriver class. Correct PortRegister, port name checking must be done on server side. Correct a missing parameter in the usage message of jack_midiseq. New SetNonBlocking method for JackSocket. Correct a dirty port array issue in JackGraphManager::GetPortsAux. | ||||
1.9.0 : Waf based build system : Nedko Arnaudov, Grame for preliminary OSX support. Control API, dbus based server control access : Nedko Arnaudov, Grame. NetJack2 components (in progress) : jack_net backend, netmanager, audioadapter, netadapter : Romain Moret, Grame. Code restructuring to help port on other architectures : Michael Voigt. Code cleanup/optimization : Tim Blechmann. Improve handling of server internal clients that can now be loaded/unloaded using the new server control API : Grame. A lot of bug fix and improvements. | 1.9.0 : Waf based build system : Nedko Arnaudov, Grame for preliminary OSX support. Control API, dbus based server control access : Nedko Arnaudov, Grame. NetJack2 components (in progress) : jack_net backend, netmanager, audioadapter, netadapter : Romain Moret, Grame. Code restructuring to help port on other architectures : Michael Voigt. Code cleanup/optimization : Tim Blechmann. Improve handling of server internal clients that can now be loaded/unloaded using the new server control API : Grame. A lot of bug fix and improvements. | ||||
1.9.1 : Fix jackctl_server_unload_internal. Filter SIGPIPE to avoid having client get a SIGPIPE when trying to access a died server. Libjack shutdown handler does not "deactivate" (fActive = false) the client anymore, so that jack_deactivate correctly does the job later on. Better isolation of server and clients system resources to allow starting the server in several user account at the same time. Report ringbuffer.c fixes from jack1. Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown). Use JACK_DRIVER_DIR variable in internal clients loader. For ALSA driver, synchronize with latest jack1 memops functions. Synchronize jack2 public headers with jack1 ones. Implement jack_client_real_time_priority and jack_client_max_real_time_priority API. Use up to BUFFER_SIZE_MAX frames in midi ports, fix for ticket #117. Cleanup server starting code for clients directly linked with libjackserver.so. JackMessageBuffer was using thread "Stop" scheme in destructor, now use the safer thread "Kill" way. Synchronize ALSA backend code with JACK1 one. Set default mode to 'slow' in JackNetDriver and JackNetAdapter. Simplify audio packet order verification. Fix JackNetInterface::SetNetBufferSize for socket buffer size computation and JackNetMasterInterface::DataRecv if synch packet is received, various cleanup. Better recovery of network overload situations, now "resynchronize" by skipping cycles.". Support for BIG_ENDIAN machines in NetJack2. Support for BIG_ENDIAN machines in NetJack2 for MIDI ports. Support for "-h" option in internal clients to print the parameters. In NetJack2, fix a bug when capture or playback only channels are used. Add a JACK_INTERNAL_DIR environment variable to be used for internal clients. Add a resample quality parameter in audioadapter. Now correctly return an error if JackServer::SetBufferSize could not change the buffer size (and was just restoring the current one). Use PRIu32 kind of macro in JackAlsaDriver again. Add a resample quality parameter in netadapter. | |||||
1.9.1 : Fix jackctl_server_unload_internal. Filter SIGPIPE to avoid having client get a SIGPIPE when trying to access a died server. Libjack shutdown handler does not "deactivate" (fActive = false) the client anymore, so that jack_deactivate correctly does the job later on. Better isolation of server and clients system resources to allow starting the server in several user account at the same time. Report ringbuffer.c fixes from JACK1. Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown). Use JACK_DRIVER_DIR variable in internal clients loader. For ALSA driver, synchronize with latest JACK1 memops functions. Synchronize JACK2 public headers with JACK1 ones. Implement jack_client_real_time_priority and jack_client_max_real_time_priority API. Use up to BUFFER_SIZE_MAX frames in midi ports, fix for ticket #117. Cleanup server starting code for clients directly linked with libjackserver.so. JackMessageBuffer was using thread "Stop" scheme in destructor, now use the safer thread "Kill" way. Synchronize ALSA backend code with JACK1 one. Set default mode to 'slow' in JackNetDriver and JackNetAdapter. Simplify audio packet order verification. Fix JackNetInterface::SetNetBufferSize for socket buffer size computation and JackNetMasterInterface::DataRecv if synch packet is received, various cleanup. Better recovery of network overload situations, now "resynchronize" by skipping cycles.". Support for BIG_ENDIAN machines in NetJack2. Support for BIG_ENDIAN machines in NetJack2 for MIDI ports. Support for "-h" option in internal clients to print the parameters. In NetJack2, fix a bug when capture or playback only channels are used. Add a JACK_INTERNAL_DIR environment variable to be used for internal clients. Add a resample quality parameter in audioadapter. Now correctly return an error if JackServer::SetBufferSize could not change the buffer size (and was just restoring the current one). Use PRIu32 kind of macro in JackAlsaDriver again. Add a resample quality parameter in netadapter. | |||||
1.9.2 : Solaris version. New "profiling" tools. Rework the mutex/signal classes. Support for BIG_ENDIAN machines in NetJack2. D-BUS based device reservation to better coexist with PulseAudio on Linux. Add auto_connect parameter in netmanager and netadapter. Use Torben Hohn PI controler code for adapters. Client incorrect re-naming fixed : now done at socket and fifo level. Virtualize and allow overriding of thread creation function, to allow Wine support (from JACK1). | 1.9.2 : Solaris version. New "profiling" tools. Rework the mutex/signal classes. Support for BIG_ENDIAN machines in NetJack2. D-BUS based device reservation to better coexist with PulseAudio on Linux. Add auto_connect parameter in netmanager and netadapter. Use Torben Hohn PI controler code for adapters. Client incorrect re-naming fixed : now done at socket and fifo level. Virtualize and allow overriding of thread creation function, to allow Wine support (from JACK1). | ||||
1.9.3 : New JackBoomerDriver class for Boomer driver on Solaris. Add mixed 32/64 bits mode (off by default). Native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver). In ALSA audio card reservation code, tries to open the card even if reservation fails. Clock source setting on Linux. Add jackctl_server_switch_master API. Fix transport callback (timebase master, sync) issue when used after jack_activate (RT thread was not running). D-Bus access for jackctl_server_add_slave/jackctl_server_remove_slave API. Cleanup "loopback" stuff in server. Torben Hohn fix for InitTime and GetMicroSeconds in JackWinTime.c. New jack_free function added in jack.h. Reworked Torben Hohn fix for server restart issue on Windows. Correct jack_set_error_function, jack_set_info_function and jack_set_thread_creator functions. Correct JackFifo::TimedWait for EINTR handling. Move DBus based audio device reservation code in ALSA backend compilation. Correct JackTransportEngine::MakeAllLocating, sync callback has to be called in this case also. NetJack2 code : better error checkout, method renaming. Tim Bechmann patch : hammerfall, only release monitor thread, if it has been created. Tim Bechmann memops.c optimization patches. In combined --dbus and --classic compilation code, use PulseAudio acquire/release code. Big rewrite of Solaris boomer driver, seems to work in duplex mode at least. Loopback backend reborn as a dynamically loadable separated backend. | 1.9.3 : New JackBoomerDriver class for Boomer driver on Solaris. Add mixed 32/64 bits mode (off by default). Native MIDI backend (JackCoreMidiDriver, JackWinMMEDriver). In ALSA audio card reservation code, tries to open the card even if reservation fails. Clock source setting on Linux. Add jackctl_server_switch_master API. Fix transport callback (timebase master, sync) issue when used after jack_activate (RT thread was not running). D-Bus access for jackctl_server_add_slave/jackctl_server_remove_slave API. Cleanup "loopback" stuff in server. Torben Hohn fix for InitTime and GetMicroSeconds in JackWinTime.c. New jack_free function added in jack.h. Reworked Torben Hohn fix for server restart issue on Windows. Correct jack_set_error_function, jack_set_info_function and jack_set_thread_creator functions. Correct JackFifo::TimedWait for EINTR handling. Move DBus based audio device reservation code in ALSA backend compilation. Correct JackTransportEngine::MakeAllLocating, sync callback has to be called in this case also. NetJack2 code : better error checkout, method renaming. Tim Bechmann patch : hammerfall, only release monitor thread, if it has been created. Tim Bechmann memops.c optimization patches. In combined --dbus and --classic compilation code, use PulseAudio acquire/release code. Big rewrite of Solaris boomer driver, seems to work in duplex mode at least. Loopback backend reborn as a dynamically loadable separated backend. | ||||
1.9.4 : Solaris boomer backend now working in capture or playback only mode. Add a -G parameter in CoreAudio backend (the computation value in RT thread expressed as percent of period). Use SNDCTL_DSP_SYNCGROUP/SNDCTL_DSP_SYNCSTART API to synchronize input and output in Solaris boomer backend. Big endian bug fix in memops.c. Fix issues in JackNetDriver::DecodeTransportData and JackNetDriver::Initialize. Correct CPU timing in JackNetDriver, now take cycle begin time after Read. Simplify transport in NetJack2: master only can control transport. Change CoreAudio notification thread setup for OSX Snow Leopard. Correct server temporary mode : now set a global and quit after server/client message handling is finished. Add a string parameter to server ==> client notification, add a new JackInfoShutdownCallback type. CoreAudio backend now issue a JackInfoShutdownCallback when an unrecoverable error is detected (sampling rate change, stream configuration changeÉ). Correct jackdmp.cpp (failures case were not correct..). Improve JackCoreAudioDriver code. Raise default port number to 2048. Correct JackProcessSync::LockedTimedWait. Correct JACK_MESSAGE_SIZE value, particularly in OSX RPC code. Now start server channel thread only when backend has been started (so in JackServer::Start). Should solve race conditions at start time. jack_verbose moved to JackGlobals class. Improve aggregate device management in JackCoreAudioDriver : now a "private" device only and cleanup properly. Aggregate device code added to JackCoreAudioAdapter. Implement "hog mode" (exclusive access of the audio device) in JackCoreAudioDriver. Fix jack_set_sample_rate_callback to have he same behavior as in JACK1. Dynamic system version detection in JackCoreAudioDriver to either create public or private aggregate device. In JackCoreAudioDriver, force the SR value to the wanted one *before* creating aggregate device (otherwise creation will fail). In JackCoreAudioDriver, better cleanup of AD when intermediate open failure. In JackCoreAudioDriver::Start, wait for the audio driver to effectively start (use the MeasureCallback). In JackCoreAudioDriver, improve management of input/output channels: -1 is now used internally to indicate a wanted max value. In JackCoreAudioDriver::OpenAUHAL, correct stream format setup and cleanup. Correct crash bug in JackAudioAdapterInterface when not input is used in adapter (temporary fixÉ). Sync JackCoreAudioAdapter code on JackCoreAudioDriver one. JACK_SCHED_POLICY switched to SCHED_FIFO. Now can aggregate device that are themselves AD. No reason to make jack_on_shutdown deprecated, so revert the incorrect change. Thread AcquireRealTime and DropRealTime were (incorrectly) using fThread field. Use pthread_self()) (or GetCurrentThread() on Windows) to get the calling thread. Correctly save and restore RT mode state in freewheel mode. Correct freewheel code on client side. Fix AcquireRealTime and DropRealTime: now distinguish when called from another thread (AcquireRealTime/DropRealTime) and from the thread itself (AcquireSelfRealTime/DropSelfRealTime). Correct JackPosixThread::StartImp : thread priority setting now done in the RT case only. Correct JackGraphManager::GetBuffer for the "client loop with one connection" case : buffer must be copied. Correct JackInfoShutdownCallback prototype, two new JackClientProcessFailure and JackClientZombie JackStatus code. Correct JackCoreAudio driver when empty strings are given as -C, -P or -d parameter. Better memory allocation error checking on client (library) side. Better memory allocation error checking in ringbuffer.c, weak import improvements. Memory allocation error checking for jack_client_new and jack_client_open (server and client side). Memory allocation error checking in server for RPC. Simplify server temporary mode : now use a JackTemporaryException. Lock/Unlock shared memory segments (to test...). Sync with JACK1 : -r parameter now used for no-realtime, realtime (-R) is now default, usable backend given vie platform. In JackCoreAudio driver, (possibly) clock drift compensation when needed in aggregated devices. In JackCoreAudio driver, clock drift compensation in aggregated devices working. In JackCoreAudio driver, clock drift compensation semantic changed a bit : when on, does not activate if not needed (same clock domain). Sync JackCoreAudioAdapter code with JackCoreAudioDriver. | 1.9.4 : Solaris boomer backend now working in capture or playback only mode. Add a -G parameter in CoreAudio backend (the computation value in RT thread expressed as percent of period). Use SNDCTL_DSP_SYNCGROUP/SNDCTL_DSP_SYNCSTART API to synchronize input and output in Solaris boomer backend. Big endian bug fix in memops.c. Fix issues in JackNetDriver::DecodeTransportData and JackNetDriver::Initialize. Correct CPU timing in JackNetDriver, now take cycle begin time after Read. Simplify transport in NetJack2: master only can control transport. Change CoreAudio notification thread setup for OSX Snow Leopard. Correct server temporary mode : now set a global and quit after server/client message handling is finished. Add a string parameter to server ==> client notification, add a new JackInfoShutdownCallback type. CoreAudio backend now issue a JackInfoShutdownCallback when an unrecoverable error is detected (sampling rate change, stream configuration changeÉ). Correct jackdmp.cpp (failures case were not correct..). Improve JackCoreAudioDriver code. Raise default port number to 2048. Correct JackProcessSync::LockedTimedWait. Correct JACK_MESSAGE_SIZE value, particularly in OSX RPC code. Now start server channel thread only when backend has been started (so in JackServer::Start). Should solve race conditions at start time. jack_verbose moved to JackGlobals class. Improve aggregate device management in JackCoreAudioDriver : now a "private" device only and cleanup properly. Aggregate device code added to JackCoreAudioAdapter. Implement "hog mode" (exclusive access of the audio device) in JackCoreAudioDriver. Fix jack_set_sample_rate_callback to have he same behavior as in JACK1. Dynamic system version detection in JackCoreAudioDriver to either create public or private aggregate device. In JackCoreAudioDriver, force the SR value to the wanted one *before* creating aggregate device (otherwise creation will fail). In JackCoreAudioDriver, better cleanup of AD when intermediate open failure. In JackCoreAudioDriver::Start, wait for the audio driver to effectively start (use the MeasureCallback). In JackCoreAudioDriver, improve management of input/output channels: -1 is now used internally to indicate a wanted max value. In JackCoreAudioDriver::OpenAUHAL, correct stream format setup and cleanup. Correct crash bug in JackAudioAdapterInterface when not input is used in adapter (temporary fixÉ). Sync JackCoreAudioAdapter code on JackCoreAudioDriver one. JACK_SCHED_POLICY switched to SCHED_FIFO. Now can aggregate device that are themselves AD. No reason to make jack_on_shutdown deprecated, so revert the incorrect change. Thread AcquireRealTime and DropRealTime were (incorrectly) using fThread field. Use pthread_self()) (or GetCurrentThread() on Windows) to get the calling thread. Correctly save and restore RT mode state in freewheel mode. Correct freewheel code on client side. Fix AcquireRealTime and DropRealTime: now distinguish when called from another thread (AcquireRealTime/DropRealTime) and from the thread itself (AcquireSelfRealTime/DropSelfRealTime). Correct JackPosixThread::StartImp : thread priority setting now done in the RT case only. Correct JackGraphManager::GetBuffer for the "client loop with one connection" case : buffer must be copied. Correct JackInfoShutdownCallback prototype, two new JackClientProcessFailure and JackClientZombie JackStatus code. Correct JackCoreAudio driver when empty strings are given as -C, -P or -d parameter. Better memory allocation error checking on client (library) side. Better memory allocation error checking in ringbuffer.c, weak import improvements. Memory allocation error checking for jack_client_new and jack_client_open (server and client side). Memory allocation error checking in server for RPC. Simplify server temporary mode : now use a JackTemporaryException. Lock/Unlock shared memory segments (to test...). Sync with JACK1 : -r parameter now used for no-realtime, realtime (-R) is now default, usable backend given vie platform. In JackCoreAudio driver, (possibly) clock drift compensation when needed in aggregated devices. In JackCoreAudio driver, clock drift compensation in aggregated devices working. In JackCoreAudio driver, clock drift compensation semantic changed a bit : when on, does not activate if not needed (same clock domain). Sync JackCoreAudioAdapter code with JackCoreAudioDriver. | ||||
1.9.5 : Dynamic choice of maximum port number. More robust sample rate change handling code in JackCoreAudioDriver. Devin Anderson patch for Jack FFADO driver issues with lost MIDI bytes between periods (and more). Fix port_rename callback : now both old name and new name are given as parameters. Special code in JackCoreAudio driver to handle completely buggy Digidesign CoreAudio user-land driver. Ensure that client-side message buffer thread calls thread_init callback if/when it is set by the client (backport of JACK1 rev 3838). Check dynamic port-max value. Fix JackCoreMidiDriver::ReadProcAux when ring buffer is full (thanks Devin Anderson). Josh Green ALSA driver capture only patch. When threads are cancelled, the exception has to be rethrown. Use a QUIT notification to properly quit the server channel, the server channel thread can then be 'stopped' instead of 'canceled'. Mario Lang alsa_io time calculation overflow patch. Shared memory manager was calling abort in case of fatal error, now return an error in caller. Change JackEngineProfiling and JackAudioAdapterInterface gnuplot scripts to output SVG instead of PDF. | 1.9.5 : Dynamic choice of maximum port number. More robust sample rate change handling code in JackCoreAudioDriver. Devin Anderson patch for Jack FFADO driver issues with lost MIDI bytes between periods (and more). Fix port_rename callback : now both old name and new name are given as parameters. Special code in JackCoreAudio driver to handle completely buggy Digidesign CoreAudio user-land driver. Ensure that client-side message buffer thread calls thread_init callback if/when it is set by the client (backport of JACK1 rev 3838). Check dynamic port-max value. Fix JackCoreMidiDriver::ReadProcAux when ring buffer is full (thanks Devin Anderson). Josh Green ALSA driver capture only patch. When threads are cancelled, the exception has to be rethrown. Use a QUIT notification to properly quit the server channel, the server channel thread can then be 'stopped' instead of 'canceled'. Mario Lang alsa_io time calculation overflow patch. Shared memory manager was calling abort in case of fatal error, now return an error in caller. Change JackEngineProfiling and JackAudioAdapterInterface gnuplot scripts to output SVG instead of PDF. | ||||
1.9.6 : Improve JackCoreAudioDriver and JackCoreAudioAdapter : when no devices are described, takes default input and output and aggregate them.Correct JackGraphManager::DeactivatePort. Correct JackMachServerChannel::Execute : keep running even in error cases. Raise JACK_PROTOCOL_VERSION number. Arnold Krille firewire patch. Raise JACK_DRIVER_PARAM_STRING_MAX and JACK_PARAM_STRING_MAX to 127 otherwise some audio drivers cannot be loaded on OSX. Fix some file header to have library side code use LGPL. On Windows, now use TRE library for regexp (BSD license instead of GPL license). ffado-portname-sync.patch from ticket #163 applied. Remove call to exit in library code. Make jack_connect/jack_disconnect wait for effective port connection/disconnection. Add tests to validate intclient.h API. On Linux, inter-process synchronization primitive switched to POSIX semaphore. In JackCoreAudioDriver, move code called in MeasureCallback to be called once in IO thread. David Garcia Garzon netone patch. Fix from Fernando Lopez-Lezcano for compilation on fc13. Fix JackPosixSemaphore::TimedWait : same behavior as JackPosixSemaphore::Wait regarding EINTR. David Garcia Garzon unused_pkt_buf_field_jack2 netone patch. Arnold Krille firewire snooping patch. Jan Engelhardt patch for get_cycles on SPARC. Adrian Knoth hurd.patch, kfreebsd-fix.patch and alpha_ia64-sigsegv.patch from ticket 177. Adrian Knoth fix for linux cycle.h (ticket 188). In JackCoreAudioDriver, fix an issue when no value is given for input. | 1.9.6 : Improve JackCoreAudioDriver and JackCoreAudioAdapter : when no devices are described, takes default input and output and aggregate them.Correct JackGraphManager::DeactivatePort. Correct JackMachServerChannel::Execute : keep running even in error cases. Raise JACK_PROTOCOL_VERSION number. Arnold Krille firewire patch. Raise JACK_DRIVER_PARAM_STRING_MAX and JACK_PARAM_STRING_MAX to 127 otherwise some audio drivers cannot be loaded on OSX. Fix some file header to have library side code use LGPL. On Windows, now use TRE library for regexp (BSD license instead of GPL license). ffado-portname-sync.patch from ticket #163 applied. Remove call to exit in library code. Make jack_connect/jack_disconnect wait for effective port connection/disconnection. Add tests to validate intclient.h API. On Linux, inter-process synchronization primitive switched to POSIX semaphore. In JackCoreAudioDriver, move code called in MeasureCallback to be called once in IO thread. David Garcia Garzon netone patch. Fix from Fernando Lopez-Lezcano for compilation on fc13. Fix JackPosixSemaphore::TimedWait : same behavior as JackPosixSemaphore::Wait regarding EINTR. David Garcia Garzon unused_pkt_buf_field_jack2 netone patch. Arnold Krille firewire snooping patch. Jan Engelhardt patch for get_cycles on SPARC. Adrian Knoth hurd.patch, kfreebsd-fix.patch and alpha_ia64-sigsegv.patch from ticket 177. Adrian Knoth fix for linux cycle.h (ticket 188). In JackCoreAudioDriver, fix an issue when no value is given for input. | ||||
1.9.7 : Sync JackAlsaDriver::alsa_driver_check_card_type with JACK1 backend. Correct JackServer::Open to avoid a race when control API is used on OSX. Improve backend error handling: fatal error returned by Read/Write now cause a Process failure (so a thread exit for blocking backends). Recoverable ones (XRuns..) are now treated internally in ALSA, FreeBob and FFADO backends. In jackdmp.cpp, jackctl_setup_signals moved before jackctl_server_start. Correct symbols export in backends on OSX. ALSA backend : suspend/resume handling. Correct dummy driver. Adrian Knoth jack_lsp patch. Remove JackPortIsActive flag. New latency API implementation. ComputeTotalLatencies now a client/server call. Add latent test client for latency API. Also print playback and capture latency in jack_lsp. jack_client_has_session_callback implementation. Check requested buffer size and limit to 1..8192 - avoids weird behaviour caused by jack_bufsize foobar. jack_port_type_get_buffer_size implementation. Stop using alloca and allocate buffer on the heap for alsa_io. Rename jdelay to jack_iodelay as per Fons' request. Call buffer size callback in activate (actually this is done on client side in the RT thread Init method). Add jack_midi_dump client. Synchronize net JACK1 with JACK1 version. Synchronize jack_connect/jack_disconnect with JACK1 version. Correct JackNetMaster::SetBufferSize. Use jack_default_audio_sample_t instead of float consistently, fix ticket #201. -X now allows to add several slave backends, add -I to load several internal clients. Rework internal slave driver management, JackServerGlobals now handle same parameters as jackdmp. Correct JackEngine::NotifyGraphReorder, update JackDebugClient with latest API. Devin Anderson server-ctl-proposal branch merged on trunk: improved control API, slave backend reworked. Implement renaming in JackDriver::Open to avoid name collision (thanks Devin Anderson). Correct alsa_driver_restart (thanks Devin Anderson). Correction of jack_connect/jack_disconnect: use of jack_activate and volatile keyword for thread shared variable. Correction of JackNetOneDriver for latest CELT API. Synchronize JackWeakAPI.cpp with new APIs. | |||||
This is a work in progress but the implementation is now stable enough to be tested. jackdmp has been used successfully with the following applications : Ardour, Hydrogen, Jamin, Qjackctl, Jack-Rack, SooperLooper, AlsaPlayer... | |||||
This is a work in progress but the implementation is now stable enough to be tested. jackdmp has been used successfully with the following applications : Ardour, Hydrogen, Jamin, QjackCtl, Jack-Rack, SooperLooper, AlsaPlayer... | |||||
------------------------------------ | ------------------------------------ | ||||
General known problems, limitations | General known problems, limitations | ||||
@@ -225,9 +222,7 @@ General known problems, limitations | |||||
- zombification of clients is not implemented | - zombification of clients is not implemented | ||||
- the number of server audio ports is fixed | |||||
- memory locking is not implemented | |||||
- memory locking is implemented for shared data only | |||||
The package is available at http://www.grame.fr/~letz/jackdmp.html | The package is available at http://www.grame.fr/~letz/jackdmp.html | ||||
@@ -116,7 +116,7 @@ extern "C" | |||||
EXPORT int jack_set_xrun_callback(jack_client_t *, | EXPORT int jack_set_xrun_callback(jack_client_t *, | ||||
JackXRunCallback xrun_callback, void *arg); | JackXRunCallback xrun_callback, void *arg); | ||||
EXPORT int jack_set_latency_callback(jack_client_t *client, | EXPORT int jack_set_latency_callback(jack_client_t *client, | ||||
JackLatencyCallback callback, void *arg); | |||||
JackLatencyCallback latency_callback, void *arg); | |||||
EXPORT int jack_activate(jack_client_t *client); | EXPORT int jack_activate(jack_client_t *client); | ||||
EXPORT int jack_deactivate(jack_client_t *client); | EXPORT int jack_deactivate(jack_client_t *client); | ||||
@@ -36,17 +36,17 @@ namespace Jack | |||||
int JackAudioAdapter::Process (jack_nframes_t frames, void* arg) | int JackAudioAdapter::Process (jack_nframes_t frames, void* arg) | ||||
{ | { | ||||
JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | JackAudioAdapter* adapter = static_cast<JackAudioAdapter*>(arg); | ||||
float* inputBuffer[adapter->fAudioAdapter->GetInputs()]; | |||||
float* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; | |||||
jack_default_audio_sample_t* inputBuffer[adapter->fAudioAdapter->GetInputs()]; | |||||
jack_default_audio_sample_t* outputBuffer[adapter->fAudioAdapter->GetOutputs()]; | |||||
// Always clear output | // Always clear output | ||||
for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | for (int i = 0; i < adapter->fAudioAdapter->GetInputs(); i++) { | ||||
inputBuffer[i] = (float*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); | |||||
memset(inputBuffer[i], 0, frames * sizeof(float)); | |||||
inputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fCapturePortList[i], frames); | |||||
memset(inputBuffer[i], 0, frames * sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | for (int i = 0; i < adapter->fAudioAdapter->GetOutputs(); i++) { | ||||
outputBuffer[i] = (float*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(adapter->fPlaybackPortList[i], frames); | |||||
} | } | ||||
adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | adapter->fAudioAdapter->PullAndPush(inputBuffer, outputBuffer, frames); | ||||
@@ -88,18 +88,18 @@ namespace Jack | |||||
JackResampler** fCaptureRingBuffer; | JackResampler** fCaptureRingBuffer; | ||||
JackResampler** fPlaybackRingBuffer; | JackResampler** fPlaybackRingBuffer; | ||||
unsigned int fQuality; | unsigned int fQuality; | ||||
unsigned int fRingbufferCurSize; | unsigned int fRingbufferCurSize; | ||||
jack_time_t fPullAndPushTime; | jack_time_t fPullAndPushTime; | ||||
bool fRunning; | bool fRunning; | ||||
bool fAdaptative; | bool fAdaptative; | ||||
void ResetRingBuffers(); | void ResetRingBuffers(); | ||||
void AdaptRingBufferSize(); | void AdaptRingBufferSize(); | ||||
void GrowRingBufferSize(); | void GrowRingBufferSize(); | ||||
public: | public: | ||||
JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE): | JackAudioAdapterInterface ( jack_nframes_t buffer_size, jack_nframes_t sample_rate, jack_nframes_t ring_buffer_size = DEFAULT_ADAPTATIVE_SIZE): | ||||
@@ -140,15 +140,15 @@ namespace Jack | |||||
{} | {} | ||||
virtual void Reset(); | virtual void Reset(); | ||||
virtual void Create(); | virtual void Create(); | ||||
virtual void Destroy(); | virtual void Destroy(); | ||||
virtual int Open() | virtual int Open() | ||||
{ | { | ||||
return 0; | return 0; | ||||
} | } | ||||
virtual int Close() | virtual int Close() | ||||
{ | { | ||||
return 0; | return 0; | ||||
@@ -157,7 +157,7 @@ namespace Jack | |||||
virtual int SetHostBufferSize ( jack_nframes_t buffer_size ) | virtual int SetHostBufferSize ( jack_nframes_t buffer_size ) | ||||
{ | { | ||||
fHostBufferSize = buffer_size; | fHostBufferSize = buffer_size; | ||||
if (fAdaptative) | |||||
if (fAdaptative) | |||||
AdaptRingBufferSize(); | AdaptRingBufferSize(); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -165,7 +165,7 @@ namespace Jack | |||||
virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size ) | virtual int SetAdaptedBufferSize ( jack_nframes_t buffer_size ) | ||||
{ | { | ||||
fAdaptedBufferSize = buffer_size; | fAdaptedBufferSize = buffer_size; | ||||
if (fAdaptative) | |||||
if (fAdaptative) | |||||
AdaptRingBufferSize(); | AdaptRingBufferSize(); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -197,7 +197,7 @@ namespace Jack | |||||
SetAdaptedSampleRate ( sample_rate ); | SetAdaptedSampleRate ( sample_rate ); | ||||
return 0; | return 0; | ||||
} | } | ||||
void SetInputs ( int inputs ) | void SetInputs ( int inputs ) | ||||
{ | { | ||||
jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs ); | jack_log ( "JackAudioAdapterInterface::SetInputs %d", inputs ); | ||||
@@ -222,8 +222,8 @@ namespace Jack | |||||
return fPlaybackChannels; | return fPlaybackChannels; | ||||
} | } | ||||
int PushAndPull(float** inputBuffer, float** outputBuffer, unsigned int frames); | |||||
int PullAndPush(float** inputBuffer, float** outputBuffer, unsigned int frames); | |||||
int PushAndPull(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); | |||||
int PullAndPush(jack_default_audio_sample_t** inputBuffer, jack_default_audio_sample_t** outputBuffer, unsigned int frames); | |||||
}; | }; | ||||
@@ -138,14 +138,13 @@ int JackAudioDriver::Attach() | |||||
// Monitor ports | // Monitor ports | ||||
if (fWithMonitorPorts) { | if (fWithMonitorPorts) { | ||||
jack_log("Create monitor port "); | |||||
jack_log("Create monitor port"); | |||||
snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1); | snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1); | ||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
jack_error("Cannot register monitor port for %s", name); | jack_error("Cannot register monitor port for %s", name); | ||||
return -1; | return -1; | ||||
} else { | } else { | ||||
port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
port->SetAlias(alias); | |||||
range.min = range.max = fEngineControl->fBufferSize; | range.min = range.max = fEngineControl->fBufferSize; | ||||
port->SetLatencyRange(JackCaptureLatency, &range); | port->SetLatencyRange(JackCaptureLatency, &range); | ||||
fMonitorPortList[i] = port_index; | fMonitorPortList[i] = port_index; | ||||
@@ -178,8 +177,8 @@ int JackAudioDriver::Write() | |||||
{ | { | ||||
for (int i = 0; i < fPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels; i++) { | ||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) { | if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) { | ||||
float* buffer = GetOutputBuffer(i); | |||||
int size = sizeof(float) * fEngineControl->fBufferSize; | |||||
jack_default_audio_sample_t* buffer = GetOutputBuffer(i); | |||||
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize; | |||||
// Monitor ports | // Monitor ports | ||||
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) | if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) | ||||
memcpy(GetMonitorBuffer(i), buffer, size); | memcpy(GetMonitorBuffer(i), buffer, size); | ||||
@@ -313,6 +312,26 @@ int JackAudioDriver::ProcessGraphSync() | |||||
return res; | return res; | ||||
} | } | ||||
int JackAudioDriver::Start() | |||||
{ | |||||
int res = JackDriver::Start(); | |||||
if ((res >= 0) && fIsMaster) { | |||||
res = StartSlaves(); | |||||
} | |||||
return res; | |||||
} | |||||
int JackAudioDriver::Stop() | |||||
{ | |||||
int res = JackDriver::Stop(); | |||||
if (fIsMaster) { | |||||
if (StopSlaves() < 0) { | |||||
res = -1; | |||||
} | |||||
} | |||||
return res; | |||||
} | |||||
void JackAudioDriver::WaitUntilNextCycle() | void JackAudioDriver::WaitUntilNextCycle() | ||||
{ | { | ||||
int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f)); | int wait_time_usec = (int((float(fEngineControl->fBufferSize) / (float(fEngineControl->fSampleRate))) * 1000000.0f)); | ||||
@@ -92,6 +92,9 @@ class SERVER_EXPORT JackAudioDriver : public JackDriver | |||||
virtual int Attach(); | virtual int Attach(); | ||||
virtual int Detach(); | virtual int Detach(); | ||||
virtual int Start(); | |||||
virtual int Stop(); | |||||
virtual int Write(); | virtual int Write(); | ||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
@@ -38,11 +38,11 @@ static void AudioBufferInit(void* buffer, size_t buffer_size, jack_nframes_t) | |||||
memset(buffer, 0, buffer_size); | memset(buffer, 0, buffer_size); | ||||
} | } | ||||
static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_t frames) | |||||
static inline void MixAudioBuffer(jack_default_audio_sample_t* mixbuffer, jack_default_audio_sample_t* buffer, jack_nframes_t frames) | |||||
{ | { | ||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
// It seems that a vector mult only operation does not exist... | // It seems that a vector mult only operation does not exist... | ||||
float gain = 1.0f; | |||||
jack_default_audio_sample_t gain = jack_default_audio_sample_t(1.0); | |||||
vDSP_vsma(buffer, 1, &gain, mixbuffer, 1, mixbuffer, 1, frames); | vDSP_vsma(buffer, 1, &gain, mixbuffer, 1, mixbuffer, 1, frames); | ||||
#else | #else | ||||
jack_nframes_t frames_group = frames / 4; | jack_nframes_t frames_group = frames / 4; | ||||
@@ -57,14 +57,14 @@ static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_ | |||||
buffer += 4; | buffer += 4; | ||||
frames_group--; | frames_group--; | ||||
#else | #else | ||||
register float mixFloat1 = *mixbuffer; | |||||
register float sourceFloat1 = *buffer; | |||||
register float mixFloat2 = *(mixbuffer + 1); | |||||
register float sourceFloat2 = *(buffer + 1); | |||||
register float mixFloat3 = *(mixbuffer + 2); | |||||
register float sourceFloat3 = *(buffer + 2); | |||||
register float mixFloat4 = *(mixbuffer + 3); | |||||
register float sourceFloat4 = *(buffer + 3); | |||||
register jack_default_audio_sample_t mixFloat1 = *mixbuffer; | |||||
register jack_default_audio_sample_t sourceFloat1 = *buffer; | |||||
register jack_default_audio_sample_t mixFloat2 = *(mixbuffer + 1); | |||||
register jack_default_audio_sample_t sourceFloat2 = *(buffer + 1); | |||||
register jack_default_audio_sample_t mixFloat3 = *(mixbuffer + 2); | |||||
register jack_default_audio_sample_t sourceFloat3 = *(buffer + 2); | |||||
register jack_default_audio_sample_t mixFloat4 = *(mixbuffer + 3); | |||||
register jack_default_audio_sample_t sourceFloat4 = *(buffer + 3); | |||||
buffer += 4; | buffer += 4; | ||||
frames_group--; | frames_group--; | ||||
@@ -84,8 +84,8 @@ static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_ | |||||
} | } | ||||
while (frames > 0) { | while (frames > 0) { | ||||
register float mixFloat1 = *mixbuffer; | |||||
register float sourceFloat1 = *buffer; | |||||
register jack_default_audio_sample_t mixFloat1 = *mixbuffer; | |||||
register jack_default_audio_sample_t sourceFloat1 = *buffer; | |||||
buffer++; | buffer++; | ||||
frames--; | frames--; | ||||
mixFloat1 += sourceFloat1; | mixFloat1 += sourceFloat1; | ||||
@@ -104,8 +104,8 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun | |||||
jack_nframes_t frames_group = nframes / 4; | jack_nframes_t frames_group = nframes / 4; | ||||
jack_nframes_t remaining_frames = nframes % 4; | jack_nframes_t remaining_frames = nframes % 4; | ||||
float * source = static_cast<float*>(src_buffers[0]); | |||||
float * target = static_cast<float*>(mixbuffer); | |||||
jack_default_audio_sample_t * source = static_cast<jack_default_audio_sample_t*>(src_buffers[0]); | |||||
jack_default_audio_sample_t * target = static_cast<jack_default_audio_sample_t*>(mixbuffer); | |||||
while (frames_group > 0) | while (frames_group > 0) | ||||
{ | { | ||||
@@ -120,19 +120,19 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun | |||||
target[i] = source[i]; | target[i] = source[i]; | ||||
#else | #else | ||||
memcpy(mixbuffer, src_buffers[0], nframes * sizeof(float)); | |||||
memcpy(mixbuffer, src_buffers[0], nframes * sizeof(jack_default_audio_sample_t)); | |||||
#endif | #endif | ||||
// Mix remaining buffers | // Mix remaining buffers | ||||
for (int i = 1; i < src_count; ++i) { | for (int i = 1; i < src_count; ++i) { | ||||
buffer = src_buffers[i]; | buffer = src_buffers[i]; | ||||
MixAudioBuffer(static_cast<float*>(mixbuffer), static_cast<float*>(buffer), nframes); | |||||
MixAudioBuffer(static_cast<jack_default_audio_sample_t*>(mixbuffer), static_cast<jack_default_audio_sample_t*>(buffer), nframes); | |||||
} | } | ||||
} | } | ||||
static size_t AudioBufferSize() | static size_t AudioBufferSize() | ||||
{ | { | ||||
return GetEngineControl()->fBufferSize * sizeof(float); | |||||
return GetEngineControl()->fBufferSize * sizeof(jack_default_audio_sample_t); | |||||
} | } | ||||
const JackPortType gAudioPortType = | const JackPortType gAudioPortType = | ||||
@@ -496,8 +496,8 @@ bool JackClient::Init() | |||||
// Setup RT | // Setup RT | ||||
if (GetEngineControl()->fRealTime) { | if (GetEngineControl()->fRealTime) { | ||||
if (fThread.AcquireRealTime(GetEngineControl()->fClientPriority) < 0) { | |||||
jack_error("JackClient::AcquireRealTime error"); | |||||
if (fThread.AcquireSelfRealTime(GetEngineControl()->fClientPriority) < 0) { | |||||
jack_error("JackClient::AcquireSelfRealTime error"); | |||||
} | } | ||||
} | } | ||||
@@ -44,7 +44,7 @@ struct JackEngineControl; | |||||
\brief The base class for clients: share part of the implementation for JackInternalClient and JackLibClient. | \brief The base class for clients: share part of the implementation for JackInternalClient and JackLibClient. | ||||
*/ | */ | ||||
class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
class SERVER_EXPORT JackClient : public JackClientInterface, public JackRunnableInterface | |||||
{ | { | ||||
friend class JackDebugClient; | friend class JackDebugClient; | ||||
@@ -195,15 +195,15 @@ class JackClient : public JackClientInterface, public JackRunnableInterface | |||||
// RT Thread | // RT Thread | ||||
jack_nframes_t CycleWait(); | jack_nframes_t CycleWait(); | ||||
void CycleSignal(int status); | void CycleSignal(int status); | ||||
int SetProcessThread(JackThreadCallback fun, void *arg); | |||||
virtual int SetProcessThread(JackThreadCallback fun, void *arg); | |||||
// Session API | // Session API | ||||
virtual jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path); | virtual jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path); | ||||
virtual int SessionReply(jack_session_event_t* ev); | virtual int SessionReply(jack_session_event_t* ev); | ||||
char* GetUUIDForClientName(const char* client_name); | |||||
char* GetClientNameByUUID(const char* uuid); | |||||
int ReserveClientName(const char* client_name, const char* uuid); | |||||
int ClientHasSessionCallback(const char* client_name); | |||||
virtual char* GetUUIDForClientName(const char* client_name); | |||||
virtual char* GetClientNameByUUID(const char* uuid); | |||||
virtual int ReserveClientName(const char* client_name, const char* uuid); | |||||
virtual int ClientHasSessionCallback(const char* client_name); | |||||
// JackRunnableInterface interface | // JackRunnableInterface interface | ||||
bool Init(); | bool Init(); | ||||
@@ -78,15 +78,15 @@ struct jackctl_server | |||||
/* int32_t, msecs; if zero, use period size. */ | /* int32_t, msecs; if zero, use period size. */ | ||||
union jackctl_parameter_value client_timeout; | union jackctl_parameter_value client_timeout; | ||||
union jackctl_parameter_value default_client_timeout; | union jackctl_parameter_value default_client_timeout; | ||||
/* uint32_t, clock source type */ | /* uint32_t, clock source type */ | ||||
union jackctl_parameter_value clock_source; | union jackctl_parameter_value clock_source; | ||||
union jackctl_parameter_value default_clock_source; | union jackctl_parameter_value default_clock_source; | ||||
/* uint32_t, max port number */ | /* uint32_t, max port number */ | ||||
union jackctl_parameter_value port_max; | union jackctl_parameter_value port_max; | ||||
union jackctl_parameter_value default_port_max; | union jackctl_parameter_value default_port_max; | ||||
/* bool */ | /* bool */ | ||||
union jackctl_parameter_value replace_registry; | union jackctl_parameter_value replace_registry; | ||||
union jackctl_parameter_value default_replace_registry; | union jackctl_parameter_value default_replace_registry; | ||||
@@ -366,7 +366,7 @@ jackctl_internals_load( | |||||
} | } | ||||
while (descriptor_node_ptr != NULL) | while (descriptor_node_ptr != NULL) | ||||
{ | |||||
{ | |||||
internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | internal_ptr = (struct jackctl_internal *)malloc(sizeof(struct jackctl_internal)); | ||||
if (internal_ptr == NULL) | if (internal_ptr == NULL) | ||||
{ | { | ||||
@@ -450,21 +450,21 @@ sigset_t | |||||
jackctl_setup_signals( | jackctl_setup_signals( | ||||
unsigned int flags) | unsigned int flags) | ||||
{ | { | ||||
if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) { | |||||
if ((waitEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL) { | |||||
jack_error("CreateEvent fails err = %ld", GetLastError()); | jack_error("CreateEvent fails err = %ld", GetLastError()); | ||||
return 0; | return 0; | ||||
} | } | ||||
(void) signal(SIGINT, do_nothing_handler); | |||||
(void) signal(SIGINT, do_nothing_handler); | |||||
(void) signal(SIGABRT, do_nothing_handler); | (void) signal(SIGABRT, do_nothing_handler); | ||||
(void) signal(SIGTERM, do_nothing_handler); | (void) signal(SIGTERM, do_nothing_handler); | ||||
return (sigset_t)waitEvent; | |||||
return (sigset_t)waitEvent; | |||||
} | } | ||||
void jackctl_wait_signals(sigset_t signals) | void jackctl_wait_signals(sigset_t signals) | ||||
{ | { | ||||
if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) { | |||||
if (WaitForSingleObject(waitEvent, INFINITE) != WAIT_OBJECT_0) { | |||||
jack_error("WaitForSingleObject fails err = %ld", GetLastError()); | jack_error("WaitForSingleObject fails err = %ld", GetLastError()); | ||||
} | } | ||||
} | } | ||||
@@ -539,7 +539,7 @@ jackctl_setup_signals( | |||||
* explicitly reset it | * explicitly reset it | ||||
*/ | */ | ||||
pthread_sigmask(SIG_BLOCK, &signals, 0); | |||||
pthread_sigmask(SIG_BLOCK, &signals, 0); | |||||
/* install a do-nothing handler because otherwise pthreads | /* install a do-nothing handler because otherwise pthreads | ||||
behaviour is undefined when we enter sigwait. | behaviour is undefined when we enter sigwait. | ||||
@@ -745,7 +745,7 @@ EXPORT jackctl_server_t * jackctl_server_create( | |||||
{ | { | ||||
goto fail_free_parameters; | goto fail_free_parameters; | ||||
} | } | ||||
value.ui = PORT_NUM; | value.ui = PORT_NUM; | ||||
if (jackctl_add_parameter( | if (jackctl_add_parameter( | ||||
&server_ptr->parameters, | &server_ptr->parameters, | ||||
@@ -795,7 +795,7 @@ EXPORT jackctl_server_t * jackctl_server_create( | |||||
{ | { | ||||
goto fail_free_parameters; | goto fail_free_parameters; | ||||
} | } | ||||
/* Allowed to fail */ | /* Allowed to fail */ | ||||
jackctl_internals_load(server_ptr); | jackctl_internals_load(server_ptr); | ||||
@@ -826,6 +826,11 @@ EXPORT const JSList * jackctl_server_get_drivers_list(jackctl_server *server_ptr | |||||
EXPORT bool jackctl_server_stop(jackctl_server *server_ptr) | EXPORT bool jackctl_server_stop(jackctl_server *server_ptr) | ||||
{ | { | ||||
server_ptr->engine->Stop(); | server_ptr->engine->Stop(); | ||||
return true; | |||||
} | |||||
EXPORT bool jackctl_server_close(jackctl_server *server_ptr) | |||||
{ | |||||
server_ptr->engine->Close(); | server_ptr->engine->Close(); | ||||
delete server_ptr->engine; | delete server_ptr->engine; | ||||
@@ -853,7 +858,7 @@ EXPORT const JSList * jackctl_server_get_parameters(jackctl_server *server_ptr) | |||||
} | } | ||||
EXPORT bool | EXPORT bool | ||||
jackctl_server_start( | |||||
jackctl_server_open( | |||||
jackctl_server *server_ptr, | jackctl_server *server_ptr, | ||||
jackctl_driver *driver_ptr) | jackctl_driver *driver_ptr) | ||||
{ | { | ||||
@@ -882,7 +887,7 @@ jackctl_server_start( | |||||
if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) | if (!server_ptr->realtime.b && server_ptr->client_timeout.i == 0) | ||||
server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | server_ptr->client_timeout.i = 500; /* 0.5 sec; usable when non realtime. */ | ||||
/* check port max value before allocating server */ | /* check port max value before allocating server */ | ||||
if (server_ptr->port_max.ui > PORT_NUM_MAX) { | if (server_ptr->port_max.ui > PORT_NUM_MAX) { | ||||
jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | jack_error("JACK server started with too much ports %d (when port max can be %d)", server_ptr->port_max.ui, PORT_NUM_MAX); | ||||
@@ -896,7 +901,7 @@ jackctl_server_start( | |||||
server_ptr->client_timeout.i, | server_ptr->client_timeout.i, | ||||
server_ptr->realtime.b, | server_ptr->realtime.b, | ||||
server_ptr->realtime_priority.i, | server_ptr->realtime_priority.i, | ||||
server_ptr->port_max.ui, | |||||
server_ptr->port_max.ui, | |||||
server_ptr->verbose.b, | server_ptr->verbose.b, | ||||
(jack_timer_type_t)server_ptr->clock_source.ui, | (jack_timer_type_t)server_ptr->clock_source.ui, | ||||
server_ptr->name.str); | server_ptr->name.str); | ||||
@@ -913,18 +918,8 @@ jackctl_server_start( | |||||
goto fail_delete; | goto fail_delete; | ||||
} | } | ||||
rc = server_ptr->engine->Start(); | |||||
if (rc < 0) | |||||
{ | |||||
jack_error("JackServer::Start() failed with %d", rc); | |||||
goto fail_close; | |||||
} | |||||
return true; | return true; | ||||
fail_close: | |||||
server_ptr->engine->Close(); | |||||
fail_delete: | fail_delete: | ||||
delete server_ptr->engine; | delete server_ptr->engine; | ||||
server_ptr->engine = NULL; | server_ptr->engine = NULL; | ||||
@@ -946,6 +941,19 @@ fail: | |||||
return false; | return false; | ||||
} | } | ||||
EXPORT bool | |||||
jackctl_server_start( | |||||
jackctl_server *server_ptr) | |||||
{ | |||||
int rc = server_ptr->engine->Start(); | |||||
bool result = rc >= 0; | |||||
if (! result) | |||||
{ | |||||
jack_error("JackServer::Start() failed with %d", rc); | |||||
} | |||||
return result; | |||||
} | |||||
EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr) | EXPORT const char * jackctl_driver_get_name(jackctl_driver *driver_ptr) | ||||
{ | { | ||||
return driver_ptr->desc_ptr->name; | return driver_ptr->desc_ptr->name; | ||||
@@ -1179,7 +1187,7 @@ EXPORT bool jackctl_server_load_internal( | |||||
{ | { | ||||
int status; | int status; | ||||
if (server_ptr->engine != NULL) { | if (server_ptr->engine != NULL) { | ||||
server_ptr->engine->InternalClientLoad(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status); | |||||
server_ptr->engine->InternalClientLoad2(internal->desc_ptr->name, internal->desc_ptr->name, internal->set_parameters, JackNullOption, &internal->refnum, -1, &status); | |||||
return (internal->refnum > 0); | return (internal->refnum > 0); | ||||
} else { | } else { | ||||
return false; | return false; | ||||
@@ -1192,6 +1200,7 @@ EXPORT bool jackctl_server_unload_internal( | |||||
{ | { | ||||
int status; | int status; | ||||
if (server_ptr->engine != NULL && internal->refnum > 0) { | if (server_ptr->engine != NULL && internal->refnum > 0) { | ||||
// Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload | |||||
return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0); | return ((server_ptr->engine->GetEngine()->InternalClientUnload(internal->refnum, &status)) == 0); | ||||
} else { | } else { | ||||
return false; | return false; | ||||
@@ -1201,8 +1210,13 @@ EXPORT bool jackctl_server_unload_internal( | |||||
EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | ||||
{ | { | ||||
if (server_ptr->engine != NULL) { | if (server_ptr->engine != NULL) { | ||||
driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters); | |||||
return (driver_ptr->info != 0); | |||||
if (server_ptr->engine->IsRunning()) { | |||||
jack_error("cannot add a slave in a running server"); | |||||
return false; | |||||
} else { | |||||
driver_ptr->info = server_ptr->engine->AddSlave(driver_ptr->desc_ptr, driver_ptr->set_parameters); | |||||
return (driver_ptr->info != 0); | |||||
} | |||||
} else { | } else { | ||||
return false; | return false; | ||||
} | } | ||||
@@ -1211,9 +1225,14 @@ EXPORT bool jackctl_server_add_slave(jackctl_server * server_ptr, jackctl_driver | |||||
EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | EXPORT bool jackctl_server_remove_slave(jackctl_server * server_ptr, jackctl_driver * driver_ptr) | ||||
{ | { | ||||
if (server_ptr->engine != NULL) { | if (server_ptr->engine != NULL) { | ||||
server_ptr->engine->RemoveSlave(driver_ptr->info); | |||||
delete driver_ptr->info; | |||||
return true; | |||||
if (server_ptr->engine->IsRunning()) { | |||||
jack_error("cannot remove a slave from a running server"); | |||||
return false; | |||||
} else { | |||||
server_ptr->engine->RemoveSlave(driver_ptr->info); | |||||
delete driver_ptr->info; | |||||
return true; | |||||
} | |||||
} else { | } else { | ||||
return false; | return false; | ||||
} | } | ||||
@@ -101,13 +101,21 @@ jackctl_server_get_drivers_list( | |||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
EXPORT bool | EXPORT bool | ||||
jackctl_server_start( | |||||
jackctl_server_open( | |||||
jackctl_server_t * server, | jackctl_server_t * server, | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
EXPORT bool | |||||
jackctl_server_start( | |||||
jackctl_server_t * server); | |||||
EXPORT bool | EXPORT bool | ||||
jackctl_server_stop( | jackctl_server_stop( | ||||
jackctl_server_t * server); | |||||
jackctl_server_t * server); | |||||
EXPORT bool | |||||
jackctl_server_close( | |||||
jackctl_server_t * server); | |||||
EXPORT const JSList * | EXPORT const JSList * | ||||
jackctl_server_get_parameters( | jackctl_server_get_parameters( | ||||
@@ -505,6 +505,54 @@ int JackDebugClient::SetPortRenameCallback(JackPortRenameCallback callback, void | |||||
return fClient->SetPortRenameCallback(callback, arg); | return fClient->SetPortRenameCallback(callback, arg); | ||||
} | } | ||||
int JackDebugClient::SetSessionCallback(JackSessionCallback callback, void *arg) | |||||
{ | |||||
CheckClient("SetSessionCallback"); | |||||
return fClient->SetSessionCallback(callback, arg); | |||||
} | |||||
int JackDebugClient::SetLatencyCallback(JackLatencyCallback callback, void *arg) | |||||
{ | |||||
CheckClient("SetLatencyCallback"); | |||||
return fClient->SetLatencyCallback(callback, arg); | |||||
} | |||||
jack_session_command_t* JackDebugClient::SessionNotify(const char* target, jack_session_event_type_t type, const char* path) | |||||
{ | |||||
CheckClient("SessionNotify"); | |||||
return fClient->SessionNotify(target, type, path); | |||||
} | |||||
int JackDebugClient::SessionReply(jack_session_event_t* ev) | |||||
{ | |||||
CheckClient("SessionReply"); | |||||
return fClient->SessionReply(ev); | |||||
} | |||||
char* JackDebugClient::GetUUIDForClientName(const char* client_name) | |||||
{ | |||||
CheckClient("GetUUIDForClientName"); | |||||
return fClient->GetUUIDForClientName(client_name); | |||||
} | |||||
char* JackDebugClient::GetClientNameByUUID(const char* uuid) | |||||
{ | |||||
CheckClient("GetClientNameByUUID"); | |||||
return fClient->GetClientNameByUUID(uuid); | |||||
} | |||||
int JackDebugClient::ReserveClientName(const char* client_name, const char* uuid) | |||||
{ | |||||
CheckClient("ReserveClientName"); | |||||
return fClient->ReserveClientName(client_name, uuid); | |||||
} | |||||
int JackDebugClient::ClientHasSessionCallback(const char* client_name) | |||||
{ | |||||
CheckClient("ClientHasSessionCallback"); | |||||
return fClient->ClientHasSessionCallback(client_name); | |||||
} | |||||
JackClientControl* JackDebugClient::GetClientControl() const | JackClientControl* JackDebugClient::GetClientControl() const | ||||
{ | { | ||||
CheckClient("GetClientControl"); | CheckClient("GetClientControl"); | ||||
@@ -46,7 +46,7 @@ PortFollower; | |||||
\brief A "decorator" debug client to validate API use. | \brief A "decorator" debug client to validate API use. | ||||
*/ | */ | ||||
class JackDebugClient : public JackClient | |||||
class SERVER_EXPORT JackDebugClient : public JackClient | |||||
{ | { | ||||
protected: | protected: | ||||
@@ -121,6 +121,8 @@ class JackDebugClient : public JackClient | |||||
int SetPortRegistrationCallback(JackPortRegistrationCallback callback, void* arg); | int SetPortRegistrationCallback(JackPortRegistrationCallback callback, void* arg); | ||||
int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | int SetPortConnectCallback(JackPortConnectCallback callback, void *arg); | ||||
int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | int SetPortRenameCallback(JackPortRenameCallback callback, void *arg); | ||||
int SetSessionCallback(JackSessionCallback callback, void *arg); | |||||
int SetLatencyCallback(JackLatencyCallback callback, void *arg); | |||||
// Internal clients | // Internal clients | ||||
char* GetInternalClientName(int ref); | char* GetInternalClientName(int ref); | ||||
@@ -128,6 +130,14 @@ class JackDebugClient : public JackClient | |||||
int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va); | int InternalClientLoad(const char* client_name, jack_options_t options, jack_status_t* status, jack_varargs_t* va); | ||||
void InternalClientUnload(int ref, jack_status_t* status); | void InternalClientUnload(int ref, jack_status_t* status); | ||||
// Session API | |||||
jack_session_command_t* SessionNotify(const char* target, jack_session_event_type_t type, const char* path); | |||||
int SessionReply(jack_session_event_t* ev); | |||||
char* GetUUIDForClientName(const char* client_name); | |||||
char* GetClientNameByUUID(const char* uuid); | |||||
int ReserveClientName(const char* client_name, const char* uuid); | |||||
int ClientHasSessionCallback(const char* client_name); | |||||
JackClientControl* GetClientControl() const; | JackClientControl* GetClientControl() const; | ||||
void CheckClient(const char* function_name) const; | void CheckClient(const char* function_name) const; | ||||
@@ -47,6 +47,7 @@ JackDriver::JackDriver(const char* name, const char* alias, JackLockedEngine* en | |||||
fBeginDateUst = 0; | fBeginDateUst = 0; | ||||
fDelayedUsecs = 0.f; | fDelayedUsecs = 0.f; | ||||
fIsMaster = true; | fIsMaster = true; | ||||
fIsRunning = false; | |||||
} | } | ||||
JackDriver::JackDriver() | JackDriver::JackDriver() | ||||
@@ -56,6 +57,7 @@ JackDriver::JackDriver() | |||||
fGraphManager = NULL; | fGraphManager = NULL; | ||||
fBeginDateUst = 0; | fBeginDateUst = 0; | ||||
fIsMaster = true; | fIsMaster = true; | ||||
fIsRunning = false; | |||||
} | } | ||||
JackDriver::~JackDriver() | JackDriver::~JackDriver() | ||||
@@ -80,7 +82,7 @@ int JackDriver::Open() | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackDriver::Open (bool capturing, | |||||
int JackDriver::Open(bool capturing, | |||||
bool playing, | bool playing, | ||||
int inchannels, | int inchannels, | ||||
int outchannels, | int outchannels, | ||||
@@ -93,6 +95,15 @@ int JackDriver::Open (bool capturing, | |||||
jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name); | jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name); | ||||
jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name); | jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name); | ||||
int refnum = -1; | int refnum = -1; | ||||
char name_res[JACK_CLIENT_NAME_SIZE + 1]; | |||||
int status; | |||||
// Check name and possibly rename | |||||
if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) { | |||||
jack_error("Client name = %s conflits with another running client", fClientControl.fName); | |||||
return -1; | |||||
} | |||||
strcpy(fClientControl.fName, name_res); | |||||
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | ||||
jack_error("Cannot allocate internal client for driver"); | jack_error("Cannot allocate internal client for driver"); | ||||
@@ -135,6 +146,15 @@ int JackDriver::Open(jack_nframes_t buffer_size, | |||||
jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name); | jack_log("JackDriver::Open capture_driver_name = %s", capture_driver_name); | ||||
jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name); | jack_log("JackDriver::Open playback_driver_name = %s", playback_driver_name); | ||||
int refnum = -1; | int refnum = -1; | ||||
char name_res[JACK_CLIENT_NAME_SIZE + 1]; | |||||
int status; | |||||
// Check name and possibly rename | |||||
if (fEngine->ClientCheck(fClientControl.fName, -1, name_res, JACK_PROTOCOL_VERSION, (int)JackNullOption, (int*)&status) < 0) { | |||||
jack_error("Client name = %s conflits with another running client", fClientControl.fName); | |||||
return -1; | |||||
} | |||||
strcpy(fClientControl.fName, name_res); | |||||
if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | if (fEngine->ClientInternalOpen(fClientControl.fName, &refnum, &fEngineControl, &fGraphManager, this, false) != 0) { | ||||
jack_error("Cannot allocate internal client for driver"); | jack_error("Cannot allocate internal client for driver"); | ||||
@@ -288,6 +308,7 @@ int JackDriver::ProcessSlaves() | |||||
JackDriverInterface* slave = *it; | JackDriverInterface* slave = *it; | ||||
if (slave->Process() < 0) | if (slave->Process() < 0) | ||||
res = -1; | res = -1; | ||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -324,15 +345,49 @@ int JackDriver::Write() | |||||
int JackDriver::Start() | int JackDriver::Start() | ||||
{ | { | ||||
fEngineControl->InitFrameTime(); | |||||
if (fIsMaster) { | |||||
fEngineControl->InitFrameTime(); | |||||
} | |||||
fIsRunning = true; | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackDriver::StartSlaves() | |||||
{ | |||||
int res = 0; | |||||
list<JackDriverInterface*>::const_iterator it; | |||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | |||||
JackDriverInterface* slave = *it; | |||||
if (slave->Start() < 0) { | |||||
res = -1; | |||||
// XXX: We should attempt to stop all of the slaves that we've | |||||
// started here. | |||||
break; | |||||
} | |||||
} | |||||
return res; | |||||
} | |||||
int JackDriver::Stop() | int JackDriver::Stop() | ||||
{ | { | ||||
fIsRunning = false; | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackDriver::StopSlaves() | |||||
{ | |||||
int res = 0; | |||||
list<JackDriverInterface*>::const_iterator it; | |||||
for (it = fSlaveList.begin(); it != fSlaveList.end(); it++) { | |||||
JackDriverInterface* slave = *it; | |||||
if (slave->Stop() < 0) | |||||
res = -1; | |||||
} | |||||
return res; | |||||
} | |||||
bool JackDriver::IsFixedBufferSize() | bool JackDriver::IsFixedBufferSize() | ||||
{ | { | ||||
return true; | return true; | ||||
@@ -97,6 +97,7 @@ class SERVER_EXPORT JackDriverInterface | |||||
virtual int ProcessSlaves() = 0; | virtual int ProcessSlaves() = 0; | ||||
virtual bool IsRealTime() const = 0; | virtual bool IsRealTime() const = 0; | ||||
virtual bool IsRunning() const = 0; | |||||
}; | }; | ||||
/*! | /*! | ||||
@@ -134,6 +135,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||||
JackClientControl fClientControl; | JackClientControl fClientControl; | ||||
std::list<JackDriverInterface*> fSlaveList; | std::list<JackDriverInterface*> fSlaveList; | ||||
bool fIsMaster; | bool fIsMaster; | ||||
bool fIsRunning; | |||||
void CycleIncTime(); | void CycleIncTime(); | ||||
void CycleTakeBeginTime(); | void CycleTakeBeginTime(); | ||||
@@ -198,7 +200,9 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||||
virtual int Write(); | virtual int Write(); | ||||
virtual int Start(); | virtual int Start(); | ||||
virtual int StartSlaves(); | |||||
virtual int Stop(); | virtual int Stop(); | ||||
virtual int StopSlaves(); | |||||
virtual bool IsFixedBufferSize(); | virtual bool IsFixedBufferSize(); | ||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
@@ -208,6 +212,7 @@ class SERVER_EXPORT JackDriver : public JackDriverClientInterface | |||||
virtual JackClientControl* GetClientControl() const; | virtual JackClientControl* GetClientControl() const; | ||||
virtual bool IsRealTime() const; | virtual bool IsRealTime() const; | ||||
virtual bool IsRunning() const { return fIsRunning; } | |||||
virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one | virtual bool Initialize(); // To be called by the wrapping thread Init method when the driver is a "blocking" one | ||||
}; | }; | ||||
@@ -119,7 +119,7 @@ jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char* argv[], JSL | |||||
desc->name); | desc->name); | ||||
} | } | ||||
printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name); | |||||
jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name); | |||||
jack_print_driver_options (desc, stdout); | jack_print_driver_options (desc, stdout); | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -263,7 +263,7 @@ jackctl_parse_driver_params (jackctl_driver *driver_ptr, int argc, char* argv[]) | |||||
desc->name); | desc->name); | ||||
} | } | ||||
printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name); | |||||
jack_log("Parameters for driver '%s' (all parameters are optional):", desc->name); | |||||
jack_print_driver_options (desc, stdout); | jack_print_driver_options (desc, stdout); | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -446,7 +446,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
free(filename); | free(filename); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if ((descriptor = so_get_descriptor ()) == NULL) { | if ((descriptor = so_get_descriptor ()) == NULL) { | ||||
jack_error("driver from '%s' returned NULL descriptor", filename); | jack_error("driver from '%s' returned NULL descriptor", filename); | ||||
UnloadDriverModule(dlhandle); | UnloadDriverModule(dlhandle); | ||||
@@ -467,7 +467,7 @@ jack_get_descriptor (JSList * drivers, const char * sofile, const char * symbol) | |||||
/* check it doesn't exist already */ | /* check it doesn't exist already */ | ||||
for (node = drivers; node; node = jack_slist_next (node)) { | for (node = drivers; node; node = jack_slist_next (node)) { | ||||
other_descriptor = (jack_driver_desc_t *) node->data; | other_descriptor = (jack_driver_desc_t *) node->data; | ||||
if (strcmp(descriptor->name, other_descriptor->name) == 0) { | if (strcmp(descriptor->name, other_descriptor->name) == 0) { | ||||
jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | jack_error("the drivers in '%s' and '%s' both have the name '%s'; using the first", | ||||
other_descriptor->file, filename, other_descriptor->name); | other_descriptor->file, filename, other_descriptor->name); | ||||
@@ -603,7 +603,7 @@ jack_drivers_load (JSList * drivers) { | |||||
} | } | ||||
while ((dir_entry = readdir(dir_stream))) { | while ((dir_entry = readdir(dir_stream))) { | ||||
/* check the filename is of the right format */ | /* check the filename is of the right format */ | ||||
if (strncmp ("jack_", dir_entry->d_name, 5) != 0) { | if (strncmp ("jack_", dir_entry->d_name, 5) != 0) { | ||||
continue; | continue; | ||||
@@ -619,7 +619,7 @@ jack_drivers_load (JSList * drivers) { | |||||
} | } | ||||
desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor"); | desc = jack_get_descriptor (drivers, dir_entry->d_name, "driver_get_descriptor"); | ||||
if (desc) { | if (desc) { | ||||
driver_list = jack_slist_append (driver_list, desc); | driver_list = jack_slist_append (driver_list, desc); | ||||
} else { | } else { | ||||
@@ -771,9 +771,9 @@ jack_internals_load (JSList * internals) { | |||||
#endif | #endif | ||||
Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver_desc, | |||||
Jack::JackLockedEngine* engine, | |||||
Jack::JackSynchro* synchro, | |||||
Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver_desc, | |||||
Jack::JackLockedEngine* engine, | |||||
Jack::JackSynchro* synchro, | |||||
const JSList* params) | const JSList* params) | ||||
{ | { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
@@ -783,7 +783,7 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
#endif | #endif | ||||
fHandle = LoadDriverModule (driver_desc->file); | fHandle = LoadDriverModule (driver_desc->file); | ||||
if (fHandle == NULL) { | if (fHandle == NULL) { | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
if ((errstr = GetLastError ()) != 0) { | if ((errstr = GetLastError ()) != 0) { | ||||
@@ -809,8 +809,14 @@ Jack::JackDriverClientInterface* JackDriverInfo::Open(jack_driver_desc_t* driver | |||||
jack_error("no initialize function in shared object %s\n", driver_desc->file); | jack_error("no initialize function in shared object %s\n", driver_desc->file); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
fBackend = fInitialize(engine, synchro, params); | fBackend = fInitialize(engine, synchro, params); | ||||
return fBackend; | return fBackend; | ||||
} | } | ||||
JackDriverInfo::~JackDriverInfo() | |||||
{ | |||||
delete fBackend; | |||||
if (fHandle) | |||||
UnloadDriverModule(fHandle); | |||||
} |
@@ -24,14 +24,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "driver_interface.h" | #include "driver_interface.h" | ||||
#include "JackControlAPI.h" | #include "JackControlAPI.h" | ||||
#include "JackPlatformPlug.h" | #include "JackPlatformPlug.h" | ||||
#include "JackDriver.h" | |||||
#include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
namespace Jack | |||||
{ | |||||
class JackDriverClientInterface; | |||||
class JackLockedEngine; | |||||
}; | |||||
typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | typedef jack_driver_desc_t * (*JackDriverDescFunction) (); | ||||
typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | typedef Jack::JackDriverClientInterface* (*driverInitialize) (Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | ||||
@@ -39,34 +34,30 @@ class JackDriverInfo | |||||
{ | { | ||||
private: | private: | ||||
driverInitialize fInitialize; | driverInitialize fInitialize; | ||||
DRIVER_HANDLE fHandle; | DRIVER_HANDLE fHandle; | ||||
Jack::JackDriverClientInterface* fBackend; | Jack::JackDriverClientInterface* fBackend; | ||||
public: | public: | ||||
JackDriverInfo():fInitialize(NULL),fHandle(NULL) | |||||
JackDriverInfo():fInitialize(NULL),fHandle(NULL),fBackend(NULL) | |||||
{} | {} | ||||
~JackDriverInfo() | |||||
{ | |||||
if (fHandle) | |||||
UnloadDriverModule(fHandle); | |||||
} | |||||
~JackDriverInfo(); | |||||
Jack::JackDriverClientInterface* Open(jack_driver_desc_t* driver_desc, Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | Jack::JackDriverClientInterface* Open(jack_driver_desc_t* driver_desc, Jack::JackLockedEngine*, Jack::JackSynchro*, const JSList*); | ||||
Jack::JackDriverClientInterface* GetBackend() | Jack::JackDriverClientInterface* GetBackend() | ||||
{ | { | ||||
return fBackend; | return fBackend; | ||||
} | } | ||||
}; | }; | ||||
jack_driver_desc_t * jack_find_driver_descriptor (JSList * drivers, const char * name); | |||||
jack_driver_desc_t * jack_find_driver_descriptor(JSList * drivers, const char * name); | |||||
JSList * jack_drivers_load (JSList * drivers); | |||||
JSList * jack_internals_load (JSList * internals); | |||||
JSList * jack_drivers_load(JSList * drivers); | |||||
JSList * jack_internals_load(JSList * internals); | |||||
EXPORT int jackctl_parse_driver_params (jackctl_driver * driver_ptr, int argc, char* argv[]); | EXPORT int jackctl_parse_driver_params (jackctl_driver * driver_ptr, int argc, char* argv[]); | ||||
EXPORT void jack_free_driver_params(JSList * param_ptr); | EXPORT void jack_free_driver_params(JSList * param_ptr); | ||||
@@ -223,7 +223,6 @@ int JackEngine::ComputeTotalLatencies() | |||||
*/ | */ | ||||
for (it = sorted.begin(); it != sorted.end(); it++) { | for (it = sorted.begin(); it != sorted.end(); it++) { | ||||
jack_log("Sorted %d", *it); | |||||
NotifyClient(*it, kLatencyCallback, true, "", 0, 0); | NotifyClient(*it, kLatencyCallback, true, "", 0, 0); | ||||
} | } | ||||
@@ -322,8 +321,8 @@ void JackEngine::NotifyXRun(int refnum) | |||||
void JackEngine::NotifyGraphReorder() | void JackEngine::NotifyGraphReorder() | ||||
{ | { | ||||
ComputeTotalLatencies(); | |||||
NotifyClients(kGraphOrderCallback, false, "", 0, 0); | NotifyClients(kGraphOrderCallback, false, "", 0, 0); | ||||
ComputeTotalLatencies(); | |||||
} | } | ||||
void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size) | void JackEngine::NotifyBufferSize(jack_nframes_t buffer_size) | ||||
@@ -520,7 +519,7 @@ void JackEngine::EnsureUUID(int uuid) | |||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (client && (client->GetClientControl()->fSessionID==uuid)) { | |||||
if (client && (client->GetClientControl()->fSessionID == uuid)) { | |||||
client->GetClientControl()->fSessionID = GetNewUUID(); | client->GetClientControl()->fSessionID = GetNewUUID(); | ||||
} | } | ||||
} | } | ||||
@@ -551,13 +550,13 @@ int JackEngine::GetClientRefNum(const char* name) | |||||
// Used for external clients | // Used for external clients | ||||
int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager) | int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager) | ||||
{ | { | ||||
char real_name[JACK_CLIENT_NAME_SIZE+1]; | |||||
char real_name[JACK_CLIENT_NAME_SIZE + 1]; | |||||
if (uuid < 0) { | if (uuid < 0) { | ||||
uuid = GetNewUUID(); | uuid = GetNewUUID(); | ||||
strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); | strncpy(real_name, name, JACK_CLIENT_NAME_SIZE); | ||||
} else { | } else { | ||||
std::map<int,std::string>::iterator res = fReservationMap.find(uuid); | |||||
std::map<int, std::string>::iterator res = fReservationMap.find(uuid); | |||||
if (res != fReservationMap.end()) { | if (res != fReservationMap.end()) { | ||||
strncpy(real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE); | strncpy(real_name, res->second.c_str(), JACK_CLIENT_NAME_SIZE); | ||||
fReservationMap.erase(uuid); | fReservationMap.erase(uuid); | ||||
@@ -568,7 +567,7 @@ int JackEngine::ClientExternalOpen(const char* name, int pid, int uuid, int* ref | |||||
EnsureUUID(uuid); | EnsureUUID(uuid); | ||||
} | } | ||||
jack_log("JackEngine::ClientExternalOpen: uuid=%d, name = %s ", uuid, real_name); | |||||
jack_log("JackEngine::ClientExternalOpen: uuid = %d, name = %s ", uuid, real_name); | |||||
int refnum = AllocateRefnum(); | int refnum = AllocateRefnum(); | ||||
if (refnum < 0) { | if (refnum < 0) { | ||||
@@ -762,7 +761,7 @@ int JackEngine::ClientDeactivate(int refnum) | |||||
fGraphManager->GetInputPorts(refnum, input_ports); | fGraphManager->GetInputPorts(refnum, input_ports); | ||||
fGraphManager->GetOutputPorts(refnum, output_ports); | fGraphManager->GetOutputPorts(refnum, output_ports); | ||||
// First disconnect all ports and remove their JackPortIsActive state | |||||
// First disconnect all ports | |||||
for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { | for (int i = 0; (i < PORT_NUM_FOR_CLIENT) && (input_ports[i] != EMPTY); i++) { | ||||
PortDisconnect(refnum, input_ports[i], ALL_PORTS); | PortDisconnect(refnum, input_ports[i], ALL_PORTS); | ||||
} | } | ||||
@@ -959,7 +958,7 @@ void JackEngine::SessionNotify(int refnum, const char *target, jack_session_even | |||||
if (client && client->GetClientControl()->fCallback[kSessionCallback]) { | if (client && client->GetClientControl()->fCallback[kSessionCallback]) { | ||||
// check if this is a notification to a specific client. | // check if this is a notification to a specific client. | ||||
if (target!=NULL && strlen(target)!=0) { | |||||
if (target != NULL && strlen(target) != 0) { | |||||
if (strcmp(target, client->GetClientControl()->fName)) { | if (strcmp(target, client->GetClientControl()->fName)) { | ||||
continue; | continue; | ||||
} | } | ||||
@@ -1019,7 +1018,7 @@ void JackEngine::GetUUIDForClientName(const char *client_name, char *uuid_res, i | |||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
JackClientInterface* client = fClientTable[i]; | JackClientInterface* client = fClientTable[i]; | ||||
if (client && (strcmp(client_name, client->GetClientControl()->fName)==0)) { | |||||
if (client && (strcmp(client_name, client->GetClientControl()->fName) == 0)) { | |||||
snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | snprintf(uuid_res, JACK_UUID_SIZE, "%d", client->GetClientControl()->fSessionID); | ||||
*result = 0; | *result = 0; | ||||
return; | return; | ||||
@@ -77,7 +77,7 @@ JackPort* JackGraphManager::GetPort(jack_port_id_t port_index) | |||||
return &fPortArray[port_index]; | return &fPortArray[port_index]; | ||||
} | } | ||||
float* JackGraphManager::GetBuffer(jack_port_id_t port_index) | |||||
jack_default_audio_sample_t* JackGraphManager::GetBuffer(jack_port_id_t port_index) | |||||
{ | { | ||||
return fPortArray[port_index].GetBuffer(); | return fPortArray[port_index].GetBuffer(); | ||||
} | } | ||||
@@ -49,7 +49,7 @@ class SERVER_EXPORT JackGraphManager : public JackShmMem, public JackAtomicState | |||||
jack_port_id_t AllocatePortAux(int refnum, const char* port_name, const char* port_type, JackPortFlags flags); | jack_port_id_t AllocatePortAux(int refnum, const char* port_name, const char* port_type, JackPortFlags flags); | ||||
void GetConnectionsAux(JackConnectionManager* manager, const char** res, jack_port_id_t port_index); | void GetConnectionsAux(JackConnectionManager* manager, const char** res, jack_port_id_t port_index); | ||||
void GetPortsAux(const char** matching_ports, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags); | void GetPortsAux(const char** matching_ports, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags); | ||||
float* GetBuffer(jack_port_id_t port_index); | |||||
jack_default_audio_sample_t* GetBuffer(jack_port_id_t port_index); | |||||
void* GetBufferAux(JackConnectionManager* manager, jack_port_id_t port_index, jack_nframes_t frames); | void* GetBufferAux(JackConnectionManager* manager, jack_port_id_t port_index, jack_nframes_t frames); | ||||
jack_nframes_t ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count); | jack_nframes_t ComputeTotalLatencyAux(jack_port_id_t port_index, jack_port_id_t src_port_index, JackConnectionManager* manager, int hop_count); | ||||
void RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode); | void RecalculateLatencyAux(jack_port_id_t port_index, jack_latency_callback_mode_t mode); | ||||
@@ -123,7 +123,7 @@ int JackLoadableInternalClient::Init(const char* so_name) | |||||
{ | { | ||||
char path_to_so[JACK_PATH_MAX + 1]; | char path_to_so[JACK_PATH_MAX + 1]; | ||||
BuildClientPath(path_to_so, sizeof(path_to_so), so_name); | BuildClientPath(path_to_so, sizeof(path_to_so), so_name); | ||||
fHandle = LoadJackModule(path_to_so); | fHandle = LoadJackModule(path_to_so); | ||||
jack_log("JackLoadableInternalClient::JackLoadableInternalClient path_to_so = %s", path_to_so); | jack_log("JackLoadableInternalClient::JackLoadableInternalClient path_to_so = %s", path_to_so); | ||||
@@ -151,7 +151,7 @@ int JackLoadableInternalClient1::Init(const char* so_name) | |||||
if (JackLoadableInternalClient::Init(so_name) < 0) { | if (JackLoadableInternalClient::Init(so_name) < 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
fInitialize = (InitializeCallback)GetJackProc(fHandle, "jack_initialize"); | fInitialize = (InitializeCallback)GetJackProc(fHandle, "jack_initialize"); | ||||
if (fInitialize == NULL) { | if (fInitialize == NULL) { | ||||
UnloadJackModule(fHandle); | UnloadJackModule(fHandle); | ||||
@@ -167,7 +167,7 @@ int JackLoadableInternalClient2::Init(const char* so_name) | |||||
if (JackLoadableInternalClient::Init(so_name) < 0) { | if (JackLoadableInternalClient::Init(so_name) < 0) { | ||||
return -1; | return -1; | ||||
} | } | ||||
fInitialize = (InternalInitializeCallback)GetJackProc(fHandle, "jack_internal_initialize"); | fInitialize = (InternalInitializeCallback)GetJackProc(fHandle, "jack_internal_initialize"); | ||||
if (fInitialize == NULL) { | if (fInitialize == NULL) { | ||||
UnloadJackModule(fHandle); | UnloadJackModule(fHandle); | ||||
@@ -181,7 +181,7 @@ int JackLoadableInternalClient2::Init(const char* so_name) | |||||
JackLoadableInternalClient1::JackLoadableInternalClient1(JackServer* server, JackSynchro* table, const char* object_data) | JackLoadableInternalClient1::JackLoadableInternalClient1(JackServer* server, JackSynchro* table, const char* object_data) | ||||
: JackLoadableInternalClient(server, table) | : JackLoadableInternalClient(server, table) | ||||
{ | { | ||||
strncpy(fObjectData, object_data, JACK_LOAD_INIT_LIMIT); | |||||
strncpy(fObjectData, object_data, JACK_LOAD_INIT_LIMIT); | |||||
} | } | ||||
JackLoadableInternalClient2::JackLoadableInternalClient2(JackServer* server, JackSynchro* table, const JSList* parameters) | JackLoadableInternalClient2::JackLoadableInternalClient2(JackServer* server, JackSynchro* table, const JSList* parameters) | ||||
@@ -201,7 +201,7 @@ JackLoadableInternalClient::~JackLoadableInternalClient() | |||||
int JackLoadableInternalClient1::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) | int JackLoadableInternalClient1::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) | ||||
{ | { | ||||
int res = -1; | int res = -1; | ||||
if (JackInternalClient::Open(server_name, name, uuid, options, status) == 0) { | if (JackInternalClient::Open(server_name, name, uuid, options, status) == 0) { | ||||
if (fInitialize((jack_client_t*)this, fObjectData) == 0) { | if (fInitialize((jack_client_t*)this, fObjectData) == 0) { | ||||
res = 0; | res = 0; | ||||
@@ -210,14 +210,14 @@ int JackLoadableInternalClient1::Open(const char* server_name, const char* name, | |||||
fFinish = NULL; | fFinish = NULL; | ||||
} | } | ||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
int JackLoadableInternalClient2::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) | int JackLoadableInternalClient2::Open(const char* server_name, const char* name, int uuid, jack_options_t options, jack_status_t* status) | ||||
{ | { | ||||
int res = -1; | int res = -1; | ||||
if (JackInternalClient::Open(server_name, name, uuid, options, status) == 0) { | if (JackInternalClient::Open(server_name, name, uuid, options, status) == 0) { | ||||
if (fInitialize((jack_client_t*)this, fParameters) == 0) { | if (fInitialize((jack_client_t*)this, fParameters) == 0) { | ||||
res = 0; | res = 0; | ||||
@@ -226,7 +226,7 @@ int JackLoadableInternalClient2::Open(const char* server_name, const char* name, | |||||
fFinish = NULL; | fFinish = NULL; | ||||
} | } | ||||
} | } | ||||
return res; | return res; | ||||
} | } | ||||
@@ -136,7 +136,7 @@ class JackInternalClientChannel : public detail::JackClientChannelInterface | |||||
void InternalClientLoad(int refnum, const char* client_name, const char* so_name, const char* objet_data, int options, int* status, int* int_ref, int uuid, 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 uuid, int* result) | ||||
{ | { | ||||
*result = fServer->InternalClientLoad(client_name, so_name, objet_data, options, int_ref, uuid, status); | |||||
*result = fServer->InternalClientLoad1(client_name, so_name, objet_data, options, int_ref, uuid, status); | |||||
} | } | ||||
void InternalClientUnload(int refnum, int int_ref, int* status, int* result) | void InternalClientUnload(int refnum, int int_ref, int* status, int* result) | ||||
@@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -32,7 +32,7 @@ namespace Jack | |||||
\brief Client on the library side. | \brief Client on the library side. | ||||
*/ | */ | ||||
class JackLibClient : public JackClient | |||||
class SERVER_EXPORT JackLibClient : public JackClient | |||||
{ | { | ||||
private: | private: | ||||
@@ -12,7 +12,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
#include "JackError.h" | #include "JackError.h" | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -42,13 +42,13 @@ class JackClient; | |||||
\brief Global library static structure: singleton kind of pattern. | \brief Global library static structure: singleton kind of pattern. | ||||
*/ | */ | ||||
struct JackLibGlobals | |||||
struct SERVER_EXPORT JackLibGlobals | |||||
{ | { | ||||
JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | JackShmReadWritePtr<JackGraphManager> fGraphManager; /*! Shared memory Port manager */ | ||||
JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | JackShmReadWritePtr<JackEngineControl> fEngineControl; /*! Shared engine control */ // transport engine has to be writable | ||||
JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */ | JackSynchro fSynchroTable[CLIENT_NUM]; /*! Shared synchro table */ | ||||
sigset_t fProcessSignals; | sigset_t fProcessSignals; | ||||
static int fClientCount; | static int fClientCount; | ||||
static JackLibGlobals* fGlobals; | static JackLibGlobals* fGlobals; | ||||
@@ -67,7 +67,7 @@ struct JackLibGlobals | |||||
sigemptyset(&signals); | sigemptyset(&signals); | ||||
sigaddset(&signals, SIGPIPE); | sigaddset(&signals, SIGPIPE); | ||||
sigprocmask(SIG_BLOCK, &signals, &fProcessSignals); | sigprocmask(SIG_BLOCK, &signals, &fProcessSignals); | ||||
#endif | |||||
#endif | |||||
} | } | ||||
~JackLibGlobals() | ~JackLibGlobals() | ||||
@@ -83,13 +83,13 @@ struct JackLibGlobals | |||||
// TODO | // TODO | ||||
#else | #else | ||||
sigprocmask(SIG_BLOCK, &fProcessSignals, 0); | sigprocmask(SIG_BLOCK, &fProcessSignals, 0); | ||||
#endif | |||||
#endif | |||||
} | } | ||||
static void Init() | static void Init() | ||||
{ | { | ||||
if (!JackGlobals::fServerRunning && fClientCount > 0) { | if (!JackGlobals::fServerRunning && fClientCount > 0) { | ||||
// Cleanup remaining clients | // Cleanup remaining clients | ||||
jack_error("Jack server was closed but clients are still allocated, cleanup..."); | jack_error("Jack server was closed but clients are still allocated, cleanup..."); | ||||
for (int i = 0; i < CLIENT_NUM; i++) { | for (int i = 0; i < CLIENT_NUM; i++) { | ||||
@@ -101,13 +101,13 @@ struct JackLibGlobals | |||||
JackGlobals::fClientTable[CLIENT_NUM] = NULL; | JackGlobals::fClientTable[CLIENT_NUM] = NULL; | ||||
} | } | ||||
} | } | ||||
// Cleanup global context | // Cleanup global context | ||||
fClientCount = 0; | fClientCount = 0; | ||||
delete fGlobals; | delete fGlobals; | ||||
fGlobals = NULL; | fGlobals = NULL; | ||||
} | } | ||||
if (fClientCount++ == 0 && !fGlobals) { | if (fClientCount++ == 0 && !fGlobals) { | ||||
jack_log("JackLibGlobals Init %x", fGlobals); | jack_log("JackLibGlobals Init %x", fGlobals); | ||||
InitTime(); | InitTime(); | ||||
@@ -27,7 +27,7 @@ JackLibSampleRateResampler::JackLibSampleRateResampler() | |||||
{ | { | ||||
int error; | int error; | ||||
fResampler = src_new(SRC_LINEAR, 1, &error); | fResampler = src_new(SRC_LINEAR, 1, &error); | ||||
if (error != 0) | |||||
if (error != 0) | |||||
jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | ||||
} | } | ||||
@@ -50,7 +50,7 @@ JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality) | |||||
case 4: | case 4: | ||||
quality = SRC_SINC_BEST_QUALITY; | quality = SRC_SINC_BEST_QUALITY; | ||||
break; | break; | ||||
default: | |||||
default: | |||||
quality = SRC_LINEAR; | quality = SRC_LINEAR; | ||||
jack_error("Out of range resample quality"); | jack_error("Out of range resample quality"); | ||||
break; | break; | ||||
@@ -58,7 +58,7 @@ JackLibSampleRateResampler::JackLibSampleRateResampler(unsigned int quality) | |||||
int error; | int error; | ||||
fResampler = src_new(quality, 1, &error); | fResampler = src_new(quality, 1, &error); | ||||
if (error != 0) | |||||
if (error != 0) | |||||
jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | jack_error("JackLibSampleRateResampler::JackLibSampleRateResampler err = %s", src_strerror(error)); | ||||
} | } | ||||
@@ -73,103 +73,103 @@ void JackLibSampleRateResampler::Reset(unsigned int new_size) | |||||
src_reset(fResampler); | src_reset(fResampler); | ||||
} | } | ||||
unsigned int JackLibSampleRateResampler::ReadResample(float* buffer, unsigned int frames) | |||||
unsigned int JackLibSampleRateResampler::ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
{ | { | ||||
jack_ringbuffer_data_t ring_buffer_data[2]; | jack_ringbuffer_data_t ring_buffer_data[2]; | ||||
SRC_DATA src_data; | SRC_DATA src_data; | ||||
unsigned int frames_to_write = frames; | unsigned int frames_to_write = frames; | ||||
unsigned int written_frames = 0; | unsigned int written_frames = 0; | ||||
int res; | int res; | ||||
jack_ringbuffer_get_read_vector(fRingBuffer, ring_buffer_data); | jack_ringbuffer_get_read_vector(fRingBuffer, ring_buffer_data); | ||||
unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(float); | |||||
unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(jack_default_audio_sample_t); | |||||
jack_log("Output available = %ld", available_frames); | jack_log("Output available = %ld", available_frames); | ||||
for (int j = 0; j < 2; j++) { | for (int j = 0; j < 2; j++) { | ||||
if (ring_buffer_data[j].len > 0) { | if (ring_buffer_data[j].len > 0) { | ||||
src_data.data_in = (float*)ring_buffer_data[j].buf; | |||||
src_data.data_in = (jack_default_audio_sample_t*)ring_buffer_data[j].buf; | |||||
src_data.data_out = &buffer[written_frames]; | src_data.data_out = &buffer[written_frames]; | ||||
src_data.input_frames = ring_buffer_data[j].len / sizeof(float); | |||||
src_data.input_frames = ring_buffer_data[j].len / sizeof(jack_default_audio_sample_t); | |||||
src_data.output_frames = frames_to_write; | src_data.output_frames = frames_to_write; | ||||
src_data.end_of_input = 0; | src_data.end_of_input = 0; | ||||
src_data.src_ratio = fRatio; | src_data.src_ratio = fRatio; | ||||
res = src_process(fResampler, &src_data); | res = src_process(fResampler, &src_data); | ||||
if (res != 0) { | if (res != 0) { | ||||
jack_error("JackLibSampleRateResampler::ReadResample ratio = %f err = %s", fRatio, src_strerror(res)); | jack_error("JackLibSampleRateResampler::ReadResample ratio = %f err = %s", fRatio, src_strerror(res)); | ||||
return 0; | return 0; | ||||
} | } | ||||
frames_to_write -= src_data.output_frames_gen; | frames_to_write -= src_data.output_frames_gen; | ||||
written_frames += src_data.output_frames_gen; | written_frames += src_data.output_frames_gen; | ||||
if ((src_data.input_frames_used == 0 || src_data.output_frames_gen == 0) && j == 0) { | if ((src_data.input_frames_used == 0 || src_data.output_frames_gen == 0) && j == 0) { | ||||
jack_log("Output : j = %d input_frames_used = %ld output_frames_gen = %ld frames1 = %lu frames2 = %lu" | jack_log("Output : j = %d input_frames_used = %ld output_frames_gen = %ld frames1 = %lu frames2 = %lu" | ||||
, j, src_data.input_frames_used, src_data.output_frames_gen, ring_buffer_data[0].len, ring_buffer_data[1].len); | , j, src_data.input_frames_used, src_data.output_frames_gen, ring_buffer_data[0].len, ring_buffer_data[1].len); | ||||
} | } | ||||
jack_log("Output : j = %d input_frames_used = %ld output_frames_gen = %ld", j, src_data.input_frames_used, src_data.output_frames_gen); | jack_log("Output : j = %d input_frames_used = %ld output_frames_gen = %ld", j, src_data.input_frames_used, src_data.output_frames_gen); | ||||
jack_ringbuffer_read_advance(fRingBuffer, src_data.input_frames_used * sizeof(float)); | |||||
jack_ringbuffer_read_advance(fRingBuffer, src_data.input_frames_used * sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
} | } | ||||
if (written_frames < frames) { | if (written_frames < frames) { | ||||
jack_error("Output available = %ld", available_frames); | jack_error("Output available = %ld", available_frames); | ||||
jack_error("JackLibSampleRateResampler::ReadResample error written_frames = %ld", written_frames); | jack_error("JackLibSampleRateResampler::ReadResample error written_frames = %ld", written_frames); | ||||
} | } | ||||
return written_frames; | return written_frames; | ||||
} | } | ||||
unsigned int JackLibSampleRateResampler::WriteResample(float* buffer, unsigned int frames) | |||||
unsigned int JackLibSampleRateResampler::WriteResample(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
{ | { | ||||
jack_ringbuffer_data_t ring_buffer_data[2]; | jack_ringbuffer_data_t ring_buffer_data[2]; | ||||
SRC_DATA src_data; | SRC_DATA src_data; | ||||
unsigned int frames_to_read = frames; | unsigned int frames_to_read = frames; | ||||
unsigned int read_frames = 0; | unsigned int read_frames = 0; | ||||
int res; | int res; | ||||
jack_ringbuffer_get_write_vector(fRingBuffer, ring_buffer_data); | jack_ringbuffer_get_write_vector(fRingBuffer, ring_buffer_data); | ||||
unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(float); | |||||
unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(jack_default_audio_sample_t); | |||||
jack_log("Input available = %ld", available_frames); | jack_log("Input available = %ld", available_frames); | ||||
for (int j = 0; j < 2; j++) { | for (int j = 0; j < 2; j++) { | ||||
if (ring_buffer_data[j].len > 0) { | if (ring_buffer_data[j].len > 0) { | ||||
src_data.data_in = &buffer[read_frames]; | src_data.data_in = &buffer[read_frames]; | ||||
src_data.data_out = (float*)ring_buffer_data[j].buf; | |||||
src_data.data_out = (jack_default_audio_sample_t*)ring_buffer_data[j].buf; | |||||
src_data.input_frames = frames_to_read; | src_data.input_frames = frames_to_read; | ||||
src_data.output_frames = (ring_buffer_data[j].len / sizeof(float)); | |||||
src_data.output_frames = (ring_buffer_data[j].len / sizeof(jack_default_audio_sample_t)); | |||||
src_data.end_of_input = 0; | src_data.end_of_input = 0; | ||||
src_data.src_ratio = fRatio; | src_data.src_ratio = fRatio; | ||||
res = src_process(fResampler, &src_data); | res = src_process(fResampler, &src_data); | ||||
if (res != 0) { | if (res != 0) { | ||||
jack_error("JackLibSampleRateResampler::ReadResample ratio = %f err = %s", fRatio, src_strerror(res)); | jack_error("JackLibSampleRateResampler::ReadResample ratio = %f err = %s", fRatio, src_strerror(res)); | ||||
return 0; | return 0; | ||||
} | } | ||||
frames_to_read -= src_data.input_frames_used; | frames_to_read -= src_data.input_frames_used; | ||||
read_frames += src_data.input_frames_used; | read_frames += src_data.input_frames_used; | ||||
if ((src_data.input_frames_used == 0 || src_data.output_frames_gen == 0) && j == 0) { | if ((src_data.input_frames_used == 0 || src_data.output_frames_gen == 0) && j == 0) { | ||||
jack_log("Input : j = %d input_frames_used = %ld output_frames_gen = %ld frames1 = %lu frames2 = %lu" | jack_log("Input : j = %d input_frames_used = %ld output_frames_gen = %ld frames1 = %lu frames2 = %lu" | ||||
, j, src_data.input_frames_used, src_data.output_frames_gen, ring_buffer_data[0].len, ring_buffer_data[1].len); | , j, src_data.input_frames_used, src_data.output_frames_gen, ring_buffer_data[0].len, ring_buffer_data[1].len); | ||||
} | } | ||||
jack_log("Input : j = %d input_frames_used = %ld output_frames_gen = %ld", j, src_data.input_frames_used, src_data.output_frames_gen); | jack_log("Input : j = %d input_frames_used = %ld output_frames_gen = %ld", j, src_data.input_frames_used, src_data.output_frames_gen); | ||||
jack_ringbuffer_write_advance(fRingBuffer, src_data.output_frames_gen * sizeof(float)); | |||||
jack_ringbuffer_write_advance(fRingBuffer, src_data.output_frames_gen * sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
} | } | ||||
if (read_frames < frames) { | if (read_frames < frames) { | ||||
jack_error("Input available = %ld", available_frames); | jack_error("Input available = %ld", available_frames); | ||||
jack_error("JackLibSampleRateResampler::ReadResample error read_frames = %ld", read_frames); | jack_error("JackLibSampleRateResampler::ReadResample error read_frames = %ld", read_frames); | ||||
} | } | ||||
return read_frames; | return read_frames; | ||||
} | } | ||||
@@ -21,6 +21,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#define __JackLibSampleRateResampler__ | #define __JackLibSampleRateResampler__ | ||||
#include "JackResampler.h" | #include "JackResampler.h" | ||||
#include "types.h" | |||||
#include <samplerate.h> | #include <samplerate.h> | ||||
namespace Jack | namespace Jack | ||||
@@ -34,20 +36,20 @@ class JackLibSampleRateResampler : public JackResampler | |||||
{ | { | ||||
private: | private: | ||||
SRC_STATE* fResampler; | SRC_STATE* fResampler; | ||||
public: | public: | ||||
JackLibSampleRateResampler(); | JackLibSampleRateResampler(); | ||||
JackLibSampleRateResampler(unsigned int quality); | JackLibSampleRateResampler(unsigned int quality); | ||||
virtual ~JackLibSampleRateResampler(); | virtual ~JackLibSampleRateResampler(); | ||||
unsigned int ReadResample(float* buffer, unsigned int frames); | |||||
unsigned int WriteResample(float* buffer, unsigned int frames); | |||||
unsigned int ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
unsigned int WriteResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
void Reset(unsigned int new_size); | void Reset(unsigned int new_size); | ||||
}; | }; | ||||
} | } | ||||
@@ -34,7 +34,7 @@ int JackLoopbackDriver::Process() | |||||
{ | { | ||||
// Loopback copy | // Loopback copy | ||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(float) * fEngineControl->fBufferSize); | |||||
memcpy(GetInputBuffer(i), GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
} | } | ||||
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); // Signal all clients | fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); // Signal all clients | ||||
@@ -54,7 +54,7 @@ extern "C" | |||||
{ | { | ||||
#endif | #endif | ||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
{ | { | ||||
jack_driver_desc_t * desc; | jack_driver_desc_t * desc; | ||||
unsigned int i; | unsigned int i; | ||||
@@ -65,7 +65,7 @@ extern "C" | |||||
desc->nparams = 1; | desc->nparams = 1; | ||||
desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | ||||
i = 0; | i = 0; | ||||
strcpy(desc->params[i].name, "channels"); | strcpy(desc->params[i].name, "channels"); | ||||
desc->params[i].character = 'c'; | desc->params[i].character = 'c'; | ||||
@@ -77,12 +77,12 @@ extern "C" | |||||
return desc; | return desc; | ||||
} | } | ||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
{ | { | ||||
const JSList * node; | const JSList * node; | ||||
const jack_driver_param_t * param; | const jack_driver_param_t * param; | ||||
int channels = 2; | int channels = 2; | ||||
for (node = params; node; node = jack_slist_next (node)) { | for (node = params; node; node = jack_slist_next (node)) { | ||||
param = (const jack_driver_param_t *) node->data; | param = (const jack_driver_param_t *) node->data; | ||||
@@ -93,7 +93,7 @@ extern "C" | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
Jack::JackDriverClientInterface* driver = new Jack::JackLoopbackDriver(engine, table); | Jack::JackDriverClientInterface* driver = new Jack::JackLoopbackDriver(engine, table); | ||||
if (driver->Open(1, 1, channels, channels, false, "loopback", "loopback", 0, 0) == 0) { | if (driver->Open(1, 1, channels, channels, false, "loopback", "loopback", 0, 0) == 0) { | ||||
return driver; | return driver; | ||||
@@ -60,11 +60,11 @@ int JackMidiDriver::Open(bool capturing, | |||||
{ | { | ||||
fCaptureChannels = inchannels; | fCaptureChannels = inchannels; | ||||
fPlaybackChannels = outchannels; | fPlaybackChannels = outchannels; | ||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
fRingBuffer[i] = jack_ringbuffer_create(sizeof(float) * BUFFER_SIZE_MAX); | |||||
fRingBuffer[i] = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * BUFFER_SIZE_MAX); | |||||
} | } | ||||
return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | return JackDriver::Open(capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency); | ||||
} | } | ||||
@@ -141,11 +141,11 @@ int JackMidiDriver::ProcessNull() | |||||
int JackMidiDriver::Process() | int JackMidiDriver::Process() | ||||
{ | { | ||||
// Read input buffers for the current cycle | // Read input buffers for the current cycle | ||||
if (Read() < 0) { | |||||
if (Read() < 0) { | |||||
jack_error("JackMidiDriver::Process: read error, skip cycle"); | jack_error("JackMidiDriver::Process: read error, skip cycle"); | ||||
return 0; // Skip cycle, but continue processing... | return 0; // Skip cycle, but continue processing... | ||||
} | } | ||||
fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); | fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); | ||||
if (fEngineControl->fSyncMode) { | if (fEngineControl->fSyncMode) { | ||||
if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, fEngineControl->fTimeOutUsecs) < 0) { | if (fGraphManager->SuspendRefNum(&fClientControl, fSynchroTable, fEngineControl->fTimeOutUsecs) < 0) { | ||||
@@ -153,13 +153,13 @@ int JackMidiDriver::Process() | |||||
return -1; | return -1; | ||||
} | } | ||||
} | } | ||||
// Write output buffers for the current cycle | // Write output buffers for the current cycle | ||||
if (Write() < 0) { | |||||
if (Write() < 0) { | |||||
jack_error("JackMidiDriver::Process: write error, skip cycle"); | jack_error("JackMidiDriver::Process: write error, skip cycle"); | ||||
return 0; // Skip cycle, but continue processing... | return 0; // Skip cycle, but continue processing... | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -72,7 +72,7 @@ static void MidiBufferInit(void* buffer, size_t buffer_size, jack_nframes_t nfra | |||||
JackMidiBuffer* midi = (JackMidiBuffer*)buffer; | JackMidiBuffer* midi = (JackMidiBuffer*)buffer; | ||||
midi->magic = JackMidiBuffer::MAGIC; | midi->magic = JackMidiBuffer::MAGIC; | ||||
/* Since port buffer has actually always BUFFER_SIZE_MAX frames, we can safely use all the size */ | /* Since port buffer has actually always BUFFER_SIZE_MAX frames, we can safely use all the size */ | ||||
midi->buffer_size = BUFFER_SIZE_MAX * sizeof(float); | |||||
midi->buffer_size = BUFFER_SIZE_MAX * sizeof(jack_default_audio_sample_t); | |||||
midi->Reset(nframes); | midi->Reset(nframes); | ||||
} | } | ||||
@@ -135,7 +135,7 @@ static void MidiBufferMixdown(void* mixbuffer, void** src_buffers, int src_count | |||||
static size_t MidiBufferSize() | static size_t MidiBufferSize() | ||||
{ | { | ||||
return BUFFER_SIZE_MAX * sizeof(float); | |||||
return BUFFER_SIZE_MAX * sizeof(jack_default_audio_sample_t); | |||||
} | } | ||||
const JackPortType gMidiPortType = | const JackPortType gMidiPortType = | ||||
@@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -71,7 +71,7 @@ struct SERVER_EXPORT JackMidiEvent | |||||
* but their data (if not inlined) is stored from the end of the same buffer. | * but their data (if not inlined) is stored from the end of the same buffer. | ||||
*/ | */ | ||||
struct JackMidiBuffer | |||||
struct SERVER_EXPORT JackMidiBuffer | |||||
{ | { | ||||
enum { MAGIC = 0x900df00d }; | enum { MAGIC = 0x900df00d }; | ||||
@@ -36,7 +36,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#endif | #endif | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#include "celt/celt.h" | |||||
#include <celt/celt.h> | |||||
#endif | #endif | ||||
#define MIN(x,y) ((x)<(y) ? (x) : (y)) | #define MIN(x,y) ((x)<(y) ? (x) : (y)) | ||||
@@ -153,12 +153,15 @@ namespace Jack | |||||
} | } | ||||
//port = fGraphManager->GetPort ( port_id ); | //port = fGraphManager->GetPort ( port_id ); | ||||
netj.capture_ports = | |||||
jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id); | |||||
netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id); | |||||
if( netj.bitdepth == CELT_MODE ) { | if( netj.bitdepth == CELT_MODE ) { | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_7 | |||||
#if HAVE_CELT_API_0_11 | |||||
celt_int32 lookahead; | |||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | |||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) ); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
celt_int32 lookahead; | celt_int32 lookahead; | ||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | ||||
netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | ||||
@@ -202,12 +205,13 @@ namespace Jack | |||||
} | } | ||||
//port = fGraphManager->GetPort ( port_id ); | //port = fGraphManager->GetPort ( port_id ); | ||||
netj.playback_ports = | |||||
jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id); | |||||
netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id); | |||||
if( netj.bitdepth == CELT_MODE ) { | if( netj.bitdepth == CELT_MODE ) { | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_7 | |||||
#if HAVE_CELT_API_0_11 | |||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | |||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom( celt_mode, 1, NULL ) ); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL ); | ||||
netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | ||||
#else | #else | ||||
@@ -697,10 +701,18 @@ namespace Jack | |||||
{ | { | ||||
// audio port, decode celt data. | // audio port, decode celt data. | ||||
CELTDecoder *decoder = (CELTDecoder *)src_node->data; | CELTDecoder *decoder = (CELTDecoder *)src_node->data; | ||||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); | |||||
else | |||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); | |||||
#else | |||||
if( !packet_payload ) | if( !packet_payload ) | ||||
celt_decode_float( decoder, NULL, net_period_down, buf ); | |||||
celt_decode_float( decoder, NULL, net_period_down, buf ); | |||||
else | else | ||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||||
#endif | |||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | } | ||||
@@ -743,11 +755,15 @@ namespace Jack | |||||
// audio port, encode celt data. | // audio port, encode celt data. | ||||
int encoded_bytes; | int encoded_bytes; | ||||
float *floatbuf = (float *)alloca (sizeof(float) * nframes ); | |||||
memcpy( floatbuf, buf, nframes*sizeof(float) ); | |||||
jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes ); | |||||
memcpy( floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t) ); | |||||
CELTEncoder *encoder = (CELTEncoder *)src_node->data; | CELTEncoder *encoder = (CELTEncoder *)src_node->data; | ||||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||||
encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up ); | |||||
#else | |||||
encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); | encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); | ||||
if( encoded_bytes != (int)net_period_up ) | |||||
#endif | |||||
if( encoded_bytes != (int)net_period_up ) | |||||
jack_error( "something in celt changed. netjack needs to be changed to handle this." ); | jack_error( "something in celt changed. netjack needs to be changed to handle this." ); | ||||
src_node = jack_slist_next( src_node ); | src_node = jack_slist_next( src_node ); | ||||
} | } | ||||
@@ -286,7 +286,7 @@ int JackPort::UnsetAlias(const char* alias) | |||||
void JackPort::ClearBuffer(jack_nframes_t frames) | void JackPort::ClearBuffer(jack_nframes_t frames) | ||||
{ | { | ||||
const JackPortType* type = GetPortType(fTypeId); | const JackPortType* type = GetPortType(fTypeId); | ||||
(type->init)(GetBuffer(), frames * sizeof(float), frames); | |||||
(type->init)(GetBuffer(), frames * sizeof(jack_default_audio_sample_t), frames); | |||||
} | } | ||||
void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size) | void JackPort::MixBuffers(void** src_buffers, int src_count, jack_nframes_t buffer_size) | ||||
@@ -57,7 +57,7 @@ class SERVER_EXPORT JackPort | |||||
bool fInUse; | bool fInUse; | ||||
jack_port_id_t fTied; // Locally tied source port | jack_port_id_t fTied; // Locally tied source port | ||||
float fBuffer[BUFFER_SIZE_MAX + 4]; | |||||
jack_default_audio_sample_t fBuffer[BUFFER_SIZE_MAX + 4]; | |||||
bool IsUsed() const | bool IsUsed() const | ||||
{ | { | ||||
@@ -105,9 +105,9 @@ class SERVER_EXPORT JackPort | |||||
} | } | ||||
// Since we are in shared memory, the resulting pointer cannot be cached, so align it here... | // Since we are in shared memory, the resulting pointer cannot be cached, so align it here... | ||||
float* GetBuffer() | |||||
jack_default_audio_sample_t* GetBuffer() | |||||
{ | { | ||||
return (float*)((long)fBuffer & ~15L) + 4; | |||||
return (jack_default_audio_sample_t*)((long)fBuffer & ~15L) + 4; | |||||
} | } | ||||
int GetRefNum() const; | int GetRefNum() const; | ||||
@@ -26,8 +26,8 @@ namespace Jack | |||||
JackResampler::JackResampler() | JackResampler::JackResampler() | ||||
:fRatio(1),fRingBufferSize(DEFAULT_RB_SIZE) | :fRatio(1),fRingBufferSize(DEFAULT_RB_SIZE) | ||||
{ | { | ||||
fRingBuffer = jack_ringbuffer_create(sizeof(float) * fRingBufferSize); | |||||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize) / 2); | |||||
fRingBuffer = jack_ringbuffer_create(sizeof(jack_default_audio_sample_t) * fRingBufferSize); | |||||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize) / 2); | |||||
} | } | ||||
JackResampler::~JackResampler() | JackResampler::~JackResampler() | ||||
@@ -40,44 +40,44 @@ void JackResampler::Reset(unsigned int new_size) | |||||
{ | { | ||||
fRingBufferSize = new_size; | fRingBufferSize = new_size; | ||||
jack_ringbuffer_reset(fRingBuffer); | jack_ringbuffer_reset(fRingBuffer); | ||||
jack_ringbuffer_reset_size(fRingBuffer, sizeof(float) * fRingBufferSize); | |||||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(float) * fRingBufferSize / 2)); | |||||
jack_ringbuffer_reset_size(fRingBuffer, sizeof(jack_default_audio_sample_t) * fRingBufferSize); | |||||
jack_ringbuffer_read_advance(fRingBuffer, (sizeof(jack_default_audio_sample_t) * fRingBufferSize / 2)); | |||||
} | } | ||||
unsigned int JackResampler::ReadSpace() | unsigned int JackResampler::ReadSpace() | ||||
{ | { | ||||
return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)); | |||||
return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
unsigned int JackResampler::WriteSpace() | unsigned int JackResampler::WriteSpace() | ||||
{ | { | ||||
return (jack_ringbuffer_write_space(fRingBuffer) / sizeof(float)); | |||||
return (jack_ringbuffer_write_space(fRingBuffer) / sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
unsigned int JackResampler::Read(float* buffer, unsigned int frames) | |||||
unsigned int JackResampler::Read(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
{ | { | ||||
size_t len = jack_ringbuffer_read_space(fRingBuffer); | size_t len = jack_ringbuffer_read_space(fRingBuffer); | ||||
jack_log("JackResampler::Read input available = %ld", len / sizeof(float)); | |||||
if (len < frames * sizeof(float)) { | |||||
jack_log("JackResampler::Read input available = %ld", len / sizeof(jack_default_audio_sample_t)); | |||||
if (len < frames * sizeof(jack_default_audio_sample_t)) { | |||||
jack_error("JackResampler::Read : producer too slow, missing frames = %d", frames); | jack_error("JackResampler::Read : producer too slow, missing frames = %d", frames); | ||||
return 0; | return 0; | ||||
} else { | } else { | ||||
jack_ringbuffer_read(fRingBuffer, (char*)buffer, frames * sizeof(float)); | |||||
jack_ringbuffer_read(fRingBuffer, (char*)buffer, frames * sizeof(jack_default_audio_sample_t)); | |||||
return frames; | return frames; | ||||
} | } | ||||
} | } | ||||
unsigned int JackResampler::Write(float* buffer, unsigned int frames) | |||||
unsigned int JackResampler::Write(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
{ | { | ||||
size_t len = jack_ringbuffer_write_space(fRingBuffer); | size_t len = jack_ringbuffer_write_space(fRingBuffer); | ||||
jack_log("JackResampler::Write output available = %ld", len / sizeof(float)); | |||||
if (len < frames * sizeof(float)) { | |||||
jack_log("JackResampler::Write output available = %ld", len / sizeof(jack_default_audio_sample_t)); | |||||
if (len < frames * sizeof(jack_default_audio_sample_t)) { | |||||
jack_error("JackResampler::Write : consumer too slow, skip frames = %d", frames); | jack_error("JackResampler::Write : consumer too slow, skip frames = %d", frames); | ||||
return 0; | return 0; | ||||
} else { | } else { | ||||
jack_ringbuffer_write(fRingBuffer, (char*)buffer, frames * sizeof(float)); | |||||
jack_ringbuffer_write(fRingBuffer, (char*)buffer, frames * sizeof(jack_default_audio_sample_t)); | |||||
return frames; | return frames; | ||||
} | } | ||||
} | } | ||||
@@ -110,12 +110,12 @@ unsigned int JackResampler::Write(void* buffer, unsigned int bytes) | |||||
} | } | ||||
} | } | ||||
unsigned int JackResampler::ReadResample(float* buffer, unsigned int frames) | |||||
unsigned int JackResampler::ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
{ | { | ||||
return Read(buffer, frames); | return Read(buffer, frames); | ||||
} | } | ||||
unsigned int JackResampler::WriteResample(float* buffer, unsigned int frames) | |||||
unsigned int JackResampler::WriteResample(jack_default_audio_sample_t* buffer, unsigned int frames) | |||||
{ | { | ||||
return Write(buffer, frames); | return Write(buffer, frames); | ||||
} | } | ||||
@@ -21,19 +21,20 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#define __JackResampler__ | #define __JackResampler__ | ||||
#include "ringbuffer.h" | #include "ringbuffer.h" | ||||
#include "types.h" | |||||
#include "JackError.h" | #include "JackError.h" | ||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
#define DEFAULT_RB_SIZE 32768 | #define DEFAULT_RB_SIZE 32768 | ||||
#define DEFAULT_ADAPTATIVE_SIZE 2048 | |||||
#define DEFAULT_ADAPTATIVE_SIZE 2048 | |||||
inline float Range(float min, float max, float val) | inline float Range(float min, float max, float val) | ||||
{ | { | ||||
return (val < min) ? min : ((val > max) ? max : val); | return (val < min) ? min : ((val > max) ? max : val); | ||||
} | } | ||||
/*! | /*! | ||||
\brief Base class for Resampler. | \brief Base class for Resampler. | ||||
*/ | */ | ||||
@@ -42,30 +43,30 @@ class JackResampler | |||||
{ | { | ||||
protected: | protected: | ||||
jack_ringbuffer_t* fRingBuffer; | jack_ringbuffer_t* fRingBuffer; | ||||
double fRatio; | double fRatio; | ||||
unsigned int fRingBufferSize; | unsigned int fRingBufferSize; | ||||
public: | public: | ||||
JackResampler(); | JackResampler(); | ||||
virtual ~JackResampler(); | virtual ~JackResampler(); | ||||
virtual void Reset(unsigned int new_size); | virtual void Reset(unsigned int new_size); | ||||
virtual unsigned int ReadResample(float* buffer, unsigned int frames); | |||||
virtual unsigned int WriteResample(float* buffer, unsigned int frames); | |||||
virtual unsigned int Read(float* buffer, unsigned int frames); | |||||
virtual unsigned int Write(float* buffer, unsigned int frames); | |||||
virtual unsigned int ReadResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
virtual unsigned int WriteResample(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
virtual unsigned int Read(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
virtual unsigned int Write(jack_default_audio_sample_t* buffer, unsigned int frames); | |||||
virtual unsigned int Read(void* buffer, unsigned int bytes); | virtual unsigned int Read(void* buffer, unsigned int bytes); | ||||
virtual unsigned int Write(void* buffer, unsigned int bytes); | virtual unsigned int Write(void* buffer, unsigned int bytes); | ||||
virtual unsigned int ReadSpace(); | virtual unsigned int ReadSpace(); | ||||
virtual unsigned int WriteSpace(); | virtual unsigned int WriteSpace(); | ||||
unsigned int GetError() | unsigned int GetError() | ||||
{ | { | ||||
return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2); | return (jack_ringbuffer_read_space(fRingBuffer) / sizeof(float)) - (fRingBufferSize / 2); | ||||
@@ -75,12 +76,12 @@ class JackResampler | |||||
{ | { | ||||
fRatio = Range(0.25, 4.0, ratio); | fRatio = Range(0.25, 4.0, ratio); | ||||
} | } | ||||
double GetRatio() | double GetRatio() | ||||
{ | { | ||||
return fRatio; | return fRatio; | ||||
} | } | ||||
}; | }; | ||||
} | } | ||||
@@ -49,7 +49,16 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio | |||||
fGraphManager = JackGraphManager::Allocate(port_max); | fGraphManager = JackGraphManager::Allocate(port_max); | ||||
fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); | fEngineControl = new JackEngineControl(sync, temporary, timeout, rt, priority, verbose, clock, server_name); | ||||
fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); | fEngine = new JackLockedEngine(fGraphManager, GetSynchroTable(), fEngineControl); | ||||
fFreewheelDriver = new JackThreadedDriver(new JackFreewheelDriver(fEngine, GetSynchroTable())); | |||||
// A distinction is made between the threaded freewheel driver and the | |||||
// regular freewheel driver because the freewheel driver needs to run in | |||||
// threaded mode when freewheel mode is active and needs to run as a slave | |||||
// when freewheel mode isn't active. | |||||
JackFreewheelDriver *freewheelDriver = | |||||
new JackFreewheelDriver(fEngine, GetSynchroTable()); | |||||
fThreadedFreewheelDriver = new JackThreadedDriver(freewheelDriver); | |||||
fFreewheelDriver = freewheelDriver; | |||||
fDriverInfo = new JackDriverInfo(); | fDriverInfo = new JackDriverInfo(); | ||||
fAudioDriver = NULL; | fAudioDriver = NULL; | ||||
fFreewheel = false; | fFreewheel = false; | ||||
@@ -61,9 +70,8 @@ JackServer::JackServer(bool sync, bool temporary, int timeout, bool rt, int prio | |||||
JackServer::~JackServer() | JackServer::~JackServer() | ||||
{ | { | ||||
JackGraphManager::Destroy(fGraphManager); | JackGraphManager::Destroy(fGraphManager); | ||||
delete fAudioDriver; | |||||
delete fDriverInfo; | delete fDriverInfo; | ||||
delete fFreewheelDriver; | |||||
delete fThreadedFreewheelDriver; | |||||
delete fEngine; | delete fEngine; | ||||
delete fEngineControl; | delete fEngineControl; | ||||
} | } | ||||
@@ -88,8 +96,8 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | |||||
goto fail_close3; | goto fail_close3; | ||||
} | } | ||||
if (fFreewheelDriver->Open() < 0) { // before engine open | |||||
jack_error("Cannot open driver"); | |||||
if (fFreewheelDriver->Open() < 0) { | |||||
jack_error("Cannot open freewheel driver"); | |||||
goto fail_close4; | goto fail_close4; | ||||
} | } | ||||
@@ -100,7 +108,7 @@ int JackServer::Open(jack_driver_desc_t* driver_desc, JSList* driver_params) | |||||
fFreewheelDriver->SetMaster(false); | fFreewheelDriver->SetMaster(false); | ||||
fAudioDriver->SetMaster(true); | fAudioDriver->SetMaster(true); | ||||
fAudioDriver->AddSlave(fFreewheelDriver); // After ??? | |||||
fAudioDriver->AddSlave(fFreewheelDriver); | |||||
InitTime(); | InitTime(); | ||||
SetClockSource(fEngineControl->fClockSource); | SetClockSource(fEngineControl->fClockSource); | ||||
return 0; | return 0; | ||||
@@ -136,14 +144,14 @@ int JackServer::Close() | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackServer::InternalClientLoad(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status) | |||||
int JackServer::InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status) | |||||
{ | { | ||||
JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data); | JackLoadableInternalClient* client = new JackLoadableInternalClient1(JackServerGlobals::fInstance, GetSynchroTable(), objet_data); | ||||
assert(client); | assert(client); | ||||
return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); | return InternalClientLoadAux(client, so_name, client_name, options, int_ref, uuid, status); | ||||
} | } | ||||
int JackServer::InternalClientLoad(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status) | |||||
int JackServer::InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status) | |||||
{ | { | ||||
JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters); | JackLoadableInternalClient* client = new JackLoadableInternalClient2(JackServerGlobals::fInstance, GetSynchroTable(), parameters); | ||||
assert(client); | assert(client); | ||||
@@ -154,6 +162,8 @@ int JackServer::InternalClientLoadAux(JackLoadableInternalClient* client, const | |||||
{ | { | ||||
// Clear status | // Clear status | ||||
*status = 0; | *status = 0; | ||||
// Client object is internally kept in JackEngine | |||||
if ((client->Init(so_name) < 0) || (client->Open(JACK_DEFAULT_SERVER_NAME, client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) { | if ((client->Init(so_name) < 0) || (client->Open(JACK_DEFAULT_SERVER_NAME, client_name, uuid, (jack_options_t)options, (jack_status_t*)status) < 0)) { | ||||
delete client; | delete client; | ||||
int my_status1 = *status | JackFailure; | int my_status1 = *status | JackFailure; | ||||
@@ -178,7 +188,18 @@ int JackServer::Start() | |||||
int JackServer::Stop() | int JackServer::Stop() | ||||
{ | { | ||||
jack_log("JackServer::Stop"); | jack_log("JackServer::Stop"); | ||||
return fAudioDriver->Stop(); | |||||
if (fFreewheel) { | |||||
return fThreadedFreewheelDriver->Stop(); | |||||
} else { | |||||
return fAudioDriver->Stop(); | |||||
} | |||||
} | |||||
bool JackServer::IsRunning() | |||||
{ | |||||
jack_log("JackServer::IsRunning"); | |||||
assert(fAudioDriver); | |||||
return fAudioDriver->IsRunning(); | |||||
} | } | ||||
int JackServer::SetBufferSize(jack_nframes_t buffer_size) | int JackServer::SetBufferSize(jack_nframes_t buffer_size) | ||||
@@ -236,10 +257,11 @@ int JackServer::SetFreewheel(bool onoff) | |||||
return -1; | return -1; | ||||
} else { | } else { | ||||
fFreewheel = false; | fFreewheel = false; | ||||
fFreewheelDriver->Stop(); | |||||
fThreadedFreewheelDriver->Stop(); | |||||
fGraphManager->Restore(&fConnectionState); // Restore previous connection state | fGraphManager->Restore(&fConnectionState); // Restore previous connection state | ||||
fEngine->NotifyFreewheel(onoff); | fEngine->NotifyFreewheel(onoff); | ||||
fFreewheelDriver->SetMaster(false); | fFreewheelDriver->SetMaster(false); | ||||
fAudioDriver->SetMaster(true); | |||||
return fAudioDriver->Start(); | return fAudioDriver->Start(); | ||||
} | } | ||||
} else { | } else { | ||||
@@ -249,8 +271,9 @@ int JackServer::SetFreewheel(bool onoff) | |||||
fGraphManager->Save(&fConnectionState); // Save connection state | fGraphManager->Save(&fConnectionState); // Save connection state | ||||
fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum); | fGraphManager->DisconnectAllPorts(fAudioDriver->GetClientControl()->fRefNum); | ||||
fEngine->NotifyFreewheel(onoff); | fEngine->NotifyFreewheel(onoff); | ||||
fAudioDriver->SetMaster(false); | |||||
fFreewheelDriver->SetMaster(true); | fFreewheelDriver->SetMaster(true); | ||||
return fFreewheelDriver->Start(); | |||||
return fThreadedFreewheelDriver->Start(); | |||||
} else { | } else { | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -269,7 +292,6 @@ void JackServer::Notify(int refnum, int notify, int value) | |||||
case kXRunCallback: | case kXRunCallback: | ||||
fEngine->NotifyXRun(refnum); | fEngine->NotifyXRun(refnum); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -295,11 +317,11 @@ JackDriverInfo* JackServer::AddSlave(jack_driver_desc_t* driver_desc, JSList* dr | |||||
if (slave == NULL) { | if (slave == NULL) { | ||||
delete info; | delete info; | ||||
return NULL; | return NULL; | ||||
} else { | |||||
slave->Attach(); | |||||
fAudioDriver->AddSlave(slave); | |||||
return info; | |||||
} | } | ||||
slave->Attach(); | |||||
slave->SetMaster(false); | |||||
fAudioDriver->AddSlave(slave); | |||||
return info; | |||||
} | } | ||||
void JackServer::RemoveSlave(JackDriverInfo* info) | void JackServer::RemoveSlave(JackDriverInfo* info) | ||||
@@ -321,33 +343,30 @@ int JackServer::SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_par | |||||
JackDriverInfo* info = new JackDriverInfo(); | JackDriverInfo* info = new JackDriverInfo(); | ||||
JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); | JackDriverClientInterface* master = info->Open(driver_desc, fEngine, GetSynchroTable(), driver_params); | ||||
if (master == NULL || info == NULL) { | |||||
if (master == NULL) { | |||||
delete info; | delete info; | ||||
delete master; | |||||
return -1; | return -1; | ||||
} else { | |||||
} | |||||
// Get slaves list | |||||
std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves(); | |||||
std::list<JackDriverInterface*>::const_iterator it; | |||||
// Get slaves list | |||||
std::list<JackDriverInterface*> slave_list = fAudioDriver->GetSlaves(); | |||||
std::list<JackDriverInterface*>::const_iterator it; | |||||
// Move slaves in new master | |||||
for (it = slave_list.begin(); it != slave_list.end(); it++) { | |||||
JackDriverInterface* slave = *it; | |||||
master->AddSlave(slave); | |||||
} | |||||
// Move slaves in new master | |||||
for (it = slave_list.begin(); it != slave_list.end(); it++) { | |||||
JackDriverInterface* slave = *it; | |||||
master->AddSlave(slave); | |||||
} | |||||
// Delete old master | |||||
delete fAudioDriver; | |||||
delete fDriverInfo; | |||||
// Delete old master | |||||
delete fDriverInfo; | |||||
// Activate master | |||||
fAudioDriver = master; | |||||
fDriverInfo = info; | |||||
fAudioDriver->Attach(); | |||||
fAudioDriver->SetMaster(true); | |||||
return fAudioDriver->Start(); | |||||
} | |||||
// Activate master | |||||
fAudioDriver = master; | |||||
fDriverInfo = info; | |||||
fAudioDriver->Attach(); | |||||
fAudioDriver->SetMaster(true); | |||||
return fAudioDriver->Start(); | |||||
} | } | ||||
//---------------------- | //---------------------- | ||||
@@ -50,6 +50,7 @@ class SERVER_EXPORT JackServer | |||||
JackDriverInfo* fDriverInfo; | JackDriverInfo* fDriverInfo; | ||||
JackDriverClientInterface* fAudioDriver; | JackDriverClientInterface* fAudioDriver; | ||||
JackDriverClientInterface* fFreewheelDriver; | JackDriverClientInterface* fFreewheelDriver; | ||||
JackDriverClientInterface* fThreadedFreewheelDriver; | |||||
JackLockedEngine* fEngine; | JackLockedEngine* fEngine; | ||||
JackEngineControl* fEngineControl; | JackEngineControl* fEngineControl; | ||||
JackGraphManager* fGraphManager; | JackGraphManager* fGraphManager; | ||||
@@ -57,7 +58,7 @@ class SERVER_EXPORT JackServer | |||||
JackConnectionManager fConnectionState; | JackConnectionManager fConnectionState; | ||||
JackSynchro fSynchroTable[CLIENT_NUM]; | JackSynchro fSynchroTable[CLIENT_NUM]; | ||||
bool fFreewheel; | bool fFreewheel; | ||||
int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status); | int InternalClientLoadAux(JackLoadableInternalClient* client, const char* so_name, const char* client_name, int options, int* int_ref, int uuid, int* status); | ||||
public: | public: | ||||
@@ -70,6 +71,7 @@ class SERVER_EXPORT JackServer | |||||
int Start(); | int Start(); | ||||
int Stop(); | int Stop(); | ||||
bool IsRunning(); | |||||
// RT thread | // RT thread | ||||
void Notify(int refnum, int notify, int value); | void Notify(int refnum, int notify, int value); | ||||
@@ -77,19 +79,19 @@ class SERVER_EXPORT JackServer | |||||
// Command thread : API | // Command thread : API | ||||
int SetBufferSize(jack_nframes_t buffer_size); | int SetBufferSize(jack_nframes_t buffer_size); | ||||
int SetFreewheel(bool onoff); | int SetFreewheel(bool onoff); | ||||
int InternalClientLoad(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status); | |||||
int InternalClientLoad(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status); | |||||
int InternalClientLoad1(const char* client_name, const char* so_name, const char* objet_data, int options, int* int_ref, int uuid, int* status); | |||||
int InternalClientLoad2(const char* client_name, const char* so_name, const JSList * parameters, int options, int* int_ref, int uuid, int* status); | |||||
void ClientKill(int refnum); | void ClientKill(int refnum); | ||||
// Transport management | // Transport management | ||||
int ReleaseTimebase(int refnum); | int ReleaseTimebase(int refnum); | ||||
int SetTimebaseCallback(int refnum, int conditional); | int SetTimebaseCallback(int refnum, int conditional); | ||||
// Backend management | // Backend management | ||||
JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); | JackDriverInfo* AddSlave(jack_driver_desc_t* driver_desc, JSList* driver_params); | ||||
void RemoveSlave(JackDriverInfo* info); | void RemoveSlave(JackDriverInfo* info); | ||||
int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params); | int SwitchMaster(jack_driver_desc_t* driver_desc, JSList* driver_params); | ||||
// Object access | // Object access | ||||
JackLockedEngine* GetEngine(); | JackLockedEngine* GetEngine(); | ||||
JackEngineControl* GetEngineControl(); | JackEngineControl* GetEngineControl(); | ||||
@@ -63,7 +63,7 @@ jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t optio | |||||
} | } | ||||
jack_log("jack_client_new %s", client_name); | jack_log("jack_client_new %s", client_name); | ||||
if (status == NULL) /* no status from caller? */ | if (status == NULL) /* no status from caller? */ | ||||
status = &my_status; /* use local status word */ | status = &my_status; /* use local status word */ | ||||
*status = (jack_status_t)0; | *status = (jack_status_t)0; | ||||
@@ -77,13 +77,13 @@ jack_client_t* jack_client_new_aux(const char* client_name, jack_options_t optio | |||||
/* parse variable arguments */ | /* parse variable arguments */ | ||||
jack_varargs_init(&va); | jack_varargs_init(&va); | ||||
if (!JackServerGlobals::Init()) { // jack server initialisation | if (!JackServerGlobals::Init()) { // jack server initialisation | ||||
int my_status1 = (JackFailure | JackServerError); | int my_status1 = (JackFailure | JackServerError); | ||||
*status = (jack_status_t)my_status1; | *status = (jack_status_t)my_status1; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if (JACK_DEBUG) { | if (JACK_DEBUG) { | ||||
client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | ||||
} else { | } else { | ||||
@@ -114,7 +114,7 @@ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t opti | |||||
} | } | ||||
jack_log("jack_client_open %s", client_name); | jack_log("jack_client_open %s", client_name); | ||||
if (status == NULL) /* no status from caller? */ | if (status == NULL) /* no status from caller? */ | ||||
status = &my_status; /* use local status word */ | status = &my_status; /* use local status word */ | ||||
*status = (jack_status_t)0; | *status = (jack_status_t)0; | ||||
@@ -128,13 +128,13 @@ jack_client_t* jack_client_open_aux(const char* client_name, jack_options_t opti | |||||
/* parse variable arguments */ | /* parse variable arguments */ | ||||
jack_varargs_parse(options, ap, &va); | jack_varargs_parse(options, ap, &va); | ||||
if (!JackServerGlobals::Init()) { // jack server initialisation | if (!JackServerGlobals::Init()) { // jack server initialisation | ||||
int my_status1 = (JackFailure | JackServerError); | int my_status1 = (JackFailure | JackServerError); | ||||
*status = (jack_status_t)my_status1; | *status = (jack_status_t)my_status1; | ||||
return NULL; | return NULL; | ||||
} | } | ||||
if (JACK_DEBUG) { | if (JACK_DEBUG) { | ||||
client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | client = new JackDebugClient(new JackInternalClient(JackServerGlobals::fInstance, GetSynchroTable())); // Debug mode | ||||
} else { | } else { | ||||
@@ -180,7 +180,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||||
{ | { | ||||
#ifdef __CLIENTDEBUG__ | #ifdef __CLIENTDEBUG__ | ||||
JackGlobals::CheckContext("jack_client_close"); | JackGlobals::CheckContext("jack_client_close"); | ||||
#endif | |||||
#endif | |||||
assert(JackGlobals::fOpenMutex); | assert(JackGlobals::fOpenMutex); | ||||
JackGlobals::fOpenMutex->Lock(); | JackGlobals::fOpenMutex->Lock(); | ||||
int res = -1; | int res = -1; | ||||
@@ -200,7 +200,7 @@ EXPORT int jack_client_close(jack_client_t* ext_client) | |||||
EXPORT int jack_get_client_pid(const char *name) | EXPORT int jack_get_client_pid(const char *name) | ||||
{ | { | ||||
return (JackServerGlobals::fInstance != NULL) | |||||
return (JackServerGlobals::fInstance != NULL) | |||||
? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name) | ? JackServerGlobals::fInstance->GetEngine()->GetClientPID(name) | ||||
: 0; | : 0; | ||||
} | } | ||||
@@ -18,6 +18,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
*/ | */ | ||||
#include "JackServerGlobals.h" | #include "JackServerGlobals.h" | ||||
#include "JackLockedEngine.h" | |||||
#include "JackTools.h" | #include "JackTools.h" | ||||
#include "shm.h" | #include "shm.h" | ||||
#include <getopt.h> | #include <getopt.h> | ||||
@@ -31,6 +32,8 @@ namespace Jack | |||||
JackServer* JackServerGlobals::fInstance; | JackServer* JackServerGlobals::fInstance; | ||||
unsigned int JackServerGlobals::fUserCount; | unsigned int JackServerGlobals::fUserCount; | ||||
int JackServerGlobals::fRTNotificationSocket; | int JackServerGlobals::fRTNotificationSocket; | ||||
std::map<std::string, JackDriverInfo*> JackServerGlobals::fSlavesList; | |||||
std::map<std::string, int> JackServerGlobals::fInternalsList; | |||||
bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; | bool (* JackServerGlobals::on_device_acquire)(const char * device_name) = NULL; | ||||
void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | void (* JackServerGlobals::on_device_release)(const char * device_name) = NULL; | ||||
@@ -63,6 +66,30 @@ void JackServerGlobals::Stop() | |||||
void JackServerGlobals::Delete() | void JackServerGlobals::Delete() | ||||
{ | { | ||||
jack_log("Jackdmp: delete server"); | jack_log("Jackdmp: delete server"); | ||||
// Slave drivers | |||||
std::map<std::string, JackDriverInfo*>::iterator it1; | |||||
for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) { | |||||
JackDriverInfo* info = (*it1).second; | |||||
if (info) { | |||||
fInstance->RemoveSlave((info)); | |||||
delete (info); | |||||
} | |||||
} | |||||
fSlavesList.clear(); | |||||
// Internal clients | |||||
std::map<std::string, int> ::iterator it2; | |||||
for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) { | |||||
int status; | |||||
int refnum = (*it2).second; | |||||
if (refnum > 0) { | |||||
// Client object is internally kept in JackEngine, and will be desallocated in InternalClientUnload | |||||
fInstance->GetEngine()->InternalClientUnload(refnum, &status); | |||||
} | |||||
} | |||||
fInternalsList.clear(); | |||||
delete fInstance; | delete fInstance; | ||||
fInstance = NULL; | fInstance = NULL; | ||||
} | } | ||||
@@ -80,49 +107,62 @@ bool JackServerGlobals::Init() | |||||
int opt = 0; | int opt = 0; | ||||
int option_index = 0; | int option_index = 0; | ||||
int seen_driver = 0; | |||||
char *driver_name = NULL; | |||||
char **driver_args = NULL; | |||||
JSList* driver_params = NULL; | |||||
char *master_driver_name = NULL; | |||||
char **master_driver_args = NULL; | |||||
JSList* master_driver_params = NULL; | |||||
jack_driver_desc_t* driver_desc; | |||||
jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK; | |||||
int driver_nargs = 1; | int driver_nargs = 1; | ||||
JSList* drivers = NULL; | JSList* drivers = NULL; | ||||
int show_version = 0; | |||||
int loopback = 0; | |||||
int sync = 0; | int sync = 0; | ||||
int rc, i; | int rc, i; | ||||
int ret; | int ret; | ||||
int replace_registry = 0; | |||||
FILE* fp = 0; | FILE* fp = 0; | ||||
char filename[255]; | char filename[255]; | ||||
char buffer[255]; | char buffer[255]; | ||||
int argc = 0; | int argc = 0; | ||||
char* argv[32]; | char* argv[32]; | ||||
jack_timer_type_t clock_source = JACK_TIMER_SYSTEM_CLOCK; | |||||
// First user starts the server | // First user starts the server | ||||
if (fUserCount++ == 0) { | if (fUserCount++ == 0) { | ||||
jack_log("JackServerGlobals Init"); | jack_log("JackServerGlobals Init"); | ||||
jack_driver_desc_t* driver_desc; | |||||
const char *options = "-ad:P:uvshVRL:STFl:t:mn:p:c:"; | |||||
static struct option long_options[] = { | |||||
{ "clock-source", 1, 0, 'c' }, | |||||
{ "driver", 1, 0, 'd' }, | |||||
{ "verbose", 0, 0, 'v' }, | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "port-max", 1, 0, 'p' }, | |||||
{ "no-mlock", 0, 0, 'm' }, | |||||
{ "name", 0, 0, 'n' }, | |||||
{ "unlock", 0, 0, 'u' }, | |||||
{ "realtime", 0, 0, 'R' }, | |||||
{ "realtime-priority", 1, 0, 'P' }, | |||||
{ "timeout", 1, 0, 't' }, | |||||
{ "temporary", 0, 0, 'T' }, | |||||
{ "version", 0, 0, 'V' }, | |||||
{ "silent", 0, 0, 's' }, | |||||
{ "sync", 0, 0, 'S' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:" | |||||
#ifdef __linux__ | |||||
"c:" | |||||
#endif | |||||
; | |||||
struct option long_options[] = { | |||||
#ifdef __linux__ | |||||
{ "clock-source", 1, 0, 'c' }, | |||||
#endif | |||||
{ "loopback-driver", 1, 0, 'L' }, | |||||
{ "audio-driver", 1, 0, 'd' }, | |||||
{ "midi-driver", 1, 0, 'X' }, | |||||
{ "internal-client", 1, 0, 'I' }, | |||||
{ "verbose", 0, 0, 'v' }, | |||||
{ "help", 0, 0, 'h' }, | |||||
{ "port-max", 1, 0, 'p' }, | |||||
{ "no-mlock", 0, 0, 'm' }, | |||||
{ "name", 1, 0, 'n' }, | |||||
{ "unlock", 0, 0, 'u' }, | |||||
{ "realtime", 0, 0, 'R' }, | |||||
{ "no-realtime", 0, 0, 'r' }, | |||||
{ "replace-registry", 0, &replace_registry, 0 }, | |||||
{ "loopback", 0, 0, 'L' }, | |||||
{ "realtime-priority", 1, 0, 'P' }, | |||||
{ "timeout", 1, 0, 't' }, | |||||
{ "temporary", 0, 0, 'T' }, | |||||
{ "version", 0, 0, 'V' }, | |||||
{ "silent", 0, 0, 's' }, | |||||
{ "sync", 0, 0, 'S' }, | |||||
{ 0, 0, 0, 0 } | |||||
}; | |||||
snprintf(filename, 255, "%s/.jackdrc", getenv("HOME")); | snprintf(filename, 255, "%s/.jackdrc", getenv("HOME")); | ||||
fp = fopen(filename, "r"); | fp = fopen(filename, "r"); | ||||
@@ -156,7 +196,7 @@ bool JackServerGlobals::Init() | |||||
opterr = 0; | opterr = 0; | ||||
optind = 1; // Important : to reset argv parsing | optind = 1; // Important : to reset argv parsing | ||||
while (!seen_driver && | |||||
while (!master_driver_name && | |||||
(opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) { | (opt = getopt_long(argc, argv, options, long_options, &option_index)) != EOF) { | ||||
switch (opt) { | switch (opt) { | ||||
@@ -174,34 +214,53 @@ bool JackServerGlobals::Init() | |||||
break; | break; | ||||
case 'd': | case 'd': | ||||
seen_driver = 1; | |||||
driver_name = optarg; | |||||
master_driver_name = optarg; | |||||
break; | break; | ||||
case 'v': | |||||
verbose_aux = 1; | |||||
case 'L': | |||||
loopback = atoi(optarg); | |||||
break; | break; | ||||
case 'S': | |||||
sync = 1; | |||||
case 'X': | |||||
fSlavesList[optarg] = NULL; | |||||
break; | break; | ||||
case 'n': | |||||
server_name = optarg; | |||||
case 'I': | |||||
fInternalsList[optarg] = -1; | |||||
break; | |||||
case 'p': | |||||
port_max = (unsigned int)atol(optarg); | |||||
break; | break; | ||||
case 'm': | case 'm': | ||||
do_mlock = 0; | do_mlock = 0; | ||||
break; | break; | ||||
case 'p': | |||||
port_max = (unsigned int)atol(optarg); | |||||
case 'u': | |||||
do_unlock = 1; | |||||
break; | |||||
case 'v': | |||||
verbose_aux = 1; | |||||
break; | |||||
case 'S': | |||||
sync = 1; | |||||
break; | |||||
case 'n': | |||||
server_name = optarg; | |||||
break; | break; | ||||
case 'P': | case 'P': | ||||
realtime_priority = atoi(optarg); | realtime_priority = atoi(optarg); | ||||
break; | break; | ||||
case 'r': | |||||
realtime = 0; | |||||
break; | |||||
case 'R': | case 'R': | ||||
realtime = 1; | realtime = 1; | ||||
break; | break; | ||||
@@ -214,14 +273,6 @@ bool JackServerGlobals::Init() | |||||
client_timeout = atoi(optarg); | client_timeout = atoi(optarg); | ||||
break; | break; | ||||
case 'u': | |||||
do_unlock = 1; | |||||
break; | |||||
case 'V': | |||||
show_version = 1; | |||||
break; | |||||
default: | default: | ||||
jack_error("unknown option character %c", optopt); | jack_error("unknown option character %c", optopt); | ||||
break; | break; | ||||
@@ -234,9 +285,9 @@ bool JackServerGlobals::Init() | |||||
goto error; | goto error; | ||||
} | } | ||||
driver_desc = jack_find_driver_descriptor(drivers, driver_name); | |||||
driver_desc = jack_find_driver_descriptor(drivers, master_driver_name); | |||||
if (!driver_desc) { | if (!driver_desc) { | ||||
jack_error("jackdmp: unknown driver '%s'", driver_name); | |||||
jack_error("jackdmp: unknown master driver '%s'", master_driver_name); | |||||
goto error; | goto error; | ||||
} | } | ||||
@@ -252,14 +303,14 @@ bool JackServerGlobals::Init() | |||||
goto error; | goto error; | ||||
} | } | ||||
driver_args = (char**)malloc(sizeof(char*) * driver_nargs); | |||||
driver_args[0] = driver_name; | |||||
master_driver_args = (char**)malloc(sizeof(char*) * driver_nargs); | |||||
master_driver_args[0] = master_driver_name; | |||||
for (i = 1; i < driver_nargs; i++) { | for (i = 1; i < driver_nargs; i++) { | ||||
driver_args[i] = argv[optind++]; | |||||
master_driver_args[i] = argv[optind++]; | |||||
} | } | ||||
if (jack_parse_driver_params(driver_desc, driver_nargs, driver_args, &driver_params)) { | |||||
if (jack_parse_driver_params(driver_desc, driver_nargs, master_driver_args, &master_driver_params)) { | |||||
goto error; | goto error; | ||||
} | } | ||||
@@ -294,7 +345,7 @@ bool JackServerGlobals::Init() | |||||
free(argv[i]); | free(argv[i]); | ||||
} | } | ||||
int res = Start(server_name, driver_desc, driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source); | |||||
int res = Start(server_name, driver_desc, master_driver_params, sync, temporary, client_timeout, realtime, realtime_priority, port_max, verbose_aux, clock_source); | |||||
if (res < 0) { | if (res < 0) { | ||||
jack_error("Cannot start server... exit"); | jack_error("Cannot start server... exit"); | ||||
Delete(); | Delete(); | ||||
@@ -303,16 +354,48 @@ bool JackServerGlobals::Init() | |||||
jack_unregister_server(server_name); | jack_unregister_server(server_name); | ||||
goto error; | goto error; | ||||
} | } | ||||
// Slave drivers | |||||
std::map<std::string, JackDriverInfo*>::iterator it1; | |||||
for (it1 = fSlavesList.begin(); it1 != fSlavesList.end(); it1++) { | |||||
const char* name = ((*it1).first).c_str(); | |||||
driver_desc = jack_find_driver_descriptor(drivers, name); | |||||
if (!driver_desc) { | |||||
jack_error("jackdmp: unknown slave driver '%s'", name); | |||||
} else { | |||||
(*it1).second = fInstance->AddSlave(driver_desc, NULL); | |||||
} | |||||
} | |||||
// Loopback driver | |||||
if (loopback > 0) { | |||||
driver_desc = jack_find_driver_descriptor(drivers, "loopback"); | |||||
if (!driver_desc) { | |||||
jack_error("jackdmp: unknown driver '%s'", "loopback"); | |||||
} else { | |||||
fSlavesList["loopback"] = fInstance->AddSlave(driver_desc, NULL); | |||||
} | |||||
} | |||||
// Internal clients | |||||
std::map<std::string, int>::iterator it2; | |||||
for (it2 = fInternalsList.begin(); it2 != fInternalsList.end(); it2++) { | |||||
int status, refnum; | |||||
const char* name = ((*it2).first).c_str(); | |||||
fInstance->InternalClientLoad2(name, name, NULL, JackNullOption, &refnum, -1, &status); | |||||
(*it2).second = refnum; | |||||
} | |||||
} | } | ||||
if (driver_params) | |||||
jack_free_driver_params(driver_params); | |||||
if (master_driver_params) | |||||
jack_free_driver_params(master_driver_params); | |||||
return true; | return true; | ||||
error: | error: | ||||
if (driver_params) | |||||
jack_free_driver_params(driver_params); | |||||
fUserCount--; | |||||
jack_log("JackServerGlobals Init error"); | |||||
if (master_driver_params) | |||||
jack_free_driver_params(master_driver_params); | |||||
Destroy(); | |||||
return false; | return false; | ||||
} | } | ||||
@@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackDriverLoader.h" | #include "JackDriverLoader.h" | ||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#include "JackServer.h" | #include "JackServer.h" | ||||
#include <map> | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -39,6 +40,9 @@ struct SERVER_EXPORT JackServerGlobals | |||||
static JackServer* fInstance; | static JackServer* fInstance; | ||||
static unsigned int fUserCount; | static unsigned int fUserCount; | ||||
static int fRTNotificationSocket; // For debugging purpose | static int fRTNotificationSocket; // For debugging purpose | ||||
static std::map<std::string, JackDriverInfo*> fSlavesList; | |||||
static std::map<std::string, int> fInternalsList; | |||||
static bool (* on_device_acquire)(const char* device_name); | static bool (* on_device_acquire)(const char* device_name); | ||||
static void (* on_device_release)(const char* device_name); | static void (* on_device_release)(const char* device_name); | ||||
@@ -152,6 +152,11 @@ bool JackThreadedDriver::IsRealTime() const | |||||
return fDriver->IsRealTime(); | return fDriver->IsRealTime(); | ||||
} | } | ||||
bool JackThreadedDriver::IsRunning() const | |||||
{ | |||||
return fDriver->IsRunning(); | |||||
} | |||||
int JackThreadedDriver::Start() | int JackThreadedDriver::Start() | ||||
{ | { | ||||
jack_log("JackThreadedDriver::Start"); | jack_log("JackThreadedDriver::Start"); | ||||
@@ -171,9 +176,9 @@ int JackThreadedDriver::Start() | |||||
int JackThreadedDriver::Stop() | int JackThreadedDriver::Stop() | ||||
{ | { | ||||
jack_log("JackThreadedDriver::Stop"); | jack_log("JackThreadedDriver::Stop"); | ||||
switch (fThread.GetStatus()) { | switch (fThread.GetStatus()) { | ||||
// Kill the thread in Init phase | // Kill the thread in Init phase | ||||
case JackThread::kStarting: | case JackThread::kStarting: | ||||
case JackThread::kIniting: | case JackThread::kIniting: | ||||
@@ -182,15 +187,15 @@ int JackThreadedDriver::Stop() | |||||
return -1; | return -1; | ||||
} | } | ||||
break; | break; | ||||
// Stop when the thread cycle is finished | // Stop when the thread cycle is finished | ||||
case JackThread::kRunning: | case JackThread::kRunning: | ||||
if (fThread.Stop() < 0) { | if (fThread.Stop() < 0) { | ||||
jack_error("Cannot stop thread"); | |||||
jack_error("Cannot stop thread"); | |||||
return -1; | return -1; | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
@@ -218,7 +223,7 @@ bool JackThreadedDriver::Init() | |||||
if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) { | if (fThread.AcquireSelfRealTime(GetEngineControl()->fServerPriority) < 0) { | ||||
jack_error("AcquireSelfRealTime error"); | jack_error("AcquireSelfRealTime error"); | ||||
} else { | } else { | ||||
set_threaded_log_function(); | |||||
set_threaded_log_function(); | |||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
@@ -38,14 +38,14 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi | |||||
JackThread fThread; | JackThread fThread; | ||||
JackDriver* fDriver; | JackDriver* fDriver; | ||||
public: | public: | ||||
JackThreadedDriver(JackDriver* driver); | JackThreadedDriver(JackDriver* driver); | ||||
virtual ~JackThreadedDriver(); | virtual ~JackThreadedDriver(); | ||||
virtual int Open(); | virtual int Open(); | ||||
virtual int Open (bool capturing, | virtual int Open (bool capturing, | ||||
bool playing, | bool playing, | ||||
int inchannels, | int inchannels, | ||||
@@ -54,7 +54,7 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi | |||||
const char* capture_driver_name, | const char* capture_driver_name, | ||||
const char* playback_driver_name, | const char* playback_driver_name, | ||||
jack_nframes_t capture_latency, | jack_nframes_t capture_latency, | ||||
jack_nframes_t playback_latency) | |||||
jack_nframes_t playback_latency) | |||||
{ | { | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -70,34 +70,35 @@ class SERVER_EXPORT JackThreadedDriver : public JackDriverClientInterface, publi | |||||
jack_nframes_t capture_latency, | jack_nframes_t capture_latency, | ||||
jack_nframes_t playback_latency); | jack_nframes_t playback_latency); | ||||
virtual int Close(); | virtual int Close(); | ||||
virtual int Process(); | virtual int Process(); | ||||
virtual int ProcessNull(); | virtual int ProcessNull(); | ||||
virtual int Attach(); | virtual int Attach(); | ||||
virtual int Detach(); | virtual int Detach(); | ||||
virtual int Read(); | virtual int Read(); | ||||
virtual int Write(); | virtual int Write(); | ||||
virtual int Start(); | virtual int Start(); | ||||
virtual int Stop(); | virtual int Stop(); | ||||
virtual bool IsFixedBufferSize(); | virtual bool IsFixedBufferSize(); | ||||
virtual int SetBufferSize(jack_nframes_t buffer_size); | virtual int SetBufferSize(jack_nframes_t buffer_size); | ||||
virtual int SetSampleRate(jack_nframes_t sample_rate); | virtual int SetSampleRate(jack_nframes_t sample_rate); | ||||
virtual void SetMaster(bool onoff); | virtual void SetMaster(bool onoff); | ||||
virtual bool GetMaster(); | virtual bool GetMaster(); | ||||
virtual void AddSlave(JackDriverInterface* slave); | virtual void AddSlave(JackDriverInterface* slave); | ||||
virtual void RemoveSlave(JackDriverInterface* slave); | virtual void RemoveSlave(JackDriverInterface* slave); | ||||
virtual std::list<JackDriverInterface*> GetSlaves(); | virtual std::list<JackDriverInterface*> GetSlaves(); | ||||
virtual int ProcessSlaves(); | virtual int ProcessSlaves(); | ||||
virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | virtual int ClientNotify(int refnum, const char* name, int notify, int sync, const char* message, int value1, int value2); | ||||
virtual JackClientControl* GetClientControl() const; | virtual JackClientControl* GetClientControl() const; | ||||
virtual bool IsRealTime() const; | virtual bool IsRealTime() const; | ||||
virtual bool IsRunning() const; | |||||
// JackRunnableInterface interface | // JackRunnableInterface interface | ||||
virtual bool Execute(); | virtual bool Execute(); | ||||
virtual bool Init(); | virtual bool Init(); | ||||
@@ -33,7 +33,7 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <iostream> | #include <iostream> | ||||
/* dynamically load libjack and forward all registered calls to libjack | |||||
/* dynamically load libjack and forward all registered calls to libjack | |||||
(similar to what relaytool is trying to do, but more portably..) | (similar to what relaytool is trying to do, but more portably..) | ||||
*/ | */ | ||||
@@ -61,15 +61,15 @@ static void __attribute__((constructor)) tryload_libjack() | |||||
#else | #else | ||||
libjack_handle = dlopen("libjack.so.0", RTLD_LAZY); | libjack_handle = dlopen("libjack.so.0", RTLD_LAZY); | ||||
#endif | #endif | ||||
} | } | ||||
libjack_is_present = (libjack_handle != 0); | libjack_is_present = (libjack_handle != 0); | ||||
} | } | ||||
void *load_jack_function(const char *fn_name) | |||||
void *load_jack_function(const char *fn_name) | |||||
{ | { | ||||
void *fn = 0; | void *fn = 0; | ||||
if (!libjack_handle) { | |||||
if (!libjack_handle) { | |||||
fprintf (stderr, "libjack not found, so do not try to load %s ffs !\n", fn_name); | fprintf (stderr, "libjack not found, so do not try to load %s ffs !\n", fn_name); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -78,13 +78,13 @@ void *load_jack_function(const char *fn_name) | |||||
#else | #else | ||||
fn = dlsym(libjack_handle, fn_name); | fn = dlsym(libjack_handle, fn_name); | ||||
#endif | #endif | ||||
if (!fn) { | |||||
if (!fn) { | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
char* lpMsgBuf; | char* lpMsgBuf; | ||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL ); | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf,0,NULL ); | ||||
fprintf (stderr, "could not GetProcAddress( %s ), %s \n", fn_name, lpMsgBuf) ; | fprintf (stderr, "could not GetProcAddress( %s ), %s \n", fn_name, lpMsgBuf) ; | ||||
#else | |||||
fprintf (stderr, "could not dlsym( %s ), %s \n", fn_name, dlerror()) ; | |||||
#else | |||||
fprintf (stderr, "could not dlsym( %s ), %s \n", fn_name, dlerror()) ; | |||||
#endif | #endif | ||||
} | } | ||||
return fn; | return fn; | ||||
@@ -107,7 +107,7 @@ void *load_jack_function(const char *fn_name) | |||||
if (fn) return (*fn)arguments; \ | if (fn) return (*fn)arguments; \ | ||||
else return (return_type)0; \ | else return (return_type)0; \ | ||||
} | } | ||||
#define DECL_VOID_FUNCTION(fn_name, arguments_types, arguments) \ | #define DECL_VOID_FUNCTION(fn_name, arguments_types, arguments) \ | ||||
typedef void (*fn_name##_ptr_t)arguments_types; \ | typedef void (*fn_name##_ptr_t)arguments_types; \ | ||||
void fn_name arguments_types { \ | void fn_name arguments_types { \ | ||||
@@ -118,8 +118,8 @@ void *load_jack_function(const char *fn_name) | |||||
DECL_VOID_FUNCTION(jack_get_version, (int *major_ptr, int *minor_ptr, int *micro_ptr, int *proto_ptr), (major_ptr, minor_ptr, micro_ptr, proto_ptr)); | DECL_VOID_FUNCTION(jack_get_version, (int *major_ptr, int *minor_ptr, int *micro_ptr, int *proto_ptr), (major_ptr, minor_ptr, micro_ptr, proto_ptr)); | ||||
DECL_FUNCTION_NULL(const char *, jack_get_version_string, (), ()); | |||||
DECL_FUNCTION_NULL(jack_client_t *, jack_client_open, (const char *client_name, jack_options_t options, jack_status_t *status, ...), | |||||
DECL_FUNCTION_NULL(const char *, jack_get_version_string, (), ()); | |||||
DECL_FUNCTION_NULL(jack_client_t *, jack_client_open, (const char *client_name, jack_options_t options, jack_status_t *status, ...), | |||||
(client_name, options, status)); | (client_name, options, status)); | ||||
DECL_FUNCTION(int, jack_client_close, (jack_client_t *client), (client)); | DECL_FUNCTION(int, jack_client_close, (jack_client_t *client), (client)); | ||||
DECL_FUNCTION_NULL(jack_client_t *, jack_client_new, (const char *client_name), (client_name)); | DECL_FUNCTION_NULL(jack_client_t *, jack_client_new, (const char *client_name), (client_name)); | ||||
@@ -135,11 +135,11 @@ DECL_VOID_FUNCTION(jack_on_info_shutdown, (jack_client_t* client, JackInfoShutdo | |||||
DECL_FUNCTION(int, jack_set_process_callback, (jack_client_t *client, | DECL_FUNCTION(int, jack_set_process_callback, (jack_client_t *client, | ||||
JackProcessCallback process_callback, | JackProcessCallback process_callback, | ||||
void *arg), (client, process_callback, arg)); | void *arg), (client, process_callback, arg)); | ||||
DECL_FUNCTION(jack_nframes_t, jack_thread_wait, (jack_client_t *client, int status), (client, status)); | |||||
DECL_FUNCTION(jack_nframes_t, jack_thread_wait, (jack_client_t *client, int status), (client, status)); | |||||
// | // | ||||
DECL_FUNCTION(jack_nframes_t, jack_cycle_wait, (jack_client_t *client), (client)); | |||||
DECL_VOID_FUNCTION(jack_cycle_signal, (jack_client_t *client, int status), (client, status)); | |||||
DECL_FUNCTION(jack_nframes_t, jack_cycle_wait, (jack_client_t *client), (client)); | |||||
DECL_VOID_FUNCTION(jack_cycle_signal, (jack_client_t *client, int status), (client, status)); | |||||
DECL_FUNCTION(int, jack_set_process_thread, (jack_client_t *client, | DECL_FUNCTION(int, jack_set_process_thread, (jack_client_t *client, | ||||
JackThreadCallback fun, | JackThreadCallback fun, | ||||
void *arg), (client, fun, arg)); | void *arg), (client, fun, arg)); | ||||
@@ -149,8 +149,8 @@ DECL_FUNCTION(int, jack_set_thread_init_callback, (jack_client_t *client, | |||||
DECL_FUNCTION(int, jack_set_freewheel_callback, (jack_client_t *client, | DECL_FUNCTION(int, jack_set_freewheel_callback, (jack_client_t *client, | ||||
JackFreewheelCallback freewheel_callback, | JackFreewheelCallback freewheel_callback, | ||||
void *arg), (client, freewheel_callback, arg)); | void *arg), (client, freewheel_callback, arg)); | ||||
DECL_FUNCTION(int, jack_set_freewheel, (jack_client_t *client, int onoff), (client, onoff)); | |||||
DECL_FUNCTION(int, jack_set_buffer_size, (jack_client_t *client, jack_nframes_t nframes), (client, nframes)); | |||||
DECL_FUNCTION(int, jack_set_freewheel, (jack_client_t *client, int onoff), (client, onoff)); | |||||
DECL_FUNCTION(int, jack_set_buffer_size, (jack_client_t *client, jack_nframes_t nframes), (client, nframes)); | |||||
DECL_FUNCTION(int, jack_set_buffer_size_callback, (jack_client_t *client, | DECL_FUNCTION(int, jack_set_buffer_size_callback, (jack_client_t *client, | ||||
JackBufferSizeCallback bufsize_callback, | JackBufferSizeCallback bufsize_callback, | ||||
void *arg), (client, bufsize_callback, arg)); | void *arg), (client, bufsize_callback, arg)); | ||||
@@ -175,6 +175,9 @@ DECL_FUNCTION(int, jack_set_graph_order_callback, (jack_client_t *client, | |||||
DECL_FUNCTION(int, jack_set_xrun_callback, (jack_client_t *client, | DECL_FUNCTION(int, jack_set_xrun_callback, (jack_client_t *client, | ||||
JackXRunCallback xrun_callback, | JackXRunCallback xrun_callback, | ||||
void *arg), (client, xrun_callback, arg)); | void *arg), (client, xrun_callback, arg)); | ||||
DECL_FUNCTION(int, jack_set_latency_callback, (jack_client_t *client, | |||||
JackLatencyCallback latency_callback, | |||||
void *arg), (client, latency_callback, arg)); | |||||
DECL_FUNCTION(int, jack_activate, (jack_client_t *client), (client)); | DECL_FUNCTION(int, jack_activate, (jack_client_t *client), (client)); | ||||
DECL_FUNCTION(int, jack_deactivate, (jack_client_t *client), (client)); | DECL_FUNCTION(int, jack_deactivate, (jack_client_t *client), (client)); | ||||
DECL_FUNCTION_NULL(jack_port_t *, jack_port_register, (jack_client_t *client, const char *port_name, const char *port_type, | DECL_FUNCTION_NULL(jack_port_t *, jack_port_register, (jack_client_t *client, const char *port_name, const char *port_type, | ||||
@@ -198,6 +201,8 @@ DECL_FUNCTION(jack_nframes_t, jack_port_get_latency, (jack_port_t *port), (port) | |||||
DECL_FUNCTION(jack_nframes_t, jack_port_get_total_latency ,(jack_client_t * client, jack_port_t *port), (client, port)); | DECL_FUNCTION(jack_nframes_t, jack_port_get_total_latency ,(jack_client_t * client, jack_port_t *port), (client, port)); | ||||
DECL_VOID_FUNCTION(jack_port_set_latency, (jack_port_t * port, jack_nframes_t frames), (port, frames)); | DECL_VOID_FUNCTION(jack_port_set_latency, (jack_port_t * port, jack_nframes_t frames), (port, frames)); | ||||
DECL_FUNCTION(int, jack_recompute_total_latency, (jack_client_t* client, jack_port_t* port), (client, port)); | DECL_FUNCTION(int, jack_recompute_total_latency, (jack_client_t* client, jack_port_t* port), (client, port)); | ||||
DECL_VOID_FUNCTION(jack_port_get_latency_range, (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range), (port, mode, range)); | |||||
DECL_VOID_FUNCTION(jack_port_set_latency_range, (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range), (port, mode, range)); | |||||
DECL_FUNCTION(int, jack_recompute_total_latencies, (jack_client_t* client),(client)); | DECL_FUNCTION(int, jack_recompute_total_latencies, (jack_client_t* client),(client)); | ||||
DECL_FUNCTION(int, jack_port_set_name, (jack_port_t *port, const char *port_name), (port, port_name)); | DECL_FUNCTION(int, jack_port_set_name, (jack_port_t *port, const char *port_name), (port, port_name)); | ||||
@@ -213,10 +218,11 @@ DECL_FUNCTION(int, jack_disconnect, (jack_client_t * client, const char *source_ | |||||
DECL_FUNCTION(int, jack_port_disconnect, (jack_client_t * client, jack_port_t * port), (client, port)); | DECL_FUNCTION(int, jack_port_disconnect, (jack_client_t * client, jack_port_t * port), (client, port)); | ||||
DECL_FUNCTION(int, jack_port_name_size,(),()); | DECL_FUNCTION(int, jack_port_name_size,(),()); | ||||
DECL_FUNCTION(int, jack_port_type_size,(),()); | DECL_FUNCTION(int, jack_port_type_size,(),()); | ||||
DECL_FUNCTION(size_t, jack_port_type_get_buffer_size, (jack_client_t *client, const char* port_type), (client, port_type)); | |||||
DECL_FUNCTION(jack_nframes_t, jack_get_sample_rate, (jack_client_t *client), (client)); | DECL_FUNCTION(jack_nframes_t, jack_get_sample_rate, (jack_client_t *client), (client)); | ||||
DECL_FUNCTION(jack_nframes_t, jack_get_buffer_size, (jack_client_t *client), (client)); | DECL_FUNCTION(jack_nframes_t, jack_get_buffer_size, (jack_client_t *client), (client)); | ||||
DECL_FUNCTION_NULL(const char**, jack_get_ports, (jack_client_t *client, const char *port_name_pattern, const char * type_name_pattern, | |||||
DECL_FUNCTION_NULL(const char**, jack_get_ports, (jack_client_t *client, const char *port_name_pattern, const char * type_name_pattern, | |||||
unsigned long flags), (client, port_name_pattern, type_name_pattern, flags)); | unsigned long flags), (client, port_name_pattern, type_name_pattern, flags)); | ||||
DECL_FUNCTION_NULL(jack_port_t *, jack_port_by_name, (jack_client_t * client, const char *port_name), (client, port_name)); | DECL_FUNCTION_NULL(jack_port_t *, jack_port_by_name, (jack_client_t * client, const char *port_name), (client, port_name)); | ||||
DECL_FUNCTION_NULL(jack_port_t *, jack_port_by_id, (jack_client_t *client, jack_port_id_t port_id), (client, port_id)); | DECL_FUNCTION_NULL(jack_port_t *, jack_port_by_id, (jack_client_t *client, jack_port_id_t port_id), (client, port_id)); | ||||
@@ -240,7 +246,7 @@ DECL_VOID_FUNCTION(jack_reset_max_delayed_usecs, (jack_client_t *client), (clien | |||||
DECL_FUNCTION(int, jack_release_timebase, (jack_client_t *client), (client)); | DECL_FUNCTION(int, jack_release_timebase, (jack_client_t *client), (client)); | ||||
DECL_FUNCTION(int, jack_set_sync_callback, (jack_client_t *client, JackSyncCallback sync_callback, void *arg), (client, sync_callback, arg)); | DECL_FUNCTION(int, jack_set_sync_callback, (jack_client_t *client, JackSyncCallback sync_callback, void *arg), (client, sync_callback, arg)); | ||||
DECL_FUNCTION(int, jack_set_sync_timeout, (jack_client_t *client, jack_time_t timeout), (client, timeout)); | DECL_FUNCTION(int, jack_set_sync_timeout, (jack_client_t *client, jack_time_t timeout), (client, timeout)); | ||||
DECL_FUNCTION(int, jack_set_timebase_callback, (jack_client_t *client, | |||||
DECL_FUNCTION(int, jack_set_timebase_callback, (jack_client_t *client, | |||||
int conditional, | int conditional, | ||||
JackTimebaseCallback timebase_callback, | JackTimebaseCallback timebase_callback, | ||||
void *arg), (client, conditional, timebase_callback, arg)); | void *arg), (client, conditional, timebase_callback, arg)); | ||||
@@ -272,17 +278,27 @@ DECL_VOID_FUNCTION(jack_set_thread_creator, (jack_thread_creator_t jtc), (jtc)); | |||||
DECL_FUNCTION(char *, jack_get_internal_client_name, (jack_client_t *client, jack_intclient_t intclient), (client, intclient)); | DECL_FUNCTION(char *, jack_get_internal_client_name, (jack_client_t *client, jack_intclient_t intclient), (client, intclient)); | ||||
DECL_FUNCTION(jack_intclient_t, jack_internal_client_handle, (jack_client_t *client, const char *client_name, jack_status_t *status), (client, client_name, status)); | DECL_FUNCTION(jack_intclient_t, jack_internal_client_handle, (jack_client_t *client, const char *client_name, jack_status_t *status), (client, client_name, status)); | ||||
/* | /* | ||||
DECL_FUNCTION(jack_intclient_t, jack_internal_client_load, (jack_client_t *client, | |||||
const char *client_name, | |||||
jack_options_t options, | |||||
DECL_FUNCTION(jack_intclient_t, jack_internal_client_load, (jack_client_t *client, | |||||
const char *client_name, | |||||
jack_options_t options, | |||||
jack_status_t *status | jack_status_t *status | ||||
, ...), (client, client_name, options, status, ...)); | , ...), (client, client_name, options, status, ...)); | ||||
*/ | */ | ||||
DECL_FUNCTION(jack_status_t, jack_internal_client_unload, (jack_client_t *client, jack_intclient_t intclient), (client, intclient)); | DECL_FUNCTION(jack_status_t, jack_internal_client_unload, (jack_client_t *client, jack_intclient_t intclient), (client, intclient)); | ||||
DECL_VOID_FUNCTION(jack_free, (void* ptr), (ptr)); | DECL_VOID_FUNCTION(jack_free, (void* ptr), (ptr)); | ||||
// MIDI | |||||
// session | |||||
DECL_FUNCTION(int, jack_set_session_callback, (jack_client_t* ext_client, JackSessionCallback session_callback, void* arg), (ext_client, session_callback, arg)); | |||||
DECL_FUNCTION(jack_session_command_t*, jack_session_notify, (jack_client_t* ext_client, const char* target, jack_session_event_type_t ev_type, const char* path), (ext_client, target, ev_type, path)Ă ); | |||||
DECL_FUNCTION(int jack_session_reply, (jack_client_t* ext_client, jack_session_event_t *event), (ext_client, event)); | |||||
DECL_VOID_FUNCTION(jack_session_event_free, (jack_session_event_t* ev), (ev)); | |||||
DECL_FUNCTION(char*, jack_get_uuid_for_client_name, (jack_client_t* ext_client, const char* client_name),(ext_client, client_name)); | |||||
DECL_FUNCTION(char*, jack_get_client_name_by_uuid, (jack_client_t* ext_client, const char* client_uuid),(ext_client, client_uuid)); | |||||
DECL_FUNCTION(int, jack_reserve_client_name, (jack_client_t* ext_client, const char* name, const char* uuid),(ext_client, name, uuid)); | |||||
DECL_VOID_FUNCTION(jack_session_commands_free, (jack_session_command_t *cmds),(cmds)); | |||||
DECL_FUNCTION(int, jack_client_has_session_callback, (jack_client_t *client, const char* client_name),(client, client_name)); | |||||
// MIDI | |||||
DECL_FUNCTION(jack_nframes_t, jack_midi_get_event_count, (void* port_buffer), (port_buffer)); | DECL_FUNCTION(jack_nframes_t, jack_midi_get_event_count, (void* port_buffer), (port_buffer)); | ||||
DECL_FUNCTION(int, jack_midi_event_get, (jack_midi_event_t* event, void* port_buffer, jack_nframes_t event_index), (event, port_buffer, event_index)) ; | DECL_FUNCTION(int, jack_midi_event_get, (jack_midi_event_t* event, void* port_buffer, jack_nframes_t event_index), (event, port_buffer, event_index)) ; | ||||
DECL_VOID_FUNCTION(jack_midi_clear_buffer, (void* port_buffer), (port_buffer)); | DECL_VOID_FUNCTION(jack_midi_clear_buffer, (void* port_buffer), (port_buffer)); | ||||
@@ -26,6 +26,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include <getopt.h> | #include <getopt.h> | ||||
#include <cstring> | #include <cstring> | ||||
#include <cstdio> | #include <cstdio> | ||||
#include <list> | |||||
#include "types.h" | #include "types.h" | ||||
#include "jack.h" | #include "jack.h" | ||||
@@ -101,7 +102,8 @@ static void usage(FILE* file) | |||||
" [ --timeout OR -t client-timeout-in-msecs ]\n" | " [ --timeout OR -t client-timeout-in-msecs ]\n" | ||||
" [ --loopback OR -L loopback-port-number ]\n" | " [ --loopback OR -L loopback-port-number ]\n" | ||||
" [ --port-max OR -p maximum-number-of-ports]\n" | " [ --port-max OR -p maximum-number-of-ports]\n" | ||||
" [ --midi OR -X midi-driver ]\n" | |||||
" [ --slave-backend OR -X slave-backend-name ]\n" | |||||
" [ --internal-client OR -I internal-client-name ]\n" | |||||
" [ --verbose OR -v ]\n" | " [ --verbose OR -v ]\n" | ||||
#ifdef __linux__ | #ifdef __linux__ | ||||
" [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n" | " [ --clocksource OR -c [ c(ycle) | h(pet) | s(ystem) ]\n" | ||||
@@ -111,21 +113,21 @@ static void usage(FILE* file) | |||||
" [ --sync OR -S ]\n" | " [ --sync OR -S ]\n" | ||||
" [ --temporary OR -T ]\n" | " [ --temporary OR -T ]\n" | ||||
" [ --version OR -V ]\n" | " [ --version OR -V ]\n" | ||||
" -d backend [ ... backend args ... ]\n" | |||||
" -d master-backend-name [ ... master-backend args ... ]\n" | |||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
" Available backends may include: coreaudio, dummy or net.\n\n" | |||||
" Available master backends may include: coreaudio, dummy or net.\n\n" | |||||
#endif | #endif | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
" Available backends may include: portaudio, dummy or net.\n\n" | |||||
" Available master backends may include: portaudio, dummy or net.\n\n" | |||||
#endif | #endif | ||||
#ifdef __linux__ | #ifdef __linux__ | ||||
" Available backends may include: alsa, dummy, freebob, firewire or net\n\n" | |||||
" Available master backends may include: alsa, dummy, freebob, firewire or net\n\n" | |||||
#endif | #endif | ||||
#if defined(__sun__) || defined(sun) | #if defined(__sun__) || defined(sun) | ||||
" Available backends may include: boomer, oss, dummy or net.\n\n" | |||||
" Available master backends may include: boomer, oss, dummy or net.\n\n" | |||||
#endif | #endif | ||||
" jackdmp -d backend --help\n" | |||||
" to display options for each backend\n\n"); | |||||
" jackdmp -d master-backend-name --help\n" | |||||
" to display options for each master backend\n\n"); | |||||
} | } | ||||
// To put in the control.h interface?? | // To put in the control.h interface?? | ||||
@@ -151,6 +153,20 @@ jackctl_server_get_driver( | |||||
return NULL; | return NULL; | ||||
} | } | ||||
static jackctl_internal_t * jackctl_server_get_internal(jackctl_server_t *server, const char *internal_name) | |||||
{ | |||||
const JSList * 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 (jackctl_internal_t *)node_ptr->data; | |||||
} | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
return NULL; | |||||
} | |||||
static jackctl_parameter_t * | static jackctl_parameter_t * | ||||
jackctl_get_parameter( | jackctl_get_parameter( | ||||
const JSList * parameters_list, | const JSList * parameters_list, | ||||
@@ -174,12 +190,11 @@ int main(int argc, char* argv[]) | |||||
jackctl_server_t * server_ctl; | jackctl_server_t * server_ctl; | ||||
const JSList * server_parameters; | const JSList * server_parameters; | ||||
const char* server_name = "default"; | const char* server_name = "default"; | ||||
jackctl_driver_t * audio_driver_ctl; | |||||
jackctl_driver_t * midi_driver_ctl; | |||||
jackctl_driver_t * master_driver_ctl; | |||||
jackctl_driver_t * loopback_driver_ctl; | jackctl_driver_t * loopback_driver_ctl; | ||||
int replace_registry = 0; | int replace_registry = 0; | ||||
const char *options = "-d:X:P:uvshVrRL:STFl:t:mn:p:" | |||||
const char *options = "-d:X:I:P:uvshVrRL:STFl:t:mn:p:" | |||||
#ifdef __linux__ | #ifdef __linux__ | ||||
"c:" | "c:" | ||||
#endif | #endif | ||||
@@ -192,6 +207,7 @@ int main(int argc, char* argv[]) | |||||
{ "loopback-driver", 1, 0, 'L' }, | { "loopback-driver", 1, 0, 'L' }, | ||||
{ "audio-driver", 1, 0, 'd' }, | { "audio-driver", 1, 0, 'd' }, | ||||
{ "midi-driver", 1, 0, 'X' }, | { "midi-driver", 1, 0, 'X' }, | ||||
{ "internal-client", 1, 0, 'I' }, | |||||
{ "verbose", 0, 0, 'v' }, | { "verbose", 0, 0, 'v' }, | ||||
{ "help", 0, 0, 'h' }, | { "help", 0, 0, 'h' }, | ||||
{ "port-max", 1, 0, 'p' }, | { "port-max", 1, 0, 'p' }, | ||||
@@ -213,14 +229,9 @@ int main(int argc, char* argv[]) | |||||
int i,opt = 0; | int i,opt = 0; | ||||
int option_index = 0; | int option_index = 0; | ||||
bool seen_audio_driver = false; | |||||
bool seen_midi_driver = false; | |||||
char *audio_driver_name = NULL; | |||||
char **audio_driver_args = NULL; | |||||
int audio_driver_nargs = 1; | |||||
char *midi_driver_name = NULL; | |||||
char **midi_driver_args = NULL; | |||||
int midi_driver_nargs = 1; | |||||
char* master_driver_name = NULL; | |||||
char** master_driver_args = NULL; | |||||
int master_driver_nargs = 1; | |||||
int do_mlock = 1; | int do_mlock = 1; | ||||
int do_unlock = 0; | int do_unlock = 0; | ||||
int loopback = 0; | int loopback = 0; | ||||
@@ -229,6 +240,14 @@ int main(int argc, char* argv[]) | |||||
jackctl_parameter_t* param; | jackctl_parameter_t* param; | ||||
union jackctl_parameter_value value; | union jackctl_parameter_value value; | ||||
std::list<char*> internals_list; | |||||
std::list<char*> slaves_list; | |||||
std::list<char*>::iterator it; | |||||
// Assume that we fail. | |||||
int return_value = -1; | |||||
bool notify_sent = false; | |||||
copyright(stdout); | copyright(stdout); | ||||
#if defined(JACK_DBUS) && defined(__linux__) | #if defined(JACK_DBUS) && defined(__linux__) | ||||
server_ctl = jackctl_server_create(audio_acquire, audio_release); | server_ctl = jackctl_server_create(audio_acquire, audio_release); | ||||
@@ -250,7 +269,7 @@ int main(int argc, char* argv[]) | |||||
} | } | ||||
opterr = 0; | opterr = 0; | ||||
while (!seen_audio_driver && | |||||
while (!master_driver_name && | |||||
(opt = getopt_long(argc, argv, options, | (opt = getopt_long(argc, argv, options, | ||||
long_options, &option_index)) != EOF) { | long_options, &option_index)) != EOF) { | ||||
switch (opt) { | switch (opt) { | ||||
@@ -270,15 +289,14 @@ int main(int argc, char* argv[]) | |||||
jackctl_parameter_set_value(param, &value); | jackctl_parameter_set_value(param, &value); | ||||
} else { | } else { | ||||
usage(stdout); | usage(stdout); | ||||
goto fail_free1; | |||||
goto destroy_server; | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
#endif | #endif | ||||
case 'd': | case 'd': | ||||
seen_audio_driver = true; | |||||
audio_driver_name = optarg; | |||||
master_driver_name = optarg; | |||||
break; | break; | ||||
case 'L': | case 'L': | ||||
@@ -286,8 +304,11 @@ int main(int argc, char* argv[]) | |||||
break; | break; | ||||
case 'X': | case 'X': | ||||
seen_midi_driver = true; | |||||
midi_driver_name = optarg; | |||||
slaves_list.push_back(optarg); | |||||
break; | |||||
case 'I': | |||||
internals_list.push_back(optarg); | |||||
break; | break; | ||||
case 'p': | case 'p': | ||||
@@ -385,7 +406,7 @@ int main(int argc, char* argv[]) | |||||
case 'h': | case 'h': | ||||
usage(stdout); | usage(stdout); | ||||
goto fail_free1; | |||||
goto destroy_server; | |||||
} | } | ||||
} | } | ||||
@@ -404,64 +425,65 @@ int main(int argc, char* argv[]) | |||||
return -1; | return -1; | ||||
} | } | ||||
if (!seen_audio_driver) { | |||||
if (!master_driver_name) { | |||||
usage(stderr); | usage(stderr); | ||||
goto fail_free1; | |||||
goto destroy_server; | |||||
} | } | ||||
// Audio driver | |||||
audio_driver_ctl = jackctl_server_get_driver(server_ctl, audio_driver_name); | |||||
if (audio_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unknown driver \"%s\"\n", audio_driver_name); | |||||
goto fail_free1; | |||||
// Master driver | |||||
master_driver_ctl = jackctl_server_get_driver(server_ctl, master_driver_name); | |||||
if (master_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unknown driver \"%s\"\n", master_driver_name); | |||||
goto destroy_server; | |||||
} | } | ||||
if (optind < argc) { | if (optind < argc) { | ||||
audio_driver_nargs = 1 + argc - optind; | |||||
master_driver_nargs = 1 + argc - optind; | |||||
} else { | } else { | ||||
audio_driver_nargs = 1; | |||||
master_driver_nargs = 1; | |||||
} | } | ||||
if (audio_driver_nargs == 0) { | |||||
if (master_driver_nargs == 0) { | |||||
fprintf(stderr, "No driver specified ... hmm. JACK won't do" | fprintf(stderr, "No driver specified ... hmm. JACK won't do" | ||||
" anything when run like this.\n"); | " anything when run like this.\n"); | ||||
goto fail_free1; | |||||
goto destroy_server; | |||||
} | } | ||||
audio_driver_args = (char **) malloc(sizeof(char *) * audio_driver_nargs); | |||||
audio_driver_args[0] = audio_driver_name; | |||||
master_driver_args = (char **) malloc(sizeof(char *) * master_driver_nargs); | |||||
master_driver_args[0] = master_driver_name; | |||||
for (i = 1; i < audio_driver_nargs; i++) { | |||||
audio_driver_args[i] = argv[optind++]; | |||||
for (i = 1; i < master_driver_nargs; i++) { | |||||
master_driver_args[i] = argv[optind++]; | |||||
} | } | ||||
if (jackctl_parse_driver_params(audio_driver_ctl, audio_driver_nargs, audio_driver_args)) { | |||||
goto fail_free1; | |||||
if (jackctl_parse_driver_params(master_driver_ctl, master_driver_nargs, master_driver_args)) { | |||||
goto destroy_server; | |||||
} | } | ||||
// Setup signals then start server | |||||
// Setup signals | |||||
signals = jackctl_setup_signals(0); | signals = jackctl_setup_signals(0); | ||||
if (!jackctl_server_start(server_ctl, audio_driver_ctl)) { | |||||
fprintf(stderr, "Failed to start server\n"); | |||||
goto fail_free1; | |||||
// Open server | |||||
if (! jackctl_server_open(server_ctl, master_driver_ctl)) { | |||||
fprintf(stderr, "Failed to open server\n"); | |||||
goto destroy_server; | |||||
} | } | ||||
// MIDI driver | |||||
if (seen_midi_driver) { | |||||
midi_driver_ctl = jackctl_server_get_driver(server_ctl, midi_driver_name); | |||||
if (midi_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unknown driver \"%s\"\n", midi_driver_name); | |||||
goto fail_free2; | |||||
// Slave drivers | |||||
for (it = slaves_list.begin(); it != slaves_list.end(); it++) { | |||||
jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); | |||||
if (slave_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unknown driver \"%s\"\n", *it); | |||||
goto close_server; | |||||
} | } | ||||
jackctl_server_add_slave(server_ctl, midi_driver_ctl); | |||||
jackctl_server_add_slave(server_ctl, slave_driver_ctl); | |||||
} | } | ||||
// Loopback driver | // Loopback driver | ||||
if (loopback > 0) { | if (loopback > 0) { | ||||
loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback"); | loopback_driver_ctl = jackctl_server_get_driver(server_ctl, "loopback"); | ||||
// XX: What if this fails? | |||||
if (loopback_driver_ctl != NULL) { | if (loopback_driver_ctl != NULL) { | ||||
const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl); | const JSList * loopback_parameters = jackctl_driver_get_parameters(loopback_driver_ctl); | ||||
param = jackctl_get_parameter(loopback_parameters, "channels"); | param = jackctl_get_parameter(loopback_parameters, "channels"); | ||||
@@ -471,27 +493,42 @@ int main(int argc, char* argv[]) | |||||
} | } | ||||
jackctl_server_add_slave(server_ctl, loopback_driver_ctl); | jackctl_server_add_slave(server_ctl, loopback_driver_ctl); | ||||
} | } | ||||
} | |||||
// Start the server | |||||
if (!jackctl_server_start(server_ctl)) { | |||||
fprintf(stderr, "Failed to start server\n"); | |||||
goto close_server; | |||||
} | |||||
// Internal clients | |||||
for (it = internals_list.begin(); it != internals_list.end(); it++) { | |||||
jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); | |||||
if (internal_driver_ctl == NULL) { | |||||
fprintf(stderr, "Unknown internal \"%s\"\n", *it); | |||||
goto stop_server; | |||||
} | |||||
jackctl_server_load_internal(server_ctl, internal_driver_ctl); | |||||
} | } | ||||
notify_server_start(server_name); | notify_server_start(server_name); | ||||
notify_sent = true; | |||||
return_value = 0; | |||||
// Waits for signal | // Waits for signal | ||||
jackctl_wait_signals(signals); | jackctl_wait_signals(signals); | ||||
if (!jackctl_server_stop(server_ctl)) | |||||
stop_server: | |||||
if (! jackctl_server_stop(server_ctl)) { | |||||
fprintf(stderr, "Cannot stop server...\n"); | fprintf(stderr, "Cannot stop server...\n"); | ||||
jackctl_server_destroy(server_ctl); | |||||
notify_server_stop(server_name); | |||||
return 0; | |||||
fail_free1: | |||||
jackctl_server_destroy(server_ctl); | |||||
return -1; | |||||
fail_free2: | |||||
jackctl_server_stop(server_ctl); | |||||
} | |||||
if (notify_sent) { | |||||
notify_server_stop(server_name); | |||||
} | |||||
close_server: | |||||
jackctl_server_close(server_ctl); | |||||
destroy_server: | |||||
jackctl_server_destroy(server_ctl); | jackctl_server_destroy(server_ctl); | ||||
notify_server_stop(server_name); | |||||
return -1; | |||||
return return_value; | |||||
} | } |
@@ -4,7 +4,7 @@ | |||||
Copyright (C) 2008 Nedko Arnaudov | Copyright (C) 2008 Nedko Arnaudov | ||||
Copyright (C) 2008 GRAME | Copyright (C) 2008 GRAME | ||||
This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||
the Free Software Foundation; version 2 of the License. | the Free Software Foundation; version 2 of the License. | ||||
@@ -86,10 +86,10 @@ extern "C" { | |||||
* @{ | * @{ | ||||
*/ | */ | ||||
/** | |||||
/** | |||||
* Call this function to setup process signal handling. As a general | * Call this function to setup process signal handling. As a general | ||||
* rule, it is required for proper operation for the server object. | * rule, it is required for proper operation for the server object. | ||||
* | |||||
* | |||||
* @param flags signals setup flags, use 0 for none. Currently no | * @param flags signals setup flags, use 0 for none. Currently no | ||||
* flags are defined | * flags are defined | ||||
* | * | ||||
@@ -99,9 +99,9 @@ sigset_t | |||||
jackctl_setup_signals( | jackctl_setup_signals( | ||||
unsigned int flags); | unsigned int flags); | ||||
/** | |||||
/** | |||||
* Call this function to wait on a signal set. | * Call this function to wait on a signal set. | ||||
* | |||||
* | |||||
* @param signals signals set to wait on | * @param signals signals set to wait on | ||||
*/ | */ | ||||
void | void | ||||
@@ -123,43 +123,65 @@ jackctl_server_create( | |||||
bool (* on_device_acquire)(const char * device_name), | bool (* on_device_acquire)(const char * device_name), | ||||
void (* on_device_release)(const char * device_name)); | void (* on_device_release)(const char * device_name)); | ||||
/** | |||||
/** | |||||
* Call this function to destroy server object. | * Call this function to destroy server object. | ||||
* | |||||
* | |||||
* @param server server object handle to destroy | * @param server server object handle to destroy | ||||
*/ | */ | ||||
void | void | ||||
jackctl_server_destroy( | jackctl_server_destroy( | ||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
/** | |||||
* Call this function to start JACK server | |||||
* | |||||
/** | |||||
* Call this function to open JACK server | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* @param driver driver to use | * @param driver driver to use | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | */ | ||||
bool | bool | ||||
jackctl_server_start( | |||||
jackctl_server_open( | |||||
jackctl_server_t * server, | jackctl_server_t * server, | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
/** | |||||
* Call this function to start JACK server | |||||
* | |||||
* @param server server object handle | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_start( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to stop JACK server | * Call this function to stop JACK server | ||||
* | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | */ | ||||
bool | bool | ||||
jackctl_server_stop( | jackctl_server_stop( | ||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
/** | |||||
/** | |||||
* Call this function to close JACK server | |||||
* | |||||
* @param server server object handle | |||||
* | |||||
* @return success status: true - success, false - fail | |||||
*/ | |||||
bool | |||||
jackctl_server_close( | |||||
jackctl_server_t * server); | |||||
/** | |||||
* Call this function to get list of available drivers. List node data | * Call this function to get list of available drivers. List node data | ||||
* pointers is a driver object handle (::jackctl_driver_t). | * pointers is a driver object handle (::jackctl_driver_t). | ||||
* | |||||
* | |||||
* @param server server object handle to get drivers for | * @param server server object handle to get drivers for | ||||
* | * | ||||
* @return Single linked list of driver object handles. Must not be | * @return Single linked list of driver object handles. Must not be | ||||
@@ -169,10 +191,10 @@ const JSList * | |||||
jackctl_server_get_drivers_list( | jackctl_server_get_drivers_list( | ||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
/** | |||||
/** | |||||
* Call this function to get list of server parameters. List node data | * Call this function to get list of server parameters. List node data | ||||
* pointers is a parameter object handle (::jackctl_parameter_t). | * pointers is a parameter object handle (::jackctl_parameter_t). | ||||
* | |||||
* | |||||
* @param server server object handle to get parameters for | * @param server server object handle to get parameters for | ||||
* | * | ||||
* @return Single linked list of parameter object handles. Must not be | * @return Single linked list of parameter object handles. Must not be | ||||
@@ -182,10 +204,10 @@ const JSList * | |||||
jackctl_server_get_parameters( | jackctl_server_get_parameters( | ||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
/** | |||||
/** | |||||
* Call this function to get list of available internal clients. List node data | * Call this function to get list of available internal clients. List node data | ||||
* pointers is a internal client object handle (::jackctl_internal_t). | * pointers is a internal client object handle (::jackctl_internal_t). | ||||
* | |||||
* | |||||
* @param server server object handle to get internal clients for | * @param server server object handle to get internal clients for | ||||
* | * | ||||
* @return Single linked list of internal client object handles. Must not be | * @return Single linked list of internal client object handles. Must not be | ||||
@@ -195,12 +217,13 @@ const JSList * | |||||
jackctl_server_get_internals_list( | jackctl_server_get_internals_list( | ||||
jackctl_server_t * server); | jackctl_server_t * server); | ||||
/** | |||||
/** | |||||
* Call this function to load one internal client. | * Call this function to load one internal client. | ||||
* | |||||
* (can be used when the server is running) | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* @param internal internal to use | * @param internal internal to use | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | */ | ||||
bool | bool | ||||
@@ -208,12 +231,13 @@ jackctl_server_load_internal( | |||||
jackctl_server_t * server, | jackctl_server_t * server, | ||||
jackctl_internal_t * internal); | jackctl_internal_t * internal); | ||||
/** | |||||
/** | |||||
* Call this function to unload one internal client. | * Call this function to unload one internal client. | ||||
* | |||||
* (can be used when the server is running) | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* @param internal internal to unload | * @param internal internal to unload | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | */ | ||||
bool | bool | ||||
@@ -221,46 +245,50 @@ jackctl_server_unload_internal( | |||||
jackctl_server_t * server, | jackctl_server_t * server, | ||||
jackctl_internal_t * internal); | jackctl_internal_t * internal); | ||||
/** | |||||
/** | |||||
* Call this function to add a slave in the driver slave list. | * Call this function to add a slave in the driver slave list. | ||||
* | |||||
* (cannot be used when the server is running that is between | |||||
* jackctl_server_start and jackctl_server_stop) | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* @param driver driver to add in the driver slave list. | * @param driver driver to add in the driver slave list. | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | |||||
bool | |||||
*/ | |||||
bool | |||||
jackctl_server_add_slave(jackctl_server_t * server, | jackctl_server_add_slave(jackctl_server_t * server, | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
/** | |||||
* Call this function to remove a slave from the driver slave list. | * Call this function to remove a slave from the driver slave list. | ||||
* | |||||
* (cannot be used when the server is running that is between | |||||
* jackctl_server_start and jackctl_server_stop) | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* @param driver driver to remove from the driver slave list. | * @param driver driver to remove from the driver slave list. | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | |||||
bool | |||||
*/ | |||||
bool | |||||
jackctl_server_remove_slave(jackctl_server_t * server, | jackctl_server_remove_slave(jackctl_server_t * server, | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
/** | |||||
* Call this function to switch master driver. | * Call this function to switch master driver. | ||||
* | |||||
* | |||||
* @param server server object handle | * @param server server object handle | ||||
* @param driver driver to switch to | * @param driver driver to switch to | ||||
* | |||||
* | |||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
*/ | |||||
bool | |||||
*/ | |||||
bool | |||||
jackctl_server_switch_master(jackctl_server_t * server, | jackctl_server_switch_master(jackctl_server_t * server, | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
/** | |||||
* Call this function to get name of driver. | * Call this function to get name of driver. | ||||
* | |||||
* | |||||
* @param driver driver object handle to get name of | * @param driver driver object handle to get name of | ||||
* | * | ||||
* @return driver name. Must not be modified. Always same for same | * @return driver name. Must not be modified. Always same for same | ||||
@@ -270,10 +298,10 @@ const char * | |||||
jackctl_driver_get_name( | jackctl_driver_get_name( | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
/** | |||||
* Call this function to get list of driver parameters. List node data | * Call this function to get list of driver parameters. List node data | ||||
* pointers is a parameter object handle (::jackctl_parameter_t). | * pointers is a parameter object handle (::jackctl_parameter_t). | ||||
* | |||||
* | |||||
* @param driver driver object handle to get parameters for | * @param driver driver object handle to get parameters for | ||||
* | * | ||||
* @return Single linked list of parameter object handles. Must not be | * @return Single linked list of parameter object handles. Must not be | ||||
@@ -283,9 +311,9 @@ const JSList * | |||||
jackctl_driver_get_parameters( | jackctl_driver_get_parameters( | ||||
jackctl_driver_t * driver); | jackctl_driver_t * driver); | ||||
/** | |||||
/** | |||||
* Call this function to get name of internal client. | * Call this function to get name of internal client. | ||||
* | |||||
* | |||||
* @param internal internal object handle to get name of | * @param internal internal object handle to get name of | ||||
* | * | ||||
* @return internal name. Must not be modified. Always same for same | * @return internal name. Must not be modified. Always same for same | ||||
@@ -295,10 +323,10 @@ const char * | |||||
jackctl_internal_get_name( | jackctl_internal_get_name( | ||||
jackctl_internal_t * internal); | jackctl_internal_t * internal); | ||||
/** | |||||
/** | |||||
* Call this function to get list of internal parameters. List node data | * Call this function to get list of internal parameters. List node data | ||||
* pointers is a parameter object handle (::jackctl_parameter_t). | * pointers is a parameter object handle (::jackctl_parameter_t). | ||||
* | |||||
* | |||||
* @param internal internal object handle to get parameters for | * @param internal internal object handle to get parameters for | ||||
* | * | ||||
* @return Single linked list of parameter object handles. Must not be | * @return Single linked list of parameter object handles. Must not be | ||||
@@ -308,9 +336,9 @@ const JSList * | |||||
jackctl_internal_get_parameters( | jackctl_internal_get_parameters( | ||||
jackctl_internal_t * internal); | jackctl_internal_t * internal); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter name. | * Call this function to get parameter name. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get name of | * @param parameter parameter object handle to get name of | ||||
* | * | ||||
* @return parameter name. Must not be modified. Always same for same | * @return parameter name. Must not be modified. Always same for same | ||||
@@ -320,9 +348,9 @@ const char * | |||||
jackctl_parameter_get_name( | jackctl_parameter_get_name( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter short description. | * Call this function to get parameter short description. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get short description of | * @param parameter parameter object handle to get short description of | ||||
* | * | ||||
* @return parameter short description. Must not be modified. Always | * @return parameter short description. Must not be modified. Always | ||||
@@ -332,9 +360,9 @@ const char * | |||||
jackctl_parameter_get_short_description( | jackctl_parameter_get_short_description( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter long description. | * Call this function to get parameter long description. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get long description of | * @param parameter parameter object handle to get long description of | ||||
* | * | ||||
* @return parameter long description. Must not be modified. Always | * @return parameter long description. Must not be modified. Always | ||||
@@ -344,9 +372,9 @@ const char * | |||||
jackctl_parameter_get_long_description( | jackctl_parameter_get_long_description( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter type. | * Call this function to get parameter type. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get type of | * @param parameter parameter object handle to get type of | ||||
* | * | ||||
* @return parameter type. Always same for same parameter object. | * @return parameter type. Always same for same parameter object. | ||||
@@ -355,21 +383,21 @@ jackctl_param_type_t | |||||
jackctl_parameter_get_type( | jackctl_parameter_get_type( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter character. | * Call this function to get parameter character. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get character of | * @param parameter parameter object handle to get character of | ||||
* | * | ||||
* @return character. | |||||
* @return character. | |||||
*/ | */ | ||||
char | char | ||||
jackctl_parameter_get_id( | jackctl_parameter_get_id( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to check whether parameter has been set, or its | * Call this function to check whether parameter has been set, or its | ||||
* default value is being used. | * default value is being used. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to check | * @param parameter parameter object handle to check | ||||
* | * | ||||
* @return true - parameter is set, false - parameter is using default | * @return true - parameter is set, false - parameter is using default | ||||
@@ -379,9 +407,9 @@ bool | |||||
jackctl_parameter_is_set( | jackctl_parameter_is_set( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to reset parameter to its default value. | * Call this function to reset parameter to its default value. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to reset value of | * @param parameter parameter object handle to reset value of | ||||
* | * | ||||
* @return success status: true - success, false - fail | * @return success status: true - success, false - fail | ||||
@@ -390,9 +418,9 @@ bool | |||||
jackctl_parameter_reset( | jackctl_parameter_reset( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter value. | * Call this function to get parameter value. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get value of | * @param parameter parameter object handle to get value of | ||||
* | * | ||||
* @return parameter value. | * @return parameter value. | ||||
@@ -401,9 +429,9 @@ union jackctl_parameter_value | |||||
jackctl_parameter_get_value( | jackctl_parameter_get_value( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to set parameter value. | * Call this function to set parameter value. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get value of | * @param parameter parameter object handle to get value of | ||||
* @param value_ptr pointer to variable containing parameter value | * @param value_ptr pointer to variable containing parameter value | ||||
* | * | ||||
@@ -414,9 +442,9 @@ jackctl_parameter_set_value( | |||||
jackctl_parameter_t * parameter, | jackctl_parameter_t * parameter, | ||||
const union jackctl_parameter_value * value_ptr); | const union jackctl_parameter_value * value_ptr); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter default value. | * Call this function to get parameter default value. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to get default value of | * @param parameter parameter object handle to get default value of | ||||
* | * | ||||
* @return parameter default value. | * @return parameter default value. | ||||
@@ -424,10 +452,10 @@ jackctl_parameter_set_value( | |||||
union jackctl_parameter_value | union jackctl_parameter_value | ||||
jackctl_parameter_get_default_value( | jackctl_parameter_get_default_value( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function check whether parameter has range constraint. | * Call this function check whether parameter has range constraint. | ||||
* | |||||
* | |||||
* @param parameter object handle of parameter to check | * @param parameter object handle of parameter to check | ||||
* | * | ||||
* @return whether parameter has range constraint. | * @return whether parameter has range constraint. | ||||
@@ -436,9 +464,9 @@ bool | |||||
jackctl_parameter_has_range_constraint( | jackctl_parameter_has_range_constraint( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function check whether parameter has enumeration constraint. | * Call this function check whether parameter has enumeration constraint. | ||||
* | |||||
* | |||||
* @param parameter object handle of parameter to check | * @param parameter object handle of parameter to check | ||||
* | * | ||||
* @return whether parameter has enumeration constraint. | * @return whether parameter has enumeration constraint. | ||||
@@ -447,9 +475,9 @@ bool | |||||
jackctl_parameter_has_enum_constraint( | jackctl_parameter_has_enum_constraint( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function get how many enumeration values parameter has. | * Call this function get how many enumeration values parameter has. | ||||
* | |||||
* | |||||
* @param parameter object handle of parameter | * @param parameter object handle of parameter | ||||
* | * | ||||
* @return number of enumeration values | * @return number of enumeration values | ||||
@@ -458,9 +486,9 @@ uint32_t | |||||
jackctl_parameter_get_enum_constraints_count( | jackctl_parameter_get_enum_constraints_count( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter enumeration value. | * Call this function to get parameter enumeration value. | ||||
* | |||||
* | |||||
* @param parameter object handle of parameter | * @param parameter object handle of parameter | ||||
* @param index index of parameter enumeration value | * @param index index of parameter enumeration value | ||||
* | * | ||||
@@ -471,9 +499,9 @@ jackctl_parameter_get_enum_constraint_value( | |||||
jackctl_parameter_t * parameter, | jackctl_parameter_t * parameter, | ||||
uint32_t index); | uint32_t index); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter enumeration value description. | * Call this function to get parameter enumeration value description. | ||||
* | |||||
* | |||||
* @param parameter object handle of parameter | * @param parameter object handle of parameter | ||||
* @param index index of parameter enumeration value | * @param index index of parameter enumeration value | ||||
* | * | ||||
@@ -484,9 +512,9 @@ jackctl_parameter_get_enum_constraint_description( | |||||
jackctl_parameter_t * parameter, | jackctl_parameter_t * parameter, | ||||
uint32_t index); | uint32_t index); | ||||
/** | |||||
/** | |||||
* Call this function to get parameter range. | * Call this function to get parameter range. | ||||
* | |||||
* | |||||
* @param parameter object handle of parameter | * @param parameter object handle of parameter | ||||
* @param min_ptr pointer to variable receiving parameter minimum value | * @param min_ptr pointer to variable receiving parameter minimum value | ||||
* @param max_ptr pointer to variable receiving parameter maximum value | * @param max_ptr pointer to variable receiving parameter maximum value | ||||
@@ -497,10 +525,10 @@ jackctl_parameter_get_range_constraint( | |||||
union jackctl_parameter_value * min_ptr, | union jackctl_parameter_value * min_ptr, | ||||
union jackctl_parameter_value * max_ptr); | union jackctl_parameter_value * max_ptr); | ||||
/** | |||||
/** | |||||
* Call this function to check whether parameter constraint is strict, | * Call this function to check whether parameter constraint is strict, | ||||
* i.e. whether supplying non-matching value will not work for sure. | * i.e. whether supplying non-matching value will not work for sure. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to check | * @param parameter parameter object handle to check | ||||
* | * | ||||
* @return whether parameter constraint is strict. | * @return whether parameter constraint is strict. | ||||
@@ -509,11 +537,11 @@ bool | |||||
jackctl_parameter_constraint_is_strict( | jackctl_parameter_constraint_is_strict( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to check whether parameter has fake values, | * Call this function to check whether parameter has fake values, | ||||
* i.e. values have no user meaningful meaning and only value | * i.e. values have no user meaningful meaning and only value | ||||
* description is meaningful to user. | * description is meaningful to user. | ||||
* | |||||
* | |||||
* @param parameter parameter object handle to check | * @param parameter parameter object handle to check | ||||
* | * | ||||
* @return whether parameter constraint is strict. | * @return whether parameter constraint is strict. | ||||
@@ -522,9 +550,9 @@ bool | |||||
jackctl_parameter_constraint_is_fake_value( | jackctl_parameter_constraint_is_fake_value( | ||||
jackctl_parameter_t * parameter); | jackctl_parameter_t * parameter); | ||||
/** | |||||
/** | |||||
* Call this function to log an error message. | * Call this function to log an error message. | ||||
* | |||||
* | |||||
* @param format string | * @param format string | ||||
*/ | */ | ||||
void | void | ||||
@@ -532,9 +560,9 @@ jack_error( | |||||
const char *format, | const char *format, | ||||
...); | ...); | ||||
/** | |||||
/** | |||||
* Call this function to log an information message. | * Call this function to log an information message. | ||||
* | |||||
* | |||||
* @param format string | * @param format string | ||||
*/ | */ | ||||
void | void | ||||
@@ -542,10 +570,10 @@ jack_info( | |||||
const char *format, | const char *format, | ||||
...); | ...); | ||||
/** | |||||
/** | |||||
* Call this function to log an information message but only when | * Call this function to log an information message but only when | ||||
* verbose mode is enabled. | * verbose mode is enabled. | ||||
* | |||||
* | |||||
* @param format string | * @param format string | ||||
*/ | */ | ||||
void | void | ||||
@@ -365,7 +365,7 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||||
if( netj->bitdepth == CELT_MODE ) | if( netj->bitdepth == CELT_MODE ) | ||||
{ | { | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||||
celt_int32 lookahead; | celt_int32 lookahead; | ||||
netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | ||||
#else | #else | ||||
@@ -398,7 +398,9 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||||
if( netj->bitdepth == CELT_MODE ) { | if( netj->bitdepth == CELT_MODE ) { | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
#if HAVE_CELT_API_0_11 | |||||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create_custom( netj->celt_mode, 1, NULL ) ); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); | netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); | ||||
#else | #else | ||||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); | netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); | ||||
@@ -444,7 +446,10 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||||
jack_slist_append (netj->playback_ports, port); | jack_slist_append (netj->playback_ports, port); | ||||
if( netj->bitdepth == CELT_MODE ) { | if( netj->bitdepth == CELT_MODE ) { | ||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
#if HAVE_CELT_API_0_11 | |||||
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | |||||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) ); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | ||||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | ||||
#else | #else | ||||
@@ -545,18 +550,18 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||||
netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | ||||
jack_client_t * client, | jack_client_t * client, | ||||
const char *name, | |||||
unsigned int capture_ports, | |||||
unsigned int playback_ports, | |||||
unsigned int capture_ports_midi, | |||||
unsigned int playback_ports_midi, | |||||
jack_nframes_t sample_rate, | |||||
jack_nframes_t period_size, | |||||
unsigned int listen_port, | |||||
unsigned int transport_sync, | |||||
unsigned int resample_factor, | |||||
unsigned int resample_factor_up, | |||||
unsigned int bitdepth, | |||||
const char *name, | |||||
unsigned int capture_ports, | |||||
unsigned int playback_ports, | |||||
unsigned int capture_ports_midi, | |||||
unsigned int playback_ports_midi, | |||||
jack_nframes_t sample_rate, | |||||
jack_nframes_t period_size, | |||||
unsigned int listen_port, | |||||
unsigned int transport_sync, | |||||
unsigned int resample_factor, | |||||
unsigned int resample_factor_up, | |||||
unsigned int bitdepth, | |||||
unsigned int use_autoconfig, | unsigned int use_autoconfig, | ||||
unsigned int latency, | unsigned int latency, | ||||
unsigned int redundancy, | unsigned int redundancy, | ||||
@@ -663,74 +668,74 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
netj->srcaddress_valid = 0; | netj->srcaddress_valid = 0; | ||||
if (netj->use_autoconfig) | if (netj->use_autoconfig) | ||||
{ | { | ||||
jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header)); | |||||
#ifdef WIN32 | |||||
int address_size = sizeof( struct sockaddr_in ); | |||||
#else | |||||
socklen_t address_size = sizeof (struct sockaddr_in); | |||||
#endif | |||||
//jack_info ("Waiting for an incoming packet !!!"); | |||||
//jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!"); | |||||
while(1) { | |||||
if( ! netjack_poll( netj->sockfd, 1000 ) ) { | |||||
jack_info ("Waiting aborted"); | |||||
return -1; | |||||
} | |||||
first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size); | |||||
#ifdef WIN32 | |||||
if( first_pack_len == -1 ) { | |||||
first_pack_len = sizeof(jacknet_packet_header); | |||||
break; | |||||
jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header)); | |||||
#ifdef WIN32 | |||||
int address_size = sizeof( struct sockaddr_in ); | |||||
#else | |||||
socklen_t address_size = sizeof (struct sockaddr_in); | |||||
#endif | |||||
//jack_info ("Waiting for an incoming packet !!!"); | |||||
//jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!"); | |||||
while(1) { | |||||
if( ! netjack_poll( netj->sockfd, 1000 ) ) { | |||||
jack_info ("Waiting aborted"); | |||||
return -1; | |||||
} | |||||
first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size); | |||||
#ifdef WIN32 | |||||
if( first_pack_len == -1 ) { | |||||
first_pack_len = sizeof(jacknet_packet_header); | |||||
break; | |||||
} | |||||
#else | |||||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||||
break; | |||||
#endif | |||||
} | } | ||||
#else | |||||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||||
break; | |||||
#endif | |||||
} | |||||
netj->srcaddress_valid = 1; | |||||
netj->srcaddress_valid = 1; | |||||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||||
{ | |||||
packet_header_ntoh (first_packet); | |||||
jack_info ("AutoConfig Override !!!"); | |||||
if (netj->sample_rate != first_packet->sample_rate) | |||||
{ | |||||
jack_info ("AutoConfig Override: Master JACK sample rate = %d", first_packet->sample_rate); | |||||
netj->sample_rate = first_packet->sample_rate; | |||||
} | |||||
if (netj->period_size != first_packet->period_size) | |||||
{ | |||||
jack_info ("AutoConfig Override: Master JACK period size is %d", first_packet->period_size); | |||||
netj->period_size = first_packet->period_size; | |||||
} | |||||
if (netj->capture_channels_audio != first_packet->capture_channels_audio) | |||||
{ | |||||
jack_info ("AutoConfig Override: capture_channels_audio = %d", first_packet->capture_channels_audio); | |||||
netj->capture_channels_audio = first_packet->capture_channels_audio; | |||||
} | |||||
if (netj->capture_channels_midi != first_packet->capture_channels_midi) | |||||
{ | |||||
jack_info ("AutoConfig Override: capture_channels_midi = %d", first_packet->capture_channels_midi); | |||||
netj->capture_channels_midi = first_packet->capture_channels_midi; | |||||
} | |||||
if (netj->playback_channels_audio != first_packet->playback_channels_audio) | |||||
{ | |||||
jack_info ("AutoConfig Override: playback_channels_audio = %d", first_packet->playback_channels_audio); | |||||
netj->playback_channels_audio = first_packet->playback_channels_audio; | |||||
} | |||||
if (netj->playback_channels_midi != first_packet->playback_channels_midi) | |||||
{ | |||||
jack_info ("AutoConfig Override: playback_channels_midi = %d", first_packet->playback_channels_midi); | |||||
netj->playback_channels_midi = first_packet->playback_channels_midi; | |||||
} | |||||
netj->mtu = first_packet->mtu; | |||||
jack_info ("MTU is set to %d bytes", first_packet->mtu); | |||||
netj->latency = first_packet->latency; | |||||
} | |||||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||||
{ | |||||
packet_header_ntoh (first_packet); | |||||
jack_info ("AutoConfig Override !!!"); | |||||
if (netj->sample_rate != first_packet->sample_rate) | |||||
{ | |||||
jack_info ("AutoConfig Override: Master JACK sample rate = %d", first_packet->sample_rate); | |||||
netj->sample_rate = first_packet->sample_rate; | |||||
} | |||||
if (netj->period_size != first_packet->period_size) | |||||
{ | |||||
jack_info ("AutoConfig Override: Master JACK period size is %d", first_packet->period_size); | |||||
netj->period_size = first_packet->period_size; | |||||
} | |||||
if (netj->capture_channels_audio != first_packet->capture_channels_audio) | |||||
{ | |||||
jack_info ("AutoConfig Override: capture_channels_audio = %d", first_packet->capture_channels_audio); | |||||
netj->capture_channels_audio = first_packet->capture_channels_audio; | |||||
} | |||||
if (netj->capture_channels_midi != first_packet->capture_channels_midi) | |||||
{ | |||||
jack_info ("AutoConfig Override: capture_channels_midi = %d", first_packet->capture_channels_midi); | |||||
netj->capture_channels_midi = first_packet->capture_channels_midi; | |||||
} | |||||
if (netj->playback_channels_audio != first_packet->playback_channels_audio) | |||||
{ | |||||
jack_info ("AutoConfig Override: playback_channels_audio = %d", first_packet->playback_channels_audio); | |||||
netj->playback_channels_audio = first_packet->playback_channels_audio; | |||||
} | |||||
if (netj->playback_channels_midi != first_packet->playback_channels_midi) | |||||
{ | |||||
jack_info ("AutoConfig Override: playback_channels_midi = %d", first_packet->playback_channels_midi); | |||||
netj->playback_channels_midi = first_packet->playback_channels_midi; | |||||
} | |||||
netj->mtu = first_packet->mtu; | |||||
jack_info ("MTU is set to %d bytes", first_packet->mtu); | |||||
netj->latency = first_packet->latency; | |||||
} | |||||
} | } | ||||
netj->capture_channels = netj->capture_channels_audio + netj->capture_channels_midi; | netj->capture_channels = netj->capture_channels_audio + netj->capture_channels_midi; | ||||
netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi; | netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi; | ||||
@@ -762,21 +767,21 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
* 1000000.0f); | * 1000000.0f); | ||||
if( netj->latency == 0 ) | if( netj->latency == 0 ) | ||||
netj->deadline_offset = 50*netj->period_usecs; | |||||
netj->deadline_offset = 50*netj->period_usecs; | |||||
else | else | ||||
netj->deadline_offset = netj->period_usecs + 10*netj->latency*netj->period_usecs/100; | |||||
netj->deadline_offset = netj->period_usecs + 10*netj->latency*netj->period_usecs/100; | |||||
if( netj->bitdepth == CELT_MODE ) { | if( netj->bitdepth == CELT_MODE ) { | ||||
// celt mode. | |||||
// TODO: this is a hack. But i dont want to change the packet header. | |||||
netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); | |||||
netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); | |||||
// celt mode. | |||||
// TODO: this is a hack. But i dont want to change the packet header. | |||||
netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); | |||||
netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); | |||||
netj->net_period_down = netj->resample_factor; | |||||
netj->net_period_up = netj->resample_factor_up; | |||||
netj->net_period_down = netj->resample_factor; | |||||
netj->net_period_up = netj->resample_factor_up; | |||||
} else { | } else { | ||||
netj->net_period_down = (float) netj->period_size / (float) netj->resample_factor; | |||||
netj->net_period_up = (float) netj->period_size / (float) netj->resample_factor_up; | |||||
netj->net_period_down = (float) netj->period_size / (float) netj->resample_factor; | |||||
netj->net_period_up = (float) netj->period_size / (float) netj->resample_factor_up; | |||||
} | } | ||||
netj->rx_bufsize = sizeof (jacknet_packet_header) + netj->net_period_down * netj->capture_channels * get_sample_size (netj->bitdepth); | netj->rx_bufsize = sizeof (jacknet_packet_header) + netj->net_period_down * netj->capture_channels * get_sample_size (netj->bitdepth); | ||||
@@ -790,9 +795,9 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
// Special handling for latency=0 | // Special handling for latency=0 | ||||
if( netj->latency == 0 ) | if( netj->latency == 0 ) | ||||
netj->resync_threshold = 0; | |||||
netj->resync_threshold = 0; | |||||
else | else | ||||
netj->resync_threshold = MIN( 15, netj->latency-1 ); | |||||
netj->resync_threshold = MIN( 15, netj->latency-1 ); | |||||
netj->running_free = 0; | netj->running_free = 0; | ||||
@@ -127,19 +127,19 @@ void netjack_detach( netjack_driver_state_t *netj ); | |||||
netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | ||||
jack_client_t * client, | jack_client_t * client, | ||||
const char *name, | |||||
unsigned int capture_ports, | |||||
unsigned int playback_ports, | |||||
unsigned int capture_ports_midi, | |||||
unsigned int playback_ports_midi, | |||||
jack_nframes_t sample_rate, | |||||
jack_nframes_t period_size, | |||||
unsigned int listen_port, | |||||
unsigned int transport_sync, | |||||
unsigned int resample_factor, | |||||
unsigned int resample_factor_up, | |||||
unsigned int bitdepth, | |||||
unsigned int use_autoconfig, | |||||
const char *name, | |||||
unsigned int capture_ports, | |||||
unsigned int playback_ports, | |||||
unsigned int capture_ports_midi, | |||||
unsigned int playback_ports_midi, | |||||
jack_nframes_t sample_rate, | |||||
jack_nframes_t period_size, | |||||
unsigned int listen_port, | |||||
unsigned int transport_sync, | |||||
unsigned int resample_factor, | |||||
unsigned int resample_factor_up, | |||||
unsigned int bitdepth, | |||||
unsigned int use_autoconfig, | |||||
unsigned int latency, | unsigned int latency, | ||||
unsigned int redundancy, | unsigned int redundancy, | ||||
int dont_htonl_floats, | int dont_htonl_floats, | ||||
@@ -130,7 +130,7 @@ int get_sample_size (int bitdepth) | |||||
//JN: why? is this for buffer sizes before or after encoding? | //JN: why? is this for buffer sizes before or after encoding? | ||||
//JN: if the former, why not int16_t, if the latter, shouldn't it depend on -c N? | //JN: if the former, why not int16_t, if the latter, shouldn't it depend on -c N? | ||||
if( bitdepth == CELT_MODE ) | if( bitdepth == CELT_MODE ) | ||||
return sizeof( unsigned char ); | |||||
return sizeof( unsigned char ); | |||||
return sizeof (int32_t); | return sizeof (int32_t); | ||||
} | } | ||||
@@ -328,7 +328,6 @@ cache_packet_add_fragment (cache_packet *pack, char *packet_buf, int rcv_len) | |||||
return; | return; | ||||
} | } | ||||
if (fragment_nr == 0) | if (fragment_nr == 0) | ||||
{ | { | ||||
memcpy (pack->packet_buf, packet_buf, rcv_len); | memcpy (pack->packet_buf, packet_buf, rcv_len); | ||||
@@ -374,7 +373,6 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||||
int timeout; | int timeout; | ||||
#endif | #endif | ||||
jack_time_t now = jack_get_time(); | jack_time_t now = jack_get_time(); | ||||
if( now >= deadline ) | if( now >= deadline ) | ||||
return 0; | return 0; | ||||
@@ -389,7 +387,6 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||||
timeout = lrintf( (float)(deadline - now) / 1000.0 ); | timeout = lrintf( (float)(deadline - now) / 1000.0 ); | ||||
#endif | #endif | ||||
fds.fd = sockfd; | fds.fd = sockfd; | ||||
fds.events = POLLIN; | fds.events = POLLIN; | ||||
@@ -600,24 +597,24 @@ packet_cache_retreive_packet_pointer( packet_cache *pcache, jack_nframes_t frame | |||||
for (i = 0; i < pcache->size; i++) { | for (i = 0; i < pcache->size; i++) { | ||||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) { | if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) { | ||||
cpack = &(pcache->packets[i]); | |||||
cpack = &(pcache->packets[i]); | |||||
break; | break; | ||||
} | |||||
} | |||||
} | } | ||||
if( cpack == NULL ) { | if( cpack == NULL ) { | ||||
//printf( "retreive packet: %d....not found\n", framecnt ); | |||||
return -1; | |||||
//printf( "retreive packet: %d....not found\n", framecnt ); | |||||
return -1; | |||||
} | } | ||||
if( !cache_packet_is_complete( cpack ) ) { | if( !cache_packet_is_complete( cpack ) ) { | ||||
return -1; | |||||
return -1; | |||||
} | } | ||||
// ok. cpack is the one we want and its complete. | // ok. cpack is the one we want and its complete. | ||||
*packet_buf = cpack->packet_buf; | *packet_buf = cpack->packet_buf; | ||||
if( timestamp ) | if( timestamp ) | ||||
*timestamp = cpack->recv_timestamp; | |||||
*timestamp = cpack->recv_timestamp; | |||||
pcache->last_framecnt_retreived_valid = 1; | pcache->last_framecnt_retreived_valid = 1; | ||||
pcache->last_framecnt_retreived = framecnt; | pcache->last_framecnt_retreived = framecnt; | ||||
@@ -634,18 +631,18 @@ packet_cache_release_packet( packet_cache *pcache, jack_nframes_t framecnt ) | |||||
for (i = 0; i < pcache->size; i++) { | for (i = 0; i < pcache->size; i++) { | ||||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) { | if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) { | ||||
cpack = &(pcache->packets[i]); | |||||
cpack = &(pcache->packets[i]); | |||||
break; | break; | ||||
} | |||||
} | |||||
} | } | ||||
if( cpack == NULL ) { | if( cpack == NULL ) { | ||||
//printf( "retreive packet: %d....not found\n", framecnt ); | |||||
return -1; | |||||
//printf( "retreive packet: %d....not found\n", framecnt ); | |||||
return -1; | |||||
} | } | ||||
if( !cache_packet_is_complete( cpack ) ) { | if( !cache_packet_is_complete( cpack ) ) { | ||||
return -1; | |||||
return -1; | |||||
} | } | ||||
cache_packet_reset (cpack); | cache_packet_reset (cpack); | ||||
@@ -661,13 +658,13 @@ packet_cache_get_fill( packet_cache *pcache, jack_nframes_t expected_framecnt ) | |||||
for (i = 0; i < pcache->size; i++) | for (i = 0; i < pcache->size; i++) | ||||
{ | { | ||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
if (cpack->valid && cache_packet_is_complete( cpack )) | if (cpack->valid && cache_packet_is_complete( cpack )) | ||||
if( cpack->framecnt >= expected_framecnt ) | |||||
num_packets_before_us += 1; | |||||
if( cpack->framecnt >= expected_framecnt ) | |||||
num_packets_before_us += 1; | |||||
} | } | ||||
return 100.0 * (float)num_packets_before_us / (float)( pcache->size ) ; | |||||
return 100.0 * (float)num_packets_before_us / (float)( pcache->size ); | |||||
} | } | ||||
// Returns 0 when no valid packet is inside the cache. | // Returns 0 when no valid packet is inside the cache. | ||||
@@ -680,29 +677,29 @@ packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t e | |||||
for (i = 0; i < pcache->size; i++) | for (i = 0; i < pcache->size; i++) | ||||
{ | { | ||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | if (!cpack->valid || !cache_packet_is_complete( cpack )) { | ||||
//printf( "invalid\n" ); | |||||
continue; | |||||
} | |||||
//printf( "invalid\n" ); | |||||
continue; | |||||
} | |||||
if( cpack->framecnt < expected_framecnt ) | |||||
continue; | |||||
if( cpack->framecnt < expected_framecnt ) | |||||
continue; | |||||
if( (cpack->framecnt - expected_framecnt) > best_offset ) { | |||||
continue; | |||||
if( (cpack->framecnt - expected_framecnt) > best_offset ) { | |||||
continue; | |||||
} | } | ||||
best_offset = cpack->framecnt - expected_framecnt; | best_offset = cpack->framecnt - expected_framecnt; | ||||
retval = 1; | retval = 1; | ||||
if( best_offset == 0 ) | |||||
if (best_offset == 0) | |||||
break; | break; | ||||
} | } | ||||
if( retval && framecnt ) | |||||
*framecnt = expected_framecnt + best_offset; | |||||
if (retval && framecnt) | |||||
*framecnt = expected_framecnt + best_offset; | |||||
return retval; | return retval; | ||||
} | } | ||||
@@ -716,12 +713,12 @@ packet_cache_get_highest_available_framecnt( packet_cache *pcache, jack_nframes_ | |||||
for (i = 0; i < pcache->size; i++) | for (i = 0; i < pcache->size; i++) | ||||
{ | { | ||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | if (!cpack->valid || !cache_packet_is_complete( cpack )) { | ||||
//printf( "invalid\n" ); | |||||
continue; | |||||
//printf( "invalid\n" ); | |||||
continue; | |||||
} | } | ||||
if (cpack->framecnt < best_value) { | if (cpack->framecnt < best_value) { | ||||
@@ -732,8 +729,8 @@ packet_cache_get_highest_available_framecnt( packet_cache *pcache, jack_nframes_ | |||||
retval = 1; | retval = 1; | ||||
} | } | ||||
if( retval && framecnt ) | |||||
*framecnt = best_value; | |||||
if (retval && framecnt) | |||||
*framecnt = best_value; | |||||
return retval; | return retval; | ||||
} | } | ||||
@@ -748,15 +745,15 @@ packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecn | |||||
for (i = 0; i < pcache->size; i++) | for (i = 0; i < pcache->size; i++) | ||||
{ | { | ||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||||
cache_packet *cpack = &(pcache->packets[i]); | |||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | if (!cpack->valid || !cache_packet_is_complete( cpack )) { | ||||
//printf( "invalid\n" ); | |||||
continue; | |||||
//printf( "invalid\n" ); | |||||
continue; | |||||
} | } | ||||
if( (cpack->framecnt - expected_framecnt) < best_offset ) { | |||||
if ((cpack->framecnt - expected_framecnt) < best_offset) { | |||||
continue; | continue; | ||||
} | } | ||||
@@ -766,8 +763,8 @@ packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecn | |||||
if( best_offset == 0 ) | if( best_offset == 0 ) | ||||
break; | break; | ||||
} | } | ||||
if( retval && framecnt ) | |||||
*framecnt = JACK_MAX_FRAMES - best_offset; | |||||
if (retval && framecnt) | |||||
*framecnt = JACK_MAX_FRAMES - best_offset; | |||||
return retval; | return retval; | ||||
} | } | ||||
@@ -786,18 +783,18 @@ netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct so | |||||
int fragment_payload_size = mtu - sizeof (jacknet_packet_header); | int fragment_payload_size = mtu - sizeof (jacknet_packet_header); | ||||
if (pkt_size <= mtu) { | if (pkt_size <= mtu) { | ||||
int err; | |||||
pkthdr = (jacknet_packet_header *) packet_buf; | |||||
int err; | |||||
pkthdr = (jacknet_packet_header *) packet_buf; | |||||
pkthdr->fragment_nr = htonl (0); | pkthdr->fragment_nr = htonl (0); | ||||
err = sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size); | err = sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size); | ||||
if( err<0 ) { | |||||
//printf( "error in send\n" ); | |||||
perror( "send" ); | |||||
} | |||||
if( err<0 ) { | |||||
//printf( "error in send\n" ); | |||||
perror( "send" ); | |||||
} | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
int err; | |||||
int err; | |||||
// Copy the packet header to the tx pack first. | // Copy the packet header to the tx pack first. | ||||
memcpy(tx_packet, packet_buf, sizeof (jacknet_packet_header)); | memcpy(tx_packet, packet_buf, sizeof (jacknet_packet_header)); | ||||
@@ -819,14 +816,13 @@ netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct so | |||||
// sendto(last_pack_size); | // sendto(last_pack_size); | ||||
err = sendto(sockfd, tx_packet, last_payload_size + sizeof(jacknet_packet_header), flags, addr, addr_size); | err = sendto(sockfd, tx_packet, last_payload_size + sizeof(jacknet_packet_header), flags, addr, addr_size); | ||||
if( err<0 ) { | |||||
//printf( "error in send\n" ); | |||||
perror( "send" ); | |||||
} | |||||
if( err<0 ) { | |||||
//printf( "error in send\n" ); | |||||
perror( "send" ); | |||||
} | |||||
} | } | ||||
} | } | ||||
void | void | ||||
decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf) | decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf) | ||||
{ | { | ||||
@@ -907,8 +903,8 @@ render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_pe | |||||
uint32_t *packet_bufX = (uint32_t *)packet_payload; | uint32_t *packet_bufX = (uint32_t *)packet_payload; | ||||
if( !packet_payload ) | |||||
return; | |||||
if (!packet_payload) | |||||
return; | |||||
while (node != NULL) | while (node != NULL) | ||||
{ | { | ||||
@@ -951,19 +947,19 @@ render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_pe | |||||
else | else | ||||
#endif | #endif | ||||
{ | { | ||||
if( dont_htonl_floats ) | |||||
{ | |||||
memcpy( buf, packet_bufX, net_period_down*sizeof(jack_default_audio_sample_t)); | |||||
} | |||||
else | |||||
{ | |||||
for (i = 0; i < net_period_down; i++) | |||||
{ | |||||
val.i = packet_bufX[i]; | |||||
val.i = ntohl (val.i); | |||||
buf[i] = val.f; | |||||
} | |||||
} | |||||
if( dont_htonl_floats ) | |||||
{ | |||||
memcpy( buf, packet_bufX, net_period_down*sizeof(jack_default_audio_sample_t)); | |||||
} | |||||
else | |||||
{ | |||||
for (i = 0; i < net_period_down; i++) | |||||
{ | |||||
val.i = packet_bufX[i]; | |||||
val.i = ntohl (val.i); | |||||
buf[i] = val.f; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
else if (jack_port_is_midi (porttype)) | else if (jack_port_is_midi (porttype)) | ||||
@@ -1031,19 +1027,19 @@ render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_src | |||||
else | else | ||||
#endif | #endif | ||||
{ | { | ||||
if( dont_htonl_floats ) | |||||
{ | |||||
memcpy( packet_bufX, buf, net_period_up*sizeof(jack_default_audio_sample_t) ); | |||||
} | |||||
else | |||||
{ | |||||
for (i = 0; i < net_period_up; i++) | |||||
{ | |||||
val.f = buf[i]; | |||||
val.i = htonl (val.i); | |||||
packet_bufX[i] = val.i; | |||||
} | |||||
} | |||||
if( dont_htonl_floats ) | |||||
{ | |||||
memcpy( packet_bufX, buf, net_period_up*sizeof(jack_default_audio_sample_t) ); | |||||
} | |||||
else | |||||
{ | |||||
for (i = 0; i < net_period_up; i++) | |||||
{ | |||||
val.f = buf[i]; | |||||
val.i = htonl (val.i); | |||||
packet_bufX[i] = val.i; | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
else if (jack_port_is_midi (porttype)) | else if (jack_port_is_midi (porttype)) | ||||
@@ -1218,8 +1214,8 @@ render_payload_to_jack_ports_8bit (void *packet_payload, jack_nframes_t net_peri | |||||
int8_t *packet_bufX = (int8_t *)packet_payload; | int8_t *packet_bufX = (int8_t *)packet_payload; | ||||
if( !packet_payload ) | |||||
return; | |||||
if (!packet_payload) | |||||
return; | |||||
while (node != NULL) | while (node != NULL) | ||||
{ | { | ||||
@@ -1368,21 +1364,20 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri | |||||
if (jack_port_is_audio (porttype)) | if (jack_port_is_audio (porttype)) | ||||
{ | { | ||||
// audio port, decode celt data. | // audio port, decode celt data. | ||||
CELTDecoder *decoder = src_node->data; | |||||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); | |||||
else | |||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); | |||||
#else | |||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf ); | |||||
else | |||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||||
#endif | |||||
CELTDecoder *decoder = src_node->data; | |||||
#if HAVE_CELT_API_0_8 | |||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); | |||||
else | |||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); | |||||
#else | |||||
if( !packet_payload ) | |||||
celt_decode_float( decoder, NULL, net_period_down, buf ); | |||||
else | |||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | |||||
#endif | |||||
src_node = jack_slist_next (src_node); | |||||
src_node = jack_slist_next (src_node); | |||||
} | } | ||||
else if (jack_port_is_midi (porttype)) | else if (jack_port_is_midi (porttype)) | ||||
{ | { | ||||
@@ -1390,8 +1385,8 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri | |||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_down / 2; | unsigned int buffer_size_uint32 = net_period_down / 2; | ||||
uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | uint32_t * buffer_uint32 = (uint32_t*) packet_bufX; | ||||
if( packet_payload ) | |||||
decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||||
if( packet_payload ) | |||||
decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf); | |||||
} | } | ||||
packet_bufX = (packet_bufX + net_period_down); | packet_bufX = (packet_bufX + net_period_down); | ||||
node = jack_slist_next (node); | node = jack_slist_next (node); | ||||
@@ -1422,7 +1417,7 @@ render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs | |||||
float *floatbuf = alloca (sizeof(float) * nframes ); | float *floatbuf = alloca (sizeof(float) * nframes ); | ||||
memcpy( floatbuf, buf, nframes*sizeof(float) ); | memcpy( floatbuf, buf, nframes*sizeof(float) ); | ||||
CELTEncoder *encoder = src_node->data; | CELTEncoder *encoder = src_node->data; | ||||
#if HAVE_CELT_API_0_8 | |||||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||||
encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up ); | encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up ); | ||||
#else | #else | ||||
encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); | encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); | ||||
@@ -39,23 +39,23 @@ extern "C" | |||||
} | } | ||||
jack_varargs_t; | jack_varargs_t; | ||||
static const char* jack_default_server_name (void) | |||||
{ | |||||
static const char* jack_default_server_name (void) | |||||
{ | |||||
const char *server_name; | const char *server_name; | ||||
if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) | if ((server_name = getenv("JACK_DEFAULT_SERVER")) == NULL) | ||||
server_name = "default"; | server_name = "default"; | ||||
return server_name; | return server_name; | ||||
} | } | ||||
static inline void jack_varargs_init (jack_varargs_t *va) | |||||
{ | |||||
static inline void jack_varargs_init (jack_varargs_t *va) | |||||
{ | |||||
memset (va, 0, sizeof(jack_varargs_t)); | memset (va, 0, sizeof(jack_varargs_t)); | ||||
va->server_name = (char*)jack_default_server_name(); | va->server_name = (char*)jack_default_server_name(); | ||||
va->session_id = -1; | va->session_id = -1; | ||||
} | } | ||||
static inline void jack_varargs_parse (jack_options_t options, va_list ap, jack_varargs_t *va) | |||||
{ | |||||
static inline void jack_varargs_parse (jack_options_t options, va_list ap, jack_varargs_t *va) | |||||
{ | |||||
// initialize default settings | // initialize default settings | ||||
jack_varargs_init (va); | jack_varargs_init (va); | ||||
@@ -153,14 +153,21 @@ jack_controller_start_server( | |||||
controller_ptr->xruns = 0; | controller_ptr->xruns = 0; | ||||
if (!jackctl_server_start( | |||||
if (!jackctl_server_open( | |||||
controller_ptr->server, | controller_ptr->server, | ||||
controller_ptr->driver)) | controller_ptr->driver)) | ||||
{ | { | ||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server"); | |||||
goto fail; | goto fail; | ||||
} | } | ||||
if (!jackctl_server_start( | |||||
controller_ptr->server)) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server"); | |||||
goto fail_close_server; | |||||
} | |||||
controller_ptr->client = jack_client_open( | controller_ptr->client = jack_client_open( | ||||
"dbusapi", | "dbusapi", | ||||
JackNoStartServer, | JackNoStartServer, | ||||
@@ -213,6 +220,12 @@ fail_stop_server: | |||||
jack_error("failed to stop jack server"); | jack_error("failed to stop jack server"); | ||||
} | } | ||||
fail_close_server: | |||||
if (!jackctl_server_close(controller_ptr->server)) | |||||
{ | |||||
jack_error("failed to close jack server"); | |||||
} | |||||
fail: | fail: | ||||
return FALSE; | return FALSE; | ||||
} | } | ||||
@@ -250,6 +263,12 @@ jack_controller_stop_server( | |||||
return FALSE; | return FALSE; | ||||
} | } | ||||
if (!jackctl_server_close(controller_ptr->server)) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server"); | |||||
return FALSE; | |||||
} | |||||
controller_ptr->started = false; | controller_ptr->started = false; | ||||
return TRUE; | return TRUE; | ||||
@@ -15,7 +15,7 @@ | |||||
#include <jack/jack.h> | #include <jack/jack.h> | ||||
#include <jack/jslist.h> | #include <jack/jslist.h> | ||||
#include <jack/memops.h> | |||||
#include "memops.h" | |||||
#include "alsa/asoundlib.h" | #include "alsa/asoundlib.h" | ||||
@@ -15,7 +15,7 @@ | |||||
#include <jack/jack.h> | #include <jack/jack.h> | ||||
#include <jack/jslist.h> | #include <jack/jslist.h> | ||||
#include <jack/memops.h> | |||||
#include "memops.h" | |||||
#include "alsa/asoundlib.h" | #include "alsa/asoundlib.h" | ||||
@@ -31,7 +31,7 @@ | |||||
jack_port_t *input_port; | jack_port_t *input_port; | ||||
jack_port_t *output_port; | jack_port_t *output_port; | ||||
int connecting, disconnecting; | int connecting, disconnecting; | ||||
int done = 0; | |||||
volatile int done = 0; | |||||
#define TRUE 1 | #define TRUE 1 | ||||
#define FALSE 0 | #define FALSE 0 | ||||
@@ -58,7 +58,6 @@ show_usage (char *my_name) | |||||
fprintf (stderr, "For more information see http://jackaudio.org/\n"); | fprintf (stderr, "For more information see http://jackaudio.org/\n"); | ||||
} | } | ||||
int | int | ||||
main (int argc, char *argv[]) | main (int argc, char *argv[]) | ||||
{ | { | ||||
@@ -181,11 +180,11 @@ main (int argc, char *argv[]) | |||||
if ((port1 = jack_port_by_name(client, portA)) == 0) { | if ((port1 = jack_port_by_name(client, portA)) == 0) { | ||||
fprintf (stderr, "ERROR %s not a valid port\n", portA); | fprintf (stderr, "ERROR %s not a valid port\n", portA); | ||||
goto exit; | goto exit; | ||||
} | |||||
} | |||||
if ((port2 = jack_port_by_name(client, portB)) == 0) { | if ((port2 = jack_port_by_name(client, portB)) == 0) { | ||||
fprintf (stderr, "ERROR %s not a valid port\n", portB); | fprintf (stderr, "ERROR %s not a valid port\n", portB); | ||||
goto exit; | goto exit; | ||||
} | |||||
} | |||||
port1_flags = jack_port_flags (port1); | port1_flags = jack_port_flags (port1); | ||||
port2_flags = jack_port_flags (port2); | port2_flags = jack_port_flags (port2); | ||||
@@ -207,17 +206,25 @@ main (int argc, char *argv[]) | |||||
goto exit; | goto exit; | ||||
} | } | ||||
/* tell the JACK server that we are ready to roll */ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "cannot activate client"); | |||||
goto exit; | |||||
} | |||||
/* connect the ports. Note: you can't do this before | /* connect the ports. Note: you can't do this before | ||||
the client is activated (this may change in the future). | the client is activated (this may change in the future). | ||||
*/ | */ | ||||
if (connecting) { | if (connecting) { | ||||
if (jack_connect(client, jack_port_name(src_port), jack_port_name(dst_port))) { | if (jack_connect(client, jack_port_name(src_port), jack_port_name(dst_port))) { | ||||
fprintf (stderr, "cannot connect client, already connected?\n"); | |||||
goto exit; | goto exit; | ||||
} | } | ||||
} | } | ||||
if (disconnecting) { | if (disconnecting) { | ||||
if (jack_disconnect(client, jack_port_name(src_port), jack_port_name(dst_port))) { | if (jack_disconnect(client, jack_port_name(src_port), jack_port_name(dst_port))) { | ||||
fprintf (stderr, "cannot disconnect client, already disconnected?\n"); | |||||
goto exit; | goto exit; | ||||
} | } | ||||
} | } | ||||
@@ -1,4 +1,4 @@ | |||||
/** @file simple_client.c | |||||
/** @file control.c | |||||
* | * | ||||
* @brief This simple client demonstrates the basic features of JACK | * @brief This simple client demonstrates the basic features of JACK | ||||
* as they would be used by many applications. | * as they would be used by many applications. | ||||
@@ -14,14 +14,14 @@ | |||||
jack_client_t *client; | jack_client_t *client; | ||||
static int reorder = 0; | static int reorder = 0; | ||||
static int Jack_Graph_Order_Callback(void *arg) | static int Jack_Graph_Order_Callback(void *arg) | ||||
{ | { | ||||
const char **ports; | const char **ports; | ||||
int i; | int i; | ||||
printf("Jack_Graph_Order_Callback count = %d\n", reorder++); | printf("Jack_Graph_Order_Callback count = %d\n", reorder++); | ||||
ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); | ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); | ||||
if (ports) { | if (ports) { | ||||
for (i = 0; ports[i]; ++i) { | for (i = 0; ports[i]; ++i) { | ||||
@@ -29,15 +29,15 @@ static int Jack_Graph_Order_Callback(void *arg) | |||||
} | } | ||||
free(ports); | free(ports); | ||||
} | } | ||||
ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); | ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); | ||||
if (ports) { | |||||
if (ports) { | |||||
for (i = 0; ports[i]; ++i) { | for (i = 0; ports[i]; ++i) { | ||||
printf("name: %s\n", ports[i]); | printf("name: %s\n", ports[i]); | ||||
} | } | ||||
free(ports); | free(ports); | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -46,7 +46,7 @@ main (int argc, char *argv[]) | |||||
{ | { | ||||
jack_options_t options = JackNullOption; | jack_options_t options = JackNullOption; | ||||
jack_status_t status; | jack_status_t status; | ||||
/* open a client connection to the JACK server */ | /* open a client connection to the JACK server */ | ||||
client = jack_client_open("control_client", options, &status); | client = jack_client_open("control_client", options, &status); | ||||
@@ -54,7 +54,7 @@ main (int argc, char *argv[]) | |||||
printf("jack_client_open() failed \n"); | printf("jack_client_open() failed \n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (jack_set_graph_order_callback(client, Jack_Graph_Order_Callback, 0) != 0) { | if (jack_set_graph_order_callback(client, Jack_Graph_Order_Callback, 0) != 0) { | ||||
printf("Error when calling jack_set_graph_order_callback() !\n"); | printf("Error when calling jack_set_graph_order_callback() !\n"); | ||||
} | } | ||||
@@ -66,10 +66,10 @@ main (int argc, char *argv[]) | |||||
printf("cannot activate client"); | printf("cannot activate client"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
printf("Type 'q' to quit\n"); | |||||
printf("Type 'q' to quit\n"); | |||||
while ((getchar() != 'q')) {} | while ((getchar() != 'q')) {} | ||||
jack_client_close(client); | jack_client_close(client); | ||||
exit (0); | exit (0); | ||||
} | } |
@@ -139,21 +139,24 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||||
printf( "jack_netsource: cannot register %s port\n", buf); | printf( "jack_netsource: cannot register %s port\n", buf); | ||||
break; | break; | ||||
} | } | ||||
if( bitdepth == 1000 ) { | |||||
#if HAVE_CELT | |||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | |||||
#else | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); | |||||
#endif | |||||
#endif | |||||
} else { | |||||
#if HAVE_SAMPLERATE | |||||
capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||||
#endif | |||||
} | |||||
if (bitdepth == 1000) { | |||||
#if HAVE_CELT | |||||
#if HAVE_CELT_API_0_11 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) ); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | |||||
#else | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL ); | |||||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); | |||||
#endif | |||||
#endif | |||||
} else { | |||||
#if HAVE_SAMPLERATE | |||||
capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||||
#endif | |||||
} | |||||
capture_ports = jack_slist_append (capture_ports, port); | capture_ports = jack_slist_append (capture_ports, port); | ||||
} | } | ||||
@@ -182,22 +185,25 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||||
printf ("jack_netsource: cannot register %s port\n", buf); | printf ("jack_netsource: cannot register %s port\n", buf); | ||||
break; | break; | ||||
} | } | ||||
if( bitdepth == 1000 ) { | |||||
#if HAVE_CELT | |||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | |||||
#else | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); | |||||
#endif | |||||
#endif | |||||
} else { | |||||
#if HAVE_SAMPLERATE | |||||
playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||||
#endif | |||||
} | |||||
playback_ports = jack_slist_append (playback_ports, port); | |||||
if( bitdepth == 1000 ) { | |||||
#if HAVE_CELT | |||||
#if HAVE_CELT_API_0_11 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create_custom( celt_mode, 1, NULL ) ); | |||||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | |||||
#else | |||||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL ); | |||||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); | |||||
#endif | |||||
#endif | |||||
} else { | |||||
#if HAVE_SAMPLERATE | |||||
playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||||
#endif | |||||
} | |||||
playback_ports = jack_slist_append (playback_ports, port); | |||||
} | } | ||||
/* Allocate midi playback channels */ | /* Allocate midi playback channels */ | ||||
@@ -226,7 +232,7 @@ sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) | |||||
int retval = sync_state; | int retval = sync_state; | ||||
if (! state_connected) { | if (! state_connected) { | ||||
return 1; | |||||
return 1; | |||||
} | } | ||||
if (latency_count) { | if (latency_count) { | ||||
latency_count--; | latency_count--; | ||||
@@ -275,14 +281,13 @@ process (jack_nframes_t nframes, void *arg) | |||||
jack_time_t packet_recv_timestamp; | jack_time_t packet_recv_timestamp; | ||||
if( bitdepth == 1000 ) | if( bitdepth == 1000 ) | ||||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||||
else | else | ||||
net_period = (float) nframes / (float) factor; | |||||
net_period = (float) nframes / (float) factor; | |||||
rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); | rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); | ||||
tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header); | tx_bufsize = get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header); | ||||
/* Allocate a buffer where both In and Out Buffer will fit */ | /* Allocate a buffer where both In and Out Buffer will fit */ | ||||
packet_buf_tx = alloca (tx_bufsize); | packet_buf_tx = alloca (tx_bufsize); | ||||
@@ -346,29 +351,29 @@ process (jack_nframes_t nframes, void *arg) | |||||
if( reply_port ) | if( reply_port ) | ||||
input_fd = insockfd; | |||||
input_fd = insockfd; | |||||
else | else | ||||
input_fd = outsockfd; | |||||
input_fd = outsockfd; | |||||
// for latency == 0 we can poll. | // for latency == 0 we can poll. | ||||
if( (latency == 0) || (freewheeling!=0) ) { | if( (latency == 0) || (freewheeling!=0) ) { | ||||
jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client)/jack_get_sample_rate(client); | |||||
// Now loop until we get the right packet. | |||||
while(1) { | |||||
jack_nframes_t got_frame; | |||||
if ( ! netjack_poll_deadline( input_fd, deadline ) ) | |||||
break; | |||||
packet_cache_drain_socket(packcache, input_fd); | |||||
if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) | |||||
if( got_frame == (framecnt - latency) ) | |||||
break; | |||||
} | |||||
jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client)/jack_get_sample_rate(client); | |||||
// Now loop until we get the right packet. | |||||
while(1) { | |||||
jack_nframes_t got_frame; | |||||
if ( ! netjack_poll_deadline( input_fd, deadline ) ) | |||||
break; | |||||
packet_cache_drain_socket(packcache, input_fd); | |||||
if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) | |||||
if( got_frame == (framecnt - latency) ) | |||||
break; | |||||
} | |||||
} else { | } else { | ||||
// normally: | |||||
// only drain socket. | |||||
packet_cache_drain_socket(packcache, input_fd); | |||||
// normally: | |||||
// only drain socket. | |||||
packet_cache_drain_socket(packcache, input_fd); | |||||
} | } | ||||
size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); | size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); | ||||
@@ -376,15 +381,15 @@ process (jack_nframes_t nframes, void *arg) | |||||
* to the JACK ports so it can be played. */ | * to the JACK ports so it can be played. */ | ||||
if (size == rx_bufsize) | if (size == rx_bufsize) | ||||
{ | { | ||||
uint32_t *packet_buf_rx = rx_packet_ptr; | |||||
jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; | |||||
packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||||
// calculate how much time there would have been, if this packet was sent at the deadline. | |||||
uint32_t *packet_buf_rx = rx_packet_ptr; | |||||
jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; | |||||
packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||||
// calculate how much time there would have been, if this packet was sent at the deadline. | |||||
int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp); | |||||
packet_header_ntoh (pkthdr_rx); | |||||
deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; | |||||
//printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); | |||||
int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp); | |||||
packet_header_ntoh (pkthdr_rx); | |||||
deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; | |||||
//printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); | |||||
if (cont_miss) | if (cont_miss) | ||||
{ | { | ||||
@@ -394,26 +399,26 @@ process (jack_nframes_t nframes, void *arg) | |||||
render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, | render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, | ||||
capture_ports, capture_srcs, nframes, dont_htonl_floats); | capture_ports, capture_srcs, nframes, dont_htonl_floats); | ||||
state_currentframe = framecnt; | |||||
state_recv_packet_queue_time = recv_time_offset; | |||||
state_connected = 1; | |||||
state_currentframe = framecnt; | |||||
state_recv_packet_queue_time = recv_time_offset; | |||||
state_connected = 1; | |||||
sync_state = pkthdr_rx->sync_state; | sync_state = pkthdr_rx->sync_state; | ||||
packet_cache_release_packet( packcache, framecnt - latency ); | |||||
packet_cache_release_packet( packcache, framecnt - latency ); | |||||
} | } | ||||
/* Second alternative : we've received something that's not | /* Second alternative : we've received something that's not | ||||
* as big as expected or we missed a packet. We render silence | * as big as expected or we missed a packet. We render silence | ||||
* to the ouput ports */ | * to the ouput ports */ | ||||
else | else | ||||
{ | { | ||||
jack_nframes_t latency_estimate; | |||||
if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) | |||||
//if( (state_latency == 0) || (latency_estimate < state_latency) ) | |||||
state_latency = latency_estimate; | |||||
jack_nframes_t latency_estimate; | |||||
if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) | |||||
//if( (state_latency == 0) || (latency_estimate < state_latency) ) | |||||
state_latency = latency_estimate; | |||||
// Set the counters up. | |||||
state_currentframe = framecnt; | |||||
//state_latency = framecnt - pkthdr->framecnt; | |||||
state_netxruns += 1; | |||||
// Set the counters up. | |||||
state_currentframe = framecnt; | |||||
//state_latency = framecnt - pkthdr->framecnt; | |||||
state_netxruns += 1; | |||||
//printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size); | //printf ("Frame %d \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size); | ||||
//printf ("Frame %d \tPacket missed or incomplete\n", framecnt); | //printf ("Frame %d \tPacket missed or incomplete\n", framecnt); | ||||
@@ -434,7 +439,7 @@ process (jack_nframes_t nframes, void *arg) | |||||
chn++; | chn++; | ||||
} | } | ||||
} | } | ||||
if( latency != 0 ) { | |||||
if (latency != 0) { | |||||
/* reset packet_bufX... */ | /* reset packet_bufX... */ | ||||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | ||||
@@ -624,15 +629,15 @@ main (int argc, char *argv[]) | |||||
case 'b': | case 'b': | ||||
bitdepth = atoi (optarg); | bitdepth = atoi (optarg); | ||||
break; | break; | ||||
case 'c': | |||||
case 'c': | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
bitdepth = 1000; | |||||
bitdepth = 1000; | |||||
factor = atoi (optarg); | factor = atoi (optarg); | ||||
#else | #else | ||||
printf( "not built with celt supprt\n" ); | |||||
printf( "not built with celt support\n" ); | |||||
exit(10); | exit(10); | ||||
#endif | #endif | ||||
break; | |||||
break; | |||||
case 'm': | case 'm': | ||||
mtu = atoi (optarg); | mtu = atoi (optarg); | ||||
break; | break; | ||||
@@ -673,24 +678,24 @@ main (int argc, char *argv[]) | |||||
outsockfd = socket (AF_INET, SOCK_DGRAM, 0); | outsockfd = socket (AF_INET, SOCK_DGRAM, 0); | ||||
insockfd = socket (AF_INET, SOCK_DGRAM, 0); | insockfd = socket (AF_INET, SOCK_DGRAM, 0); | ||||
if( (outsockfd == -1) || (insockfd == -1) ) { | |||||
if ((outsockfd == -1) || (insockfd == -1)) { | |||||
fprintf (stderr, "cant open sockets\n" ); | fprintf (stderr, "cant open sockets\n" ); | ||||
return 1; | return 1; | ||||
} | } | ||||
init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_port); | init_sockaddr_in ((struct sockaddr_in *) &destaddr, peer_ip, peer_port); | ||||
if(bind_port) { | |||||
if (bind_port) { | |||||
init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, bind_port); | init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, bind_port); | ||||
if( bind (outsockfd, &bindaddr, sizeof (bindaddr)) ) { | if( bind (outsockfd, &bindaddr, sizeof (bindaddr)) ) { | ||||
fprintf (stderr, "bind failure\n" ); | |||||
} | |||||
fprintf (stderr, "bind failure\n" ); | |||||
} | |||||
} | } | ||||
if(reply_port) | |||||
if (reply_port) | |||||
{ | { | ||||
init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); | init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); | ||||
if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { | if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { | ||||
fprintf (stderr, "bind failure\n" ); | |||||
} | |||||
fprintf (stderr, "bind failure\n" ); | |||||
} | |||||
} | } | ||||
/* try to become a client of the JACK server */ | /* try to become a client of the JACK server */ | ||||
@@ -711,9 +716,9 @@ main (int argc, char *argv[]) | |||||
alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); | alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); | ||||
if( bitdepth == 1000 ) | if( bitdepth == 1000 ) | ||||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||||
else | else | ||||
net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); | |||||
net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); | |||||
int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); | int rx_bufsize = get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header); | ||||
packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); | packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); | ||||
@@ -757,26 +762,26 @@ main (int argc, char *argv[]) | |||||
if (statecopy_connected) | if (statecopy_connected) | ||||
{ | { | ||||
if (statecopy_netxruns != state_netxruns) { | |||||
statecopy_netxruns = state_netxruns; | |||||
printf ("%s: at frame %06d -> total netxruns %d (%d%%) queue time= %d\n", | |||||
if (statecopy_netxruns != state_netxruns) { | |||||
statecopy_netxruns = state_netxruns; | |||||
printf ("%s: at frame %06d -> total netxruns %d (%d%%) queue time= %d\n", | |||||
client_name, | client_name, | ||||
state_currentframe, | state_currentframe, | ||||
statecopy_netxruns, | statecopy_netxruns, | ||||
100*statecopy_netxruns/state_currentframe, | 100*statecopy_netxruns/state_currentframe, | ||||
state_recv_packet_queue_time); | state_recv_packet_queue_time); | ||||
fflush(stdout); | |||||
fflush(stdout); | |||||
} | } | ||||
} | |||||
else | |||||
} | |||||
else | |||||
{ | |||||
if (statecopy_latency != state_latency) | |||||
{ | { | ||||
if (statecopy_latency != state_latency) | |||||
{ | |||||
statecopy_latency = state_latency; | |||||
if (statecopy_latency > 1) | |||||
printf ("current latency %d\n", statecopy_latency); | |||||
fflush(stdout); | |||||
statecopy_latency = state_latency; | |||||
if (statecopy_latency > 1) | |||||
printf ("current latency %d\n", statecopy_latency); | |||||
fflush(stdout); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
Copyright (C) 2008 Grame | Copyright (C) 2008 Grame | ||||
This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||
the Free Software Foundation; either version 2 of the License, or | the Free Software Foundation; either version 2 of the License, or | ||||
@@ -74,23 +74,23 @@ jackctl_get_parameter( | |||||
static void print_value(union jackctl_parameter_value value, jackctl_param_type_t type) | static void print_value(union jackctl_parameter_value value, jackctl_param_type_t type) | ||||
{ | { | ||||
switch (type) { | switch (type) { | ||||
case JackParamInt: | case JackParamInt: | ||||
printf("parameter value = %d\n", value.i); | printf("parameter value = %d\n", value.i); | ||||
break; | break; | ||||
case JackParamUInt: | case JackParamUInt: | ||||
printf("parameter value = %u\n", value.ui); | printf("parameter value = %u\n", value.ui); | ||||
break; | break; | ||||
case JackParamChar: | case JackParamChar: | ||||
printf("parameter value = %c\n", value.c); | printf("parameter value = %c\n", value.c); | ||||
break; | break; | ||||
case JackParamString: | case JackParamString: | ||||
printf("parameter value = %s\n", value.str); | printf("parameter value = %s\n", value.str); | ||||
break; | break; | ||||
case JackParamBool: | case JackParamBool: | ||||
printf("parameter value = %d\n", value.b); | printf("parameter value = %d\n", value.b); | ||||
break; | break; | ||||
@@ -115,7 +115,7 @@ static void print_driver(jackctl_driver_t * driver) | |||||
printf("\n--------------------------\n"); | printf("\n--------------------------\n"); | ||||
printf("driver = %s\n", jackctl_driver_get_name(driver)); | printf("driver = %s\n", jackctl_driver_get_name(driver)); | ||||
printf("-------------------------- \n"); | printf("-------------------------- \n"); | ||||
print_parameters(jackctl_driver_get_parameters(driver)); | |||||
print_parameters(jackctl_driver_get_parameters(driver)); | |||||
} | } | ||||
static void print_internal(jackctl_internal_t * internal) | static void print_internal(jackctl_internal_t * internal) | ||||
@@ -152,7 +152,7 @@ int main(int argc, char *argv[]) | |||||
{"driver", 1, 0, 'd'}, | {"driver", 1, 0, 'd'}, | ||||
{"client", 1, 0, 'c'}, | {"client", 1, 0, 'c'}, | ||||
}; | }; | ||||
while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | while ((opt = getopt_long (argc, argv, options, long_options, &option_index)) != EOF) { | ||||
switch (opt) { | switch (opt) { | ||||
case 'd': | case 'd': | ||||
@@ -166,10 +166,10 @@ int main(int argc, char *argv[]) | |||||
exit(0); | exit(0); | ||||
} | } | ||||
} | } | ||||
server = jackctl_server_create(NULL, NULL); | server = jackctl_server_create(NULL, NULL); | ||||
parameters = jackctl_server_get_parameters(server); | parameters = jackctl_server_get_parameters(server); | ||||
/* | /* | ||||
jackctl_parameter_t* param; | jackctl_parameter_t* param; | ||||
union jackctl_parameter_value value; | union jackctl_parameter_value value; | ||||
@@ -179,58 +179,63 @@ int main(int argc, char *argv[]) | |||||
jackctl_parameter_set_value(param, &value); | jackctl_parameter_set_value(param, &value); | ||||
} | } | ||||
*/ | */ | ||||
printf("\n========================== \n"); | printf("\n========================== \n"); | ||||
printf("List of server parameters \n"); | printf("List of server parameters \n"); | ||||
printf("========================== \n"); | printf("========================== \n"); | ||||
print_parameters(parameters); | print_parameters(parameters); | ||||
printf("\n========================== \n"); | printf("\n========================== \n"); | ||||
printf("List of drivers \n"); | printf("List of drivers \n"); | ||||
printf("========================== \n"); | printf("========================== \n"); | ||||
drivers = jackctl_server_get_drivers_list(server); | drivers = jackctl_server_get_drivers_list(server); | ||||
node_ptr = drivers; | node_ptr = drivers; | ||||
while (node_ptr != NULL) { | while (node_ptr != NULL) { | ||||
print_driver((jackctl_driver_t *)node_ptr->data); | print_driver((jackctl_driver_t *)node_ptr->data); | ||||
node_ptr = jack_slist_next(node_ptr); | node_ptr = jack_slist_next(node_ptr); | ||||
} | } | ||||
printf("\n========================== \n"); | printf("\n========================== \n"); | ||||
printf("List of internal clients \n"); | printf("List of internal clients \n"); | ||||
printf("========================== \n"); | printf("========================== \n"); | ||||
internals = jackctl_server_get_internals_list(server); | internals = jackctl_server_get_internals_list(server); | ||||
node_ptr = internals; | node_ptr = internals; | ||||
while (node_ptr != NULL) { | while (node_ptr != NULL) { | ||||
print_internal((jackctl_internal_t *)node_ptr->data); | print_internal((jackctl_internal_t *)node_ptr->data); | ||||
node_ptr = jack_slist_next(node_ptr); | node_ptr = jack_slist_next(node_ptr); | ||||
} | } | ||||
jackctl_server_start(server, jackctl_server_get_driver(server, driver_name)); | |||||
// No error checking in this simple example... | |||||
jackctl_server_open(server, jackctl_server_get_driver(server, driver_name)); | |||||
jackctl_server_start(server); | |||||
jackctl_server_load_internal(server, jackctl_server_get_internal(server, client_name)); | jackctl_server_load_internal(server, jackctl_server_get_internal(server, client_name)); | ||||
/* | /* | ||||
// Switch master test | // Switch master test | ||||
jackctl_driver_t* master; | jackctl_driver_t* master; | ||||
usleep(5000000); | usleep(5000000); | ||||
printf("jackctl_server_load_master\n"); | printf("jackctl_server_load_master\n"); | ||||
master = jackctl_server_get_driver(server, "coreaudio"); | master = jackctl_server_get_driver(server, "coreaudio"); | ||||
jackctl_server_switch_master(server, master); | jackctl_server_switch_master(server, master); | ||||
usleep(5000000); | usleep(5000000); | ||||
printf("jackctl_server_load_master\n"); | printf("jackctl_server_load_master\n"); | ||||
master = jackctl_server_get_driver(server, "dummy"); | master = jackctl_server_get_driver(server, "dummy"); | ||||
jackctl_server_switch_master(server, master); | jackctl_server_switch_master(server, master); | ||||
*/ | */ | ||||
signals = jackctl_setup_signals(0); | signals = jackctl_setup_signals(0); | ||||
jackctl_wait_signals(signals); | jackctl_wait_signals(signals); | ||||
jackctl_server_stop(server); | |||||
jackctl_server_close(server); | |||||
jackctl_server_destroy(server); | jackctl_server_destroy(server); | ||||
return 0; | return 0; | ||||
} | } |
@@ -63,7 +63,7 @@ def configure(conf): | |||||
conf.env['BUILD_EXAMPLE_CLIENT_REC'] = conf.is_defined('HAVE_SNDFILE') | conf.env['BUILD_EXAMPLE_CLIENT_REC'] = conf.is_defined('HAVE_SNDFILE') | ||||
conf.env['BUILD_EXAMPLE_ALSA_IO'] = conf.is_defined('HAVE_SAMPLERATE') and conf.is_defined('HAVE_ALSA') | |||||
conf.env['BUILD_EXAMPLE_ALSA_IO'] = conf.is_defined('HAVE_SAMPLERATE') and conf.env['BUILD_DRIVER_ALSA'] | |||||
def build(bld): | def build(bld): | ||||
if bld.env['IS_LINUX']: | if bld.env['IS_LINUX']: | ||||
@@ -137,21 +137,21 @@ def build(bld): | |||||
prog.target = 'jack_netsource' | prog.target = 'jack_netsource' | ||||
if bld.env['IS_LINUX'] and bld.env['BUILD_EXAMPLE_ALSA_IO']: | if bld.env['IS_LINUX'] and bld.env['BUILD_EXAMPLE_ALSA_IO']: | ||||
prog = bld.new_task_gen('cc', 'program') | |||||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||||
prog.source = ['alsa_in.c', '../common/memops.c'] | |||||
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") | |||||
prog.uselib = 'ALSA SAMPLERATE' | |||||
prog.uselib_local = 'clientlib' | |||||
prog.target = 'alsa_in' | |||||
prog = bld.new_task_gen('cc', 'program') | |||||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||||
prog.source = ['alsa_out.c', '../common/memops.c'] | |||||
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") | |||||
prog.uselib = 'ALSA SAMPLERATE' | |||||
prog.uselib_local = 'clientlib' | |||||
prog.target = 'alsa_out' | |||||
prog = bld.new_task_gen('cc', 'program') | |||||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||||
prog.source = ['alsa_in.c', '../common/memops.c'] | |||||
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") | |||||
prog.uselib = 'ALSA SAMPLERATE' | |||||
prog.uselib_local = 'clientlib' | |||||
prog.target = 'alsa_in' | |||||
prog = bld.new_task_gen('cc', 'program') | |||||
prog.includes = os_incdir + ['../common/jack', '../common'] | |||||
prog.source = ['alsa_out.c', '../common/memops.c'] | |||||
prog.env.append_value("CCFLAGS", "-DNO_JACK_ERROR") | |||||
prog.uselib = 'ALSA SAMPLERATE' | |||||
prog.uselib_local = 'clientlib' | |||||
prog.target = 'alsa_out' | |||||
for example_lib, example_lib_source in example_libs.items(): | for example_lib, example_lib_source in example_libs.items(): | ||||
lib = bld.new_task_gen('cc', 'shlib') | lib = bld.new_task_gen('cc', 'shlib') | ||||
@@ -14,7 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | |||||
along with this program; if not, write to the Free Software | |||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -82,7 +82,7 @@ static int jack_hpet_init () | |||||
} | } | ||||
/* this assumes period to be constant. if needed, | /* this assumes period to be constant. if needed, | ||||
it can be moved to the clock access function | |||||
it can be moved to the clock access function | |||||
*/ | */ | ||||
hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD)); | hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD)); | ||||
hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS)); | hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS)); | ||||
@@ -93,7 +93,7 @@ static int jack_hpet_init () | |||||
return 0; | return 0; | ||||
} | } | ||||
static jack_time_t jack_get_microseconds_from_hpet (void) | |||||
static jack_time_t jack_get_microseconds_from_hpet (void) | |||||
{ | { | ||||
hpet_counter_t hpet_counter; | hpet_counter_t hpet_counter; | ||||
long double hpet_time; | long double hpet_time; | ||||
@@ -116,7 +116,7 @@ static int jack_hpet_init () | |||||
return -1; | return -1; | ||||
} | } | ||||
static jack_time_t jack_get_microseconds_from_hpet (void) | |||||
static jack_time_t jack_get_microseconds_from_hpet (void) | |||||
{ | { | ||||
/* never called */ | /* never called */ | ||||
return 0; | return 0; | ||||
@@ -168,7 +168,7 @@ static jack_time_t jack_get_mhz (void) | |||||
ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz); | ret = sscanf(buf, "bogomips per cpu: %" SCNu64, &mhz); | ||||
#else /* MIPS, ARM, alpha */ | #else /* MIPS, ARM, alpha */ | ||||
ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz); | ret = sscanf(buf, "BogoMIPS : %" SCNu64, &mhz); | ||||
#endif | |||||
#endif | |||||
if (ret == 1) | if (ret == 1) | ||||
{ | { | ||||
@@ -182,7 +182,7 @@ static jack_time_t jack_get_mhz (void) | |||||
#ifndef HAVE_CLOCK_GETTIME | #ifndef HAVE_CLOCK_GETTIME | ||||
static jack_time_t jack_get_microseconds_from_system (void) | |||||
static jack_time_t jack_get_microseconds_from_system (void) | |||||
{ | { | ||||
jack_time_t jackTime; | jack_time_t jackTime; | ||||
struct timeval tv; | struct timeval tv; | ||||
@@ -194,7 +194,7 @@ static jack_time_t jack_get_microseconds_from_system (void) | |||||
#else | #else | ||||
static jack_time_t jack_get_microseconds_from_system (void) | |||||
static jack_time_t jack_get_microseconds_from_system (void) | |||||
{ | { | ||||
jack_time_t jackTime; | jack_time_t jackTime; | ||||
struct timespec time; | struct timespec time; | ||||
@@ -208,7 +208,7 @@ static jack_time_t jack_get_microseconds_from_system (void) | |||||
#endif /* HAVE_CLOCK_GETTIME */ | #endif /* HAVE_CLOCK_GETTIME */ | ||||
SERVER_EXPORT void JackSleep(long usec) | |||||
SERVER_EXPORT void JackSleep(long usec) | |||||
{ | { | ||||
usleep(usec); | usleep(usec); | ||||
} | } | ||||
@@ -266,3 +266,9 @@ SERVER_EXPORT jack_time_t GetMicroSeconds() | |||||
{ | { | ||||
return _jack_get_microseconds(); | return _jack_get_microseconds(); | ||||
} | } | ||||
SERVER_EXPORT jack_time_t jack_get_microseconds() | |||||
{ | |||||
return _jack_get_microseconds(); | |||||
} | |||||
@@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#endif | #endif | ||||
#include "JackAlsaAdapter.h" | #include "JackAlsaAdapter.h" | ||||
#include "JackServerGlobals.h" | |||||
#include "JackGlobals.h" | |||||
#include "JackEngineControl.h" | #include "JackEngineControl.h" | ||||
namespace Jack | namespace Jack | ||||
@@ -104,7 +104,7 @@ namespace Jack | |||||
fAudioInterface.longinfo(); | fAudioInterface.longinfo(); | ||||
//turn the thread realtime | //turn the thread realtime | ||||
fThread.AcquireRealTime ( JackServerGlobals::fInstance->GetEngineControl()->fClientPriority ); | |||||
fThread.AcquireRealTime(GetEngineControl()->fClientPriority); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -154,7 +154,7 @@ namespace Jack | |||||
//read data from audio interface | //read data from audio interface | ||||
if (fAudioInterface.read() < 0) | if (fAudioInterface.read() < 0) | ||||
return false; | return false; | ||||
PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize); | PushAndPull(fAudioInterface.fInputSoftChannels, fAudioInterface.fOutputSoftChannels, fAdaptedBufferSize); | ||||
//write data to audio interface | //write data to audio interface | ||||
@@ -273,7 +273,7 @@ extern "C" | |||||
strcpy ( desc->params[i].short_desc, | strcpy ( desc->params[i].short_desc, | ||||
"Number of playback channels (defaults to hardware max)" ); | "Number of playback channels (defaults to hardware max)" ); | ||||
strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | ||||
i++; | i++; | ||||
strcpy(desc->params[i].name, "quality"); | strcpy(desc->params[i].name, "quality"); | ||||
desc->params[i].character = 'q'; | desc->params[i].character = 'q'; | ||||
@@ -281,7 +281,7 @@ extern "C" | |||||
desc->params[i].value.ui = 0; | desc->params[i].value.ui = 0; | ||||
strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | ||||
strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
i++; | i++; | ||||
strcpy(desc->params[i].name, "ring-buffer"); | strcpy(desc->params[i].name, "ring-buffer"); | ||||
desc->params[i].character = 'g'; | desc->params[i].character = 'g'; | ||||
@@ -145,8 +145,8 @@ namespace Jack | |||||
void* fOutputCardChannels[256]; | void* fOutputCardChannels[256]; | ||||
//non-interleaved mod, floating point software buffers | //non-interleaved mod, floating point software buffers | ||||
float* fInputSoftChannels[256]; | |||||
float* fOutputSoftChannels[256]; | |||||
jack_default_audio_sample_t* fInputSoftChannels[256]; | |||||
jack_default_audio_sample_t* fOutputSoftChannels[256]; | |||||
//public methods --------------------------------------------------------- | //public methods --------------------------------------------------------- | ||||
@@ -165,12 +165,12 @@ namespace Jack | |||||
return fBuffering; | return fBuffering; | ||||
} | } | ||||
float** inputSoftChannels() | |||||
jack_default_audio_sample_t** inputSoftChannels() | |||||
{ | { | ||||
return fInputSoftChannels; | return fInputSoftChannels; | ||||
} | } | ||||
float** outputSoftChannels() | |||||
jack_default_audio_sample_t** outputSoftChannels() | |||||
{ | { | ||||
return fOutputSoftChannels; | return fOutputSoftChannels; | ||||
} | } | ||||
@@ -182,10 +182,10 @@ namespace Jack | |||||
fInputParams = 0; | fInputParams = 0; | ||||
fOutputParams = 0; | fOutputParams = 0; | ||||
fPeriod = 2; | fPeriod = 2; | ||||
fInputCardBuffer = 0; | fInputCardBuffer = 0; | ||||
fOutputCardBuffer = 0; | fOutputCardBuffer = 0; | ||||
for ( int i = 0; i < 256; i++ ) | for ( int i = 0; i < 256; i++ ) | ||||
{ | { | ||||
fInputCardChannels[i] = 0; | fInputCardChannels[i] = 0; | ||||
@@ -222,18 +222,18 @@ namespace Jack | |||||
//get hardware input parameters | //get hardware input parameters | ||||
check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) ); | check_error ( snd_pcm_hw_params_malloc ( &fInputParams ) ); | ||||
setAudioParams ( fInputDevice, fInputParams ); | setAudioParams ( fInputDevice, fInputParams ); | ||||
//get hardware output parameters | //get hardware output parameters | ||||
check_error ( snd_pcm_hw_params_malloc ( &fOutputParams ) ) | check_error ( snd_pcm_hw_params_malloc ( &fOutputParams ) ) | ||||
setAudioParams ( fOutputDevice, fOutputParams ); | setAudioParams ( fOutputDevice, fOutputParams ); | ||||
// set the number of physical input and output channels close to what we need | // set the number of physical input and output channels close to what we need | ||||
fCardInputs = fSoftInputs; | fCardInputs = fSoftInputs; | ||||
fCardOutputs = fSoftOutputs; | fCardOutputs = fSoftOutputs; | ||||
snd_pcm_hw_params_set_channels_near(fInputDevice, fInputParams, &fCardInputs); | snd_pcm_hw_params_set_channels_near(fInputDevice, fInputParams, &fCardInputs); | ||||
snd_pcm_hw_params_set_channels_near(fOutputDevice, fOutputParams, &fCardOutputs); | snd_pcm_hw_params_set_channels_near(fOutputDevice, fOutputParams, &fCardOutputs); | ||||
//set input/output param | //set input/output param | ||||
check_error ( snd_pcm_hw_params ( fInputDevice, fInputParams ) ); | check_error ( snd_pcm_hw_params ( fInputDevice, fInputParams ) ); | ||||
check_error ( snd_pcm_hw_params ( fOutputDevice, fOutputParams ) ); | check_error ( snd_pcm_hw_params ( fOutputDevice, fOutputParams ) ); | ||||
@@ -260,14 +260,14 @@ namespace Jack | |||||
for ( unsigned int i = 0; i < fSoftInputs; i++ ) | for ( unsigned int i = 0; i < fSoftInputs; i++ ) | ||||
{ | { | ||||
fInputSoftChannels[i] = ( float* ) aligned_calloc ( fBuffering, sizeof ( float ) ); | |||||
fInputSoftChannels[i] = ( jack_default_audio_sample_t* ) aligned_calloc ( fBuffering, sizeof ( jack_default_audio_sample_t ) ); | |||||
for ( int j = 0; j < fBuffering; j++ ) | for ( int j = 0; j < fBuffering; j++ ) | ||||
fInputSoftChannels[i][j] = 0.0; | fInputSoftChannels[i][j] = 0.0; | ||||
} | } | ||||
for ( unsigned int i = 0; i < fSoftOutputs; i++ ) | for ( unsigned int i = 0; i < fSoftOutputs; i++ ) | ||||
{ | { | ||||
fOutputSoftChannels[i] = ( float* ) aligned_calloc ( fBuffering, sizeof ( float ) ); | |||||
fOutputSoftChannels[i] = ( jack_default_audio_sample_t* ) aligned_calloc ( fBuffering, sizeof ( jack_default_audio_sample_t ) ); | |||||
for ( int j = 0; j < fBuffering; j++ ) | for ( int j = 0; j < fBuffering; j++ ) | ||||
fOutputSoftChannels[i][j] = 0.0; | fOutputSoftChannels[i][j] = 0.0; | ||||
} | } | ||||
@@ -376,14 +376,14 @@ namespace Jack | |||||
short* buffer16b = ( short* ) fInputCardBuffer; | short* buffer16b = ( short* ) fInputCardBuffer; | ||||
for ( s = 0; s < fBuffering; s++ ) | for ( s = 0; s < fBuffering; s++ ) | ||||
for ( c = 0; c < fCardInputs; c++ ) | for ( c = 0; c < fCardInputs; c++ ) | ||||
fInputSoftChannels[c][s] = float ( buffer16b[c + s*fCardInputs] ) * ( 1.0/float ( SHRT_MAX ) ); | |||||
fInputSoftChannels[c][s] = jack_default_audio_sample_t(buffer16b[c + s*fCardInputs]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(SHRT_MAX)); | |||||
} | } | ||||
else // SND_PCM_FORMAT_S32 | else // SND_PCM_FORMAT_S32 | ||||
{ | { | ||||
int32_t* buffer32b = ( int32_t* ) fInputCardBuffer; | int32_t* buffer32b = ( int32_t* ) fInputCardBuffer; | ||||
for ( s = 0; s < fBuffering; s++ ) | for ( s = 0; s < fBuffering; s++ ) | ||||
for ( c = 0; c < fCardInputs; c++ ) | for ( c = 0; c < fCardInputs; c++ ) | ||||
fInputSoftChannels[c][s] = float ( buffer32b[c + s*fCardInputs] ) * ( 1.0/float ( INT_MAX ) ); | |||||
fInputSoftChannels[c][s] = jack_default_audio_sample_t(buffer32b[c + s*fCardInputs]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(INT_MAX)); | |||||
} | } | ||||
break; | break; | ||||
case SND_PCM_ACCESS_RW_NONINTERLEAVED : | case SND_PCM_ACCESS_RW_NONINTERLEAVED : | ||||
@@ -400,7 +400,7 @@ namespace Jack | |||||
{ | { | ||||
chan16b = ( short* ) fInputCardChannels[c]; | chan16b = ( short* ) fInputCardChannels[c]; | ||||
for ( s = 0; s < fBuffering; s++ ) | for ( s = 0; s < fBuffering; s++ ) | ||||
fInputSoftChannels[c][s] = float ( chan16b[s] ) * ( 1.0/float ( SHRT_MAX ) ); | |||||
fInputSoftChannels[c][s] = jack_default_audio_sample_t(chan16b[s]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(SHRT_MAX)); | |||||
} | } | ||||
} | } | ||||
else // SND_PCM_FORMAT_S32 | else // SND_PCM_FORMAT_S32 | ||||
@@ -410,7 +410,7 @@ namespace Jack | |||||
{ | { | ||||
chan32b = ( int32_t* ) fInputCardChannels[c]; | chan32b = ( int32_t* ) fInputCardChannels[c]; | ||||
for ( s = 0; s < fBuffering; s++ ) | for ( s = 0; s < fBuffering; s++ ) | ||||
fInputSoftChannels[c][s] = float ( chan32b[s] ) * ( 1.0/float ( INT_MAX ) ); | |||||
fInputSoftChannels[c][s] = jack_default_audio_sample_t(chan32b[s]) * (jack_default_audio_sample_t(1.0)/jack_default_audio_sample_t(INT_MAX)); | |||||
} | } | ||||
} | } | ||||
break; | break; | ||||
@@ -440,8 +440,8 @@ namespace Jack | |||||
{ | { | ||||
for ( unsigned int c = 0; c < fCardOutputs; c++ ) | for ( unsigned int c = 0; c < fCardOutputs; c++ ) | ||||
{ | { | ||||
float x = fOutputSoftChannels[c][f]; | |||||
buffer16b[c + f * fCardOutputs] = short ( max ( min ( x, 1.0 ), -1.0 ) * float ( SHRT_MAX ) ); | |||||
jack_default_audio_sample_t x = fOutputSoftChannels[c][f]; | |||||
buffer16b[c + f * fCardOutputs] = short(max(min (x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(SHRT_MAX)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -452,8 +452,8 @@ namespace Jack | |||||
{ | { | ||||
for ( unsigned int c = 0; c < fCardOutputs; c++ ) | for ( unsigned int c = 0; c < fCardOutputs; c++ ) | ||||
{ | { | ||||
float x = fOutputSoftChannels[c][f]; | |||||
buffer32b[c + f * fCardOutputs] = int32_t ( max ( min ( x, 1.0 ), -1.0 ) * float ( INT_MAX ) ); | |||||
jack_default_audio_sample_t x = fOutputSoftChannels[c][f]; | |||||
buffer32b[c + f * fCardOutputs] = int32_t(max(min(x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(INT_MAX)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -474,8 +474,8 @@ namespace Jack | |||||
short* chan16b = ( short* ) fOutputCardChannels[c]; | short* chan16b = ( short* ) fOutputCardChannels[c]; | ||||
for ( f = 0; f < fBuffering; f++ ) | for ( f = 0; f < fBuffering; f++ ) | ||||
{ | { | ||||
float x = fOutputSoftChannels[c][f]; | |||||
chan16b[f] = short ( max ( min ( x,1.0 ), -1.0 ) * float ( SHRT_MAX ) ) ; | |||||
jack_default_audio_sample_t x = fOutputSoftChannels[c][f]; | |||||
chan16b[f] = short(max(min (x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(SHRT_MAX)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -486,8 +486,8 @@ namespace Jack | |||||
int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c]; | int32_t* chan32b = ( int32_t* ) fOutputCardChannels[c]; | ||||
for ( f = 0; f < fBuffering; f++ ) | for ( f = 0; f < fBuffering; f++ ) | ||||
{ | { | ||||
float x = fOutputSoftChannels[c][f]; | |||||
chan32b[f] = int32_t ( max ( min ( x,1.0 ),-1.0 ) * float ( INT_MAX ) ) ; | |||||
jack_default_audio_sample_t x = fOutputSoftChannels[c][f]; | |||||
chan32b[f] = int32_t(max(min(x, jack_default_audio_sample_t(1.0)), jack_default_audio_sample_t(-1.0)) * jack_default_audio_sample_t(INT_MAX)); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -24,7 +24,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackAudioDriver.h" | #include "JackAudioDriver.h" | ||||
#include "JackThreadedDriver.h" | #include "JackThreadedDriver.h" | ||||
#include "JackTime.h" | #include "JackTime.h" | ||||
#include "alsa_driver.h" | #include "alsa_driver.h" | ||||
namespace Jack | namespace Jack | ||||
@@ -42,87 +41,11 @@ class JackAlsaDriver : public JackAudioDriver | |||||
jack_driver_t* fDriver; | jack_driver_t* fDriver; | ||||
int fReservedCaptureDevice; | int fReservedCaptureDevice; | ||||
int fReservedPlaybackDevice; | int fReservedPlaybackDevice; | ||||
void alsa_driver_release_channel_dependent_memory(alsa_driver_t *driver); | |||||
int alsa_driver_check_capabilities(alsa_driver_t *driver); | |||||
int alsa_driver_check_card_type(alsa_driver_t *driver); | |||||
int alsa_driver_hammerfall_hardware(alsa_driver_t *driver); | |||||
int alsa_driver_hdsp_hardware(alsa_driver_t *driver); | |||||
int alsa_driver_ice1712_hardware(alsa_driver_t *driver); | |||||
int alsa_driver_usx2y_hardware(alsa_driver_t *driver); | |||||
int alsa_driver_generic_hardware(alsa_driver_t *driver); | |||||
int alsa_driver_hw_specific(alsa_driver_t *driver, int hw_monitoring, | |||||
int hw_metering); | |||||
int alsa_driver_setup_io_function_pointers (alsa_driver_t *driver); | |||||
int alsa_driver_configure_stream(alsa_driver_t *driver, char *device_name, | |||||
const char *stream_name, | |||||
snd_pcm_t *handle, | |||||
snd_pcm_hw_params_t *hw_params, | |||||
snd_pcm_sw_params_t *sw_params, | |||||
unsigned int *nperiodsp, | |||||
unsigned long *nchns, | |||||
unsigned long sample_width); | |||||
int alsa_driver_set_parameters(alsa_driver_t *driver, | |||||
jack_nframes_t frames_per_cycle, | |||||
jack_nframes_t user_nperiods, | |||||
jack_nframes_t rate); | |||||
int alsa_driver_reset_parameters(alsa_driver_t *driver, | |||||
jack_nframes_t frames_per_cycle, | |||||
jack_nframes_t user_nperiods, | |||||
jack_nframes_t rate); | |||||
int alsa_driver_get_channel_addresses(alsa_driver_t *driver, | |||||
snd_pcm_uframes_t *capture_avail, | |||||
snd_pcm_uframes_t *playback_avail, | |||||
snd_pcm_uframes_t *capture_offset, | |||||
snd_pcm_uframes_t *playback_offset); | |||||
jack_driver_t * alsa_driver_new(const char *name, char *playback_alsa_device, | |||||
char *capture_alsa_device, | |||||
jack_client_t *client, | |||||
jack_nframes_t frames_per_cycle, | |||||
jack_nframes_t user_nperiods, | |||||
jack_nframes_t rate, | |||||
int hw_monitoring, | |||||
int hw_metering, | |||||
int capturing, | |||||
int playing, | |||||
DitherAlgorithm dither, | |||||
int soft_mode, | |||||
int monitor, | |||||
int user_capture_nchnls, | |||||
int user_playback_nchnls, | |||||
int shorts_first, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency, | |||||
alsa_midi_t *midi); | |||||
void alsa_driver_delete(alsa_driver_t *driver); | |||||
int alsa_driver_start(alsa_driver_t *driver); | |||||
int alsa_driver_stop(alsa_driver_t *driver); | |||||
int alsa_driver_read(alsa_driver_t *driver, jack_nframes_t nframes); | |||||
int alsa_driver_write(alsa_driver_t *driver, jack_nframes_t nframes); | |||||
jack_nframes_t alsa_driver_wait(alsa_driver_t *driver, int extra_fd, int *status, float | |||||
*delayed_usecs); | |||||
void alsa_driver_silence_untouched_channels(alsa_driver_t *driver, | |||||
jack_nframes_t nframes); | |||||
int alsa_driver_restart(alsa_driver_t *driver); | |||||
int alsa_driver_xrun_recovery(alsa_driver_t *driver, float *delayed_usecs); | |||||
void jack_driver_init(jack_driver_t *driver); | |||||
void jack_driver_nt_init(jack_driver_nt_t * driver); | |||||
public: | public: | ||||
JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | JackAlsaDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | ||||
: JackAudioDriver(name, alias, engine, table) | |||||
,fDriver(NULL) | |||||
,fReservedCaptureDevice(-1) | |||||
,fReservedPlaybackDevice(-1) | |||||
: JackAudioDriver(name, alias, engine, table),fDriver(NULL),fReservedCaptureDevice(-1),fReservedPlaybackDevice(-1) | |||||
{} | {} | ||||
virtual ~JackAlsaDriver() | virtual ~JackAlsaDriver() | ||||
{} | {} | ||||
@@ -164,7 +87,13 @@ class JackAlsaDriver : public JackAudioDriver | |||||
int SetBufferSize(jack_nframes_t buffer_size); | int SetBufferSize(jack_nframes_t buffer_size); | ||||
// jack api emulation for the midi driver | |||||
void ReadInputAux(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nread); | |||||
void MonitorInputAux(); | |||||
void ClearOutputAux(); | |||||
void WriteOutputAux(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nwritten); | |||||
void SetTimetAux(jack_time_t time); | |||||
// JACK API emulation for the midi driver | |||||
int is_realtime() const; | int is_realtime() const; | ||||
int create_thread(pthread_t *thread, int prio, int rt, void *(*start_func)(void*), void *arg); | int create_thread(pthread_t *thread, int prio, int rt, void *(*start_func)(void*), void *arg); | ||||
@@ -32,12 +32,20 @@ | |||||
#define IS_BE 0 | #define IS_BE 0 | ||||
#endif | #endif | ||||
#define TRUE 1 | |||||
#define FALSE 0 | |||||
#include "types.h" | #include "types.h" | ||||
#include "hardware.h" | #include "hardware.h" | ||||
#include "driver.h" | #include "driver.h" | ||||
#include "memops.h" | #include "memops.h" | ||||
#include "alsa_midi.h" | #include "alsa_midi.h" | ||||
#ifdef __cplusplus | |||||
extern "C" | |||||
{ | |||||
#endif | |||||
typedef void (*ReadCopyFunction) (jack_default_audio_sample_t *dst, char *src, | typedef void (*ReadCopyFunction) (jack_default_audio_sample_t *dst, char *src, | ||||
unsigned long src_bytes, | unsigned long src_bytes, | ||||
unsigned long src_skip_bytes); | unsigned long src_skip_bytes); | ||||
@@ -45,13 +53,8 @@ typedef void (*WriteCopyFunction) (char *dst, jack_default_audio_sample_t *src, | |||||
unsigned long src_bytes, | unsigned long src_bytes, | ||||
unsigned long dst_skip_bytes, | unsigned long dst_skip_bytes, | ||||
dither_state_t *state); | dither_state_t *state); | ||||
typedef void (*CopyCopyFunction) (char *dst, char *src, | |||||
unsigned long src_bytes, | |||||
unsigned long dst_skip_bytes, | |||||
unsigned long src_skip_byte); | |||||
typedef struct _alsa_driver | |||||
{ | |||||
typedef struct _alsa_driver { | |||||
JACK_DRIVER_NT_DECL | JACK_DRIVER_NT_DECL | ||||
@@ -124,7 +127,6 @@ typedef struct _alsa_driver | |||||
ReadCopyFunction read_via_copy; | ReadCopyFunction read_via_copy; | ||||
WriteCopyFunction write_via_copy; | WriteCopyFunction write_via_copy; | ||||
CopyCopyFunction channel_copy; | |||||
int dither; | int dither; | ||||
dither_state_t *dither_state; | dither_state_t *dither_state; | ||||
@@ -144,100 +146,143 @@ typedef struct _alsa_driver | |||||
alsa_midi_t *midi; | alsa_midi_t *midi; | ||||
int xrun_recovery; | int xrun_recovery; | ||||
} | |||||
alsa_driver_t; | |||||
} alsa_driver_t; | |||||
static inline void | static inline void | ||||
alsa_driver_mark_channel_done (alsa_driver_t *driver, channel_t chn) | |||||
{ | |||||
bitset_remove (driver->channels_not_done, chn); | |||||
driver->silent[chn] = 0; | |||||
alsa_driver_mark_channel_done (alsa_driver_t *driver, channel_t chn) { | |||||
bitset_remove (driver->channels_not_done, chn); | |||||
driver->silent[chn] = 0; | |||||
} | } | ||||
static inline void | static inline void | ||||
alsa_driver_silence_on_channel (alsa_driver_t *driver, channel_t chn, | alsa_driver_silence_on_channel (alsa_driver_t *driver, channel_t chn, | ||||
jack_nframes_t nframes) | |||||
{ | |||||
if (driver->playback_interleaved) { | |||||
memset_interleave | |||||
(driver->playback_addr[chn], | |||||
0, nframes * driver->playback_sample_bytes, | |||||
driver->interleave_unit, | |||||
driver->playback_interleave_skip[chn]); | |||||
} else { | |||||
memset (driver->playback_addr[chn], 0, | |||||
nframes * driver->playback_sample_bytes); | |||||
} | |||||
alsa_driver_mark_channel_done (driver, chn); | |||||
jack_nframes_t nframes) { | |||||
if (driver->playback_interleaved) { | |||||
memset_interleave | |||||
(driver->playback_addr[chn], | |||||
0, nframes * driver->playback_sample_bytes, | |||||
driver->interleave_unit, | |||||
driver->playback_interleave_skip[chn]); | |||||
} else { | |||||
memset (driver->playback_addr[chn], 0, | |||||
nframes * driver->playback_sample_bytes); | |||||
} | |||||
alsa_driver_mark_channel_done (driver,chn); | |||||
} | } | ||||
static inline void | static inline void | ||||
alsa_driver_silence_on_channel_no_mark (alsa_driver_t *driver, channel_t chn, | alsa_driver_silence_on_channel_no_mark (alsa_driver_t *driver, channel_t chn, | ||||
jack_nframes_t nframes) | |||||
{ | |||||
if (driver->playback_interleaved) { | |||||
memset_interleave | |||||
(driver->playback_addr[chn], | |||||
0, nframes * driver->playback_sample_bytes, | |||||
driver->interleave_unit, | |||||
driver->playback_interleave_skip[chn]); | |||||
} else { | |||||
memset (driver->playback_addr[chn], 0, | |||||
nframes * driver->playback_sample_bytes); | |||||
} | |||||
jack_nframes_t nframes) { | |||||
if (driver->playback_interleaved) { | |||||
memset_interleave | |||||
(driver->playback_addr[chn], | |||||
0, nframes * driver->playback_sample_bytes, | |||||
driver->interleave_unit, | |||||
driver->playback_interleave_skip[chn]); | |||||
} else { | |||||
memset (driver->playback_addr[chn], 0, | |||||
nframes * driver->playback_sample_bytes); | |||||
} | |||||
} | } | ||||
static inline void | static inline void | ||||
alsa_driver_read_from_channel (alsa_driver_t *driver, | alsa_driver_read_from_channel (alsa_driver_t *driver, | ||||
channel_t channel, | |||||
jack_default_audio_sample_t *buf, | |||||
jack_nframes_t nsamples) | |||||
channel_t channel, | |||||
jack_default_audio_sample_t *buf, | |||||
jack_nframes_t nsamples) | |||||
{ | { | ||||
driver->read_via_copy (buf, | |||||
driver->capture_addr[channel], | |||||
nsamples, | |||||
driver->capture_interleave_skip[channel]); | |||||
driver->read_via_copy (buf, | |||||
driver->capture_addr[channel], | |||||
nsamples, | |||||
driver->capture_interleave_skip[channel]); | |||||
} | } | ||||
static inline void | static inline void | ||||
alsa_driver_write_to_channel (alsa_driver_t *driver, | alsa_driver_write_to_channel (alsa_driver_t *driver, | ||||
channel_t channel, | |||||
jack_default_audio_sample_t *buf, | |||||
jack_nframes_t nsamples) | |||||
channel_t channel, | |||||
jack_default_audio_sample_t *buf, | |||||
jack_nframes_t nsamples) | |||||
{ | { | ||||
driver->write_via_copy (driver->playback_addr[channel], | |||||
buf, | |||||
nsamples, | |||||
driver->playback_interleave_skip[channel], | |||||
driver->dither_state + channel); | |||||
alsa_driver_mark_channel_done (driver, channel); | |||||
} | |||||
static inline void | |||||
alsa_driver_copy_channel (alsa_driver_t *driver, | |||||
channel_t input_channel, | |||||
channel_t output_channel, | |||||
jack_nframes_t nsamples) | |||||
{ | |||||
driver->channel_copy (driver->playback_addr[output_channel], | |||||
driver->capture_addr[input_channel], | |||||
nsamples * driver->playback_sample_bytes, | |||||
driver->playback_interleave_skip[output_channel], | |||||
driver->capture_interleave_skip[input_channel]); | |||||
alsa_driver_mark_channel_done (driver, output_channel); | |||||
driver->write_via_copy (driver->playback_addr[channel], | |||||
buf, | |||||
nsamples, | |||||
driver->playback_interleave_skip[channel], | |||||
driver->dither_state+channel); | |||||
alsa_driver_mark_channel_done (driver, channel); | |||||
} | } | ||||
void alsa_driver_silence_untouched_channels (alsa_driver_t *driver, | void alsa_driver_silence_untouched_channels (alsa_driver_t *driver, | ||||
jack_nframes_t nframes); | |||||
jack_nframes_t nframes); | |||||
void alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn, | void alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn, | ||||
ClockSyncStatus status); | |||||
ClockSyncStatus status); | |||||
int alsa_driver_listen_for_clock_sync_status (alsa_driver_t *, | int alsa_driver_listen_for_clock_sync_status (alsa_driver_t *, | ||||
ClockSyncListenerFunction, | |||||
void *arg); | |||||
ClockSyncListenerFunction, | |||||
void *arg); | |||||
int alsa_driver_stop_listen_for_clock_sync_status (alsa_driver_t *, | int alsa_driver_stop_listen_for_clock_sync_status (alsa_driver_t *, | ||||
unsigned int); | |||||
unsigned int); | |||||
void alsa_driver_clock_sync_notify (alsa_driver_t *, channel_t chn, | void alsa_driver_clock_sync_notify (alsa_driver_t *, channel_t chn, | ||||
ClockSyncStatus); | |||||
ClockSyncStatus); | |||||
int | |||||
alsa_driver_reset_parameters (alsa_driver_t *driver, | |||||
jack_nframes_t frames_per_cycle, | |||||
jack_nframes_t user_nperiods, | |||||
jack_nframes_t rate); | |||||
jack_driver_t * | |||||
alsa_driver_new (char *name, char *playback_alsa_device, | |||||
char *capture_alsa_device, | |||||
jack_client_t *client, | |||||
jack_nframes_t frames_per_cycle, | |||||
jack_nframes_t user_nperiods, | |||||
jack_nframes_t rate, | |||||
int hw_monitoring, | |||||
int hw_metering, | |||||
int capturing, | |||||
int playing, | |||||
DitherAlgorithm dither, | |||||
int soft_mode, | |||||
int monitor, | |||||
int user_capture_nchnls, | |||||
int user_playback_nchnls, | |||||
int shorts_first, | |||||
jack_nframes_t capture_latency, | |||||
jack_nframes_t playback_latency, | |||||
alsa_midi_t *midi_driver | |||||
); | |||||
void | |||||
alsa_driver_delete (alsa_driver_t *driver); | |||||
int | |||||
alsa_driver_start (alsa_driver_t *driver); | |||||
int | |||||
alsa_driver_stop (alsa_driver_t *driver); | |||||
jack_nframes_t | |||||
alsa_driver_wait (alsa_driver_t *driver, int extra_fd, int *status, float | |||||
*delayed_usecs); | |||||
int | |||||
alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes); | |||||
int | |||||
alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes); | |||||
jack_time_t jack_get_microseconds(void); | |||||
// Code implemented in JackAlsaDriver.cpp | |||||
void ReadInput(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nread); | |||||
void MonitorInput(); | |||||
void ClearOutput(); | |||||
void WriteOutput(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nwritten); | |||||
void SetTime(jack_time_t time); | |||||
int Restart(); | |||||
#ifdef __cplusplus | |||||
} | |||||
#endif | |||||
#endif /* __jack_alsa_driver_h__ */ | #endif /* __jack_alsa_driver_h__ */ |
@@ -526,7 +526,7 @@ int JackFFADODriver::Attach() | |||||
port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
// Add one buffer more latency if "async" mode is used... | // Add one buffer more latency if "async" mode is used... | ||||
range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency | |||||
range.min = range.max = (driver->period_size * (driver->device_options.nb_buffers - 1)) + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize) + driver->playback_frame_latency; | |||||
port->SetLatencyRange(JackPlaybackLatency, &range); | port->SetLatencyRange(JackPlaybackLatency, &range); | ||||
// playback port aliases (jackd1 style port names) | // playback port aliases (jackd1 style port names) | ||||
snprintf(buf, sizeof(buf) - 1, "%s:playback_%i", fClientControl.fName, (int) chn + 1); | snprintf(buf, sizeof(buf) - 1, "%s:playback_%i", fClientControl.fName, (int) chn + 1); | ||||
@@ -644,20 +644,32 @@ int JackFFADODriver::Open(ffado_jack_settings_t *params) | |||||
int JackFFADODriver::Close() | int JackFFADODriver::Close() | ||||
{ | { | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
ffado_driver_delete((ffado_driver_t*)fDriver); | ffado_driver_delete((ffado_driver_t*)fDriver); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackFFADODriver::Start() | int JackFFADODriver::Start() | ||||
{ | { | ||||
JackAudioDriver::Start(); | |||||
return ffado_driver_start((ffado_driver_t *)fDriver); | |||||
int res = JackAudioDriver::Start(); | |||||
if (res >= 0) { | |||||
res = ffado_driver_start((ffado_driver_t *)fDriver); | |||||
if (res < 0) { | |||||
JackAudioDriver::Stop(); | |||||
} | |||||
} | |||||
return res; | |||||
} | } | ||||
int JackFFADODriver::Stop() | int JackFFADODriver::Stop() | ||||
{ | { | ||||
return ffado_driver_stop((ffado_driver_t *)fDriver); | |||||
int res = ffado_driver_stop((ffado_driver_t *)fDriver); | |||||
if (JackAudioDriver::Stop() < 0) { | |||||
res = -1; | |||||
} | |||||
return res; | |||||
} | } | ||||
int JackFFADODriver::Read() | int JackFFADODriver::Read() | ||||
@@ -832,20 +832,32 @@ int JackFreebobDriver::Open(freebob_jack_settings_t *params) | |||||
int JackFreebobDriver::Close() | int JackFreebobDriver::Close() | ||||
{ | { | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
freebob_driver_delete((freebob_driver_t*)fDriver); | freebob_driver_delete((freebob_driver_t*)fDriver); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackFreebobDriver::Start() | int JackFreebobDriver::Start() | ||||
{ | { | ||||
JackAudioDriver::Start(); | |||||
return freebob_driver_start((freebob_driver_t *)fDriver); | |||||
int res = JackAudioDriver::Start(); | |||||
if (res >= 0) { | |||||
res = freebob_driver_start((freebob_driver_t *)fDriver); | |||||
if (res < 0) { | |||||
JackAudioDriver::Stop(); | |||||
} | |||||
} | |||||
return res; | |||||
} | } | ||||
int JackFreebobDriver::Stop() | int JackFreebobDriver::Stop() | ||||
{ | { | ||||
return freebob_driver_stop((freebob_driver_t *)fDriver); | |||||
int res = freebob_driver_stop((freebob_driver_t *)fDriver); | |||||
if (JackAudioDriver::Stop() < 0) { | |||||
res = -1; | |||||
} | |||||
return res; | |||||
} | } | ||||
int JackFreebobDriver::Read() | int JackFreebobDriver::Read() | ||||
@@ -44,13 +44,15 @@ def build(bld): | |||||
create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') | create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') | ||||
alsa_driver_src = ['alsa/JackAlsaDriver.cpp', | |||||
alsa_driver_src = [ | |||||
'alsa/JackAlsaDriver.cpp', | |||||
'alsa/alsa_rawmidi.c', | 'alsa/alsa_rawmidi.c', | ||||
'alsa/alsa_seqmidi.c', | 'alsa/alsa_seqmidi.c', | ||||
'alsa/alsa_midi_jackmp.cpp', | 'alsa/alsa_midi_jackmp.cpp', | ||||
'../common/memops.c', | '../common/memops.c', | ||||
'alsa/generic_hw.c', | 'alsa/generic_hw.c', | ||||
'alsa/hdsp.c', | 'alsa/hdsp.c', | ||||
'alsa/alsa_driver.c', | |||||
'alsa/hammerfall.c', | 'alsa/hammerfall.c', | ||||
'alsa/ice1712.c' | 'alsa/ice1712.c' | ||||
] | ] | ||||
@@ -1598,6 +1598,7 @@ | |||||
4B98AE010931D30C0091932A /* JackDebugClient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackDebugClient.h; path = ../common/JackDebugClient.h; sourceTree = SOURCE_ROOT; }; | 4B98AE010931D30C0091932A /* JackDebugClient.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackDebugClient.h; path = ../common/JackDebugClient.h; sourceTree = SOURCE_ROOT; }; | ||||
4B9A25B30DBF8330006E9FBC /* JackError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackError.cpp; path = ../common/JackError.cpp; sourceTree = SOURCE_ROOT; }; | 4B9A25B30DBF8330006E9FBC /* JackError.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackError.cpp; path = ../common/JackError.cpp; sourceTree = SOURCE_ROOT; }; | ||||
4B9A26000DBF8584006E9FBC /* jslist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jslist.h; path = ../common/jack/jslist.h; sourceTree = SOURCE_ROOT; }; | 4B9A26000DBF8584006E9FBC /* jslist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = jslist.h; path = ../common/jack/jslist.h; sourceTree = SOURCE_ROOT; }; | ||||
4BA2574C132FB49B009F2D3F /* alsa_driver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = alsa_driver.c; path = ../linux/alsa/alsa_driver.c; sourceTree = SOURCE_ROOT; }; | |||||
4BA339AC10B2E36800190E3B /* Jackservermp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackservermp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; | 4BA339AC10B2E36800190E3B /* Jackservermp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackservermp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; | ||||
4BA577BC08BF8BE200F82DE1 /* testSynchroClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroClient.cpp; path = ../tests/testSynchroClient.cpp; sourceTree = SOURCE_ROOT; }; | 4BA577BC08BF8BE200F82DE1 /* testSynchroClient.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroClient.cpp; path = ../tests/testSynchroClient.cpp; sourceTree = SOURCE_ROOT; }; | ||||
4BA577FB08BF8E4600F82DE1 /* testSynchroServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroServer.cpp; path = ../tests/testSynchroServer.cpp; sourceTree = SOURCE_ROOT; }; | 4BA577FB08BF8E4600F82DE1 /* testSynchroServer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSynchroServer.cpp; path = ../tests/testSynchroServer.cpp; sourceTree = SOURCE_ROOT; }; | ||||
@@ -2683,6 +2684,7 @@ | |||||
4B05A09D0DF72C6000840F4C /* Additional */ = { | 4B05A09D0DF72C6000840F4C /* Additional */ = { | ||||
isa = PBXGroup; | isa = PBXGroup; | ||||
children = ( | children = ( | ||||
4BA2574C132FB49B009F2D3F /* alsa_driver.c */, | |||||
4B05A08A0DF72BF600840F4C /* Windows */, | 4B05A08A0DF72BF600840F4C /* Windows */, | ||||
4B05A0420DF72B8500840F4C /* Linux */, | 4B05A0420DF72B8500840F4C /* Linux */, | ||||
); | ); | ||||
@@ -276,17 +276,17 @@ OSStatus JackCoreAudioAdapter::Render(void *inRefCon, | |||||
JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon); | ||||
AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData); | ||||
float* inputBuffer[adapter->fCaptureChannels]; | |||||
float* outputBuffer[adapter->fPlaybackChannels]; | |||||
jack_default_audio_sample_t* inputBuffer[adapter->fCaptureChannels]; | |||||
jack_default_audio_sample_t* outputBuffer[adapter->fPlaybackChannels]; | |||||
for (int i = 0; i < adapter->fCaptureChannels; i++) { | for (int i = 0; i < adapter->fCaptureChannels; i++) { | ||||
inputBuffer[i] = (float*)adapter->fInputData->mBuffers[i].mData; | |||||
inputBuffer[i] = (jack_default_audio_sample_t*)adapter->fInputData->mBuffers[i].mData; | |||||
} | } | ||||
for (int i = 0; i < adapter->fPlaybackChannels; i++) { | for (int i = 0; i < adapter->fPlaybackChannels; i++) { | ||||
outputBuffer[i] = (float*)ioData->mBuffers[i].mData; | |||||
outputBuffer[i] = (jack_default_audio_sample_t*)ioData->mBuffers[i].mData; | |||||
} | } | ||||
adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, inNumberFrames); | |||||
adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, inNumberFrames); | |||||
return noErr; | return noErr; | ||||
} | } | ||||
@@ -769,8 +769,8 @@ int JackCoreAudioAdapter::SetupBuffers(int inchannels) | |||||
fInputData->mNumberBuffers = inchannels; | fInputData->mNumberBuffers = inchannels; | ||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
fInputData->mBuffers[i].mNumberChannels = 1; | fInputData->mBuffers[i].mNumberChannels = 1; | ||||
fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(float); | |||||
fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(float)); | |||||
fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(jack_default_audio_sample_t); | |||||
fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(jack_default_audio_sample_t)); | |||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -942,9 +942,9 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||||
srcFormat.mSampleRate = samplerate; | srcFormat.mSampleRate = samplerate; | ||||
srcFormat.mFormatID = kAudioFormatLinearPCM; | srcFormat.mFormatID = kAudioFormatLinearPCM; | ||||
srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | ||||
srcFormat.mBytesPerPacket = sizeof(float); | |||||
srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t); | |||||
srcFormat.mFramesPerPacket = 1; | srcFormat.mFramesPerPacket = 1; | ||||
srcFormat.mBytesPerFrame = sizeof(float); | |||||
srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t); | |||||
srcFormat.mChannelsPerFrame = inchannels; | srcFormat.mChannelsPerFrame = inchannels; | ||||
srcFormat.mBitsPerChannel = 32; | srcFormat.mBitsPerChannel = 32; | ||||
PrintStreamDesc(&srcFormat); | PrintStreamDesc(&srcFormat); | ||||
@@ -973,9 +973,9 @@ int JackCoreAudioAdapter::OpenAUHAL(bool capturing, | |||||
dstFormat.mSampleRate = samplerate; | dstFormat.mSampleRate = samplerate; | ||||
dstFormat.mFormatID = kAudioFormatLinearPCM; | dstFormat.mFormatID = kAudioFormatLinearPCM; | ||||
dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | ||||
dstFormat.mBytesPerPacket = sizeof(float); | |||||
dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t); | |||||
dstFormat.mFramesPerPacket = 1; | dstFormat.mFramesPerPacket = 1; | ||||
dstFormat.mBytesPerFrame = sizeof(float); | |||||
dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t); | |||||
dstFormat.mChannelsPerFrame = outchannels; | dstFormat.mChannelsPerFrame = outchannels; | ||||
dstFormat.mBitsPerChannel = 32; | dstFormat.mBitsPerChannel = 32; | ||||
PrintStreamDesc(&dstFormat); | PrintStreamDesc(&dstFormat); | ||||
@@ -55,7 +55,7 @@ static void PrintStreamDesc(AudioStreamBasicDescription *inDesc) | |||||
jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame); | jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame); | ||||
jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame); | jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame); | ||||
jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel); | jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel); | ||||
jack_log("- - - - - - - - - - - - - - - - - - - -\n"); | |||||
jack_log("- - - - - - - - - - - - - - - - - - - -"); | |||||
} | } | ||||
static void printError(OSStatus err) | static void printError(OSStatus err) | ||||
@@ -224,20 +224,19 @@ int JackCoreAudioDriver::Write() | |||||
{ | { | ||||
for (int i = 0; i < fPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels; i++) { | ||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) { | if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) { | ||||
float* buffer = GetOutputBuffer(i); | |||||
int size = sizeof(float) * fEngineControl->fBufferSize; | |||||
memcpy((float*)fDriverOutputData->mBuffers[i].mData, buffer, size); | |||||
jack_default_audio_sample_t* buffer = GetOutputBuffer(i); | |||||
int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize; | |||||
memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size); | |||||
// Monitor ports | // Monitor ports | ||||
if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) | if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) | ||||
memcpy(GetMonitorBuffer(i), buffer, size); | memcpy(GetMonitorBuffer(i), buffer, size); | ||||
} else { | } else { | ||||
memset((float*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(float) * fEngineControl->fBufferSize); | |||||
memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice, | OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice, | ||||
UInt32 inChannel, | UInt32 inChannel, | ||||
Boolean isInput, | Boolean isInput, | ||||
@@ -1294,9 +1293,9 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||||
srcFormat.mSampleRate = samplerate; | srcFormat.mSampleRate = samplerate; | ||||
srcFormat.mFormatID = kAudioFormatLinearPCM; | srcFormat.mFormatID = kAudioFormatLinearPCM; | ||||
srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | ||||
srcFormat.mBytesPerPacket = sizeof(float); | |||||
srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t); | |||||
srcFormat.mFramesPerPacket = 1; | srcFormat.mFramesPerPacket = 1; | ||||
srcFormat.mBytesPerFrame = sizeof(float); | |||||
srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t); | |||||
srcFormat.mChannelsPerFrame = inchannels; | srcFormat.mChannelsPerFrame = inchannels; | ||||
srcFormat.mBitsPerChannel = 32; | srcFormat.mBitsPerChannel = 32; | ||||
PrintStreamDesc(&srcFormat); | PrintStreamDesc(&srcFormat); | ||||
@@ -1324,9 +1323,9 @@ int JackCoreAudioDriver::OpenAUHAL(bool capturing, | |||||
dstFormat.mSampleRate = samplerate; | dstFormat.mSampleRate = samplerate; | ||||
dstFormat.mFormatID = kAudioFormatLinearPCM; | dstFormat.mFormatID = kAudioFormatLinearPCM; | ||||
dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved; | ||||
dstFormat.mBytesPerPacket = sizeof(float); | |||||
dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t); | |||||
dstFormat.mFramesPerPacket = 1; | dstFormat.mFramesPerPacket = 1; | ||||
dstFormat.mBytesPerFrame = sizeof(float); | |||||
dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t); | |||||
dstFormat.mChannelsPerFrame = outchannels; | dstFormat.mChannelsPerFrame = outchannels; | ||||
dstFormat.mBitsPerChannel = 32; | dstFormat.mBitsPerChannel = 32; | ||||
PrintStreamDesc(&dstFormat); | PrintStreamDesc(&dstFormat); | ||||
@@ -1376,7 +1375,7 @@ int JackCoreAudioDriver::SetupBuffers(int inchannels) | |||||
fJackInputData->mNumberBuffers = inchannels; | fJackInputData->mNumberBuffers = inchannels; | ||||
for (int i = 0; i < inchannels; i++) { | for (int i = 0; i < inchannels; i++) { | ||||
fJackInputData->mBuffers[i].mNumberChannels = 1; | fJackInputData->mBuffers[i].mNumberChannels = 1; | ||||
fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float); | |||||
fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t); | |||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -1551,12 +1550,15 @@ int JackCoreAudioDriver::Close() | |||||
{ | { | ||||
jack_log("JackCoreAudioDriver::Close"); | jack_log("JackCoreAudioDriver::Close"); | ||||
Stop(); | Stop(); | ||||
JackAudioDriver::Close(); | |||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | |||||
RemoveListeners(); | RemoveListeners(); | ||||
DisposeBuffers(); | DisposeBuffers(); | ||||
CloseAUHAL(); | CloseAUHAL(); | ||||
DestroyAggregateDevice(); | DestroyAggregateDevice(); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackCoreAudioDriver::Attach() | int JackCoreAudioDriver::Attach() | ||||
@@ -1577,11 +1579,11 @@ int JackCoreAudioDriver::Attach() | |||||
err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable); | err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error "); | |||||
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error"); | |||||
if (err == noErr && size > 0) { | if (err == noErr && size > 0) { | ||||
err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name); | err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error "); | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error"); | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1); | ||||
} else { | } else { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1); | ||||
@@ -1599,10 +1601,10 @@ int JackCoreAudioDriver::Attach() | |||||
UInt32 value2 = 0; | UInt32 value2 = 0; | ||||
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); | err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error "); | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); | err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error "); | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
port->SetAlias(alias); | port->SetAlias(alias); | ||||
@@ -1615,11 +1617,11 @@ int JackCoreAudioDriver::Attach() | |||||
err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable); | err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error "); | |||||
jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error"); | |||||
if (err == noErr && size > 0) { | if (err == noErr && size > 0) { | ||||
err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name); | err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error "); | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error"); | |||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1); | ||||
} else { | } else { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1); | ||||
@@ -1637,10 +1639,10 @@ int JackCoreAudioDriver::Attach() | |||||
UInt32 value2 = 0; | UInt32 value2 = 0; | ||||
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); | err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error "); | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error"); | |||||
err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); | err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2); | ||||
if (err != noErr) | if (err != noErr) | ||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error "); | |||||
jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error"); | |||||
port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
port->SetAlias(alias); | port->SetAlias(alias); | ||||
@@ -1651,14 +1653,13 @@ int JackCoreAudioDriver::Attach() | |||||
// Monitor ports | // Monitor ports | ||||
if (fWithMonitorPorts) { | if (fWithMonitorPorts) { | ||||
jack_log("Create monitor port "); | |||||
jack_log("Create monitor port"); | |||||
snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1); | snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1); | ||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
jack_error("Cannot register monitor port for %s", name); | jack_error("Cannot register monitor port for %s", name); | ||||
return -1; | return -1; | ||||
} else { | } else { | ||||
port = fGraphManager->GetPort(port_index); | port = fGraphManager->GetPort(port_index); | ||||
port->SetAlias(alias); | |||||
range.min = range.max = fEngineControl->fBufferSize; | range.min = range.max = fEngineControl->fBufferSize; | ||||
port->SetLatencyRange(JackCaptureLatency, &range); | port->SetLatencyRange(JackCaptureLatency, &range); | ||||
fMonitorPortList[i] = port_index; | fMonitorPortList[i] = port_index; | ||||
@@ -1677,33 +1678,38 @@ int JackCoreAudioDriver::Attach() | |||||
int JackCoreAudioDriver::Start() | int JackCoreAudioDriver::Start() | ||||
{ | { | ||||
jack_log("JackCoreAudioDriver::Start"); | jack_log("JackCoreAudioDriver::Start"); | ||||
JackAudioDriver::Start(); | |||||
if (JackAudioDriver::Start() >= 0) { | |||||
OSStatus err = AudioOutputUnitStart(fAUHAL); | |||||
if (err == noErr) { | |||||
OSStatus err = AudioOutputUnitStart(fAUHAL); | |||||
if (err != noErr) | |||||
return -1; | |||||
// Waiting for Measure callback to be called (= driver has started) | |||||
fState = false; | |||||
int count = 0; | |||||
while (!fState && count++ < WAIT_COUNTER) { | |||||
usleep(100000); | |||||
jack_log("JackCoreAudioDriver::Start wait count = %d", count); | |||||
} | |||||
// Waiting for Measure callback to be called (= driver has started) | |||||
fState = false; | |||||
int count = 0; | |||||
while (!fState && count++ < WAIT_COUNTER) { | |||||
usleep(100000); | |||||
jack_log("JackCoreAudioDriver::Start wait count = %d", count); | |||||
} | |||||
if (count < WAIT_COUNTER) { | |||||
jack_info("CoreAudio driver is running..."); | |||||
return 0; | |||||
} | |||||
if (count < WAIT_COUNTER) { | |||||
jack_info("CoreAudio driver is running..."); | |||||
return 0; | |||||
} else { | |||||
jack_error("CoreAudio driver cannot start..."); | |||||
return -1; | |||||
jack_error("CoreAudio driver cannot start..."); | |||||
} | |||||
JackAudioDriver::Stop(); | |||||
} | } | ||||
return -1; | |||||
} | } | ||||
int JackCoreAudioDriver::Stop() | int JackCoreAudioDriver::Stop() | ||||
{ | { | ||||
jack_log("JackCoreAudioDriver::Stop"); | jack_log("JackCoreAudioDriver::Stop"); | ||||
return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; | |||||
int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1; | |||||
if (JackAudioDriver::Stop() < 0) { | |||||
res = -1; | |||||
} | |||||
return res; | |||||
} | } | ||||
int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
@@ -1723,7 +1729,7 @@ int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | |||||
// Input buffers do no change : prepare them only once | // Input buffers do no change : prepare them only once | ||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
fJackInputData->mBuffers[i].mNumberChannels = 1; | fJackInputData->mBuffers[i].mNumberChannels = 1; | ||||
fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float); | |||||
fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t); | |||||
fJackInputData->mBuffers[i].mData = GetInputBuffer(i); | fJackInputData->mBuffers[i].mData = GetInputBuffer(i); | ||||
} | } | ||||
@@ -45,15 +45,15 @@ void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuf | |||||
jack_error("ReadProc : ring buffer is full, skip events..."); | jack_error("ReadProc : ring buffer is full, skip events..."); | ||||
return; | return; | ||||
} | } | ||||
jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32)); | jack_ringbuffer_write(ringbuffer, (char*)&pktlist->numPackets, sizeof(UInt32)); | ||||
for (unsigned int i = 0; i < pktlist->numPackets; ++i) { | for (unsigned int i = 0; i < pktlist->numPackets; ++i) { | ||||
MIDIPacket *packet = (MIDIPacket *)pktlist->packet; | MIDIPacket *packet = (MIDIPacket *)pktlist->packet; | ||||
// TODO : use timestamp | // TODO : use timestamp | ||||
// Check available size first.. | // Check available size first.. | ||||
size = jack_ringbuffer_write_space(ringbuffer); | size = jack_ringbuffer_write_space(ringbuffer); | ||||
if (size < (sizeof(UInt16) + packet->length)) { | if (size < (sizeof(UInt16) + packet->length)) { | ||||
@@ -64,7 +64,7 @@ void JackCoreMidiDriver::ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuf | |||||
jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16)); | jack_ringbuffer_write(ringbuffer, (char*)&packet->length, sizeof(UInt16)); | ||||
// Write event actual data | // Write event actual data | ||||
jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length); | jack_ringbuffer_write(ringbuffer, (char*)packet->data, packet->length); | ||||
packet = MIDIPacketNext(packet); | packet = MIDIPacketNext(packet); | ||||
} | } | ||||
} | } | ||||
@@ -83,7 +83,7 @@ void JackCoreMidiDriver::ReadVirtualProc(const MIDIPacketList *pktlist, void *re | |||||
void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon) | void JackCoreMidiDriver::NotifyProc(const MIDINotification *message, void *refCon) | ||||
{ | { | ||||
jack_info("NotifyProc %d", message->messageID); | |||||
jack_log("NotifyProc %d", message->messageID); | |||||
} | } | ||||
JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | JackCoreMidiDriver::JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) | ||||
@@ -106,15 +106,15 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
OSStatus err; | OSStatus err; | ||||
CFStringRef coutputStr; | CFStringRef coutputStr; | ||||
std::string str; | std::string str; | ||||
// Get real input/output number | // Get real input/output number | ||||
fRealCaptureChannels = MIDIGetNumberOfSources(); | fRealCaptureChannels = MIDIGetNumberOfSources(); | ||||
fRealPlaybackChannels = MIDIGetNumberOfDestinations(); | fRealPlaybackChannels = MIDIGetNumberOfDestinations(); | ||||
// Generic JackMidiDriver Open | // Generic JackMidiDriver Open | ||||
if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) | if (JackMidiDriver::Open(capturing, playing, inchannels + fRealCaptureChannels, outchannels + fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) | ||||
return -1; | return -1; | ||||
coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding()); | coutputStr = CFStringCreateWithCString(0, "JackMidi", CFStringGetSystemEncoding()); | ||||
err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient); | err = MIDIClientCreate(coutputStr, NotifyProc, this, &fMidiClient); | ||||
CFRelease(coutputStr); | CFRelease(coutputStr); | ||||
@@ -122,7 +122,7 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
jack_error("Cannot create CoreMidi client"); | jack_error("Cannot create CoreMidi client"); | ||||
goto error; | goto error; | ||||
} | } | ||||
err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort); | err = MIDIInputPortCreate(fMidiClient, CFSTR("Input port"), ReadProc, this, &fInputPort); | ||||
if (!fInputPort) { | if (!fInputPort) { | ||||
jack_error("Cannot open CoreMidi in port\n"); | jack_error("Cannot open CoreMidi in port\n"); | ||||
@@ -134,10 +134,10 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
jack_error("Cannot open CoreMidi out port\n"); | jack_error("Cannot open CoreMidi out port\n"); | ||||
goto error; | goto error; | ||||
} | } | ||||
fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels]; | fMidiDestination = new MIDIEndpointRef[inchannels + fRealCaptureChannels]; | ||||
assert(fMidiDestination); | assert(fMidiDestination); | ||||
// Virtual input | // Virtual input | ||||
for (int i = 0; i < inchannels; i++) { | for (int i = 0; i < inchannels; i++) { | ||||
std::stringstream num; | std::stringstream num; | ||||
@@ -151,13 +151,13 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
goto error; | goto error; | ||||
} | } | ||||
} | } | ||||
// Real input | // Real input | ||||
for (int i = 0; i < fRealCaptureChannels; i++) { | for (int i = 0; i < fRealCaptureChannels; i++) { | ||||
fMidiDestination[i + inchannels] = MIDIGetSource(i); | fMidiDestination[i + inchannels] = MIDIGetSource(i); | ||||
MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]); | MIDIPortConnectSource(fInputPort, fMidiDestination[i + inchannels], fRingBuffer[i + inchannels]); | ||||
} | } | ||||
fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels]; | fMidiSource = new MIDIEndpointRef[outchannels + fRealPlaybackChannels]; | ||||
assert(fMidiSource); | assert(fMidiSource); | ||||
@@ -172,47 +172,50 @@ int JackCoreMidiDriver::Open(bool capturing, | |||||
if (!fMidiSource[i]) { | if (!fMidiSource[i]) { | ||||
jack_error("Cannot create CoreMidi source"); | jack_error("Cannot create CoreMidi source"); | ||||
goto error; | goto error; | ||||
} | |||||
} | |||||
} | } | ||||
// Real output | // Real output | ||||
for (int i = 0; i < fRealPlaybackChannels; i++) { | for (int i = 0; i < fRealPlaybackChannels; i++) { | ||||
fMidiSource[i + outchannels] = MIDIGetDestination(i); | fMidiSource[i + outchannels] = MIDIGetDestination(i); | ||||
} | } | ||||
return 0; | return 0; | ||||
error: | error: | ||||
Close(); | Close(); | ||||
return -1; | return -1; | ||||
} | } | ||||
int JackCoreMidiDriver::Close() | int JackCoreMidiDriver::Close() | ||||
{ | { | ||||
// Generic midi driver close | |||||
int res = JackMidiDriver::Close(); | |||||
if (fInputPort) | if (fInputPort) | ||||
MIDIPortDispose(fInputPort); | MIDIPortDispose(fInputPort); | ||||
if (fOutputPort) | |||||
if (fOutputPort) | |||||
MIDIPortDispose(fOutputPort); | MIDIPortDispose(fOutputPort); | ||||
// Only dispose "virtual" endpoints | // Only dispose "virtual" endpoints | ||||
for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels - fRealCaptureChannels; i++) { | ||||
if (fMidiDestination) | |||||
if (fMidiDestination) | |||||
MIDIEndpointDispose(fMidiDestination[i]); | MIDIEndpointDispose(fMidiDestination[i]); | ||||
} | } | ||||
delete[] fMidiDestination; | delete[] fMidiDestination; | ||||
// Only dispose "virtual" endpoints | // Only dispose "virtual" endpoints | ||||
for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) { | for (int i = 0; i < fPlaybackChannels - fRealPlaybackChannels; i++) { | ||||
if (fMidiSource[i]) | |||||
if (fMidiSource[i]) | |||||
MIDIEndpointDispose(fMidiSource[i]); | MIDIEndpointDispose(fMidiSource[i]); | ||||
} | } | ||||
delete[] fMidiSource; | delete[] fMidiSource; | ||||
if (fMidiClient) | |||||
if (fMidiClient) | |||||
MIDIClientDispose(fMidiClient); | MIDIClientDispose(fMidiClient); | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackCoreMidiDriver::Attach() | int JackCoreMidiDriver::Attach() | ||||
@@ -229,7 +232,7 @@ int JackCoreMidiDriver::Attach() | |||||
jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | jack_log("JackCoreMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); | ||||
for (i = 0; i < fCaptureChannels; i++) { | for (i = 0; i < fCaptureChannels; i++) { | ||||
err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname); | err = MIDIObjectGetStringProperty(fMidiDestination[i], kMIDIPropertyName, &pname); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | ||||
@@ -238,7 +241,7 @@ int JackCoreMidiDriver::Attach() | |||||
} else { | } else { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); | ||||
} | } | ||||
snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); | snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); | ||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
@@ -251,7 +254,7 @@ int JackCoreMidiDriver::Attach() | |||||
} | } | ||||
for (i = 0; i < fPlaybackChannels; i++) { | for (i = 0; i < fPlaybackChannels; i++) { | ||||
err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname); | err = MIDIObjectGetStringProperty(fMidiSource[i], kMIDIPropertyName, &pname); | ||||
if (err == noErr) { | if (err == noErr) { | ||||
CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | CFStringGetCString(pname, endpoint_name, sizeof(endpoint_name), 0); | ||||
@@ -260,7 +263,7 @@ int JackCoreMidiDriver::Attach() | |||||
} else { | } else { | ||||
snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1); | snprintf(alias, sizeof(alias) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, i + 1); | ||||
} | } | ||||
snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); | snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); | ||||
if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize)) == NO_PORT) { | ||||
jack_error("driver: cannot register port for %s", name); | jack_error("driver: cannot register port for %s", name); | ||||
@@ -277,23 +280,23 @@ int JackCoreMidiDriver::Attach() | |||||
int JackCoreMidiDriver::Read() | int JackCoreMidiDriver::Read() | ||||
{ | { | ||||
for (int chan = 0; chan < fCaptureChannels; chan++) { | for (int chan = 0; chan < fCaptureChannels; chan++) { | ||||
if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { | if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { | ||||
// Get JACK port | // Get JACK port | ||||
JackMidiBuffer* midi_buffer = GetInputBuffer(chan); | JackMidiBuffer* midi_buffer = GetInputBuffer(chan); | ||||
if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) { | if (jack_ringbuffer_read_space(fRingBuffer[chan]) == 0) { | ||||
// Reset buffer | // Reset buffer | ||||
midi_buffer->Reset(midi_buffer->nframes); | midi_buffer->Reset(midi_buffer->nframes); | ||||
} else { | } else { | ||||
while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) { | while (jack_ringbuffer_read_space(fRingBuffer[chan]) > 0) { | ||||
// Read event number | // Read event number | ||||
int ev_count = 0; | int ev_count = 0; | ||||
jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); | jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); | ||||
for (int j = 0; j < ev_count; j++) { | for (int j = 0; j < ev_count; j++) { | ||||
// Read event length | // Read event length | ||||
UInt16 event_len; | UInt16 event_len; | ||||
@@ -304,7 +307,7 @@ int JackCoreMidiDriver::Read() | |||||
} | } | ||||
} | } | ||||
} | } | ||||
} else { | } else { | ||||
// Consume ring buffer | // Consume ring buffer | ||||
jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); | ||||
@@ -316,35 +319,35 @@ int JackCoreMidiDriver::Read() | |||||
int JackCoreMidiDriver::Write() | int JackCoreMidiDriver::Write() | ||||
{ | { | ||||
MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer; | MIDIPacketList* pktlist = (MIDIPacketList*)fMIDIBuffer; | ||||
for (int chan = 0; chan < fPlaybackChannels; chan++) { | for (int chan = 0; chan < fPlaybackChannels; chan++) { | ||||
if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { | if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { | ||||
MIDIPacket* packet = MIDIPacketListInit(pktlist); | MIDIPacket* packet = MIDIPacketListInit(pktlist); | ||||
JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); | JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); | ||||
// TODO : use timestamp | // TODO : use timestamp | ||||
for (unsigned int j = 0; j < midi_buffer->event_count; j++) { | for (unsigned int j = 0; j < midi_buffer->event_count; j++) { | ||||
JackMidiEvent* ev = &midi_buffer->events[j]; | JackMidiEvent* ev = &midi_buffer->events[j]; | ||||
packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer)); | packet = MIDIPacketListAdd(pktlist, sizeof(fMIDIBuffer), packet, MIDIGetCurrentHostTime(), ev->size, ev->GetData(midi_buffer)); | ||||
} | } | ||||
if (packet) { | if (packet) { | ||||
if (chan < fPlaybackChannels - fRealPlaybackChannels) { | if (chan < fPlaybackChannels - fRealPlaybackChannels) { | ||||
OSStatus err = MIDIReceived(fMidiSource[chan], pktlist); | OSStatus err = MIDIReceived(fMidiSource[chan], pktlist); | ||||
if (err != noErr) | |||||
if (err != noErr) | |||||
jack_error("MIDIReceived error"); | jack_error("MIDIReceived error"); | ||||
} else { | } else { | ||||
OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist); | OSStatus err = MIDISend(fOutputPort, fMidiSource[chan], pktlist); | ||||
if (err != noErr) | |||||
if (err != noErr) | |||||
jack_error("MIDISend error"); | jack_error("MIDISend error"); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -355,7 +358,7 @@ extern "C" | |||||
{ | { | ||||
#endif | #endif | ||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() | |||||
{ | { | ||||
jack_driver_desc_t * desc; | jack_driver_desc_t * desc; | ||||
unsigned int i; | unsigned int i; | ||||
@@ -366,7 +369,7 @@ extern "C" | |||||
desc->nparams = 2; | desc->nparams = 2; | ||||
desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); | ||||
i = 0; | i = 0; | ||||
strcpy(desc->params[i].name, "inchannels"); | strcpy(desc->params[i].name, "inchannels"); | ||||
desc->params[i].character = 'i'; | desc->params[i].character = 'i'; | ||||
@@ -386,7 +389,7 @@ extern "C" | |||||
return desc; | return desc; | ||||
} | } | ||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) | |||||
{ | { | ||||
const JSList * node; | const JSList * node; | ||||
const jack_driver_param_t * param; | const jack_driver_param_t * param; | ||||
@@ -407,7 +410,7 @@ extern "C" | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table); | Jack::JackDriverClientInterface* driver = new Jack::JackCoreMidiDriver("system_midi", "coremidi", engine, table); | ||||
if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) { | if (driver->Open(1, 1, virtual_in, virtual_out, false, "in", "out", 0, 0) == 0) { | ||||
return driver; | return driver; | ||||
@@ -41,17 +41,17 @@ class JackCoreMidiDriver : public JackMidiDriver | |||||
MIDIPortRef fOutputPort; | MIDIPortRef fOutputPort; | ||||
MIDIEndpointRef* fMidiDestination; | MIDIEndpointRef* fMidiDestination; | ||||
MIDIEndpointRef* fMidiSource; | MIDIEndpointRef* fMidiSource; | ||||
char fMIDIBuffer[BUFFER_SIZE_MAX * sizeof(float)]; | |||||
char fMIDIBuffer[BUFFER_SIZE_MAX * sizeof(jack_default_audio_sample_t)]; | |||||
int fRealCaptureChannels; | int fRealCaptureChannels; | ||||
int fRealPlaybackChannels; | int fRealPlaybackChannels; | ||||
static void ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuffer_t* ringbuffer); | static void ReadProcAux(const MIDIPacketList *pktlist, jack_ringbuffer_t* ringbuffer); | ||||
static void ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | static void ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | ||||
static void ReadVirtualProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | static void ReadVirtualProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon); | ||||
static void NotifyProc(const MIDINotification *message, void *refCon); | static void NotifyProc(const MIDINotification *message, void *refCon); | ||||
public: | public: | ||||
JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | JackCoreMidiDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table); | ||||
@@ -67,7 +67,7 @@ class JackCoreMidiDriver : public JackMidiDriver | |||||
jack_nframes_t capture_latency, | jack_nframes_t capture_latency, | ||||
jack_nframes_t playback_latency); | jack_nframes_t playback_latency); | ||||
int Close(); | int Close(); | ||||
int Attach(); | int Attach(); | ||||
int Read(); | int Read(); | ||||
@@ -392,7 +392,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) | |||||
JackInternalClientLoadRequest req; | JackInternalClientLoadRequest req; | ||||
JackInternalClientLoadResult res; | JackInternalClientLoadResult res; | ||||
if (req.Read(socket) == 0) | if (req.Read(socket) == 0) | ||||
res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
if (res.Write(socket) < 0) | if (res.Write(socket) < 0) | ||||
jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName); | jack_error("JackRequest::InternalClientLoad write error name = %s", req.fName); | ||||
break; | break; | ||||
@@ -25,7 +25,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include <signal.h> | #include <signal.h> | ||||
#include <dlfcn.h> | #include <dlfcn.h> | ||||
#ifndef UINT32_MAX | |||||
#define UINT32_MAX 4294967295U | #define UINT32_MAX 4294967295U | ||||
#endif | |||||
#define DRIVER_HANDLE void* | #define DRIVER_HANDLE void* | ||||
#define LoadDriverModule(name) dlopen((name), RTLD_NOW | RTLD_GLOBAL) | #define LoadDriverModule(name) dlopen((name), RTLD_NOW | RTLD_GLOBAL) | ||||
@@ -1,5 +1,5 @@ | |||||
/* | /* | ||||
Copyright (C) 2006 Grame | |||||
Copyright (C) 2006 Grame | |||||
This program is free software; you can redistribute it and/or modify | 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 | it under the terms of the GNU General Public License as published by | ||||
@@ -58,13 +58,13 @@ static const double twoRaisedTo32Reciprocal = 1. / twoRaisedTo32; | |||||
using namespace std; | using namespace std; | ||||
// class id. | |||||
// class id. | |||||
// {838FE50A-C1AB-4b77-B9B6-0A40788B53F3} | // {838FE50A-C1AB-4b77-B9B6-0A40788B53F3} | ||||
CLSID IID_ASIO_DRIVER = { 0x838fe50a, 0xc1ab, 0x4b77, { 0xb9, 0xb6, 0xa, 0x40, 0x78, 0x8b, 0x53, 0xf3 } }; | CLSID IID_ASIO_DRIVER = { 0x838fe50a, 0xc1ab, 0x4b77, { 0xb9, 0xb6, 0xa, 0x40, 0x78, 0x8b, 0x53, 0xf3 } }; | ||||
CFactoryTemplate g_Templates[1] = { | CFactoryTemplate g_Templates[1] = { | ||||
{L"ASIOJACK", &IID_ASIO_DRIVER, JackRouter::CreateInstance} | |||||
{L"ASIOJACK", &IID_ASIO_DRIVER, JackRouter::CreateInstance} | |||||
}; | }; | ||||
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); | int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); | ||||
@@ -183,7 +183,7 @@ JackRouter::JackRouter() : AsioDriver() | |||||
char dllName[512]; | char dllName[512]; | ||||
string confPath; | string confPath; | ||||
DWORD res = GetModuleFileName(handle, dllName, 512); | DWORD res = GetModuleFileName(handle, dllName, 512); | ||||
// Compute .ini file path | // Compute .ini file path | ||||
string fullPath = dllName; | string fullPath = dllName; | ||||
int lastPos = fullPath.find_last_of(PATH_SEP); | int lastPos = fullPath.find_last_of(PATH_SEP); | ||||
@@ -223,7 +223,7 @@ static bool GetEXEName(DWORD dwProcessID, char* name) | |||||
{ | { | ||||
DWORD aProcesses [1024], cbNeeded, cProcesses; | DWORD aProcesses [1024], cbNeeded, cProcesses; | ||||
unsigned int i; | unsigned int i; | ||||
// Enumerate all processes | // Enumerate all processes | ||||
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) | if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) | ||||
return false; | return false; | ||||
@@ -240,33 +240,33 @@ static bool GetEXEName(DWORD dwProcessID, char* name) | |||||
// Get a handle to the process | // Get a handle to the process | ||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | | HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | | ||||
PROCESS_VM_READ, FALSE, dwProcessID); | PROCESS_VM_READ, FALSE, dwProcessID); | ||||
// Get the process name | // Get the process name | ||||
if (NULL != hProcess) { | if (NULL != hProcess) { | ||||
HMODULE hMod; | HMODULE hMod; | ||||
DWORD cbNeeded; | DWORD cbNeeded; | ||||
if(EnumProcessModules(hProcess, &hMod, | |||||
if(EnumProcessModules(hProcess, &hMod, | |||||
sizeof(hMod), &cbNeeded)) { | sizeof(hMod), &cbNeeded)) { | ||||
//Get the name of the exe file | //Get the name of the exe file | ||||
GetModuleBaseName(hProcess, hMod, szEXEName, | |||||
GetModuleBaseName(hProcess, hMod, szEXEName, | |||||
sizeof(szEXEName)/sizeof(TCHAR)); | sizeof(szEXEName)/sizeof(TCHAR)); | ||||
int len = strlen((char*)szEXEName) - 4; // remove ".exe" | int len = strlen((char*)szEXEName) - 4; // remove ".exe" | ||||
strncpy(name, (char*)szEXEName, len); | |||||
strncpy(name, (char*)szEXEName, len); | |||||
name[len] = '\0'; | name[len] = '\0'; | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
} | |||||
} | |||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
//------------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------------ | ||||
static inline float ClipFloat(float sample) | |||||
static inline jack_default_audio_sample_t ClipFloat(jack_default_audio_sample_t sample) | |||||
{ | { | ||||
return (sample < -1.0f) ? -1.0f : (sample > 1.0f) ? 1.0f : sample; | |||||
return (sample < jack_default_audio_sample_t(-1.0)) ? jack_default_audio_sample_t(-1.0) : (sample > jack_default_audio_sample_t(1.0)) ? jack_default_audio_sample_t(1.0) : sample; | |||||
} | } | ||||
//------------------------------------------------------------------------------------------ | //------------------------------------------------------------------------------------------ | ||||
@@ -288,42 +288,42 @@ int JackRouter::process(jack_nframes_t nframes, void* arg) | |||||
{ | { | ||||
JackRouter* driver = (JackRouter*)arg; | JackRouter* driver = (JackRouter*)arg; | ||||
int i,j; | int i,j; | ||||
int pos = (driver->fToggle) ? 0 : driver->fBufferSize ; | |||||
for (i = 0; i < driver->fActiveInputs; i++) { | |||||
#ifdef LONG_SAMPLE | |||||
float* buffer = (float*)jack_port_get_buffer(driver->fInputPorts[i], nframes); | |||||
int pos = (driver->fToggle) ? 0 : driver->fBufferSize ; | |||||
for (i = 0; i < driver->fActiveInputs; i++) { | |||||
#ifdef LONG_SAMPLE | |||||
jack_default_audio_sample_t* buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(driver->fInputPorts[i], nframes); | |||||
long* in = driver->fInputBuffers[i] + pos; | long* in = driver->fInputBuffers[i] + pos; | ||||
for (j = 0; j < nframes; j++) { | for (j = 0; j < nframes; j++) { | ||||
in[j] = buffer[j] * float(0x7fffffff); | |||||
in[j] = buffer[j] * jack_default_audio_sample_t(0x7fffffff); | |||||
} | } | ||||
#else | #else | ||||
memcpy(driver->fInputBuffers[i] + pos, | memcpy(driver->fInputBuffers[i] + pos, | ||||
jack_port_get_buffer(driver->fInputPorts[i], nframes), | jack_port_get_buffer(driver->fInputPorts[i], nframes), | ||||
nframes * sizeof(float)); | |||||
nframes * sizeof(jack_default_audio_sample_t)); | |||||
#endif | #endif | ||||
} | |||||
} | |||||
driver->bufferSwitch(); | driver->bufferSwitch(); | ||||
for (i = 0; i < driver->fActiveOutputs; i++) { | for (i = 0; i < driver->fActiveOutputs; i++) { | ||||
#ifdef LONG_SAMPLE | #ifdef LONG_SAMPLE | ||||
float* buffer = (float*)jack_port_get_buffer(driver->fOutputPorts[i], nframes); | |||||
jack_default_audio_sample_t* buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(driver->fOutputPorts[i], nframes); | |||||
long* out = driver->fOutputBuffers[i] + pos; | long* out = driver->fOutputBuffers[i] + pos; | ||||
float gain = 1.f/float(0x7fffffff); | |||||
jack_default_audio_sample_t gain = jack_default_audio_sample_t(1)/jack_default_audio_sample_t(0x7fffffff); | |||||
for (j = 0; j < nframes; j++) { | for (j = 0; j < nframes; j++) { | ||||
buffer[j] = out[j] * gain; | buffer[j] = out[j] * gain; | ||||
} | } | ||||
#else | #else | ||||
memcpy(jack_port_get_buffer(driver->fOutputPorts[i], nframes), | memcpy(jack_port_get_buffer(driver->fOutputPorts[i], nframes), | ||||
driver->fOutputBuffers[i] + pos, | driver->fOutputBuffers[i] + pos, | ||||
nframes * sizeof(float)); | |||||
nframes * sizeof(jack_default_audio_sample_t)); | |||||
#endif | #endif | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -356,7 +356,7 @@ ASIOBool JackRouter::init(void* sysRef) | |||||
HANDLE win = (HANDLE)sysRef; | HANDLE win = (HANDLE)sysRef; | ||||
int my_pid = _getpid(); | int my_pid = _getpid(); | ||||
if (!GetEXEName(my_pid, name)) { // If getting the .exe name fails, takes a generic one. | if (!GetEXEName(my_pid, name)) { // If getting the .exe name fails, takes a generic one. | ||||
_snprintf(name, sizeof(name) - 1, "JackRouter_%d", my_pid); | _snprintf(name, sizeof(name) - 1, "JackRouter_%d", my_pid); | ||||
} | } | ||||
@@ -365,19 +365,19 @@ ASIOBool JackRouter::init(void* sysRef) | |||||
printf("Error: jack client still present...\n"); | printf("Error: jack client still present...\n"); | ||||
return true; | return true; | ||||
} | } | ||||
fClient = jack_client_open(name, JackNullOption, NULL); | fClient = jack_client_open(name, JackNullOption, NULL); | ||||
if (fClient == NULL) { | if (fClient == NULL) { | ||||
strcpy (fErrorMessage, "Open error: is jack server running?"); | strcpy (fErrorMessage, "Open error: is jack server running?"); | ||||
printf("Open error: is jack server running?\n"); | printf("Open error: is jack server running?\n"); | ||||
return false; | return false; | ||||
} | } | ||||
fBufferSize = jack_get_buffer_size(fClient); | fBufferSize = jack_get_buffer_size(fClient); | ||||
fSampleRate = jack_get_sample_rate(fClient); | fSampleRate = jack_get_sample_rate(fClient); | ||||
jack_set_process_callback(fClient, process, this); | jack_set_process_callback(fClient, process, this); | ||||
jack_on_shutdown(fClient, shutdown, this); | jack_on_shutdown(fClient, shutdown, this); | ||||
fInputLatency = fBufferSize; // typically | fInputLatency = fBufferSize; // typically | ||||
fOutputLatency = fBufferSize * 2; | fOutputLatency = fBufferSize * 2; | ||||
fMilliSeconds = (long)((double)(fBufferSize * 1000) / fSampleRate); | fMilliSeconds = (long)((double)(fBufferSize * 1000) / fSampleRate); | ||||
@@ -399,7 +399,7 @@ ASIOError JackRouter::start() | |||||
fToggle = 0; | fToggle = 0; | ||||
fStarted = true; | fStarted = true; | ||||
printf("Start ASIO Jack\n"); | printf("Start ASIO Jack\n"); | ||||
if (jack_activate(fClient) == 0) { | if (jack_activate(fClient) == 0) { | ||||
if (fFirstActivate) { | if (fFirstActivate) { | ||||
@@ -413,9 +413,9 @@ ASIOError JackRouter::start() | |||||
} else { | } else { | ||||
return ASE_NotPresent; | return ASE_NotPresent; | ||||
} | |||||
} | |||||
} | } | ||||
return ASE_NotPresent; | return ASE_NotPresent; | ||||
} | } | ||||
@@ -533,8 +533,8 @@ ASIOError JackRouter::getChannelInfo(ASIOChannelInfo *info) | |||||
char buf[32]; | char buf[32]; | ||||
if (info->isInput) { | if (info->isInput) { | ||||
for (i = 0; i < fActiveInputs; i++) { | |||||
if (fInMap[i] == info->channel) { | |||||
for (i = 0; i < fActiveInputs; i++) { | |||||
if (fInMap[i] == info->channel) { | |||||
info->isActive = ASIOTrue; | info->isActive = ASIOTrue; | ||||
//_snprintf(buf, sizeof(buf) - 1, "Jack::In%d ", info->channel); | //_snprintf(buf, sizeof(buf) - 1, "Jack::In%d ", info->channel); | ||||
//strcpy(info->name, buf); | //strcpy(info->name, buf); | ||||
@@ -545,7 +545,7 @@ ASIOError JackRouter::getChannelInfo(ASIOChannelInfo *info) | |||||
_snprintf(buf, sizeof(buf) - 1, "In%d ", info->channel); | _snprintf(buf, sizeof(buf) - 1, "In%d ", info->channel); | ||||
strcpy(info->name, buf); | strcpy(info->name, buf); | ||||
} else { | } else { | ||||
for (i = 0; i < fActiveOutputs; i++) { | |||||
for (i = 0; i < fActiveOutputs; i++) { | |||||
if (fOutMap[i] == info->channel) { //NOT USED !! | if (fOutMap[i] == info->channel) { //NOT USED !! | ||||
info->isActive = ASIOTrue; | info->isActive = ASIOTrue; | ||||
//_snprintf(buf, sizeof(buf) - 1, "Jack::Out%d ", info->channel); | //_snprintf(buf, sizeof(buf) - 1, "Jack::Out%d ", info->channel); | ||||
@@ -579,7 +579,7 @@ ASIOError JackRouter::createBuffers(ASIOBufferInfo *bufferInfos, long numChannel | |||||
#ifdef LONG_SAMPLE | #ifdef LONG_SAMPLE | ||||
fInputBuffers[fActiveInputs] = new long[fBufferSize * 2]; // double buffer | fInputBuffers[fActiveInputs] = new long[fBufferSize * 2]; // double buffer | ||||
#else | #else | ||||
fInputBuffers[fActiveInputs] = new float[fBufferSize * 2]; // double buffer | |||||
fInputBuffers[fActiveInputs] = new jack_default_audio_sample_t[fBufferSize * 2]; // double buffer | |||||
#endif | #endif | ||||
if (fInputBuffers[fActiveInputs]) { | if (fInputBuffers[fActiveInputs]) { | ||||
info->buffers[0] = fInputBuffers[fActiveInputs]; | info->buffers[0] = fInputBuffers[fActiveInputs]; | ||||
@@ -588,9 +588,9 @@ ASIOError JackRouter::createBuffers(ASIOBufferInfo *bufferInfos, long numChannel | |||||
info->buffers[0] = info->buffers[1] = 0; | info->buffers[0] = info->buffers[1] = 0; | ||||
notEnoughMem = true; | notEnoughMem = true; | ||||
} | } | ||||
_snprintf(buf, sizeof(buf) - 1, "in%d", fActiveInputs + 1); | _snprintf(buf, sizeof(buf) - 1, "in%d", fActiveInputs + 1); | ||||
fInputPorts[fActiveInputs] | |||||
fInputPorts[fActiveInputs] | |||||
= jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0); | = jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput,0); | ||||
if (fInputPorts[fActiveInputs] == NULL) | if (fInputPorts[fActiveInputs] == NULL) | ||||
goto error; | goto error; | ||||
@@ -601,17 +601,17 @@ error: | |||||
disposeBuffers(); | disposeBuffers(); | ||||
return ASE_InvalidParameter; | return ASE_InvalidParameter; | ||||
} | } | ||||
} else { // output | |||||
} else { // output | |||||
if (info->channelNum < 0 || info->channelNum >= kNumOutputs) | if (info->channelNum < 0 || info->channelNum >= kNumOutputs) | ||||
goto error; | goto error; | ||||
fOutMap[fActiveOutputs] = info->channelNum; | fOutMap[fActiveOutputs] = info->channelNum; | ||||
#ifdef LONG_SAMPLE | #ifdef LONG_SAMPLE | ||||
fOutputBuffers[fActiveOutputs] = new long[fBufferSize * 2]; // double buffer | fOutputBuffers[fActiveOutputs] = new long[fBufferSize * 2]; // double buffer | ||||
#else | #else | ||||
fOutputBuffers[fActiveOutputs] = new float[fBufferSize * 2]; // double buffer | |||||
fOutputBuffers[fActiveOutputs] = new jack_default_audio_sample_t[fBufferSize * 2]; // double buffer | |||||
#endif | #endif | ||||
if (fOutputBuffers[fActiveOutputs]) { | if (fOutputBuffers[fActiveOutputs]) { | ||||
info->buffers[0] = fOutputBuffers[fActiveOutputs]; | info->buffers[0] = fOutputBuffers[fActiveOutputs]; | ||||
info->buffers[1] = fOutputBuffers[fActiveOutputs] + fBufferSize; | info->buffers[1] = fOutputBuffers[fActiveOutputs] + fBufferSize; | ||||
@@ -619,9 +619,9 @@ error: | |||||
info->buffers[0] = info->buffers[1] = 0; | info->buffers[0] = info->buffers[1] = 0; | ||||
notEnoughMem = true; | notEnoughMem = true; | ||||
} | } | ||||
_snprintf(buf, sizeof(buf) - 1, "out%d", fActiveOutputs + 1); | _snprintf(buf, sizeof(buf) - 1, "out%d", fActiveOutputs + 1); | ||||
fOutputPorts[fActiveOutputs] | |||||
fOutputPorts[fActiveOutputs] | |||||
= jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput,0); | = jack_port_register(fClient, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput,0); | ||||
if (fOutputPorts[fActiveOutputs] == NULL) | if (fOutputPorts[fActiveOutputs] == NULL) | ||||
goto error; | goto error; | ||||
@@ -633,7 +633,7 @@ error: | |||||
return ASE_InvalidParameter; | return ASE_InvalidParameter; | ||||
} | } | ||||
} | } | ||||
} | |||||
} | |||||
if (notEnoughMem) { | if (notEnoughMem) { | ||||
disposeBuffers(); | disposeBuffers(); | ||||
@@ -653,9 +653,9 @@ error: | |||||
fAsioTime.timeCode.timeCodeSamples.lo = fAsioTime.timeCode.timeCodeSamples.hi = 0; | fAsioTime.timeCode.timeCodeSamples.lo = fAsioTime.timeCode.timeCodeSamples.hi = 0; | ||||
fAsioTime.timeCode.flags = kTcValid | kTcRunning ; | fAsioTime.timeCode.flags = kTcValid | kTcRunning ; | ||||
} else { | } else { | ||||
fTimeInfoMode = false; | |||||
fTimeInfoMode = false; | |||||
} | } | ||||
return ASE_OK; | return ASE_OK; | ||||
} | } | ||||
@@ -663,14 +663,14 @@ error: | |||||
ASIOError JackRouter::disposeBuffers() | ASIOError JackRouter::disposeBuffers() | ||||
{ | { | ||||
long i; | long i; | ||||
fCallbacks = 0; | fCallbacks = 0; | ||||
stop(); | stop(); | ||||
for (i = 0; i < fActiveInputs; i++) { | for (i = 0; i < fActiveInputs; i++) { | ||||
delete[] fInputBuffers[i]; | delete[] fInputBuffers[i]; | ||||
jack_port_unregister(fClient, fInputPorts[i]); | jack_port_unregister(fClient, fInputPorts[i]); | ||||
} | |||||
} | |||||
fActiveInputs = 0; | fActiveInputs = 0; | ||||
for (i = 0; i < fActiveOutputs; i++) { | for (i = 0; i < fActiveOutputs; i++) { | ||||
@@ -689,7 +689,7 @@ ASIOError JackRouter::controlPanel() | |||||
} | } | ||||
//--------------------------------------------------------------------------------------------- | //--------------------------------------------------------------------------------------------- | ||||
ASIOError JackRouter::future(long selector, void* opt) // !!! check properties | |||||
ASIOError JackRouter::future(long selector, void* opt) // !!! check properties | |||||
{ | { | ||||
ASIOTransportParameters* tp = (ASIOTransportParameters*)opt; | ASIOTransportParameters* tp = (ASIOTransportParameters*)opt; | ||||
switch (selector) | switch (selector) | ||||
@@ -804,7 +804,7 @@ void JackRouter::RestoreConnections() | |||||
void JackRouter::AutoConnect() | void JackRouter::AutoConnect() | ||||
{ | { | ||||
const char** ports; | const char** ports; | ||||
if ((ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput)) == NULL) { | if ((ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput)) == NULL) { | ||||
printf("Cannot find any physical capture ports\n"); | printf("Cannot find any physical capture ports\n"); | ||||
} else { | } else { | ||||
@@ -818,9 +818,9 @@ void JackRouter::AutoConnect() | |||||
} | } | ||||
} | } | ||||
} | } | ||||
jack_free(ports); | |||||
jack_free(ports); | |||||
} | } | ||||
if ((ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput)) == NULL) { | if ((ports = jack_get_ports(fClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput)) == NULL) { | ||||
printf("Cannot find any physical playback ports"); | printf("Cannot find any physical playback ports"); | ||||
} else { | } else { | ||||
@@ -834,7 +834,7 @@ void JackRouter::AutoConnect() | |||||
} | } | ||||
} | } | ||||
} | } | ||||
jack_free(ports); | |||||
jack_free(ports); | |||||
} | } | ||||
} | } | ||||
@@ -307,7 +307,7 @@ bool JackClientPipeThread::HandleRequest() | |||||
JackInternalClientLoadRequest req; | JackInternalClientLoadRequest req; | ||||
JackInternalClientLoadResult res; | JackInternalClientLoadResult res; | ||||
if (req.Read(fPipe) == 0) | if (req.Read(fPipe) == 0) | ||||
res.fResult = fServer->InternalClientLoad(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
res.fResult = fServer->InternalClientLoad1(req.fName, req.fDllName, req.fLoadInitName, req.fOptions, &res.fIntRefNum, req.fUUID, &res.fStatus); | |||||
res.Write(fPipe); | res.Write(fPipe); | ||||
break; | break; | ||||
} | } | ||||
@@ -1,20 +1,20 @@ | |||||
/* | /* | ||||
Copyright (C) 2004-2008 Grame | Copyright (C) 2004-2008 Grame | ||||
This program is free software; you can redistribute it and/or modify | 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 | 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 | the Free Software Foundation; either version 2.1 of the License, or | ||||
(at your option) any later version. | (at your option) any later version. | ||||
This program is distributed in the hope that it will be useful, | This program is distributed in the hope that it will be useful, | ||||
but WITHOUT ANY WARRANTY; without even the implied warranty of | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
GNU Lesser General Public License for more details. | GNU Lesser General Public License for more details. | ||||
You should have received a copy of the GNU Lesser General Public License | You should have received a copy of the GNU Lesser General Public License | ||||
along with this program; if not, write to the Free Software | along with this program; if not, write to the Free Software | ||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||||
*/ | */ | ||||
@@ -74,7 +74,7 @@ bool JackWinProcessSync::LockedTimedWait(long usec) | |||||
} | } | ||||
/* | /* | ||||
Code from CAGuard.cpp : does ot sees to work as expected.. | |||||
Code from APPLE CAGuard.cpp : does not seem to work as expected... | |||||
void JackWinProcessSync::Wait() | void JackWinProcessSync::Wait() | ||||
{ | { | ||||
@@ -35,7 +35,7 @@ namespace Jack | |||||
void* userData) | void* userData) | ||||
{ | { | ||||
JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData); | JackPortAudioAdapter* adapter = static_cast<JackPortAudioAdapter*>(userData); | ||||
adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, framesPerBuffer); | |||||
adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)outputBuffer, framesPerBuffer); | |||||
return paContinue; | return paContinue; | ||||
} | } | ||||
@@ -38,8 +38,8 @@ namespace Jack | |||||
void* userData) | void* userData) | ||||
{ | { | ||||
JackPortAudioDriver* driver = (JackPortAudioDriver*)userData; | JackPortAudioDriver* driver = (JackPortAudioDriver*)userData; | ||||
driver->fInputBuffer = (float**)inputBuffer; | |||||
driver->fOutputBuffer = (float**)outputBuffer; | |||||
driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer; | |||||
driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer; | |||||
// Setup threadded based log function | // Setup threadded based log function | ||||
set_threaded_log_function(); | set_threaded_log_function(); | ||||
driver->CycleTakeBeginTime(); | driver->CycleTakeBeginTime(); | ||||
@@ -49,14 +49,14 @@ namespace Jack | |||||
int JackPortAudioDriver::Read() | int JackPortAudioDriver::Read() | ||||
{ | { | ||||
for (int i = 0; i < fCaptureChannels; i++) | for (int i = 0; i < fCaptureChannels; i++) | ||||
memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(float) * fEngineControl->fBufferSize); | |||||
memcpy(GetInputBuffer(i), fInputBuffer[i], sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
return 0; | return 0; | ||||
} | } | ||||
int JackPortAudioDriver::Write() | int JackPortAudioDriver::Write() | ||||
{ | { | ||||
for (int i = 0; i < fPlaybackChannels; i++) | for (int i = 0; i < fPlaybackChannels; i++) | ||||
memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(float) * fEngineControl->fBufferSize); | |||||
memcpy(fOutputBuffer[i], GetOutputBuffer(i), sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -180,7 +180,9 @@ error: | |||||
int JackPortAudioDriver::Close() | int JackPortAudioDriver::Close() | ||||
{ | { | ||||
// Generic audio driver close | |||||
int res = JackAudioDriver::Close(); | int res = JackAudioDriver::Close(); | ||||
jack_log("JackPortAudioDriver::Close"); | jack_log("JackPortAudioDriver::Close"); | ||||
Pa_CloseStream(fStream); | Pa_CloseStream(fStream); | ||||
return res; | return res; | ||||
@@ -189,16 +191,25 @@ error: | |||||
int JackPortAudioDriver::Start() | int JackPortAudioDriver::Start() | ||||
{ | { | ||||
jack_log("JackPortAudioDriver::Start"); | jack_log("JackPortAudioDriver::Start"); | ||||
JackAudioDriver::Start(); | |||||
PaError err = Pa_StartStream(fStream); | |||||
return (err == paNoError) ? 0 : -1; | |||||
if (JackAudioDriver::Start() >= 0) { | |||||
PaError err = Pa_StartStream(fStream); | |||||
if (err == paNoError) { | |||||
return 0; | |||||
} | |||||
JackAudioDriver::Stop(); | |||||
} | |||||
return -1; | |||||
} | } | ||||
int JackPortAudioDriver::Stop() | int JackPortAudioDriver::Stop() | ||||
{ | { | ||||
jack_log("JackPortAudioDriver::Stop"); | jack_log("JackPortAudioDriver::Stop"); | ||||
PaError err = Pa_StopStream(fStream); | PaError err = Pa_StopStream(fStream); | ||||
return (err == paNoError) ? 0 : -1; | |||||
int res = (err == paNoError) ? 0 : -1; | |||||
if (JackAudioDriver::Stop() < 0) { | |||||
res = -1; | |||||
} | |||||
return res; | |||||
} | } | ||||
int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | int JackPortAudioDriver::SetBufferSize(jack_nframes_t buffer_size) | ||||
@@ -37,8 +37,8 @@ class JackPortAudioDriver : public JackAudioDriver | |||||
PortAudioDevices* fPaDevices; | PortAudioDevices* fPaDevices; | ||||
PaStream* fStream; | PaStream* fStream; | ||||
float** fInputBuffer; | |||||
float** fOutputBuffer; | |||||
jack_default_audio_sample_t** fInputBuffer; | |||||
jack_default_audio_sample_t** fOutputBuffer; | |||||
PaDeviceIndex fInputDevice; | PaDeviceIndex fInputDevice; | ||||
PaDeviceIndex fOutputDevice; | PaDeviceIndex fOutputDevice; | ||||
@@ -264,6 +264,9 @@ int JackWinMMEDriver::Close() | |||||
{ | { | ||||
jack_log("JackWinMMEDriver::Close"); | jack_log("JackWinMMEDriver::Close"); | ||||
// Generic midi driver close | |||||
int res = JackMidiDriver::Close(); | |||||
// Close input | // Close input | ||||
if (fMidiDestination) { | if (fMidiDestination) { | ||||
for (int i = 0; i < fRealCaptureChannels; i++) { | for (int i = 0; i < fRealCaptureChannels; i++) { | ||||
@@ -280,7 +283,7 @@ int JackWinMMEDriver::Close() | |||||
delete[] fMidiSource; | delete[] fMidiSource; | ||||
} | } | ||||
return 0; | |||||
return res; | |||||
} | } | ||||
int JackWinMMEDriver::Attach() | int JackWinMMEDriver::Attach() | ||||
@@ -129,23 +129,33 @@ def configure(conf): | |||||
conf.fatal('jackdbus was explicitly requested but cannot be built') | conf.fatal('jackdbus was explicitly requested but cannot be built') | ||||
conf.sub_config('example-clients') | conf.sub_config('example-clients') | ||||
if conf.check_cfg(package='celt', atleast_version='0.8.0', args='--cflags --libs'): | |||||
if conf.check_cfg(package='celt', atleast_version='0.11.0', args='--cflags --libs'): | |||||
conf.define('HAVE_CELT', 1) | conf.define('HAVE_CELT', 1) | ||||
conf.define('HAVE_CELT_API_0_11', 1) | |||||
conf.define('HAVE_CELT_API_0_8', 0) | |||||
conf.define('HAVE_CELT_API_0_7', 0) | |||||
conf.define('HAVE_CELT_API_0_5', 0) | |||||
elif conf.check_cfg(package='celt', atleast_version='0.8.0', args='--cflags --libs'): | |||||
conf.define('HAVE_CELT', 1) | |||||
conf.define('HAVE_CELT_API_0_11', 0) | |||||
conf.define('HAVE_CELT_API_0_8', 1) | conf.define('HAVE_CELT_API_0_8', 1) | ||||
conf.define('HAVE_CELT_API_0_7', 0) | conf.define('HAVE_CELT_API_0_7', 0) | ||||
conf.define('HAVE_CELT_API_0_5', 0) | conf.define('HAVE_CELT_API_0_5', 0) | ||||
elif conf.check_cfg(package='celt', atleast_version='0.7.0', args='--cflags --libs'): | elif conf.check_cfg(package='celt', atleast_version='0.7.0', args='--cflags --libs'): | ||||
conf.define('HAVE_CELT', 1) | conf.define('HAVE_CELT', 1) | ||||
conf.define('HAVE_CELT_API_0_11', 0) | |||||
conf.define('HAVE_CELT_API_0_8', 0) | conf.define('HAVE_CELT_API_0_8', 0) | ||||
conf.define('HAVE_CELT_API_0_7', 1) | conf.define('HAVE_CELT_API_0_7', 1) | ||||
conf.define('HAVE_CELT_API_0_5', 0) | conf.define('HAVE_CELT_API_0_5', 0) | ||||
elif conf.check_cfg(package='celt', atleast_version='0.5.0', args='--cflags --libs', required=True): | elif conf.check_cfg(package='celt', atleast_version='0.5.0', args='--cflags --libs', required=True): | ||||
conf.define('HAVE_CELT', 1) | conf.define('HAVE_CELT', 1) | ||||
conf.define('HAVE_CELT_API_0_11', 0) | |||||
conf.define('HAVE_CELT_API_0_8', 0) | conf.define('HAVE_CELT_API_0_8', 0) | ||||
conf.define('HAVE_CELT_API_0_7', 0) | conf.define('HAVE_CELT_API_0_7', 0) | ||||
conf.define('HAVE_CELT_API_0_5', 1) | conf.define('HAVE_CELT_API_0_5', 1) | ||||
else: | else: | ||||
conf.define('HAVE_CELT', 0) | conf.define('HAVE_CELT', 0) | ||||
conf.define('HAVE_CELT_API_0_11', 0) | |||||
conf.define('HAVE_CELT_API_0_8', 0) | conf.define('HAVE_CELT_API_0_8', 0) | ||||
conf.define('HAVE_CELT_API_0_7', 0) | conf.define('HAVE_CELT_API_0_7', 0) | ||||
conf.define('HAVE_CELT_API_0_5', 0) | conf.define('HAVE_CELT_API_0_5', 0) | ||||