| @@ -0,0 +1,14 @@ | |||
| .PHONY: all | |||
| all: | |||
| CC=${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-gcc CXX=${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++ AR=${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-ar LDFLAGS="-L${INSTALL_ROOT_nto}/aarch64le/lib -L${INSTALL_ROOT_nto}/aarch64le/usr/lib -L${QNX_TARGET}/aarch64le/lib -L${QNX_TARGET}/aarch64le/usr/lib" PKG_CONFIG_LIBDIR=${INSTALL_ROOT_nto}/aarch64le/usr/lib/pkgconfig ./waf configure --platform=qnx --prefix=/usr --libdir=/usr/lib64 | |||
| ./waf build | |||
| ./waf install --destdir=${INSTALL_ROOT_nto}/aarch64le | |||
| .PHONY: install | |||
| install: all | |||
| .PHONY:clean | |||
| clean: | |||
| # ignore error codes otherwise it would for example fail if clean is called before configure | |||
| -./waf clean | |||
| @@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #endif | |||
| #include "JackAudioAdapter.h" | |||
| #ifndef MY_TARGET_OS_IPHONE | |||
| #if !defined(MY_TARGET_OS_IPHONE) && !defined(__QNXNTO__) | |||
| #include "JackLibSampleRateResampler.h" | |||
| #endif | |||
| #include "JackTime.h" | |||
| @@ -185,7 +185,7 @@ namespace Jack | |||
| fRunning = false; | |||
| } | |||
| #ifdef MY_TARGET_OS_IPHONE | |||
| #if defined(MY_TARGET_OS_IPHONE) || defined(__QNXNTO__) | |||
| void JackAudioAdapterInterface::Create() | |||
| {} | |||
| #else | |||
| @@ -34,6 +34,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
| using namespace std; | |||
| #ifdef __QNXNTO__ | |||
| void __attribute__((constructor)) init_output_for_percent_s_NULL_for_clients(); | |||
| void init_output_for_percent_s_NULL_for_clients() | |||
| { | |||
| extern const char *output_for_percent_s_NULL; | |||
| output_for_percent_s_NULL = "(null)"; | |||
| } | |||
| #endif | |||
| namespace Jack | |||
| { | |||
| @@ -663,7 +663,10 @@ jackctl_setup_signals( | |||
| sigfillset(&allsignals); | |||
| action.sa_handler = signal_handler; | |||
| action.sa_mask = allsignals; | |||
| action.sa_flags = SA_RESTART|SA_RESETHAND; | |||
| action.sa_flags = SA_RESETHAND; | |||
| #ifndef __QNXNTO__ | |||
| action.sa_flags |= SA_RESTART; | |||
| #endif | |||
| for (i = 1; i < NSIG; i++) | |||
| { | |||
| @@ -107,7 +107,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #endif /* _WIN32 && !__CYGWIN__ && !GNU_WIN32 */ | |||
| #if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) | |||
| #if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) || defined(__QNXNTO__) | |||
| #if defined(__CYGWIN__) || defined(GNU_WIN32) | |||
| #include <stdint.h> | |||
| @@ -428,7 +428,9 @@ netjack_poll (int sockfd, int timeout) | |||
| action.sa_handler = SIG_DFL; | |||
| action.sa_mask = sigmask; | |||
| #ifndef __QNXNTO__ | |||
| action.sa_flags = SA_RESTART; | |||
| #endif | |||
| for (i = 1; i < NSIG; i++) | |||
| if (sigismember (&sigmask, i)) | |||
| @@ -49,11 +49,16 @@ | |||
| #include <sys/mman.h> | |||
| #include <sys/types.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/shm.h> | |||
| #include <sys/sem.h> | |||
| #include <stdlib.h> | |||
| #include "promiscuous.h" | |||
| #ifdef __QNXNTO__ | |||
| #include <sys/mman.h> | |||
| #else | |||
| #include <sys/shm.h> | |||
| #endif | |||
| #endif | |||
| #include "shm.h" | |||
| @@ -148,8 +153,6 @@ static jack_shm_registry_t *jack_shm_registry = NULL; | |||
| #define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY | |||
| #endif | |||
| static int semid = -1; | |||
| #ifdef WIN32 | |||
| #include <psapi.h> | |||
| @@ -178,12 +181,61 @@ static BOOL check_process_running(DWORD process_id) | |||
| } | |||
| static int | |||
| semaphore_init () {return 0;} | |||
| jack_shm_lock_registry () {return 0;} | |||
| static void | |||
| jack_shm_unlock_registry () { } | |||
| #elif __QNXNTO__ | |||
| #include <semaphore.h> | |||
| static sem_t* semid = SEM_FAILED; | |||
| static int | |||
| semaphore_init () | |||
| { | |||
| const char name[] = "/jack-shm-registry-lock"; | |||
| const int oflag = O_CREAT | O_RDWR; | |||
| const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; | |||
| if ((semid = sem_open(name, oflag, mode, 1)) == SEM_FAILED) { | |||
| jack_error("Creating semaphore %s failed", name); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| static int | |||
| jack_shm_lock_registry (void) | |||
| { | |||
| if (semid == SEM_FAILED) { | |||
| if (semaphore_init () < 0) | |||
| return -1; | |||
| } | |||
| // TODO automatically unblock in case the process terminates | |||
| const int ret = sem_wait(semid); | |||
| if (ret < 0) { | |||
| jack_error("sem_wait() failed with %s", strerror(ret)); | |||
| return -1; | |||
| } | |||
| static int | |||
| semaphore_add (int value) {return 0;} | |||
| return 0; | |||
| } | |||
| static void | |||
| jack_shm_unlock_registry (void) | |||
| { | |||
| const int ret = sem_post(semid); | |||
| if (ret < 0) { | |||
| jack_error("sem_post() failed with %s", strerror(ret)); | |||
| } | |||
| } | |||
| #else | |||
| static int semid = -1; | |||
| /* all semaphore errors are fatal -- issue message, but do not return */ | |||
| static void | |||
| semaphore_error (char *msg) | |||
| @@ -247,8 +299,6 @@ semaphore_add (int value) | |||
| return 0; | |||
| } | |||
| #endif | |||
| static int | |||
| jack_shm_lock_registry (void) | |||
| { | |||
| @@ -266,6 +316,8 @@ jack_shm_unlock_registry (void) | |||
| semaphore_add (1); | |||
| } | |||
| #endif | |||
| static void | |||
| jack_shm_init_registry () | |||
| { | |||
| @@ -1308,4 +1360,3 @@ jack_attach_shm_read (jack_shm_info_t* si) | |||
| } | |||
| #endif /* !USE_POSIX_SHM */ | |||
| @@ -28,6 +28,8 @@ def create_jack_process_obj(bld, target, sources, uselib = None, framework = Non | |||
| env_includes = ['../macosx', '../posix', '../macosx/coreaudio'] | |||
| if bld.env['IS_LINUX']: | |||
| env_includes = ['../linux', '../posix', '../linux/alsa'] | |||
| if bld.env['IS_QNX']: | |||
| env_includes = ['../qnx', '../posix'] | |||
| if bld.env['IS_SUN']: | |||
| env_includes = ['../solaris', '../posix', '../solaris/oss'] | |||
| if bld.env['IS_WINDOWS']: | |||
| @@ -36,7 +38,7 @@ def create_jack_process_obj(bld, target, sources, uselib = None, framework = Non | |||
| process.name = target | |||
| process.target = target | |||
| process.source = sources | |||
| if bld.env['IS_LINUX'] or bld.env['IS_MACOSX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_MACOSX'] or bld.env['IS_QNX']: | |||
| process.env.append_value('CPPFLAGS', '-fvisibility=hidden') | |||
| process.install_path = '${ADDON_DIR}/' | |||
| process.use = [uselib.name] | |||
| @@ -92,6 +94,22 @@ def build(bld): | |||
| uselib.append('RT') | |||
| uselib.append('DL') | |||
| if bld.env['IS_QNX']: | |||
| common_libsources += [ | |||
| 'JackDebugClient.cpp', | |||
| 'timestamps.c', | |||
| 'promiscuous.c', | |||
| '../posix/JackPosixThread.cpp', | |||
| '../posix/JackPosixProcessSync.cpp', | |||
| '../posix/JackPosixMutex.cpp', | |||
| '../posix/JackSocket.cpp', | |||
| '../posix/JackFifo.cpp', | |||
| '../linux/JackLinuxTime.c', | |||
| ] | |||
| includes = ['../qnx', '../posix'] + includes | |||
| uselib.append('SOCKET') | |||
| # libdl and librt is included in libc in QNX | |||
| if bld.env['IS_SUN']: | |||
| common_libsources += [ | |||
| 'JackDebugClient.cpp', | |||
| @@ -163,7 +181,7 @@ def build(bld): | |||
| 'JackMetadata.cpp', | |||
| ] | |||
| if bld.env['IS_LINUX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_QNX']: | |||
| clientlib.source += [ | |||
| '../posix/JackSocketClientChannel.cpp', | |||
| '../posix/JackPosixServerLaunch.cpp', | |||
| @@ -192,7 +210,7 @@ def build(bld): | |||
| if not bld.env['IS_WINDOWS']: | |||
| clientlib.vnum = bld.env['JACK_API_VERSION'] | |||
| if bld.env['IS_LINUX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_QNX']: | |||
| clientlib.env.append_value('CPPFLAGS', '-fvisibility=hidden') | |||
| if bld.env['IS_MACOSX']: | |||
| @@ -270,7 +288,7 @@ def build(bld): | |||
| 'JackMetadata.cpp', | |||
| ] | |||
| if bld.env['IS_LINUX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_QNX']: | |||
| serverlib.source += [ | |||
| '../posix/JackSocketServerChannel.cpp', | |||
| '../posix/JackSocketNotifyChannel.cpp', | |||
| @@ -307,7 +325,7 @@ def build(bld): | |||
| if not bld.env['IS_WINDOWS']: | |||
| serverlib.vnum = bld.env['JACK_API_VERSION'] | |||
| if bld.env['IS_LINUX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_QNX']: | |||
| serverlib.env.append_value('CPPFLAGS', '-fvisibility=hidden') | |||
| if bld.env['IS_MACOSX']: | |||
| @@ -333,7 +351,7 @@ def build(bld): | |||
| if skipshared: | |||
| netlib.env['SHLIB_MARKER'] = '' | |||
| netlib.use += ['WS2_32', 'WINMM'] | |||
| elif not bld.env['IS_MACOSX']: | |||
| elif not bld.env['IS_MACOSX'] and not bld.env['IS_QNX']: | |||
| netlib.use += ['RT'] | |||
| netlib.install_path = '${LIBDIR}' | |||
| netlib.source = [ | |||
| @@ -347,7 +365,7 @@ def build(bld): | |||
| 'JackGlobals.cpp', | |||
| 'ringbuffer.c'] | |||
| if bld.env['IS_LINUX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_QNX']: | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../linux/JackLinuxTime.c'] | |||
| netlib.env.append_value('CPPFLAGS', '-fvisibility=hidden') | |||
| @@ -49,6 +49,8 @@ def build(bld): | |||
| os_incdir = ['../linux', '../posix'] | |||
| if bld.env['IS_MACOSX']: | |||
| os_incdir = ['../macosx', '../posix'] | |||
| if bld.env['IS_QNX']: | |||
| os_incdir = ['../qnx', '../posix'] | |||
| if bld.env['IS_SUN']: | |||
| os_incdir = ['../solaris', '../posix'] | |||
| if bld.env['IS_WINDOWS']: | |||
| @@ -76,7 +78,7 @@ def build(bld): | |||
| prog.use = use | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'M'] | |||
| if bld.env['IS_SUN']: | |||
| if bld.env['IS_SUN'] or bld.env['IS_QNX']: | |||
| prog.use += ['M'] | |||
| #prog.cflags = ['-Wno-deprecated-declarations', '-Wno-misleading-indentation'] | |||
| #prog.cxxflags = ['-Wno-deprecated-declarations', '-Wno-misleading-indentation'] | |||
| @@ -90,7 +92,7 @@ def build(bld): | |||
| prog.use = ['clientlib'] | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'READLINE'] | |||
| if bld.env['IS_MACOSX']: | |||
| if bld.env['IS_MACOSX'] or bld.env['IS_QNX']: | |||
| prog.use += ['READLINE'] | |||
| if bld.env['IS_WINDOWS']: | |||
| prog.use += ['READLINE'] | |||
| @@ -101,7 +103,7 @@ def build(bld): | |||
| prog.includes = os_incdir + ['../common/jack', '../common'] | |||
| prog.source = 'capture_client.c' | |||
| prog.use = ['clientlib'] | |||
| if bld.env['IS_MACOSX']: | |||
| if bld.env['IS_MACOSX'] or bld.env['IS_QNX']: | |||
| prog.use += ['SNDFILE'] | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'SNDFILE'] | |||
| @@ -111,7 +113,7 @@ def build(bld): | |||
| prog.uselib = ['SNDFILE'] | |||
| prog.target = 'jack_rec' | |||
| if bld.env['IS_LINUX'] or bld.env['IS_MACOSX']: | |||
| if bld.env['IS_LINUX'] or bld.env['IS_MACOSX'] or bld.env['IS_QNX']: | |||
| prog = bld(features = 'c cprogram') | |||
| prog.includes = os_incdir + ['.', '..', '../common/jack', '../common'] | |||
| prog.source = ['netsource.c', '../common/netjack_packet.c'] | |||
| @@ -204,6 +204,7 @@ int JackAlsaDriver::Detach() | |||
| return JackAudioDriver::Detach(); | |||
| } | |||
| #ifndef __QNXNTO__ | |||
| extern "C" char* get_control_device_name(const char * device_name) | |||
| { | |||
| char * ctl_name; | |||
| @@ -233,7 +234,9 @@ extern "C" char* get_control_device_name(const char * device_name) | |||
| return ctl_name; | |||
| } | |||
| #endif | |||
| #ifndef __QNXNTO__ | |||
| static int card_to_num(const char* device) | |||
| { | |||
| int err; | |||
| @@ -273,6 +276,7 @@ free: | |||
| fail: | |||
| return i; | |||
| } | |||
| #endif | |||
| int JackAlsaDriver::Open(jack_nframes_t nframes, | |||
| jack_nframes_t user_nperiods, | |||
| @@ -301,6 +305,8 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||
| } | |||
| alsa_midi_t *midi = 0; | |||
| #ifndef __QNXNTO__ | |||
| #ifndef __ANDROID__ | |||
| if (strcmp(midi_driver_name, "seq") == 0) | |||
| midi = alsa_seqmidi_new((jack_client_t*)this, 0); | |||
| @@ -333,6 +339,7 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| fDriver = alsa_driver_new ((char*)"alsa_pcm", (char*)playback_driver_name, (char*)capture_driver_name, | |||
| NULL, | |||
| @@ -356,12 +363,14 @@ int JackAlsaDriver::Open(jack_nframes_t nframes, | |||
| // ALSA driver may have changed the in/out values | |||
| fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels; | |||
| fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels; | |||
| #ifndef __QNXNTO__ | |||
| if (JackServerGlobals::on_device_reservation_loop != NULL) { | |||
| device_reservation_loop_running = true; | |||
| if (JackPosixThread::StartImp(&fReservationLoopThread, 0, 0, on_device_reservation_loop, NULL) != 0) { | |||
| device_reservation_loop_running = false; | |||
| } | |||
| } | |||
| #endif | |||
| return 0; | |||
| } else { | |||
| Close(); | |||
| @@ -378,6 +387,7 @@ int JackAlsaDriver::Close() | |||
| alsa_driver_delete((alsa_driver_t*)fDriver); | |||
| } | |||
| #ifndef __QNXNTO__ | |||
| if (device_reservation_loop_running) { | |||
| device_reservation_loop_running = false; | |||
| JackPosixThread::StopImp(fReservationLoopThread); | |||
| @@ -398,6 +408,7 @@ int JackAlsaDriver::Close() | |||
| JackServerGlobals::on_device_release(audio_name); | |||
| } | |||
| } | |||
| #endif | |||
| return res; | |||
| } | |||
| @@ -578,6 +589,7 @@ extern "C" | |||
| { | |||
| #endif | |||
| #ifndef __QNXNTO__ | |||
| static | |||
| jack_driver_param_constraint_desc_t * | |||
| enum_alsa_devices() | |||
| @@ -667,6 +679,7 @@ fail: | |||
| jack_constraint_free(constraint_ptr); | |||
| return NULL; | |||
| } | |||
| #endif | |||
| static int | |||
| dither_opt (char c, DitherAlgorithm* dither) | |||
| @@ -705,11 +718,14 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor () | |||
| desc = jack_driver_descriptor_construct("alsa", JackDriverMaster, "Linux ALSA API based audio backend", &filler); | |||
| strcpy(value.str, "hw:0"); | |||
| #ifndef __QNXNTO__ | |||
| #ifdef __ANDROID__ | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "ALSA device name", NULL); | |||
| #else | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices(), "ALSA device name", NULL); | |||
| #endif | |||
| #endif | |||
| strcpy(value.str, "none"); | |||
| jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL); | |||
| @@ -951,8 +967,13 @@ void SetTime(jack_time_t time) | |||
| int Restart() | |||
| { | |||
| int res; | |||
| if ((res = g_alsa_driver->Stop()) == 0) { | |||
| res = g_alsa_driver->Start(); | |||
| if ((res = g_alsa_driver->Stop()) != 0) { | |||
| jack_error("restart: stop driver failed"); | |||
| return res; | |||
| } | |||
| if ((res = g_alsa_driver->Start()) != 0) { | |||
| jack_error("restart: start driver failed"); | |||
| return res; | |||
| } | |||
| return res; | |||
| } | |||
| @@ -21,7 +21,12 @@ | |||
| #ifndef __jack_alsa_driver_h__ | |||
| #define __jack_alsa_driver_h__ | |||
| #ifdef __QNXNTO__ | |||
| #include <sys/asoundlib.h> | |||
| #else | |||
| #include <alsa/asoundlib.h> | |||
| #endif | |||
| #include "bitset.h" | |||
| #if __BYTE_ORDER == __LITTLE_ENDIAN | |||
| @@ -41,6 +46,24 @@ | |||
| #include "memops.h" | |||
| #include "alsa_midi.h" | |||
| #ifdef __QNXNTO__ | |||
| #define SND_PCM_FORMAT_S16_LE SND_PCM_SFMT_S16_LE | |||
| #define SND_PCM_FORMAT_S16_BE SND_PCM_SFMT_S16_BE | |||
| #define SND_PCM_FORMAT_S24_LE SND_PCM_SFMT_S24_LE | |||
| #define SND_PCM_FORMAT_S24_BE SND_PCM_SFMT_S24_BE | |||
| #define SND_PCM_FORMAT_S32_LE SND_PCM_SFMT_S32_LE | |||
| #define SND_PCM_FORMAT_S32_BE SND_PCM_SFMT_S32_BE | |||
| #define SND_PCM_FORMAT_FLOAT_LE SND_PCM_SFMT_FLOAT_LE | |||
| #define SND_PCM_STATE_SUSPENDED SND_PCM_STATUS_SUSPENDED | |||
| #define SND_PCM_STATE_XRUN SND_PCM_STATUS_UNDERRUN | |||
| #define SND_PCM_STREAM_PLAYBACK SND_PCM_CHANNEL_PLAYBACK | |||
| #define SND_PCM_STREAM_CAPTURE SND_PCM_CHANNEL_CAPTURE | |||
| typedef unsigned long snd_pcm_uframes_t; | |||
| typedef signed long snd_pcm_sframes_t; | |||
| typedef int32_t alsa_driver_default_format_t; | |||
| #endif | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| @@ -58,13 +81,28 @@ typedef struct _alsa_driver { | |||
| JACK_DRIVER_NT_DECL | |||
| #ifdef __QNXNTO__ | |||
| unsigned int playback_sample_format; | |||
| unsigned int capture_sample_format; | |||
| void *capture_areas; | |||
| void *playback_areas; | |||
| void *capture_areas_ptr; | |||
| void *playback_areas_ptr; | |||
| #else | |||
| snd_pcm_format_t playback_sample_format; | |||
| snd_pcm_format_t capture_sample_format; | |||
| const snd_pcm_channel_area_t *capture_areas; | |||
| const snd_pcm_channel_area_t *playback_areas; | |||
| snd_pcm_hw_params_t *playback_hw_params; | |||
| snd_pcm_sw_params_t *playback_sw_params; | |||
| snd_pcm_hw_params_t *capture_hw_params; | |||
| snd_pcm_sw_params_t *capture_sw_params; | |||
| #endif | |||
| int poll_timeout_ms; | |||
| jack_time_t poll_last; | |||
| jack_time_t poll_next; | |||
| char **playback_addr; | |||
| char **capture_addr; | |||
| const snd_pcm_channel_area_t *capture_areas; | |||
| const snd_pcm_channel_area_t *playback_areas; | |||
| struct pollfd *pfd; | |||
| unsigned int playback_nfds; | |||
| unsigned int capture_nfds; | |||
| @@ -89,8 +127,6 @@ typedef struct _alsa_driver { | |||
| char *alsa_driver; | |||
| bitset_t channels_not_done; | |||
| bitset_t channels_done; | |||
| snd_pcm_format_t playback_sample_format; | |||
| snd_pcm_format_t capture_sample_format; | |||
| float max_sample_val; | |||
| unsigned long user_nperiods; | |||
| unsigned int playback_nperiods; | |||
| @@ -99,10 +135,6 @@ typedef struct _alsa_driver { | |||
| snd_ctl_t *ctl_handle; | |||
| snd_pcm_t *playback_handle; | |||
| snd_pcm_t *capture_handle; | |||
| snd_pcm_hw_params_t *playback_hw_params; | |||
| snd_pcm_sw_params_t *playback_sw_params; | |||
| snd_pcm_hw_params_t *capture_hw_params; | |||
| snd_pcm_sw_params_t *capture_sw_params; | |||
| jack_hardware_t *hw; | |||
| ClockSyncStatus *clock_sync_data; | |||
| jack_client_t *client; | |||
| @@ -211,18 +243,6 @@ alsa_driver_write_to_channel (alsa_driver_t *driver, | |||
| alsa_driver_mark_channel_done (driver, channel); | |||
| } | |||
| void alsa_driver_silence_untouched_channels (alsa_driver_t *driver, | |||
| jack_nframes_t nframes); | |||
| void alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn, | |||
| ClockSyncStatus status); | |||
| int alsa_driver_listen_for_clock_sync_status (alsa_driver_t *, | |||
| ClockSyncListenerFunction, | |||
| void *arg); | |||
| int alsa_driver_stop_listen_for_clock_sync_status (alsa_driver_t *, | |||
| unsigned int); | |||
| void alsa_driver_clock_sync_notify (alsa_driver_t *, channel_t chn, | |||
| ClockSyncStatus); | |||
| int | |||
| alsa_driver_reset_parameters (alsa_driver_t *driver, | |||
| jack_nframes_t frames_per_cycle, | |||
| @@ -269,8 +289,6 @@ alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes); | |||
| int | |||
| alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes); | |||
| jack_time_t jack_get_microseconds(void); | |||
| // Code implemented in JackAlsaDriver.cpp | |||
| void ReadInput(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nread); | |||
| @@ -22,6 +22,8 @@ | |||
| #ifndef __jack_usx2y_h__ | |||
| #define __jack_usx2y_h__ | |||
| #include <poll.h> | |||
| #define USX2Y_MAXPACK 50 | |||
| #define USX2Y_MAXBUFFERMS 100 | |||
| #define USX2Y_MAXSTRIDE 3 | |||
| @@ -51,7 +53,9 @@ typedef struct snd_usX2Y_hwdep_pcm_shm snd_usX2Y_hwdep_pcm_shm_t; | |||
| typedef struct | |||
| { | |||
| alsa_driver_t *driver; | |||
| #ifndef __QNXNTO__ | |||
| snd_hwdep_t *hwdep_handle; | |||
| #endif | |||
| struct pollfd pfds; | |||
| struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm; | |||
| int playback_iso_start; | |||
| @@ -44,7 +44,7 @@ class SERVER_EXPORT JackFifo : public detail::JackSynchro | |||
| protected: | |||
| void BuildName(const char* name, const char* server_name, char* res); | |||
| void BuildName(const char* name, const char* server_name, char* res, int size); | |||
| public: | |||
| @@ -0,0 +1,86 @@ | |||
| /* | |||
| 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_linux__ | |||
| #define __JackAtomic_linux__ | |||
| #include "JackTypes.h" | |||
| #ifdef __PPC__ | |||
| static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr) | |||
| { | |||
| register int result; | |||
| register UInt32 tmp; | |||
| asm volatile ( | |||
| "# CAS \n" | |||
| " lwarx %4, 0, %1 \n" // creates a reservation on addr | |||
| " cmpw %4, %2 \n" // test value at addr | |||
| " bne- 1f \n" | |||
| " sync \n" // synchronize instructions | |||
| " stwcx. %3, 0, %1 \n" // if the reservation is not altered | |||
| // stores the new value at addr | |||
| " bne- 1f \n" | |||
| " li %0, 1 \n" | |||
| " b 2f \n" | |||
| "1: \n" | |||
| " li %0, 0 \n" | |||
| "2: \n" | |||
| : "=r" (result) | |||
| : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp) | |||
| ); | |||
| return result; | |||
| } | |||
| #endif | |||
| #if defined(__i386__) || defined(__x86_64__) | |||
| #define LOCK "lock ; " | |||
| static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) | |||
| { | |||
| register char ret; | |||
| __asm__ __volatile__ ( | |||
| "# CAS \n\t" | |||
| LOCK "cmpxchg %2, (%1) \n\t" | |||
| "sete %0 \n\t" | |||
| : "=a" (ret) | |||
| : "c" (addr), "d" (newvalue), "a" (value) | |||
| ); | |||
| return ret; | |||
| } | |||
| #endif | |||
| #if !defined(__i386__) && !defined(__x86_64__) && !defined(__PPC__) | |||
| static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) | |||
| { | |||
| return __sync_bool_compare_and_swap ((UInt32*)addr, value, newvalue); | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,215 @@ | |||
| /* | |||
| Copyright (C) 2001-2003 Paul Davis | |||
| Copyright (C) 2005 Jussi Laako | |||
| 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 "JackConstants.h" | |||
| #include "JackTime.h" | |||
| #include "JackTypes.h" | |||
| #include "JackError.h" | |||
| #include <stdint.h> | |||
| #include <stdio.h> | |||
| #include <sys/mman.h> | |||
| #include <sys/time.h> | |||
| #include <sys/types.h> | |||
| #include <sys/stat.h> | |||
| #include <fcntl.h> | |||
| #include <errno.h> | |||
| #include <string.h> | |||
| #include <unistd.h> | |||
| #include <stdlib.h> | |||
| #include <inttypes.h> | |||
| jack_time_t (*_jack_get_microseconds)(void) = 0; | |||
| #if defined(__gnu_linux__) && (defined(__i386__) || defined(__x86_64__)) | |||
| #define HPET_SUPPORT | |||
| #define HPET_MMAP_SIZE 1024 | |||
| #define HPET_CAPS 0x000 | |||
| #define HPET_PERIOD 0x004 | |||
| #define HPET_COUNTER 0x0f0 | |||
| #define HPET_CAPS_COUNTER_64BIT (1 << 13) | |||
| #if defined(__x86_64__) | |||
| typedef uint64_t hpet_counter_t; | |||
| #else | |||
| typedef uint32_t hpet_counter_t; | |||
| #endif | |||
| static int hpet_fd; | |||
| static unsigned char *hpet_ptr; | |||
| static uint32_t hpet_period; /* period length in femto secs */ | |||
| static uint64_t hpet_offset = 0; | |||
| static uint64_t hpet_wrap; | |||
| static hpet_counter_t hpet_previous = 0; | |||
| #endif /* defined(__gnu_linux__) && (__i386__ || __x86_64__) */ | |||
| #ifdef HPET_SUPPORT | |||
| static int jack_hpet_init () | |||
| { | |||
| uint32_t hpet_caps; | |||
| hpet_fd = open("/dev/hpet", O_RDONLY); | |||
| if (hpet_fd < 0) { | |||
| jack_error ("This system has no accessible HPET device (%s)", strerror (errno)); | |||
| return -1; | |||
| } | |||
| hpet_ptr = (unsigned char *) mmap(NULL, HPET_MMAP_SIZE, | |||
| PROT_READ, MAP_SHARED, hpet_fd, 0); | |||
| if (hpet_ptr == MAP_FAILED) { | |||
| jack_error ("This system has no mappable HPET device (%s)", strerror (errno)); | |||
| close (hpet_fd); | |||
| return -1; | |||
| } | |||
| /* this assumes period to be constant. if needed, | |||
| it can be moved to the clock access function | |||
| */ | |||
| hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD)); | |||
| hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS)); | |||
| hpet_wrap = ((hpet_caps & HPET_CAPS_COUNTER_64BIT) && | |||
| (sizeof(hpet_counter_t) == sizeof(uint64_t))) ? | |||
| 0 : ((uint64_t) 1 << 32); | |||
| return 0; | |||
| } | |||
| static jack_time_t jack_get_microseconds_from_hpet (void) | |||
| { | |||
| hpet_counter_t hpet_counter; | |||
| long double hpet_time; | |||
| hpet_counter = *((hpet_counter_t *) (hpet_ptr + HPET_COUNTER)); | |||
| if (hpet_counter < hpet_previous) | |||
| hpet_offset += hpet_wrap; | |||
| hpet_previous = hpet_counter; | |||
| hpet_time = (long double) (hpet_offset + hpet_counter) * | |||
| (long double) hpet_period * (long double) 1e-9; | |||
| return ((jack_time_t) (hpet_time + 0.5)); | |||
| } | |||
| #else | |||
| static int jack_hpet_init () | |||
| { | |||
| jack_error ("This version of JACK or this computer does not have HPET support.\n" | |||
| "Please choose a different clock source."); | |||
| return -1; | |||
| } | |||
| static jack_time_t jack_get_microseconds_from_hpet (void) | |||
| { | |||
| /* never called */ | |||
| return 0; | |||
| } | |||
| #endif /* HPET_SUPPORT */ | |||
| #define HAVE_CLOCK_GETTIME 1 | |||
| #ifndef HAVE_CLOCK_GETTIME | |||
| static jack_time_t jack_get_microseconds_from_system (void) | |||
| { | |||
| jack_time_t jackTime; | |||
| struct timeval tv; | |||
| gettimeofday (&tv, NULL); | |||
| jackTime = (jack_time_t) tv.tv_sec * 1000000 + (jack_time_t) tv.tv_usec; | |||
| return jackTime; | |||
| } | |||
| #else | |||
| static jack_time_t jack_get_microseconds_from_system (void) | |||
| { | |||
| jack_time_t jackTime; | |||
| struct timespec time; | |||
| clock_gettime(CLOCK_MONOTONIC, &time); | |||
| jackTime = (jack_time_t) time.tv_sec * 1e6 + | |||
| (jack_time_t) time.tv_nsec / 1e3; | |||
| return jackTime; | |||
| } | |||
| #endif /* HAVE_CLOCK_GETTIME */ | |||
| SERVER_EXPORT void JackSleep(long usec) | |||
| { | |||
| usleep(usec); | |||
| } | |||
| SERVER_EXPORT void InitTime() | |||
| { | |||
| /* nothing to do on a generic system - we use the system clock */ | |||
| } | |||
| SERVER_EXPORT void EndTime() | |||
| {} | |||
| void SetClockSource(jack_timer_type_t source) | |||
| { | |||
| jack_log("Clock source : %s", ClockSourceName(source)); | |||
| switch (source) | |||
| { | |||
| case JACK_TIMER_HPET: | |||
| if (jack_hpet_init () == 0) { | |||
| _jack_get_microseconds = jack_get_microseconds_from_hpet; | |||
| } else { | |||
| _jack_get_microseconds = jack_get_microseconds_from_system; | |||
| } | |||
| break; | |||
| case JACK_TIMER_SYSTEM_CLOCK: | |||
| default: | |||
| _jack_get_microseconds = jack_get_microseconds_from_system; | |||
| break; | |||
| } | |||
| } | |||
| const char* ClockSourceName(jack_timer_type_t source) | |||
| { | |||
| switch (source) { | |||
| case JACK_TIMER_HPET: | |||
| return "hpet"; | |||
| case JACK_TIMER_SYSTEM_CLOCK: | |||
| #ifdef HAVE_CLOCK_GETTIME | |||
| return "system clock via clock_gettime"; | |||
| #else | |||
| return "system clock via gettimeofday"; | |||
| #endif | |||
| } | |||
| /* what is wrong with gcc ? */ | |||
| return "unknown"; | |||
| } | |||
| SERVER_EXPORT jack_time_t GetMicroSeconds() | |||
| { | |||
| return _jack_get_microseconds(); | |||
| } | |||
| SERVER_EXPORT jack_time_t jack_get_microseconds() | |||
| { | |||
| return _jack_get_microseconds(); | |||
| } | |||
| @@ -0,0 +1,85 @@ | |||
| /* | |||
| 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_linux__ | |||
| #define __JackPlatformPlug_linux__ | |||
| #define jack_server_dir "/dev/shm" | |||
| #define jack_client_dir "/dev/shm" | |||
| #define JACK_DEFAULT_DRIVER "alsa" | |||
| 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; } | |||
| #include "JackFifo.h" | |||
| namespace Jack { typedef JackFifo JackSynchro; } | |||
| /* __JackPlatformChannelTransaction__ */ | |||
| /* | |||
| #include "JackSocket.h" | |||
| namespace Jack { typedef JackClientSocket JackChannelTransaction; } | |||
| */ | |||
| /* __JackPlatformProcessSync__ */ | |||
| #include "JackPosixProcessSync.h" | |||
| namespace Jack { typedef JackPosixProcessSync JackProcessSync; } | |||
| /* __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 | |||
| @@ -0,0 +1,300 @@ | |||
| /* | |||
| Copyright (C) 2001 Paul Davis | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| $Id: driver.h,v 1.2 2005/11/23 11:24:29 letz Exp $ | |||
| */ | |||
| #ifndef __jack_driver_h__ | |||
| #define __jack_driver_h__ | |||
| #include <pthread.h> | |||
| #include "types.h" | |||
| #include "jslist.h" | |||
| #include "driver_interface.h" | |||
| typedef float gain_t; | |||
| typedef long channel_t; | |||
| typedef enum { | |||
| Lock = 0x1, | |||
| NoLock = 0x2, | |||
| Sync = 0x4, | |||
| NoSync = 0x8 | |||
| } ClockSyncStatus; | |||
| typedef void (*ClockSyncListenerFunction)(channel_t, ClockSyncStatus, void*); | |||
| typedef struct | |||
| { | |||
| unsigned long id; | |||
| ClockSyncListenerFunction function; | |||
| void *arg; | |||
| } | |||
| ClockSyncListener; | |||
| struct _jack_engine; | |||
| struct _jack_driver; | |||
| typedef int (*JackDriverAttachFunction)(struct _jack_driver *, | |||
| struct _jack_engine *); | |||
| typedef int (*JackDriverDetachFunction)(struct _jack_driver *, | |||
| struct _jack_engine *); | |||
| typedef int (*JackDriverReadFunction)(struct _jack_driver *, | |||
| jack_nframes_t nframes); | |||
| typedef int (*JackDriverWriteFunction)(struct _jack_driver *, | |||
| jack_nframes_t nframes); | |||
| typedef int (*JackDriverNullCycleFunction)(struct _jack_driver *, | |||
| jack_nframes_t nframes); | |||
| typedef int (*JackDriverStopFunction)(struct _jack_driver *); | |||
| typedef int (*JackDriverStartFunction)(struct _jack_driver *); | |||
| typedef int (*JackDriverBufSizeFunction)(struct _jack_driver *, | |||
| jack_nframes_t nframes); | |||
| /* | |||
| Call sequence summary: | |||
| 1) engine loads driver via runtime dynamic linking | |||
| - calls jack_driver_load | |||
| - we call dlsym for "driver_initialize" and execute it | |||
| 2) engine attaches to driver | |||
| 3) engine starts driver | |||
| 4) driver runs its own thread, calling | |||
| while () { | |||
| driver->wait (); | |||
| driver->engine->run_cycle () | |||
| } | |||
| 5) engine stops driver | |||
| 6) engine detaches from driver | |||
| 7) engine calls driver `finish' routine | |||
| Note that stop/start may be called multiple times in the event of an | |||
| error return from the `wait' function. | |||
| */ | |||
| typedef struct _jack_driver | |||
| { | |||
| /* The _jack_driver structure fields are included at the beginning of | |||
| each driver-specific structure using the JACK_DRIVER_DECL macro, | |||
| which is defined below. The comments that follow describe each | |||
| common field. | |||
| The driver should set this to be the interval it expects to elapse | |||
| between returning from the `wait' function. if set to zero, it | |||
| implies that the driver does not expect regular periodic wakeups. | |||
| jack_time_t period_usecs; | |||
| The driver should set this within its "wait" function to indicate | |||
| the UST of the most recent determination that the engine cycle | |||
| should run. it should not be set if the "extra_fd" argument of | |||
| the wait function is set to a non-zero value. | |||
| jack_time_t last_wait_ust; | |||
| These are not used by the driver. They should not be written to or | |||
| modified in any way | |||
| void *handle; | |||
| struct _jack_internal_client *internal_client; | |||
| This should perform any cleanup associated with the driver. it will | |||
| be called when jack server process decides to get rid of the | |||
| driver. in some systems, it may not be called at all, so the driver | |||
| should never rely on a call to this. it can set it to NULL if | |||
| it has nothing do do. | |||
| void (*finish)(struct _jack_driver *); | |||
| The JACK engine will call this when it wishes to attach itself to | |||
| the driver. the engine will pass a pointer to itself, which the driver | |||
| may use in anyway it wishes to. the driver may assume that this | |||
| is the same engine object that will make `wait' calls until a | |||
| `detach' call is made. | |||
| JackDriverAttachFunction attach; | |||
| The JACK engine will call this when it is finished using a driver. | |||
| JackDriverDetachFunction detach; | |||
| The JACK engine will call this when it wants to wait until the | |||
| driver decides that its time to process some data. the driver returns | |||
| a count of the number of audioframes that can be processed. | |||
| it should set the variable pointed to by `status' as follows: | |||
| zero: the wait completed normally, processing may begin | |||
| negative: the wait failed, and recovery is not possible | |||
| positive: the wait failed, and the driver stopped itself. | |||
| a call to `start' will return the driver to | |||
| a correct and known state. | |||
| the driver should also fill out the `delayed_usecs' variable to | |||
| indicate any delay in its expected periodic execution. for example, | |||
| if it discovers that its return from poll(2) is later than it | |||
| expects it to be, it would place an estimate of the delay | |||
| in this variable. the engine will use this to decide if it | |||
| plans to continue execution. | |||
| JackDriverWaitFunction wait; | |||
| The JACK engine will call this to ask the driver to move | |||
| data from its inputs to its output port buffers. it should | |||
| return 0 to indicate successful completion, negative otherwise. | |||
| This function will always be called after the wait function (above). | |||
| JackDriverReadFunction read; | |||
| The JACK engine will call this to ask the driver to move | |||
| data from its input port buffers to its outputs. it should | |||
| return 0 to indicate successful completion, negative otherwise. | |||
| this function will always be called after the read function (above). | |||
| JackDriverWriteFunction write; | |||
| The JACK engine will call this after the wait function (above) has | |||
| been called, but for some reason the engine is unable to execute | |||
| a full "cycle". the driver should do whatever is necessary to | |||
| keep itself running correctly, but cannot reference ports | |||
| or other JACK data structures in any way. | |||
| JackDriverNullCycleFunction null_cycle; | |||
| The engine will call this when it plans to stop calling the `wait' | |||
| function for some period of time. the driver should take | |||
| appropriate steps to handle this (possibly no steps at all). | |||
| NOTE: the driver must silence its capture buffers (if any) | |||
| from within this function or the function that actually | |||
| implements the change in state. | |||
| JackDriverStopFunction stop; | |||
| The engine will call this to let the driver know that it plans | |||
| to start calling the `wait' function on a regular basis. the driver | |||
| should take any appropriate steps to handle this (possibly no steps | |||
| at all). NOTE: The driver may wish to silence its playback buffers | |||
| (if any) from within this function or the function that actually | |||
| implements the change in state. | |||
| JackDriverStartFunction start; | |||
| The engine will call this to let the driver know that some client | |||
| has requested a new buffer size. The stop function will be called | |||
| prior to this, and the start function after this one has returned. | |||
| JackDriverBufSizeFunction bufsize; | |||
| */ | |||
| /* define the fields here... */ | |||
| #define JACK_DRIVER_DECL \ | |||
| jack_time_t period_usecs; \ | |||
| jack_time_t last_wait_ust; \ | |||
| void *handle; \ | |||
| struct _jack_client_internal * internal_client; \ | |||
| void (*finish)(struct _jack_driver *);\ | |||
| JackDriverAttachFunction attach; \ | |||
| JackDriverDetachFunction detach; \ | |||
| JackDriverReadFunction read; \ | |||
| JackDriverWriteFunction write; \ | |||
| JackDriverNullCycleFunction null_cycle; \ | |||
| JackDriverStopFunction stop; \ | |||
| JackDriverStartFunction start; \ | |||
| JackDriverBufSizeFunction bufsize; | |||
| JACK_DRIVER_DECL /* expand the macro */ | |||
| } | |||
| jack_driver_t; | |||
| void jack_driver_init (jack_driver_t *); | |||
| void jack_driver_release (jack_driver_t *); | |||
| jack_driver_t *jack_driver_load (int argc, char **argv); | |||
| void jack_driver_unload (jack_driver_t *); | |||
| /**************************** | |||
| *** Non-Threaded Drivers *** | |||
| ****************************/ | |||
| /* | |||
| Call sequence summary: | |||
| 1) engine loads driver via runtime dynamic linking | |||
| - calls jack_driver_load | |||
| - we call dlsym for "driver_initialize" and execute it | |||
| - driver_initialize calls jack_driver_nt_init | |||
| 2) nt layer attaches to driver | |||
| 3) nt layer starts driver | |||
| 4) nt layer runs a thread, calling | |||
| while () { | |||
| driver->nt_run_ctcle(); | |||
| } | |||
| 5) nt layer stops driver | |||
| 6) nt layer detaches driver | |||
| 7) engine calls driver `finish' routine which calls jack_driver_nt_finish | |||
| Note that stop/start may be called multiple times in the event of an | |||
| error return from the `wait' function. | |||
| */ | |||
| struct _jack_driver_nt; | |||
| typedef int (*JackDriverNTAttachFunction)(struct _jack_driver_nt *); | |||
| typedef int (*JackDriverNTDetachFunction)(struct _jack_driver_nt *); | |||
| typedef int (*JackDriverNTStopFunction)(struct _jack_driver_nt *); | |||
| typedef int (*JackDriverNTStartFunction)(struct _jack_driver_nt *); | |||
| typedef int (*JackDriverNTBufSizeFunction)(struct _jack_driver_nt *, | |||
| jack_nframes_t nframes); | |||
| typedef int (*JackDriverNTRunCycleFunction)(struct _jack_driver_nt *); | |||
| typedef struct _jack_driver_nt | |||
| { | |||
| #define JACK_DRIVER_NT_DECL \ | |||
| JACK_DRIVER_DECL \ | |||
| struct _jack_engine * engine; \ | |||
| volatile int nt_run; \ | |||
| pthread_t nt_thread; \ | |||
| pthread_mutex_t nt_run_lock; \ | |||
| JackDriverNTAttachFunction nt_attach; \ | |||
| JackDriverNTDetachFunction nt_detach; \ | |||
| JackDriverNTStopFunction nt_stop; \ | |||
| JackDriverNTStartFunction nt_start; \ | |||
| JackDriverNTBufSizeFunction nt_bufsize; \ | |||
| JackDriverNTRunCycleFunction nt_run_cycle; | |||
| #define nt_read read | |||
| #define nt_write write | |||
| #define nt_null_cycle null_cycle | |||
| JACK_DRIVER_NT_DECL | |||
| } | |||
| jack_driver_nt_t; | |||
| void jack_driver_nt_init (jack_driver_nt_t * driver); | |||
| void jack_driver_nt_finish (jack_driver_nt_t * driver); | |||
| #endif /* __jack_driver_h__ */ | |||
| @@ -20,6 +20,8 @@ def build(bld): | |||
| prog.includes = ['..','../macosx', '../posix', '../common/jack', '../common'] | |||
| if bld.env['IS_LINUX']: | |||
| prog.includes = ['..','../linux', '../posix', '../common/jack', '../common'] | |||
| if bld.env['IS_QNX']: | |||
| prog.includes = ['..','../qnx', '../posix', '../common/jack', '../common'] | |||
| if bld.env['IS_SUN']: | |||
| prog.includes = ['..','../solaris', '../posix', '../common/jack', '../common'] | |||
| prog.source = test_program_sources | |||
| @@ -95,6 +95,15 @@ def options(opt): | |||
| alsa.check_cfg( | |||
| package='alsa >= 1.0.18', | |||
| args='--cflags --libs') | |||
| # Check for QNX sound headers | |||
| qsa = opt.add_auto_option( | |||
| 'qsa', | |||
| help='Enable QNX sound driver', | |||
| conf_dest='BUILD_DRIVER_ALSA') | |||
| qsa.check(lib='asound', uselib_store='ALSA') | |||
| qsa.check( | |||
| header_name=['sys/asoundlib.h'], | |||
| msg='Checking for header sys/asoundlib.h') | |||
| firewire = opt.add_auto_option( | |||
| 'firewire', | |||
| help='Enable FireWire driver (FFADO)', | |||
| @@ -185,6 +194,7 @@ def detect_platform(conf): | |||
| platforms = [ | |||
| # ('KEY, 'Human readable name', ['strings', 'to', 'check', 'for']) | |||
| ('IS_LINUX', 'Linux', ['gnu0', 'gnukfreebsd', 'linux', 'posix']), | |||
| ('IS_QNX', 'QNX', ['qnx']), | |||
| ('IS_MACOSX', 'MacOS X', ['darwin']), | |||
| ('IS_SUN', 'SunOS', ['sunos']), | |||
| ('IS_WINDOWS', 'Windows', ['cygwin', 'msys', 'win32']) | |||
| @@ -304,7 +314,11 @@ def configure(conf): | |||
| conf.check_cc(fragment=fragment, define_name='HAVE_NGREG', mandatory=False, | |||
| msg='Checking for NGREG') | |||
| conf.env['LIB_PTHREAD'] = ['pthread'] | |||
| if conf.env['IS_QNX']: | |||
| conf.env['LIB_PTHREAD'] = ['c'] | |||
| conf.env['LIB_SOCKET'] = ['socket'] | |||
| else: | |||
| conf.env['LIB_PTHREAD'] = ['pthread'] | |||
| conf.env['LIB_DL'] = ['dl'] | |||
| conf.env['LIB_RT'] = ['rt'] | |||
| conf.env['LIB_M'] = ['m'] | |||
| @@ -512,6 +526,9 @@ def obj_add_includes(bld, obj): | |||
| if bld.env['IS_MACOSX']: | |||
| obj.includes += ['macosx', 'posix'] | |||
| if bld.env['IS_QNX']: | |||
| obj.includes += ['qnx', 'posix'] | |||
| if bld.env['IS_SUN']: | |||
| obj.includes += ['posix', 'solaris'] | |||
| @@ -540,6 +557,10 @@ def build_jackd(bld): | |||
| jackd.use += ['DL', 'PTHREAD'] | |||
| jackd.framework = ['CoreFoundation'] | |||
| if bld.env['IS_QNX']: | |||
| jackd.use += ['M', 'PTHREAD'] | |||
| if bld.env['IS_SUN']: | |||
| jackd.use += ['DL', 'PTHREAD'] | |||
| @@ -598,16 +619,20 @@ def build_drivers(bld): | |||
| alsa_src = [ | |||
| 'common/memops.c', | |||
| 'linux/alsa/JackAlsaDriver.cpp', | |||
| 'linux/alsa/alsa_rawmidi.c', | |||
| 'linux/alsa/alsa_seqmidi.c', | |||
| 'linux/alsa/alsa_midi_jackmp.cpp', | |||
| 'linux/alsa/generic_hw.c', | |||
| 'linux/alsa/hdsp.c', | |||
| 'linux/alsa/alsa_driver.c', | |||
| 'linux/alsa/hammerfall.c', | |||
| 'linux/alsa/ice1712.c' | |||
| 'linux/alsa/alsa_driver.c' | |||
| ] | |||
| if not bld.env['IS_QNX']: | |||
| alsa_src += [ | |||
| 'linux/alsa/alsa_rawmidi.c', | |||
| 'linux/alsa/alsa_seqmidi.c', | |||
| 'linux/alsa/alsa_midi_jackmp.cpp', | |||
| 'linux/alsa/generic_hw.c', | |||
| 'linux/alsa/hdsp.c', | |||
| 'linux/alsa/hammerfall.c', | |||
| 'linux/alsa/ice1712.c' | |||
| ] | |||
| alsarawmidi_src = [ | |||
| 'linux/alsarawmidi/JackALSARawMidiDriver.cpp', | |||
| 'linux/alsarawmidi/JackALSARawMidiInputPort.cpp', | |||
| @@ -704,11 +729,12 @@ def build_drivers(bld): | |||
| target = 'alsa', | |||
| source = alsa_src, | |||
| use = ['ALSA']) | |||
| create_driver_obj( | |||
| bld, | |||
| target = 'alsarawmidi', | |||
| source = alsarawmidi_src, | |||
| use = ['ALSA']) | |||
| if not bld.env['IS_QNX']: | |||
| create_driver_obj( | |||
| bld, | |||
| target = 'alsarawmidi', | |||
| source = alsarawmidi_src, | |||
| use = ['ALSA']) | |||
| if bld.env['BUILD_DRIVER_FFADO']: | |||
| create_driver_obj( | |||