| @@ -35,6 +35,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #define JackPlatformAdapter JackAlsaAdapter | |||
| #endif | |||
| #ifdef __QNX__ | |||
| #include "JackIoAudioAdapter.h" | |||
| #define JackPlatformAdapter JackIoAudioAdapter | |||
| #endif | |||
| #if defined(__sun__) || defined(sun) | |||
| #include "JackOSSAdapter.h" | |||
| #define JackPlatformAdapter JackOSSAdapter | |||
| @@ -661,7 +661,12 @@ jackctl_setup_signals( | |||
| sigfillset(&allsignals); | |||
| action.sa_handler = signal_handler; | |||
| action.sa_mask = allsignals; | |||
| #ifdef __QNX__ | |||
| // SA_RESTART is not supported in QNX 6.6.0 | |||
| action.sa_flags = SA_RESETHAND; | |||
| #else | |||
| action.sa_flags = SA_RESTART|SA_RESETHAND; | |||
| #endif | |||
| for (i = 1; i < NSIG; i++) | |||
| { | |||
| @@ -103,7 +103,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(__QNX__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) | |||
| #if defined(__CYGWIN__) || defined(GNU_WIN32) | |||
| #include <stdint.h> | |||
| @@ -67,21 +67,16 @@ size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); | |||
| LIB_EXPORT jack_ringbuffer_t * | |||
| jack_ringbuffer_create (size_t sz) | |||
| { | |||
| int power_of_two; | |||
| jack_ringbuffer_t *rb; | |||
| if ((rb = (jack_ringbuffer_t *) malloc (sizeof (jack_ringbuffer_t))) == NULL) { | |||
| return NULL; | |||
| } | |||
| for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++); | |||
| rb->buf = NULL; | |||
| jack_ringbuffer_reset_size( rb, sz ); | |||
| rb->size = 1 << power_of_two; | |||
| rb->size_mask = rb->size; | |||
| rb->size_mask -= 1; | |||
| rb->write_ptr = 0; | |||
| rb->read_ptr = 0; | |||
| if ((rb->buf = (char *) malloc (rb->size)) == NULL) { | |||
| if (rb->buf == NULL) { | |||
| free (rb); | |||
| return NULL; | |||
| } | |||
| @@ -129,17 +124,38 @@ jack_ringbuffer_reset (jack_ringbuffer_t * rb) | |||
| memset(rb->buf, 0, rb->size); | |||
| } | |||
| /* Reset the read and write pointers to zero. This is not thread | |||
| safe. */ | |||
| /* Reset the size of the ringbuffer. | |||
| Reallocates the internal buffer using the next power-of-two size up from | |||
| the requested size. | |||
| If the reallocation fails, the previous buffer is left intact. | |||
| */ | |||
| LIB_EXPORT void | |||
| jack_ringbuffer_reset_size (jack_ringbuffer_t * rb, size_t sz) | |||
| { | |||
| rb->size = sz; | |||
| rb->size_mask = rb->size; | |||
| rb->size_mask -= 1; | |||
| rb->read_ptr = 0; | |||
| rb->write_ptr = 0; | |||
| /* Attempt to reallocate buffer to size sz */ | |||
| int power_of_two; | |||
| for (power_of_two = 1; 1 << power_of_two < sz; power_of_two++); | |||
| size_t newsz = 1 << power_of_two; | |||
| void* newbuf = realloc (rb->buf, newsz); | |||
| if (NULL != newbuf) | |||
| { | |||
| rb->buf = newbuf; | |||
| rb->size = newsz; | |||
| rb->size_mask = rb->size; | |||
| rb->size_mask -= 1; | |||
| rb->read_ptr = 0; | |||
| rb->write_ptr = 0; | |||
| } | |||
| else | |||
| { | |||
| /* Reallocation failed. Ringbuffer is left in initial state | |||
| * so application must check ringbuffer size to see if | |||
| * the resize succeeded. */ | |||
| } | |||
| } | |||
| /* Return the number of bytes available for reading. This is the | |||
| @@ -49,7 +49,9 @@ | |||
| #include <sys/mman.h> | |||
| #include <sys/types.h> | |||
| #include <sys/stat.h> | |||
| #ifndef USE_POSIX_SHM | |||
| #include <sys/shm.h> | |||
| #endif | |||
| #include <sys/sem.h> | |||
| #include <stdlib.h> | |||
| @@ -176,6 +178,49 @@ semaphore_init () {return 0;} | |||
| static int | |||
| semaphore_add (int value) {return 0;} | |||
| #elif defined(__QNX__) | |||
| #include <semaphore.h> | |||
| static sem_t sem; | |||
| /* all semaphore errors are fatal -- issue message, but do not return */ | |||
| static void | |||
| semaphore_error (char *msg) | |||
| { | |||
| jack_error ("JACK semaphore error: %s (%s)", | |||
| msg, strerror (errno)); | |||
| } | |||
| static int | |||
| semaphore_init () | |||
| { | |||
| semid = sem_init(&sem, JACK_SEMAPHORE_KEY, 1); | |||
| if( semid == -1) | |||
| { | |||
| semaphore_error("semaphore_init()"); | |||
| } | |||
| return 0; | |||
| } | |||
| static inline int | |||
| semaphore_add (int value) | |||
| { | |||
| while( value > 0 ) | |||
| { | |||
| sem_post( &sem ); | |||
| --value; | |||
| } | |||
| while( value < 0 ) | |||
| { | |||
| sem_wait( &sem ); | |||
| ++value; | |||
| } | |||
| return 0; | |||
| } | |||
| #else | |||
| /* all semaphore errors are fatal -- issue message, but do not return */ | |||
| static void | |||
| @@ -26,6 +26,8 @@ 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_QNX']: | |||
| env_includes = ['../qnx', '../posix', '../qnx/ioaudio'] | |||
| if bld.env['IS_SUN']: | |||
| env_includes = ['../solaris', '../posix', '../solaris/oss'] | |||
| if bld.env['IS_WINDOWS']: | |||
| @@ -36,6 +38,8 @@ def create_jack_process_obj(bld, target, sources, uselib = None): | |||
| process.source = sources | |||
| if bld.env['IS_LINUX']: | |||
| process.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| if bld.env['IS_QNX']: | |||
| 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 -arch x86_64") | |||
| #process.env.append_value("LINKFLAGS", "-arch i386 -arch ppc -arch x86_64") | |||
| @@ -93,6 +97,22 @@ def build(bld): | |||
| uselib.append('RT') | |||
| uselib.append('DL') | |||
| if bld.env['IS_QNX']: | |||
| common_libsources += [ | |||
| 'JackDebugClient.cpp', | |||
| 'timestamps.c', | |||
| '../posix/JackPosixThread.cpp', | |||
| '../posix/JackPosixSemaphore.cpp', | |||
| '../posix/JackPosixProcessSync.cpp', | |||
| '../posix/JackPosixMutex.cpp', | |||
| '../posix/JackSocket.cpp', | |||
| '../qnx/JackQnxTime.c', | |||
| ] | |||
| includes = ['../qnx', '../posix'] + includes | |||
| uselib.append('RT') | |||
| uselib.append('DL') | |||
| uselib.append('SOCKET') | |||
| if bld.env['IS_SUN']: | |||
| common_libsources += [ | |||
| 'JackDebugClient.cpp', | |||
| @@ -158,6 +178,12 @@ def build(bld): | |||
| '../posix/JackPosixServerLaunch.cpp', | |||
| ] | |||
| if bld.env['IS_QNX']: | |||
| clientlib.source += [ | |||
| '../posix/JackSocketClientChannel.cpp', | |||
| '../posix/JackPosixServerLaunch.cpp', | |||
| ] | |||
| if bld.env['IS_SUN']: | |||
| clientlib.source += [ | |||
| '../posix/JackSocketClientChannel.cpp', | |||
| @@ -183,6 +209,9 @@ def build(bld): | |||
| if bld.env['IS_LINUX']: | |||
| clientlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| if bld.env['IS_QNX']: | |||
| 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 -arch x86_64") | |||
| @@ -252,6 +281,14 @@ def build(bld): | |||
| '../posix/JackNetUnixSocket.cpp', | |||
| ] | |||
| if bld.env['IS_QNX']: | |||
| serverlib.source += [ | |||
| '../posix/JackSocketServerChannel.cpp', | |||
| '../posix/JackSocketNotifyChannel.cpp', | |||
| '../posix/JackSocketServerNotifyChannel.cpp', | |||
| '../posix/JackNetUnixSocket.cpp', | |||
| ] | |||
| if bld.env['IS_SUN']: | |||
| serverlib.source += [ | |||
| '../posix/JackSocketServerChannel.cpp', | |||
| @@ -283,6 +320,9 @@ def build(bld): | |||
| if bld.env['IS_LINUX']: | |||
| serverlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| if bld.env['IS_QNX']: | |||
| 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 -arch x86_64") | |||
| @@ -321,6 +361,10 @@ def build(bld): | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../linux/JackLinuxTime.c'] | |||
| netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| if bld.env['IS_QNX']: | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp','../posix/JackPosixMutex.cpp','../qnx/JackQnxTime.c'] | |||
| netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| if bld.env['IS_SUN']: | |||
| netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../solaris/JackSolarisTime.c'] | |||
| netlib.env.append_value("CPPFLAGS", "-fvisibility=hidden") | |||
| @@ -370,6 +414,11 @@ def build(bld): | |||
| process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | |||
| process.use = ['ALSA', 'SAMPLERATE'] | |||
| if bld.env['BUILD_ADAPTER'] and bld.env['IS_QNX']: | |||
| audio_adapter_sources += ['../qnx/ioaudio/JackIoAudioAdapter.cpp'] | |||
| process = create_jack_process_obj(bld, 'audioadapter', audio_adapter_sources, serverlib) | |||
| process.use = ['IOAUDIO', '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) | |||
| @@ -41,6 +41,8 @@ def build(bld): | |||
| sysdeps_dbus_include = ['../linux', '../posix'] | |||
| if bld.env['IS_MACOSX']: | |||
| sysdeps_dbus_include = ['../macosx', '../posix'] | |||
| if bld.env['IS_QNX']: | |||
| sysdeps_dbus_include = ['../qnx', '../posix'] | |||
| obj.includes = sysdeps_dbus_include + ['.', '../', '../common', '../common/jack'] | |||
| obj.defines = ['HAVE_CONFIG_H','SERVER_SIDE'] | |||
| @@ -66,6 +68,8 @@ def build(bld): | |||
| obj.use += ['PTHREAD', 'DL', 'RT', 'DBUS-1', 'EXPAT', 'STDC++'] | |||
| if bld.env['IS_MACOSX']: | |||
| obj.use += ['PTHREAD', 'DL', 'DBUS-1', 'EXPAT'] | |||
| if bld.env['IS_QNX']: | |||
| obj.use += ['PTHREAD', 'DL', 'DBUS-1', 'EXPAT', 'STDC++'] | |||
| obj.target = 'jackdbus' | |||
| # process org.jackaudio.service.in -> org.jackaudio.service | |||
| @@ -47,6 +47,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']: | |||
| @@ -75,11 +77,12 @@ def build(bld): | |||
| prog.env.append_value("LINKFLAGS", "") | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'M'] | |||
| if bld.env['IS_QNX']: | |||
| prog.use += ['M','SOCKET'] | |||
| if bld.env['IS_SUN']: | |||
| prog.use += ['M'] | |||
| prog.target = example_program | |||
| if bld.env['BUILD_EXAMPLE_CLIENT_TRANSPORT']: | |||
| prog = bld(features = 'c cprogram') | |||
| prog.includes = os_incdir + ['../common/jack', '../common'] | |||
| @@ -95,6 +98,8 @@ def build(bld): | |||
| prog.use += ['READLINE'] | |||
| if bld.env['IS_WINDOWS']: | |||
| prog.use += ['READLINE'] | |||
| if bld.env['IS_QNX']: | |||
| prog.use += ['READLINE'] | |||
| prog.target = 'jack_transport' | |||
| if bld.env['BUILD_EXAMPLE_CLIENT_REC']: | |||
| @@ -109,6 +114,8 @@ def build(bld): | |||
| prog.use += ['SNDFILE'] | |||
| if bld.env['IS_LINUX']: | |||
| prog.use += ['RT', 'SNDFILE'] | |||
| if bld.env['IS_QNX']: | |||
| prog.use += ['SNDFILE'] | |||
| if bld.env['IS_SUN']: | |||
| prog.use += ['RT', 'SNDFILE'] | |||
| if bld.env['IS_WINDOWS']: | |||
| @@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include <unistd.h> | |||
| #include <fcntl.h> | |||
| #include <sys/time.h> | |||
| using namespace std; | |||
| @@ -33,9 +33,9 @@ void JackPosixSemaphore::BuildName(const char* client_name, const char* server_n | |||
| char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | |||
| JackTools::RewriteName(client_name, ext_client_name); | |||
| if (getenv("JACK_PROMISCUOUS_SERVER")) { | |||
| snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); | |||
| snprintf(res, size, "/jack_sem.%s_%s", server_name, ext_client_name); | |||
| } else { | |||
| snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | |||
| snprintf(res, size, "/jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | |||
| } | |||
| } | |||
| @@ -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_qnx__ | |||
| #define __JackAtomic_qnx__ | |||
| #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,90 @@ | |||
| /* | |||
| 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_qnx__ | |||
| #define __JackPlatformPlug_qnx__ | |||
| #define jack_server_dir "/dev/shmem" | |||
| #define jack_client_dir "/dev/shmem" | |||
| #define JACK_DEFAULT_DRIVER "ioaudio" | |||
| 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; } | |||
| */ | |||
| #include "JackPosixSemaphore.h" | |||
| namespace Jack { typedef JackPosixSemaphore 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,216 @@ | |||
| /* | |||
| 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 "cycles.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,30 @@ | |||
| /* | |||
| Copyright (C) 2001 Paul Davis | |||
| Code derived from various headers from the Linux kernel | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (at your option) any later version. | |||
| This program is distributed in the hope that it will be useful, | |||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| GNU General Public License for more details. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| $Id: cycles.h,v 1.4.2.1 2006/06/20 14:44:00 letz Exp $ | |||
| */ | |||
| #ifndef __jack_cycles_h__ | |||
| #define __jack_cycles_h__ | |||
| #include <sys/neutrino.h> | |||
| typedef uint64_t cycles_t; | |||
| #define get_cycles() ClockCycles() | |||
| #endif /* __jack_cycles_h__ */ | |||
| @@ -0,0 +1,257 @@ | |||
| /* | |||
| Copyright (C) 2008 Grame | |||
| This program is free software; you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| the Free Software Foundation; either version 2 of the License, or | |||
| (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 __JackIoAudioAdapter__ | |||
| #define __JackIoAudioAdapter__ | |||
| #include <cmath> | |||
| #include <climits> | |||
| #include <cassert> | |||
| #include <sys/asoundlib.h> | |||
| #include "JackAudioAdapterInterface.h" | |||
| #include "JackPlatformPlug.h" | |||
| #include "JackError.h" | |||
| #include "jack.h" | |||
| #include "jslist.h" | |||
| namespace Jack | |||
| { | |||
| #define max(x,y) (((x)>(y)) ? (x) : (y)) | |||
| #define min(x,y) (((x)<(y)) ? (x) : (y)) | |||
| #define NUM_BUFFERS 256 | |||
| /** | |||
| * A convenient class to pass parameters to AudioInterface | |||
| */ | |||
| class AudioParam | |||
| { | |||
| public: | |||
| const char* fInputCardName; | |||
| const char* fOutputCardName; | |||
| unsigned int fFrequency; | |||
| int fBuffering; | |||
| unsigned int fCardInputVoices; | |||
| unsigned int fCardOutputVoices; | |||
| unsigned int fPeriod; | |||
| public: | |||
| AudioParam( | |||
| jack_nframes_t buffer_size = 512, | |||
| jack_nframes_t sample_rate = 44100, | |||
| const char* input_card = "pcmPreferredc", | |||
| int input_ports = 2, | |||
| const char* output_card = "pcmPreferredp", | |||
| int output_ports = 2, | |||
| int periods = 2) : | |||
| fInputCardName(input_card), | |||
| fOutputCardName(output_card), | |||
| fFrequency(sample_rate), | |||
| fBuffering(buffer_size), | |||
| fCardInputVoices(input_ports), | |||
| fCardOutputVoices(output_ports), | |||
| fPeriod(periods) | |||
| { | |||
| } | |||
| AudioParam& inputCardName(const char* n) | |||
| { | |||
| fInputCardName = n; | |||
| return *this; | |||
| } | |||
| AudioParam& outputCardName(const char* n) | |||
| { | |||
| fOutputCardName = n; | |||
| return *this; | |||
| } | |||
| AudioParam& frequency(int f) | |||
| { | |||
| fFrequency = f; | |||
| return *this; | |||
| } | |||
| AudioParam& buffering(int fpb) | |||
| { | |||
| fBuffering = fpb; | |||
| return *this; | |||
| } | |||
| void setInputs(int inputs) | |||
| { | |||
| fCardInputVoices = inputs; | |||
| } | |||
| AudioParam& inputs(int n) | |||
| { | |||
| fCardInputVoices = n; | |||
| return *this; | |||
| } | |||
| void setOutputs(int outputs) | |||
| { | |||
| fCardOutputVoices = outputs; | |||
| } | |||
| AudioParam& outputs(int n) | |||
| { | |||
| fCardOutputVoices = n; | |||
| return *this; | |||
| } | |||
| }; | |||
| /** | |||
| * An io-audio client interface | |||
| */ | |||
| class AudioInterface | |||
| { | |||
| public: | |||
| AudioParam fParams; | |||
| //device info | |||
| snd_pcm_t* fOutputDevice; | |||
| snd_pcm_t* fInputDevice; | |||
| snd_pcm_channel_params_t *fInputParams; | |||
| snd_pcm_channel_params_t *fOutputParams; | |||
| snd_pcm_channel_setup_t *fInputSetup; | |||
| snd_pcm_channel_setup_t *fOutputSetup; | |||
| //samples info | |||
| snd_pcm_format_t fInputFormat; | |||
| snd_pcm_format_t fOutputFormat; | |||
| unsigned int fNumInputPorts; | |||
| unsigned int fNumOutputPorts; | |||
| //Number of frames for one voice/port | |||
| jack_nframes_t fInputBufferFrames; | |||
| jack_nframes_t fOutputBufferFrames; | |||
| // audiocard buffers | |||
| void* fInputCardBuffer; | |||
| void* fOutputCardBuffer; | |||
| // floating point JACK buffers | |||
| jack_default_audio_sample_t** fJackInputBuffers; | |||
| jack_default_audio_sample_t** fJackOutputBuffers; | |||
| //public methods --------------------------------------------------------- | |||
| AudioInterface(const AudioParam& ap = AudioParam()); | |||
| AudioInterface(jack_nframes_t buffer_size, jack_nframes_t sample_rate); | |||
| ~AudioInterface(); | |||
| /** | |||
| * Open the audio interface | |||
| */ | |||
| int open(); | |||
| int close(); | |||
| int setAudioParams(snd_pcm_t* stream, snd_pcm_channel_params_t* params); | |||
| ssize_t interleavedBufferSize(snd_pcm_channel_params_t* params); | |||
| ssize_t noninterleavedBufferSize(snd_pcm_channel_params_t* params); | |||
| /** | |||
| * Read audio samples from the audio card. Convert samples to floats and take | |||
| * care of interleaved buffers | |||
| */ | |||
| int read(); | |||
| /** | |||
| * write the output soft channels to the audio card. Convert sample | |||
| * format and interleaves buffers when needed | |||
| */ | |||
| int write(); | |||
| /** | |||
| * print short information on the audio device | |||
| */ | |||
| int shortinfo(); | |||
| /** | |||
| * print more detailled information on the audio device | |||
| */ | |||
| int longinfo(); | |||
| void printCardInfo(snd_ctl_hw_info_t* ci); | |||
| void printHWParams(snd_pcm_channel_params_t* params); | |||
| private: | |||
| int AudioInterface_common(); | |||
| }; | |||
| /*! | |||
| \brief Audio adapter using io-audio API. | |||
| */ | |||
| class JackIoAudioAdapter: public JackAudioAdapterInterface, | |||
| public JackRunnableInterface | |||
| { | |||
| private: | |||
| JackThread fThread; | |||
| AudioInterface fAudioInterface; | |||
| public: | |||
| JackIoAudioAdapter( | |||
| jack_nframes_t buffer_size, | |||
| jack_nframes_t sample_rate, | |||
| const JSList* params); | |||
| ~JackIoAudioAdapter() | |||
| { | |||
| } | |||
| virtual int Open(); | |||
| virtual int Close(); | |||
| virtual void Create(); | |||
| virtual void Destroy(); | |||
| virtual int SetSampleRate(jack_nframes_t sample_rate); | |||
| virtual int SetBufferSize(jack_nframes_t buffer_size); | |||
| virtual bool Init(); | |||
| virtual bool Execute(); | |||
| }; | |||
| } | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include "JackCompilerDeps.h" | |||
| #include "driver_interface.h" | |||
| SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor(); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -0,0 +1,749 @@ | |||
| /* | |||
| * ioaudio_driver.c | |||
| * | |||
| * Copyright 2015 Garmin | |||
| */ | |||
| #define HW_CONTEXT_T struct jack_card | |||
| #define PCM_SUBCHN_CONTEXT_T struct subchn | |||
| #include <stdlib.h> | |||
| #include <audio_driver.h> | |||
| #include <jack/jack.h> | |||
| #include <jack/ringbuffer.h> | |||
| #include <pthread.h> | |||
| #include <sys/asound.h> | |||
| static const char* PORTNAME_FMT = "playback_%d"; | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| struct subchn | |||
| { | |||
| ado_pcm_subchn_t *pcm_subchn; | |||
| ado_pcm_config_t *pcm_config; | |||
| int32_t pcm_offset; /* holds offset of data populated in PCM subchannel buffer */ | |||
| uint8_t go; /* indicates if trigger GO has been issue by client for data transfer */ | |||
| void *strm; /* pointer back to parent stream structure */ | |||
| }; | |||
| typedef struct jack_card | |||
| { | |||
| /** | |||
| * PCM device instance | |||
| */ | |||
| ado_pcm_t* pcm; | |||
| /** | |||
| * Audio Card Instance | |||
| */ | |||
| ado_card_t* card; | |||
| /** | |||
| * Audio Hardware Mutex | |||
| */ | |||
| ado_mutex_t hw_lock; | |||
| /** | |||
| * Audio Mixer Instance | |||
| */ | |||
| ado_mixer_t* mixer; | |||
| /** | |||
| * PCM Device Capabilities | |||
| */ | |||
| ado_pcm_cap_t caps; | |||
| /** | |||
| * PCM Device Callbacks | |||
| */ | |||
| ado_pcm_hw_t funcs; | |||
| /** | |||
| * PCM Subchannel used by client | |||
| */ | |||
| struct subchn subchn; | |||
| /** | |||
| * Name of JACK server to communicate with | |||
| */ | |||
| char* server; | |||
| /** | |||
| * Name of this client | |||
| */ | |||
| char* name; | |||
| /** | |||
| * Handle to this client | |||
| */ | |||
| jack_client_t* client; | |||
| /** | |||
| * SND_PCM_CHANNEL_CAPTURE or SND_PCM_CHANNEL_PLAYBACK | |||
| */ | |||
| int channel_type; | |||
| /** | |||
| * Number of voices / ports | |||
| */ | |||
| int voices; | |||
| /** | |||
| * Ringbuffer between io-audio and JACK | |||
| */ | |||
| jack_ringbuffer_t ringbuffer; | |||
| /** | |||
| * Number of audio frames per fragment | |||
| */ | |||
| size_t fragsize; | |||
| /** | |||
| * Array of ports between io-audio and JACK | |||
| * | |||
| * size of array is 'voices' | |||
| */ | |||
| jack_port_t** ports; | |||
| /** | |||
| * Mutex controlling JACK processing | |||
| */ | |||
| pthread_mutex_t process_lock; | |||
| } jack_card_t; | |||
| static int parse_commandline( | |||
| jack_card_t* jack_card, | |||
| char* theArgs ) | |||
| { | |||
| int opt = 0; | |||
| char* value; | |||
| char* argdup = ado_strdup( theArgs ); | |||
| char* args = argdup; | |||
| char* opts[] = { "server", "name", "type", "voices", NULL }; | |||
| while( ( NULL != args ) && ( '\0' != args[0] ) ) | |||
| { | |||
| opt = getsubopt( &args, | |||
| opts, | |||
| &value ); | |||
| if( opt >= 0 ) | |||
| { | |||
| switch( opt ) | |||
| { | |||
| case 0: /* server: JACK server name */ | |||
| if( NULL == value ) | |||
| { | |||
| ado_error( "server option given without value; ignoring" ); | |||
| jack_card->server = NULL; | |||
| } | |||
| else | |||
| { | |||
| jack_card->server = ado_strdup( value ); | |||
| } | |||
| break; | |||
| case 1: /* name: JACK client name */ | |||
| if( NULL == value ) | |||
| { | |||
| ado_error( "name option given without value; ignoring" ); | |||
| jack_card->name = ado_strdup( "jack_ioaudio" ); | |||
| } | |||
| else | |||
| { | |||
| jack_card->name = ado_strdup( value ); | |||
| } | |||
| break; | |||
| case 2: /* type: io-audio channel type */ | |||
| if( NULL != value ) | |||
| { | |||
| if( value[0] == 'P' || value[0] == 'p' ) | |||
| { | |||
| jack_card->channel_type = SND_PCM_CHANNEL_PLAYBACK; | |||
| } | |||
| else if( value[0] == 'C' || value[0] == 'c' ) | |||
| { | |||
| jack_card->channel_type = SND_PCM_CHANNEL_CAPTURE; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| ado_error( | |||
| "type option value not 'c' or 'p'; defaulting to 'p'" ); | |||
| jack_card->channel_type = SND_PCM_CHANNEL_PLAYBACK; | |||
| } | |||
| break; | |||
| case 3: /* voices: number of voices in io-audio channel and JACK ports */ | |||
| if( NULL != value ) | |||
| { | |||
| char* endptr; | |||
| int val; | |||
| errno = 0; /* To distinguish success/failure after call */ | |||
| val = strtol( value, | |||
| &endptr, | |||
| 0 ); | |||
| /* Check for various possible errors */ | |||
| if( ( errno == ERANGE | |||
| && ( val == LONG_MAX || val == LONG_MIN ) ) | |||
| || ( errno != 0 && val == 0 ) ) | |||
| { | |||
| ado_error( "voices option value out of range" ); | |||
| return errno; | |||
| } | |||
| if( endptr == value ) | |||
| { | |||
| ado_error( "voices option value contains no digits" ); | |||
| return EINVAL; | |||
| } | |||
| jack_card->voices = val; | |||
| } | |||
| else | |||
| { | |||
| ado_error( "voices option given without value; failing" ); | |||
| return EINVAL; | |||
| } | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: found unknown argument %s", | |||
| value ); | |||
| } | |||
| } | |||
| ado_free( argdup ); | |||
| return EOK; | |||
| } | |||
| int32_t cb_capabilities( | |||
| HW_CONTEXT_T * mcasp_card, | |||
| ado_pcm_t *pcm, | |||
| snd_pcm_channel_info_t * info ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: capabilities()" ); | |||
| return EOK; | |||
| } | |||
| int32_t cb_aquire( | |||
| HW_CONTEXT_T *jack_card, | |||
| PCM_SUBCHN_CONTEXT_T **pc, | |||
| ado_pcm_config_t *config, | |||
| ado_pcm_subchn_t *subchn, | |||
| uint32_t *why_failed ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: aquire()" ); | |||
| if( jack_card->subchn.pcm_subchn ) | |||
| { | |||
| *why_failed = SND_PCM_PARAMS_NO_CHANNEL; | |||
| return ( EAGAIN ); | |||
| } | |||
| /* | |||
| * Create shared memory region for ringbuffer | |||
| */ | |||
| config->dmabuf.addr = ado_shm_alloc( config->dmabuf.size, | |||
| config->dmabuf.name, | |||
| ADO_SHM_DMA_SAFE, | |||
| &config->dmabuf.phys_addr ); | |||
| /* | |||
| * Set up JACK ringbuffer structure to use SHM region instead of own | |||
| * buffer. | |||
| */ | |||
| jack_card->ringbuffer.buf = (char*)config->dmabuf.addr; | |||
| jack_card->ringbuffer.size = config->dmabuf.size; | |||
| jack_card->ringbuffer.size_mask = config->dmabuf.size - 1; | |||
| jack_ringbuffer_reset( &jack_card->ringbuffer ); | |||
| /* | |||
| * Store parameters for future use | |||
| */ | |||
| jack_card->subchn.pcm_config = config; | |||
| jack_card->subchn.pcm_subchn = subchn; | |||
| /* | |||
| * Set output parameters | |||
| */ | |||
| *pc = &jack_card->subchn; | |||
| return EOK; | |||
| } | |||
| int32_t cb_release( | |||
| HW_CONTEXT_T *jack_card, | |||
| PCM_SUBCHN_CONTEXT_T *pc, | |||
| ado_pcm_config_t *config ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: release()" ); | |||
| pthread_mutex_lock( &jack_card->process_lock ); | |||
| jack_card->subchn.go = 0; | |||
| jack_ringbuffer_reset( &jack_card->ringbuffer ); | |||
| ado_shm_free( pc->pcm_config->dmabuf.addr, | |||
| pc->pcm_config->dmabuf.size, | |||
| pc->pcm_config->dmabuf.name ); | |||
| pc->pcm_subchn = NULL; | |||
| pthread_mutex_unlock( &jack_card->process_lock ); | |||
| return EOK; | |||
| } | |||
| int32_t cb_prepare( | |||
| HW_CONTEXT_T *jack_card, | |||
| PCM_SUBCHN_CONTEXT_T *pc, | |||
| ado_pcm_config_t *config ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: prepare()" ); | |||
| jack_ringbuffer_reset( &jack_card->ringbuffer ); | |||
| return EOK; | |||
| } | |||
| int32_t cb_trigger( | |||
| HW_CONTEXT_T *jack_card, | |||
| PCM_SUBCHN_CONTEXT_T *pc, | |||
| uint32_t cmd ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: trigger( %d )", | |||
| cmd ); | |||
| if( ADO_PCM_TRIGGER_STOP == cmd ) | |||
| { | |||
| jack_card->subchn.go = 0; | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: ADO_PCM_TRIGGER_STOP" ); | |||
| } | |||
| else if( ADO_PCM_TRIGGER_GO == cmd ) | |||
| { | |||
| /* | |||
| * Signal readiness to JACK and ADO | |||
| */ | |||
| jack_card->subchn.go = 1; | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: ADO_PCM_TRIGGER_GO" ); | |||
| } | |||
| else | |||
| { | |||
| jack_card->subchn.go = 0; | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: ADO_PCM_TRIGGER_SYNC_AND_GO" ); | |||
| } | |||
| return EOK; | |||
| } | |||
| uint32_t cb_position( | |||
| HW_CONTEXT_T *jack_card, | |||
| PCM_SUBCHN_CONTEXT_T *pc, | |||
| ado_pcm_config_t *config ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: position()" ); | |||
| return EOK; | |||
| } | |||
| void irq_handler( | |||
| HW_CONTEXT_T *jack_card, | |||
| int32_t event ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: irq_handler()" ); | |||
| } | |||
| /** | |||
| * Prototype for the client supplied function that is called | |||
| * by the engine anytime there is work to be done. | |||
| * | |||
| * @pre nframes == jack_get_buffer_size() | |||
| * @pre nframes == pow(2,x) | |||
| * | |||
| * @param nframes number of frames to process | |||
| * @param arg pointer to a client supplied structure | |||
| * | |||
| * @return zero on success, non-zero on error | |||
| */ | |||
| int jack_process( | |||
| jack_nframes_t nframes, | |||
| void *arg ) | |||
| { | |||
| int v; | |||
| jack_card_t* jack_card = (jack_card_t*)arg; | |||
| size_t total_size = nframes * sizeof(sample_t); | |||
| size_t size_completed; | |||
| if( ( jack_card->fragsize != total_size ) ) | |||
| { | |||
| ado_error( | |||
| "deva_ctrl-jack: mismatch of fragment size with number of frames requested" ); | |||
| } | |||
| /* | |||
| * Try to lock the process mutex. If the lock can't be acquired, assume something is happening with the subchannel | |||
| * and write zeroes to JACK instead. | |||
| */ | |||
| if( jack_card->subchn.go | |||
| && ( 0 == pthread_mutex_trylock( &jack_card->process_lock ) ) ) | |||
| { | |||
| int voices = jack_card->subchn.pcm_config->format.voices; | |||
| size_t size_per_voice = total_size / voices; | |||
| void* jack_buf[voices]; | |||
| for( v = 0; v < voices; ++v ) | |||
| { | |||
| jack_buf[v] = jack_port_get_buffer( jack_card->ports[v], | |||
| nframes ); | |||
| } | |||
| for( size_completed = 0; size_completed < total_size; size_completed += | |||
| size_per_voice ) | |||
| { | |||
| for( v = 0; v < voices; ++v ) | |||
| { | |||
| /* | |||
| * Advance ringbuffer write pointer on the assumption that io-audio has filled in nframes of data | |||
| */ | |||
| jack_ringbuffer_write_advance( &jack_card->ringbuffer, | |||
| size_per_voice ); | |||
| jack_ringbuffer_data_t read_buf[2]; | |||
| jack_ringbuffer_get_read_vector( &jack_card->ringbuffer, | |||
| read_buf ); | |||
| if( SND_PCM_SFMT_FLOAT_LE | |||
| == jack_card->subchn.pcm_config->format.format ) | |||
| { | |||
| jack_ringbuffer_read( &jack_card->ringbuffer, | |||
| jack_buf[v], | |||
| size_per_voice ); | |||
| } | |||
| else if( SND_PCM_SFMT_S32_LE | |||
| == jack_card->subchn.pcm_config->format.format ) | |||
| { | |||
| int s; | |||
| size_t remaining = size_per_voice / sizeof(sample_t); | |||
| read_buf[0].len /= sizeof(sample_t); | |||
| read_buf[1].len /= sizeof(sample_t); | |||
| int32_t* src = (sample_t*)read_buf[0].buf; | |||
| sample_t* dest = (sample_t*)jack_buf[v]; | |||
| size_t amt = min( read_buf[0].len, | |||
| remaining ); | |||
| for( s = 0; s < amt; s += sizeof(sample_t) ) | |||
| { | |||
| dest[s] = ( (sample_t)src[s] ) * ( (sample_t)1.0 ) | |||
| / ( (sample_t)INT_MAX ); | |||
| } | |||
| remaining -= amt; | |||
| if( remaining > 0 ) | |||
| { | |||
| src = (int32_t*)read_buf[1].buf; | |||
| dest += amt; | |||
| amt = min( read_buf[1].len, | |||
| remaining ); | |||
| for( s = 0; s < amt; s += sizeof(sample_t) ) | |||
| { | |||
| dest[s] = ( (sample_t)src[s] ) * ( (sample_t)1.0 ) | |||
| / ( (sample_t)INT_MAX ); | |||
| } | |||
| } | |||
| jack_ringbuffer_read_advance( &jack_card->ringbuffer, | |||
| size_per_voice ); | |||
| } | |||
| jack_buf[v] += size_per_voice; | |||
| } | |||
| dma_interrupt( jack_card->subchn.pcm_subchn ); | |||
| } | |||
| pthread_mutex_unlock( &jack_card->process_lock ); | |||
| } | |||
| else | |||
| { | |||
| /* | |||
| * In the case where there is no subchannel or we can't aquire the ringbuffer lock, | |||
| * write zeroes to the JACK buffers rather than let stale data sit in them. | |||
| */ | |||
| for( v = 0; v < jack_card->voices; ++v ) | |||
| { | |||
| void* jack_buf = jack_port_get_buffer( jack_card->ports[v], | |||
| nframes ); | |||
| memset( jack_buf, | |||
| 0, | |||
| total_size ); | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| /** | |||
| * Prototype for the client supplied function that is called | |||
| * whenever jackd is shutdown. Note that after server shutdown, | |||
| * the client pointer is *not* deallocated by libjack, | |||
| * the application is responsible to properly use jack_client_close() | |||
| * to release client ressources. Warning: jack_client_close() cannot be | |||
| * safely used inside the shutdown callback and has to be called outside of | |||
| * the callback context. | |||
| * | |||
| * @param arg pointer to a client supplied structure | |||
| */ | |||
| void jack_shutdown( | |||
| void *arg ) | |||
| { | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: jack_shutdown" ); | |||
| jack_card_t* card = (jack_card_t*)arg; | |||
| /* | |||
| * TODO | |||
| * Find a way to trigger io-audio to call ctrl_destroy() to clean up | |||
| */ | |||
| } | |||
| ado_ctrl_dll_init_t ctrl_init; | |||
| int ctrl_init( | |||
| HW_CONTEXT_T ** hw_context, | |||
| ado_card_t * card, | |||
| char *args ) | |||
| { | |||
| int retval; | |||
| int i; | |||
| jack_card_t* jack_card; | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: ctrl_init" ); | |||
| jack_card = ado_calloc( 1, | |||
| sizeof(jack_card_t) ); | |||
| if( NULL == jack_card ) | |||
| { | |||
| ado_error( "Unable to allocate memory for jack_card (%s)", | |||
| strerror( errno ) ); | |||
| return -1; | |||
| } | |||
| *hw_context = jack_card; | |||
| jack_card->card = card; | |||
| pthread_mutex_init( &jack_card->process_lock, | |||
| NULL ); | |||
| ado_card_set_shortname( card, | |||
| "jack_card" ); | |||
| ado_card_set_longname( card, | |||
| "jack_card", | |||
| 0x1000 ); | |||
| retval = parse_commandline( jack_card, | |||
| args ); | |||
| if( EOK != retval ) | |||
| { | |||
| ado_error( | |||
| "Received error from parse_commandline(): %d; cannot continue", | |||
| retval ); | |||
| return -1; | |||
| } | |||
| /* | |||
| * Create client per command line arguments | |||
| */ | |||
| int client_name_size = jack_client_name_size(); | |||
| if( strlen( jack_card->name ) > client_name_size ) | |||
| { | |||
| ado_error( | |||
| "Client name %s is too long (%d chars).\nPlease use a client name of %d characters or less.", | |||
| strlen( jack_card->name ), | |||
| client_name_size ); | |||
| return -1; | |||
| } | |||
| jack_status_t open_status; | |||
| if( NULL != jack_card->server ) | |||
| { | |||
| jack_card->client = jack_client_open( jack_card->name, | |||
| JackServerName, | |||
| &open_status, | |||
| jack_card->server ); | |||
| } | |||
| else | |||
| { | |||
| jack_card->client = jack_client_open( jack_card->name, | |||
| JackNullOption, | |||
| &open_status ); | |||
| } | |||
| if( NULL == jack_card->client ) | |||
| { | |||
| ado_error( "Error opening JACK client (%x)", | |||
| open_status ); | |||
| ado_free( jack_card ); | |||
| return -1; | |||
| } | |||
| /* | |||
| * Set JACK and ADO processing callbacks | |||
| */ | |||
| jack_set_process_callback( jack_card->client, | |||
| jack_process, | |||
| jack_card ); | |||
| jack_on_shutdown( jack_card->client, | |||
| jack_shutdown, | |||
| 0 ); | |||
| /* | |||
| * Allocate jack_port_t array | |||
| */ | |||
| int voices = jack_card->voices; | |||
| jack_card->ports = ado_calloc( voices, | |||
| sizeof(jack_port_t*) ); | |||
| /* | |||
| * Register JACK ports and create their ringbuffers | |||
| */ | |||
| int port_name_size = jack_port_name_size(); | |||
| char* portname = calloc( jack_port_name_size(), | |||
| sizeof(char) ); | |||
| for( i = 0; i < voices; ++i ) | |||
| { | |||
| snprintf( portname, | |||
| port_name_size, | |||
| PORTNAME_FMT, | |||
| ( i + 1 ) ); | |||
| jack_card->ports[i] = jack_port_register( jack_card->client, | |||
| portname, | |||
| JACK_DEFAULT_AUDIO_TYPE, | |||
| JackPortIsOutput, | |||
| 0 ); | |||
| } | |||
| free( portname ); | |||
| /* | |||
| * Initialize Capabilities | |||
| */ | |||
| jack_card->caps.chn_flags = SND_PCM_CHNINFO_BLOCK | |||
| | SND_PCM_CHNINFO_NONINTERLEAVE; | |||
| jack_card->caps.formats = 0xFFFF; | |||
| jack_card->caps.formats = SND_PCM_FMT_FLOAT_LE | SND_PCM_FMT_S32_LE; | |||
| jack_nframes_t rate = jack_get_sample_rate( jack_card->client ); | |||
| uint32_t rateflag = ado_pcm_rate2flag( rate ); | |||
| jack_card->caps.rates = rateflag; | |||
| jack_card->caps.min_voices = 1; | |||
| jack_card->caps.max_voices = jack_card->voices; | |||
| /* | |||
| * Get size of ringbuffer from JACK server | |||
| */ | |||
| jack_card->fragsize = jack_get_buffer_size( jack_card->client ) | |||
| * sizeof(sample_t); | |||
| jack_card->caps.min_fragsize = jack_card->fragsize; | |||
| jack_card->caps.max_fragsize = jack_card->fragsize; | |||
| jack_card->caps.max_dma_size = 0; | |||
| jack_card->caps.max_frags = 0; | |||
| jack_card->funcs.capabilities2 = cb_capabilities; | |||
| jack_card->funcs.aquire = cb_aquire; | |||
| jack_card->funcs.release = cb_release; | |||
| jack_card->funcs.prepare = cb_prepare; | |||
| jack_card->funcs.trigger = cb_trigger; | |||
| jack_card->funcs.position = cb_position; | |||
| /* | |||
| * Create Audio PCM Device | |||
| */ | |||
| retval = ado_pcm_create( card, | |||
| "JACK io-audio driver", | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_PLAYBACK ) ? | |||
| SND_PCM_INFO_PLAYBACK : SND_PCM_INFO_CAPTURE, | |||
| "jack-audio", | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_PLAYBACK ) ? 1 : 0, | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_PLAYBACK ) ? | |||
| &jack_card->caps : NULL, | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_PLAYBACK ) ? | |||
| &jack_card->funcs : NULL, | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_CAPTURE ) ? 1 : 0, | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_CAPTURE ) ? | |||
| &jack_card->caps : NULL, | |||
| ( jack_card->channel_type | |||
| == SND_PCM_CHANNEL_CAPTURE ) ? | |||
| &jack_card->funcs : NULL, | |||
| &jack_card->pcm ); | |||
| if( -1 == retval ) | |||
| { | |||
| ado_error( "deva_ctrl_jack: ERROR: %s", | |||
| strerror( errno ) ); | |||
| ado_free( jack_card->ports ); | |||
| ado_free( jack_card ); | |||
| return -1; | |||
| } | |||
| /* | |||
| * Activate JACK client | |||
| */ | |||
| return jack_activate( jack_card->client ); | |||
| } | |||
| ado_ctrl_dll_destroy_t ctrl_destroy; | |||
| int ctrl_destroy( | |||
| HW_CONTEXT_T * context ) | |||
| { | |||
| jack_card_t* jack_card = (jack_card_t*)context; | |||
| ado_debug( DB_LVL_DRIVER, | |||
| "deva-ctrl-jack: ctrl_destroy()" ); | |||
| jack_deactivate( jack_card->client ); | |||
| jack_client_close( jack_card->client ); | |||
| ado_free( jack_card->ports ); | |||
| ado_free( jack_card->server ); | |||
| ado_free( jack_card->name ); | |||
| pthread_mutex_destroy( &jack_card->process_lock ); | |||
| ado_free( jack_card ); | |||
| return EOK; | |||
| } | |||
| ado_dll_version_t ctrl_version; | |||
| void ctrl_version( | |||
| int *major, | |||
| int *minor, | |||
| char *date ) | |||
| { | |||
| *major = ADO_MAJOR_VERSION; | |||
| *minor = 1; | |||
| date = __DATE__; | |||
| } | |||
| int ctrl_devctl( | |||
| uint32_t cmd, | |||
| uint8_t *msg, | |||
| uint16_t *msg_size, | |||
| HW_CONTEXT_T *context ) | |||
| { | |||
| } | |||
| @@ -0,0 +1,43 @@ | |||
| def configure(conf): | |||
| conf.check_cc(lib='asound', header_name='audio_driver.h', uselib_store='IOAUDIO', define_name="HAVE_IOAUDIO", mandatory=False) | |||
| if conf.is_defined('HAVE_IOAUDIO'): | |||
| conf.env['BUILD_DRIVER_IOAUDIO'] = True | |||
| def create_jack_driver_obj(bld, target, sources, uselib=None): | |||
| driver = bld(features=['c', 'cxx', 'cxxshlib', 'cshlib']) | |||
| driver.env['cxxshlib_PATTERN'] = 'jack_%s.so' | |||
| driver.defines = ['HAVE_CONFIG_H', 'SERVER_SIDE', 'HAVE_PPOLL', 'HAVE_TIMERFD'] | |||
| driver.includes = ['.', '../qnx', '../posix', '../common', '../common/jack', '../dbus', '../'] | |||
| driver.target = target | |||
| driver.source = sources | |||
| driver.install_path = '${ADDON_DIR}/' | |||
| driver.use = [] | |||
| driver.cflags = [] | |||
| if uselib: | |||
| driver.use += uselib | |||
| return driver | |||
| def build(bld): | |||
| if bld.env['BUILD_JACKD'] == True: | |||
| jackd = bld(features=['cxx', 'cxxprogram']) | |||
| jackd.includes = ['../qnx', '../posix', '../common/jack', '../common', '../dbus', '../'] | |||
| jackd.defines = ['HAVE_CONFIG_H', 'SERVER_SIDE'] | |||
| jackd.source = ['../common/Jackdmp.cpp'] | |||
| jackd.use = ['serverlib'] | |||
| if bld.env['IS_QNX'] and bld.env['BUILD_JACKDBUS']: | |||
| jackd.source += ['../dbus/reserve.c', '../dbus/audio_reserve.c'] | |||
| jackd.use += ['PTHREAD', 'DL', 'RT', 'M', 'STDC++', 'DBUS-1'] | |||
| else: | |||
| jackd.use += ['PTHREAD', 'DL', 'RT', 'M', 'STDC++'] | |||
| jackd.target = 'jackd' | |||
| create_jack_driver_obj(bld, 'dummy', '../common/JackDummyDriver.cpp') | |||
| create_jack_driver_obj(bld, 'loopback', '../common/JackLoopbackDriver.cpp') | |||
| if bld.env['BUILD_DRIVER_IOAUDIO']: | |||
| deva = create_jack_driver_obj(bld, 'jack', 'ioaudio/ioaudio_driver.c', ['IOAUDIO', 'clientlib', 'PTHREAD']) | |||
| deva.env['cxxshlib_PATTERN'] = 'deva-ctrl-%s.so' | |||
| deva.install_path = '/lib/dll' | |||
| @@ -17,7 +17,7 @@ | |||
| */ | |||
| #include "external_metro.h" | |||
| #include <stdio.h> | |||
| #include <cstdio> | |||
| typedef jack_default_audio_sample_t sample_t; | |||
| @@ -21,18 +21,13 @@ | |||
| #ifndef __external_metro__ | |||
| #define __external_metro__ | |||
| #ifdef __cplusplus | |||
| extern "C" | |||
| { | |||
| #endif | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <errno.h> | |||
| #include <cstdlib> | |||
| #include <cstdio> | |||
| #include <cerrno> | |||
| #include <unistd.h> | |||
| #include <math.h> | |||
| #include <cmath> | |||
| #include <getopt.h> | |||
| #include <string.h> | |||
| #include <cstring> | |||
| #include <jack/jack.h> | |||
| #include <jack/transport.h> | |||
| @@ -63,8 +58,4 @@ extern "C" | |||
| static void shutdown (void* arg); | |||
| }; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif | |||
| @@ -479,7 +479,7 @@ int process4(jack_nframes_t nframes, void *arg) | |||
| jack_nframes_t delta_time = cur_time - last_time; | |||
| Log("calling process4 callback : jack_frame_time = %ld delta_time = %ld\n", cur_time, delta_time); | |||
| if (delta_time > 0 && (jack_nframes_t)abs(delta_time - cur_buffer_size) > tolerance) { | |||
| if (delta_time > 0 && (jack_nframes_t)abs((int64_t)delta_time - (int64_t)cur_buffer_size) > tolerance) { | |||
| printf("!!! ERROR !!! jack_frame_time seems to return incorrect values cur_buffer_size = %d, delta_time = %d tolerance %d\n", cur_buffer_size, delta_time, tolerance); | |||
| } | |||
| @@ -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 | |||
| @@ -395,7 +395,7 @@ def options(opt): | |||
| opt.add_option('--mandir', type='string', help="Manpage directory [Default: <prefix>/share/man/man1]") | |||
| # options affecting binaries | |||
| opt.add_option('--dist-target', type='string', default='auto', help='Specify the target for cross-compiling [auto,mingw]') | |||
| opt.add_option('--dist-target', type='string', default='auto', help='Specify the target for cross-compiling [auto,mingw,qnx]') | |||
| opt.add_option('--mixed', action='store_true', default=False, help='Build with 32/64 bits mixed mode') | |||
| opt.add_option('--debug', action='store_true', default=False, dest='debug', help='Build debuggable binaries') | |||
| @@ -438,6 +438,8 @@ def options(opt): | |||
| readline.add_library('readline') | |||
| readline.set_check_hook(check_for_readline, check_for_readline_error) | |||
| ioaudio = add_auto_option(opt, 'ioaudio', help='Enable io-audio driver', conf_dest='BUILD_DRIVER_IOAUDIO') | |||
| # dbus options | |||
| opt.recurse('dbus') | |||
| @@ -457,6 +459,8 @@ def configure(conf): | |||
| conf.env['IS_LINUX'] = True | |||
| elif Options.options.dist_target == 'mingw': | |||
| conf.env['IS_WINDOWS'] = True | |||
| elif Options.options.dist_target == 'qnx': | |||
| conf.env['IS_QNX'] = True | |||
| if conf.env['IS_LINUX']: | |||
| Logs.pprint('CYAN', "Linux detected") | |||
| @@ -464,6 +468,9 @@ def configure(conf): | |||
| if conf.env['IS_MACOSX']: | |||
| Logs.pprint('CYAN', "MacOS X detected") | |||
| if conf.env['IS_QNX']: | |||
| Logs.pprint('CYAN', "Cross compile to QNX") | |||
| if conf.env['IS_SUN']: | |||
| Logs.pprint('CYAN', "SunOS detected") | |||
| @@ -483,6 +490,8 @@ def configure(conf): | |||
| conf.recurse('common') | |||
| if conf.env['IS_LINUX']: | |||
| conf.recurse('linux') | |||
| if conf.env['IS_QNX']: | |||
| conf.recurse('qnx') | |||
| if Options.options.dbus: | |||
| conf.recurse('dbus') | |||
| if conf.env['BUILD_JACKDBUS'] != True: | |||
| @@ -495,6 +504,14 @@ def configure(conf): | |||
| conf.env['LIB_RT'] = ['rt'] | |||
| conf.env['LIB_M'] = ['m'] | |||
| conf.env['LIB_STDC++'] = ['stdc++'] | |||
| if conf.env['IS_QNX']: | |||
| conf.env['LIB_PTHREAD'] = ['c'] | |||
| conf.env['LIB_DL'] = ['c'] | |||
| conf.env['LIB_RT'] = [] | |||
| conf.check_cxx( lib=['rt'], uselib_store='RT', mandatory=False ) | |||
| conf.check_cxx( lib=['socket'], uselib_store='SOCKET' ) | |||
| conf.env['JACK_API_VERSION'] = JACK_API_VERSION | |||
| conf.env['JACK_VERSION'] = VERSION | |||
| @@ -508,6 +525,15 @@ def configure(conf): | |||
| else: | |||
| conf.env['BUILD_JACKD'] = True | |||
| path = os.path | |||
| if sys.platform == 'win32' and (conf.env['IS_QNX'] or conf.env['IS_LINUX']): | |||
| # If we are cross-compiling from Windows to a system with POSIX style filenames, | |||
| # we need to construct file paths using posixpath instead of os.path. Also, we | |||
| # need fix PREFIX, since Waf constructed it incorrectly | |||
| import posixpath | |||
| path = posixpath | |||
| conf.env['PREFIX'] = os.path.splitdrive(conf.env['PREFIX'])[1].replace('\\', '/') | |||
| conf.env['BINDIR'] = conf.env['PREFIX'] + '/bin' | |||
| if Options.options.htmldir: | |||
| @@ -564,9 +590,9 @@ def configure(conf): | |||
| # don't define ADDON_DIR in config.h, use the default 'jack' defined in | |||
| # windows/JackPlatformPlug_os.h | |||
| else: | |||
| conf.env['ADDON_DIR'] = os.path.normpath(os.path.join(conf.env['LIBDIR'], 'jack')) | |||
| conf.env['ADDON_DIR'] = path.normpath(path.join(conf.env['LIBDIR'], 'jack')) | |||
| conf.define('ADDON_DIR', conf.env['ADDON_DIR']) | |||
| conf.define('JACK_LOCATION', os.path.normpath(os.path.join(conf.env['PREFIX'], 'bin'))) | |||
| conf.define('JACK_LOCATION', path.normpath(path.join(conf.env['PREFIX'], 'bin'))) | |||
| if not conf.env['IS_WINDOWS']: | |||
| conf.define('USE_POSIX_SHM', 1) | |||
| @@ -716,6 +742,14 @@ def build(bld): | |||
| if bld.env['BUILD_JACKDBUS'] == True: | |||
| bld.recurse('dbus') | |||
| if bld.env['IS_QNX']: | |||
| bld.recurse('qnx') | |||
| bld.recurse('example-clients') | |||
| bld.recurse('tests') | |||
| bld.recurse('man') | |||
| if bld.env['BUILD_JACKDBUS'] == True: | |||
| bld.recurse('dbus') | |||
| if bld.env['IS_SUN']: | |||
| bld.recurse('solaris') | |||
| bld.recurse('example-clients') | |||