From 32987ca1d2c885250e8f3b74fad368fe83e88c9f Mon Sep 17 00:00:00 2001 From: sletz Date: Wed, 11 Feb 2009 12:31:20 +0000 Subject: [PATCH] Merge Solaris branch back on trunk. git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3306 0c269be4-1314-0410-8aa9-9f06e86f4224 --- ChangeLog | 75 +- common/JackAPI.cpp | 12 + common/JackAudioAdapterFactory.cpp | 11 +- common/JackAudioDriver.h | 9 +- common/JackAudioPort.cpp | 6 +- common/JackClient.cpp | 2 +- common/JackConstants.h | 16 +- common/JackControlAPI.cpp | 6 +- common/JackEngine.cpp | 11 + common/JackEngine.h | 1 + common/JackEngineControl.cpp | 5 +- common/JackEngineControl.h | 10 + common/JackEngineProfiling.cpp | 330 ++++++ ...ckEngineTiming.h => JackEngineProfiling.h} | 43 +- common/JackEngineTiming.cpp | 71 -- common/JackLockedEngine.h | 8 +- common/JackNetManager.cpp | 3 +- common/JackProfiler.cpp | 291 +++++ common/JackProfiler.h | 80 ++ common/JackServer.cpp | 1 + common/JackShmMem.cpp | 14 +- common/JackShmMem.h | 3 + common/JackTools.cpp | 3 +- common/jack/jslist.h | 5 +- common/jack/systemdeps.h | 4 +- {linux/alsa => common}/memops.c | 89 +- {linux/alsa => common}/memops.h | 6 +- common/shm.h | 4 + common/wscript | 70 +- example-clients/cpu_load.c | 92 ++ example-clients/simple_client.c | 7 +- example-clients/wscript | 10 +- linux/wscript | 2 +- macosx/JackMachTime.c | 2 +- macosx/Jackdmp.xcodeproj/project.pbxproj | 154 +-- posix/JackCompilerDeps_os.h | 16 +- posix/JackFifo.cpp | 13 +- posix/JackNetUnixSocket.cpp | 111 ++ posix/JackNetUnixSocket.h | 5 + posix/JackSocket.cpp | 118 +- posix/JackSocket.h | 5 +- posix/JackSocketServerChannel.cpp | 7 +- solaris/JackAtomic_os.h | 32 + solaris/JackPlatformPlug_os.h | 80 ++ solaris/JackSolarisTime.c | 37 + solaris/oss/JackOSSAdapter.cpp | 766 +++++++++++++ solaris/oss/JackOSSAdapter.h | 123 ++ solaris/oss/JackOSSDriver.cpp | 1010 +++++++++++++++++ solaris/oss/JackOSSDriver.h | 126 ++ solaris/wscript | 34 + svnversion_regenerate.sh | 2 +- tests/wscript | 10 +- windows/portaudio/JackPortAudioDriver.cpp | 30 +- wscript | 47 +- 54 files changed, 3750 insertions(+), 278 deletions(-) create mode 100644 common/JackEngineProfiling.cpp rename common/{JackEngineTiming.h => JackEngineProfiling.h} (61%) delete mode 100644 common/JackEngineTiming.cpp create mode 100644 common/JackProfiler.cpp create mode 100644 common/JackProfiler.h rename {linux/alsa => common}/memops.c (89%) rename {linux/alsa => common}/memops.h (99%) create mode 100644 example-clients/cpu_load.c create mode 100644 solaris/JackAtomic_os.h create mode 100644 solaris/JackPlatformPlug_os.h create mode 100644 solaris/JackSolarisTime.c create mode 100644 solaris/oss/JackOSSAdapter.cpp create mode 100644 solaris/oss/JackOSSAdapter.h create mode 100644 solaris/oss/JackOSSDriver.cpp create mode 100644 solaris/oss/JackOSSDriver.h create mode 100644 solaris/wscript diff --git a/ChangeLog b/ChangeLog index f2f15a4a..1b861382 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,10 @@ Michael Voigt 2009-02-11 Stephane Letz + * Merge Solaris branch back on trunk. + +2009-02-10 Stephane Letz + * Add a resample quality parameter in netadapter. 2009-02-09 Stephane Letz @@ -76,6 +80,14 @@ Michael Voigt * Cleanup server starting code for clients directly linked with libjackserver.so. +2009-01-09 Stephane Letz + + * JackProfiler scan already running clients (so can now be added anytime in the graph). + +2009-01-09 Stephane Letz + + * New JackProfiler class for real-time server monitoring. + 2009-01-07 Stephane Letz * Use up to BUFFER_SIZE_MAX frames in midi ports, fix for ticket #117. @@ -88,6 +100,8 @@ Michael Voigt 2008-12-18 Stephane Letz * For ALSA driver, synchronize with latest jack1 memops functions. + * Use memops functions in JackOSSDriver. + * Use memops functions in JackOSSAdapter. 2008-12-17 Stephane Letz @@ -95,15 +109,37 @@ Michael Voigt 2008-12-16 Stephane Letz + * Fix JackOSSDriver::SetBufferSize (was crashing when restoring old size), fix ticket #111. + * Force memory page in of profiling array in JackOSSDriver::Open. + * Cleanup profiling code. * Client and library global context cleanup in case of incorrect shutdown handling (that is applications not correctly closing client after server has shutdown). +2008-12-08 Stephane Letz + + * Forbid JackOSSDriver to run in "aynchronous" mode, correct DSP CPU computation. + +2008-12-04 Stephane Letz + + * More profiling in JackOSSDriver: sample conversion duration is measured. + +2008-12-02 Stephane Letz + + * Optimize JackOSSDriver: no samples conversion if ports are not connected. + +2008-12-01 Stephane Letz + + * Force preload of memory table in JackEngineProfiling. + 2008-11-27 Stephane Letz + * Add timing profiling code in JackOSSDriver. * Report ringbuffer.c fixes from jack1. 2008-11-21 Stephane Letz + * Report ringbuffer.c fixes from jack1. * Better isolation of server and clients system resources to allow starting the server in several user account at the same time. + * Correct ressource cleanup in case of driver open failure. 2008-11-19 Stephane Letz @@ -119,12 +155,13 @@ Michael Voigt * Fix jackctl_server_unload_internal. 2008-10-30 Stephane Letz - - * Fix Midi port initialization in JackNetDriver. - * Correct JackClient::ShutDown. + * Correct JackClient::ShutDown. + * TimeOut management in JackNetUnixSocket on Solaris. + 2008-10-23 Stephane Letz + * In JackOSSDriver, vmix mode is used by default, exclusif (O_EXCL) mode can be selected with -e option. * Fix a crash in JackEngine::Close when backend cannot be loaded. * Tim Blechmann optimization patch. * Backport of latest Paul alsa_seqmidi changes. @@ -147,6 +184,38 @@ Michael Voigt * Checking for libsamplerate in waf, fix ticket #89." * Header cleanup, add --clients and --ports options in configure. +2008-09-22 Stephane Letz + + * Socket time out implementation on Solaris. + * Fix a conflict with Audio Hijack in JackCoreAudioDriver. + +2008-10-10 Stephane Letz + + * Improve OSS backend : SNDCTL_DSP_SETFRAGMENT must be done before, use of AFMT_S16_LE kind of values. + +2008-10-09 Stephane Letz + + * First version of OSS backend. + * Use a mutex to make jack_client_open/jack_client_close thread safe, remove use of jack_init/jack_uninit. + +2008-10-08 Stephane Letz + + * Fix a SMP related bug introduced in rev 2957 : remove the __SMP__ flag and define LOCK for SMP in all cases. + +2008-10-03 Stephane Letz + + * Add engine profiling tools. + +2008-10-02 Stephane Letz + + * Correct file permission for jack-shm-registry POSIX shared memory segment. + * Checking for libsamplerate in waf, fix ticket #89." + * Header cleanup, add --clients and --ports options in configure. + +2008-10-01 Stephane Letz + + * First Solaris version. + 2008-09-22 Stephane Letz * Cleanup jack_port_id_t/jack_port_t mess, should work again on 64 bits machines." diff --git a/common/JackAPI.cpp b/common/JackAPI.cpp index 9224da7c..02b8ff8d 100644 --- a/common/JackAPI.cpp +++ b/common/JackAPI.cpp @@ -1098,7 +1098,11 @@ EXPORT jack_port_t* jack_port_register(jack_client_t* ext_client, const char* po jack_error("jack_port_register called with a NULL port name or a NULL port_type"); return NULL; } else { +#if defined(__x86_64__) || defined(__ppc64__) + return (jack_port_t *)((uint64_t)client->PortRegister(port_name, port_type, flags, buffer_size)); +#else return (jack_port_t *)client->PortRegister(port_name, port_type, flags, buffer_size); +#endif } } @@ -1349,7 +1353,11 @@ EXPORT jack_port_t* jack_port_by_name(jack_client_t* ext_client, const char* por if (!manager) return NULL; int res = manager->GetPort(portname); // returns a port index at least > 1 +#if defined(__x86_64__) || defined(__ppc64__) + return (res == NO_PORT) ? NULL : (jack_port_t*)((uint64_t)res); +#else return (res == NO_PORT) ? NULL : (jack_port_t*)res; +#endif } } @@ -1359,7 +1367,11 @@ EXPORT jack_port_t* jack_port_by_id(jack_client_t* ext_client, jack_port_id_t id JackLibGlobals::CheckContext(); #endif /* jack_port_t* type is actually the port index */ +#if defined(__x86_64__) || defined(__ppc64__) + return (jack_port_t*)((uint64_t)id); +#else return (jack_port_t*)id; +#endif } EXPORT int jack_engine_takeover_timebase(jack_client_t* ext_client) diff --git a/common/JackAudioAdapterFactory.cpp b/common/JackAudioAdapterFactory.cpp index 8c3e8423..14266854 100644 --- a/common/JackAudioAdapterFactory.cpp +++ b/common/JackAudioAdapterFactory.cpp @@ -23,8 +23,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #include -#include "driver_interface.h" - #ifdef __linux__ #include "JackAlsaAdapter.h" #endif @@ -37,6 +35,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include "JackPortAudioAdapter.h" #endif +#if defined(__sun__) || defined(sun) +#include "JackOSSAdapter.h" +#endif + #ifdef __cplusplus extern "C" { @@ -65,6 +67,11 @@ extern "C" #ifdef __APPLE__ adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackCoreAudioAdapter(buffer_size, sample_rate, params)); #endif + + #if defined(__sun__) || defined(sun) + adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackOSSAdapter(buffer_size, sample_rate, params)); + #endif + assert(adapter); if (adapter->Open() == 0) diff --git a/common/JackAudioDriver.h b/common/JackAudioDriver.h index 568732e4..93d6830d 100644 --- a/common/JackAudioDriver.h +++ b/common/JackAudioDriver.h @@ -33,16 +33,15 @@ namespace Jack class SERVER_EXPORT JackAudioDriver : public JackDriver { - private: + protected: - int ProcessAsync(); - int ProcessSync(); void ProcessGraphAsync(); void ProcessGraphSync(); void WaitUntilNextCycle(); - protected: - + virtual int ProcessAsync(); + virtual int ProcessSync(); + int fCaptureChannels; int fPlaybackChannels; diff --git a/common/JackAudioPort.cpp b/common/JackAudioPort.cpp index 765c3c4e..20cf1e8c 100644 --- a/common/JackAudioPort.cpp +++ b/common/JackAudioPort.cpp @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #if defined (__APPLE__) #include -#elif defined (__SSE__) +#elif defined (__SSE__) && !defined (__sun__) #include #endif @@ -46,7 +46,7 @@ static inline void MixAudioBuffer(float* mixbuffer, float* buffer, jack_nframes_ frames = frames % 4; while (frames_group > 0) { -#ifdef __SSE__ +#if defined (__SSE__) && !defined (__sun__) __m128 vec = _mm_add_ps(_mm_load_ps(mixbuffer), _mm_load_ps(buffer)); _mm_store_ps(mixbuffer, vec); @@ -97,7 +97,7 @@ static void AudioBufferMixdown(void* mixbuffer, void** src_buffers, int src_coun void* buffer; // Copy first buffer -#ifdef __SSE__ +#if defined (__SSE__) && !defined (__sun__) jack_nframes_t frames_group = nframes / 4; jack_nframes_t remaining_frames = nframes % 4; diff --git a/common/JackClient.cpp b/common/JackClient.cpp index bf3be7e3..60a1abd1 100644 --- a/common/JackClient.cpp +++ b/common/JackClient.cpp @@ -362,7 +362,7 @@ bool JackClient::Execute() if (GetEngineControl()->fRealTime) set_threaded_log_function(); - + if (fThreadFun) { // Execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished) WaitSync(); diff --git a/common/JackConstants.h b/common/JackConstants.h index 7bf66ac8..9ceaa0b4 100644 --- a/common/JackConstants.h +++ b/common/JackConstants.h @@ -57,17 +57,27 @@ #ifdef WIN32 #define jack_server_dir "server" #define jack_client_dir "client" -#define ADDON_DIR "jack" -#elif __APPLE__ +#define ADDON_DIR "jackmp" +#endif + +#ifdef __APPLE__ #define jack_server_dir "/tmp" #define jack_client_dir "/tmp" #define JACK_DEFAULT_DRIVER "coreaudio" -#else +#endif + +#ifdef __linux__ #define jack_server_dir "/dev/shm" #define jack_client_dir "/dev/shm" #define JACK_DEFAULT_DRIVER "alsa" #endif +#if defined(__sun__) || defined(sun) +#define jack_server_dir "/tmp" +#define jack_client_dir "/tmp" +#define JACK_DEFAULT_DRIVER "oss" +#endif + #define jack_server_entry "jackdmp_entry" #define jack_client_entry "jack_client" diff --git a/common/JackControlAPI.cpp b/common/JackControlAPI.cpp index 92e85f03..7fd71a0d 100644 --- a/common/JackControlAPI.cpp +++ b/common/JackControlAPI.cpp @@ -21,7 +21,6 @@ */ #ifndef WIN32 -#include #include #include #include @@ -42,6 +41,7 @@ #include "JackTools.h" #include "JackControlAPI.h" #include "JackLockedEngine.h" +#include "JackConstants.h" using namespace Jack; @@ -561,7 +561,11 @@ jackctl_wait_signals(sigset_t signals) bool waiting = true; while (waiting) { + #if defined(sun) && !defined(__sun__) // SUN compiler only, to check + sigwait(&signals); + #else sigwait(&signals, &sig); + #endif fprintf(stderr, "jack main caught signal %d\n", sig); switch (sig) { diff --git a/common/JackEngine.cpp b/common/JackEngine.cpp index 80a30aa9..5a098214 100644 --- a/common/JackEngine.cpp +++ b/common/JackEngine.cpp @@ -467,6 +467,17 @@ int JackEngine::GetClientPID(const char* name) return 0; } +int JackEngine::GetClientRefNum(const char* name) +{ + for (int i = 0; i < CLIENT_NUM; i++) { + JackClientInterface* client = fClientTable[i]; + if (client && (strcmp(client->GetClientControl()->fName, name) == 0)) + return client->GetClientControl()->fRefNum; + } + + return -1; +} + // Used for external clients int JackEngine::ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager) { diff --git a/common/JackEngine.h b/common/JackEngine.h index ac7c964a..9ec65124 100644 --- a/common/JackEngine.h +++ b/common/JackEngine.h @@ -91,6 +91,7 @@ class SERVER_EXPORT JackEngine int ClientDeactivate(int refnum); int GetClientPID(const char* name); + int GetClientRefNum(const char* name); // Internal client management int GetInternalClientName(int int_ref, char* name_res); diff --git a/common/JackEngineControl.cpp b/common/JackEngineControl.cpp index 7a2f03ce..b75dcf25 100644 --- a/common/JackEngineControl.cpp +++ b/common/JackEngineControl.cpp @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. namespace Jack { -static inline _jack_time_t JACK_MAX(_jack_time_t a, _jack_time_t b) +static inline jack_time_t JACK_MAX(jack_time_t a, jack_time_t b) { return (a < b) ? b : a; } @@ -46,6 +46,9 @@ void JackEngineControl::CycleBegin(JackClientInterface** table, { fTransport.CycleBegin(fSampleRate, cur_cycle_begin); CalcCPULoad(table, manager, cur_cycle_begin, prev_cycle_end); +#ifdef JACK_MONITOR + fProfiler.Profile(table, manager, fPeriodUsecs, cur_cycle_begin, prev_cycle_end); +#endif } void JackEngineControl::CycleEnd(JackClientInterface** table) diff --git a/common/JackEngineControl.h b/common/JackEngineControl.h index d1f98182..e8d6c8e5 100644 --- a/common/JackEngineControl.h +++ b/common/JackEngineControl.h @@ -24,9 +24,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "JackShmMem.h" #include "JackFrameTimer.h" #include "JackTransportEngine.h" +#include "JackConstants.h" #include "types.h" #include +#ifdef JACK_MONITOR +#include "JackEngineProfiling.h" +#endif + namespace Jack { @@ -78,6 +83,10 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem // Timer JackFrameTimer fFrameTimer; + +#ifdef JACK_MONITOR + JackEngineProfiling fProfiler; +#endif JackEngineControl(bool sync, bool temporary, long timeout, bool rt, long priority, bool verbose, const char* server_name) { @@ -105,6 +114,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem fMaxDelayedUsecs = 0.f; fXrunDelayedUsecs = 0.f; } + ~JackEngineControl() {} diff --git a/common/JackEngineProfiling.cpp b/common/JackEngineProfiling.cpp new file mode 100644 index 00000000..f9f29727 --- /dev/null +++ b/common/JackEngineProfiling.cpp @@ -0,0 +1,330 @@ +/* +Copyright (C) 2008 Grame & RTL + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "JackEngineProfiling.h" +#include "JackGraphManager.h" +#include "JackClientControl.h" +#include "JackClientInterface.h" +#include "JackTime.h" + +namespace Jack +{ + +JackEngineProfiling::JackEngineProfiling():fAudioCycle(0) +{ + jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024)); + + // Force memory page in + memset(fProfileTable, 0, sizeof(fProfileTable)); +} + +JackEngineProfiling::~JackEngineProfiling() +{ + // Window monitoring + int max_client = 0; + char buffer[1024]; + char* nameTable[CLIENT_NUM]; + FILE* file = fopen("JackEngineProfiling.log", "w"); + + jack_info("Write server and clients timing data..."); + + if (file == NULL) { + jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file"); + } else { + + for (int i = 2; i < TIME_POINTS; i++) { + bool header = true; + bool printed = false; + int count = 0; + for (int j = REAL_REFNUM; j < CLIENT_NUM; j++) { + if (fProfileTable[i].fClientTable[j].fRefNum > 0) { + long d1 = long(fProfileTable[i - 1].fCurCycleBegin - fProfileTable[i - 2].fCurCycleBegin); + long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin); + if (d1 > 0 && fProfileTable[i].fClientTable[j].fStatus != NotTriggered) { // Valid cycle + count++; + nameTable[count] = fNameTable[fProfileTable[i].fClientTable[j].fRefNum]; + + // driver delta and end cycle + if (header) { + fprintf(file, "%ld \t %ld \t", d1, d2); + header = false; + } + long d5 = long(fProfileTable[i].fClientTable[j].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin); + long d6 = long(fProfileTable[i].fClientTable[j].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin); + long d7 = long(fProfileTable[i].fClientTable[j].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin); + + // ref, signal, start, end, scheduling, duration, status + fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t", + fProfileTable[i].fClientTable[j].fRefNum, + ((d5 > 0) ? d5 : 0), + ((d6 > 0) ? d6 : 0), + ((d7 > 0) ? d7 : 0), + ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0), + ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0), + fProfileTable[i].fClientTable[j].fStatus); + printed = true; + } + } + max_client = (count > max_client) ? count : max_client; + } + if (printed) { + fprintf(file, "\n"); + } else if (fProfileTable[i].fAudioCycle > 0) { // Driver timing only + long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin); + long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin); + if (d1 > 0) { // Valid cycle + fprintf(file, "%ld \t %ld \n", d1, d2); + } + } + } + fclose(file); + } + + // Driver period + file = fopen("Timing1.plot", "w"); + + if (file == NULL) { + jack_error("JackEngineProfiling::Save cannot open Timing1.log file"); + } else { + + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Audio driver timing\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n"); + + fprintf(file, "set output 'Timing1.pdf\n"); + fprintf(file, "set terminal pdf\n"); + + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Audio driver timing\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot \"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines \n"); + + fclose(file); + } + + // Driver end date + file = fopen("Timing2.plot", "w"); + + if (file == NULL) { + jack_error("JackEngineProfiling::Save cannot open Timing2.log file"); + } else { + + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Driver end date\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n"); + + fprintf(file, "set output 'Timing2.pdf\n"); + fprintf(file, "set terminal pdf\n"); + + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Driver end date\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot \"JackEngineProfiling.log\" using 2 title \"Driver end date\" with lines \n"); + + fclose(file); + } + + // Clients end date + if (max_client > 0) { + file = fopen("Timing3.plot", "w"); + if (file == NULL) { + jack_error("JackEngineProfiling::Save cannot open Timing3.log file"); + } else { + + fprintf(file, "set multiplot\n"); + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Clients end date\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + + fprintf(file, "plot "); + for (int i = 0; i < max_client; i++) { + if (i == 0) { + if ((i + 1) == max_client) { + sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", + ((i + 1) * 7) - 1 , nameTable[(i + 1)]); + } else { + sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", + ((i + 1) * 7) - 1 , nameTable[(i + 1)]); + } + } else if ((i + 1) == max_client) { // Last client + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]); + } else { + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]); + } + fprintf(file, buffer); + } + + fprintf(file, "\n unset multiplot\n"); + fprintf(file, "set output 'Timing3.pdf\n"); + fprintf(file, "set terminal pdf\n"); + + fprintf(file, "set multiplot\n"); + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Clients end date\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot "); + for (int i = 0; i < max_client; i++) { + if (i == 0) { + if ((i + 1) == max_client) { + sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", + ((i + 1) * 7) - 1 , nameTable[(i + 1)]); + } else { + sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", + ((i + 1) * 7) - 1 , nameTable[(i + 1)]); + } + } else if ((i + 1) == max_client) { // Last client + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]); + } else { + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]); + } + fprintf(file, buffer); + } + fclose(file); + } + } + + // Clients scheduling + if (max_client > 0) { + file = fopen("Timing4.plot", "w"); + + if (file == NULL) { + jack_error("JackEngineProfiling::Save cannot open Timing4.log file"); + } else { + + fprintf(file, "set multiplot\n"); + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Clients scheduling latency\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot "); + for (int i = 0; i < max_client; i++) { + if ((i + 1) == max_client) // Last client + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]); + else + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]); + fprintf(file, buffer); + } + + fprintf(file, "\n unset multiplot\n"); + fprintf(file, "set output 'Timing4.pdf\n"); + fprintf(file, "set terminal pdf\n"); + + fprintf(file, "set multiplot\n"); + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Clients scheduling latency\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot "); + for (int i = 0; i < max_client; i++) { + if ((i + 1) == max_client) // Last client + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]); + else + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]); + fprintf(file, buffer); + } + fclose(file); + } + } + + // Clients duration + if (max_client > 0) { + file = fopen("Timing5.plot", "w"); + + if (file == NULL) { + jack_error("JackEngineProfiling::Save cannot open Timing5.log file"); + } else { + + fprintf(file, "set multiplot\n"); + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Clients duration\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot "); + for (int i = 0; i < max_client; i++) { + if ((i + 1) == max_client) // Last client + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]); + else + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]); + fprintf(file, buffer); + } + + fprintf(file, "\n unset multiplot\n"); + fprintf(file, "set output 'Timing5.pdf\n"); + fprintf(file, "set terminal pdf\n"); + + fprintf(file, "set multiplot\n"); + fprintf(file, "set grid\n"); + fprintf(file, "set title \"Clients duration\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot "); + for (int i = 0; i < max_client; i++) { + if ((i + 1) == max_client) // Last client + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]); + else + sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]); + fprintf(file, buffer); + } + fclose(file); + } + } +} + +void JackEngineProfiling::Profile(JackClientInterface** table, + JackGraphManager* manager, + jack_time_t period_usecs, + jack_time_t cur_cycle_begin, + jack_time_t prev_cycle_end) +{ + fAudioCycle = (fAudioCycle + 1) % TIME_POINTS; + + // Keeps cycle data + fProfileTable[fAudioCycle].fPeriodUsecs = period_usecs; + fProfileTable[fAudioCycle].fCurCycleBegin = cur_cycle_begin; + fProfileTable[fAudioCycle].fPrevCycleEnd = prev_cycle_end; + fProfileTable[fAudioCycle].fAudioCycle = fAudioCycle; + + for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { + JackClientInterface* client = table[i]; + JackClientTiming* timing = manager->GetClientTiming(i); + if (client && client->GetClientControl()->fActive) { + strcpy(fNameTable[i], client->GetClientControl()->fName); + fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i; + fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt; + fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt; + fProfileTable[fAudioCycle].fClientTable[i].fFinishedAt = timing->fFinishedAt; + fProfileTable[fAudioCycle].fClientTable[i].fStatus = timing->fStatus; + } + } +} + +JackTimingMeasure* JackEngineProfiling::GetCurMeasure() +{ + return &fProfileTable[fAudioCycle]; +} + +} // end of namespace diff --git a/common/JackEngineTiming.h b/common/JackEngineProfiling.h similarity index 61% rename from common/JackEngineTiming.h rename to common/JackEngineProfiling.h index 5c0a9b18..43888e76 100644 --- a/common/JackEngineTiming.h +++ b/common/JackEngineProfiling.h @@ -1,6 +1,5 @@ /* -Copyright (C) 2003 Paul Davis -Copyright (C) 2004-2008 Grame +Copyright (C) 2008 Grame & RTL This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -18,17 +17,20 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef __JackEngineTiming__ -#define __JackEngineTiming__ +#ifndef __JackEngineProfiling__ +#define __JackEngineProfiling__ #include "types.h" #include "JackTypes.h" #include "JackConstants.h" +#include "JackShmMem.h" namespace Jack { -#define TIME_POINTS 1000 +#define TIME_POINTS 250000 +#define FAILURE_TIME_POINTS 10000 +#define FAILURE_WINDOW 10 /*! \brief Timing stucture for a client. @@ -50,36 +52,41 @@ struct JackTimingMeasureClient struct JackTimingMeasure { unsigned int fAudioCycle; - jack_time_t fEngineTime; + jack_time_t fPeriodUsecs; + jack_time_t fCurCycleBegin; + jack_time_t fPrevCycleEnd; JackTimingMeasureClient fClientTable[CLIENT_NUM]; }; /*! -\brief Client timing. +\brief Client timing monitoring. */ class JackClientInterface; class JackGraphManager; -class JackEngineTiming +class SERVER_EXPORT JackEngineProfiling { private: - JackTimingMeasure fMeasure[TIME_POINTS]; + JackTimingMeasure fProfileTable[TIME_POINTS]; + char fNameTable[CLIENT_NUM][JACK_CLIENT_NAME_SIZE + 1]; unsigned int fAudioCycle; - jack_time_t fPrevCycleTime; - jack_time_t fCurCycleTime; - + public: - JackEngineTiming():fAudioCycle(0),fPrevCycleTime(0),fCurCycleTime(0) - {} - ~JackEngineTiming() - {} + JackEngineProfiling(); + ~JackEngineProfiling(); + + void Profile(JackClientInterface** table, + JackGraphManager* manager, + jack_time_t period_usecs, + jack_time_t cur_cycle_begin, + jack_time_t prev_cycle_end); + + JackTimingMeasure* GetCurMeasure(); - void GetTimeMeasure(JackClientInterface** table, JackGraphManager* manager, jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end); - void ClearTimeMeasures(); }; } // end of namespace diff --git a/common/JackEngineTiming.cpp b/common/JackEngineTiming.cpp deleted file mode 100644 index 12c74e93..00000000 --- a/common/JackEngineTiming.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* -Copyright (C) 2003 Paul Davis -Copyright (C) 2004-2008 Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "JackEngineTiming.h" -#include "JackGraphManager.h" -#include "JackClientControl.h" -#include "JackClientInterface.h" -#include "JackTime.h" - -namespace Jack -{ - -void JackEngineTiming::GetTimeMeasure(JackClientInterface** table, - JackGraphManager* manager, - jack_time_t cur_cycle_begin, - jack_time_t prev_cycle_end) -{ - int pos = (++fAudioCycle) % TIME_POINTS; - - fPrevCycleTime = fCurCycleTime; - fCurCycleTime = cur_cycle_begin; - - if (fPrevCycleTime > 0) { - fMeasure[pos].fEngineTime = fPrevCycleTime; - fMeasure[pos].fAudioCycle = fAudioCycle; - - for (int i = 0; i < CLIENT_NUM; i++) { - JackClientInterface* client = table[i]; - JackClientTiming* timing = manager->GetClientTiming(i); - if (client && client->GetClientControl()->fActive) { - fMeasure[pos].fClientTable[i].fRefNum = i; - fMeasure[pos].fClientTable[i].fSignaledAt = timing->fSignaledAt; - fMeasure[pos].fClientTable[i].fAwakeAt = timing->fAwakeAt; - fMeasure[pos].fClientTable[i].fFinishedAt = timing->fFinishedAt; - fMeasure[pos].fClientTable[i].fStatus = timing->fStatus; - } - } - } -} - -void JackEngineTiming::ClearTimeMeasures() -{ - for (int i = 0; i < TIME_POINTS; i++) { - for (int j = 0; j < CLIENT_NUM; j++) { - fMeasure[i].fClientTable[j].fRefNum = 0; - fMeasure[i].fClientTable[j].fSignaledAt = 0; - fMeasure[i].fClientTable[j].fAwakeAt = 0; - fMeasure[i].fClientTable[j].fFinishedAt = 0; - } - } - fPrevCycleTime = fCurCycleTime = 0; -} - -} // end of namespace diff --git a/common/JackLockedEngine.h b/common/JackLockedEngine.h index 96235aa6..c8799f49 100644 --- a/common/JackLockedEngine.h +++ b/common/JackLockedEngine.h @@ -196,7 +196,13 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble JackLock lock(this); return fEngine.GetClientPID(name); } - + + int GetClientRefNum(const char* name) + { + JackLock lock(this); + return fEngine.GetClientRefNum(name); + } + }; } // end of namespace diff --git a/common/JackNetManager.cpp b/common/JackNetManager.cpp index 1a1a9b02..95e0e802 100644 --- a/common/JackNetManager.cpp +++ b/common/JackNetManager.cpp @@ -508,10 +508,9 @@ namespace Jack JackNetMasterManager::~JackNetMasterManager() { jack_log ( "JackNetMasterManager::~JackNetMasterManager" ); - jack_info ( "Exiting net manager..." ); fRunning = false; - jack_client_stop_thread ( fManagerClient, fManagerThread ); + jack_client_kill_thread ( fManagerClient, fManagerThread ); master_list_t::iterator it; for ( it = fMasterList.begin(); it != fMasterList.end(); it++ ) delete ( *it ); diff --git a/common/JackProfiler.cpp b/common/JackProfiler.cpp new file mode 100644 index 00000000..f4fa904b --- /dev/null +++ b/common/JackProfiler.cpp @@ -0,0 +1,291 @@ +/* +Copyright (C) 2009 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "JackProfiler.h" +#include "JackServerGlobals.h" +#include "JackEngineControl.h" +#include "JackLockedEngine.h" +#include "JackArgParser.h" +#include +#include + +namespace Jack +{ + + JackProfilerClient::JackProfilerClient(jack_client_t* client, const char* name) + :fClient(client) + { + char port_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + fRefNum = JackServerGlobals::fInstance->GetEngine()->GetClientRefNum(name); + + snprintf(port_name, sizeof(port_name) - 1, "%s:scheduling", name); + fSchedulingPort = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + + snprintf(port_name, sizeof(port_name) - 1, "%s:duration", name); + fDurationPort = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + } + + JackProfilerClient::~JackProfilerClient() + { + jack_port_unregister(fClient, fSchedulingPort); + jack_port_unregister(fClient, fDurationPort); + } + +#ifdef JACK_MONITOR + JackProfiler::JackProfiler(jack_client_t* client, const JSList* params) + :fClient(client), fLastMeasure(NULL) +#else + JackProfiler::JackProfiler(jack_client_t* client, const JSList* params) + :fClient(client) +#endif + { + jack_log("JackProfiler::JackProfiler"); + + fCPULoadPort = fDriverPeriodPort = fDriverEndPort = NULL; + + const JSList* node; + const jack_driver_param_t* param; + for (node = params; node; node = jack_slist_next(node)) { + param = (const jack_driver_param_t*)node->data; + + switch (param->character) { + case 'c': + fCPULoadPort = jack_port_register(client, "cpu_load", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + break; + + case 'p': + fDriverPeriodPort = jack_port_register(client, "driver_period", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + break; + + case 'e': + fDriverEndPort = jack_port_register(client, "driver_end_time", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + break; + } + } + + // Resigster all running clients + const char **ports = jack_get_ports(client, NULL, NULL, 0); + if (ports) { + for (int i = 0; ports[i]; ++i) { + std::string str = std::string(ports[i]); + ClientRegistration(str.substr(0, str.find_first_of(':')).c_str(), 1, this); + } + free(ports); + } + + jack_set_process_callback(client, Process, this); + jack_set_client_registration_callback(client, ClientRegistration, this); + jack_activate(client); + } + + JackProfiler::~JackProfiler() + { + jack_log("JackProfiler::~JackProfiler"); + } + + void JackProfiler::ClientRegistration(const char* name, int val, void *arg) + { + #ifdef JACK_MONITOR + JackProfiler* profiler = static_cast(arg); + + // Filter client or "system" name + if (strcmp(name, jack_get_client_name(profiler->fClient)) == 0 || strcmp(name, "system") == 0) + return; + + profiler->fMutex.Lock(); + if (val) { + std::map::iterator it = profiler->fClientTable.find(name); + if (it == profiler->fClientTable.end()) { + jack_log("Client %s added", name); + profiler->fClientTable[name] = new JackProfilerClient(profiler->fClient, name); + } + } else { + std::map::iterator it = profiler->fClientTable.find(name); + if (it != profiler->fClientTable.end()) { + jack_log("Client %s removed", name); + profiler->fClientTable.erase(it); + delete((*it).second); + } + } + profiler->fMutex.Unlock(); + #endif + } + + int JackProfiler::Process(jack_nframes_t nframes, void* arg) + { + JackProfiler* profiler = static_cast(arg); + + if (profiler->fCPULoadPort) { + float* buffer_cpu_load = (float*)jack_port_get_buffer(profiler->fCPULoadPort, nframes); + float cpu_load = jack_cpu_load(profiler->fClient); + for (unsigned int i = 0; i < nframes; i++) { + buffer_cpu_load[i] = cpu_load / 100.f; + } + } + + #ifdef JACK_MONITOR + + JackEngineControl* control = JackServerGlobals::fInstance->GetEngineControl(); + JackEngineProfiling* engine_profiler = &control->fProfiler; + JackTimingMeasure* measure = engine_profiler->GetCurMeasure(); + + if (profiler->fLastMeasure && profiler->fMutex.Trylock()) { + + if (profiler->fDriverPeriodPort) { + float* buffer_driver_period = (float*)jack_port_get_buffer(profiler->fDriverPeriodPort, nframes); + float value1 = (float(measure->fPeriodUsecs) - float(measure->fCurCycleBegin - profiler->fLastMeasure->fCurCycleBegin)) / float(measure->fPeriodUsecs); + for (unsigned int i = 0; i < nframes; i++) { + buffer_driver_period[i] = value1; + } + } + + if (profiler->fDriverEndPort) { + float* buffer_driver_end_time = (float*)jack_port_get_buffer(profiler->fDriverEndPort, nframes); + float value2 = (float(measure->fPrevCycleEnd - profiler->fLastMeasure->fCurCycleBegin)) / float(measure->fPeriodUsecs); + for (unsigned int i = 0; i < nframes; i++) { + buffer_driver_end_time[i] = value2; + } + } + + std::map::iterator it; + for (it = profiler->fClientTable.begin(); it != profiler->fClientTable.end(); it++) { + int ref = (*it).second->fRefNum; + long d5 = long(measure->fClientTable[ref].fSignaledAt - profiler->fLastMeasure->fCurCycleBegin); + long d6 = long(measure->fClientTable[ref].fAwakeAt - profiler->fLastMeasure->fCurCycleBegin); + long d7 = long(measure->fClientTable[ref].fFinishedAt - profiler->fLastMeasure->fCurCycleBegin); + + float* buffer_scheduling = (float*)jack_port_get_buffer((*it).second->fSchedulingPort, nframes); + float value3 = float(d6 - d5) / float(measure->fPeriodUsecs); + jack_log("Scheduling %f", value3); + for (unsigned int i = 0; i < nframes; i++) { + buffer_scheduling[i] = value3; + } + + float* buffer_duration = (float*)jack_port_get_buffer((*it).second->fDurationPort, nframes); + float value4 = float(d7 - d6) / float(measure->fPeriodUsecs); + jack_log("Duration %f", value4); + for (unsigned int i = 0; i < nframes; i++) { + buffer_duration[i] = value4; + } + } + + profiler->fMutex.Unlock(); + } + profiler->fLastMeasure = measure; + #endif + return 0; + } + +} // namespace Jack + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "driver_interface.h" + + using namespace Jack; + + static Jack::JackProfiler* profiler = NULL; + + SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() + { + jack_driver_desc_t* desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); + + strcpy(desc->name, "profiler"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 + strcpy(desc->desc, "real-time server profiling"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 + + desc->nparams = 3; + desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); + + int i = 0; + strcpy(desc->params[i].name, "cpu-load"); + desc->params[i].character = 'c'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = TRUE; + strcpy(desc->params[i].short_desc, "Show DSP CPU load"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "driver-period"); + desc->params[i].character = 'p'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = TRUE; + strcpy(desc->params[i].short_desc, "Show driver period"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "driver-end-time"); + desc->params[i].character = 'e'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = TRUE; + strcpy(desc->params[i].short_desc, "Show driver end time"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + return desc; + } + + SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params) + { + if (profiler) { + jack_info("profiler already loaded"); + return 1; + } + + jack_log("Loading profiler"); + try { + profiler = new Jack::JackProfiler(jack_client, params); + assert(profiler); + return 0; + } catch (...) { + return 1; + } + } + + SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init) + { + JSList* params = NULL; + bool parse_params = true; + int res = 1; + jack_driver_desc_t* desc = jack_get_descriptor(); + + Jack::JackArgParser parser ( load_init ); + if ( parser.GetArgc() > 0 ) + parse_params = parser.ParseParams ( desc, ¶ms ); + + if (parse_params) { + res = jack_internal_initialize ( jack_client, params ); + parser.FreeParams ( params ); + } + return res; + } + + SERVER_EXPORT void jack_finish(void* arg) + { + Jack::JackProfiler* profiler = static_cast(arg); + + if (profiler) { + jack_log("Unloading profiler"); + delete profiler; + } + } + +#ifdef __cplusplus +} +#endif diff --git a/common/JackProfiler.h b/common/JackProfiler.h new file mode 100644 index 00000000..bdf3419f --- /dev/null +++ b/common/JackProfiler.h @@ -0,0 +1,80 @@ +/* +Copyright (C) 2009 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackProfiler__ +#define __JackProfiler__ + +#include "JackConstants.h" +#include "JackPlatformPlug.h" +#include "jack.h" +#include "jslist.h" +#include +#include + +#ifdef JACK_MONITOR +#include "JackEngineProfiling.h" +#endif + +namespace Jack +{ + +struct JackProfilerClient { + + int fRefNum; + jack_client_t* fClient; + jack_port_t* fSchedulingPort; + jack_port_t* fDurationPort; + + JackProfilerClient(jack_client_t* client, const char* name); + ~JackProfilerClient(); + +}; + +/*! +\brief Server real-time monitoring +*/ + +class JackProfiler +{ + + private: + + jack_client_t* fClient; + jack_port_t* fCPULoadPort; + jack_port_t* fDriverPeriodPort; + jack_port_t* fDriverEndPort; + #ifdef JACK_MONITOR + JackTimingMeasure* fLastMeasure; + std::map fClientTable; + JackMutex fMutex; + #endif + + public: + + JackProfiler(jack_client_t* jack_client, const JSList* params); + ~JackProfiler(); + + static int Process(jack_nframes_t nframes, void* arg); + static void ClientRegistration(const char* name, int val, void *arg); + +}; + +} + +#endif diff --git a/common/JackServer.cpp b/common/JackServer.cpp index 39f9cb0e..8dcf2bfb 100644 --- a/common/JackServer.cpp +++ b/common/JackServer.cpp @@ -226,6 +226,7 @@ int JackServer::SetBufferSize(jack_nframes_t buffer_size) return fAudioDriver->Start(); } else { // Failure: try to restore current value jack_error("Cannot SetBufferSize for audio driver, restore current value %ld", current_buffer_size); + fAudioDriver->SetBufferSize(current_buffer_size); fFreewheelDriver->SetBufferSize(current_buffer_size); fEngineControl->InitFrameTime(); fAudioDriver->Start(); diff --git a/common/JackShmMem.cpp b/common/JackShmMem.cpp index 9934ee0f..a6ec3159 100644 --- a/common/JackShmMem.cpp +++ b/common/JackShmMem.cpp @@ -102,7 +102,17 @@ void JackShmMem::operator delete(void* obj) void LockMemoryImp(void* ptr, size_t size) { - if (CHECK_MLOCK(ptr, size)) { + if (CHECK_MLOCK((char*)ptr, size)) { + jack_log("Succeeded in locking %u byte memory area", size); + } else { + jack_error("Cannot lock down memory area (%s)", strerror(errno)); + } +} + +void InitLockMemoryImp(void* ptr, size_t size) +{ + if (CHECK_MLOCK((char*)ptr, size)) { + memset(ptr, 0, size); jack_log("Succeeded in locking %u byte memory area", size); } else { jack_error("Cannot lock down memory area (%s)", strerror(errno)); @@ -111,7 +121,7 @@ void LockMemoryImp(void* ptr, size_t size) void UnlockMemoryImp(void* ptr, size_t size) { - if (CHECK_MUNLOCK(ptr, size)) { + if (CHECK_MUNLOCK((char*)ptr, size)) { jack_log("Succeeded in unlocking %u byte memory area", size); } else { jack_error("Cannot unlock down memory area (%s)", strerror(errno)); diff --git a/common/JackShmMem.h b/common/JackShmMem.h index a00cd190..6a6261a2 100644 --- a/common/JackShmMem.h +++ b/common/JackShmMem.h @@ -35,7 +35,10 @@ namespace Jack { SERVER_EXPORT void LockMemoryImp(void* ptr, size_t size); +SERVER_EXPORT void InitLockMemoryImp(void* ptr, size_t size); SERVER_EXPORT void UnlockMemoryImp(void* ptr, size_t size); +SERVER_EXPORT void LockAllMemory(); +SERVER_EXPORT void UnlockAllMemory(); class JackMem { diff --git a/common/JackTools.cpp b/common/JackTools.cpp index 4d87f962..891809dd 100644 --- a/common/JackTools.cpp +++ b/common/JackTools.cpp @@ -28,6 +28,7 @@ #include #endif + using namespace std; namespace Jack { @@ -38,7 +39,7 @@ namespace Jack { int JackTools::GetPID() { #ifdef WIN32 - return _getpid(); + return _getpid(); #else return getpid(); #endif diff --git a/common/jack/jslist.h b/common/jack/jslist.h index c3a501ee..18773708 100644 --- a/common/jack/jslist.h +++ b/common/jack/jslist.h @@ -26,9 +26,12 @@ #define __jack_jslist_h__ #include - #include +#ifdef sun +#define __inline__ +#endif + typedef struct _JSList JSList; typedef int (*JCompareFunc) (void* a, void* b); diff --git a/common/jack/systemdeps.h b/common/jack/systemdeps.h index 4f19941d..0099449c 100644 --- a/common/jack/systemdeps.h +++ b/common/jack/systemdeps.h @@ -29,8 +29,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #include #else #define __inline__ inline -//#define vsnprintf _vsnprintf -//#define snprintf _snprintf typedef char int8_t; typedef unsigned char uint8_t; typedef short int16_t; @@ -44,7 +42,7 @@ typedef HANDLE pthread_t; typedef int64_t _jack_time_t; #endif // WIN32 */ -#if defined(__APPLE__) || defined(__linux__) +#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) #include #include diff --git a/linux/alsa/memops.c b/common/memops.c similarity index 89% rename from linux/alsa/memops.c rename to common/memops.c index 803a6f68..fff41f1f 100644 --- a/linux/alsa/memops.c +++ b/common/memops.c @@ -30,10 +30,15 @@ #include #include #include +#ifdef __linux__ #include - +#endif #include "memops.h" +#if defined (__SSE2__) && !defined (__sun__) +#include +#endif + /* Notes about these *_SCALING values. the MAX_BIT values are floating point. when multiplied by @@ -162,15 +167,13 @@ /* Linear Congruential noise generator. From the music-dsp list * less random than rand(), but good enough and 10x faster */ +static unsigned int seed = 22222; inline unsigned int fast_rand() { - static unsigned int seed = 22222; seed = (seed * 96314165) + 907633515; - return seed; } - /* functions for native float sample data */ void sample_move_floatLE_sSs (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) { @@ -222,7 +225,6 @@ void sample_move_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsign float_24u32 (*src, z); - #if __BYTE_ORDER == __LITTLE_ENDIAN dst[0]=(char)(z>>24); dst[1]=(char)(z>>16); @@ -241,11 +243,57 @@ void sample_move_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsign void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state) { +#if defined (__SSE2__) && !defined (__sun__) + __m128 int_max = _mm_set1_ps(SAMPLE_24BIT_MAX_F); + __m128 int_min = _mm_sub_ps(_mm_setzero_ps(), int_max); + __m128 factor = int_max; + + unsigned long unrolled = nsamples / 4; + nsamples = nsamples & 3; + + while (unrolled--) { + __m128 in = _mm_load_ps(src); + __m128 scaled = _mm_mul_ps(in, factor); + __m128 clipped = _mm_min_ps(int_max, _mm_max_ps(scaled, int_min)); + + __m128i y = _mm_cvttps_epi32(clipped); + __m128i shifted = _mm_slli_epi32(y, 8); + + __m128i shuffled1 = _mm_shuffle_epi32(shifted, _MM_SHUFFLE(0, 3, 2, 1)); + __m128i shuffled2 = _mm_shuffle_epi32(shifted, _MM_SHUFFLE(1, 0, 3, 2)); + __m128i shuffled3 = _mm_shuffle_epi32(shifted, _MM_SHUFFLE(2, 1, 0, 3)); + + _mm_store_ss((float*)dst, (__m128)shifted); + dst += dst_skip; + _mm_store_ss((float*)dst, (__m128)shuffled1); + dst += dst_skip; + _mm_store_ss((float*)dst, (__m128)shuffled2); + dst += dst_skip; + _mm_store_ss((float*)dst, (__m128)shuffled3); + dst += dst_skip; + + src+= 4; + } + + while (nsamples--) { + __m128 in = _mm_load_ss(src); + __m128 scaled = _mm_mul_ss(in, factor); + __m128 clipped = _mm_min_ss(int_max, _mm_max_ss(scaled, int_min)); + + int y = _mm_cvttss_si32(clipped); + *((int *) dst) = y<<8; + + dst += dst_skip; + src++; + } + +#else while (nsamples--) { float_24u32 (*src, *((int32_t*) dst)); dst += dst_skip; src++; } +#endif } void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) @@ -279,6 +327,34 @@ void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsign void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) { +#if defined (__SSE2__) && !defined (__sun__) + unsigned long unrolled = nsamples / 4; + static float inv_sample_max_24bit = 1.0 / SAMPLE_24BIT_SCALING; + __m128 factor = _mm_set1_ps(inv_sample_max_24bit); + while (unrolled--) + { + int i1 = *((int *) src); + src+= src_skip; + int i2 = *((int *) src); + src+= src_skip; + int i3 = *((int *) src); + src+= src_skip; + int i4 = *((int *) src); + src+= src_skip; + + __m128i src = _mm_set_epi32(i1, i2, i3, i4); + __m128i shifted = _mm_srai_epi32(src, 8); + + __m128 as_float = _mm_cvtepi32_ps(shifted); + __m128 divided = _mm_mul_ps(as_float, factor); + + _mm_storeu_ps(dst, divided); + + dst += 4; + } + nsamples = nsamples & 3; +#endif + /* ALERT: signed sign-extension portability !!! */ while (nsamples--) { @@ -579,7 +655,6 @@ void sample_move_dS_s16s (jack_default_audio_sample_t *dst, char *src, unsigned } void sample_move_dS_s16 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip) - { /* ALERT: signed sign-extension portability !!! */ while (nsamples--) { @@ -652,7 +727,6 @@ memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, void memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes) - { while (src_bytes) { memcpy(dst, src, 3); @@ -665,7 +739,6 @@ memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, void memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes) - { while (src_bytes) { *((int *) dst) = *((int *) src); diff --git a/linux/alsa/memops.h b/common/memops.h similarity index 99% rename from linux/alsa/memops.h rename to common/memops.h index 691491bc..c027e4d6 100644 --- a/linux/alsa/memops.h +++ b/common/memops.h @@ -27,6 +27,10 @@ extern "C" { #endif +#ifdef sun +#define __inline__ +#endif + typedef enum { None, Rectangular, @@ -87,7 +91,6 @@ void sample_merge_d32u24_sS (char *dst, jack_default_audio_sample_t *sr static __inline__ void sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) - { while (cnt--) { *dst += *src; @@ -98,7 +101,6 @@ sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src static __inline__ void sample_memcpy (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) - { memcpy (dst, src, cnt * sizeof (jack_default_audio_sample_t)); } diff --git a/common/shm.h b/common/shm.h index c566f15f..a3d9f34f 100644 --- a/common/shm.h +++ b/common/shm.h @@ -28,6 +28,10 @@ extern "C" */ #ifdef USE_POSIX_SHM +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + #ifndef SHM_NAME_MAX #define SHM_NAME_MAX NAME_MAX #endif diff --git a/common/wscript b/common/wscript index 10cd4548..8c576a15 100644 --- a/common/wscript +++ b/common/wscript @@ -21,15 +21,18 @@ def create_jack_process_obj(bld, target, sources, uselib = None): env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] if bld.env['IS_LINUX']: env_includes = ['../linux', '../posix', '../linux/alsa'] + if bld.env['IS_SUN']: + env_includes = ['../solaris', '../posix', '../solaris/oss'] process.includes = ['.'] + env_includes + ['jack', '..'] process.name = target process.target = target process.source = sources - process.env.append_value("CPPFLAGS", "-fvisibility=hidden") + if bld.env['IS_LINUX']: + process.env.append_value("CPPFLAGS", "-fvisibility=hidden") if bld.env['IS_MACOSX']: process.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc") - process.env.append_value("LINKFLAGS", "") + process.env.append_value("CPPFLAGS", "-fvisibility=hidden") process.install_path = '${ADDON_DIR}/' process.uselib_local = uselib.name return process @@ -58,6 +61,7 @@ def build(bld): 'timestamps.c', 'JackTools.cpp', 'JackMessageBuffer.cpp', + 'JackEngineProfiling.cpp', ] includes = ['.', './jack', '..'] @@ -70,12 +74,23 @@ def build(bld): '../posix/JackFifo.cpp', '../posix/JackProcessSync.cpp', '../posix/JackSocket.cpp', - '../linux/JackLinuxTime.c', + '../linux/JackLinuxTime.c', ] includes = ['../linux', '../posix'] + includes uselib.append('RT') uselib.append('DL') + if bld.env['IS_SUN']: + common_libsources += [ + '../posix/JackPosixThread.cpp', + '../posix/JackFifo.cpp', + '../posix/JackProcessSync.cpp', + '../posix/JackSocket.cpp', + '../solaris/JackSolarisTime.c', + ] + includes = ['../solaris', '../posix'] + includes + uselib.append('RT') + if bld.env['IS_MACOSX']: common_libsources += [ '../posix/JackProcessSync.cpp', @@ -83,7 +98,7 @@ def build(bld): '../macosx/JackMachThread.cpp', '../macosx/JackMachSemaphore.cpp', '../macosx/JackMachPort.cpp', - '../macosx/JackMachTime.c', + '../macosx/JackMachTime.c', ] includes = ['../macosx', '../macosx/RPC', '../posix'] + includes @@ -125,6 +140,14 @@ def build(bld): '../posix/JackNetUnixSocket.cpp', ] + if bld.env['IS_SUN']: + serverlib.source += [ + '../posix/JackSocketServerChannel.cpp', + '../posix/JackSocketNotifyChannel.cpp', + '../posix/JackSocketServerNotifyChannel.cpp', + '../posix/JackNetUnixSocket.cpp', + ] + if bld.env['IS_MACOSX']: serverlib.source += [ '../macosx/JackMachServerChannel.cpp', @@ -136,12 +159,19 @@ def build(bld): ] serverlib.vnum = bld.env['JACK_API_VERSION'] - serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") + + if bld.env['IS_LINUX']: + serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") + if bld.env['IS_MACOSX']: + serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") serverlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") #serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc") serverlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module") - serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") + serverlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") + + if bld.env['IS_SUN']: + serverlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") clientlib = bld.new_task_gen('cxx', 'shlib') clientlib.features.append('cc') @@ -165,6 +195,12 @@ def build(bld): '../posix/JackPosixServerLaunch.cpp', ] + if bld.env['IS_SUN']: + clientlib.source += [ + '../posix/JackSocketClientChannel.cpp', + '../posix/JackPosixServerLaunch.cpp', + ] + if bld.env['IS_MACOSX']: clientlib.source += [ '../macosx/JackMachClientChannel.cpp', @@ -174,15 +210,24 @@ def build(bld): ] clientlib.vnum = bld.env['JACK_API_VERSION'] - clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") + + if bld.env['IS_LINUX']: + clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") + if bld.env['IS_MACOSX']: + clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") clientlib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") - #clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc") - clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module") + #clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module -arch i386 -arch ppc" + clientlib.env.append_value("LINKFLAGS", "-framework CoreAudio -framework vecLib -single_module") clientlib.env.append_value("LINKFLAGS", "-compatibility_version 1 -current_version 1") + if bld.env['IS_SUN']: + clientlib.env.append_value("LINKFLAGS", "-lnsl -lsocket") + create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib) + create_jack_process_obj(bld, 'profiler', 'JackProfiler.cpp', serverlib) + net_adapter_sources = [ 'JackResampler.cpp', 'JackLibSampleRateResampler.cpp', @@ -201,7 +246,7 @@ def build(bld): 'JackAudioAdapter.cpp', 'JackAudioAdapterInterface.cpp', 'JackAudioAdapterFactory.cpp', - ] + ] if bld.env['BUILD_ADAPTER'] and bld.env['IS_MACOSX']: audio_adapter_sources += ['../macosx/coreaudio/JackCoreAudioAdapter.cpp'] @@ -214,6 +259,11 @@ def build(bld): process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) process.uselib = ['ALSA', 'SAMPLERATE'] + if bld.env['BUILD_ADAPTER'] and bld.env['IS_SUN']: + audio_adapter_sources += ['../solaris/oss/JackOSSAdapter.cpp', 'memops.c'] + process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) + process.uselib = 'SAMPLERATE' + #audio_adapter_sources += ['../windows/JackPortAudioAdapter.cpp'] #process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) diff --git a/example-clients/cpu_load.c b/example-clients/cpu_load.c new file mode 100644 index 00000000..1d5787ac --- /dev/null +++ b/example-clients/cpu_load.c @@ -0,0 +1,92 @@ +/** @file cpu_load.c + * + */ + +#include +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include + + +jack_client_t *client; + +static void signal_handler ( int sig ) +{ + jack_client_close ( client ); + fprintf ( stderr, "signal received, exiting ...\n" ); + exit ( 0 ); +} + + +/** + * JACK calls this shutdown_callback if the server ever shuts down or + * decides to disconnect the client. + */ +void +jack_shutdown ( void *arg ) +{ + exit ( 1 ); +} + +int +main ( int argc, char *argv[] ) +{ + jack_options_t options = JackNullOption; + jack_status_t status; + + /* open a client connection to the JACK server */ + + client = jack_client_open ("jack_cpu_load", options, &status); + if ( client == NULL ) + { + fprintf ( stderr, "jack_client_open() failed, " + "status = 0x%2.0x\n", status ); + if ( status & JackServerFailed ) + { + fprintf ( stderr, "Unable to connect to JACK server\n" ); + } + exit ( 1 ); + } + + jack_on_shutdown ( client, jack_shutdown, 0 ); + + /* Tell the JACK server that we are ready to roll. Our + * process() callback will start running now. */ + + if ( jack_activate ( client ) ) + { + fprintf ( stderr, "cannot activate client" ); + exit ( 1 ); + } + + /* install a signal handler to properly quits jack client */ +#ifdef WIN32 + signal ( SIGINT, signal_handler ); + signal ( SIGABRT, signal_handler ); + signal ( SIGTERM, signal_handler ); +#else + signal ( SIGQUIT, signal_handler ); + signal ( SIGTERM, signal_handler ); + signal ( SIGHUP, signal_handler ); + signal ( SIGINT, signal_handler ); +#endif + + while (1) + { + printf("jack DSP load %f\n", jack_cpu_load(client)); +#ifdef WIN32 + Sleep ( 1000 ); +#else + sleep ( 1 ); +#endif + } + + jack_client_close ( client ); + exit ( 0 ); +} diff --git a/example-clients/simple_client.c b/example-clients/simple_client.c index f8799b55..9e90fcd1 100644 --- a/example-clients/simple_client.c +++ b/example-clients/simple_client.c @@ -53,8 +53,8 @@ process (jack_nframes_t nframes, void *arg) paTestData *data = (paTestData*)arg; int i; - out1 = jack_port_get_buffer (output_port1, nframes); - out2 = jack_port_get_buffer (output_port2, nframes); + out1 = (jack_default_audio_sample_t*)jack_port_get_buffer (output_port1, nframes); + out2 = (jack_default_audio_sample_t*)jack_port_get_buffer (output_port2, nframes); for( i=0; i= 3) { /* server name specified? */ server_name = argv[2]; - options |= JackServerName; + int my_option = JackNullOption | JackServerName; + options = (jack_options_t)my_option; } } else { /* use basename of argv[0] */ client_name = strrchr(argv[0], '/'); diff --git a/example-clients/wscript b/example-clients/wscript index 5125bcdf..03886af4 100644 --- a/example-clients/wscript +++ b/example-clients/wscript @@ -19,6 +19,7 @@ example_programs = { 'jack_evmon' : 'evmon.c', 'jack_monitor_client' : 'monitor_client.c', 'jack_thru' : 'thru_client.c', + 'jack_cpu_load' : 'cpu_load.c', 'jack_server_control' : 'server_control.cpp', } @@ -51,6 +52,8 @@ def build(bld): os_incdir = ['../linux', '../posix'] if bld.env['IS_MACOSX']: os_incdir = ['../macosx', '../posix'] + if bld.env['IS_SUN']: + os_incdir = ['../solaris', '../posix'] for example_program, example_program_source in example_programs.items(): prog = bld.new_task_gen('cxx', 'program') prog.features.append('cc') @@ -62,6 +65,8 @@ def build(bld): prog.env.append_value("LINKFLAGS", "") if bld.env['IS_LINUX']: prog.uselib = 'RT' + if bld.env['IS_SUN']: + prog.env.append_value("LINKFLAGS", "-lm") if example_program == 'jack_server_control': prog.uselib_local = 'serverlib' else: @@ -92,10 +97,9 @@ def build(bld): prog.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") #prog.env.append_value("LINKFLAGS", "-arch i386 -arch ppc") prog.env.append_value("LINKFLAGS", "") + prog.uselib = 'SNDFILE' if bld.env['IS_LINUX']: prog.uselib = 'RT SNDFILE' - if bld.env['IS_MACOSX']: - prog.uselib = 'SNDFILE' prog.uselib_local = 'clientlib' prog.target = 'jack_rec' @@ -109,6 +113,8 @@ def build(bld): lib.env.append_value("CPPFLAGS", "-mmacosx-version-min=10.4 -arch i386 -arch ppc") #lib.env.append_value("LINKFLAGS", "-arch i386 -arch ppc") lib.env.append_value("LINKFLAGS", "") + if bld.env['IS_SUN']: + lib.env.append_value("LINKFLAGS", "-lm") lib.uselib_local = 'serverlib' lib.install_path = '${ADDON_DIR}/' diff --git a/linux/wscript b/linux/wscript index 89275d8b..0df5e866 100644 --- a/linux/wscript +++ b/linux/wscript @@ -40,7 +40,7 @@ def build(bld): 'alsa/alsa_rawmidi.c', 'alsa/alsa_seqmidi.c', 'alsa/alsa_midi_jackmp.cpp', - 'alsa/memops.c', + '../common/memops.c', 'alsa/generic_hw.c', 'alsa/hdsp.c', 'alsa/hammerfall.c', diff --git a/macosx/JackMachTime.c b/macosx/JackMachTime.c index f6f8f2eb..bd8237a6 100644 --- a/macosx/JackMachTime.c +++ b/macosx/JackMachTime.c @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include -double __jack_time_ratio; +static double __jack_time_ratio; SERVER_EXPORT void JackSleep(long usec) { diff --git a/macosx/Jackdmp.xcodeproj/project.pbxproj b/macosx/Jackdmp.xcodeproj/project.pbxproj index fcf54b67..3423db05 100644 --- a/macosx/Jackdmp.xcodeproj/project.pbxproj +++ b/macosx/Jackdmp.xcodeproj/project.pbxproj @@ -481,8 +481,6 @@ 4B80D7EB0BA0D17400F035BB /* JackMidiPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B80D7E50BA0D17400F035BB /* JackMidiPort.h */; }; 4B80D7EC0BA0D17400F035BB /* JackMidiPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E60BA0D17400F035BB /* JackMidiPort.cpp */; }; 4B80D7ED0BA0D17400F035BB /* JackMidiAPI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B80D7E70BA0D17400F035BB /* JackMidiAPI.cpp */; }; - 4B8F3D4B0E06C4A10096D19C /* JackEngineTiming.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B8F3D490E06C4A10096D19C /* JackEngineTiming.cpp */; }; - 4B8F3D4C0E06C4A10096D19C /* JackEngineTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8F3D4A0E06C4A10096D19C /* JackEngineTiming.h */; }; 4B93F1990E87992100E4ECCD /* JackPosixThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6A20E703B2E0066E42F /* JackPosixThread.cpp */; }; 4B93F19A0E87992200E4ECCD /* JackPosixThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BC3B6A30E703B2E0066E42F /* JackPosixThread.h */; }; 4B93F19B0E87992300E4ECCD /* JackProcessSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BC3B6AA0E703B690066E42F /* JackProcessSync.cpp */; }; @@ -512,11 +510,11 @@ 4BA7BDD00DC22F4500AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BA7BDCB0DC22F4500AA3457 /* Jackservermp.framework */; }; 4BA7BDD10DC22F4500AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BA7BDCB0DC22F4500AA3457 /* Jackservermp.framework */; }; 4BA7BDD20DC22F4500AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BA7BDCB0DC22F4500AA3457 /* Jackservermp.framework */; }; - 4BA7BE0F0DC232A400AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; }; - 4BA7BE1A0DC2347500AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; }; - 4BA7BE200DC234FB00AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; }; - 4BA7BE240DC2350D00AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; }; - 4BA7BE270DC2352A00AA3457 /* Jackservermp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; }; + 4BA7BE0F0DC232A400AA3457 /* Jackdmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */; }; + 4BA7BE1A0DC2347500AA3457 /* Jackdmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */; }; + 4BA7BE200DC234FB00AA3457 /* Jackdmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */; }; + 4BA7BE240DC2350D00AA3457 /* Jackdmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */; }; + 4BA7BE270DC2352A00AA3457 /* Jackdmp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */; }; 4BA7FECA0D8E76650017FF73 /* control.c in Sources */ = {isa = PBXBuildFile; fileRef = 4BA7FEC80D8E76650017FF73 /* control.c */; }; 4BAB95B80B9E20B800A0C723 /* JackPortType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BAB95B60B9E20B800A0C723 /* JackPortType.cpp */; }; 4BAB95B90B9E20B800A0C723 /* JackPortType.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BAB95B70B9E20B800A0C723 /* JackPortType.h */; }; @@ -527,6 +525,10 @@ 4BB9D4B30E2610B300351653 /* JackTransportEngine.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BD4B4D409BACD9600750C0F /* JackTransportEngine.h */; }; 4BB9D4B40E2610B400351653 /* JackTransportEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4B4D509BACD9600750C0F /* JackTransportEngine.cpp */; }; 4BB9D4E40E26112900351653 /* JackEngineControl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B6F7AEC0CD0CDBD00F48A9D /* JackEngineControl.cpp */; }; + 4BBAE4100F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BBAE40E0F42FA6100B8BD3F /* JackEngineProfiling.h */; }; + 4BBAE4110F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBAE40F0F42FA6100B8BD3F /* JackEngineProfiling.cpp */; }; + 4BBAE4120F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BBAE40E0F42FA6100B8BD3F /* JackEngineProfiling.h */; }; + 4BBAE4130F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBAE40F0F42FA6100B8BD3F /* JackEngineProfiling.cpp */; }; 4BBB00D30E72614F0018AB1B /* JackPortAudioDevices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB00CF0E72614F0018AB1B /* JackPortAudioDevices.cpp */; }; 4BBB00D40E72614F0018AB1B /* JackPortAudioDevices.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BBB00D00E72614F0018AB1B /* JackPortAudioDevices.h */; }; 4BBB00D50E72614F0018AB1B /* JackPortAudioDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BBB00D10E72614F0018AB1B /* JackPortAudioDriver.cpp */; }; @@ -1127,8 +1129,6 @@ 4B05A05D0DF72BC000840F4C /* JackAlsaDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackAlsaDriver.cpp; path = ../linux/alsa/JackAlsaDriver.cpp; sourceTree = SOURCE_ROOT; }; 4B05A05E0DF72BC000840F4C /* JackAlsaDriver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackAlsaDriver.h; path = ../linux/alsa/JackAlsaDriver.h; sourceTree = SOURCE_ROOT; }; 4B05A05F0DF72BC000840F4C /* jslist.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = jslist.h; path = ../linux/alsa/jslist.h; sourceTree = SOURCE_ROOT; }; - 4B05A0600DF72BC000840F4C /* memops.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = memops.c; path = ../linux/alsa/memops.c; sourceTree = SOURCE_ROOT; }; - 4B05A0610DF72BC000840F4C /* memops.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = memops.h; path = ../linux/alsa/memops.h; sourceTree = SOURCE_ROOT; }; 4B05A0620DF72BC000840F4C /* midi_pack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = midi_pack.h; path = ../linux/alsa/midi_pack.h; sourceTree = SOURCE_ROOT; }; 4B05A0630DF72BC000840F4C /* midi_unpack.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = midi_unpack.h; path = ../linux/alsa/midi_unpack.h; sourceTree = SOURCE_ROOT; }; 4B05A0640DF72BC000840F4C /* usx2y.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = usx2y.c; path = ../linux/alsa/usx2y.c; sourceTree = SOURCE_ROOT; }; @@ -1161,7 +1161,7 @@ 4B0A28E60D52073D002EFF74 /* jack_thread_wait */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_thread_wait; sourceTree = BUILT_PRODUCTS_DIR; }; 4B0A28EC0D520852002EFF74 /* tw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tw.c; path = "../example-clients/tw.c"; sourceTree = SOURCE_ROOT; }; 4B0A292D0D52108E002EFF74 /* jack_thread_wait */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_thread_wait; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B19B3000E23620F00DD4A82 /* audioadapter.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = audioadapter.so; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B19B3000E23620F00DD4A82 /* netmanager.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = netmanager.so; sourceTree = BUILT_PRODUCTS_DIR; }; 4B19B3060E2362E700DD4A82 /* JackAudioAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapter.cpp; path = ../common/JackAudioAdapter.cpp; sourceTree = SOURCE_ROOT; }; 4B19B3070E2362E700DD4A82 /* JackAudioAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackAudioAdapter.h; path = ../common/JackAudioAdapter.h; sourceTree = SOURCE_ROOT; }; 4B19B3080E2362E700DD4A82 /* JackAudioAdapterInterface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioAdapterInterface.cpp; path = ../common/JackAudioAdapterInterface.cpp; sourceTree = SOURCE_ROOT; }; @@ -1173,7 +1173,7 @@ 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackGlobals.cpp; path = ../common/JackGlobals.cpp; sourceTree = SOURCE_ROOT; }; 4B35C4250D4731D1000DE7AE /* jackdmp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jackdmp; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C4830D4731D1000DE7AE /* Jackmp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackmp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackservermp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Jackdmp.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C5140D4731D1000DE7AE /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C5200D4731D1000DE7AE /* jack_midisine */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midisine; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C52C0D4731D1000DE7AE /* jack_metro */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_metro; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1197,19 +1197,19 @@ 4B35C6290D4731D2000DE7AE /* jack_portaudio.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_portaudio.so; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C6340D4731D2000DE7AE /* jack_dummy.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_dummy.so; sourceTree = BUILT_PRODUCTS_DIR; }; 4B35C63E0D4731D3000DE7AE /* inprocess.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = inprocess.so; sourceTree = BUILT_PRODUCTS_DIR; }; - 4B363DD80DEB02F6001F72D9 /* jack_alias */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_alias; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363DD80DEB02F6001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363DDE0DEB034E001F72D9 /* alias.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = alias.c; path = "../example-clients/alias.c"; sourceTree = SOURCE_ROOT; }; - 4B363E1A0DEB03C5001F72D9 /* jack_evmon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_evmon; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363E1A0DEB03C5001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363E200DEB0401001F72D9 /* evmon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = evmon.c; path = "../example-clients/evmon.c"; sourceTree = SOURCE_ROOT; }; - 4B363E4E0DEB0775001F72D9 /* jack_bufsize */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_bufsize; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363E4E0DEB0775001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363E710DEB0808001F72D9 /* bufsize.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bufsize.c; path = "../example-clients/bufsize.c"; sourceTree = SOURCE_ROOT; }; - 4B363EE90DEB091C001F72D9 /* jack_rec */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_rec; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363EE90DEB091C001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363EED0DEB094B001F72D9 /* capture_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = capture_client.c; path = "../example-clients/capture_client.c"; sourceTree = SOURCE_ROOT; }; - 4B363F1E0DEB0A6A001F72D9 /* jack_monitor_client */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_monitor_client; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363F1E0DEB0A6A001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363F220DEB0AB0001F72D9 /* monitor_client.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = monitor_client.c; path = "../example-clients/monitor_client.c"; sourceTree = SOURCE_ROOT; }; - 4B363F350DEB0BD1001F72D9 /* jack_showtime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_showtime; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363F350DEB0BD1001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363F3D0DEB0C31001F72D9 /* showtime.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = showtime.c; path = "../example-clients/showtime.c"; sourceTree = SOURCE_ROOT; }; - 4B363F720DEB0D4E001F72D9 /* jack_impulse_grabber */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_impulse_grabber; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B363F720DEB0D4E001F72D9 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4B363F750DEB0D7D001F72D9 /* impulse_grabber.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = impulse_grabber.c; path = "../example-clients/impulse_grabber.c"; sourceTree = SOURCE_ROOT; }; 4B37C20306DF1FBE0016E567 /* CALatencyLog.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = CALatencyLog.cpp; path = /Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.cpp; sourceTree = ""; }; 4B37C20406DF1FBE0016E567 /* CALatencyLog.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CALatencyLog.h; path = /Developer/Examples/CoreAudio/PublicUtility/CALatencyLog.h; sourceTree = ""; }; @@ -1228,7 +1228,7 @@ 4B5A1BBD0CD1CC110005BF74 /* midiseq.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = midiseq.c; path = "../example-clients/midiseq.c"; sourceTree = SOURCE_ROOT; }; 4B5A1BDA0CD1CCE10005BF74 /* jack_midisine */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midisine; sourceTree = BUILT_PRODUCTS_DIR; }; 4B5A1BDC0CD1CD420005BF74 /* midisine.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = midisine.c; path = "../example-clients/midisine.c"; sourceTree = SOURCE_ROOT; }; - 4B5E08D50E5B66EE00BEE4E0 /* netadapter.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = netadapter.so; sourceTree = BUILT_PRODUCTS_DIR; }; + 4B5E08D50E5B66EE00BEE4E0 /* netmanager.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = netmanager.so; sourceTree = BUILT_PRODUCTS_DIR; }; 4B5E08DF0E5B676C00BEE4E0 /* JackNetAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackNetAdapter.cpp; path = ../common/JackNetAdapter.cpp; sourceTree = SOURCE_ROOT; }; 4B5E08E00E5B676C00BEE4E0 /* JackNetAdapter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackNetAdapter.h; path = ../common/JackNetAdapter.h; sourceTree = SOURCE_ROOT; }; 4B5F253D0DEE9B8F0041E486 /* JackLockedEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackLockedEngine.h; path = ../common/JackLockedEngine.h; sourceTree = SOURCE_ROOT; }; @@ -1272,8 +1272,6 @@ 4B869D7F08C9CB00001CF041 /* JackDriverLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackDriverLoader.cpp; path = ../common/JackDriverLoader.cpp; sourceTree = SOURCE_ROOT; }; 4B89B759076B731100D170DE /* JackRPCClientUser.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = JackRPCClientUser.c; path = RPC/JackRPCClientUser.c; sourceTree = SOURCE_ROOT; }; 4B89B769076B74D200D170DE /* JackRPCEngineUser.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = JackRPCEngineUser.c; path = RPC/JackRPCEngineUser.c; sourceTree = SOURCE_ROOT; }; - 4B8F3D490E06C4A10096D19C /* JackEngineTiming.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackEngineTiming.cpp; path = ../common/JackEngineTiming.cpp; sourceTree = SOURCE_ROOT; }; - 4B8F3D4A0E06C4A10096D19C /* JackEngineTiming.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackEngineTiming.h; path = ../common/JackEngineTiming.h; sourceTree = SOURCE_ROOT; }; 4B940B9B06DDDE5B00D77F60 /* AudioHardware.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = AudioHardware.h; path = /System/Library/Frameworks/CoreAudio.framework/Versions/A/Headers/AudioHardware.h; sourceTree = ""; }; 4B95BCAD0D913073000F7695 /* control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = control.h; path = ../common/jack/control.h; sourceTree = SOURCE_ROOT; }; 4B978DBB0A31CF4A009E2DD1 /* jack_portaudio.so */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = jack_portaudio.so; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1288,12 +1286,14 @@ 4BA692D40CBE4C9000EAD520 /* jack_unload */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_unload; sourceTree = BUILT_PRODUCTS_DIR; }; 4BA692D60CBE4CC600EAD520 /* ipunload.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ipunload.c; path = "../example-clients/ipunload.c"; sourceTree = SOURCE_ROOT; }; 4BA7BDCB0DC22F4500AA3457 /* Jackservermp.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Jackservermp.framework; path = build/Development/Jackservermp.framework; sourceTree = SOURCE_ROOT; }; - 4BA7FEC30D8E76270017FF73 /* jack_server_control */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_server_control; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BA7FEC30D8E76270017FF73 /* jack_lsp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_lsp; sourceTree = BUILT_PRODUCTS_DIR; }; 4BA7FEC80D8E76650017FF73 /* control.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = control.c; path = "../example-clients/control.c"; sourceTree = SOURCE_ROOT; }; 4BAB95B60B9E20B800A0C723 /* JackPortType.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortType.cpp; path = ../common/JackPortType.cpp; sourceTree = SOURCE_ROOT; }; 4BAB95B70B9E20B800A0C723 /* JackPortType.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackPortType.h; path = ../common/JackPortType.h; sourceTree = SOURCE_ROOT; }; 4BAB95EC0B9E21A500A0C723 /* JackAudioPort.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackAudioPort.cpp; path = ../common/JackAudioPort.cpp; sourceTree = SOURCE_ROOT; }; 4BB371D40C1AD85A0050C1E4 /* JackNotification.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackNotification.h; path = ../common/JackNotification.h; sourceTree = SOURCE_ROOT; }; + 4BBAE40E0F42FA6100B8BD3F /* JackEngineProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JackEngineProfiling.h; path = ../common/JackEngineProfiling.h; sourceTree = SOURCE_ROOT; }; + 4BBAE40F0F42FA6100B8BD3F /* JackEngineProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JackEngineProfiling.cpp; path = ../common/JackEngineProfiling.cpp; sourceTree = SOURCE_ROOT; }; 4BBB00CF0E72614F0018AB1B /* JackPortAudioDevices.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortAudioDevices.cpp; path = ../windows/portaudio/JackPortAudioDevices.cpp; sourceTree = SOURCE_ROOT; }; 4BBB00D00E72614F0018AB1B /* JackPortAudioDevices.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackPortAudioDevices.h; path = ../windows/portaudio/JackPortAudioDevices.h; sourceTree = SOURCE_ROOT; }; 4BBB00D10E72614F0018AB1B /* JackPortAudioDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackPortAudioDriver.cpp; path = ../windows/portaudio/JackPortAudioDriver.cpp; sourceTree = SOURCE_ROOT; }; @@ -1405,14 +1405,14 @@ 4BF8D2470834F20600C94B91 /* testSem.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = testSem.cpp; path = ../tests/testSem.cpp; sourceTree = SOURCE_ROOT; }; 4BF8FB0D08AC88EF00D1A344 /* JackFrameTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JackFrameTimer.cpp; path = ../common/JackFrameTimer.cpp; sourceTree = SOURCE_ROOT; }; 4BF8FB0E08AC88EF00D1A344 /* JackFrameTimer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JackFrameTimer.h; path = ../common/JackFrameTimer.h; sourceTree = SOURCE_ROOT; }; - 4BFA5E980DEC4D9C00FA4CDB /* testMutex */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testMutex; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA5E980DEC4D9C00FA4CDB /* testSem */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testSem; sourceTree = BUILT_PRODUCTS_DIR; }; 4BFA5E9E0DEC4DD900FA4CDB /* testMutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testMutex.cpp; path = ../tests/testMutex.cpp; sourceTree = SOURCE_ROOT; }; - 4BFA828C0DF6A9E40087B4E1 /* jack_evmon */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_evmon; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA829F0DF6A9E40087B4E1 /* jack_bufsize */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_bufsize; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA82AB0DF6A9E40087B4E1 /* jack_rec */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_rec; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA82B70DF6A9E40087B4E1 /* jack_monitor_client */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_monitor_client; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA82C30DF6A9E40087B4E1 /* jack_showtime */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_showtime; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_impulse_grabber; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA828C0DF6A9E40087B4E1 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA829F0DF6A9E40087B4E1 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA82AB0DF6A9E40087B4E1 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA82B70DF6A9E40087B4E1 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA82C30DF6A9E40087B4E1 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; + 4BFA82CF0DF6A9E40087B4E1 /* jack_midiseq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jack_midiseq; sourceTree = BUILT_PRODUCTS_DIR; }; 4BFA99A20AAAF3B0009E916C /* jdelay */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = jdelay; sourceTree = BUILT_PRODUCTS_DIR; }; 4BFA99A90AAAF40C009E916C /* jdelay.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = jdelay.cpp; path = ../tests/jdelay.cpp; sourceTree = SOURCE_ROOT; }; 4BFB297708AF44ED00D450D4 /* JackMachServerNotifyChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JackMachServerNotifyChannel.cpp; sourceTree = ""; }; @@ -1550,7 +1550,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4BA7BE0F0DC232A400AA3457 /* Jackservermp.framework in Frameworks */, + 4BA7BE0F0DC232A400AA3457 /* Jackdmp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1558,7 +1558,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4BA7BE1A0DC2347500AA3457 /* Jackservermp.framework in Frameworks */, + 4BA7BE1A0DC2347500AA3457 /* Jackdmp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1601,7 +1601,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4BA7BE200DC234FB00AA3457 /* Jackservermp.framework in Frameworks */, + 4BA7BE200DC234FB00AA3457 /* Jackdmp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1609,7 +1609,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4BA7BE240DC2350D00AA3457 /* Jackservermp.framework in Frameworks */, + 4BA7BE240DC2350D00AA3457 /* Jackdmp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1617,7 +1617,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 4BA7BE270DC2352A00AA3457 /* Jackservermp.framework in Frameworks */, + 4BA7BE270DC2352A00AA3457 /* Jackdmp.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2042,7 +2042,7 @@ 4B5A1BDA0CD1CCE10005BF74 /* jack_midisine */, 4B35C4250D4731D1000DE7AE /* jackdmp */, 4B35C4830D4731D1000DE7AE /* Jackmp.framework */, - 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */, + 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */, 4B35C5140D4731D1000DE7AE /* jack_midiseq */, 4B35C5200D4731D1000DE7AE /* jack_midisine */, 4B35C52C0D4731D1000DE7AE /* jack_metro */, @@ -2069,26 +2069,26 @@ 4B0A28E60D52073D002EFF74 /* jack_thread_wait */, 4B0A292D0D52108E002EFF74 /* jack_thread_wait */, 4B57F5950D72C27900B4E719 /* jack_thread_wait */, - 4BA7FEC30D8E76270017FF73 /* jack_server_control */, + 4BA7FEC30D8E76270017FF73 /* jack_lsp */, BA222ACF0DC88132001A17F4 /* jack_net.so */, BA222AE90DC882DB001A17F4 /* netmanager.so */, - 4BA7FEC30D8E76270017FF73 /* jack_server_control */, - 4B363DD80DEB02F6001F72D9 /* jack_alias */, - 4B363E1A0DEB03C5001F72D9 /* jack_evmon */, - 4B363E4E0DEB0775001F72D9 /* jack_bufsize */, - 4B363EE90DEB091C001F72D9 /* jack_rec */, - 4B363F1E0DEB0A6A001F72D9 /* jack_monitor_client */, - 4B363F350DEB0BD1001F72D9 /* jack_showtime */, - 4B363F720DEB0D4E001F72D9 /* jack_impulse_grabber */, - 4BFA5E980DEC4D9C00FA4CDB /* testMutex */, - 4BFA828C0DF6A9E40087B4E1 /* jack_evmon */, - 4BFA829F0DF6A9E40087B4E1 /* jack_bufsize */, - 4BFA82AB0DF6A9E40087B4E1 /* jack_rec */, - 4BFA82B70DF6A9E40087B4E1 /* jack_monitor_client */, - 4BFA82C30DF6A9E40087B4E1 /* jack_showtime */, - 4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */, - 4B19B3000E23620F00DD4A82 /* audioadapter.so */, - 4B5E08D50E5B66EE00BEE4E0 /* netadapter.so */, + 4BA7FEC30D8E76270017FF73 /* jack_lsp */, + 4B363DD80DEB02F6001F72D9 /* jack_midiseq */, + 4B363E1A0DEB03C5001F72D9 /* jack_midiseq */, + 4B363E4E0DEB0775001F72D9 /* jack_midiseq */, + 4B363EE90DEB091C001F72D9 /* jack_midiseq */, + 4B363F1E0DEB0A6A001F72D9 /* jack_midiseq */, + 4B363F350DEB0BD1001F72D9 /* jack_midiseq */, + 4B363F720DEB0D4E001F72D9 /* jack_midiseq */, + 4BFA5E980DEC4D9C00FA4CDB /* testSem */, + 4BFA828C0DF6A9E40087B4E1 /* jack_midiseq */, + 4BFA829F0DF6A9E40087B4E1 /* jack_midiseq */, + 4BFA82AB0DF6A9E40087B4E1 /* jack_midiseq */, + 4BFA82B70DF6A9E40087B4E1 /* jack_midiseq */, + 4BFA82C30DF6A9E40087B4E1 /* jack_midiseq */, + 4BFA82CF0DF6A9E40087B4E1 /* jack_midiseq */, + 4B19B3000E23620F00DD4A82 /* netmanager.so */, + 4B5E08D50E5B66EE00BEE4E0 /* netmanager.so */, ); name = Products; sourceTree = ""; @@ -2152,8 +2152,6 @@ 4B05A05D0DF72BC000840F4C /* JackAlsaDriver.cpp */, 4B05A05E0DF72BC000840F4C /* JackAlsaDriver.h */, 4B05A05F0DF72BC000840F4C /* jslist.h */, - 4B05A0600DF72BC000840F4C /* memops.c */, - 4B05A0610DF72BC000840F4C /* memops.h */, 4B05A0620DF72BC000840F4C /* midi_pack.h */, 4B05A0630DF72BC000840F4C /* midi_unpack.h */, 4B05A0640DF72BC000840F4C /* usx2y.c */, @@ -2328,8 +2326,8 @@ 4B2C28F908DAD01E00249230 /* JackGlobals.cpp */, 4BF8D2190834F03D00C94B91 /* JackEngineControl.h */, 4B6F7AEC0CD0CDBD00F48A9D /* JackEngineControl.cpp */, - 4B8F3D4A0E06C4A10096D19C /* JackEngineTiming.h */, - 4B8F3D490E06C4A10096D19C /* JackEngineTiming.cpp */, + 4BBAE40E0F42FA6100B8BD3F /* JackEngineProfiling.h */, + 4BBAE40F0F42FA6100B8BD3F /* JackEngineProfiling.cpp */, 4BD4B4D409BACD9600750C0F /* JackTransportEngine.h */, 4BD4B4D509BACD9600750C0F /* JackTransportEngine.cpp */, 4BF8D2220834F05C00C94B91 /* JackServer.h */, @@ -2741,6 +2739,7 @@ 4B4CA9770E02CF9600F4BFDA /* JackRestartThreadedDriver.h in Headers */, 4B4E9AFD0E5F1090000A3278 /* JackControlAPI.h in Headers */, 4B93F19A0E87992200E4ECCD /* JackPosixThread.h in Headers */, + 4BBAE4120F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3103,10 +3102,10 @@ 4B5F253E0DEE9B8F0041E486 /* JackLockedEngine.h in Headers */, 4BBC93BB0DF9736C002DF220 /* JackWaitThreadedDriver.h in Headers */, 4B4CA9750E02CF9600F4BFDA /* JackRestartThreadedDriver.h in Headers */, - 4B8F3D4C0E06C4A10096D19C /* JackEngineTiming.h in Headers */, 4B4E9AFB0E5F1090000A3278 /* JackControlAPI.h in Headers */, 4BC3B6A70E703B2E0066E42F /* JackPosixThread.h in Headers */, 4BF2841B0F31B4BC00B05BE3 /* JackArgParser.h in Headers */, + 4BBAE4100F42FA6100B8BD3F /* JackEngineProfiling.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3393,7 +3392,7 @@ ); name = audioadapter; productName = jack_coreaudio; - productReference = 4B19B3000E23620F00DD4A82 /* audioadapter.so */; + productReference = 4B19B3000E23620F00DD4A82 /* netmanager.so */; productType = "com.apple.product-type.library.dynamic"; }; 4B35C41B0D4731D1000DE7AE /* jackdmp framework 64bits */ = { @@ -3450,7 +3449,7 @@ ); name = "Jackservermp.framework 64 bits"; productName = Jack; - productReference = 4B35C4FC0D4731D1000DE7AE /* Jackservermp.framework */; + productReference = 4B35C4FC0D4731D1000DE7AE /* Jackdmp.framework */; productType = "com.apple.product-type.framework"; }; 4B35C50A0D4731D1000DE7AE /* jack_midiseq 64 bits */ = { @@ -3899,7 +3898,7 @@ name = "jack_alias Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363DD80DEB02F6001F72D9 /* jack_alias */; + productReference = 4B363DD80DEB02F6001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B363E100DEB03C5001F72D9 /* jack_evmon Universal */ = { @@ -3918,7 +3917,7 @@ name = "jack_evmon Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363E1A0DEB03C5001F72D9 /* jack_evmon */; + productReference = 4B363E1A0DEB03C5001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B363E440DEB0775001F72D9 /* jack_bufsize Universal */ = { @@ -3937,7 +3936,7 @@ name = "jack_bufsize Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363E4E0DEB0775001F72D9 /* jack_bufsize */; + productReference = 4B363E4E0DEB0775001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B363EDF0DEB091C001F72D9 /* jack_rec Universal */ = { @@ -3956,7 +3955,7 @@ name = "jack_rec Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363EE90DEB091C001F72D9 /* jack_rec */; + productReference = 4B363EE90DEB091C001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B363F140DEB0A6A001F72D9 /* jack_monitor_client Universal */ = { @@ -3975,7 +3974,7 @@ name = "jack_monitor_client Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363F1E0DEB0A6A001F72D9 /* jack_monitor_client */; + productReference = 4B363F1E0DEB0A6A001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B363F2B0DEB0BD1001F72D9 /* jack_showtime Universal */ = { @@ -3994,7 +3993,7 @@ name = "jack_showtime Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363F350DEB0BD1001F72D9 /* jack_showtime */; + productReference = 4B363F350DEB0BD1001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B363F680DEB0D4E001F72D9 /* jack_impulse_grabber Universal */ = { @@ -4013,7 +4012,7 @@ name = "jack_impulse_grabber Universal"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4B363F720DEB0D4E001F72D9 /* jack_impulse_grabber */; + productReference = 4B363F720DEB0D4E001F72D9 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4B5A1BB10CD1CB9E0005BF74 /* jack_midiseq Universal */ = { @@ -4068,7 +4067,7 @@ ); name = netadapter; productName = jack_coreaudio; - productReference = 4B5E08D50E5B66EE00BEE4E0 /* netadapter.so */; + productReference = 4B5E08D50E5B66EE00BEE4E0 /* netmanager.so */; productType = "com.apple.product-type.library.dynamic"; }; 4B699BA7097D421600A18468 /* jackdmp framework Universal */ = { @@ -4462,7 +4461,7 @@ name = "jack_server_control Universal"; productInstallPath = /usr/local/bin; productName = jack_lsp; - productReference = 4BA7FEC30D8E76270017FF73 /* jack_server_control */; + productReference = 4BA7FEC30D8E76270017FF73 /* jack_lsp */; productType = "com.apple.product-type.tool"; }; 4BD623ED0CBCF0F000DE782F /* inprocess */ = { @@ -4536,7 +4535,7 @@ name = "testMutex Universal"; productInstallPath = /usr/local/bin; productName = testSem; - productReference = 4BFA5E980DEC4D9C00FA4CDB /* testMutex */; + productReference = 4BFA5E980DEC4D9C00FA4CDB /* testSem */; productType = "com.apple.product-type.tool"; }; 4BFA82820DF6A9E40087B4E1 /* jack_evmon 64 bits */ = { @@ -4555,7 +4554,7 @@ name = "jack_evmon 64 bits"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4BFA828C0DF6A9E40087B4E1 /* jack_evmon */; + productReference = 4BFA828C0DF6A9E40087B4E1 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4BFA82950DF6A9E40087B4E1 /* jack_bufsize 64 bits */ = { @@ -4574,7 +4573,7 @@ name = "jack_bufsize 64 bits"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4BFA829F0DF6A9E40087B4E1 /* jack_bufsize */; + productReference = 4BFA829F0DF6A9E40087B4E1 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4BFA82A10DF6A9E40087B4E1 /* jack_rec 64 bits */ = { @@ -4593,7 +4592,7 @@ name = "jack_rec 64 bits"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4BFA82AB0DF6A9E40087B4E1 /* jack_rec */; + productReference = 4BFA82AB0DF6A9E40087B4E1 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4BFA82AD0DF6A9E40087B4E1 /* jack_monitor_client 64 bits */ = { @@ -4612,7 +4611,7 @@ name = "jack_monitor_client 64 bits"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4BFA82B70DF6A9E40087B4E1 /* jack_monitor_client */; + productReference = 4BFA82B70DF6A9E40087B4E1 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4BFA82B90DF6A9E40087B4E1 /* jack_showtime 64 bits */ = { @@ -4631,7 +4630,7 @@ name = "jack_showtime 64 bits"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4BFA82C30DF6A9E40087B4E1 /* jack_showtime */; + productReference = 4BFA82C30DF6A9E40087B4E1 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4BFA82C50DF6A9E40087B4E1 /* jack_impulse_grabber 64 bits */ = { @@ -4650,7 +4649,7 @@ name = "jack_impulse_grabber 64 bits"; productInstallPath = /usr/local/bin; productName = jack_metro; - productReference = 4BFA82CF0DF6A9E40087B4E1 /* jack_impulse_grabber */; + productReference = 4BFA82CF0DF6A9E40087B4E1 /* jack_midiseq */; productType = "com.apple.product-type.tool"; }; 4BFA99980AAAF3B0009E916C /* jdelay Universal */ = { @@ -5389,6 +5388,7 @@ 4B93F1990E87992100E4ECCD /* JackPosixThread.cpp in Sources */, 4B93F19B0E87992300E4ECCD /* JackProcessSync.cpp in Sources */, 4B93F22B0E87A72500E4ECCD /* JackMachTime.c in Sources */, + 4BBAE4130F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -5762,12 +5762,12 @@ 4B4F9C8C0DC20C0400706CB0 /* JackMessageBuffer.cpp in Sources */, 4BBC93BA0DF9736C002DF220 /* JackWaitThreadedDriver.cpp in Sources */, 4B4CA9760E02CF9600F4BFDA /* JackRestartThreadedDriver.cpp in Sources */, - 4B8F3D4B0E06C4A10096D19C /* JackEngineTiming.cpp in Sources */, 4B4E9AFA0E5F1090000A3278 /* JackControlAPI.cpp in Sources */, 4BC3B6A60E703B2E0066E42F /* JackPosixThread.cpp in Sources */, 4BC3B6AC0E703B690066E42F /* JackProcessSync.cpp in Sources */, 4BF5FBCA0E878D24003D2374 /* JackMachTime.c in Sources */, 4BF2841A0F31B4BC00B05BE3 /* JackArgParser.cpp in Sources */, + 4BBAE4110F42FA6100B8BD3F /* JackEngineProfiling.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/posix/JackCompilerDeps_os.h b/posix/JackCompilerDeps_os.h index 9ac08cfb..d7d10992 100644 --- a/posix/JackCompilerDeps_os.h +++ b/posix/JackCompilerDeps_os.h @@ -21,17 +21,21 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #define __JackCompilerDeps_POSIX__ #if __GNUC__ - #define MEM_ALIGN(x,y) x __attribute__((aligned(y))) - #define EXPORT __attribute__((visibility("default"))) + #define MEM_ALIGN(x,y) x __attribute__((aligned(y))) + #define EXPORT __attribute__((visibility("default"))) #ifdef SERVER_SIDE - #define SERVER_EXPORT __attribute__((visibility("default"))) + #if (__GNUC__< 4) + #define SERVER_EXPORT + #else + #define SERVER_EXPORT __attribute__((visibility("default"))) + #endif #else #define SERVER_EXPORT #endif #else - #define MEM_ALIGN(x,y) x - #define EXPORT - #define SERVER_EXPORT + #define MEM_ALIGN(x,y) x + #define EXPORT + #define SERVER_EXPORT #endif #endif diff --git a/posix/JackFifo.cpp b/posix/JackFifo.cpp index d2528c4d..94d76fcf 100644 --- a/posix/JackFifo.cpp +++ b/posix/JackFifo.cpp @@ -121,28 +121,27 @@ bool JackFifo::Allocate(const char* name, const char* server_name, int value) { struct stat statbuf; BuildName(name, server_name, fName); - jack_log("JackFifo::Allocate name = %s", fName); - if (stat(fName, &statbuf)) { - if (errno == ENOENT) { + if (stat(fName, &statbuf) < 0) { + if (errno == ENOENT || errno == EPERM) { if (mkfifo(fName, 0666) < 0) { - jack_error("Cannot create inter-client FIFO [%s] (%s)\n", name, strerror(errno)); + jack_error("Cannot create inter-client FIFO name = %s err = %s", name, strerror(errno)); return false; } } else { - jack_error("Cannot check on FIFO %s\n", name); + jack_error("Cannot check on FIFO %s", name); return false; } } else { if (!S_ISFIFO(statbuf.st_mode)) { - jack_error("FIFO (%s) already exists, but is not a FIFO!\n", name); + jack_error("FIFO name = %s already exists, but is not a FIFO", name); return false; } } if ((fFifo = open(fName, O_RDWR | O_CREAT, 0666)) < 0) { - jack_error("Cannot open fifo [%s] (%s)", name, strerror(errno)); + jack_error("Cannot open FIFO name = %s err = %s", name, strerror(errno)); return false; } else { fPoll.fd = fFifo; diff --git a/posix/JackNetUnixSocket.cpp b/posix/JackNetUnixSocket.cpp index c6e9970a..7649ca8c 100644 --- a/posix/JackNetUnixSocket.cpp +++ b/posix/JackNetUnixSocket.cpp @@ -18,6 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "JackNetUnixSocket.h" +#include +#include namespace Jack { @@ -38,6 +40,7 @@ namespace Jack { fSockfd = 0; fPort = 0; + fTimeOut = 0; fSendAddr.sin_family = AF_INET; fSendAddr.sin_addr.s_addr = htonl ( INADDR_ANY ); memset ( &fSendAddr.sin_zero, 0, 8 ); @@ -50,6 +53,7 @@ namespace Jack { fSockfd = 0; fPort = port; + fTimeOut = 0; fSendAddr.sin_family = AF_INET; fSendAddr.sin_port = htons ( port ); inet_aton ( ip, &fSendAddr.sin_addr ); @@ -63,6 +67,7 @@ namespace Jack JackNetUnixSocket::JackNetUnixSocket ( const JackNetUnixSocket& socket ) { fSockfd = 0; + fTimeOut = 0; fPort = socket.fPort; fSendAddr = socket.fSendAddr; fRecvAddr = socket.fRecvAddr; @@ -212,6 +217,86 @@ namespace Jack } //timeout************************************************************************************************************ + +#if defined(__sun__) || defined(sun) + int JackNetUnixSocket::SetTimeOut ( int us ) + { + int flags; + fTimeOut = us; + + if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) { + jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL"); + return -1; + } + + flags |= O_NONBLOCK; + if (fcntl(fSockfd, F_SETFL, flags) < 0) { + jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL"); + return 1; + } + + return 0; + } + + int JackNetUnixSocket::WaitRead() + { + if (fTimeOut > 0) { + + struct timeval tv; + fd_set fdset; + ssize_t res; + + tv.tv_sec = fTimeOut / 1000000; + tv.tv_usec = fTimeOut % 1000000; + + FD_ZERO(&fdset); + FD_SET(fSockfd, &fdset); + + do { + res = select(fSockfd + 1, &fdset, NULL, NULL, &tv); + } while (res < 0 && errno == EINTR); + + if (res < 0) { + return res; + } else if (res == 0) { + errno = ETIMEDOUT; + return -1; + } + } + + return 0; + } + + int JackNetUnixSocket::WaitWrite() + { + if (fTimeOut > 0) { + + struct timeval tv; + fd_set fdset; + ssize_t res; + + tv.tv_sec = fTimeOut / 1000000; + tv.tv_usec = fTimeOut % 1000000; + + FD_ZERO(&fdset); + FD_SET(fSockfd, &fdset); + + do { + res = select(fSockfd + 1, NULL, &fdset, NULL, &tv); + } while (res < 0 && errno == EINTR); + + if (res < 0) { + return res; + } else if (res == 0) { + errno = ETIMEDOUT; + return -1; + } + } + + return 0; + } + +#else int JackNetUnixSocket::SetTimeOut ( int us ) { jack_log ( "JackNetUnixSocket::SetTimeout %d usecs", us ); @@ -237,6 +322,7 @@ namespace Jack } return SetOption ( SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof ( timeout ) ); } +#endif //local loop********************************************************************************************************** int JackNetUnixSocket::SetLocalLoop() @@ -248,6 +334,10 @@ namespace Jack //network operations************************************************************************************************** int JackNetUnixSocket::SendTo ( const void* buffer, size_t nbytes, int flags ) { + #if defined(__sun__) || defined(sun) + if (WaitWrite() < 0) + return -1; + #endif return sendto ( fSockfd, buffer, nbytes, flags, reinterpret_cast ( &fSendAddr ), sizeof ( socket_address_t ) ); } @@ -256,28 +346,48 @@ namespace Jack int addr_conv = inet_aton ( ip, &fSendAddr.sin_addr ); if ( addr_conv < 1 ) return addr_conv; + #if defined(__sun__) || defined(sun) + if (WaitWrite() < 0) + return -1; + #endif return SendTo ( buffer, nbytes, flags ); } int JackNetUnixSocket::Send ( const void* buffer, size_t nbytes, int flags ) { + #if defined(__sun__) || defined(sun) + if (WaitWrite() < 0) + return -1; + #endif return send ( fSockfd, buffer, nbytes, flags ); } int JackNetUnixSocket::RecvFrom ( void* buffer, size_t nbytes, int flags ) { socklen_t addr_len = sizeof ( socket_address_t ); + #if defined(__sun__) || defined(sun) + if (WaitRead() < 0) + return -1; + #endif return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast ( &fRecvAddr ), &addr_len ); } int JackNetUnixSocket::Recv ( void* buffer, size_t nbytes, int flags ) { + #if defined(__sun__) || defined(sun) + if (WaitRead() < 0) + return -1; + #endif return recv ( fSockfd, buffer, nbytes, flags ); } int JackNetUnixSocket::CatchHost ( void* buffer, size_t nbytes, int flags ) { socklen_t addr_len = sizeof ( socket_address_t ); + #if defined(__sun__) || defined(sun) + if (WaitRead() < 0) + return -1; + #endif return recvfrom ( fSockfd, buffer, nbytes, flags, reinterpret_cast ( &fSendAddr ), &addr_len ); } @@ -286,6 +396,7 @@ namespace Jack switch ( errno ) { case EAGAIN: + case ETIMEDOUT: return NET_NO_DATA; case ECONNABORTED: diff --git a/posix/JackNetUnixSocket.h b/posix/JackNetUnixSocket.h index fd639370..34e69b05 100644 --- a/posix/JackNetUnixSocket.h +++ b/posix/JackNetUnixSocket.h @@ -42,9 +42,14 @@ namespace Jack private: int fSockfd; int fPort; + int fTimeOut; struct sockaddr_in fSendAddr; struct sockaddr_in fRecvAddr; + #if defined(__sun__) || defined(sun) + int WaitRead(); + int WaitWrite(); + #endif public: JackNetUnixSocket(); JackNetUnixSocket ( const char* ip, int port ); diff --git a/posix/JackSocket.cpp b/posix/JackSocket.cpp index cc122042..989d6b55 100644 --- a/posix/JackSocket.cpp +++ b/posix/JackSocket.cpp @@ -18,18 +18,58 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "JackSocket.h" +#include "JackConstants.h" #include "JackTools.h" #include "JackError.h" #include #include #include +#include namespace Jack { -JackClientSocket::JackClientSocket(int socket): fSocket(socket) +JackClientSocket::JackClientSocket(int socket): fSocket(socket),fTimeOut(0) {} +#if defined(__sun__) || defined(sun) + +void JackClientSocket::SetReadTimeOut(long sec) +{ + int flags; + fTimeOut = sec; + + if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) { + jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_GETFL"); + return; + } + + flags |= O_NONBLOCK; + if (fcntl(fSocket, F_SETFL, flags) < 0) { + jack_error("JackClientSocket::SetReadTimeOut error in fcntl F_SETFL"); + return; + } +} + +void JackClientSocket::SetWriteTimeOut(long sec) +{ + int flags; + fTimeOut = sec; + + if ((flags = fcntl(fSocket, F_GETFL, 0)) < 0) { + jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_GETFL"); + return; + } + + flags |= O_NONBLOCK; + if (fcntl(fSocket, F_SETFL, flags) < 0) { + jack_error("JackClientSocket::SetWriteTimeOut error in fcntl F_SETFL"); + return; + } +} + +#else + void JackClientSocket::SetReadTimeOut(long sec) { struct timeval timout; @@ -50,11 +90,15 @@ void JackClientSocket::SetWriteTimeOut(long sec) } } +#endif + void JackClientSocket::SetNonBlocking(bool onoff) { - int flag = (onoff) ? 1 : 0; - if (ioctl(fSocket, FIONBIO, &flag) < 0) { - jack_error("SetNonBlocking fd = %ld err = %s", fSocket, strerror(errno)); + if (onoff) { + long flags = 0; + if (fcntl(fSocket, F_SETFL, flags | O_NONBLOCK) < 0) { + jack_error("SetNonBlocking fd = %ld err = %s", fSocket, strerror(errno)); + } } } @@ -131,11 +175,40 @@ int JackClientSocket::Close() int JackClientSocket::Read(void* data, int len) { - if (read(fSocket, data, len) != len) { - jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); + int res; + +#if defined(__sun__) || defined(sun) + if (fTimeOut > 0) { + + struct timeval tv; + fd_set fdset; + ssize_t res; + + tv.tv_sec = fTimeOut; + tv.tv_usec = 0; + + FD_ZERO(&fdset); + FD_SET(fSocket, &fdset); + + do { + res = select(fSocket + 1, &fdset, NULL, NULL, &tv); + } while (res < 0 && errno == EINTR); + + if (res < 0) { + return res; + } else if (res == 0) { + return -1; + } + } +#endif + + if ((res = read(fSocket, data, len)) != len) { if (errno == EWOULDBLOCK) { jack_error("JackClientSocket::Read time out"); return 0; // For a non blocking socket, a read failure is not considered as an error + } else if (res != 0) { + jack_error("Cannot read socket fd = %d err = %s", fSocket, strerror(errno)); + return 0; } else { return -1; } @@ -146,11 +219,40 @@ int JackClientSocket::Read(void* data, int len) int JackClientSocket::Write(void* data, int len) { - if (write(fSocket, data, len) != len) { - jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); + int res; + +#if defined(__sun__) || defined(sun) + if (fTimeOut > 0) { + + struct timeval tv; + fd_set fdset; + ssize_t res; + + tv.tv_sec = fTimeOut; + tv.tv_usec = 0; + + FD_ZERO(&fdset); + FD_SET(fSocket, &fdset); + + do { + res = select(fSocket + 1, NULL, &fdset, NULL, &tv); + } while (res < 0 && errno == EINTR); + + if (res < 0) { + return res; + } else if (res == 0) { + return -1; + } + } +#endif + + if ((res = write(fSocket, data, len)) != len) { if (errno == EWOULDBLOCK) { jack_log("JackClientSocket::Write time out"); return 0; // For a non blocking socket, a write failure is not considered as an error + } else if (res != 0) { + jack_error("Cannot write socket fd = %ld err = %s", fSocket, strerror(errno)); + return 0; } else { return -1; } diff --git a/posix/JackSocket.h b/posix/JackSocket.h index 04074b0b..2ccaf06d 100644 --- a/posix/JackSocket.h +++ b/posix/JackSocket.h @@ -42,10 +42,11 @@ class JackClientSocket private: int fSocket; - + int fTimeOut; + public: - JackClientSocket(): fSocket( -1) + JackClientSocket(): fSocket( -1),fTimeOut(0) {} JackClientSocket(int socket); diff --git a/posix/JackSocketServerChannel.cpp b/posix/JackSocketServerChannel.cpp index 42b02fcb..b04fdb0a 100644 --- a/posix/JackSocketServerChannel.cpp +++ b/posix/JackSocketServerChannel.cpp @@ -154,7 +154,8 @@ bool JackSocketServerChannel::HandleRequest(int fd) // Read header JackRequest header; if (header.Read(socket) < 0) { - jack_error("HandleRequest: cannot read header"); + jack_log("HandleRequest: cannot read header"); + ClientKill(fd); // TO CHECK SOLARIS return false; } @@ -391,7 +392,7 @@ bool JackSocketServerChannel::HandleRequest(int fd) } default: - jack_log("Unknown request %ld", header.fType); + jack_error("Unknown request %ld", header.fType); break; } @@ -449,7 +450,7 @@ bool JackSocketServerChannel::Execute() ClientKill(fd); } else if (fPollTable[i].revents & POLLIN) { if (!HandleRequest(fd)) - jack_error("Could not handle external client request"); + jack_log("Could not handle external client request"); } } diff --git a/solaris/JackAtomic_os.h b/solaris/JackAtomic_os.h new file mode 100644 index 00000000..c1368050 --- /dev/null +++ b/solaris/JackAtomic_os.h @@ -0,0 +1,32 @@ +/* +Copyright (C) 2004-2008 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __JackAtomic_sun__ +#define __JackAtomic_sun__ + +#include "JackTypes.h" +#include + +static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) +{ + return (atomic_cas_32((uint32_t*)addr, value, newvalue) == value); +} + +#endif + diff --git a/solaris/JackPlatformPlug_os.h b/solaris/JackPlatformPlug_os.h new file mode 100644 index 00000000..a244010a --- /dev/null +++ b/solaris/JackPlatformPlug_os.h @@ -0,0 +1,80 @@ +/* +Copyright (C) 2004-2008 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#ifndef __JackPlatformPlug_sun__ +#define __JackPlatformPlug_sun__ + +namespace Jack +{ + struct JackRequest; + struct JackResult; + + class JackPosixMutex; + class JackPosixThread; + class JackFifo; + + class JackSocketServerChannel; + class JackSocketClientChannel; + class JackSocketServerNotifyChannel; + class JackSocketNotifyChannel; + class JackClientSocket; + class JackNetUnixSocket; +} + +/* __JackPlatformMutex__ */ +#include "JackPosixMutex.h" +namespace Jack {typedef JackPosixMutex JackMutex; } + +/* __JackPlatformThread__ */ +#include "JackPosixThread.h" +namespace Jack { typedef JackPosixThread JackThread; } + +/* __JackPlatformSynchro__ client activation */ +#include "JackFifo.h" +namespace Jack { typedef JackFifo JackSynchro; } + +/* __JackPlatformChannelTransaction__ */ +#include "JackSocket.h" +namespace Jack { typedef JackClientSocket JackChannelTransaction; } + +#include "JackProcessSync.h" +/* __JackPlatformProcessSync__ */ +/* Only on windows a special JackProcessSync is used. It is directly defined by including JackProcessSync.h here */ + +/* __JackPlatformServerChannel__ */ +#include "JackSocketServerChannel.h" +namespace Jack { typedef JackSocketServerChannel JackServerChannel; } + +/* __JackPlatformClientChannel__ */ +#include "JackSocketClientChannel.h" +namespace Jack { typedef JackSocketClientChannel JackClientChannel; } + +/* __JackPlatformServerNotifyChannel__ */ +#include "JackSocketServerNotifyChannel.h" +namespace Jack { typedef JackSocketServerNotifyChannel JackServerNotifyChannel; } + +/* __JackPlatformNotifyChannel__ */ +#include "JackSocketNotifyChannel.h" +namespace Jack { typedef JackSocketNotifyChannel JackNotifyChannel; } + +/* __JackPlatformNetSocket__ */ +#include "JackNetUnixSocket.h" +namespace Jack { typedef JackNetUnixSocket JackNetSocket; } + +#endif diff --git a/solaris/JackSolarisTime.c b/solaris/JackSolarisTime.c new file mode 100644 index 00000000..0cff5fff --- /dev/null +++ b/solaris/JackSolarisTime.c @@ -0,0 +1,37 @@ +/* +Copyright (C) 2001-2003 Paul Davis +Copyright (C) 2004-2008 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "JackTime.h" +#include +#include + +SERVER_EXPORT void JackSleep(long usec) +{ + usleep(usec); +} + +SERVER_EXPORT void InitTime() +{} + +SERVER_EXPORT jack_time_t GetMicroSeconds(void) +{ + return (jack_time_t)(gethrtime() / 1000); +} + diff --git a/solaris/oss/JackOSSAdapter.cpp b/solaris/oss/JackOSSAdapter.cpp new file mode 100644 index 00000000..e74b7430 --- /dev/null +++ b/solaris/oss/JackOSSAdapter.cpp @@ -0,0 +1,766 @@ +/* +Copyright (C) 2008 Grame & RTL 2008 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "JackOSSAdapter.h" +#include "JackServerGlobals.h" +#include "JackEngineControl.h" +#include "memops.h" + +#include +#include +#include +#include +#include + +namespace Jack +{ + +inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; } + +static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits) +{ + switch (bits) { + + case 16: { + signed short *s16src = (signed short*)src; + s16src += channel; + sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1); + break; + } + case 24: { + signed short *s32src = (signed short*)src; + s32src += channel; + sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2); + break; + } + case 32: { + signed short *s32src = (signed short*)src; + s32src += channel; + sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2); + break; + } + } +} + +static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits) +{ + switch (bits) { + + case 16: { + signed short *s16dst = (signed short*)dst; + s16dst += channel; + sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now... + break; + } + case 24: { + signed int *s32dst = (signed int*)dst; + s32dst += channel; + sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now... + break; + } + case 32: { + signed int *s32dst = (signed int*)dst; + s32dst += channel; + sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); + break; + } + } +} + +void JackOSSAdapter::SetSampleFormat() +{ + switch (fBits) { + + case 24: /* native-endian LSB aligned 24-bits in 32-bits integer */ + fSampleFormat = AFMT_S24_NE; + fSampleSize = sizeof(int); + break; + case 32: /* native-endian 32-bit integer */ + fSampleFormat = AFMT_S32_NE; + fSampleSize = sizeof(int); + break; + case 16: /* native-endian 16-bit integer */ + default: + fSampleFormat = AFMT_S16_NE; + fSampleSize = sizeof(short); + break; + } +} + +JackOSSAdapter::JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params) + :JackAudioAdapterInterface(buffer_size, sample_rate) + ,fThread(this), + fInFD(-1), fOutFD(-1), fBits(OSS_DRIVER_DEF_BITS), + fSampleFormat(0), fNperiods(OSS_DRIVER_DEF_NPERIODS), fRWMode(0), fIgnoreHW(true), fExcl(false), + fInputBufferSize(0), fOutputBufferSize(0), + fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true) +{ + const JSList* node; + const jack_driver_param_t* param; + + fCaptureChannels = 2; + fPlaybackChannels = 2; + + strcpy(fCaptureDriverName, OSS_DRIVER_DEF_DEV); + strcpy(fPlaybackDriverName, OSS_DRIVER_DEF_DEV); + + for (node = params; node; node = jack_slist_next(node)) { + param = (const jack_driver_param_t*) node->data; + + switch (param->character) { + + case 'r': + SetAdaptedSampleRate(param->value.ui); + break; + + case 'p': + SetAdaptedBufferSize(param->value.ui); + break; + + case 'n': + fNperiods = param->value.ui; + break; + + case 'w': + fBits = param->value.i; + break; + + case 'i': + fCaptureChannels = param->value.ui; + break; + + case 'o': + fPlaybackChannels = param->value.ui; + break; + + case 'e': + fExcl = true; + break; + + case 'C': + fRWMode |= kRead; + if (strcmp(param->value.str, "none") != 0) { + strcpy(fCaptureDriverName, param->value.str); + } + break; + + case 'P': + fRWMode |= kWrite; + if (strcmp(param->value.str, "none") != 0) { + strcpy(fPlaybackDriverName, param->value.str); + } + break; + + case 'd': + fRWMode |= kRead; + fRWMode |= kWrite; + strcpy(fCaptureDriverName, param->value.str); + strcpy(fPlaybackDriverName, param->value.str); + break; + + case 'b': + fIgnoreHW = true; + break; + + case 'q': + fQuality = param->value.ui; + break; + + } + } + + fRWMode |= kRead; + fRWMode |= kWrite; +} + +void JackOSSAdapter::DisplayDeviceInfo() +{ + audio_buf_info info; + oss_audioinfo ai_in, ai_out; + memset(&info, 0, sizeof(audio_buf_info)); + int cap = 0; + + // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html + + jack_info("Audio Interface Description :"); + jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fAdaptedSampleRate, fSampleFormat, fRWMode); + + if (fRWMode & kWrite) { + + oss_sysinfo si; + if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) { + jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("OSS product %s", si.product); + jack_info("OSS version %s", si.version); + jack_info("OSS version num %d", si.versionnum); + jack_info("OSS numaudios %d", si.numaudios); + jack_info("OSS numaudioengines %d", si.numaudioengines); + jack_info("OSS numcards %d", si.numcards); + } + + jack_info("Output capabilities - %d channels : ", fPlaybackChannels); + jack_info("Output block size = %d", fOutputBufferSize); + + if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) { + jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d", + info.fragments, info.fragstotal, info.fragsize, info.bytes); + } + + if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) { + jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX"); + if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME"); + if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH"); + if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC"); + if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER"); + if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP"); + if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI"); + if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); + } + } + + if (fRWMode & kRead) { + + oss_sysinfo si; + if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) { + jack_error("JackOSSAdapter::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("OSS product %s", si.product); + jack_info("OSS version %s", si.version); + jack_info("OSS version num %d", si.versionnum); + jack_info("OSS numaudios %d", si.numaudios); + jack_info("OSS numaudioengines %d", si.numaudioengines); + jack_info("OSS numcards %d", si.numcards); + } + + jack_info("Input capabilities - %d channels : ", fCaptureChannels); + jack_info("Input block size = %d", fInputBufferSize); + + if (ioctl(fInFD, SNDCTL_DSP_GETOSPACE, &info) == -1) { + jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d", + info.fragments, info.fragstotal, info.fragsize, info.bytes); + } + + if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) { + jack_error("JackOSSAdapter::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX"); + if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME"); + if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH"); + if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC"); + if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER"); + if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP"); + if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI"); + if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); + } + } + + if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) { + jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name); + } + + if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) { + jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name); + } + + if (ai_in.rate_source != ai_out.rate_source) { + jack_info("Warning : input and output are not necessarily driven by the same clock!"); + } +} + +int JackOSSAdapter::OpenInput() +{ + int flags = 0; + int gFragFormat; + int cur_sample_format, cur_capture_channels; + jack_nframes_t cur_sample_rate; + + if (fCaptureChannels == 0) fCaptureChannels = 2; + + if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) { + jack_error("JackOSSAdapter::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + +jack_log("JackOSSAdapter::OpenInput input fInFD = %d", fInFD); + + if (fExcl) { + if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) { + jack_error("JackOSSAdapter::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + } + +printf("fAdaptedBufferSize %d %d %d %d %s\n", fExcl, fAdaptedBufferSize, fSampleSize, fCaptureChannels, fCaptureDriverName); + + gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fCaptureChannels); + if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) { + jack_error("JackOSSAdapter::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + cur_sample_format = fSampleFormat; + if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) { + jack_error("JackOSSAdapter::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_format != fSampleFormat) { + jack_info("JackOSSAdapter::OpenInput driver forced the sample format %ld", fSampleFormat); + } + + cur_capture_channels = fCaptureChannels; + if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) { + jack_error("JackOSSAdapter::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_capture_channels != fCaptureChannels) { + jack_info("JackOSSAdapter::OpenInput driver forced the number of capture channels %ld", fCaptureChannels); + } + + cur_sample_rate = fAdaptedSampleRate; + if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) { + jack_error("JackOSSAdapter::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_rate != fAdaptedSampleRate) { + jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate); + } + + fInputBufferSize = 0; + if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) { + jack_error("JackOSSAdapter::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (fInputBufferSize != fAdaptedBufferSize * fSampleSize * fCaptureChannels) { + if (fIgnoreHW) { + jack_info("JackOSSAdapter::OpenInput driver forced buffer size %ld", fOutputBufferSize); + } else { + jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained"); + goto error; + } + } + + fInputBuffer = (void*)calloc(fInputBufferSize, 1); + assert(fInputBuffer); + + fInputSampleBuffer = (float**)malloc(fCaptureChannels * sizeof(float*)); + assert(fInputSampleBuffer); + + for (int i = 0; i < fCaptureChannels; i++) { + fInputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float)); + assert(fInputSampleBuffer[i]); + } + return 0; + +error: + ::close(fInFD); + return -1; +} + +int JackOSSAdapter::OpenOutput() +{ + int flags = 0; + int gFragFormat; + int cur_sample_format, cur_playback_channels; + jack_nframes_t cur_sample_rate; + + if (fPlaybackChannels == 0) fPlaybackChannels = 2; + + if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) { + jack_error("JackOSSAdapter::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + + if (fExcl) { + if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) { + jack_error("JackOSSAdapter::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + } + +printf("fAdaptedBufferSize %d %d %d %d %s\n", fExcl, fAdaptedBufferSize, fSampleSize, fPlaybackChannels, fPlaybackDriverName); + + + gFragFormat = (2 << 16) + int2pow2(fAdaptedBufferSize * fSampleSize * fPlaybackChannels); + if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) { + jack_error("JackOSSAdapter::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + cur_sample_format = fSampleFormat; + if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) { + jack_error("JackOSSAdapter::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_format != fSampleFormat) { + jack_info("JackOSSAdapter::OpenOutput driver forced the sample format %ld", fSampleFormat); + } + + cur_playback_channels = fPlaybackChannels; + if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) { + jack_error("JackOSSAdapter::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_playback_channels != fPlaybackChannels) { + jack_info("JackOSSAdapter::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels); + } + + cur_sample_rate = fAdaptedSampleRate; + if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fAdaptedSampleRate) == -1) { + jack_error("JackOSSAdapter::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_rate != fAdaptedSampleRate) { + jack_info("JackOSSAdapter::OpenInput driver forced the sample rate %ld", fAdaptedSampleRate); + } + + fOutputBufferSize = 0; + if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) { + jack_error("JackOSSAdapter::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (fOutputBufferSize != fAdaptedBufferSize * fSampleSize * fPlaybackChannels) { + if (fIgnoreHW) { + jack_info("JackOSSAdapter::OpenOutput driver forced buffer size %ld", fOutputBufferSize); + } else { + jack_error("JackOSSAdapter::OpenInput wanted buffer size cannot be obtained"); + goto error; + } + } + + fOutputBuffer = (void*)calloc(fOutputBufferSize, 1); + assert(fOutputBuffer); + + fOutputSampleBuffer = (float**)malloc(fPlaybackChannels * sizeof(float*)); + assert(fOutputSampleBuffer); + + for (int i = 0; i < fPlaybackChannels; i++) { + fOutputSampleBuffer[i] = (float*)malloc(fAdaptedBufferSize * sizeof(float)); + assert(fOutputSampleBuffer[i]); + } + + fFirstCycle = true; + return 0; + +error: + ::close(fOutFD); + return -1; +} + +int JackOSSAdapter::Open() +{ + SetSampleFormat(); + + if ((fRWMode & kRead) && (OpenInput() < 0)) { + return -1; + } + + if ((fRWMode & kWrite) && (OpenOutput() < 0)) { + return -1; + } + + // In duplex mode, check that input and output use the same buffer size + if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) { + jack_error("JackOSSAdapter::OpenAux input and output buffer size are not the same!!"); + goto error; + } + + DisplayDeviceInfo(); + + fThread.AcquireRealTime(JackServerGlobals::fInstance->GetEngineControl()->fClientPriority); + return fThread.StartSync(); + +error: + CloseAux(); + return -1; +} + + +int JackOSSAdapter::Close() +{ +#ifdef DEBUG + fTable.Save(); +#endif + + fThread.Stop(); + CloseAux(); + return 0; +} + +void JackOSSAdapter::CloseAux() +{ + if (fRWMode & kRead) { + close(fInFD); + fInFD = -1; + } + + if (fRWMode & kWrite) { + close(fOutFD); + fOutFD = -1; + } + + free(fInputBuffer); + fInputBuffer = NULL; + + free(fOutputBuffer); + fOutputBuffer = NULL; + + for (int i = 0; i < fCaptureChannels; i++) { + free(fInputSampleBuffer[i]); + } + free(fInputSampleBuffer); + + for (int i = 0; i < fPlaybackChannels; i++) { + free(fOutputSampleBuffer[i]); + } + free(fOutputSampleBuffer); + } + +int JackOSSAdapter::Read() +{ + ssize_t count = ::read(fInFD, fInputBuffer, fInputBufferSize); + + if (count < fInputBufferSize) { + jack_error("JackOSSAdapter::Read error bytes read = %ld", count); + return -1; + } else { + for (int i = 0; i < fCaptureChannels; i++) { + CopyAndConvertIn(fInputSampleBuffer[i], fInputBuffer, fAdaptedBufferSize, i, fCaptureChannels, fBits); + } + return 0; + } +} + +int JackOSSAdapter::Write() +{ + ssize_t count; + + // Maybe necessay to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html + if (fFirstCycle) { + + fFirstCycle = false; + memset(fOutputBuffer, 0, fOutputBufferSize); + + // Prefill ouput buffer + for (int i = 0; i < fNperiods; i++) { + count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); + if (count < fOutputBufferSize) { + jack_error("JackOSSDriver::Write error bytes written = %ld", count); + return -1; + } + } + + int delay; + if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) { + jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + + delay /= fSampleSize * fPlaybackChannels; + jack_info("JackOSSDriver::Write output latency frames = %ld", delay); + } + + for (int i = 0; i < fPlaybackChannels; i++) { + CopyAndConvertOut(fOutputBuffer, fOutputSampleBuffer[i], fAdaptedBufferSize, i, fCaptureChannels, fBits); + } + + count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); + + if (count < fOutputBufferSize) { + jack_error("JackOSSAdapter::Write error bytes written = %ld", count); + return -1; + } else { + return 0; + } +} + +bool JackOSSAdapter::Execute() +{ + if (Read() < 0) + return false; + + bool failure = false; + jack_nframes_t time1, time2; + ResampleFactor(time1, time2); + + for (int i = 0; i < fCaptureChannels; i++) { + fCaptureRingBuffer[i]->SetRatio(time1, time2); + if (fCaptureRingBuffer[i]->WriteResample(fInputSampleBuffer[i], fAdaptedBufferSize) < fAdaptedBufferSize) + failure = true; + } + + for (int i = 0; i < fPlaybackChannels; i++) { + fPlaybackRingBuffer[i]->SetRatio(time2, time1); + if (fPlaybackRingBuffer[i]->ReadResample(fOutputSampleBuffer[i], fAdaptedBufferSize) < fAdaptedBufferSize) + failure = true; + } + +#ifdef DEBUG + fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1), + fCaptureRingBuffer[0]->ReadSpace(), fPlaybackRingBuffer[0]->WriteSpace()); +#endif + + if (Write() < 0) + return false; + + // Reset all ringbuffers in case of failure + if (failure) { + jack_error("JackOSSAdapter::Execute ringbuffer failure... reset"); + ResetRingBuffers(); + } + return true; +} + +int JackOSSAdapter::SetBufferSize(jack_nframes_t buffer_size) +{ + JackAudioAdapterInterface::SetBufferSize(buffer_size); + Close(); + return Open(); +} + +} // namespace + +#ifdef __cplusplus +extern "C" +{ +#endif + + SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor() + { + jack_driver_desc_t *desc; + unsigned int i; + desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); + + strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 + strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 + + desc->nparams = OSS_DRIVER_N_PARAMS; + desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); + + i = 0; + strcpy(desc->params[i].name, "rate"); + desc->params[i].character = 'r'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_FS; + strcpy(desc->params[i].short_desc, "Sample rate"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "period"); + desc->params[i].character = 'p'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE; + strcpy(desc->params[i].short_desc, "Frames per period"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "nperiods"); + desc->params[i].character = 'n'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS; + strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "wordlength"); + desc->params[i].character = 'w'; + desc->params[i].type = JackDriverParamInt; + desc->params[i].value.i = OSS_DRIVER_DEF_BITS; + strcpy(desc->params[i].short_desc, "Word length"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "inchannels"); + desc->params[i].character = 'i'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_INS; + strcpy(desc->params[i].short_desc, "Capture channels"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "outchannels"); + desc->params[i].character = 'o'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS; + strcpy(desc->params[i].short_desc, "Playback channels"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "excl"); + desc->params[i].character = 'e'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = false; + strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "capture"); + desc->params[i].character = 'C'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV); + strcpy(desc->params[i].short_desc, "Input device"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "playback"); + desc->params[i].character = 'P'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV); + strcpy(desc->params[i].short_desc, "Output device"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy (desc->params[i].name, "device"); + desc->params[i].character = 'd'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV); + strcpy(desc->params[i].short_desc, "OSS device name"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "ignorehwbuf"); + desc->params[i].character = 'b'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = true; + strcpy(desc->params[i].short_desc, "Ignore hardware period size"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "quality"); + desc->params[i].character = 'q'; + desc->params[i].type = JackDriverParamInt; + desc->params[i].value.ui = 0; + strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + return desc; + } + +#ifdef __cplusplus +} +#endif + diff --git a/solaris/oss/JackOSSAdapter.h b/solaris/oss/JackOSSAdapter.h new file mode 100644 index 00000000..1a6dbe21 --- /dev/null +++ b/solaris/oss/JackOSSAdapter.h @@ -0,0 +1,123 @@ +/* +Copyright (C) 2008 Grame & RTL 2008 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackOSSAdapter__ +#define __JackOSSAdapter__ + +#include +#include +#include +#include "JackAudioAdapterInterface.h" +#include "JackPlatformPlug.h" +#include "JackError.h" +#include "jack.h" +#include "jslist.h" + +namespace Jack +{ + +typedef jack_default_audio_sample_t jack_sample_t; + +#define OSS_DRIVER_N_PARAMS 12 +#define OSS_DRIVER_DEF_DEV "/dev/dsp" +#define OSS_DRIVER_DEF_FS 48000 +#define OSS_DRIVER_DEF_BLKSIZE 1024 +#define OSS_DRIVER_DEF_NPERIODS 2 +#define OSS_DRIVER_DEF_BITS 16 +#define OSS_DRIVER_DEF_INS 2 +#define OSS_DRIVER_DEF_OUTS 2 + +/*! +\brief The OSS adapter. +*/ + +class JackOSSAdapter : public JackAudioAdapterInterface, public JackRunnableInterface +{ + + enum { kRead = 1, kWrite = 2, kReadWrite = 3 }; + + private: + + JackThread fThread; + + char fCaptureDriverName[JACK_CLIENT_NAME_SIZE + 1]; + char fPlaybackDriverName[JACK_CLIENT_NAME_SIZE + 1]; + + int fInFD; + int fOutFD; + + int fBits; + int fSampleFormat; + int fNperiods; + unsigned int fSampleSize; + int fRWMode; + bool fIgnoreHW; + bool fExcl; + + unsigned int fInputBufferSize; + unsigned int fOutputBufferSize; + + void* fInputBuffer; + void* fOutputBuffer; + + float** fInputSampleBuffer; + float** fOutputSampleBuffer; + + bool fFirstCycle; + + int OpenInput(); + int OpenOutput(); + void CloseAux(); + void SetSampleFormat(); + void DisplayDeviceInfo(); + + public: + + JackOSSAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params); + ~JackOSSAdapter() + {} + + int Open(); + int Close(); + + int Read(); + int Write(); + + int SetBufferSize(jack_nframes_t buffer_size); + + bool Execute(); +}; + +} + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "JackCompilerDeps.h" +#include "driver_interface.h" + +EXPORT jack_driver_desc_t* jack_get_descriptor(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/solaris/oss/JackOSSDriver.cpp b/solaris/oss/JackOSSDriver.cpp new file mode 100644 index 00000000..5731d28a --- /dev/null +++ b/solaris/oss/JackOSSDriver.cpp @@ -0,0 +1,1010 @@ +/* +Copyright (C) 2003-2007 Jussi Laako +Copyright (C) 2008 Grame & RTL 2008 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "driver_interface.h" +#include "JackThreadedDriver.h" +#include "JackDriverLoader.h" +#include "JackOSSDriver.h" +#include "JackEngineControl.h" +#include "JackGraphManager.h" +#include "JackError.h" +#include "JackTime.h" +#include "JackShmMem.h" +#include "memops.h" + +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace Jack +{ + +#ifdef JACK_MONITOR + +#define CYCLE_POINTS 500000 + +struct OSSCycle { + jack_time_t fBeforeRead; + jack_time_t fAfterRead; + jack_time_t fAfterReadConvert; + jack_time_t fBeforeWrite; + jack_time_t fAfterWrite; + jack_time_t fBeforeWriteConvert; +}; + +struct OSSCycleTable { + jack_time_t fBeforeFirstWrite; + jack_time_t fAfterFirstWrite; + OSSCycle fTable[CYCLE_POINTS]; +}; + +OSSCycleTable gCycleTable; +int gCycleCount = 0; + +#endif + +inline int int2pow2(int x) { int r = 0; while ((1 << r) < x) r++; return r; } + +static inline void CopyAndConvertIn(jack_sample_t *dst, void *src, size_t nframes, int channel, int chcount, int bits) +{ + switch (bits) { + + case 16: { + signed short *s16src = (signed short*)src; + s16src += channel; + sample_move_dS_s16(dst, (char*)s16src, nframes, chcount<<1); + break; + } + case 24: { + signed short *s32src = (signed short*)src; + s32src += channel; + sample_move_dS_s24(dst, (char*)s32src, nframes, chcount<<2); + break; + } + case 32: { + signed short *s32src = (signed short*)src; + s32src += channel; + sample_move_dS_s32u24(dst, (char*)s32src, nframes, chcount<<2); + break; + } + } +} + +static inline void CopyAndConvertOut(void *dst, jack_sample_t *src, size_t nframes, int channel, int chcount, int bits) +{ + switch (bits) { + + case 16: { + signed short *s16dst = (signed short*)dst; + s16dst += channel; + sample_move_d16_sS((char*)s16dst, src, nframes, chcount<<1, NULL); // No dithering for now... + break; + } + case 24: { + signed int *s32dst = (signed int*)dst; + s32dst += channel; + sample_move_d24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); // No dithering for now... + break; + } + case 32: { + signed int *s32dst = (signed int*)dst; + s32dst += channel; + sample_move_d32u24_sS((char*)s32dst, src, nframes, chcount<<2, NULL); + break; + } + } +} + +void JackOSSDriver::SetSampleFormat() +{ + switch (fBits) { + + case 24: /* native-endian LSB aligned 24-bits in 32-bits integer */ + fSampleFormat = AFMT_S24_NE; + fSampleSize = sizeof(int); + break; + case 32: /* native-endian 32-bit integer */ + fSampleFormat = AFMT_S32_NE; + fSampleSize = sizeof(int); + break; + case 16: /* native-endian 16-bit integer */ + default: + fSampleFormat = AFMT_S16_NE; + fSampleSize = sizeof(short); + break; + } +} + +void JackOSSDriver::DisplayDeviceInfo() +{ + audio_buf_info info; + oss_audioinfo ai_in, ai_out; + memset(&info, 0, sizeof(audio_buf_info)); + int cap = 0; + + // Duplex cards : http://manuals.opensound.com/developer/full_duplex.html + jack_info("Audio Interface Description :"); + jack_info("Sampling Frequency : %d, Sample Format : %d, Mode : %d", fEngineControl->fSampleRate, fSampleFormat, fRWMode); + + if (fRWMode & kWrite) { + + oss_sysinfo si; + if (ioctl(fOutFD, OSS_SYSINFO, &si) == -1) { + jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("OSS product %s", si.product); + jack_info("OSS version %s", si.version); + jack_info("OSS version num %d", si.versionnum); + jack_info("OSS numaudios %d", si.numaudios); + jack_info("OSS numaudioengines %d", si.numaudioengines); + jack_info("OSS numcards %d", si.numcards); + } + + jack_info("Output capabilities - %d channels : ", fPlaybackChannels); + jack_info("Output block size = %d", fOutputBufferSize); + + if (ioctl(fOutFD, SNDCTL_DSP_GETOSPACE, &info) == -1) { + jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("output space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d", + info.fragments, info.fragstotal, info.fragsize, info.bytes); + } + + if (ioctl(fOutFD, SNDCTL_DSP_GETCAPS, &cap) == -1) { + jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX"); + if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME"); + if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH"); + if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC"); + if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER"); + if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP"); + if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI"); + if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); + } + } + + if (fRWMode & kRead) { + + oss_sysinfo si; + if (ioctl(fInFD, OSS_SYSINFO, &si) == -1) { + jack_error("JackOSSDriver::DisplayDeviceInfo OSS_SYSINFO failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("OSS product %s", si.product); + jack_info("OSS version %s", si.version); + jack_info("OSS version num %d", si.versionnum); + jack_info("OSS numaudios %d", si.numaudios); + jack_info("OSS numaudioengines %d", si.numaudioengines); + jack_info("OSS numcards %d", si.numcards); + } + + jack_info("Input capabilities - %d channels : ", fCaptureChannels); + jack_info("Input block size = %d", fInputBufferSize); + + if (ioctl(fInFD, SNDCTL_DSP_GETISPACE, &info) == -1) { + jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETOSPACE failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + jack_info("input space info: fragments = %d, fragstotal = %d, fragsize = %d, bytes = %d", + info.fragments, info.fragstotal, info.fragsize, info.bytes); + } + + if (ioctl(fInFD, SNDCTL_DSP_GETCAPS, &cap) == -1) { + jack_error("JackOSSDriver::DisplayDeviceInfo SNDCTL_DSP_GETCAPS failed : %s@%i, errno = %d", __FILE__, __LINE__, errno); + } else { + if (cap & DSP_CAP_DUPLEX) jack_info(" DSP_CAP_DUPLEX"); + if (cap & DSP_CAP_REALTIME) jack_info(" DSP_CAP_REALTIME"); + if (cap & DSP_CAP_BATCH) jack_info(" DSP_CAP_BATCH"); + if (cap & DSP_CAP_COPROC) jack_info(" DSP_CAP_COPROC"); + if (cap & DSP_CAP_TRIGGER) jack_info(" DSP_CAP_TRIGGER"); + if (cap & DSP_CAP_MMAP) jack_info(" DSP_CAP_MMAP"); + if (cap & DSP_CAP_MULTI) jack_info(" DSP_CAP_MULTI"); + if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); + } + } + /* + TODO + + ai_in.dev = fInFD; + jack_log("JackOSSDriver::DisplayDeviceInfo input fInFD = %d", ai_in.dev); + if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) { + jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name); + if (ai_in.iformats & AFMT_S24_NE) + jack_info("Available input format : AFMT_S24_NE"); + if (ai_in.iformats & AFMT_S16_NE) + jack_info("Available input format : AFMT_S16_NE"); + if (ai_in.iformats & AFMT_S32_NE) + jack_info("Available input format : AFMT_S32_NE"); + } + + ai_out.dev = fOutFD; + jack_log("JackOSSDriver::DisplayDeviceInfo output fOutFD = %d", ai_out.dev); + if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) { + jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name); + if (ai_out.oformats & AFMT_S24_NE) + jack_info("Available output format : AFMT_S24_NE"); + if (ai_out.oformats & AFMT_S16_NE) + jack_info("Available output format : AFMT_S16_NE"); + if (ai_out.oformats & AFMT_S32_NE) + jack_info("Available output format : AFMT_S32_NE"); + } + */ + + if (ai_in.rate_source != ai_out.rate_source) { + jack_info("Warning : input and output are not necessarily driven by the same clock!"); + } +} + +int JackOSSDriver::OpenInput() +{ + int flags = 0; + int gFragFormat; + int cur_capture_channels; + int cur_sample_format; + jack_nframes_t cur_sample_rate; + + if (fCaptureChannels == 0) fCaptureChannels = 2; + + if ((fInFD = open(fCaptureDriverName, O_RDONLY | ((fExcl) ? O_EXCL : 0))) < 0) { + jack_error("JackOSSDriver::OpenInput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + + jack_log("JackOSSDriver::OpenInput input fInFD = %d", fInFD); + + if (fExcl) { + if (ioctl(fInFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) { + jack_error("JackOSSDriver::OpenInput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + } + + gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fCaptureChannels); + if (ioctl(fInFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) { + jack_error("JackOSSDriver::OpenInput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + cur_sample_format = fSampleFormat; + if (ioctl(fInFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) { + jack_error("JackOSSDriver::OpenInput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_format != fSampleFormat) { + jack_info("JackOSSDriver::OpenInput driver forced the sample format %ld", fSampleFormat); + } + + cur_capture_channels = fCaptureChannels; + if (ioctl(fInFD, SNDCTL_DSP_CHANNELS, &fCaptureChannels) == -1) { + jack_error("JackOSSDriver::OpenInput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_capture_channels != fCaptureChannels) { + jack_info("JackOSSDriver::OpenInput driver forced the number of capture channels %ld", fCaptureChannels); + } + + cur_sample_rate = fEngineControl->fSampleRate; + if (ioctl(fInFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) { + jack_error("JackOSSDriver::OpenInput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_rate != fEngineControl->fSampleRate) { + jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate); + } + + fInputBufferSize = 0; + if (ioctl(fInFD, SNDCTL_DSP_GETBLKSIZE, &fInputBufferSize) == -1) { + jack_error("JackOSSDriver::OpenInput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (fInputBufferSize != fEngineControl->fBufferSize * fSampleSize * fCaptureChannels) { + if (fIgnoreHW) { + int new_buffer_size = fInputBufferSize / (fSampleSize * fCaptureChannels); + jack_info("JackOSSDriver::OpenInput driver forced buffer size %ld", new_buffer_size); + JackAudioDriver::SetBufferSize(new_buffer_size); // never fails + } else { + jack_error("JackOSSDriver::OpenInput wanted buffer size cannot be obtained"); + goto error; + } + } + + fInputBuffer = (void*)calloc(fInputBufferSize, 1); + assert(fInputBuffer); + return 0; + +error: + ::close(fInFD); + return -1; +} + +int JackOSSDriver::OpenOutput() +{ + int flags = 0; + int gFragFormat; + int cur_sample_format; + int cur_playback_channels; + jack_nframes_t cur_sample_rate; + + if (fPlaybackChannels == 0) fPlaybackChannels = 2; + + if ((fOutFD = open(fPlaybackDriverName, O_WRONLY | ((fExcl) ? O_EXCL : 0))) < 0) { + jack_error("JackOSSDriver::OpenOutput failed to open device : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + + jack_log("JackOSSDriver::OpenOutput output fOutFD = %d", fOutFD); + + if (fExcl) { + if (ioctl(fOutFD, SNDCTL_DSP_COOKEDMODE, &flags) == -1) { + jack_error("JackOSSDriver::OpenOutput failed to set cooked mode : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + } + + gFragFormat = (2 << 16) + int2pow2(fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels); + if (ioctl(fOutFD, SNDCTL_DSP_SETFRAGMENT, &gFragFormat) == -1) { + jack_error("JackOSSDriver::OpenOutput failed to set fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + cur_sample_format = fSampleFormat; + if (ioctl(fOutFD, SNDCTL_DSP_SETFMT, &fSampleFormat) == -1) { + jack_error("JackOSSDriver::OpenOutput failed to set format : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_format != fSampleFormat) { + jack_info("JackOSSDriver::OpenOutput driver forced the sample format %ld", fSampleFormat); + } + + cur_playback_channels = fPlaybackChannels; + if (ioctl(fOutFD, SNDCTL_DSP_CHANNELS, &fPlaybackChannels) == -1) { + jack_error("JackOSSDriver::OpenOutput failed to set channels : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_playback_channels != fPlaybackChannels) { + jack_info("JackOSSDriver::OpenOutput driver forced the number of playback channels %ld", fPlaybackChannels); + } + + cur_sample_rate = fEngineControl->fSampleRate; + if (ioctl(fOutFD, SNDCTL_DSP_SPEED, &fEngineControl->fSampleRate) == -1) { + jack_error("JackOSSDriver::OpenOutput failed to set sample rate : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + if (cur_sample_rate != fEngineControl->fSampleRate) { + jack_info("JackOSSDriver::OpenInput driver forced the sample rate %ld", fEngineControl->fSampleRate); + } + + fOutputBufferSize = 0; + if (ioctl(fOutFD, SNDCTL_DSP_GETBLKSIZE, &fOutputBufferSize) == -1) { + jack_error("JackOSSDriver::OpenOutput failed to get fragments : %s@%i, errno = %d", __FILE__, __LINE__, errno); + goto error; + } + + if (fOutputBufferSize != fEngineControl->fBufferSize * fSampleSize * fPlaybackChannels) { + if (fIgnoreHW) { + int new_buffer_size = fOutputBufferSize / (fSampleSize * fPlaybackChannels); + jack_info("JackOSSDriver::OpenOutput driver forced buffer size %ld", new_buffer_size); + JackAudioDriver::SetBufferSize(new_buffer_size); // never fails + } else { + jack_error("JackOSSDriver::OpenInput wanted buffer size cannot be obtained"); + goto error; + } + } + + fOutputBuffer = (void*)calloc(fOutputBufferSize, 1); + fFirstCycle = true; + assert(fOutputBuffer); + return 0; + +error: + ::close(fOutFD); + return -1; +} + +int JackOSSDriver::Open(jack_nframes_t nframes, + int user_nperiods, + jack_nframes_t samplerate, + bool capturing, + bool playing, + int inchannels, + int outchannels, + bool excl, + bool monitor, + const char* capture_driver_uid, + const char* playback_driver_uid, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency, + int bits, + bool ignorehwbuf) +{ + // Generic JackAudioDriver Open + if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, + capture_driver_uid, playback_driver_uid, capture_latency, playback_latency) != 0) { + return -1; + } else { + + if (!fEngineControl->fSyncMode) { + jack_error("Cannot run in asynchronous mode, use the -S parameter for jackd"); + return -1; + } + + fRWMode |= ((capturing) ? kRead : 0); + fRWMode |= ((playing) ? kWrite : 0); + fBits = bits; + fIgnoreHW = ignorehwbuf; + fNperiods = user_nperiods; + fExcl = excl; + + #ifdef JACK_MONITOR + // Force memory page in + memset(&gCycleTable, 0, sizeof(gCycleTable)); + #endif + + if (OpenAux() < 0) { + Close(); + return -1; + } else { + return 0; + } + } +} + +int JackOSSDriver::Close() +{ + #ifdef JACK_MONITOR + FILE* file = fopen("OSSProfiling.log", "w"); + + if (file) { + jack_info("Writing OSS driver timing data...."); + for (int i = 1; i < gCycleCount; i++) { + int d1 = gCycleTable.fTable[i].fAfterRead - gCycleTable.fTable[i].fBeforeRead; + int d2 = gCycleTable.fTable[i].fAfterReadConvert - gCycleTable.fTable[i].fAfterRead; + int d3 = gCycleTable.fTable[i].fAfterWrite - gCycleTable.fTable[i].fBeforeWrite; + int d4 = gCycleTable.fTable[i].fBeforeWrite - gCycleTable.fTable[i].fBeforeWriteConvert; + fprintf(file, "%d \t %d \t %d \t %d \t \n", d1, d2, d3, d4); + } + fclose(file); + } else { + jack_error("JackOSSDriver::Close : cannot open OSSProfiling.log file"); + } + + file = fopen("TimingOSS.plot", "w"); + + if (file == NULL) { + jack_error("JackOSSDriver::Close cannot open TimingOSS.plot file"); + } else { + + fprintf(file, "set grid\n"); + fprintf(file, "set title \"OSS audio driver timing\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \ + \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \ + \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \ + \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n"); + + fprintf(file, "set output 'TimingOSS.pdf\n"); + fprintf(file, "set terminal pdf\n"); + + fprintf(file, "set grid\n"); + fprintf(file, "set title \"OSS audio driver timing\"\n"); + fprintf(file, "set xlabel \"audio cycles\"\n"); + fprintf(file, "set ylabel \"usec\"\n"); + fprintf(file, "plot \"OSSProfiling.log\" using 1 title \"Driver read wait\" with lines, \ + \"OSSProfiling.log\" using 2 title \"Driver read convert duration\" with lines, \ + \"OSSProfiling.log\" using 3 title \"Driver write wait\" with lines, \ + \"OSSProfiling.log\" using 4 title \"Driver write convert duration\" with lines\n"); + + fclose(file); + } + #endif + int res = JackAudioDriver::Close(); + CloseAux(); + return res; +} + + +int JackOSSDriver::OpenAux() +{ + SetSampleFormat(); + + if ((fRWMode & kRead) && (OpenInput() < 0)) { + return -1; + } + + if ((fRWMode & kWrite) && (OpenOutput() < 0)) { + return -1; + } + + // In duplex mode, check that input and output use the same buffer size + if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) { + jack_error("JackOSSDriver::OpenAux input and output buffer size are not the same!!"); + return -1; + } + + DisplayDeviceInfo(); + return 0; +} + +void JackOSSDriver::CloseAux() +{ + if (fRWMode & kRead && fInFD > 0) { + close(fInFD); + fInFD = -1; + } + + if (fRWMode & kWrite && fOutFD > 0) { + close(fOutFD); + fOutFD = -1; + } + + if (fInputBuffer) + free(fInputBuffer); + fInputBuffer = NULL; + + if (fOutputBuffer) + free(fOutputBuffer); + fOutputBuffer = NULL; +} + +int JackOSSDriver::Read() +{ + if (fInFD < 0) { + // Keep begin cycle time + JackDriver::CycleTakeBeginTime(); + return 0; + } + + ssize_t count; +/* + // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html + if (fFirstCycle) { + + fFirstCycle = false; + memset(fOutputBuffer, 0, fOutputBufferSize); + + // Prefill ouput buffer + for (int i = 0; i < fNperiods; i++) { + count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); + if (count < fOutputBufferSize) { + jack_error("JackOSSDriver::Write error bytes written = %ld", count); + return -1; + } + } + + int delay; + if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) { + jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + + delay /= fSampleSize * fPlaybackChannels; + jack_info("JackOSSDriver::Write output latency frames = %ld", delay); + } +*/ + +#ifdef JACK_MONITOR + gCycleTable.fTable[gCycleCount].fBeforeRead = GetMicroSeconds(); +#endif + + audio_errinfo ei_in; + count = ::read(fInFD, fInputBuffer, fInputBufferSize); + +#ifdef JACK_MONITOR + if (count > 0 && count != fInputBufferSize) + jack_log("JackOSSDriver::Read count = %ld", count / (fSampleSize * fCaptureChannels)); + gCycleTable.fTable[gCycleCount].fAfterRead = GetMicroSeconds(); +#endif + + // XRun detection + if (ioctl(fInFD, SNDCTL_DSP_GETERROR, &ei_in) == 0) { + + if (ei_in.rec_overruns > 0 ) { + jack_error("JackOSSDriver::Read overruns"); + jack_time_t cur_time = GetMicroSeconds(); + NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... + } + + if (ei_in.rec_errorcount > 0 && ei_in.rec_lasterror != 0) { + jack_error("%d OSS rec event(s), last=%05d:%d", ei_in.rec_errorcount, ei_in.rec_lasterror, ei_in.rec_errorparm); + } + } + + if (count < 0) { + jack_log("JackOSSDriver::Read error = %s", strerror(errno)); + return -1; + } else if (count < fInputBufferSize) { + jack_error("JackOSSDriver::Read error bytes read = %ld", count); + return -1; + } else { + + // Keep begin cycle time + JackDriver::CycleTakeBeginTime(); + for (int i = 0; i < fCaptureChannels; i++) { + if (fGraphManager->GetConnectionsNum(fCapturePortList[i]) > 0) { + CopyAndConvertIn(GetInputBuffer(i), fInputBuffer, fEngineControl->fBufferSize, i, fCaptureChannels, fBits); + } + } + + #ifdef JACK_MONITOR + gCycleTable.fTable[gCycleCount].fAfterReadConvert = GetMicroSeconds(); + #endif + + return 0; + } +} + +int JackOSSDriver::Write() +{ + if (fOutFD < 0) { + // Keep end cycle time + JackDriver::CycleTakeEndTime(); + return 0; + } + + ssize_t count; + audio_errinfo ei_out; + + // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html + if (fFirstCycle) { + + fFirstCycle = false; + memset(fOutputBuffer, 0, fOutputBufferSize); + + // Prefill ouput buffer + for (int i = 0; i < fNperiods; i++) { + count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); + if (count < fOutputBufferSize) { + jack_error("JackOSSDriver::Write error bytes written = %ld", count); + return -1; + } + } + + int delay; + if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) { + jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno); + return -1; + } + + delay /= fSampleSize * fPlaybackChannels; + jack_info("JackOSSDriver::Write output latency frames = %ld", delay); + } + +#ifdef JACK_MONITOR + gCycleTable.fTable[gCycleCount].fBeforeWriteConvert = GetMicroSeconds(); +#endif + + memset(fOutputBuffer, 0, fOutputBufferSize); + for (int i = 0; i < fPlaybackChannels; i++) { + if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) { + CopyAndConvertOut(fOutputBuffer, GetOutputBuffer(i), fEngineControl->fBufferSize, i, fPlaybackChannels, fBits); + } + } + + #ifdef JACK_MONITOR + gCycleTable.fTable[gCycleCount].fBeforeWrite = GetMicroSeconds(); + #endif + + // Keep end cycle time + JackDriver::CycleTakeEndTime(); + count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); + + #ifdef JACK_MONITOR + if (count > 0 && count != fOutputBufferSize) + jack_log("JackOSSDriver::Write count = %ld", count / (fSampleSize * fPlaybackChannels)); + gCycleTable.fTable[gCycleCount].fAfterWrite = GetMicroSeconds(); + gCycleCount = (gCycleCount == CYCLE_POINTS - 1) ? gCycleCount: gCycleCount + 1; + #endif + + // XRun detection + if (ioctl(fOutFD, SNDCTL_DSP_GETERROR, &ei_out) == 0) { + + if (ei_out.play_underruns > 0) { + jack_error("JackOSSDriver::Write underruns"); + jack_time_t cur_time = GetMicroSeconds(); + NotifyXRun(cur_time, float(cur_time - fBeginDateUst)); // Better this value than nothing... + } + + if (ei_out.play_errorcount > 0 && ei_out.play_lasterror != 0) { + jack_error("%d OSS play event(s), last=%05d:%d",ei_out.play_errorcount, ei_out.play_lasterror, ei_out.play_errorparm); + } + } + + if (count < 0) { + jack_log("JackOSSDriver::Write error = %s", strerror(errno)); + return -1; + } else if (count < fOutputBufferSize) { + jack_error("JackOSSDriver::Write error bytes written = %ld", count); + return -1; + } else { + return 0; + } +} + +int JackOSSDriver::SetBufferSize(jack_nframes_t buffer_size) +{ + CloseAux(); + JackAudioDriver::SetBufferSize(buffer_size); // never fails + return OpenAux(); +} + +int JackOSSDriver::ProcessSync() +{ + // Read input buffers for the current cycle + if (Read() < 0) { + jack_error("ProcessSync: read error, skip cycle"); + return 0; // Skip cycle, but continue processing... + } + + if (fIsMaster) { + ProcessGraphSync(); + } else { + fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable); + } + + // Write output buffers for the current cycle + if (Write() < 0) { + jack_error("JackAudioDriver::ProcessSync: write error, skip cycle"); + return 0; // Skip cycle, but continue processing... + } + + return 0; +} + +} // end of namespace + +#ifdef __cplusplus +extern "C" +{ +#endif + +SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor() +{ + jack_driver_desc_t *desc; + unsigned int i; + desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t)); + + strcpy(desc->name, "oss"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 + strcpy(desc->desc, "OSS API based audio backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 + + desc->nparams = OSS_DRIVER_N_PARAMS; + desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t)); + + i = 0; + strcpy(desc->params[i].name, "rate"); + desc->params[i].character = 'r'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_FS; + strcpy(desc->params[i].short_desc, "Sample rate"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "period"); + desc->params[i].character = 'p'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_BLKSIZE; + strcpy(desc->params[i].short_desc, "Frames per period"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "nperiods"); + desc->params[i].character = 'n'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_NPERIODS; + strcpy(desc->params[i].short_desc, "Number of periods to prefill output buffer"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "wordlength"); + desc->params[i].character = 'w'; + desc->params[i].type = JackDriverParamInt; + desc->params[i].value.i = OSS_DRIVER_DEF_BITS; + strcpy(desc->params[i].short_desc, "Word length"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "inchannels"); + desc->params[i].character = 'i'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_INS; + strcpy(desc->params[i].short_desc, "Capture channels"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "outchannels"); + desc->params[i].character = 'o'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.ui = OSS_DRIVER_DEF_OUTS; + strcpy(desc->params[i].short_desc, "Playback channels"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "excl"); + desc->params[i].character = 'e'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = false; + strcpy(desc->params[i].short_desc, "Exclusif (O_EXCL) access mode"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "capture"); + desc->params[i].character = 'C'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV); + strcpy(desc->params[i].short_desc, "Input device"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "playback"); + desc->params[i].character = 'P'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV); + strcpy(desc->params[i].short_desc, "Output device"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy (desc->params[i].name, "device"); + desc->params[i].character = 'd'; + desc->params[i].type = JackDriverParamString; + strcpy(desc->params[i].value.str, OSS_DRIVER_DEF_DEV); + strcpy(desc->params[i].short_desc, "OSS device name"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "ignorehwbuf"); + desc->params[i].character = 'b'; + desc->params[i].type = JackDriverParamBool; + desc->params[i].value.i = TRUE; + strcpy(desc->params[i].short_desc, "Ignore hardware period size"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "input-latency"); + desc->params[i].character = 'I'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.i = 0; + strcpy(desc->params[i].short_desc, "Extra input latency"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + i++; + strcpy(desc->params[i].name, "output-latency"); + desc->params[i].character = 'O'; + desc->params[i].type = JackDriverParamUInt; + desc->params[i].value.i = 0; + strcpy(desc->params[i].short_desc, "Extra output latency"); + strcpy(desc->params[i].long_desc, desc->params[i].short_desc); + + return desc; +} + +EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) +{ + int bits = OSS_DRIVER_DEF_BITS; + jack_nframes_t srate = OSS_DRIVER_DEF_FS; + jack_nframes_t frames_per_interrupt = OSS_DRIVER_DEF_BLKSIZE; + const char* capture_pcm_name = OSS_DRIVER_DEF_DEV; + const char* playback_pcm_name = OSS_DRIVER_DEF_DEV; + bool capture = false; + bool playback = false; + int chan_in = 0; + int chan_out = 0; + bool monitor = false; + bool excl = false; + unsigned int nperiods = OSS_DRIVER_DEF_NPERIODS; + const JSList *node; + const jack_driver_param_t *param; + bool ignorehwbuf = false; + jack_nframes_t systemic_input_latency = 0; + jack_nframes_t systemic_output_latency = 0; + + for (node = params; node; node = jack_slist_next(node)) { + + param = (const jack_driver_param_t *)node->data; + + switch (param->character) { + + case 'r': + srate = param->value.ui; + break; + + case 'p': + frames_per_interrupt = (unsigned int)param->value.ui; + break; + + case 'n': + nperiods = (unsigned int)param->value.ui; + break; + + case 'w': + bits = param->value.i; + break; + + case 'i': + chan_in = (int)param->value.ui; + break; + + case 'o': + chan_out = (int)param->value.ui; + break; + + case 'C': + capture = true; + if (strcmp(param->value.str, "none") != 0) { + capture_pcm_name = strdup(param->value.str); + } + break; + + case 'P': + playback = true; + if (strcmp(param->value.str, "none") != 0) { + playback_pcm_name = strdup(param->value.str); + } + break; + + case 'd': + playback_pcm_name = strdup (param->value.str); + capture_pcm_name = strdup (param->value.str); + break; + + case 'b': + ignorehwbuf = true; + break; + + case 'e': + excl = true; + break; + + case 'I': + systemic_input_latency = param->value.ui; + break; + + case 'O': + systemic_output_latency = param->value.ui; + break; + } + } + + // duplex is the default + if (!capture && !playback) { + capture = true; + playback = true; + } + + Jack::JackOSSDriver* oss_driver = new Jack::JackOSSDriver("system", "oss", engine, table); + Jack::JackDriverClientInterface* threaded_driver = new Jack::JackThreadedDriver(oss_driver); + + // Special open for OSS driver... + if (oss_driver->Open(frames_per_interrupt, nperiods, srate, capture, playback, chan_in, chan_out, + excl, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency, bits, ignorehwbuf) == 0) { + return threaded_driver; + } else { + delete threaded_driver; // Delete the decorated driver + return NULL; + } +} + +#ifdef __cplusplus +} +#endif diff --git a/solaris/oss/JackOSSDriver.h b/solaris/oss/JackOSSDriver.h new file mode 100644 index 00000000..bedd72b7 --- /dev/null +++ b/solaris/oss/JackOSSDriver.h @@ -0,0 +1,126 @@ +/* +Copyright (C) 2003-2007 Jussi Laako +Copyright (C) 2008 Grame & RTL 2008 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __JackOSSDriver__ +#define __JackOSSDriver__ + +#include "JackAudioDriver.h" + +namespace Jack +{ + +typedef jack_default_audio_sample_t jack_sample_t; + +#define OSS_DRIVER_N_PARAMS 13 +#define OSS_DRIVER_DEF_DEV "/dev/dsp" +#define OSS_DRIVER_DEF_FS 48000 +#define OSS_DRIVER_DEF_BLKSIZE 1024 +#define OSS_DRIVER_DEF_NPERIODS 1 +#define OSS_DRIVER_DEF_BITS 16 +#define OSS_DRIVER_DEF_INS 2 +#define OSS_DRIVER_DEF_OUTS 2 + +/*! +\brief The OSS driver. +*/ + +class JackOSSDriver : public JackAudioDriver +{ + + enum { kRead = 1, kWrite = 2, kReadWrite = 3 }; + + private: + + int fInFD; + int fOutFD; + + int fBits; + int fSampleFormat; + int fNperiods; + unsigned int fSampleSize; + int fRWMode; + bool fExcl; + bool fIgnoreHW; + + unsigned int fInputBufferSize; + unsigned int fOutputBufferSize; + + void* fInputBuffer; + void* fOutputBuffer; + + bool fFirstCycle; + + int OpenInput(); + int OpenOutput(); + int OpenAux(); + void CloseAux(); + void SetSampleFormat(); + void DisplayDeviceInfo(); + + // Redefining since timing for CPU load is specific + int ProcessSync(); + + public: + + JackOSSDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackAudioDriver(name, alias, engine, table), + fInFD(-1), fOutFD(-1), fBits(0), + fSampleFormat(0), fNperiods(0), fRWMode(0), fExcl(false), fIgnoreHW(true), + fInputBufferSize(0), fOutputBufferSize(0), + fInputBuffer(NULL), fOutputBuffer(NULL), fFirstCycle(true) + {} + + virtual ~JackOSSDriver() + {} + + int Open(jack_nframes_t frames_per_cycle, + int user_nperiods, + jack_nframes_t rate, + bool capturing, + bool playing, + int chan_in, + int chan_out, + bool vmix, + bool monitor, + const char* capture_driver_name, + const char* playback_driver_name, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency, + int bits, + bool ignorehwbuf); + + int Close(); + + int Read(); + int Write(); + + // BufferSize can be changed + bool IsFixedBufferSize() + { + return false; + } + + int SetBufferSize(jack_nframes_t buffer_size); + +}; + +} // end of namespace + +#endif diff --git a/solaris/wscript b/solaris/wscript new file mode 100644 index 00000000..06bbe5b9 --- /dev/null +++ b/solaris/wscript @@ -0,0 +1,34 @@ +#! /usr/bin/env python +# encoding: utf-8 + +def create_jack_driver_obj(bld, target, sources, uselib = None): + driver = bld.new_task_gen('cxx', 'shlib') + driver.features.append('cc') + driver.env['shlib_PATTERN'] = 'jack_%s.so' + #driver.env.append_unique('CXXFLAGS', '-march=i686 -msse3 -ffast-math') + #driver.env.append_unique('CCFLAGS', '-march=i686 -msse3 -ffast-math') + driver.defines = 'HAVE_CONFIG_H' + driver.includes = ['.', '..','../posix', '../common', '../common/jack'] + driver.target = target + driver.source = sources + driver.install_path = '${ADDON_DIR}/' + driver.uselib_local = 'serverlib' + if uselib: + driver.uselib = uselib + return driver + +def build(bld): + jackd = bld.new_task_gen('cxx', 'program') + jackd.includes = ['.','..', '../posix', '../common/jack', '../common'] + jackd.defines = 'HAVE_CONFIG_H' + jackd.source = ['../common/Jackdmp.cpp'] + jackd.uselib = 'PTHREAD DL' + jackd.uselib_local = 'serverlib' + jackd.target = 'jackd' + + create_jack_driver_obj(bld, 'oss', ['oss/JackOSSDriver.cpp', '../common/memops.c']) + + create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') + + create_jack_driver_obj(bld, 'net', '../common/JackNetDriver.cpp') + diff --git a/svnversion_regenerate.sh b/svnversion_regenerate.sh index a765c31b..f98f977e 100755 --- a/svnversion_regenerate.sh +++ b/svnversion_regenerate.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash #set -x diff --git a/tests/wscript b/tests/wscript index a207c8f5..6693ebad 100644 --- a/tests/wscript +++ b/tests/wscript @@ -17,10 +17,12 @@ def build(bld): for test_program, test_program_sources in test_programs.items(): prog = bld.new_task_gen('cxx', 'program') prog.features.append('cc') - if bld.env['IS_MACOSX']: - prog.includes = ['../macosx', '../posix', '../common/jack', '../common'] - if bld.env['IS_LINUX']: - prog.includes = ['../linux', '../posix', '../common/jack', '../common'] + if bld.env['IS_MACOSX']: + prog.includes = ['..','../macosx', '../posix', '../common/jack', '../common'] + if bld.env['IS_LINUX']: + prog.includes = ['..','../linux', '../posix', '../common/jack', '../common'] + if bld.env['IS_SUN']: + prog.includes = ['..','../solaris', '../posix', '../common/jack', '../common'] prog.source = test_program_sources if bld.env['IS_LINUX']: prog.uselib = 'RT' diff --git a/windows/portaudio/JackPortAudioDriver.cpp b/windows/portaudio/JackPortAudioDriver.cpp index 9be7c761..01e3d943 100644 --- a/windows/portaudio/JackPortAudioDriver.cpp +++ b/windows/portaudio/JackPortAudioDriver.cpp @@ -180,10 +180,10 @@ error: int JackPortAudioDriver::Close() { - JackAudioDriver::Close(); + int res = JackAudioDriver::Close(); jack_log("JackPortAudioDriver::Close"); Pa_CloseStream(fStream); - return 0; + return res; } int JackPortAudioDriver::Start() @@ -348,7 +348,6 @@ extern "C" strcpy(desc->params[i].name, "device"); desc->params[i].character = 'd'; desc->params[i].type = JackDriverParamString; - desc->params[i].value.ui = 128U; strcpy(desc->params[i].value.str, "will take default PortAudio device name"); strcpy(desc->params[i].short_desc, "PortAudio device name"); strcpy(desc->params[i].long_desc, desc->params[i].short_desc); @@ -386,8 +385,8 @@ extern "C" jack_nframes_t frames_per_interrupt = 512; const char* capture_pcm_name = ""; const char* playback_pcm_name = ""; - int capture = FALSE; - int playback = FALSE; + bool capture = false; + bool playback = false; int chan_in = 0; int chan_out = 0; bool monitor = false; @@ -410,26 +409,25 @@ extern "C" break; case 'D': - capture = TRUE; - playback = TRUE; + capture = true; + playback = true; break; case 'c': - chan_in = chan_out = (int) param->value.ui; + chan_in = chan_out = (int)param->value.ui; break; case 'i': - chan_in = (int) param->value.ui; + chan_in = (int)param->value.ui; break; case 'o': - chan_out = (int) param->value.ui; + chan_out = (int)param->value.ui; break; case 'C': - capture = TRUE; - if (strcmp(param->value.str, "none") != 0) - { + capture = true; + if (strcmp(param->value.str, "none") != 0) { capture_pcm_name = strdup(param->value.str); } break; @@ -450,7 +448,7 @@ extern "C" break; case 'p': - frames_per_interrupt = (unsigned int) param->value.ui; + frames_per_interrupt = (unsigned int)param->value.ui; break; case 'I': @@ -469,8 +467,8 @@ extern "C" // duplex is the default if (!capture && !playback) { - capture = TRUE; - playback = TRUE; + capture = true; + playback = true; } Jack::JackDriverClientInterface* driver = new Jack::JackPortAudioDriver("system", "portaudio", engine, table, pa_devices); diff --git a/wscript b/wscript index b37a93b5..cb44a74a 100644 --- a/wscript +++ b/wscript @@ -63,7 +63,9 @@ def set_options(opt): opt.add_option('--libdir', type='string', help="Library directory [Default: /lib]") opt.add_option('--dbus', action='store_true', default=False, help='Enable D-Bus JACK (jackdbus)') opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation') - opt.add_option('--monitor', action='store_true', default=False, help='Build with monitoring records') + opt.add_option('--profile', action='store_true', default=False, help='Build with engine profiling') + opt.add_option('--clients', default=64, type="int", dest="clients", help='Maximum number of JACK clients') + opt.add_option('--ports', default=512, type="int", dest="ports", help='Maximum number of ports') opt.add_option('--clients', default=64, type="int", dest="clients", help='Maximum number of JACK clients') opt.add_option('--ports', default=512, type="int", dest="ports", help='Maximum number of ports') opt.sub_options('dbus') @@ -72,6 +74,7 @@ def configure(conf): platform = Utils.detect_platform() conf.env['IS_MACOSX'] = platform == 'darwin' conf.env['IS_LINUX'] = platform == 'linux' + conf.env['IS_SUN'] = platform == 'sunos' if conf.env['IS_LINUX']: Utils.pprint('CYAN', "Linux detected") @@ -79,9 +82,26 @@ def configure(conf): if conf.env['IS_MACOSX']: Utils.pprint('CYAN', "MacOS X detected") - conf.check_tool('compiler_cxx') - conf.check_tool('compiler_cc') + if conf.env['IS_SUN']: + Utils.pprint('CYAN', "SunOS detected") + if conf.env['IS_LINUX']: + conf.check_tool('compiler_cxx') + conf.check_tool('compiler_cc') + + if conf.env['IS_MACOSX']: + conf.check_tool('compiler_cxx') + conf.check_tool('compiler_cc') + + # waf 1.5 : check_tool('compiler_cxx') and check_tool('compiler_cc') do not work correctly, so explicit use of gcc and g++ + if conf.env['IS_SUN']: + conf.check_tool('g++') + conf.check_tool('gcc') + + #if conf.env['IS_SUN']: + # conf.check_tool('compiler_cxx') + # conf.check_tool('compiler_cc') + conf.env.append_unique('CXXFLAGS', '-O3 -Wall') conf.env.append_unique('CCFLAGS', '-O3 -Wall') @@ -99,7 +119,7 @@ def configure(conf): conf.env['JACK_VERSION'] = VERSION conf.env['BUILD_DOXYGEN_DOCS'] = Options.options.doxygen - conf.env['BUILD_WITH_MONITOR'] = Options.options.monitor + conf.env['BUILD_WITH_PROFILE'] = Options.options.profile if Options.options.libdir: conf.env['LIBDIR'] = Options.options.libdir @@ -115,7 +135,7 @@ def configure(conf): conf.define('JACKMP', 1) if conf.env['BUILD_JACKDBUS'] == True: conf.define('JACK_DBUS', 1) - if conf.env['BUILD_WITH_MONITOR'] == True: + if conf.env['BUILD_WITH_PROFILE'] == True: conf.define('JACK_MONITOR', 1) conf.write_config_header('config.h') @@ -142,7 +162,8 @@ def configure(conf): display_msg("Library directory", conf.env['LIBDIR'], 'CYAN') display_msg("Drivers directory", conf.env['ADDON_DIR'], 'CYAN') display_feature('Build doxygen documentation', conf.env['BUILD_DOXYGEN_DOCS']) - display_feature('Build with monitoring records', conf.env['BUILD_WITH_MONITOR']) + display_feature('Build with engine profiling', conf.env['BUILD_WITH_PROFILE']) + if conf.env['IS_LINUX']: display_feature('Build with ALSA support', conf.env['BUILD_DRIVER_ALSA'] == True) @@ -171,14 +192,15 @@ def build(bld): if not os.access('svnversion.h', os.R_OK): create_svnversion_task(bld) - # process subfolders from here + # process subfolders from here bld.add_subdirs('common') if bld.env['IS_LINUX']: bld.add_subdirs('linux') - if bld.env['BUILD_JACKDBUS'] == True: - bld.add_subdirs('dbus') bld.add_subdirs('example-clients') bld.add_subdirs('tests') + if bld.env['BUILD_JACKDBUS'] == True: + bld.add_subdirs('dbus') + if bld.env['IS_MACOSX']: bld.add_subdirs('macosx') bld.add_subdirs('example-clients') @@ -186,6 +208,13 @@ def build(bld): if bld.env['BUILD_JACKDBUS'] == True: bld.add_subdirs('dbus') + if bld.env['IS_SUN']: + bld.add_subdirs('solaris') + bld.add_subdirs('example-clients') + bld.add_subdirs('tests') + if bld.env['BUILD_JACKDBUS'] == True: + bld.add_subdirs('dbus') + if bld.env['BUILD_DOXYGEN_DOCS'] == True: share_dir = bld.env.get_destdir() + bld.env['PREFIX'] + '/share/jack-audio-connection-kit' html_docs_source_dir = "build/default/html"