Browse Source

Merge pull request #1 from AndrewCooper/qnx

Qnx
pull/244/head
Shaun Tierney 10 years ago
parent
commit
d49e6e290a
23 changed files with 2877 additions and 38 deletions
  1. +5
    -0
      common/JackAudioAdapterFactory.cpp
  2. +5
    -0
      common/JackControlAPI.cpp
  3. +1
    -1
      common/jack/systemdeps.h
  4. +31
    -15
      common/ringbuffer.c
  5. +45
    -0
      common/shm.c
  6. +49
    -0
      common/wscript
  7. +4
    -0
      dbus/wscript
  8. +8
    -1
      example-clients/wscript
  9. +1
    -0
      posix/JackNetUnixSocket.cpp
  10. +2
    -2
      posix/JackPosixSemaphore.cpp
  11. +86
    -0
      qnx/JackAtomic_os.h
  12. +90
    -0
      qnx/JackPlatformPlug_os.h
  13. +216
    -0
      qnx/JackQnxTime.c
  14. +30
    -0
      qnx/cycles.h
  15. +1209
    -0
      qnx/ioaudio/JackIoAudioAdapter.cpp
  16. +257
    -0
      qnx/ioaudio/JackIoAudioAdapter.h
  17. +749
    -0
      qnx/ioaudio/ioaudio_driver.c
  18. +43
    -0
      qnx/wscript
  19. +1
    -1
      tests/external_metro.cpp
  20. +5
    -14
      tests/external_metro.h
  21. +1
    -1
      tests/test.cpp
  22. +2
    -0
      tests/wscript
  23. +37
    -3
      wscript

+ 5
- 0
common/JackAudioAdapterFactory.cpp View File

@@ -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


+ 5
- 0
common/JackControlAPI.cpp View File

@@ -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++)
{


+ 1
- 1
common/jack/systemdeps.h View File

@@ -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>


+ 31
- 15
common/ringbuffer.c View File

@@ -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


+ 45
- 0
common/shm.c View File

@@ -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


+ 49
- 0
common/wscript View File

@@ -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)


+ 4
- 0
dbus/wscript View File

@@ -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


+ 8
- 1
example-clients/wscript View File

@@ -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']:


+ 1
- 0
posix/JackNetUnixSocket.cpp View File

@@ -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;



+ 2
- 2
posix/JackPosixSemaphore.cpp View File

@@ -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);
}
}



+ 86
- 0
qnx/JackAtomic_os.h View File

@@ -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


+ 90
- 0
qnx/JackPlatformPlug_os.h View File

@@ -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

+ 216
- 0
qnx/JackQnxTime.c View File

@@ -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();
}


+ 30
- 0
qnx/cycles.h View File

@@ -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__ */

+ 1209
- 0
qnx/ioaudio/JackIoAudioAdapter.cpp
File diff suppressed because it is too large
View File


+ 257
- 0
qnx/ioaudio/JackIoAudioAdapter.h View File

@@ -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

+ 749
- 0
qnx/ioaudio/ioaudio_driver.c View File

@@ -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 )
{

}


+ 43
- 0
qnx/wscript View File

@@ -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'

+ 1
- 1
tests/external_metro.cpp View File

@@ -17,7 +17,7 @@
*/

#include "external_metro.h"
#include <stdio.h>
#include <cstdio>

typedef jack_default_audio_sample_t sample_t;



+ 5
- 14
tests/external_metro.h View File

@@ -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

+ 1
- 1
tests/test.cpp View File

@@ -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);
}



+ 2
- 0
tests/wscript View File

@@ -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


+ 37
- 3
wscript View File

@@ -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')


Loading…
Cancel
Save