Browse Source

Merge 831f4e64b4 into ba28ffa3db

pull/463/merge
twischer-adit GitHub 5 years ago
parent
commit
39f0cf61fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1589 additions and 304 deletions
  1. +14
    -0
      Makefile
  2. +2
    -2
      common/JackAudioAdapterInterface.cpp
  3. +9
    -0
      common/JackClient.cpp
  4. +4
    -1
      common/JackControlAPI.cpp
  5. +1
    -1
      common/jack/systemdeps.h
  6. +2
    -0
      common/netjack_packet.c
  7. +60
    -9
      common/shm.c
  8. +25
    -7
      common/wscript
  9. +6
    -4
      example-clients/wscript
  10. +23
    -2
      linux/alsa/JackAlsaDriver.cpp
  11. +670
    -241
      linux/alsa/alsa_driver.c
  12. +40
    -22
      linux/alsa/alsa_driver.h
  13. +4
    -0
      linux/alsa/usx2y.h
  14. +1
    -1
      posix/JackFifo.h
  15. +86
    -0
      qnx/JackAtomic_os.h
  16. +215
    -0
      qnx/JackLinuxTime.c
  17. +85
    -0
      qnx/JackPlatformPlug_os.h
  18. +300
    -0
      qnx/driver.h
  19. +2
    -0
      tests/wscript
  20. +40
    -14
      wscript

+ 14
- 0
Makefile View File

