Change-Id: Ic0b9c377e111cb59ed4859819b810842347e8525 Signed-off-by: Timo Wischer <twischer@de.adit-jv.com>pull/545/head
| @@ -107,7 +107,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| #endif /* _WIN32 && !__CYGWIN__ && !GNU_WIN32 */ | #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) | #if defined(__CYGWIN__) || defined(GNU_WIN32) | ||||
| #include <stdint.h> | #include <stdint.h> | ||||
| @@ -0,0 +1,86 @@ | |||||
| /* | |||||
| Copyright (C) 2004-2008 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| */ | |||||
| #ifndef __JackAtomic_linux__ | |||||
| #define __JackAtomic_linux__ | |||||
| #include "JackTypes.h" | |||||
| #ifdef __PPC__ | |||||
| static inline int CAS(register UInt32 value, register UInt32 newvalue, register volatile void* addr) | |||||
| { | |||||
| register int result; | |||||
| register UInt32 tmp; | |||||
| asm volatile ( | |||||
| "# CAS \n" | |||||
| " lwarx %4, 0, %1 \n" // creates a reservation on addr | |||||
| " cmpw %4, %2 \n" // test value at addr | |||||
| " bne- 1f \n" | |||||
| " sync \n" // synchronize instructions | |||||
| " stwcx. %3, 0, %1 \n" // if the reservation is not altered | |||||
| // stores the new value at addr | |||||
| " bne- 1f \n" | |||||
| " li %0, 1 \n" | |||||
| " b 2f \n" | |||||
| "1: \n" | |||||
| " li %0, 0 \n" | |||||
| "2: \n" | |||||
| : "=r" (result) | |||||
| : "r" (addr), "r" (value), "r" (newvalue), "r" (tmp) | |||||
| ); | |||||
| return result; | |||||
| } | |||||
| #endif | |||||
| #if defined(__i386__) || defined(__x86_64__) | |||||
| #define LOCK "lock ; " | |||||
| static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) | |||||
| { | |||||
| register char ret; | |||||
| __asm__ __volatile__ ( | |||||
| "# CAS \n\t" | |||||
| LOCK "cmpxchg %2, (%1) \n\t" | |||||
| "sete %0 \n\t" | |||||
| : "=a" (ret) | |||||
| : "c" (addr), "d" (newvalue), "a" (value) | |||||
| ); | |||||
| return ret; | |||||
| } | |||||
| #endif | |||||
| #if !defined(__i386__) && !defined(__x86_64__) && !defined(__PPC__) | |||||
| static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) | |||||
| { | |||||
| return __sync_bool_compare_and_swap ((UInt32*)addr, value, newvalue); | |||||
| } | |||||
| #endif | |||||
| #endif | |||||
| @@ -0,0 +1,215 @@ | |||||
| /* | |||||
| Copyright (C) 2001-2003 Paul Davis | |||||
| Copyright (C) 2005 Jussi Laako | |||||
| Copyright (C) 2004-2008 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| */ | |||||
| #include "JackConstants.h" | |||||
| #include "JackTime.h" | |||||
| #include "JackTypes.h" | |||||
| #include "JackError.h" | |||||
| #include <stdint.h> | |||||
| #include <stdio.h> | |||||
| #include <sys/mman.h> | |||||
| #include <sys/time.h> | |||||
| #include <sys/types.h> | |||||
| #include <sys/stat.h> | |||||
| #include <fcntl.h> | |||||
| #include <errno.h> | |||||
| #include <string.h> | |||||
| #include <unistd.h> | |||||
| #include <stdlib.h> | |||||
| #include <inttypes.h> | |||||
| jack_time_t (*_jack_get_microseconds)(void) = 0; | |||||
| #if defined(__gnu_linux__) && (defined(__i386__) || defined(__x86_64__)) | |||||
| #define HPET_SUPPORT | |||||
| #define HPET_MMAP_SIZE 1024 | |||||
| #define HPET_CAPS 0x000 | |||||
| #define HPET_PERIOD 0x004 | |||||
| #define HPET_COUNTER 0x0f0 | |||||
| #define HPET_CAPS_COUNTER_64BIT (1 << 13) | |||||
| #if defined(__x86_64__) | |||||
| typedef uint64_t hpet_counter_t; | |||||
| #else | |||||
| typedef uint32_t hpet_counter_t; | |||||
| #endif | |||||
| static int hpet_fd; | |||||
| static unsigned char *hpet_ptr; | |||||
| static uint32_t hpet_period; /* period length in femto secs */ | |||||
| static uint64_t hpet_offset = 0; | |||||
| static uint64_t hpet_wrap; | |||||
| static hpet_counter_t hpet_previous = 0; | |||||
| #endif /* defined(__gnu_linux__) && (__i386__ || __x86_64__) */ | |||||
| #ifdef HPET_SUPPORT | |||||
| static int jack_hpet_init () | |||||
| { | |||||
| uint32_t hpet_caps; | |||||
| hpet_fd = open("/dev/hpet", O_RDONLY); | |||||
| if (hpet_fd < 0) { | |||||
| jack_error ("This system has no accessible HPET device (%s)", strerror (errno)); | |||||
| return -1; | |||||
| } | |||||
| hpet_ptr = (unsigned char *) mmap(NULL, HPET_MMAP_SIZE, | |||||
| PROT_READ, MAP_SHARED, hpet_fd, 0); | |||||
| if (hpet_ptr == MAP_FAILED) { | |||||
| jack_error ("This system has no mappable HPET device (%s)", strerror (errno)); | |||||
| close (hpet_fd); | |||||
| return -1; | |||||
| } | |||||
| /* this assumes period to be constant. if needed, | |||||
| it can be moved to the clock access function | |||||
| */ | |||||
| hpet_period = *((uint32_t *) (hpet_ptr + HPET_PERIOD)); | |||||
| hpet_caps = *((uint32_t *) (hpet_ptr + HPET_CAPS)); | |||||
| hpet_wrap = ((hpet_caps & HPET_CAPS_COUNTER_64BIT) && | |||||
| (sizeof(hpet_counter_t) == sizeof(uint64_t))) ? | |||||
| 0 : ((uint64_t) 1 << 32); | |||||
| return 0; | |||||
| } | |||||
| static jack_time_t jack_get_microseconds_from_hpet (void) | |||||
| { | |||||
| hpet_counter_t hpet_counter; | |||||
| long double hpet_time; | |||||
| hpet_counter = *((hpet_counter_t *) (hpet_ptr + HPET_COUNTER)); | |||||
| if (hpet_counter < hpet_previous) | |||||
| hpet_offset += hpet_wrap; | |||||
| hpet_previous = hpet_counter; | |||||
| hpet_time = (long double) (hpet_offset + hpet_counter) * | |||||
| (long double) hpet_period * (long double) 1e-9; | |||||
| return ((jack_time_t) (hpet_time + 0.5)); | |||||
| } | |||||
| #else | |||||
| static int jack_hpet_init () | |||||
| { | |||||
| jack_error ("This version of JACK or this computer does not have HPET support.\n" | |||||
| "Please choose a different clock source."); | |||||
| return -1; | |||||
| } | |||||
| static jack_time_t jack_get_microseconds_from_hpet (void) | |||||
| { | |||||
| /* never called */ | |||||
| return 0; | |||||
| } | |||||
| #endif /* HPET_SUPPORT */ | |||||
| #define HAVE_CLOCK_GETTIME 1 | |||||
| #ifndef HAVE_CLOCK_GETTIME | |||||
| static jack_time_t jack_get_microseconds_from_system (void) | |||||
| { | |||||
| jack_time_t jackTime; | |||||
| struct timeval tv; | |||||
| gettimeofday (&tv, NULL); | |||||
| jackTime = (jack_time_t) tv.tv_sec * 1000000 + (jack_time_t) tv.tv_usec; | |||||
| return jackTime; | |||||
| } | |||||
| #else | |||||
| static jack_time_t jack_get_microseconds_from_system (void) | |||||
| { | |||||
| jack_time_t jackTime; | |||||
| struct timespec time; | |||||
| clock_gettime(CLOCK_MONOTONIC, &time); | |||||
| jackTime = (jack_time_t) time.tv_sec * 1e6 + | |||||
| (jack_time_t) time.tv_nsec / 1e3; | |||||
| return jackTime; | |||||
| } | |||||
| #endif /* HAVE_CLOCK_GETTIME */ | |||||
| SERVER_EXPORT void JackSleep(long usec) | |||||
| { | |||||
| usleep(usec); | |||||
| } | |||||
| SERVER_EXPORT void InitTime() | |||||
| { | |||||
| /* nothing to do on a generic system - we use the system clock */ | |||||
| } | |||||
| SERVER_EXPORT void EndTime() | |||||
| {} | |||||
| void SetClockSource(jack_timer_type_t source) | |||||
| { | |||||
| jack_log("Clock source : %s", ClockSourceName(source)); | |||||
| switch (source) | |||||
| { | |||||
| case JACK_TIMER_HPET: | |||||
| if (jack_hpet_init () == 0) { | |||||
| _jack_get_microseconds = jack_get_microseconds_from_hpet; | |||||
| } else { | |||||
| _jack_get_microseconds = jack_get_microseconds_from_system; | |||||
| } | |||||
| break; | |||||
| case JACK_TIMER_SYSTEM_CLOCK: | |||||
| default: | |||||
| _jack_get_microseconds = jack_get_microseconds_from_system; | |||||
| break; | |||||
| } | |||||
| } | |||||
| const char* ClockSourceName(jack_timer_type_t source) | |||||
| { | |||||
| switch (source) { | |||||
| case JACK_TIMER_HPET: | |||||
| return "hpet"; | |||||
| case JACK_TIMER_SYSTEM_CLOCK: | |||||
| #ifdef HAVE_CLOCK_GETTIME | |||||
| return "system clock via clock_gettime"; | |||||
| #else | |||||
| return "system clock via gettimeofday"; | |||||
| #endif | |||||
| } | |||||
| /* what is wrong with gcc ? */ | |||||
| return "unknown"; | |||||
| } | |||||
| SERVER_EXPORT jack_time_t GetMicroSeconds() | |||||
| { | |||||
| return _jack_get_microseconds(); | |||||
| } | |||||
| SERVER_EXPORT jack_time_t jack_get_microseconds() | |||||
| { | |||||
| return _jack_get_microseconds(); | |||||
| } | |||||
| @@ -0,0 +1,85 @@ | |||||
| /* | |||||
| Copyright (C) 2004-2008 Grame | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU Lesser General Public License as published by | |||||
| the Free Software Foundation; either version 2.1 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU Lesser General Public License for more details. | |||||
| You should have received a copy of the GNU Lesser General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| */ | |||||
| #ifndef __JackPlatformPlug_linux__ | |||||
| #define __JackPlatformPlug_linux__ | |||||
| #define jack_server_dir "/dev/shm" | |||||
| #define jack_client_dir "/dev/shm" | |||||
| #define JACK_DEFAULT_DRIVER "alsa" | |||||
| namespace Jack | |||||
| { | |||||
| struct JackRequest; | |||||
| struct JackResult; | |||||
| class JackPosixMutex; | |||||
| class JackPosixThread; | |||||
| class JackFifo; | |||||
| class JackSocketServerChannel; | |||||
| class JackSocketClientChannel; | |||||
| class JackSocketServerNotifyChannel; | |||||
| class JackSocketNotifyChannel; | |||||
| class JackClientSocket; | |||||
| class JackNetUnixSocket; | |||||
| } | |||||
| /* __JackPlatformMutex__ */ | |||||
| #include "JackPosixMutex.h" | |||||
| namespace Jack {typedef JackPosixMutex JackMutex; } | |||||
| /* __JackPlatformThread__ */ | |||||
| #include "JackPosixThread.h" | |||||
| namespace Jack { typedef JackPosixThread JackThread; } | |||||
| #include "JackFifo.h" | |||||
| namespace Jack { typedef JackFifo JackSynchro; } | |||||
| /* __JackPlatformChannelTransaction__ */ | |||||
| /* | |||||
| #include "JackSocket.h" | |||||
| namespace Jack { typedef JackClientSocket JackChannelTransaction; } | |||||
| */ | |||||
| /* __JackPlatformProcessSync__ */ | |||||
| #include "JackPosixProcessSync.h" | |||||
| namespace Jack { typedef JackPosixProcessSync JackProcessSync; } | |||||
| /* __JackPlatformServerChannel__ */ | |||||
| #include "JackSocketServerChannel.h" | |||||
| namespace Jack { typedef JackSocketServerChannel JackServerChannel; } | |||||
| /* __JackPlatformClientChannel__ */ | |||||
| #include "JackSocketClientChannel.h" | |||||
| namespace Jack { typedef JackSocketClientChannel JackClientChannel; } | |||||
| /* __JackPlatformServerNotifyChannel__ */ | |||||
| #include "JackSocketServerNotifyChannel.h" | |||||
| namespace Jack { typedef JackSocketServerNotifyChannel JackServerNotifyChannel; } | |||||
| /* __JackPlatformNotifyChannel__ */ | |||||
| #include "JackSocketNotifyChannel.h" | |||||
| namespace Jack { typedef JackSocketNotifyChannel JackNotifyChannel; } | |||||
| /* __JackPlatformNetSocket__ */ | |||||
| #include "JackNetUnixSocket.h" | |||||
| namespace Jack { typedef JackNetUnixSocket JackNetSocket; } | |||||
| #endif | |||||
| @@ -0,0 +1,300 @@ | |||||
| /* | |||||
| Copyright (C) 2001 Paul Davis | |||||
| This program is free software; you can redistribute it and/or modify | |||||
| it under the terms of the GNU General Public License as published by | |||||
| the Free Software Foundation; either version 2 of the License, or | |||||
| (at your option) any later version. | |||||
| This program is distributed in the hope that it will be useful, | |||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| GNU General Public License for more details. | |||||
| You should have received a copy of the GNU General Public License | |||||
| along with this program; if not, write to the Free Software | |||||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| $Id: driver.h,v 1.2 2005/11/23 11:24:29 letz Exp $ | |||||
| */ | |||||
| #ifndef __jack_driver_h__ | |||||
| #define __jack_driver_h__ | |||||
| #include <pthread.h> | |||||
| #include "types.h" | |||||
| #include "jslist.h" | |||||
| #include "driver_interface.h" | |||||
| typedef float gain_t; | |||||
| typedef long channel_t; | |||||
| typedef enum { | |||||
| Lock = 0x1, | |||||
| NoLock = 0x2, | |||||
| Sync = 0x4, | |||||
| NoSync = 0x8 | |||||
| } ClockSyncStatus; | |||||
| typedef void (*ClockSyncListenerFunction)(channel_t, ClockSyncStatus, void*); | |||||
| typedef struct | |||||
| { | |||||
| unsigned long id; | |||||
| ClockSyncListenerFunction function; | |||||
| void *arg; | |||||
| } | |||||
| ClockSyncListener; | |||||
| struct _jack_engine; | |||||
| struct _jack_driver; | |||||
| typedef int (*JackDriverAttachFunction)(struct _jack_driver *, | |||||
| struct _jack_engine *); | |||||
| typedef int (*JackDriverDetachFunction)(struct _jack_driver *, | |||||
| struct _jack_engine *); | |||||
| typedef int (*JackDriverReadFunction)(struct _jack_driver *, | |||||
| jack_nframes_t nframes); | |||||
| typedef int (*JackDriverWriteFunction)(struct _jack_driver *, | |||||
| jack_nframes_t nframes); | |||||
| typedef int (*JackDriverNullCycleFunction)(struct _jack_driver *, | |||||
| jack_nframes_t nframes); | |||||
| typedef int (*JackDriverStopFunction)(struct _jack_driver *); | |||||
| typedef int (*JackDriverStartFunction)(struct _jack_driver *); | |||||
| typedef int (*JackDriverBufSizeFunction)(struct _jack_driver *, | |||||
| jack_nframes_t nframes); | |||||
| /* | |||||
| Call sequence summary: | |||||
| 1) engine loads driver via runtime dynamic linking | |||||
| - calls jack_driver_load | |||||
| - we call dlsym for "driver_initialize" and execute it | |||||
| 2) engine attaches to driver | |||||
| 3) engine starts driver | |||||
| 4) driver runs its own thread, calling | |||||
| while () { | |||||
| driver->wait (); | |||||
| driver->engine->run_cycle () | |||||
| } | |||||
| 5) engine stops driver | |||||
| 6) engine detaches from driver | |||||
| 7) engine calls driver `finish' routine | |||||
| Note that stop/start may be called multiple times in the event of an | |||||
| error return from the `wait' function. | |||||
| */ | |||||
| typedef struct _jack_driver | |||||
| { | |||||
| /* The _jack_driver structure fields are included at the beginning of | |||||
| each driver-specific structure using the JACK_DRIVER_DECL macro, | |||||
| which is defined below. The comments that follow describe each | |||||
| common field. | |||||
| The driver should set this to be the interval it expects to elapse | |||||
| between returning from the `wait' function. if set to zero, it | |||||
| implies that the driver does not expect regular periodic wakeups. | |||||
| jack_time_t period_usecs; | |||||
| The driver should set this within its "wait" function to indicate | |||||
| the UST of the most recent determination that the engine cycle | |||||
| should run. it should not be set if the "extra_fd" argument of | |||||
| the wait function is set to a non-zero value. | |||||
| jack_time_t last_wait_ust; | |||||
| These are not used by the driver. They should not be written to or | |||||
| modified in any way | |||||
| void *handle; | |||||
| struct _jack_internal_client *internal_client; | |||||
| This should perform any cleanup associated with the driver. it will | |||||
| be called when jack server process decides to get rid of the | |||||
| driver. in some systems, it may not be called at all, so the driver | |||||
| should never rely on a call to this. it can set it to NULL if | |||||
| it has nothing do do. | |||||
| void (*finish)(struct _jack_driver *); | |||||
| The JACK engine will call this when it wishes to attach itself to | |||||
| the driver. the engine will pass a pointer to itself, which the driver | |||||
| may use in anyway it wishes to. the driver may assume that this | |||||
| is the same engine object that will make `wait' calls until a | |||||
| `detach' call is made. | |||||
| JackDriverAttachFunction attach; | |||||
| The JACK engine will call this when it is finished using a driver. | |||||
| JackDriverDetachFunction detach; | |||||
| The JACK engine will call this when it wants to wait until the | |||||
| driver decides that its time to process some data. the driver returns | |||||
| a count of the number of audioframes that can be processed. | |||||
| it should set the variable pointed to by `status' as follows: | |||||
| zero: the wait completed normally, processing may begin | |||||
| negative: the wait failed, and recovery is not possible | |||||
| positive: the wait failed, and the driver stopped itself. | |||||
| a call to `start' will return the driver to | |||||
| a correct and known state. | |||||
| the driver should also fill out the `delayed_usecs' variable to | |||||
| indicate any delay in its expected periodic execution. for example, | |||||
| if it discovers that its return from poll(2) is later than it | |||||
| expects it to be, it would place an estimate of the delay | |||||
| in this variable. the engine will use this to decide if it | |||||
| plans to continue execution. | |||||
| JackDriverWaitFunction wait; | |||||
| The JACK engine will call this to ask the driver to move | |||||
| data from its inputs to its output port buffers. it should | |||||
| return 0 to indicate successful completion, negative otherwise. | |||||
| This function will always be called after the wait function (above). | |||||
| JackDriverReadFunction read; | |||||
| The JACK engine will call this to ask the driver to move | |||||
| data from its input port buffers to its outputs. it should | |||||
| return 0 to indicate successful completion, negative otherwise. | |||||
| this function will always be called after the read function (above). | |||||
| JackDriverWriteFunction write; | |||||
| The JACK engine will call this after the wait function (above) has | |||||
| been called, but for some reason the engine is unable to execute | |||||
| a full "cycle". the driver should do whatever is necessary to | |||||
| keep itself running correctly, but cannot reference ports | |||||
| or other JACK data structures in any way. | |||||
| JackDriverNullCycleFunction null_cycle; | |||||
| The engine will call this when it plans to stop calling the `wait' | |||||
| function for some period of time. the driver should take | |||||
| appropriate steps to handle this (possibly no steps at all). | |||||
| NOTE: the driver must silence its capture buffers (if any) | |||||
| from within this function or the function that actually | |||||
| implements the change in state. | |||||
| JackDriverStopFunction stop; | |||||
| The engine will call this to let the driver know that it plans | |||||
| to start calling the `wait' function on a regular basis. the driver | |||||
| should take any appropriate steps to handle this (possibly no steps | |||||
| at all). NOTE: The driver may wish to silence its playback buffers | |||||
| (if any) from within this function or the function that actually | |||||
| implements the change in state. | |||||
| JackDriverStartFunction start; | |||||
| The engine will call this to let the driver know that some client | |||||
| has requested a new buffer size. The stop function will be called | |||||
| prior to this, and the start function after this one has returned. | |||||
| JackDriverBufSizeFunction bufsize; | |||||
| */ | |||||
| /* define the fields here... */ | |||||
| #define JACK_DRIVER_DECL \ | |||||
| jack_time_t period_usecs; \ | |||||
| jack_time_t last_wait_ust; \ | |||||
| void *handle; \ | |||||
| struct _jack_client_internal * internal_client; \ | |||||
| void (*finish)(struct _jack_driver *);\ | |||||
| JackDriverAttachFunction attach; \ | |||||
| JackDriverDetachFunction detach; \ | |||||
| JackDriverReadFunction read; \ | |||||
| JackDriverWriteFunction write; \ | |||||
| JackDriverNullCycleFunction null_cycle; \ | |||||
| JackDriverStopFunction stop; \ | |||||
| JackDriverStartFunction start; \ | |||||
| JackDriverBufSizeFunction bufsize; | |||||
| JACK_DRIVER_DECL /* expand the macro */ | |||||
| } | |||||
| jack_driver_t; | |||||
| void jack_driver_init (jack_driver_t *); | |||||
| void jack_driver_release (jack_driver_t *); | |||||
| jack_driver_t *jack_driver_load (int argc, char **argv); | |||||
| void jack_driver_unload (jack_driver_t *); | |||||
| /**************************** | |||||
| *** Non-Threaded Drivers *** | |||||
| ****************************/ | |||||
| /* | |||||
| Call sequence summary: | |||||
| 1) engine loads driver via runtime dynamic linking | |||||
| - calls jack_driver_load | |||||
| - we call dlsym for "driver_initialize" and execute it | |||||
| - driver_initialize calls jack_driver_nt_init | |||||
| 2) nt layer attaches to driver | |||||
| 3) nt layer starts driver | |||||
| 4) nt layer runs a thread, calling | |||||
| while () { | |||||
| driver->nt_run_ctcle(); | |||||
| } | |||||
| 5) nt layer stops driver | |||||
| 6) nt layer detaches driver | |||||
| 7) engine calls driver `finish' routine which calls jack_driver_nt_finish | |||||
| Note that stop/start may be called multiple times in the event of an | |||||
| error return from the `wait' function. | |||||
| */ | |||||
| struct _jack_driver_nt; | |||||
| typedef int (*JackDriverNTAttachFunction)(struct _jack_driver_nt *); | |||||
| typedef int (*JackDriverNTDetachFunction)(struct _jack_driver_nt *); | |||||
| typedef int (*JackDriverNTStopFunction)(struct _jack_driver_nt *); | |||||
| typedef int (*JackDriverNTStartFunction)(struct _jack_driver_nt *); | |||||
| typedef int (*JackDriverNTBufSizeFunction)(struct _jack_driver_nt *, | |||||
| jack_nframes_t nframes); | |||||
| typedef int (*JackDriverNTRunCycleFunction)(struct _jack_driver_nt *); | |||||
| typedef struct _jack_driver_nt | |||||
| { | |||||
| #define JACK_DRIVER_NT_DECL \ | |||||
| JACK_DRIVER_DECL \ | |||||
| struct _jack_engine * engine; \ | |||||
| volatile int nt_run; \ | |||||
| pthread_t nt_thread; \ | |||||
| pthread_mutex_t nt_run_lock; \ | |||||
| JackDriverNTAttachFunction nt_attach; \ | |||||
| JackDriverNTDetachFunction nt_detach; \ | |||||
| JackDriverNTStopFunction nt_stop; \ | |||||
| JackDriverNTStartFunction nt_start; \ | |||||
| JackDriverNTBufSizeFunction nt_bufsize; \ | |||||
| JackDriverNTRunCycleFunction nt_run_cycle; | |||||
| #define nt_read read | |||||
| #define nt_write write | |||||
| #define nt_null_cycle null_cycle | |||||
| JACK_DRIVER_NT_DECL | |||||
| } | |||||
| jack_driver_nt_t; | |||||
| void jack_driver_nt_init (jack_driver_nt_t * driver); | |||||
| void jack_driver_nt_finish (jack_driver_nt_t * driver); | |||||
| #endif /* __jack_driver_h__ */ | |||||