@@ -0,0 +1,14 @@
.PHONY: all
all:
CC=${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-gcc CXX=${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-g++ AR=${QNX_HOST}/usr/bin/aarch64-unknown-nto-qnx7.0.0-ar LDFLAGS="-L${INSTALL_ROOT_nto}/aarch64le/lib -L${INSTALL_ROOT_nto}/aarch64le/usr/lib -L${QNX_TARGET}/aarch64le/lib -L${QNX_TARGET}/aarch64le/usr/lib" PKG_CONFIG_LIBDIR=${INSTALL_ROOT_nto}/aarch64le/usr/lib/pkgconfig ./waf configure --platform=qnx --prefix=/usr --libdir=/usr/lib64
./waf build
./waf install --destdir=${INSTALL_ROOT_nto}/aarch64le

.PHONY: install
install: all

.PHONY:clean
clean:
# ignore error codes otherwise it would for example fail if clean is called before configure
-./waf clean


+ 2
- 2
common/JackAudioAdapterInterface.cpp View File

@@ -22,7 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#endif

#include "JackAudioAdapter.h"
#ifndef MY_TARGET_OS_IPHONE
#if !defined(MY_TARGET_OS_IPHONE) && !defined(__QNXNTO__)
#include "JackLibSampleRateResampler.h"
#endif
#include "JackTime.h"
@@ -185,7 +185,7 @@ namespace Jack
fRunning = false;
}

#ifdef MY_TARGET_OS_IPHONE
#if defined(MY_TARGET_OS_IPHONE) || defined(__QNXNTO__)
void JackAudioAdapterInterface::Create()
{}
#else


+ 9
- 0
common/JackClient.cpp View File

@@ -34,6 +34,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

using namespace std;

#ifdef __QNXNTO__
void __attribute__((constructor)) init_output_for_percent_s_NULL_for_clients();
void init_output_for_percent_s_NULL_for_clients()
{
extern const char *output_for_percent_s_NULL;
output_for_percent_s_NULL = "(null)";
}
#endif

namespace Jack
{



+ 4
- 1
common/JackControlAPI.cpp View File

@@ -663,7 +663,10 @@ jackctl_setup_signals(
sigfillset(&allsignals);
action.sa_handler = signal_handler;
action.sa_mask = allsignals;
action.sa_flags = SA_RESTART|SA_RESETHAND;
action.sa_flags = SA_RESETHAND;
#ifndef __QNXNTO__
action.sa_flags |= SA_RESTART;
#endif

for (i = 1; i < NSIG; i++)
{


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

@@ -107,7 +107,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#endif /* _WIN32 && !__CYGWIN__ && !GNU_WIN32 */

#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32)
#if defined(__APPLE__) || defined(__linux__) || defined(__sun__) || defined(sun) || defined(__unix__) || defined(__CYGWIN__) || defined(GNU_WIN32) || defined(__QNXNTO__)

#if defined(__CYGWIN__) || defined(GNU_WIN32)
#include <stdint.h>


+ 2
- 0
common/netjack_packet.c View File

@@ -428,7 +428,9 @@ netjack_poll (int sockfd, int timeout)

action.sa_handler = SIG_DFL;
action.sa_mask = sigmask;
#ifndef __QNXNTO__
action.sa_flags = SA_RESTART;
#endif

for (i = 1; i < NSIG; i++)
if (sigismember (&sigmask, i))


+ 60
- 9
common/shm.c View File

@@ -49,11 +49,16 @@
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <stdlib.h>
#include "promiscuous.h"

#ifdef __QNXNTO__
#include <sys/mman.h>
#else
#include <sys/shm.h>
#endif

#endif

#include "shm.h"
@@ -148,8 +153,6 @@ static jack_shm_registry_t *jack_shm_registry = NULL;
#define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY
#endif

static int semid = -1;

#ifdef WIN32

#include <psapi.h>
@@ -178,12 +181,61 @@ static BOOL check_process_running(DWORD process_id)
}

static int
semaphore_init () {return 0;}
jack_shm_lock_registry () {return 0;}

static void
jack_shm_unlock_registry () { }

#elif __QNXNTO__
#include <semaphore.h>

static sem_t* semid = SEM_FAILED;

static int
semaphore_init ()
{
const char name[] = "/jack-shm-registry-lock";
const int oflag = O_CREAT | O_RDWR;
const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
if ((semid = sem_open(name, oflag, mode, 1)) == SEM_FAILED) {
jack_error("Creating semaphore %s failed", name);
return -1;
}

return 0;
}

static int
jack_shm_lock_registry (void)
{
if (semid == SEM_FAILED) {
if (semaphore_init () < 0)
return -1;
}

// TODO automatically unblock in case the process terminates
const int ret = sem_wait(semid);
if (ret < 0) {
jack_error("sem_wait() failed with %s", strerror(ret));
return -1;
}

static int
semaphore_add (int value) {return 0;}
return 0;
}

static void
jack_shm_unlock_registry (void)
{
const int ret = sem_post(semid);

if (ret < 0) {
jack_error("sem_post() failed with %s", strerror(ret));
}
}

#else
static int semid = -1;

/* all semaphore errors are fatal -- issue message, but do not return */
static void
semaphore_error (char *msg)
@@ -247,8 +299,6 @@ semaphore_add (int value)
return 0;
}

#endif

static int
jack_shm_lock_registry (void)
{
@@ -266,6 +316,8 @@ jack_shm_unlock_registry (void)
semaphore_add (1);
}

#endif

static void
jack_shm_init_registry ()
{
@@ -1308,4 +1360,3 @@ jack_attach_shm_read (jack_shm_info_t* si)
}

#endif /* !USE_POSIX_SHM */


+ 25
- 7
common/wscript View File

@@ -28,6 +28,8 @@ def create_jack_process_obj(bld, target, sources, uselib = None, framework = Non
env_includes = ['../macosx', '../posix', '../macosx/coreaudio']
if bld.env['IS_LINUX']:
env_includes = ['../linux', '../posix', '../linux/alsa']
if bld.env['IS_QNX']:
env_includes = ['../qnx', '../posix']
if bld.env['IS_SUN']:
env_includes = ['../solaris', '../posix', '../solaris/oss']
if bld.env['IS_WINDOWS']:
@@ -36,7 +38,7 @@ def create_jack_process_obj(bld, target, sources, uselib = None, framework = Non
process.name = target
process.target = target
process.source = sources
if bld.env['IS_LINUX'] or bld.env['IS_MACOSX']:
if bld.env['IS_LINUX'] or bld.env['IS_MACOSX'] or bld.env['IS_QNX']:
process.env.append_value('CPPFLAGS', '-fvisibility=hidden')
process.install_path = '${ADDON_DIR}/'
process.use = [uselib.name]
@@ -92,6 +94,22 @@ def build(bld):
uselib.append('RT')
uselib.append('DL')

if bld.env['IS_QNX']:
common_libsources += [
'JackDebugClient.cpp',
'timestamps.c',
'promiscuous.c',
'../posix/JackPosixThread.cpp',
'../posix/JackPosixProcessSync.cpp',
'../posix/JackPosixMutex.cpp',
'../posix/JackSocket.cpp',
'../posix/JackFifo.cpp',
'../linux/JackLinuxTime.c',
]
includes = ['../qnx', '../posix'] + includes
uselib.append('SOCKET')
# libdl and librt is included in libc in QNX

if bld.env['IS_SUN']:
common_libsources += [
'JackDebugClient.cpp',
@@ -163,7 +181,7 @@ def build(bld):
'JackMetadata.cpp',
]

if bld.env['IS_LINUX']:
if bld.env['IS_LINUX'] or bld.env['IS_QNX']:
clientlib.source += [
'../posix/JackSocketClientChannel.cpp',
'../posix/JackPosixServerLaunch.cpp',
@@ -192,7 +210,7 @@ def build(bld):
if not bld.env['IS_WINDOWS']:
clientlib.vnum = bld.env['JACK_API_VERSION']

if bld.env['IS_LINUX']:
if bld.env['IS_LINUX'] or bld.env['IS_QNX']:
clientlib.env.append_value('CPPFLAGS', '-fvisibility=hidden')

if bld.env['IS_MACOSX']:
@@ -270,7 +288,7 @@ def build(bld):
'JackMetadata.cpp',
]

if bld.env['IS_LINUX']:
if bld.env['IS_LINUX'] or bld.env['IS_QNX']:
serverlib.source += [
'../posix/JackSocketServerChannel.cpp',
'../posix/JackSocketNotifyChannel.cpp',
@@ -307,7 +325,7 @@ def build(bld):
if not bld.env['IS_WINDOWS']:
serverlib.vnum = bld.env['JACK_API_VERSION']

if bld.env['IS_LINUX']:
if bld.env['IS_LINUX'] or bld.env['IS_QNX']:
serverlib.env.append_value('CPPFLAGS', '-fvisibility=hidden')

if bld.env['IS_MACOSX']:
@@ -333,7 +351,7 @@ def build(bld):
if skipshared:
netlib.env['SHLIB_MARKER'] = ''
netlib.use += ['WS2_32', 'WINMM']
elif not bld.env['IS_MACOSX']:
elif not bld.env['IS_MACOSX'] and not bld.env['IS_QNX']:
netlib.use += ['RT']
netlib.install_path = '${LIBDIR}'
netlib.source = [
@@ -347,7 +365,7 @@ def build(bld):
'JackGlobals.cpp',
'ringbuffer.c']

if bld.env['IS_LINUX']:
if bld.env['IS_LINUX'] or bld.env['IS_QNX']:
netlib.source += ['../posix/JackNetUnixSocket.cpp','../posix/JackPosixThread.cpp', '../posix/JackPosixMutex.cpp', '../linux/JackLinuxTime.c']
netlib.env.append_value('CPPFLAGS', '-fvisibility=hidden')



+ 6
- 4
example-clients/wscript View File

@@ -49,6 +49,8 @@ def build(bld):
os_incdir = ['../linux', '../posix']
if bld.env['IS_MACOSX']:
os_incdir = ['../macosx', '../posix']
if bld.env['IS_QNX']:
os_incdir = ['../qnx', '../posix']
if bld.env['IS_SUN']:
os_incdir = ['../solaris', '../posix']
if bld.env['IS_WINDOWS']:
@@ -76,7 +78,7 @@ def build(bld):
prog.use = use
if bld.env['IS_LINUX']:
prog.use += ['RT', 'M']
if bld.env['IS_SUN']:
if bld.env['IS_SUN'] or bld.env['IS_QNX']:
prog.use += ['M']
#prog.cflags = ['-Wno-deprecated-declarations', '-Wno-misleading-indentation']
#prog.cxxflags = ['-Wno-deprecated-declarations', '-Wno-misleading-indentation']
@@ -90,7 +92,7 @@ def build(bld):
prog.use = ['clientlib']
if bld.env['IS_LINUX']:
prog.use += ['RT', 'READLINE']
if bld.env['IS_MACOSX']:
if bld.env['IS_MACOSX'] or bld.env['IS_QNX']:
prog.use += ['READLINE']
if bld.env['IS_WINDOWS']:
prog.use += ['READLINE']
@@ -101,7 +103,7 @@ def build(bld):
prog.includes = os_incdir + ['../common/jack', '../common']
prog.source = 'capture_client.c'
prog.use = ['clientlib']
if bld.env['IS_MACOSX']:
if bld.env['IS_MACOSX'] or bld.env['IS_QNX']:
prog.use += ['SNDFILE']
if bld.env['IS_LINUX']:
prog.use += ['RT', 'SNDFILE']
@@ -111,7 +113,7 @@ def build(bld):
prog.uselib = ['SNDFILE']
prog.target = 'jack_rec'

if bld.env['IS_LINUX'] or bld.env['IS_MACOSX']:
if bld.env['IS_LINUX'] or bld.env['IS_MACOSX'] or bld.env['IS_QNX']:
prog = bld(features = 'c cprogram')
prog.includes = os_incdir + ['.', '..', '../common/jack', '../common']
prog.source = ['netsource.c', '../common/netjack_packet.c']


+ 23
- 2
linux/alsa/JackAlsaDriver.cpp View File

@@ -204,6 +204,7 @@ int JackAlsaDriver::Detach()
return JackAudioDriver::Detach();
}

#ifndef __QNXNTO__
extern "C" char* get_control_device_name(const char * device_name)
{
char * ctl_name;
@@ -233,7 +234,9 @@ extern "C" char* get_control_device_name(const char * device_name)

return ctl_name;
}
#endif

#ifndef __QNXNTO__
static int card_to_num(const char* device)
{
int err;
@@ -273,6 +276,7 @@ free:
fail:
return i;
}
#endif

int JackAlsaDriver::Open(jack_nframes_t nframes,
jack_nframes_t user_nperiods,
@@ -301,6 +305,8 @@ int JackAlsaDriver::Open(jack_nframes_t nframes,
}

alsa_midi_t *midi = 0;

#ifndef __QNXNTO__
#ifndef __ANDROID__
if (strcmp(midi_driver_name, "seq") == 0)
midi = alsa_seqmidi_new((jack_client_t*)this, 0);
@@ -333,6 +339,7 @@ int JackAlsaDriver::Open(jack_nframes_t nframes,
}
}
}
#endif

fDriver = alsa_driver_new ((char*)"alsa_pcm", (char*)playback_driver_name, (char*)capture_driver_name,
NULL,
@@ -356,12 +363,14 @@ int JackAlsaDriver::Open(jack_nframes_t nframes,
// ALSA driver may have changed the in/out values
fCaptureChannels = ((alsa_driver_t *)fDriver)->capture_nchannels;
fPlaybackChannels = ((alsa_driver_t *)fDriver)->playback_nchannels;
#ifndef __QNXNTO__
if (JackServerGlobals::on_device_reservation_loop != NULL) {
device_reservation_loop_running = true;
if (JackPosixThread::StartImp(&fReservationLoopThread, 0, 0, on_device_reservation_loop, NULL) != 0) {
device_reservation_loop_running = false;
}
}
#endif
return 0;
} else {
Close();
@@ -378,6 +387,7 @@ int JackAlsaDriver::Close()
alsa_driver_delete((alsa_driver_t*)fDriver);
}

#ifndef __QNXNTO__
if (device_reservation_loop_running) {
device_reservation_loop_running = false;
JackPosixThread::StopImp(fReservationLoopThread);
@@ -398,6 +408,7 @@ int JackAlsaDriver::Close()
JackServerGlobals::on_device_release(audio_name);
}
}
#endif

return res;
}
@@ -578,6 +589,7 @@ extern "C"
{
#endif

#ifndef __QNXNTO__
static
jack_driver_param_constraint_desc_t *
enum_alsa_devices()
@@ -667,6 +679,7 @@ fail:
jack_constraint_free(constraint_ptr);
return NULL;
}
#endif

static int
dither_opt (char c, DitherAlgorithm* dither)
@@ -705,11 +718,14 @@ SERVER_EXPORT const jack_driver_desc_t* driver_get_descriptor ()
desc = jack_driver_descriptor_construct("alsa", JackDriverMaster, "Linux ALSA API based audio backend", &filler);

strcpy(value.str, "hw:0");
#ifndef __QNXNTO__
#ifdef __ANDROID__
jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "ALSA device name", NULL);
#else
jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, enum_alsa_devices(), "ALSA device name", NULL);
#endif
#endif


strcpy(value.str, "none");
jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Provide capture ports. Optionally set device", NULL);
@@ -951,8 +967,13 @@ void SetTime(jack_time_t time)
int Restart()
{
int res;
if ((res = g_alsa_driver->Stop()) == 0) {
res = g_alsa_driver->Start();
if ((res = g_alsa_driver->Stop()) != 0) {
jack_error("restart: stop driver failed");
return res;
}
if ((res = g_alsa_driver->Start()) != 0) {
jack_error("restart: start driver failed");
return res;
}
return res;
}


+ 670
- 241
linux/alsa/alsa_driver.c
File diff suppressed because it is too large
View File


+ 40
- 22
linux/alsa/alsa_driver.h View File

@@ -21,7 +21,12 @@
#ifndef __jack_alsa_driver_h__
#define __jack_alsa_driver_h__

#ifdef __QNXNTO__
#include <sys/asoundlib.h>
#else
#include <alsa/asoundlib.h>
#endif

#include "bitset.h"

#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -41,6 +46,24 @@
#include "memops.h"
#include "alsa_midi.h"

#ifdef __QNXNTO__
#define SND_PCM_FORMAT_S16_LE SND_PCM_SFMT_S16_LE
#define SND_PCM_FORMAT_S16_BE SND_PCM_SFMT_S16_BE
#define SND_PCM_FORMAT_S24_LE SND_PCM_SFMT_S24_LE
#define SND_PCM_FORMAT_S24_BE SND_PCM_SFMT_S24_BE
#define SND_PCM_FORMAT_S32_LE SND_PCM_SFMT_S32_LE
#define SND_PCM_FORMAT_S32_BE SND_PCM_SFMT_S32_BE
#define SND_PCM_FORMAT_FLOAT_LE SND_PCM_SFMT_FLOAT_LE
#define SND_PCM_STATE_SUSPENDED SND_PCM_STATUS_SUSPENDED
#define SND_PCM_STATE_XRUN SND_PCM_STATUS_UNDERRUN
#define SND_PCM_STREAM_PLAYBACK SND_PCM_CHANNEL_PLAYBACK
#define SND_PCM_STREAM_CAPTURE SND_PCM_CHANNEL_CAPTURE

typedef unsigned long snd_pcm_uframes_t;
typedef signed long snd_pcm_sframes_t;
typedef int32_t alsa_driver_default_format_t;
#endif

#ifdef __cplusplus
extern "C"
{
@@ -58,13 +81,28 @@ typedef struct _alsa_driver {

JACK_DRIVER_NT_DECL

#ifdef __QNXNTO__
unsigned int playback_sample_format;
unsigned int capture_sample_format;
void *capture_areas;
void *playback_areas;
void *capture_areas_ptr;
void *playback_areas_ptr;
#else
snd_pcm_format_t playback_sample_format;
snd_pcm_format_t capture_sample_format;
const snd_pcm_channel_area_t *capture_areas;
const snd_pcm_channel_area_t *playback_areas;
snd_pcm_hw_params_t *playback_hw_params;
snd_pcm_sw_params_t *playback_sw_params;
snd_pcm_hw_params_t *capture_hw_params;
snd_pcm_sw_params_t *capture_sw_params;
#endif
int poll_timeout_ms;
jack_time_t poll_last;
jack_time_t poll_next;
char **playback_addr;
char **capture_addr;
const snd_pcm_channel_area_t *capture_areas;
const snd_pcm_channel_area_t *playback_areas;
struct pollfd *pfd;
unsigned int playback_nfds;
unsigned int capture_nfds;
@@ -89,8 +127,6 @@ typedef struct _alsa_driver {
char *alsa_driver;
bitset_t channels_not_done;
bitset_t channels_done;
snd_pcm_format_t playback_sample_format;
snd_pcm_format_t capture_sample_format;
float max_sample_val;
unsigned long user_nperiods;
unsigned int playback_nperiods;
@@ -99,10 +135,6 @@ typedef struct _alsa_driver {
snd_ctl_t *ctl_handle;
snd_pcm_t *playback_handle;
snd_pcm_t *capture_handle;
snd_pcm_hw_params_t *playback_hw_params;
snd_pcm_sw_params_t *playback_sw_params;
snd_pcm_hw_params_t *capture_hw_params;
snd_pcm_sw_params_t *capture_sw_params;
jack_hardware_t *hw;
ClockSyncStatus *clock_sync_data;
jack_client_t *client;
@@ -211,18 +243,6 @@ alsa_driver_write_to_channel (alsa_driver_t *driver,
alsa_driver_mark_channel_done (driver, channel);
}

void alsa_driver_silence_untouched_channels (alsa_driver_t *driver,
jack_nframes_t nframes);
void alsa_driver_set_clock_sync_status (alsa_driver_t *driver, channel_t chn,
ClockSyncStatus status);
int alsa_driver_listen_for_clock_sync_status (alsa_driver_t *,
ClockSyncListenerFunction,
void *arg);
int alsa_driver_stop_listen_for_clock_sync_status (alsa_driver_t *,
unsigned int);
void alsa_driver_clock_sync_notify (alsa_driver_t *, channel_t chn,
ClockSyncStatus);

int
alsa_driver_reset_parameters (alsa_driver_t *driver,
jack_nframes_t frames_per_cycle,
@@ -269,8 +289,6 @@ alsa_driver_read (alsa_driver_t *driver, jack_nframes_t nframes);
int
alsa_driver_write (alsa_driver_t* driver, jack_nframes_t nframes);

jack_time_t jack_get_microseconds(void);

// Code implemented in JackAlsaDriver.cpp

void ReadInput(jack_nframes_t orig_nframes, snd_pcm_sframes_t contiguous, snd_pcm_sframes_t nread);


+ 4
- 0
linux/alsa/usx2y.h View File

@@ -22,6 +22,8 @@
#ifndef __jack_usx2y_h__
#define __jack_usx2y_h__

#include <poll.h>

#define USX2Y_MAXPACK 50
#define USX2Y_MAXBUFFERMS 100
#define USX2Y_MAXSTRIDE 3
@@ -51,7 +53,9 @@ typedef struct snd_usX2Y_hwdep_pcm_shm snd_usX2Y_hwdep_pcm_shm_t;
typedef struct
{
alsa_driver_t *driver;
#ifndef __QNXNTO__
snd_hwdep_t *hwdep_handle;
#endif
struct pollfd pfds;
struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm;
int playback_iso_start;


+ 1
- 1
posix/JackFifo.h View File

@@ -44,7 +44,7 @@ class SERVER_EXPORT JackFifo : public detail::JackSynchro

protected:

void BuildName(const char* name, const char* server_name, char* res);
void BuildName(const char* name, const char* server_name, char* res, int size);

public:



+ 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_linux__
#define __JackAtomic_linux__

#include "JackTypes.h"

#ifdef __PPC__

static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr)
{
register int result;
register UInt32 tmp;
asm volatile (
"# CAS \n"
" lwarx %4, 0, %1 \n" // creates a reservation on addr
" cmpw %4, %2 \n" // test value at addr
" bne- 1f \n"
" sync \n" // synchronize instructions
" stwcx. %3, 0, %1 \n" // if the reservation is not altered
// stores the new value at addr
" bne- 1f \n"
" li %0, 1 \n"
" b 2f \n"
"1: \n"
" li %0, 0 \n"
"2: \n"
: "=r" (result)
: "r" (addr), "r" (value), "r" (newvalue), "r" (tmp)
);
return result;
}

#endif

#if defined(__i386__) || defined(__x86_64__)

#define LOCK "lock ; "

static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
{
register char ret;
__asm__ __volatile__ (
"# CAS \n\t"
LOCK "cmpxchg %2, (%1) \n\t"
"sete %0 \n\t"
: "=a" (ret)
: "c" (addr), "d" (newvalue), "a" (value)
);
return ret;
}

#endif




#if !defined(__i386__) && !defined(__x86_64__) && !defined(__PPC__)


static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
{
return __sync_bool_compare_and_swap ((UInt32*)addr, value, newvalue);
}
#endif


#endif


+ 215
- 0
qnx/JackLinuxTime.c View File

@@ -0,0 +1,215 @@
/*
Copyright (C) 2001-2003 Paul Davis
Copyright (C) 2005 Jussi Laako
Copyright (C) 2004-2008 Grame

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#include "JackConstants.h"
#include "JackTime.h"
#include "JackTypes.h"
#include "JackError.h"

#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>

jack_time_t (*_jack_get_microseconds)(void) = 0;

#if defined(__gnu_linux__) && (defined(__i386__) || defined(__x86_64__))
#define HPET_SUPPORT
#define HPET_MMAP_SIZE 1024
#define HPET_CAPS 0x000
#define HPET_PERIOD 0x004
#define HPET_COUNTER 0x0f0
#define HPET_CAPS_COUNTER_64BIT (1 << 13)
#if defined(__x86_64__)
typedef uint64_t hpet_counter_t;
#else
typedef uint32_t hpet_counter_t;
#endif
static int hpet_fd;
static unsigned char *hpet_ptr;
static uint32_t hpet_period; /* period length in femto secs */
static uint64_t hpet_offset = 0;
static uint64_t hpet_wrap;
static hpet_counter_t hpet_previous = 0;
#endif /* defined(__gnu_linux__) && (__i386__ || __x86_64__) */

#ifdef HPET_SUPPORT

static int jack_hpet_init ()
{
uint32_t hpet_caps;

hpet_fd = open("/dev/hpet", O_RDONLY);
if (hpet_fd < 0) {
jack_error ("This system has no accessible HPET device (%s)", strerror (errno));
return -1;
}

hpet_ptr = (unsigned char *) mmap(NULL, HPET_MMAP_SIZE,
PROT_READ, MAP_SHARED, hpet_fd, 0);
if (hpet_ptr == MAP_FAILED) {
jack_error ("This system has no mappable HPET device (%s)", strerror (errno));
close (hpet_fd);
return -1;
}

/* this assumes period to be constant. if needed,
it can be moved to the clock access function
*/
hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD));
hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS));
hpet_wrap = ((hpet_caps & HPET_CAPS_COUNTER_64BIT) &&
(sizeof(hpet_counter_t) == sizeof(uint64_t))) ?
0 : ((uint64_t) 1 << 32);

return 0;
}

static jack_time_t jack_get_microseconds_from_hpet (void)
{
hpet_counter_t hpet_counter;
long double hpet_time;

hpet_counter = *((hpet_counter_t *) (hpet_ptr + HPET_COUNTER));
if (hpet_counter < hpet_previous)
hpet_offset += hpet_wrap;
hpet_previous = hpet_counter;
hpet_time = (long double) (hpet_offset + hpet_counter) *
(long double) hpet_period * (long double) 1e-9;
return ((jack_time_t) (hpet_time + 0.5));
}

#else

static int jack_hpet_init ()
{
jack_error ("This version of JACK or this computer does not have HPET support.\n"
"Please choose a different clock source.");
return -1;
}

static jack_time_t jack_get_microseconds_from_hpet (void)
{
/* never called */
return 0;
}

#endif /* HPET_SUPPORT */

#define HAVE_CLOCK_GETTIME 1

#ifndef HAVE_CLOCK_GETTIME

static jack_time_t jack_get_microseconds_from_system (void)
{
jack_time_t jackTime;
struct timeval tv;

gettimeofday (&tv, NULL);
jackTime = (jack_time_t) tv.tv_sec * 1000000 + (jack_time_t) tv.tv_usec;
return jackTime;
}

#else

static jack_time_t jack_get_microseconds_from_system (void)
{
jack_time_t jackTime;
struct timespec time;

clock_gettime(CLOCK_MONOTONIC, &time);
jackTime = (jack_time_t) time.tv_sec * 1e6 +
(jack_time_t) time.tv_nsec / 1e3;
return jackTime;
}

#endif /* HAVE_CLOCK_GETTIME */


SERVER_EXPORT void JackSleep(long usec)
{
usleep(usec);
}

SERVER_EXPORT void InitTime()
{
/* nothing to do on a generic system - we use the system clock */
}

SERVER_EXPORT void EndTime()
{}

void SetClockSource(jack_timer_type_t source)
{
jack_log("Clock source : %s", ClockSourceName(source));

switch (source)
{
case JACK_TIMER_HPET:
if (jack_hpet_init () == 0) {
_jack_get_microseconds = jack_get_microseconds_from_hpet;
} else {
_jack_get_microseconds = jack_get_microseconds_from_system;
}
break;

case JACK_TIMER_SYSTEM_CLOCK:
default:
_jack_get_microseconds = jack_get_microseconds_from_system;
break;
}
}

const char* ClockSourceName(jack_timer_type_t source)
{
switch (source) {
case JACK_TIMER_HPET:
return "hpet";
case JACK_TIMER_SYSTEM_CLOCK:
#ifdef HAVE_CLOCK_GETTIME
return "system clock via clock_gettime";
#else
return "system clock via gettimeofday";
#endif
}

/* what is wrong with gcc ? */
return "unknown";
}

SERVER_EXPORT jack_time_t GetMicroSeconds()
{
return _jack_get_microseconds();
}

SERVER_EXPORT jack_time_t jack_get_microseconds()
{
return _jack_get_microseconds();
}


+ 85
- 0
qnx/JackPlatformPlug_os.h View File

@@ -0,0 +1,85 @@
/*
Copyright (C) 2004-2008 Grame

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#ifndef __JackPlatformPlug_linux__
#define __JackPlatformPlug_linux__

#define jack_server_dir "/dev/shm"
#define jack_client_dir "/dev/shm"
#define JACK_DEFAULT_DRIVER "alsa"

namespace Jack
{
struct JackRequest;
struct JackResult;

class JackPosixMutex;
class JackPosixThread;
class JackFifo;
class JackSocketServerChannel;
class JackSocketClientChannel;
class JackSocketServerNotifyChannel;
class JackSocketNotifyChannel;
class JackClientSocket;
class JackNetUnixSocket;
}

/* __JackPlatformMutex__ */
#include "JackPosixMutex.h"
namespace Jack {typedef JackPosixMutex JackMutex; }

/* __JackPlatformThread__ */
#include "JackPosixThread.h"
namespace Jack { typedef JackPosixThread JackThread; }

#include "JackFifo.h"
namespace Jack { typedef JackFifo JackSynchro; }


/* __JackPlatformChannelTransaction__ */
/*
#include "JackSocket.h"
namespace Jack { typedef JackClientSocket JackChannelTransaction; }
*/

/* __JackPlatformProcessSync__ */
#include "JackPosixProcessSync.h"
namespace Jack { typedef JackPosixProcessSync JackProcessSync; }

/* __JackPlatformServerChannel__ */
#include "JackSocketServerChannel.h"
namespace Jack { typedef JackSocketServerChannel JackServerChannel; }

/* __JackPlatformClientChannel__ */
#include "JackSocketClientChannel.h"
namespace Jack { typedef JackSocketClientChannel JackClientChannel; }

/* __JackPlatformServerNotifyChannel__ */
#include "JackSocketServerNotifyChannel.h"
namespace Jack { typedef JackSocketServerNotifyChannel JackServerNotifyChannel; }

/* __JackPlatformNotifyChannel__ */
#include "JackSocketNotifyChannel.h"
namespace Jack { typedef JackSocketNotifyChannel JackNotifyChannel; }

/* __JackPlatformNetSocket__ */
#include "JackNetUnixSocket.h"
namespace Jack { typedef JackNetUnixSocket JackNetSocket; }

#endif

+ 300
- 0
qnx/driver.h View File

@@ -0,0 +1,300 @@
/*
Copyright (C) 2001 Paul Davis

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

$Id: driver.h,v 1.2 2005/11/23 11:24:29 letz Exp $
*/

#ifndef __jack_driver_h__
#define __jack_driver_h__

#include <pthread.h>
#include "types.h"
#include "jslist.h"
#include "driver_interface.h"

typedef float gain_t;
typedef long channel_t;

typedef enum {
Lock = 0x1,
NoLock = 0x2,
Sync = 0x4,
NoSync = 0x8
} ClockSyncStatus;

typedef void (*ClockSyncListenerFunction)(channel_t, ClockSyncStatus, void*);

typedef struct
{
unsigned long id;
ClockSyncListenerFunction function;
void *arg;
}
ClockSyncListener;

struct _jack_engine;
struct _jack_driver;

typedef int (*JackDriverAttachFunction)(struct _jack_driver *,
struct _jack_engine *);
typedef int (*JackDriverDetachFunction)(struct _jack_driver *,
struct _jack_engine *);
typedef int (*JackDriverReadFunction)(struct _jack_driver *,
jack_nframes_t nframes);
typedef int (*JackDriverWriteFunction)(struct _jack_driver *,
jack_nframes_t nframes);
typedef int (*JackDriverNullCycleFunction)(struct _jack_driver *,
jack_nframes_t nframes);
typedef int (*JackDriverStopFunction)(struct _jack_driver *);
typedef int (*JackDriverStartFunction)(struct _jack_driver *);
typedef int (*JackDriverBufSizeFunction)(struct _jack_driver *,
jack_nframes_t nframes);
/*
Call sequence summary:

1) engine loads driver via runtime dynamic linking
- calls jack_driver_load
- we call dlsym for "driver_initialize" and execute it
2) engine attaches to driver
3) engine starts driver
4) driver runs its own thread, calling
while () {
driver->wait ();
driver->engine->run_cycle ()
}
5) engine stops driver
6) engine detaches from driver
7) engine calls driver `finish' routine

Note that stop/start may be called multiple times in the event of an
error return from the `wait' function.
*/

typedef struct _jack_driver
{

/* The _jack_driver structure fields are included at the beginning of
each driver-specific structure using the JACK_DRIVER_DECL macro,
which is defined below. The comments that follow describe each
common field.
The driver should set this to be the interval it expects to elapse
between returning from the `wait' function. if set to zero, it
implies that the driver does not expect regular periodic wakeups.
jack_time_t period_usecs;
The driver should set this within its "wait" function to indicate
the UST of the most recent determination that the engine cycle
should run. it should not be set if the "extra_fd" argument of
the wait function is set to a non-zero value.
jack_time_t last_wait_ust;
These are not used by the driver. They should not be written to or
modified in any way
void *handle;
struct _jack_internal_client *internal_client;
This should perform any cleanup associated with the driver. it will
be called when jack server process decides to get rid of the
driver. in some systems, it may not be called at all, so the driver
should never rely on a call to this. it can set it to NULL if
it has nothing do do.
void (*finish)(struct _jack_driver *);
The JACK engine will call this when it wishes to attach itself to
the driver. the engine will pass a pointer to itself, which the driver
may use in anyway it wishes to. the driver may assume that this
is the same engine object that will make `wait' calls until a
`detach' call is made.
JackDriverAttachFunction attach;
The JACK engine will call this when it is finished using a driver.
JackDriverDetachFunction detach;
The JACK engine will call this when it wants to wait until the
driver decides that its time to process some data. the driver returns
a count of the number of audioframes that can be processed.
it should set the variable pointed to by `status' as follows:
zero: the wait completed normally, processing may begin
negative: the wait failed, and recovery is not possible
positive: the wait failed, and the driver stopped itself.
a call to `start' will return the driver to
a correct and known state.
the driver should also fill out the `delayed_usecs' variable to
indicate any delay in its expected periodic execution. for example,
if it discovers that its return from poll(2) is later than it
expects it to be, it would place an estimate of the delay
in this variable. the engine will use this to decide if it
plans to continue execution.
JackDriverWaitFunction wait;
The JACK engine will call this to ask the driver to move
data from its inputs to its output port buffers. it should
return 0 to indicate successful completion, negative otherwise.
This function will always be called after the wait function (above).
JackDriverReadFunction read;
The JACK engine will call this to ask the driver to move
data from its input port buffers to its outputs. it should
return 0 to indicate successful completion, negative otherwise.
this function will always be called after the read function (above).
JackDriverWriteFunction write;
The JACK engine will call this after the wait function (above) has
been called, but for some reason the engine is unable to execute
a full "cycle". the driver should do whatever is necessary to
keep itself running correctly, but cannot reference ports
or other JACK data structures in any way.
JackDriverNullCycleFunction null_cycle;
The engine will call this when it plans to stop calling the `wait'
function for some period of time. the driver should take
appropriate steps to handle this (possibly no steps at all).
NOTE: the driver must silence its capture buffers (if any)
from within this function or the function that actually
implements the change in state.
JackDriverStopFunction stop;
The engine will call this to let the driver know that it plans
to start calling the `wait' function on a regular basis. the driver
should take any appropriate steps to handle this (possibly no steps
at all). NOTE: The driver may wish to silence its playback buffers
(if any) from within this function or the function that actually
implements the change in state.
JackDriverStartFunction start;
The engine will call this to let the driver know that some client
has requested a new buffer size. The stop function will be called
prior to this, and the start function after this one has returned.
JackDriverBufSizeFunction bufsize;
*/

/* define the fields here... */
#define JACK_DRIVER_DECL \
jack_time_t period_usecs; \
jack_time_t last_wait_ust; \
void *handle; \
struct _jack_client_internal * internal_client; \
void (*finish)(struct _jack_driver *);\
JackDriverAttachFunction attach; \
JackDriverDetachFunction detach; \
JackDriverReadFunction read; \
JackDriverWriteFunction write; \
JackDriverNullCycleFunction null_cycle; \
JackDriverStopFunction stop; \
JackDriverStartFunction start; \
JackDriverBufSizeFunction bufsize;

JACK_DRIVER_DECL /* expand the macro */
}
jack_driver_t;

void jack_driver_init (jack_driver_t *);
void jack_driver_release (jack_driver_t *);

jack_driver_t *jack_driver_load (int argc, char **argv);
void jack_driver_unload (jack_driver_t *);

/****************************
*** Non-Threaded Drivers ***
****************************/

/*
Call sequence summary:

1) engine loads driver via runtime dynamic linking
- calls jack_driver_load
- we call dlsym for "driver_initialize" and execute it
- driver_initialize calls jack_driver_nt_init
2) nt layer attaches to driver
3) nt layer starts driver
4) nt layer runs a thread, calling
while () {
driver->nt_run_ctcle();
}
5) nt layer stops driver
6) nt layer detaches driver
7) engine calls driver `finish' routine which calls jack_driver_nt_finish

Note that stop/start may be called multiple times in the event of an
error return from the `wait' function.
*/

struct _jack_driver_nt;

typedef int (*JackDriverNTAttachFunction)(struct _jack_driver_nt *);
typedef int (*JackDriverNTDetachFunction)(struct _jack_driver_nt *);
typedef int (*JackDriverNTStopFunction)(struct _jack_driver_nt *);
typedef int (*JackDriverNTStartFunction)(struct _jack_driver_nt *);
typedef int (*JackDriverNTBufSizeFunction)(struct _jack_driver_nt *,
jack_nframes_t nframes);
typedef int (*JackDriverNTRunCycleFunction)(struct _jack_driver_nt *);

typedef struct _jack_driver_nt
{
#define JACK_DRIVER_NT_DECL \
JACK_DRIVER_DECL \
struct _jack_engine * engine; \
volatile int nt_run; \
pthread_t nt_thread; \
pthread_mutex_t nt_run_lock; \
JackDriverNTAttachFunction nt_attach; \
JackDriverNTDetachFunction nt_detach; \
JackDriverNTStopFunction nt_stop; \
JackDriverNTStartFunction nt_start; \
JackDriverNTBufSizeFunction nt_bufsize; \
JackDriverNTRunCycleFunction nt_run_cycle;
#define nt_read read
#define nt_write write
#define nt_null_cycle null_cycle

JACK_DRIVER_NT_DECL
}
jack_driver_nt_t;

void jack_driver_nt_init (jack_driver_nt_t * driver);
void jack_driver_nt_finish (jack_driver_nt_t * driver);

#endif /* __jack_driver_h__ */

+ 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


+ 40
- 14
wscript View File

@@ -95,6 +95,15 @@ def options(opt):
alsa.check_cfg(
package='alsa >= 1.0.18',
args='--cflags --libs')
# Check for QNX sound headers
qsa = opt.add_auto_option(
'qsa',
help='Enable QNX sound driver',
conf_dest='BUILD_DRIVER_ALSA')
qsa.check(lib='asound', uselib_store='ALSA')
qsa.check(
header_name=['sys/asoundlib.h'],
msg='Checking for header sys/asoundlib.h')
firewire = opt.add_auto_option(
'firewire',
help='Enable FireWire driver (FFADO)',
@@ -185,6 +194,7 @@ def detect_platform(conf):
platforms = [
# ('KEY, 'Human readable name', ['strings', 'to', 'check', 'for'])
('IS_LINUX', 'Linux', ['gnu0', 'gnukfreebsd', 'linux', 'posix']),
('IS_QNX', 'QNX', ['qnx']),
('IS_MACOSX', 'MacOS X', ['darwin']),
('IS_SUN', 'SunOS', ['sunos']),
('IS_WINDOWS', 'Windows', ['cygwin', 'msys', 'win32'])
@@ -304,7 +314,11 @@ def configure(conf):
conf.check_cc(fragment=fragment, define_name='HAVE_NGREG', mandatory=False,
msg='Checking for NGREG')

conf.env['LIB_PTHREAD'] = ['pthread']
if conf.env['IS_QNX']:
conf.env['LIB_PTHREAD'] = ['c']
conf.env['LIB_SOCKET'] = ['socket']
else:
conf.env['LIB_PTHREAD'] = ['pthread']
conf.env['LIB_DL'] = ['dl']
conf.env['LIB_RT'] = ['rt']
conf.env['LIB_M'] = ['m']
@@ -512,6 +526,9 @@ def obj_add_includes(bld, obj):
if bld.env['IS_MACOSX']:
obj.includes += ['macosx', 'posix']

if bld.env['IS_QNX']:
obj.includes += ['qnx', 'posix']

if bld.env['IS_SUN']:
obj.includes += ['posix', 'solaris']

@@ -540,6 +557,10 @@ def build_jackd(bld):
jackd.use += ['DL', 'PTHREAD']
jackd.framework = ['CoreFoundation']

if bld.env['IS_QNX']:
jackd.use += ['M', 'PTHREAD']


if bld.env['IS_SUN']:
jackd.use += ['DL', 'PTHREAD']

@@ -598,16 +619,20 @@ def build_drivers(bld):
alsa_src = [
'common/memops.c',
'linux/alsa/JackAlsaDriver.cpp',
'linux/alsa/alsa_rawmidi.c',
'linux/alsa/alsa_seqmidi.c',
'linux/alsa/alsa_midi_jackmp.cpp',
'linux/alsa/generic_hw.c',
'linux/alsa/hdsp.c',
'linux/alsa/alsa_driver.c',
'linux/alsa/hammerfall.c',
'linux/alsa/ice1712.c'
'linux/alsa/alsa_driver.c'
]

if not bld.env['IS_QNX']:
alsa_src += [
'linux/alsa/alsa_rawmidi.c',
'linux/alsa/alsa_seqmidi.c',
'linux/alsa/alsa_midi_jackmp.cpp',
'linux/alsa/generic_hw.c',
'linux/alsa/hdsp.c',
'linux/alsa/hammerfall.c',
'linux/alsa/ice1712.c'
]

alsarawmidi_src = [
'linux/alsarawmidi/JackALSARawMidiDriver.cpp',
'linux/alsarawmidi/JackALSARawMidiInputPort.cpp',
@@ -704,11 +729,12 @@ def build_drivers(bld):
target = 'alsa',
source = alsa_src,
use = ['ALSA'])
create_driver_obj(
bld,
target = 'alsarawmidi',
source = alsarawmidi_src,
use = ['ALSA'])
if not bld.env['IS_QNX']:
create_driver_obj(
bld,
target = 'alsarawmidi',
source = alsarawmidi_src,
use = ['ALSA'])

if bld.env['BUILD_DRIVER_FFADO']:
create_driver_obj(


Loading…
Cancel
Save