commit 2476dca8c1ff620d043c9ad603d7ebddc51c1807 Author: Nedko Arnaudov Date: Thu Feb 2 19:16:32 2012 +0200 Import jack1 headers from svn r4772 diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..3cafb12 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,42 @@ +MAINTAINERCLEANFILES = Makefile.in version.h + +libjackincludedir = $(includedir)/jack + +libjackinclude_HEADERS = \ + intclient.h \ + jack.h \ + ringbuffer.h \ + statistics.h \ + session.h \ + thread.h \ + timestamps.h \ + transport.h \ + types.h \ + midiport.h \ + weakmacros.h \ + weakjack.h \ + control.h \ + jslist.h + +noinst_HEADERS = \ + atomicity.h \ + bitset.h \ + driver.h \ + driver_interface.h \ + driver_parse.h \ + engine.h \ + hardware.h \ + internal.h \ + intsimd.h \ + memops.h \ + messagebuffer.h \ + pool.h \ + port.h \ + ringbuffer.h \ + sanitycheck.h \ + shm.h \ + start.h \ + systemtest.h \ + unlock.h \ + varargs.h \ + version.h diff --git a/atomicity.h b/atomicity.h new file mode 100644 index 0000000..fb625ec --- /dev/null +++ b/atomicity.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2004 Jack O'Quin + + 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 __jack_atomicity_h__ +#define __jack_atomicity_h__ + +/* + * Interface with various machine-dependent headers derived from the + * gcc/libstdc++.v3 sources. We try to modify the GCC sources as + * little as possible. The following include is resolved using the + * config/configure.hosts mechanism. It will use an OS-dependent + * version if available, otherwise the one for this CPU. Some of + * these files might not work with older GCC compilers. + */ +#include + +/* These functions are defined for each platform. The C++ library + * function names start with "__" to avoid namespace pollution. */ +#define exchange_and_add __exchange_and_add +#define atomic_add __atomic_add + +#endif /* __jack_atomicity_h__ */ diff --git a/bitset.h b/bitset.h new file mode 100644 index 0000000..f607815 --- /dev/null +++ b/bitset.h @@ -0,0 +1,111 @@ +/* + * bitset.h -- some simple bit vector set operations. + * + * This is useful for sets of small non-negative integers. There are + * some obvious set operations that are not implemented because I + * don't need them right now. + * + * These functions represent sets as arrays of unsigned 32-bit + * integers allocated on the heap. The first entry contains the set + * cardinality (number of elements allowed), followed by one or more + * words containing bit vectors. + * + */ + +/* + * Copyright (C) 2005 Jack O'Quin + * + * 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 __bitset_h__ +#define __bitset_h__ + +#include /* POSIX standard fixed-size types */ +#include /* `#define NDEBUG' to disable */ + +/* On some 64-bit machines, this implementation may be slightly + * inefficient, depending on how compilers allocate space for + * uint32_t. For the set sizes I currently need, this is acceptable. + * It should not be hard to pack the bits better, if that becomes + * worthwhile. + */ +typedef uint32_t _bitset_word_t; +typedef _bitset_word_t *bitset_t; + +#define WORD_SIZE(cardinality) (1+((cardinality)+31)/32) +#define BYTE_SIZE(cardinality) (WORD_SIZE(cardinality)*sizeof(_bitset_word_t)) +#define WORD_INDEX(element) (1+(element)/32) +#define BIT_INDEX(element) ((element)&037) + +static inline void +bitset_add(bitset_t set, unsigned int element) +{ + assert(element < set[0]); + set[WORD_INDEX(element)] |= (1 << BIT_INDEX(element)); +} + +static inline void +bitset_copy(bitset_t to_set, bitset_t from_set) +{ + assert(to_set[0] == from_set[0]); + memcpy(to_set, from_set, BYTE_SIZE(to_set[0])); +} + +static inline void +bitset_create(bitset_t *set, unsigned int cardinality) +{ + *set = (bitset_t) calloc(WORD_SIZE(cardinality), + sizeof(_bitset_word_t)); + assert(*set); + *set[0] = cardinality; +} + +static inline void +bitset_destroy(bitset_t *set) +{ + if (*set) { + free(*set); + *set = (bitset_t) 0; + } +} + +static inline int +bitset_empty(bitset_t set) +{ + int i; + _bitset_word_t result = 0; + int nwords = WORD_SIZE(set[0]); + for (i = 1; i < nwords; i++) { + result |= set[i]; + } + return (result == 0); +} + +static inline int +bitset_contains(bitset_t set, unsigned int element) +{ + assert(element < set[0]); + return (0 != (set[WORD_INDEX(element)] & (1< + +#if !defined (__sun__) +#include +#endif + +/** Parameter types, intentionally similar to jack_driver_param_type_t */ +typedef enum +{ + JackParamInt = 1, /**< @brief value type is a signed integer */ + JackParamUInt, /**< @brief value type is an unsigned integer */ + JackParamChar, /**< @brief value type is a char */ + JackParamString, /**< @brief value type is a string with max size of ::JACK_PARAM_STRING_MAX+1 chars */ + JackParamBool, /**< @brief value type is a boolean */ +} jackctl_param_type_t; + +/** @brief Max value that jackctl_param_type_t type can have */ +#define JACK_PARAM_MAX (JackParamBool + 1) + +/** @brief Max length of string parameter value, excluding terminating null char */ +#define JACK_PARAM_STRING_MAX 127 + +/** @brief Type for parameter value */ +/* intentionally similar to jack_driver_param_value_t */ +union jackctl_parameter_value +{ + uint32_t ui; /**< @brief member used for ::JackParamUInt */ + int32_t i; /**< @brief member used for ::JackParamInt */ + char c; /**< @brief member used for ::JackParamChar */ + char str[JACK_PARAM_STRING_MAX + 1]; /**< @brief member used for ::JackParamString */ + bool b; /**< @brief member used for ::JackParamBool */ +}; + +/** opaque type for server object */ +typedef struct jackctl_server jackctl_server_t; + +/** opaque type for driver object */ +typedef struct jackctl_driver jackctl_driver_t; + +/** opaque type for internal client object */ +typedef struct jackctl_internal jackctl_internal_t; + +/** opaque type for parameter object */ +typedef struct jackctl_parameter jackctl_parameter_t; + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} /* Adjust editor indent */ +#endif + +/** + * @defgroup ControlAPI the API for starting and controlling a JACK server + * @{ + */ + +/** + * Call this function to setup process signal handling. As a general + * rule, it is required for proper operation for the server object. + * + * @param flags signals setup flags, use 0 for none. Currently no + * flags are defined + * + * @return the configurated signal set. + */ +sigset_t +jackctl_setup_signals( + unsigned int flags); + +/** + * Call this function to wait on a signal set. + * + * @param signals signals set to wait on + */ +void +jackctl_wait_signals( + sigset_t signals); + +/** + * Call this function to create server object. + * + * @param on_device_acquire - Optional callback to be called before device is acquired. If false is returned, device usage will fail + * @param on_device_release - Optional callback to be called after device is released. + * + * @return server object handle, NULL if creation of server object + * failed. Successfully created server object must be destroyed with + * paired call to ::jackctl_server_destroy + */ +jackctl_server_t * +jackctl_server_create( + bool (* on_device_acquire)(const char * device_name), + void (* on_device_release)(const char * device_name)); + +/** + * Call this function to destroy server object. + * + * @param server server object handle to destroy + */ +void +jackctl_server_destroy( + jackctl_server_t * server); + +/** + * Call this function to start JACK server + * + * @param server server object handle + * @param driver driver to use + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_start( + jackctl_server_t * server, + jackctl_driver_t * driver); + +/** + * Call this function to stop JACK server + * + * @param server server object handle + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_stop( + jackctl_server_t * server); + +/** + * Call this function to get list of available drivers. List node data + * pointers is a driver object handle (::jackctl_driver_t). + * + * @param server server object handle to get drivers for + * + * @return Single linked list of driver object handles. Must not be + * modified. Always same for same server object. + */ +const JSList * +jackctl_server_get_drivers_list( + jackctl_server_t * server); + +/** + * Call this function to get list of server parameters. List node data + * pointers is a parameter object handle (::jackctl_parameter_t). + * + * @param server server object handle to get parameters for + * + * @return Single linked list of parameter object handles. Must not be + * modified. Always same for same server object. + */ +const JSList * +jackctl_server_get_parameters( + jackctl_server_t * server); + +/** + * Call this function to get list of available internal clients. List node data + * pointers is a internal client object handle (::jackctl_internal_t). + * + * @param server server object handle to get internal clients for + * + * @return Single linked list of internal client object handles. Must not be + * modified. Always same for same server object. + */ +const JSList * +jackctl_server_get_internals_list( + jackctl_server_t * server); + +/** + * Call this function to load one internal client. + * + * @param server server object handle + * @param internal internal to use + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_load_internal( + jackctl_server_t * server, + jackctl_internal_t * internal); + +/** + * Call this function to unload one internal client. + * + * @param server server object handle + * @param internal internal to unload + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_unload_internal( + jackctl_server_t * server, + jackctl_internal_t * internal); + +/** + * Call this function to add a slave in the driver slave list. + * + * @param server server object handle + * @param driver driver to add in the driver slave list. + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_add_slave(jackctl_server_t * server, + jackctl_driver_t * driver); + +/** + * Call this function to remove a slave from the driver slave list. + * + * @param server server object handle + * @param driver driver to remove from the driver slave list. + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_remove_slave(jackctl_server_t * server, + jackctl_driver_t * driver); + +/** + * Call this function to switch master driver. + * + * @param server server object handle + * @param driver driver to switch to + * + * @return success status: true - success, false - fail + */ +bool +jackctl_server_switch_master(jackctl_server_t * server, + jackctl_driver_t * driver); + + +/** + * Call this function to get name of driver. + * + * @param driver driver object handle to get name of + * + * @return driver name. Must not be modified. Always same for same + * driver object. + */ +const char * +jackctl_driver_get_name( + jackctl_driver_t * driver); + +/** + * Call this function to get list of driver parameters. List node data + * pointers is a parameter object handle (::jackctl_parameter_t). + * + * @param driver driver object handle to get parameters for + * + * @return Single linked list of parameter object handles. Must not be + * modified. Always same for same driver object. + */ +const JSList * +jackctl_driver_get_parameters( + jackctl_driver_t * driver); + +/** + * Call this function to get name of internal client. + * + * @param internal internal object handle to get name of + * + * @return internal name. Must not be modified. Always same for same + * internal object. + */ +const char * +jackctl_internal_get_name( + jackctl_internal_t * internal); + +/** + * Call this function to get list of internal parameters. List node data + * pointers is a parameter object handle (::jackctl_parameter_t). + * + * @param internal internal object handle to get parameters for + * + * @return Single linked list of parameter object handles. Must not be + * modified. Always same for same internal object. + */ +const JSList * +jackctl_internal_get_parameters( + jackctl_internal_t * internal); + +/** + * Call this function to get parameter name. + * + * @param parameter parameter object handle to get name of + * + * @return parameter name. Must not be modified. Always same for same + * parameter object. + */ +const char * +jackctl_parameter_get_name( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter short description. + * + * @param parameter parameter object handle to get short description of + * + * @return parameter short description. Must not be modified. Always + * same for same parameter object. + */ +const char * +jackctl_parameter_get_short_description( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter long description. + * + * @param parameter parameter object handle to get long description of + * + * @return parameter long description. Must not be modified. Always + * same for same parameter object. + */ +const char * +jackctl_parameter_get_long_description( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter type. + * + * @param parameter parameter object handle to get type of + * + * @return parameter type. Always same for same parameter object. + */ +jackctl_param_type_t +jackctl_parameter_get_type( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter character. + * + * @param parameter parameter object handle to get character of + * + * @return character. + */ +char +jackctl_parameter_get_id( + jackctl_parameter_t * parameter); + +/** + * Call this function to check whether parameter has been set, or its + * default value is being used. + * + * @param parameter parameter object handle to check + * + * @return true - parameter is set, false - parameter is using default + * value. + */ +bool +jackctl_parameter_is_set( + jackctl_parameter_t * parameter); + +/** + * Call this function to reset parameter to its default value. + * + * @param parameter parameter object handle to reset value of + * + * @return success status: true - success, false - fail + */ +bool +jackctl_parameter_reset( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter value. + * + * @param parameter parameter object handle to get value of + * + * @return parameter value. + */ +union jackctl_parameter_value +jackctl_parameter_get_value( + jackctl_parameter_t * parameter); + +/** + * Call this function to set parameter value. + * + * @param parameter parameter object handle to get value of + * @param value_ptr pointer to variable containing parameter value + * + * @return success status: true - success, false - fail + */ +bool +jackctl_parameter_set_value( + jackctl_parameter_t * parameter, + const union jackctl_parameter_value * value_ptr); + +/** + * Call this function to get parameter default value. + * + * @param parameter parameter object handle to get default value of + * + * @return parameter default value. + */ +union jackctl_parameter_value +jackctl_parameter_get_default_value( + jackctl_parameter_t * parameter); + +/** + * Call this function check whether parameter has range constraint. + * + * @param parameter object handle of parameter to check + * + * @return whether parameter has range constraint. + */ +bool +jackctl_parameter_has_range_constraint( + jackctl_parameter_t * parameter); + +/** + * Call this function check whether parameter has enumeration constraint. + * + * @param parameter object handle of parameter to check + * + * @return whether parameter has enumeration constraint. + */ +bool +jackctl_parameter_has_enum_constraint( + jackctl_parameter_t * parameter); + +/** + * Call this function get how many enumeration values parameter has. + * + * @param parameter object handle of parameter + * + * @return number of enumeration values + */ +uint32_t +jackctl_parameter_get_enum_constraints_count( + jackctl_parameter_t * parameter); + +/** + * Call this function to get parameter enumeration value. + * + * @param parameter object handle of parameter + * @param index index of parameter enumeration value + * + * @return enumeration value. + */ +union jackctl_parameter_value +jackctl_parameter_get_enum_constraint_value( + jackctl_parameter_t * parameter, + uint32_t index); + +/** + * Call this function to get parameter enumeration value description. + * + * @param parameter object handle of parameter + * @param index index of parameter enumeration value + * + * @return enumeration value description. + */ +const char * +jackctl_parameter_get_enum_constraint_description( + jackctl_parameter_t * parameter, + uint32_t index); + +/** + * Call this function to get parameter range. + * + * @param parameter object handle of parameter + * @param min_ptr pointer to variable receiving parameter minimum value + * @param max_ptr pointer to variable receiving parameter maximum value + */ +void +jackctl_parameter_get_range_constraint( + jackctl_parameter_t * parameter, + union jackctl_parameter_value * min_ptr, + union jackctl_parameter_value * max_ptr); + +/** + * Call this function to check whether parameter constraint is strict, + * i.e. whether supplying non-matching value will not work for sure. + * + * @param parameter parameter object handle to check + * + * @return whether parameter constraint is strict. + */ +bool +jackctl_parameter_constraint_is_strict( + jackctl_parameter_t * parameter); + +/** + * Call this function to check whether parameter has fake values, + * i.e. values have no user meaningful meaning and only value + * description is meaningful to user. + * + * @param parameter parameter object handle to check + * + * @return whether parameter constraint is strict. + */ +bool +jackctl_parameter_constraint_is_fake_value( + jackctl_parameter_t * parameter); + +/** + * Call this function to log an error message. + * + * @param format string + */ +void +jack_error( + const char *format, + ...); + +/** + * Call this function to log an information message. + * + * @param format string + */ +void +jack_info( + const char *format, + ...); + +/** + * Call this function to log an information message but only when + * verbose mode is enabled. + * + * @param format string + */ +void +jack_log( + const char *format, + ...); + +/* @} */ + +#if 0 +{ /* Adjust editor indent */ +#endif +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* #ifndef JACKCTL_H__2EEDAD78_DF4C_4B26_83B7_4FF1A446A47E__INCLUDED */ diff --git a/driver.h b/driver.h new file mode 100644 index 0000000..ec1eea9 --- /dev/null +++ b/driver.h @@ -0,0 +1,304 @@ +/* + 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. + +*/ + +#ifndef __jack_driver_h__ +#define __jack_driver_h__ + +#include +#include +#include +#include + +typedef float gain_t; +typedef unsigned 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; + + +typedef jack_driver_desc_t * (*JackDriverDescFunction) (); + +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__ */ diff --git a/driver_interface.h b/driver_interface.h new file mode 100644 index 0000000..16da9f0 --- /dev/null +++ b/driver_interface.h @@ -0,0 +1,123 @@ +/* + Copyright (C) 2003 Bob Ham + + 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 __jack_driver_interface_h__ +#define __jack_driver_interface_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include + +#define JACK_DRIVER_NAME_MAX 15 +#define JACK_DRIVER_PARAM_NAME_MAX 15 +#define JACK_DRIVER_PARAM_STRING_MAX 63 + +#define JACK_CONSTRAINT_FLAG_RANGE ((uint32_t)1) /**< if set, constraint is a range (min-max) */ +#define JACK_CONSTRAINT_FLAG_STRICT ((uint32_t)2) /**< if set, constraint is strict, i.e. supplying non-matching value will not work */ +#define JACK_CONSTRAINT_FLAG_FAKE_VALUE ((uint32_t)4) /**< if set, values have no user meaningful meaning */ + + +/** Driver parameter types */ +typedef enum +{ + JackDriverParamInt = 1, + JackDriverParamUInt, + JackDriverParamChar, + JackDriverParamString, + JackDriverParamBool + +} jack_driver_param_type_t; + +/** Driver parameter value */ +typedef union +{ + uint32_t ui; + int32_t i; + char c; + char str[JACK_DRIVER_PARAM_STRING_MAX+1]; +} jack_driver_param_value_t; + +typedef struct { + jack_driver_param_value_t value; + char short_desc[64]; /**< A short (~30 chars) description for the user */ +} jack_driver_param_value_enum_t; + +typedef struct { + uint32_t flags; /**< JACK_CONSTRAINT_FLAG_XXX */ + + union { + struct { + jack_driver_param_value_t min; + jack_driver_param_value_t max; + } range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */ + + struct { + uint32_t count; + jack_driver_param_value_enum_t * possible_values_array; + } enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */ + } constraint; +} jack_driver_param_constraint_desc_t; + + +/** A driver parameter descriptor */ +typedef struct +{ + char name[JACK_DRIVER_NAME_MAX+1]; /**< The parameter's name */ + char character; /**< The parameter's character (for getopt, etc) */ + jack_driver_param_type_t type; /**< The parameter's type */ + jack_driver_param_value_t value; /**< The parameter's (default) value */ + jack_driver_param_constraint_desc_t * constraint; /**< Pointer to parameter constraint descriptor. NULL if there is no constraint */ + char short_desc[64]; /**< A short (~30 chars) description for the user */ + char long_desc[1024]; /**< A longer description for the user */ + +} jack_driver_param_desc_t; + +/** A driver parameter */ +typedef struct +{ + char character; + jack_driver_param_value_t value; +} jack_driver_param_t; + + +/** A struct for describing a jack driver */ +typedef struct +{ + char name[JACK_DRIVER_NAME_MAX+1]; /**< The driver's canonical name */ + char file[PATH_MAX+1]; /**< The filename of the driver's shared object file */ + uint32_t nparams; /**< The number of parameters the driver has */ + jack_driver_param_desc_t * params; /**< An array of parameter descriptors */ + +} jack_driver_desc_t; + + + + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_driver_interface_h__ */ + + diff --git a/driver_parse.h b/driver_parse.h new file mode 100644 index 0000000..d6d63b7 --- /dev/null +++ b/driver_parse.h @@ -0,0 +1,212 @@ +/* -*- mode: c; c-file-style: "linux"; -*- */ +/* + Copyright (C) 2003 Bob Ham +#include + +static void +jack_print_driver_options (jack_driver_desc_t * desc, FILE *file) +{ + unsigned long i; + char arg_default[JACK_DRIVER_PARAM_STRING_MAX + 1]; + + for (i = 0; i < desc->nparams; i++) { + switch (desc->params[i].type) { + case JackDriverParamInt: + sprintf (arg_default, "%" PRId32, desc->params[i].value.i); + break; + case JackDriverParamUInt: + sprintf (arg_default, "%" PRIu32, desc->params[i].value.ui); + break; + case JackDriverParamChar: + sprintf (arg_default, "%c", desc->params[i].value.c); + break; + case JackDriverParamString: + if (desc->params[i].value.str && + strcmp (desc->params[i].value.str, "") != 0) + sprintf (arg_default, "%s", desc->params[i].value.str); + else + sprintf (arg_default, "none"); + break; + case JackDriverParamBool: + sprintf (arg_default, "%s", desc->params[i].value.i ? "true" : "false"); + break; + } + + fprintf (file, "\t-%c, --%s \t%s (default: %s)\n", + desc->params[i].character, + desc->params[i].name, + desc->params[i].short_desc, + arg_default); + } +} + +static void +jack_print_driver_param_usage (jack_driver_desc_t * desc, unsigned long param, FILE *file) +{ + fprintf (file, "Usage information for the '%s' parameter for driver '%s':\n", + desc->params[param].name, desc->name); + + fprintf (file, "%s\n", desc->params[param].long_desc); +} + + +static int +jack_parse_driver_params (jack_driver_desc_t * desc, int argc, char **argv, JSList ** param_ptr) +{ + struct option * long_options; + char * options, * options_ptr; + unsigned long i; + int opt, param_index; + JSList * params = NULL; + jack_driver_param_t * driver_param; + + if (argc <= 1) { + *param_ptr = NULL; + return 0; + } + + /* check for help */ + if (strcmp (argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0) { + if (argc > 2) { + for (i = 0; i < desc->nparams; i++) { + if (strcmp (desc->params[i].name, argv[2]) == 0) { + jack_print_driver_param_usage (desc, i, stdout); + return 1; + } + } + + fprintf (stderr, "jackd: unknown option '%s' " + "for driver '%s'\n", argv[2], + desc->name); + } + + printf ("Parameters for driver '%s' (all parameters are optional):\n", desc->name); + jack_print_driver_options (desc, stdout); + return 1; + } + + + /* set up the stuff for getopt */ + options = calloc (desc->nparams*3 + 1, sizeof (char)); + long_options = calloc (desc->nparams + 1, sizeof (struct option)); + + options_ptr = options; + for (i = 0; i < desc->nparams; i++) { + sprintf (options_ptr, "%c::", desc->params[i].character); + options_ptr += 3; + + long_options[i].name = desc->params[i].name; + long_options[i].flag = NULL; + long_options[i].val = desc->params[i].character; + long_options[i].has_arg = optional_argument; + } + + /* create the params */ + optind = 0; + opterr = 0; + while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != -1) { + + if (opt == ':' || opt == '?') { + if (opt == ':') { + fprintf (stderr, "Missing option to argument '%c'\n", optopt); + } else { + fprintf (stderr, "Unknownage with option '%c'\n", optopt); + } + + fprintf (stderr, "Options for driver '%s':\n", desc->name); + jack_print_driver_options (desc, stderr); + exit (1); + } + + for (param_index = 0; param_index < desc->nparams; param_index++) { + if (opt == desc->params[param_index].character) { + break; + } + } + + driver_param = calloc (1, sizeof (jack_driver_param_t)); + + driver_param->character = desc->params[param_index].character; + + if (!optarg && optind < argc && + strlen(argv[optind]) && + argv[optind][0] != '-') { + optarg = argv[optind]; + } + + if (optarg) { + switch (desc->params[param_index].type) { + case JackDriverParamInt: + driver_param->value.i = atoi (optarg); + break; + case JackDriverParamUInt: + driver_param->value.ui = strtoul (optarg, NULL, 10); + break; + case JackDriverParamChar: + driver_param->value.c = optarg[0]; + break; + case JackDriverParamString: + strncpy (driver_param->value.str, optarg, JACK_DRIVER_PARAM_STRING_MAX); + break; + case JackDriverParamBool: + + if (strcasecmp ("false", optarg) == 0 || + strcasecmp ("off", optarg) == 0 || + strcasecmp ("no", optarg) == 0 || + strcasecmp ("0", optarg) == 0 || + strcasecmp ("(null)", optarg) == 0 ) { + + driver_param->value.i = FALSE; + + } else { + + driver_param->value.i = TRUE; + + } + break; + } + } else { + if (desc->params[param_index].type == JackDriverParamBool) { + driver_param->value.i = TRUE; + } else { + driver_param->value = desc->params[param_index].value; + } + } + + params = jack_slist_append (params, driver_param); + } + + free (options); + free (long_options); + + if (param_ptr) + *param_ptr = params; + + return 0; +} + + +#endif /* __jack_driver_parse_h__ */ + + diff --git a/engine.h b/engine.h new file mode 100644 index 0000000..3c840dd --- /dev/null +++ b/engine.h @@ -0,0 +1,272 @@ +/* -*- mode: c; c-file-style: "bsd"; -*- */ +/* + Copyright (C) 2001-2003 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. + +*/ + +#ifndef __jack_engine_h__ +#define __jack_engine_h__ + +#include +#include +#include + +struct _jack_driver; +struct _jack_client_internal; +struct _jack_port_internal; + +/* Structures is allocated by the engine in local memory to keep track + * of port buffers and connections. + */ +typedef struct { + jack_shm_info_t* shm_info; + jack_shmsize_t offset; +} jack_port_buffer_info_t; + +/* The engine keeps an array of these in its local memory. */ +typedef struct _jack_port_internal { + struct _jack_port_shared *shared; + JSList *connections; + jack_port_buffer_info_t *buffer_info; +} jack_port_internal_t; + +/* The engine's internal port type structure. */ +typedef struct _jack_port_buffer_list { + pthread_mutex_t lock; /* only lock within server */ + JSList *freelist; /* list of free buffers */ + jack_port_buffer_info_t *info; /* jack_buffer_info_t array */ +} jack_port_buffer_list_t; + +typedef struct _jack_reserved_name { + jack_client_id_t uuid; + char name[JACK_CLIENT_NAME_SIZE]; +} jack_reserved_name_t; + +#define JACKD_WATCHDOG_TIMEOUT 10000 +#define JACKD_CLIENT_EVENT_TIMEOUT 2000 + +/* The main engine structure in local memory. */ +struct _jack_engine { + jack_control_t *control; + + JSList *drivers; + struct _jack_driver *driver; + jack_driver_desc_t *driver_desc; + JSList *driver_params; + + JSList *slave_drivers; + + /* these are "callbacks" made by the driver backend */ + int (*set_buffer_size) (struct _jack_engine *, jack_nframes_t frames); + int (*set_sample_rate) (struct _jack_engine *, jack_nframes_t frames); + int (*run_cycle) (struct _jack_engine *, jack_nframes_t nframes, + float delayed_usecs); + void (*delay) (struct _jack_engine *, float delayed_usecs); + void (*transport_cycle_start) (struct _jack_engine *, jack_time_t time); + void (*driver_exit) (struct _jack_engine *); + jack_time_t (*get_microseconds)(void); + /* "private" sections starts here */ + + /* engine serialization -- use precedence for deadlock avoidance */ + pthread_mutex_t request_lock; /* precedes client_lock */ + pthread_rwlock_t client_lock; + pthread_mutex_t port_lock; + pthread_mutex_t problem_lock; /* must hold write lock on client_lock */ + int process_errors; + int period_msecs; + + /* Time to wait for clients in msecs. Used when jackd is run + * without realtime priority enabled. */ + int client_timeout_msecs; + + /* info on the shm segment containing this->control */ + + jack_shm_info_t control_shm; + + /* address-space local port buffer and segment info, + indexed by the port type_id + */ + jack_port_buffer_list_t port_buffers[JACK_MAX_PORT_TYPES]; + jack_shm_info_t port_segment[JACK_MAX_PORT_TYPES]; + + unsigned int port_max; + pthread_t server_thread; + pthread_t watchdog_thread; + + int fds[2]; + int cleanup_fifo[2]; + jack_client_id_t next_client_id; + size_t pfd_size; + size_t pfd_max; + struct pollfd *pfd; + char fifo_prefix[PATH_MAX+1]; + int *fifo; + unsigned long fifo_size; + + /* session handling */ + int session_reply_fd; + int session_pending_replies; + + unsigned long external_client_cnt; + int rtpriority; + volatile char freewheeling; + volatile char stop_freewheeling; + jack_client_id_t fwclient; + pthread_t freewheel_thread; + char verbose; + char do_munlock; + const char *server_name; + char temporary; + int reordered; + int watchdog_check; + int feedbackcount; + int removing_clients; + pid_t wait_pid; + int nozombies; + int timeout_count_threshold; + volatile int problems; + volatile int timeout_count; + volatile int new_clients_allowed; + + /* these lists are protected by `client_lock' */ + JSList *clients; + JSList *clients_waiting; + JSList *reserved_client_names; + + jack_port_internal_t *internal_ports; + jack_client_internal_t *timebase_client; + jack_port_buffer_info_t *silent_buffer; + jack_client_internal_t *current_client; + +#define JACK_ENGINE_ROLLING_COUNT 32 +#define JACK_ENGINE_ROLLING_INTERVAL 1024 + + jack_time_t rolling_client_usecs[JACK_ENGINE_ROLLING_COUNT]; + int rolling_client_usecs_cnt; + int rolling_client_usecs_index; + int rolling_interval; + float max_usecs; + float spare_usecs; + + int first_wakeup; + +#ifdef JACK_USE_MACH_THREADS + /* specific resources for server/client real-time thread communication */ + mach_port_t servertask, bp; + int portnum; +#endif + + /* used for port names munging */ + int audio_out_cnt; + int audio_in_cnt; + int midi_out_cnt; + int midi_in_cnt; +}; + +/* public functions */ + +jack_engine_t *jack_engine_new (int real_time, int real_time_priority, + int do_mlock, int do_unlock, + const char *server_name, int temporary, + int verbose, int client_timeout, + unsigned int port_max, + pid_t waitpid, jack_nframes_t frame_time_offset, int nozombies, + int timeout_count_threshold, + JSList *drivers); +void jack_engine_delete (jack_engine_t *); +int jack_run (jack_engine_t *engine); +int jack_wait (jack_engine_t *engine); +int jack_engine_load_driver (jack_engine_t *engine, + jack_driver_desc_t * driver_desc, + JSList * driver_params); +int jack_engine_load_slave_driver (jack_engine_t *engine, + jack_driver_desc_t * driver_desc, + JSList * driver_params); +void jack_dump_configuration(jack_engine_t *engine, int take_lock); + +/* private engine functions */ +void jack_engine_reset_rolling_usecs (jack_engine_t *engine); +int internal_client_request (void* ptr, jack_request_t *request); +int jack_get_fifo_fd (jack_engine_t *engine, + unsigned int which_fifo); + +extern jack_timer_type_t clock_source; + +extern jack_client_internal_t * +jack_client_internal_by_id (jack_engine_t *engine, jack_client_id_t id); + +#define jack_rdlock_graph(e) { DEBUG ("acquiring graph read lock"); if (pthread_rwlock_rdlock (&e->client_lock)) abort(); } +#define jack_lock_graph(e) { DEBUG ("acquiring graph write lock"); if (pthread_rwlock_wrlock (&e->client_lock)) abort(); } +#define jack_try_rdlock_graph(e) pthread_rwlock_tryrdlock (&e->client_lock) +#define jack_unlock_graph(e) { DEBUG ("release graph lock"); if (pthread_rwlock_unlock (&e->client_lock)) abort(); } + +#define jack_trylock_problems(e) pthread_mutex_trylock (&e->problem_lock) +#define jack_lock_problems(e) { DEBUG ("acquiring problem lock"); if (pthread_mutex_lock (&e->problem_lock)) abort(); } +#define jack_unlock_problems(e) { DEBUG ("release problem lock"); if (pthread_mutex_unlock (&e->problem_lock)) abort(); } + +#if 0 +static inline void jack_rdlock_graph (jack_engine_t* engine) { + DEBUG ("acquiring graph read lock"); + pthread_rwlock_rdlock (&engine->client_lock); +} + +static inline void jack_lock_graph (jack_engine_t* engine) { + DEBUG ("acquiring graph lock"); + pthread_rwlock_wrlock (&engine->client_lock); +} + +static inline int jack_try_rdlock_graph (jack_engine_t *engine) +{ + DEBUG ("TRYING to acquiring graph read lock"); + return pthread_rwlock_tryrdlock (&engine->client_lock); +} + +static inline void jack_unlock_graph (jack_engine_t* engine) +{ + DEBUG ("releasing graph lock"); + pthread_rwlock_unlock (&engine->client_lock); +} +#endif + +static inline unsigned int jack_power_of_two (unsigned int n) +{ + return !(n & (n - 1)); +} + +/* Internal port handling interfaces for JACK engine. */ +void jack_port_clear_connections (jack_engine_t *engine, + jack_port_internal_t *port); +void jack_port_registration_notify (jack_engine_t *, jack_port_id_t, int); +void jack_port_release (jack_engine_t *engine, jack_port_internal_t *); +void jack_sort_graph (jack_engine_t *engine); +int jack_stop_freewheeling (jack_engine_t* engine, int engine_exiting); +jack_client_internal_t * +jack_client_by_name (jack_engine_t *engine, const char *name); + +int jack_deliver_event (jack_engine_t *, jack_client_internal_t *, jack_event_t *); +void jack_stop_watchdog (jack_engine_t * ); + +void +jack_engine_signal_problems (jack_engine_t* engine); +int +jack_use_driver (jack_engine_t *engine, struct _jack_driver *driver); +int +jack_drivers_start (jack_engine_t *engine); +int +jack_add_slave_driver (jack_engine_t *engine, struct _jack_driver *driver); + +#endif /* __jack_engine_h__ */ diff --git a/hardware.h b/hardware.h new file mode 100644 index 0000000..01aefca --- /dev/null +++ b/hardware.h @@ -0,0 +1,65 @@ +/* + 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. + +*/ + +#ifndef __jack_hardware_h__ +#define __jack_hardware_h__ + +#include + +typedef enum { + AutoSync, + WordClock, + ClockMaster +} SampleClockMode; + +typedef enum { + Cap_HardwareMonitoring = 0x1, + Cap_AutoSync = 0x2, + Cap_WordClock = 0x4, + Cap_ClockMaster = 0x8, + Cap_ClockLockReporting = 0x10, + Cap_HardwareMetering = 0x20 +} Capabilities; + +struct _jack_hardware; + +typedef void (*JackHardwareReleaseFunction)(struct _jack_hardware *); +typedef int (*JackHardwareSetInputMonitorMaskFunction)(struct _jack_hardware *, unsigned long); +typedef int (*JackHardwareChangeSampleClockFunction)(struct _jack_hardware *, SampleClockMode); +typedef double (*JackHardwareGetHardwarePeak)(jack_port_t *port, jack_nframes_t frames); +typedef double (*JackHardwareGetHardwarePower)(jack_port_t *port, jack_nframes_t frames); + + +typedef struct _jack_hardware { + + unsigned long capabilities; + unsigned long input_monitor_mask; + + JackHardwareChangeSampleClockFunction change_sample_clock; + JackHardwareSetInputMonitorMaskFunction set_input_monitor_mask; + JackHardwareReleaseFunction release; + JackHardwareGetHardwarePeak get_hardware_peak; + JackHardwareGetHardwarePower get_hardware_power; + void *private; + +} jack_hardware_t; + +jack_hardware_t * jack_hardware_new (); + +#endif /* __jack_hardware_h__ */ diff --git a/intclient.h b/intclient.h new file mode 100644 index 0000000..36883de --- /dev/null +++ b/intclient.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2004 Jack O'Quin + * + * 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 __jack_intclient_h__ +#define __jack_intclient_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * Get an internal client's name. This is useful when @ref + * JackUseExactName was not specified on jack_internal_client_load() + * and @ref JackNameNotUnique status was returned. In that case, the + * actual name will differ from the @a client_name requested. + * + * @param client requesting JACK client's handle. + * + * @param intclient handle returned from jack_internal_client_load() + * or jack_internal_client_handle(). + * + * @return NULL if unsuccessful, otherwise pointer to the internal + * client name obtained from the heap via malloc(). The caller should + * free() this storage when no longer needed. + */ +char *jack_get_internal_client_name (jack_client_t *client, + jack_intclient_t intclient); + +/** + * Return the @ref jack_intclient_t handle for an internal client + * running in the JACK server. + * + * @param client requesting JACK client's handle. + * + * @param client_name for the internal client of no more than + * jack_client_name_size() characters. The name scope is local to the + * current server. + * + * @param status (if non-NULL) an address for JACK to return + * information from this operation. This status word is formed by + * OR-ing together the relevant @ref JackStatus bits. + * + * @return Opaque internal client handle if successful. If 0, the + * internal client was not found, and @a *status includes the @ref + * JackNoSuchClient and @ref JackFailure bits. + */ +jack_intclient_t jack_internal_client_handle (jack_client_t *client, + const char *client_name, + jack_status_t *status); + +/** + * Load an internal client into the JACK server. + * + * Internal clients run inside the JACK server process. They can use + * most of the same functions as external clients. Each internal + * client is built as a shared object module, which must declare + * jack_initialize() and jack_finish() entry points called at load and + * unload times. See @ref inprocess.c for an example. + * + * @param client loading JACK client's handle. + * + * @param client_name of at most jack_client_name_size() characters + * for the internal client to load. The name scope is local to the + * current server. + * + * @param options formed by OR-ing together @ref JackOptions bits. + * Only the @ref JackLoadOptions bits are valid. + * + * @param status (if non-NULL) an address for JACK to return + * information from the load operation. This status word is formed by + * OR-ing together the relevant @ref JackStatus bits. + * + * Optional parameters: depending on corresponding [@a options + * bits] additional parameters may follow @a status (in this order). + * + * @arg [@ref JackLoadName] (char *) load_name is the shared + * object file from which to load the new internal client (otherwise + * use the @a client_name). + * + * @arg [@ref JackLoadInit] (char *) load_init an arbitary + * string passed to the internal client's jack_initialize() routine + * (otherwise NULL), of no more than @ref JACK_LOAD_INIT_LIMIT bytes. + * + * @return Opaque internal client handle if successful. If this is 0, + * the load operation failed, the internal client was not loaded, and + * @a *status includes the @ref JackFailure bit. + */ +jack_intclient_t jack_internal_client_load (jack_client_t *client, + const char *client_name, + jack_options_t options, + jack_status_t *status, ...); +/** + * Unload an internal client from a JACK server. This calls the + * intclient's jack_finish() entry point then removes it. See @ref + * inprocess.c for an example. + * + * @param client unloading JACK client's handle. + * + * @param intclient handle returned from jack_internal_client_load() or + * jack_internal_client_handle(). + * + * @return 0 if successful, otherwise @ref JackStatus bits. + */ +jack_status_t jack_internal_client_unload (jack_client_t *client, + jack_intclient_t intclient); + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_intclient_h__ */ diff --git a/internal.h b/internal.h new file mode 100644 index 0000000..d289191 --- /dev/null +++ b/internal.h @@ -0,0 +1,561 @@ +/* -*- mode: c; c-file-style: "bsd"; -*- */ +/* + Internal shared data and functions. + + If you edit this file, you should carefully consider changing the + JACK_PROTOCOL_VERSION in configure.in. + + Copyright (C) 2001-2003 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. + +*/ + +#ifndef __jack_internal_h__ +#define __jack_internal_h__ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef POST_PACKED_STRUCTURE +#ifdef __GNUC__ +/* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. +*/ +#define POST_PACKED_STRUCTURE __attribute__((__packed__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +/* Needed by */ +extern void jack_error (const char *fmt, ...); + +extern void jack_info (const char *fmt, ...); + +#include +#include +#include +#include +#include +#include + +extern jack_thread_creator_t jack_thread_creator; + +typedef enum { + JACK_TIMER_SYSTEM_CLOCK, + JACK_TIMER_CYCLE_COUNTER, + JACK_TIMER_HPET, +} jack_timer_type_t; + +void jack_init_time (); +void jack_set_clock_source (jack_timer_type_t); +const char* jack_clock_source_name (jack_timer_type_t); + +#include +#include + +#ifdef JACK_USE_MACH_THREADS +#include +#endif + +#include + +#ifndef PATH_MAX + #ifdef MAXPATHLEN + #define PATH_MAX MAXPATHLEN + #else + #define PATH_MAX 1024 + #endif /* MAXPATHLEN */ +#endif /* !PATH_MAX */ + +#ifdef DEBUG_ENABLED + +/* grab thread id instead of PID on linux */ +#if defined(__gnu_linux__) + #ifdef gettid /* glibc has a version */ + #define GETTID() gettid() + #else /* use our own version */ + #include + #define GETTID() syscall(__NR_gettid) + #endif +#else + #define GETTID() getpid() +#endif + +#define DEBUG(format,args...) \ + MESSAGE("jack:%5d:%" PRIu64 " %s:%s:%d: " format "", GETTID(), jack_get_microseconds(), __FILE__, __FUNCTION__, __LINE__ , ## args) + +#else +#if JACK_CPP_VARARGS_BROKEN + #define DEBUG(format...) +#else + #define DEBUG(format,args...) +#endif +#endif + +/* Enable preemption checking for Linux Realtime Preemption kernels. + * + * This checks if any RT-safe code section does anything to cause CPU + * preemption. Examples are sleep() or other system calls that block. + * If a problem is detected, the kernel writes a syslog entry, and + * sends SIGUSR2 to the client. + */ +#ifdef DO_PREEMPTION_CHECKING +#define CHECK_PREEMPTION(engine, onoff) \ + if ((engine)->real_time) gettimeofday (1, (onoff)) +#else +#define CHECK_PREEMPTION(engine, onoff) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +typedef struct _jack_engine jack_engine_t; +typedef struct _jack_request jack_request_t; + +typedef void * dlhandle; + +typedef enum { + TransportCommandNone = 0, + TransportCommandStart = 1, + TransportCommandStop = 2, +} transport_command_t; + +typedef struct { + + volatile uint32_t guard1; + volatile jack_nframes_t frames; + volatile jack_time_t current_wakeup; + volatile jack_time_t next_wakeup; + volatile float second_order_integrator; + volatile int32_t initialized; + volatile uint32_t guard2; + + /* not accessed by clients */ + + int32_t reset_pending; /* xrun happened, deal with it */ + float filter_coefficient; /* set once, never altered */ + +} POST_PACKED_STRUCTURE jack_frame_timer_t; + +/* JACK engine shared memory data structure. */ +typedef struct { + + jack_transport_state_t transport_state; + volatile transport_command_t transport_cmd; + transport_command_t previous_cmd; /* previous transport_cmd */ + jack_position_t current_time; /* position for current cycle */ + jack_position_t pending_time; /* position for next cycle */ + jack_position_t request_time; /* latest requested position */ + jack_unique_t prev_request; /* previous request unique ID */ + volatile _Atomic_word seq_number; /* unique ID sequence number */ + int8_t new_pos; /* new position this cycle */ + int8_t pending_pos; /* new position request pending */ + jack_nframes_t pending_frame; /* pending frame number */ + int32_t sync_clients; /* number of active_slowsync clients */ + int32_t sync_remain; /* number of them with sync_poll */ + jack_time_t sync_timeout; + jack_time_t sync_time_left; + jack_frame_timer_t frame_timer; + int32_t internal; + jack_timer_type_t clock_source; + pid_t engine_pid; + jack_nframes_t buffer_size; + int8_t real_time; + int8_t do_mlock; + int8_t do_munlock; + int32_t client_priority; + int32_t max_client_priority; + int32_t has_capabilities; + float cpu_load; + float xrun_delayed_usecs; + float max_delayed_usecs; + uint32_t port_max; + int32_t engine_ok; + jack_port_type_id_t n_port_types; + jack_port_type_info_t port_types[JACK_MAX_PORT_TYPES]; + jack_port_shared_t ports[0]; + +} POST_PACKED_STRUCTURE jack_control_t; + +typedef enum { + BufferSizeChange, + SampleRateChange, + AttachPortSegment, + PortConnected, + PortDisconnected, + GraphReordered, + PortRegistered, + PortUnregistered, + XRun, + StartFreewheel, + StopFreewheel, + ClientRegistered, + ClientUnregistered, + SaveSession, + LatencyCallback +} JackEventType; + +typedef struct { + JackEventType type; + union { + uint32_t n; + char name[JACK_PORT_NAME_SIZE]; + jack_port_id_t port_id; + jack_port_id_t self_id; + } x; + union { + uint32_t n; + jack_port_type_id_t ptid; + jack_port_id_t other_id; + } y; +} POST_PACKED_STRUCTURE jack_event_t; + +typedef enum { + ClientInternal, /* connect request just names .so */ + ClientDriver, /* code is loaded along with driver */ + ClientExternal /* client is in another process */ +} ClientType; + +typedef enum { + NotTriggered, + Triggered, + Running, + Finished +} jack_client_state_t; + +/* JACK client shared memory data structure. */ +typedef volatile struct { + + volatile jack_client_id_t id; /* w: engine r: engine and client */ + volatile jack_client_id_t uid; /* w: engine r: engine and client */ + volatile jack_client_state_t state; /* w: engine and client r: engine */ + volatile char name[JACK_CLIENT_NAME_SIZE]; + volatile char session_command[JACK_PORT_NAME_SIZE]; + volatile jack_session_flags_t session_flags; + volatile ClientType type; /* w: engine r: engine and client */ + volatile int8_t active; /* w: engine r: engine and client */ + volatile int8_t dead; /* r/w: engine */ + volatile int8_t timed_out; /* r/w: engine */ + volatile int8_t is_timebase; /* w: engine, r: engine and client */ + volatile int8_t timebase_new; /* w: engine and client, r: engine */ + volatile int8_t is_slowsync; /* w: engine, r: engine and client */ + volatile int8_t active_slowsync; /* w: engine, r: engine and client */ + volatile int8_t sync_poll; /* w: engine and client, r: engine */ + volatile int8_t sync_new; /* w: engine and client, r: engine */ + volatile pid_t pid; /* w: client r: engine; client pid */ + volatile pid_t pgrp; /* w: client r: engine; client pgrp */ + volatile uint64_t signalled_at; + volatile uint64_t awake_at; + volatile uint64_t finished_at; + volatile int32_t last_status; /* w: client, r: engine and client */ + + /* indicators for whether callbacks have been set for this client. + We do not include ptrs to the callbacks here (or their arguments) + so that we can avoid 32/64 bit pointer size mismatches between + the jack server and a client. The pointers are in the client- + local structure which is part of the libjack compiled for + either 32 bit or 64 bit clients. + */ + volatile uint8_t process_cbset; + volatile uint8_t thread_init_cbset; + volatile uint8_t bufsize_cbset; + volatile uint8_t srate_cbset; + volatile uint8_t port_register_cbset; + volatile uint8_t port_connect_cbset; + volatile uint8_t graph_order_cbset; + volatile uint8_t xrun_cbset; + volatile uint8_t sync_cb_cbset; + volatile uint8_t timebase_cb_cbset; + volatile uint8_t freewheel_cb_cbset; + volatile uint8_t client_register_cbset; + volatile uint8_t thread_cb_cbset; + volatile uint8_t session_cbset; + volatile uint8_t latency_cbset; + +} POST_PACKED_STRUCTURE jack_client_control_t; + +typedef struct { + + uint32_t protocol_v; /* protocol version, must go first */ + int32_t load; + ClientType type; + jack_options_t options; + jack_client_id_t uuid; + + char name[JACK_CLIENT_NAME_SIZE]; + char object_path[PATH_MAX+1]; + char object_data[1024]; + +} POST_PACKED_STRUCTURE jack_client_connect_request_t; + +typedef struct { + + jack_status_t status; + + jack_shm_registry_index_t client_shm_index; + jack_shm_registry_index_t engine_shm_index; + + char fifo_prefix[PATH_MAX+1]; + + int32_t realtime; + int32_t realtime_priority; + + char name[JACK_CLIENT_NAME_SIZE]; /* unique name, if assigned */ + + /* these are actually pointers, but they must + be the same size regardless of whether the + server and/or client are 64 bit or 32 bit. + force them to be 64 bit. + */ + + uint64_t client_control; + uint64_t engine_control; + +#ifdef JACK_USE_MACH_THREADS + /* specific resources for server/client real-time thread communication */ + int32_t portnum; +#endif + +} POST_PACKED_STRUCTURE jack_client_connect_result_t; + +typedef struct { + jack_client_id_t client_id; +} POST_PACKED_STRUCTURE jack_client_connect_ack_request_t; + +typedef struct { + int8_t status; +} POST_PACKED_STRUCTURE jack_client_connect_ack_result_t; + +typedef enum { + RegisterPort = 1, + UnRegisterPort = 2, + ConnectPorts = 3, + DisconnectPorts = 4, + SetTimeBaseClient = 5, + ActivateClient = 6, + DeactivateClient = 7, + DisconnectPort = 8, + SetClientCapabilities = 9, + GetPortConnections = 10, + GetPortNConnections = 11, + ResetTimeBaseClient = 12, + SetSyncClient = 13, + ResetSyncClient = 14, + SetSyncTimeout = 15, + SetBufferSize = 16, + FreeWheel = 17, + StopFreeWheel = 18, + IntClientHandle = 19, + IntClientLoad = 20, + IntClientName = 21, + IntClientUnload = 22, + RecomputeTotalLatencies = 23, + RecomputeTotalLatency = 24, + SessionNotify = 25, + GetClientByUUID = 26, + ReserveName = 30, + SessionReply = 31, + SessionHasCallback = 32 +} RequestType; + +struct _jack_request { + + //RequestType type; + uint32_t type; + union { + struct { + char name[JACK_PORT_NAME_SIZE]; + char type[JACK_PORT_TYPE_SIZE]; + uint32_t flags; + jack_shmsize_t buffer_size; + jack_port_id_t port_id; + jack_client_id_t client_id; + } POST_PACKED_STRUCTURE port_info; + struct { + char source_port[JACK_PORT_NAME_SIZE]; + char destination_port[JACK_PORT_NAME_SIZE]; + } POST_PACKED_STRUCTURE connect; + struct { + char path[JACK_PORT_NAME_SIZE]; + jack_session_event_type_t type; + char target[JACK_CLIENT_NAME_SIZE]; + } POST_PACKED_STRUCTURE session; + struct { + int32_t nports; + const char **ports; /* this is only exposed to internal clients, so there + is no 64/32 issue. external clients read the ports + one by one from the server, and allocate their + own "ports" array in their own address space. + + we are lucky, because this is part of a union + whose other components are bigger than this one. + otherwise it would change structure size when + comparing the 64 and 32 bit versions. + */ + } POST_PACKED_STRUCTURE port_connections; + struct { + jack_client_id_t client_id; + int32_t conditional; + } POST_PACKED_STRUCTURE timebase; + struct { + char name[JACK_CLIENT_NAME_SIZE]; + jack_client_id_t uuid; + } POST_PACKED_STRUCTURE reservename; + struct { + //jack_options_t options; + uint32_t options; + jack_client_id_t id; + char name[JACK_CLIENT_NAME_SIZE]; + char path[PATH_MAX+1]; + char init[JACK_LOAD_INIT_LIMIT]; + } POST_PACKED_STRUCTURE intclient; + jack_client_id_t client_id; + jack_nframes_t nframes; + jack_time_t timeout; + pid_t cap_pid; + char name[JACK_CLIENT_NAME_SIZE]; + } POST_PACKED_STRUCTURE x; + int32_t status; +} POST_PACKED_STRUCTURE; + +/* Per-client structure allocated in the server's address space. + * It's here because its not part of the engine structure. + */ + +typedef struct _jack_client_internal { + + jack_client_control_t *control; + + int request_fd; + int event_fd; + int subgraph_start_fd; + int subgraph_wait_fd; + JSList *ports; /* protected by engine->client_lock */ + JSList *truefeeds; /* protected by engine->client_lock */ + JSList *sortfeeds; /* protected by engine->client_lock */ + int fedcount; + int tfedcount; + jack_shm_info_t control_shm; + unsigned long execution_order; + struct _jack_client_internal *next_client; /* not a linked list! */ + dlhandle handle; + int (*initialize)(jack_client_t*, const char*); /* int. clients only */ + void (*finish)(void *); /* internal clients only */ + int error; + + int session_reply_pending; + +#ifdef JACK_USE_MACH_THREADS + /* specific resources for server/client real-time thread communication */ + mach_port_t serverport; + trivial_message message; + int running; + int portnum; +#endif /* JACK_USE_MACH_THREADS */ + + jack_client_t *private_client; +} jack_client_internal_t; + +typedef struct _jack_thread_arg { + jack_client_t* client; + void* (*work_function)(void*); + int priority; + int realtime; + void* arg; + pid_t cap_pid; +} jack_thread_arg_t; + +extern int jack_client_handle_port_connection (jack_client_t *client, + jack_event_t *event); +extern jack_client_t *jack_driver_client_new (jack_engine_t *, + const char *client_name); +extern jack_client_t *jack_client_alloc_internal (jack_client_control_t*, + jack_engine_t*); + +/* internal clients call this. it's defined in jack/engine.c */ +void handle_internal_client_request (jack_control_t*, jack_request_t*); + +extern char *jack_tmpdir; + +extern char *jack_user_dir (void); + +extern char *jack_server_dir (const char *server_name, char *server_dir); + +extern void *jack_zero_filled_buffer; + +extern jack_port_functions_t jack_builtin_audio_functions; + +extern jack_port_type_info_t jack_builtin_port_types[]; + +extern void jack_client_fix_port_buffers (jack_client_t *client); + +extern void jack_transport_copy_position (jack_position_t *from, + jack_position_t *to); +extern void jack_call_sync_client (jack_client_t *client); + +extern void jack_call_timebase_master (jack_client_t *client); + +extern char *jack_default_server_name (void); + +void silent_jack_error_callback (const char *desc); + +/* needed for port management */ +extern jack_port_t *jack_port_by_id_int (const jack_client_t *client, + jack_port_id_t id, int* free); + +extern jack_port_t *jack_port_by_name_int (jack_client_t *client, + const char *port_name); +extern int jack_port_name_equals (jack_port_shared_t* port, const char* target); + +/** Get the size (in bytes) of the data structure used to store + * MIDI events internally. + */ +extern size_t jack_midi_internal_event_size (); + +extern int jack_client_handle_latency_callback (jack_client_t *client, jack_event_t *event, int is_driver); + +#ifdef __GNUC__ +# define likely(x) __builtin_expect((x),1) +# define unlikely(x) __builtin_expect((x),0) +#else +# define likely(x) (x) +# define unlikely(x) (x) +#endif + +#ifdef VALGRIND_CLEAN +#include +#define VALGRIND_MEMSET(ptr,val,size) memset ((ptr),(val),(size)) +#else +#define VALGRIND_MEMSET(ptr,val,size) +#endif + +#endif /* __jack_internal_h__ */ + diff --git a/intsimd.h b/intsimd.h new file mode 100644 index 0000000..2377bd1 --- /dev/null +++ b/intsimd.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2005-2007 Jussi Laako + + 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 __jack_intsimd_h__ +#define __jack_intsimd_h__ + +#ifdef USE_DYNSIMD +#if (defined(__i386__) || defined(__x86_64__)) +#define ARCH_X86 +#endif /* __i386__ || __x86_64__ */ +#endif /* USE_DYNSIMD */ + +#ifdef ARCH_X86 +#define ARCH_X86_SSE(x) ((x) & 0xff) +#define ARCH_X86_HAVE_SSE2(x) (ARCH_X86_SSE(x) >= 2) +#define ARCH_X86_3DNOW(x) ((x) >> 8) +#define ARCH_X86_HAVE_3DNOW(x) (ARCH_X86_3DNOW(x)) + +typedef float v2sf __attribute__((vector_size(8))); +typedef float v4sf __attribute__((vector_size(16))); +typedef v2sf * pv2sf; +typedef v4sf * pv4sf; + +extern int cpu_type; + +int have_3dnow (void); +int have_sse (void); +void x86_3dnow_copyf (float *, const float *, int); +void x86_3dnow_add2f (float *, const float *, int); +void x86_sse_copyf (float *, const float *, int); +void x86_sse_add2f (float *, const float *, int); +void x86_sse_f2i (int *, const float *, int, float); +void x86_sse_i2f (float *, const int *, int, float); + +#endif /* ARCH_X86 */ + +void jack_port_set_funcs (void); + +#endif /* __jack_intsimd_h__ */ + diff --git a/jack.h b/jack.h new file mode 100644 index 0000000..4ee2bff --- /dev/null +++ b/jack.h @@ -0,0 +1,1226 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004 Jack O'Quin + + 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 __jack_h__ +#define __jack_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * Note: More documentation can be found in jack/types.h. + + */ + +/************************************************************* + * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function + * added to the JACK API after the 0.116.2 release. + * + * Functions that predate this release are marked with + * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile + * time in a variety of ways. The default definition is empty, + * so that these symbols get normal linkage. If you wish to + * use all JACK symbols with weak linkage, include + * before jack.h. + *************************************************************/ + +#include + +/** + * @defgroup ClientFunctions Creating & manipulating clients + * @{ + */ + +/** + * Open an external client session with a JACK server. This interface + * is more complex but more powerful than jack_client_new(). With it, + * clients may choose which of several servers to connect, and control + * whether and how to start the server automatically, if it was not + * already running. There is also an option for JACK to generate a + * unique client name, when necessary. + * + * @param client_name of at most jack_client_name_size() characters. + * The name scope is local to each server. Unless forbidden by the + * @ref JackUseExactName option, the server will modify this name to + * create a unique variant, if needed. + * + * @param options formed by OR-ing together @ref JackOptions bits. + * Only the @ref JackOpenOptions bits are allowed. + * + * @param status (if non-NULL) an address for JACK to return + * information from the open operation. This status word is formed by + * OR-ing together the relevant @ref JackStatus bits. + * + * + * Optional parameters: depending on corresponding [@a options + * bits] additional parameters may follow @a status (in this order). + * + * @arg [@ref JackServerName] (char *) server_name selects + * from among several possible concurrent server instances. Server + * names are unique to each user. If unspecified, use "default" + * unless \$JACK_DEFAULT_SERVER is defined in the process environment. + * + * @return Opaque client handle if successful. If this is NULL, the + * open operation failed, @a *status includes @ref JackFailure and the + * caller is not a JACK client. + */ +jack_client_t *jack_client_open (const char *client_name, + jack_options_t options, + jack_status_t *status, ...) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN + * NEW JACK CLIENTS + * + */ +jack_client_t *jack_client_new (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Disconnects an external client from a JACK server. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_client_close (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the maximum number of characters in a JACK client name + * including the final NULL character. This value is a constant. + */ +int jack_client_name_size (void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return pointer to actual client name. This is useful when @ref + * JackUseExactName is not specified on open and @ref + * JackNameNotUnique status was returned. In that case, the actual + * name will differ from the @a client_name requested. + */ +char *jack_get_client_name (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Load an internal client into the Jack server. + * + * Internal clients run inside the JACK server process. They can use + * most of the same functions as external clients. Each internal + * client must declare jack_initialize() and jack_finish() entry + * points, called at load and unload times. See inprocess.c for an + * example of how to write an internal client. + * + * @deprecated Please use jack_internal_client_load(). + * + * @param client_name of at most jack_client_name_size() characters. + * + * @param load_name of a shared object file containing the code for + * the new client. + * + * @param load_init an arbitary string passed to the jack_initialize() + * routine of the new client (may be NULL). + * + * @return 0 if successful. + */ +int jack_internal_client_new (const char *client_name, + const char *load_name, + const char *load_init) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Remove an internal client from a JACK server. + * + * @deprecated Please use jack_internal_client_load(). + */ +void jack_internal_client_close (const char *client_name) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Tell the Jack server that the program is ready to start processing + * audio. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_activate (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to remove this @a client from the process + * graph. Also, disconnect all ports belonging to it, since inactive + * clients have no port connections. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_deactivate (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the pthread ID of the thread running the JACK client side + * code. + */ +jack_native_thread_t jack_client_thread_id (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @param client pointer to JACK client structure. + * + * Check if the JACK subsystem is running with -R (--realtime). + * + * @return 1 if JACK is running realtime, 0 otherwise + */ +int jack_is_realtime (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @defgroup NonCallbackAPI The non-callback API + * @{ + */ + +/** + * THIS FUNCTION IS DEPRECATED AND SHOULD NOT BE USED IN + * NEW JACK CLIENTS + * + * It should be replace by use of @ jack_cycle_wait and @ jack_cycle_signal functions. + * + */ +jack_nframes_t jack_thread_wait (jack_client_t*, int status) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Wait until this JACK client should process data. + * + * @param client - pointer to a JACK client structure + * + * @return the number of frames of data to process + */ +jack_nframes_t jack_cycle_wait (jack_client_t* client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Signal next clients in the graph. + * + * @param client - pointer to a JACK client structure + * @param status - if non-zero, calling thread should exit + */ +void jack_cycle_signal (jack_client_t* client, int status) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a thread_callback in the RT thread. + * Typical use are in conjunction with @a jack_cycle_wait and @ jack_cycle_signal functions. + * The code in the supplied function must be suitable for real-time + * execution. That means that it cannot call functions that might + * block for a long time. This includes all I/O functions (disk, TTY, network), + * malloc, free, printf, pthread_mutex_lock, sleep, wait, poll, select, pthread_join, + * pthread_cond_wait, etc, etc. + * + * @return 0 on success, otherwise a non-zero error code. +*/ +int jack_set_process_thread(jack_client_t* client, JackThreadCallback fun, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup ClientCallbacks Setting Client Callbacks + * @{ + */ + +/** + * Tell JACK to call @a thread_init_callback once just after + * the creation of the thread in which all other callbacks + * will be handled. + * + * The code in the supplied function does not need to be + * suitable for real-time execution. + * + * @return 0 on success, otherwise a non-zero error code, causing JACK + * to remove that client from the process() graph. + */ +int jack_set_thread_init_callback (jack_client_t *client, + JackThreadInitCallback thread_init_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @param client pointer to JACK client structure. + * @param function The jack_shutdown function pointer. + * @param arg The arguments for the jack_shutdown function. + * + * Register a function (and argument) to be called if and when the + * JACK server shuts down the client thread. The function must + * be written as if it were an asynchonrous POSIX signal + * handler --- use only async-safe functions, and remember that it + * is executed from another thread. A typical function might + * set a flag or write to a pipe so that the rest of the + * application knows that the JACK client thread has shut + * down. + * + * NOTE: clients do not need to call this. It exists only + * to help more complex clients understand what is going + * on. It should be called before jack_client_activate(). + * + * NOTE: if a client calls this AND jack_on_info_shutdown(), then + * the event of a client thread shutdown, the callback + * passed to this function will not be called, and the one passed to + * jack_on_info_shutdown() will. + */ +void jack_on_shutdown (jack_client_t *client, + JackShutdownCallback function, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @param client pointer to JACK client structure. + * @param function The jack_shutdown function pointer. + * @param arg The arguments for the jack_shutdown function. + * + * Register a function (and argument) to be called if and when the + * JACK server shuts down the client thread. The function must + * be written as if it were an asynchonrous POSIX signal + * handler --- use only async-safe functions, and remember that it + * is executed from another thread. A typical function might + * set a flag or write to a pipe so that the rest of the + * application knows that the JACK client thread has shut + * down. + * + * NOTE: clients do not need to call this. It exists only + * to help more complex clients understand what is going + * on. It should be called before jack_client_activate(). + * + * NOTE: if a client calls this AND jack_on_shutdown(), then in the + * event of a client thread shutdown, the callback passed to + * this function will be called, and the one passed to + * jack_on_shutdown() will not. + */ +void jack_on_info_shutdown (jack_client_t *client, + JackInfoShutdownCallback function, void *arg) JACK_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a process_callback whenever there is + * work be done, passing @a arg as the second argument. + * + * The code in the supplied function must be suitable for real-time + * execution. That means that it cannot call functions that might + * block for a long time. This includes all I/O functions (disk, TTY, network), + * malloc, free, printf, pthread_mutex_lock, sleep, wait, poll, select, pthread_join, + * pthread_cond_wait, etc, etc. + * + * @return 0 on success, otherwise a non-zero error code, causing JACK + * to remove that client from the process() graph. + */ +int jack_set_process_callback (jack_client_t *client, + JackProcessCallback process_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a freewheel_callback + * whenever we enter or leave "freewheel" mode, passing @a + * arg as the second argument. The first argument to the + * callback will be non-zero if JACK is entering freewheel + * mode, and zero otherwise. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_freewheel_callback (jack_client_t *client, + JackFreewheelCallback freewheel_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell JACK to call @a bufsize_callback whenever the size of the the + * buffer that will be passed to the @a process_callback is about to + * change. Clients that depend on knowing the buffer size must supply + * a @a bufsize_callback before activating themselves. + * + * @param client pointer to JACK client structure. + * @param bufsize_callback function to call when the buffer size changes. + * @param arg argument for @a bufsize_callback. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_buffer_size_callback (jack_client_t *client, + JackBufferSizeCallback bufsize_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a srate_callback whenever the system + * sample rate changes. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_sample_rate_callback (jack_client_t *client, + JackSampleRateCallback srate_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a registration_callback whenever a + * port is registered or unregistered, passing @a arg as a parameter. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_client_registration_callback (jack_client_t *, + JackClientRegistrationCallback + registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a registration_callback whenever a + * port is registered or unregistered, passing @a arg as a parameter. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_port_registration_callback (jack_client_t *, + JackPortRegistrationCallback + registration_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a connect_callback whenever a + * port is connected or disconnected, passing @a arg as a parameter. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_port_connect_callback (jack_client_t *, + JackPortConnectCallback + connect_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; +/** + * Tell the JACK server to call @a graph_callback whenever the + * processing graph is reordered, passing @a arg as a parameter. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_graph_order_callback (jack_client_t *, + JackGraphOrderCallback graph_callback, + void *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the JACK server to call @a xrun_callback whenever there is a + * xrun, passing @a arg as a parameter. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_xrun_callback (jack_client_t *, + JackXRunCallback xrun_callback, void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Tell the Jack server to call @a latency_callback whenever it + * is necessary to recompute the latencies for some or all + * Jack ports. + * + * @a latency_callback will be called twice each time it is + * needed, once being passed JackCaptureLatency and once + * JackPlaybackLatency. See @ref LatencyFunctions for + * the definition of each type of latency and related functions. + * + * IMPORTANT: Most JACK clients do NOT need to register a latency + * callback. + * + * Clients that meet any of the following conditions do NOT + * need to register a latency callback: + * + * - have only input ports + * - have only output ports + * - their output is totally unrelated to their input + * - their output is not delayed relative to their input + * (i.e. data that arrives in a given process() + * callback is processed and output again in the + * same callback) + * + * Clients NOT registering a latency callback MUST also + * satisfy this condition: + * + * - have no multiple distinct internal signal pathways + * + * This means that if your client has more than 1 input and + * output port, and considers them always "correlated" + * (e.g. as a stereo pair), then there is only 1 (e.g. stereo) + * signal pathway through the client. This would be true, + * for example, of a stereo FX rack client that has a + * left/right input pair and a left/right output pair. + * + * However, this is somewhat a matter of perspective. The + * same FX rack client could be connected so that its + * two input ports were connected to entirely separate + * sources. Under these conditions, the fact that the client + * does not register a latency callback MAY result + * in port latency values being incorrect. + * + * Clients that do not meet any of those conditions SHOULD + * register a latency callback. + * + * See the documentation for @ref jack_port_set_latency_range() + * on how the callback should operate. Remember that the @a mode + * argument given to the latency callback will need to be + * passed into @ref jack_port_set_latency_range() + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_latency_callback (jack_client_t *, + JackLatencyCallback latency_callback, + void *) JACK_WEAK_EXPORT; +/*@}*/ + +/** + * @defgroup ServerControl Controlling & querying JACK server operation + * @{ + */ + +/** + * Start/Stop JACK's "freewheel" mode. + * + * When in "freewheel" mode, JACK no longer waits for + * any external event to begin the start of the next process + * cycle. + * + * As a result, freewheel mode causes "faster than realtime" + * execution of a JACK graph. If possessed, real-time + * scheduling is dropped when entering freewheel mode, and + * if appropriate it is reacquired when stopping. + * + * IMPORTANT: on systems using capabilities to provide real-time + * scheduling (i.e. Linux kernel 2.4), if onoff is zero, this function + * must be called from the thread that originally called jack_activate(). + * This restriction does not apply to other systems (e.g. Linux kernel 2.6 + * or OS X). + * + * @param client pointer to JACK client structure + * @param onoff if non-zero, freewheel mode starts. Otherwise + * freewheel mode ends. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_freewheel(jack_client_t* client, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Change the buffer size passed to the @a process_callback. + * + * This operation stops the JACK engine process cycle, then calls all + * registered @a bufsize_callback functions before restarting the + * process cycle. This will cause a gap in the audio flow, so it + * should only be done at appropriate stopping points. + * + * @see jack_set_buffer_size_callback() + * + * @param client pointer to JACK client structure. + * @param nframes new buffer size. Must be a power of two. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the sample rate of the jack system, as set by the user when + * jackd was started. + */ +jack_nframes_t jack_get_sample_rate (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the current maximum size that will ever be passed to the @a + * process_callback. It should only be used *before* the client has + * been activated. This size may change, clients that depend on it + * must register a @a bufsize_callback so they will be notified if it + * does. + * + * @see jack_set_buffer_size_callback() + */ +jack_nframes_t jack_get_buffer_size (jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Old-style interface to become the timebase for the entire JACK + * subsystem. + * + * @deprecated This function still exists for compatibility with the + * earlier transport interface, but it does nothing. Instead, see + * transport.h and use jack_set_timebase_callback(). + * + * @return ENOSYS, function not implemented. + */ +int jack_engine_takeover_timebase (jack_client_t *) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * @return the current CPU load estimated by JACK. This is a running + * average of the time it takes to execute a full process cycle for + * all clients as a percentage of the real time available per cycle + * determined by the buffer size and sample rate. + */ +float jack_cpu_load (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + + +/*@}*/ + +/** + * @defgroup PortFunctions Creating & manipulating ports + * @{ + */ + +/** + * Create a new port for the client. This is an object used for moving + * data of any type in or out of the client. Ports may be connected + * in various ways. + * + * Each port has a short name. The port's full name contains the name + * of the client concatenated with a colon (:) followed by its short + * name. The jack_port_name_size() is the maximum length of this full + * name. Exceeding that will cause the port registration to fail and + * return NULL. + * + * The @a port_name must be unique among all ports owned by this client. + * If the name is not unique, the registration will fail. + * + * All ports have a type, which may be any non-NULL and non-zero + * length string, passed as an argument. Some port types are built + * into the JACK API, like JACK_DEFAULT_AUDIO_TYPE or JACK_DEFAULT_MIDI_TYPE + * + * @param client pointer to JACK client structure. + * @param port_name non-empty short name for the new port (not + * including the leading @a "client_name:"). Must be unique. + * @param port_type port type name. If longer than + * jack_port_type_size(), only that many characters are significant. + * @param flags @ref JackPortFlags bit mask. + * @param buffer_size must be non-zero if this is not a built-in @a + * port_type. Otherwise, it is ignored. + * + * @return jack_port_t pointer on success, otherwise NULL. + */ +jack_port_t *jack_port_register (jack_client_t *client, + const char *port_name, + const char *port_type, + unsigned long flags, + unsigned long buffer_size) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Remove the port from the client, disconnecting any existing + * connections. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_unregister (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * This returns a pointer to the memory area associated with the + * specified port. For an output port, it will be a memory area + * that can be written to; for an input port, it will be an area + * containing the data from the port's connection(s), or + * zero-filled. if there are multiple inbound connections, the data + * will be mixed appropriately. + * + * Do not cache the returned address across process() callbacks. + * Port buffers have to be retrieved in each callback for proper functionning. + */ +void *jack_port_get_buffer (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the full name of the jack_port_t (including the @a + * "client_name:" prefix). + * + * @see jack_port_name_size(). + */ +const char *jack_port_name (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the short name of the jack_port_t (not including the @a + * "client_name:" prefix). + * + * @see jack_port_name_size(). + */ +const char *jack_port_short_name (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the @ref JackPortFlags of the jack_port_t. + */ +int jack_port_flags (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the @a port type, at most jack_port_type_size() characters + * including a final NULL. + */ +const char *jack_port_type (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return TRUE if the jack_port_t belongs to the jack_client_t. + */ +int jack_port_is_mine (const jack_client_t *, const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return number of connections to or from @a port. + * + * @pre The calling client must own @a port. + */ +int jack_port_connected (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return TRUE if the locally-owned @a port is @b directly connected + * to the @a port_name. + * + * @see jack_port_name_size() + */ +int jack_port_connected_to (const jack_port_t *port, + const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return a null-terminated array of full port names to which the @a + * port is connected. If none, returns NULL. + * + * The caller is responsible for calling jack_free(3) on any non-NULL + * returned value. + * + * @param port locally owned jack_port_t pointer. + * + * @see jack_port_name_size(), jack_port_get_all_connections() + */ +const char **jack_port_get_connections (const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return a null-terminated array of full port names to which the @a + * port is connected. If none, returns NULL. + * + * The caller is responsible for calling jack_free(3) on any non-NULL + * returned value. + * + * This differs from jack_port_get_connections() in two important + * respects: + * + * 1) You may not call this function from code that is + * executed in response to a JACK event. For example, + * you cannot use it in a GraphReordered handler. + * + * 2) You need not be the owner of the port to get information + * about its connections. + * + * @see jack_port_name_size() + */ +const char **jack_port_get_all_connections (const jack_client_t *client, + const jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * + * @deprecated This function will be removed from a future version + * of JACK. Do not use it. There is no replacement. It has + * turned out to serve essentially no purpose in real-life + * JACK clients. + */ +int jack_port_tie (jack_port_t *src, jack_port_t *dst) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * + * @deprecated This function will be removed from a future version + * of JACK. Do not use it. There is no replacement. It has + * turned out to serve essentially no purpose in real-life + * JACK clients. + */ +int jack_port_untie (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Modify a port's short name. May be called at any time. If the + * resulting full name (including the @a "client_name:" prefix) is + * longer than jack_port_name_size(), it will be truncated. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_set_name (jack_port_t *port, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set @a alias as an alias for @a port. May be called at any time. + * If the alias is longer than jack_port_name_size(), it will be truncated. + * + * After a successful call, and until JACK exits or + * jack_port_unset_alias() is called, may be + * used as a alternate name for the port. + * + * Ports can have up to two aliases - if both are already + * set, this function will return an error. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_set_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Remove @a alias as an alias for @a port. May be called at any time. + * + * After a successful call, @a alias can no longer be + * used as a alternate name for the port. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_unset_alias (jack_port_t *port, const char *alias) JACK_OPTIONAL_WEAK_EXPORT; + +/* + * Get any aliases known for @port. + * + * @return the number of aliases discovered for the port + */ +int jack_port_get_aliases (const jack_port_t *port, char* const aliases[2]) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * If @ref JackPortCanMonitor is set for this @a port, turn input + * monitoring on or off. Otherwise, do nothing. + */ +int jack_port_request_monitor (jack_port_t *port, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * If @ref JackPortCanMonitor is set for this @a port_name, turn input + * monitoring on or off. Otherwise, do nothing. + * + * @return 0 on success, otherwise a non-zero error code. + * + * @see jack_port_name_size() + */ +int jack_port_request_monitor_by_name (jack_client_t *client, + const char *port_name, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * If @ref JackPortCanMonitor is set for a port, this function turns + * on input monitoring if it was off, and turns it off if only one + * request has been made to turn it on. Otherwise it does nothing. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_ensure_monitor (jack_port_t *port, int onoff) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return TRUE if input monitoring has been requested for @a port. + */ +int jack_port_monitoring_input (jack_port_t *port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Establish a connection between two ports. + * + * When a connection exists, data written to the source port will + * be available to be read at the destination port. + * + * @pre The port types must be identical. + * + * @pre The @ref JackPortFlags of the @a source_port must include @ref + * JackPortIsOutput. + * + * @pre The @ref JackPortFlags of the @a destination_port must include + * @ref JackPortIsInput. + * + * @return 0 on success, EEXIST if the connection is already made, + * otherwise a non-zero error code + */ +int jack_connect (jack_client_t *, + const char *source_port, + const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Remove a connection between two ports. + * + * @pre The port types must be identical. + * + * @pre The @ref JackPortFlags of the @a source_port must include @ref + * JackPortIsOutput. + * + * @pre The @ref JackPortFlags of the @a destination_port must include + * @ref JackPortIsInput. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_disconnect (jack_client_t *, + const char *source_port, + const char *destination_port) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Perform the same function as jack_disconnect() using port handles + * rather than names. This avoids the name lookup inherent in the + * name-based version. + * + * Clients connecting their own ports are likely to use this function, + * while generic connection clients (e.g. patchbays) would use + * jack_disconnect(). + */ +int jack_port_disconnect (jack_client_t *, jack_port_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the maximum number of characters in a full JACK port name + * including the final NULL character. This value is a constant. + * + * A port's full name contains the owning client name concatenated + * with a colon (:) followed by its short name and a NULL + * character. + */ +int jack_port_name_size(void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the maximum number of characters in a JACK port type name + * including the final NULL character. This value is a constant. + */ +int jack_port_type_size(void) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the buffersize of a port of type @arg port_type. + * + * this function may only be called in a buffer_size callback. + */ +size_t jack_port_type_get_buffer_size (jack_client_t *client, const char *port_type) JACK_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup LatencyFunctions Managing and determining latency + * + * The purpose of JACK's latency API is to allow clients to + * easily answer two questions: + * + * - How long has it been since the data read from a port arrived + * at the edge of the JACK graph (either via a physical port + * or being synthesized from scratch)? + * + * - How long will it be before the data written to a port arrives + * at the edge of a JACK graph? + + * To help answering these two questions, all JACK ports have two + * latency values associated with them, both measured in frames: + * + * capture latency: how long since the data read from + * the buffer of a port arrived at at + * a port marked with JackPortIsTerminal. + * The data will have come from the "outside + * world" if the terminal port is also + * marked with JackPortIsPhysical, or + * will have been synthesized by the client + * that owns the terminal port. + * + * playback latency: how long until the data + * written to the buffer of port will reach a port + * marked with JackPortIsTerminal. + * + * Both latencies might potentially have more than one value + * because there may be multiple pathways to/from a given port + * and a terminal port. Latency is therefore generally + * expressed a min/max pair. + * + * In most common setups, the minimum and maximum latency + * are the same, but this design accomodates more complex + * routing, and allows applications (and thus users) to + * detect cases where routing is creating an anomalous + * situation that may either need fixing or more + * sophisticated handling by clients that care about + * latency. + * + * See also @ref jack_set_latency_callback for details on how + * clients that add latency to the signal path should interact + * with JACK to ensure that the correct latency figures are + * used. + * @{ + */ + +/** + * The port latency is zero by default. Clients that control + * physical hardware with non-zero latency should call this + * to set the latency to its correct value. Note that the value + * should include any systemic latency present "outside" the + * physical hardware controlled by the client. For example, + * for a client controlling a digital audio interface connected + * to an external digital converter, the latency setting should + * include both buffering by the audio interface *and* the converter. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by a latency callback that calls @ref + * jack_port_set_latency_range(). + */ +void jack_port_set_latency (jack_port_t *, jack_nframes_t) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * return the latency range defined by @a mode for + * @a port, in frames. + * + * See @ref LatencyFunctions for the definition of each latency value. + * + * This is normally used in the LatencyCallback. + * and therefor safe to execute from callbacks. + */ +void jack_port_get_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; + +/** + * set the minimum and maximum latencies defined by + * @a mode for @a port, in frames. + * + * See @ref LatencyFunctions for the definition of each latency value. + * + * This function should ONLY be used inside a latency + * callback. The client should determine the current + * value of the latency using @ref jack_port_get_latency_range() + * (called using the same mode as @a mode) + * and then add some number of frames to that reflects + * latency added by the client. + * + * How much latency a client adds will vary + * dramatically. For most clients, the answer is zero + * and there is no reason for them to register a latency + * callback and thus they should never call this + * function. + * + * More complex clients that take an input signal, + * transform it in some way and output the result but + * not during the same process() callback will + * generally know a single constant value to add + * to the value returned by @ref jack_port_get_latency_range(). + * + * Such clients would register a latency callback (see + * @ref jack_set_latency_callback) and must know what input + * ports feed which output ports as part of their + * internal state. Their latency callback will update + * the ports' latency values appropriately. + * + * A pseudo-code example will help. The @a mode argument to the latency + * callback will determine whether playback or capture + * latency is being set. The callback will use + * @ref jack_port_set_latency_range() as follows: + * + * \code + * jack_latency_range_t range; + * if (mode == JackPlaybackLatency) { + * foreach input_port in (all self-registered port) { + * jack_port_get_latency_range (port_feeding_input_port, JackPlaybackLatency, &range); + * range.min += min_delay_added_as_signal_flows_from port_feeding to input_port; + * range.max += max_delay_added_as_signal_flows_from port_feeding to input_port; + * jack_port_set_latency_range (input_port, JackPlaybackLatency, &range); + * } + * } else if (mode == JackCaptureLatency) { + * foreach output_port in (all self-registered port) { + * jack_port_get_latency_range (port_fed_by_output_port, JackCaptureLatency, &range); + * range.min += min_delay_added_as_signal_flows_from_output_port_to_fed_by_port; + * range.max += max_delay_added_as_signal_flows_from_output_port_to_fed_by_port; + * jack_port_set_latency_range (output_port, JackCaptureLatency, &range); + * } + * } + * \endcode + * + * In this relatively simple pseudo-code example, it is assumed that + * each input port or output is connected to only 1 output or input + * port respectively. + * + * If a port is connected to more than 1 other port, then the + * range.min and range.max values passed to @ref + * jack_port_set_latency_range() should reflect the minimum and + * maximum values across all connected ports. + * + * See the description of @ref jack_set_latency_callback for more + * information. + */ +void jack_port_set_latency_range (jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range) JACK_WEAK_EXPORT; + +/** + * Request a complete recomputation of all port latencies. This + * can be called by a client that has just changed the internal + * latency of its port using jack_port_set_latency + * and wants to ensure that all signal pathways in the graph + * are updated with respect to the values that will be returned + * by jack_port_get_total_latency. It allows a client + * to change multiple port latencies without triggering a + * recompute for each change. + * + * @return zero for successful execution of the request. non-zero + * otherwise. + */ +int jack_recompute_total_latencies (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the time (in frames) between data being available or + * delivered at/to a port, and the time at which it arrived at or is + * delivered to the "other side" of the port. E.g. for a physical + * audio output port, this is the time between writing to the port and + * when the signal will leave the connector. For a physical audio + * input port, this is the time between the sound arriving at the + * connector and the corresponding frames being readable from the + * port. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_port_get_latency_range() in any existing + * use cases. + */ +jack_nframes_t jack_port_get_latency (jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * The maximum of the sum of the latencies in every + * connection path that can be drawn between the port and other + * ports with the @ref JackPortIsTerminal flag set. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_port_get_latency_range() in any existing + * use cases. + */ +jack_nframes_t jack_port_get_total_latency (jack_client_t *, + jack_port_t *port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Request a complete recomputation of a port's total latency. This + * can be called by a client that has just changed the internal + * latency of its port using jack_port_set_latency + * and wants to ensure that all signal pathways in the graph + * are updated with respect to the values that will be returned + * by jack_port_get_total_latency. + * + * @return zero for successful execution of the request. non-zero + * otherwise. + * + * @deprecated This method will be removed in the next major + * release of JACK. It should not be used in new code, and should + * be replaced by jack_recompute_total_latencies() in any existing + * use cases. + */ +int jack_recompute_total_latency (jack_client_t*, jack_port_t* port) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/*@}*/ + +/** + * @defgroup PortSearching Looking up ports + * @{ + */ + +/** + * @param port_name_pattern A regular expression used to select + * ports by name. If NULL or of zero length, no selection based + * on name will be carried out. + * @param type_name_pattern A regular expression used to select + * ports by type. If NULL or of zero length, no selection based + * on type will be carried out. + * @param flags A value used to select ports by their flags. + * If zero, no selection based on flags will be carried out. + * + * @return a NULL-terminated array of ports that match the specified + * arguments. The caller is responsible for calling jack_free(3) any + * non-NULL returned value. + * + * @see jack_port_name_size(), jack_port_type_size() + */ +const char **jack_get_ports (jack_client_t *, + const char *port_name_pattern, + const char *type_name_pattern, + unsigned long flags) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return address of the jack_port_t named @a port_name. + * + * @see jack_port_name_size() + */ +jack_port_t *jack_port_by_name (jack_client_t *, const char *port_name) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return address of the jack_port_t of a @a port_id. + */ +jack_port_t *jack_port_by_id (jack_client_t *client, + jack_port_id_t port_id) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + + +/** + * @defgroup TimeFunctions Handling time + * @{ + * + * JACK time is in units of 'frames', according to the current sample rate. + * The absolute value of frame times is meaningless, frame times have meaning + * only relative to each other. + */ + +/** + * @return the estimated time in frames that has passed since the JACK + * server began the current process cycle. + */ +jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the estimated current time in frames. + * This function is intended for use in other threads (not the process + * callback). The return value can be compared with the value of + * jack_last_frame_time to relate time in other threads to JACK time. + */ +jack_nframes_t jack_frame_time (const jack_client_t *) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the precise time at the start of the current process cycle. + * This function may only be used from the process callback, and can + * be used to interpret timestamps generated by jack_frame_time() in + * other threads with respect to the current process cycle. + * + * This is the only jack time function that returns exact time: + * when used during the process callback it always returns the same + * value (until the next process callback, where it will return + * that value + nframes, etc). The return value is guaranteed to be + * monotonic and linear in this fashion unless an xrun occurs. + * If an xrun occurs, clients must check this value again, as time + * may have advanced in a non-linear way (e.g. cycles may have been skipped). + */ +jack_nframes_t jack_last_frame_time (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the estimated time in microseconds of the specified frame time + */ +jack_time_t jack_frames_to_time(const jack_client_t *client, jack_nframes_t) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return the estimated time in frames for the specified system time. + */ +jack_nframes_t jack_time_to_frames(const jack_client_t *client, jack_time_t) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @return return JACK's current system time in microseconds, + * using the JACK clock source. + * + * The value returned is guaranteed to be monotonic, but not linear. + */ +jack_time_t jack_get_time() JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/** + * @defgroup ErrorOutput Controlling error/information output + */ +/*@{*/ + +/** + * Display JACK error message. + * + * Set via jack_set_error_function(), otherwise a JACK-provided + * default will print @a msg (plus a newline) to stderr. + * + * @param msg error message text (no newline at end). + */ +extern void (*jack_error_callback)(const char *msg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the @ref jack_error_callback for error message display. + * + * The JACK library provides two built-in callbacks for this purpose: + * default_jack_error_callback() and silent_jack_error_callback(). + */ +void jack_set_error_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Display JACK info message. + * + * Set via jack_set_info_function(), otherwise a JACK-provided + * default will print @a msg (plus a newline) to stdout. + * + * @param msg info message text (no newline at end). + */ +extern void (*jack_info_callback)(const char *msg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the @ref jack_info_callback for info message display. + */ +void jack_set_info_function (void (*func)(const char *)) JACK_OPTIONAL_WEAK_EXPORT; +/*@}*/ + +/** + * The free function to be used on memory returned by jack_port_get_connections, + * jack_port_get_all_connections and jack_get_ports functions. + * This is MANDATORY on Windows when otherwise all nasty runtime version related crashes can occur. + * Developers are strongly encouraged to use this function instead of the standard "free" function in new code. + * + */ +void jack_free(void* ptr) JACK_OPTIONAL_WEAK_EXPORT; + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_h__ */ diff --git a/jslist.h b/jslist.h new file mode 100644 index 0000000..9c91540 --- /dev/null +++ b/jslist.h @@ -0,0 +1,303 @@ +/* + Based on gslist.c from glib-1.2.9 (LGPL). + + Adaption to JACK, Copyright (C) 2002 Kai Vehmanen. + - replaced use of gtypes with normal ANSI C types + - glib's memery allocation routines replaced with + malloc/free calls + + 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 __jack_jslist_h__ +#define __jack_jslist_h__ + +#include + +typedef struct _JSList JSList; + +typedef int (*JCompareFunc) (void* a, + void* b); +struct _JSList +{ + void *data; + JSList *next; +}; + +static __inline__ +JSList* +jack_slist_alloc (void) +{ + JSList *new_list; + + new_list = malloc(sizeof(JSList)); + new_list->data = NULL; + new_list->next = NULL; + + return new_list; +} + +static __inline__ +JSList* +jack_slist_prepend (JSList *list, + void *data) +{ + JSList *new_list; + + new_list = malloc(sizeof(JSList)); + new_list->data = data; + new_list->next = list; + + return new_list; +} + +#define jack_slist_next(slist) ((slist) ? (((JSList *)(slist))->next) : NULL) +static __inline__ +JSList* +jack_slist_last (JSList *list) +{ + if (list) + { + while (list->next) + list = list->next; + } + + return list; +} + +static __inline__ +JSList* +jack_slist_remove_link (JSList *list, + JSList *link) +{ + JSList *tmp; + JSList *prev; + + prev = NULL; + tmp = list; + + while (tmp) + { + if (tmp == link) + { + if (prev) + prev->next = tmp->next; + if (list == tmp) + list = list->next; + + tmp->next = NULL; + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +static __inline__ +void +jack_slist_free (JSList *list) +{ + while (list) + { + JSList *next = list->next; + free(list); + list = next; + } +} + +static __inline__ +void +jack_slist_free_1 (JSList *list) +{ + if (list) + { + free(list); + } +} + +static __inline__ +JSList* +jack_slist_remove (JSList *list, + void *data) +{ + JSList *tmp; + JSList *prev; + + prev = NULL; + tmp = list; + + while (tmp) + { + if (tmp->data == data) + { + if (prev) + prev->next = tmp->next; + if (list == tmp) + list = list->next; + + tmp->next = NULL; + jack_slist_free (tmp); + + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +static __inline__ +unsigned int +jack_slist_length (JSList *list) +{ + unsigned int length; + + length = 0; + while (list) + { + length++; + list = list->next; + } + + return length; +} + +static __inline__ +JSList* +jack_slist_find (JSList *list, + void *data) +{ + while (list) + { + if (list->data == data) + break; + list = list->next; + } + + return list; +} + +static __inline__ +JSList* +jack_slist_copy (JSList *list) +{ + JSList *new_list = NULL; + + if (list) + { + JSList *last; + + new_list = jack_slist_alloc (); + new_list->data = list->data; + last = new_list; + list = list->next; + while (list) + { + last->next = jack_slist_alloc (); + last = last->next; + last->data = list->data; + list = list->next; + } + } + + return new_list; +} + +static __inline__ +JSList* +jack_slist_append (JSList *list, + void *data) +{ + JSList *new_list; + JSList *last; + + new_list = jack_slist_alloc (); + new_list->data = data; + + if (list) + { + last = jack_slist_last (list); + last->next = new_list; + + return list; + } + else + return new_list; +} + +static __inline__ +JSList* +jack_slist_sort_merge (JSList *l1, + JSList *l2, + JCompareFunc compare_func) +{ + JSList list, *l; + + l=&list; + + while (l1 && l2) + { + if (compare_func(l1->data,l2->data) < 0) + { + l=l->next=l1; + l1=l1->next; + } + else + { + l=l->next=l2; + l2=l2->next; + } + } + l->next= l1 ? l1 : l2; + + return list.next; +} + +static __inline__ +JSList* +jack_slist_sort (JSList *list, + JCompareFunc compare_func) +{ + JSList *l1, *l2; + + if (!list) + return NULL; + if (!list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) + { + if ((l2 = l2->next) == NULL) + break; + l1=l1->next; + } + l2 = l1->next; + l1->next = NULL; + + return jack_slist_sort_merge (jack_slist_sort (list, compare_func), + jack_slist_sort (l2, compare_func), + compare_func); +} + +#endif /* __jack_jslist_h__ */ diff --git a/memops.h b/memops.h new file mode 100644 index 0000000..a5582bf --- /dev/null +++ b/memops.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 1999-2000 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. + +*/ + +#ifndef __jack_memops_h__ +#define __jack_memops_h__ + +#include + +typedef enum { + None, + Rectangular, + Triangular, + Shaped +} DitherAlgorithm; + +#define DITHER_BUF_SIZE 8 +#define DITHER_BUF_MASK 7 + +typedef struct { + unsigned int depth; + float rm1; + unsigned int idx; + float e[DITHER_BUF_SIZE]; +} dither_state_t; + +/* float functions */ +void sample_move_floatLE_sSs (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long dst_skip); +void sample_move_dS_floatLE (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); + +/* integer functions */ +void sample_move_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); + +void sample_move_dither_rect_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_rect_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_tri_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_tri_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_shaped_d32u24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_shaped_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_rect_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_rect_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_tri_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_tri_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_shaped_d24_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_shaped_d24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_rect_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_rect_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_tri_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_tri_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_shaped_d16_sSs (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_move_dither_shaped_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); + +void sample_move_dS_s32u24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); +void sample_move_dS_s32u24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); +void sample_move_dS_s24s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); +void sample_move_dS_s24 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); +void sample_move_dS_s16s (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); +void sample_move_dS_s16 (jack_default_audio_sample_t *dst, char *src, unsigned long nsamples, unsigned long src_skip); + +void sample_merge_d16_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); +void sample_merge_d32u24_sS (char *dst, jack_default_audio_sample_t *src, unsigned long nsamples, unsigned long dst_skip, dither_state_t *state); + +static __inline__ void +sample_merge (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) + +{ + while (cnt--) { + *dst += *src; + dst++; + src++; + } +} + +static __inline__ void +sample_memcpy (jack_default_audio_sample_t *dst, jack_default_audio_sample_t *src, unsigned long cnt) + +{ + memcpy (dst, src, cnt * sizeof (jack_default_audio_sample_t)); +} + +void memset_interleave (char *dst, char val, unsigned long bytes, unsigned long unit_bytes, unsigned long skip_bytes); +void memcpy_fake (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); + +void memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); +void memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); +void memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); + +void merge_memcpy_interleave_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); +void merge_memcpy_interleave_d24_s24 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); +void merge_memcpy_interleave_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long dst_skip_bytes, unsigned long src_skip_bytes); + +void merge_memcpy_d16_s16 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); +void merge_memcpy_d32_s32 (char *dst, char *src, unsigned long src_bytes, unsigned long foo, unsigned long bar); + +#endif /* __jack_memops_h__ */ diff --git a/messagebuffer.h b/messagebuffer.h new file mode 100644 index 0000000..18b8027 --- /dev/null +++ b/messagebuffer.h @@ -0,0 +1,44 @@ +/* + * messagebuffer.h -- realtime-safe message interface for jackd. + * + * This function is included in libjack so backend drivers can use + * it, *not* for external client processes. The VERBOSE() and + * MESSAGE() macros are realtime-safe. + */ + +/* + * Copyright (C) 2004 Rui Nuno Capela, Steve Harris + * + * 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 __jack_messagebuffer_h__ +#define __jack_messagebuffer_h__ + +#define MESSAGE(fmt,args...) jack_messagebuffer_add(fmt , ##args) +#define VERBOSE(engine,fmt,args...) \ + if ((engine)->verbose) \ + jack_messagebuffer_add(fmt , ##args) + +void jack_messagebuffer_init(); +void jack_messagebuffer_exit(); +void jack_message_buffer_thread_init (void (*cb)(void*), void*); + +void jack_messagebuffer_add(const char *fmt, ...); + +void jack_messagebuffer_thread_init (void (*cb)(void*), void* arg); + +#endif /* __jack_messagebuffer_h__ */ diff --git a/midiport.h b/midiport.h new file mode 100644 index 0000000..b388254 --- /dev/null +++ b/midiport.h @@ -0,0 +1,174 @@ +/* + Copyright (C) 2004 Ian Esten + + 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 __JACK_MIDIPORT_H +#define __JACK_MIDIPORT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + + +/** Type for raw event data contained in @ref jack_midi_event_t. */ +typedef unsigned char jack_midi_data_t; + + +/** A Jack MIDI event. */ +typedef struct _jack_midi_event +{ + jack_nframes_t time; /**< Sample index at which event is valid */ + size_t size; /**< Number of bytes of data in \a buffer */ + jack_midi_data_t *buffer; /**< Raw MIDI data */ +} jack_midi_event_t; + + +/** + * @defgroup MIDIAPI Reading and writing MIDI data + * @{ + */ + +/* Get number of events in a port buffer. + * + * @param port_buffer Port buffer from which to retrieve event. + * @return number of events inside @a port_buffer + */ +jack_nframes_t +jack_midi_get_event_count(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Get a MIDI event from an event port buffer. + * + * Jack MIDI is normalised, the MIDI event returned by this function is + * guaranteed to be a complete MIDI event (the status byte will always be + * present, and no realtime events will interspered with the event). + * + * @param event Event structure to store retrieved event in. + * @param port_buffer Port buffer from which to retrieve event. + * @param event_index Index of event to retrieve. + * @return 0 on success, ENODATA if buffer is empty. + */ +int +jack_midi_event_get(jack_midi_event_t *event, + void *port_buffer, + uint32_t event_index) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Clear an event buffer. + * + * This should be called at the beginning of each process cycle before calling + * @ref jack_midi_event_reserve or @ref jack_midi_event_write. This + * function may not be called on an input port's buffer. + * + * @param port_buffer Port buffer to clear (must be an output port buffer). + */ +void +jack_midi_clear_buffer(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Get the size of the largest event that can be stored by the port. + * + * This function returns the current space available, taking into account + * events already stored in the port. + * + * @param port_buffer Port buffer to check size of. + */ +size_t +jack_midi_max_event_size(void* port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Allocate space for an event to be written to an event port buffer. + * + * Clients are to write the actual event data to be written starting at the + * pointer returned by this function. Clients must not write more than + * @a data_size bytes into this buffer. Clients must write normalised + * MIDI data to the port - no running status and no (1-byte) realtime + * messages interspersed with other messages (realtime messages are fine + * when they occur on their own, like other messages). + * + * Events must be written in order, sorted by their sample offsets. + * JACK will not sort the events for you, and will refuse to store + * out-of-order events. + * + * @param port_buffer Buffer to write event to. + * @param time Sample offset of event. + * @param data_size Length of event's raw data in bytes. + * @return Pointer to the beginning of the reserved event's data buffer, or + * NULL on error (ie not enough space). + */ +jack_midi_data_t* +jack_midi_event_reserve(void *port_buffer, + jack_nframes_t time, + size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Write an event into an event port buffer. + * + * This function is simply a wrapper for @ref jack_midi_event_reserve + * which writes the event data into the space reserved in the buffer. + * + * Clients must not write more than + * @a data_size bytes into this buffer. Clients must write normalised + * MIDI data to the port - no running status and no (1-byte) realtime + * messages interspersed with other messages (realtime messages are fine + * when they occur on their own, like other messages). + * + * Events must be written in order, sorted by their sample offsets. + * JACK will not sort the events for you, and will refuse to store + * out-of-order events. + * + * @param port_buffer Buffer to write event to. + * @param time Sample offset of event. + * @param data Message data to be written. + * @param data_size Length of @a data in bytes. + * @return 0 on success, ENOBUFS if there's not enough space in buffer for event. + */ +int +jack_midi_event_write(void *port_buffer, + jack_nframes_t time, + const jack_midi_data_t *data, + size_t data_size) JACK_OPTIONAL_WEAK_EXPORT; + + +/** Get the number of events that could not be written to @a port_buffer. + * + * This function returning a non-zero value implies @a port_buffer is full. + * Currently the only way this can happen is if events are lost on port mixdown. + * + * @param port_buffer Port to receive count for. + * @returns Number of events that could not be written to @a port_buffer. + */ +uint32_t +jack_midi_get_lost_event_count(void *port_buffer) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + + +#ifdef __cplusplus +} +#endif + + +#endif /* __JACK_MIDIPORT_H */ + + diff --git a/pool.h b/pool.h new file mode 100644 index 0000000..41ad618 --- /dev/null +++ b/pool.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2001 Paul Davis + + 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 __jack_pool_h__ +#define __jack_pool_h__ + +#include + +void * jack_pool_alloc (size_t bytes); +void jack_pool_release (void *); + +#endif /* __jack_pool_h__ */ diff --git a/port.h b/port.h new file mode 100644 index 0000000..4447f74 --- /dev/null +++ b/port.h @@ -0,0 +1,188 @@ +/* + Copyright (C) 2001 Paul Davis + + 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 __jack_port_h__ +#define __jack_port_h__ + +#include +#include +#include +#include + +#define JACK_PORT_NAME_SIZE 256 +#define JACK_PORT_TYPE_SIZE 32 + +/* The relatively low value of this constant reflects the fact that + * JACK currently only knows about *2* port types. (May 2006) + * + * Further, the 4 covers: + * - a single non-negotiated audio format + * - music data (ie. MIDI) + * - video + * - one other + * + * which is probably enough for more than just the foreseeable future. + */ +#define JACK_MAX_PORT_TYPES 4 +#define JACK_AUDIO_PORT_TYPE 0 +#define JACK_MIDI_PORT_TYPE 1 + +/* these should probably go somewhere else, but not in */ +#define JACK_CLIENT_NAME_SIZE 33 +typedef uint32_t jack_client_id_t; + +/* JACK shared memory segments are limited to MAX_INT32, they can be + * shared between 32-bit and 64-bit clients. + */ +#define JACK_SHM_MAX (MAX_INT32) +typedef int32_t jack_port_type_id_t; + +#define JACK_BACKEND_ALIAS "system" + +#ifndef POST_PACKED_STRUCTURE +#ifdef __GNUC__ +/* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. +*/ +#define POST_PACKED_STRUCTURE __attribute__((__packed__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +/* Port type structure. + * + * (1) One for each port type is part of the engine's jack_control_t + * shared memory structure. + * + * (2) One for each port type is appended to the engine's + * jack_client_connect_result_t response. The client reads them into + * its local memory, using them to attach the corresponding shared + * memory segments. + */ +typedef struct _jack_port_type_info { + + jack_port_type_id_t ptype_id; + const char type_name[JACK_PORT_TYPE_SIZE]; + + /* If == 1, then a buffer to handle nframes worth of data has + * sizeof(jack_default_audio_sample_t) * nframes bytes. + * + * If > 1, the buffer allocated for input mixing will be + * this value times sizeof(jack_default_audio_sample_t) + * * nframes bytes in size. For non-audio data types, + * it may have a different value. + * + * If < 0, the value should be ignored, and buffer_size + * should be used. + */ + int32_t buffer_scale_factor; + + /* ignored unless buffer_scale_factor is < 0. see above */ + jack_shmsize_t buffer_size; + + jack_shm_registry_index_t shm_registry_index; + + jack_shmsize_t zero_buffer_offset; + +} POST_PACKED_STRUCTURE jack_port_type_info_t; + +/* Allocated by the engine in shared memory. */ +typedef struct _jack_port_shared { + + jack_port_type_id_t ptype_id; /* index into port type array */ + jack_shmsize_t offset; /* buffer offset in shm segment */ + jack_port_id_t id; /* index into engine port array */ + uint32_t flags; + char name[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE]; + char alias1[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE]; + char alias2[JACK_CLIENT_NAME_SIZE+JACK_PORT_NAME_SIZE]; + jack_client_id_t client_id; /* who owns me */ + + volatile jack_nframes_t latency; + volatile jack_nframes_t total_latency; + volatile jack_latency_range_t playback_latency; + volatile jack_latency_range_t capture_latency; + volatile uint8_t monitor_requests; + + char has_mixdown; /* port has a mixdown function */ + char in_use; + char unused; /* legacy locked field */ + +} POST_PACKED_STRUCTURE jack_port_shared_t; + +typedef struct _jack_port_functions { + + /* Function to initialize port buffer. Cannot be NULL. + * NOTE: This must take a buffer rather than jack_port_t as it is called + * in jack_engine_place_buffers() before any port creation. + * A better solution is to make jack_engine_place_buffers to be type-specific, + * but this works. + */ + void (*buffer_init)(void *buffer, size_t size, jack_nframes_t); + + /* Function to mixdown multiple inputs to a buffer. Can be NULL, + * indicating that multiple input connections are not legal for + * this data type. + */ + void (*mixdown)(jack_port_t *, jack_nframes_t); + +} jack_port_functions_t; + +/** + * Get port functions. + * @param ptid port type id. + * + * @return pointer to port type functions or NULL if port type is unknown. + */ +/*const*/ jack_port_functions_t * +jack_get_port_functions(jack_port_type_id_t ptid); + + +/* Allocated by the client in local memory. */ +struct _jack_port { + void **client_segment_base; + void *mix_buffer; + jack_port_type_info_t *type_info; /* shared memory type info */ + struct _jack_port_shared *shared; /* corresponding shm struct */ + struct _jack_port *tied; /* locally tied source port */ + jack_port_functions_t fptr; + pthread_mutex_t connection_lock; + JSList *connections; +}; + +/* Inline would be cleaner, but it needs to be fast even in + * non-optimized code. jack_output_port_buffer() only handles output + * ports. jack_port_buffer() works for both input and output ports. + */ +#define jack_port_buffer(p) \ + ((void *) ((p)->mix_buffer? (p)->mix_buffer: \ + *(p)->client_segment_base + (p)->shared->offset)) +#define jack_output_port_buffer(p) \ + ((void *) (*(p)->client_segment_base + (p)->shared->offset)) + +/* not for use by JACK applications */ +size_t jack_port_type_buffer_size (jack_port_type_info_t* port_type_info, jack_nframes_t nframes); + +#endif /* __jack_port_h__ */ + diff --git a/ringbuffer.h b/ringbuffer.h new file mode 100644 index 0000000..2662d9c --- /dev/null +++ b/ringbuffer.h @@ -0,0 +1,235 @@ +/* + Copyright (C) 2000 Paul Davis + Copyright (C) 2003 Rohan Drape + + 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 _RINGBUFFER_H +#define _RINGBUFFER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** @file ringbuffer.h + * + * A set of library functions to make lock-free ringbuffers available + * to JACK clients. The `capture_client.c' (in the example_clients + * directory) is a fully functioning user of this API. + * + * The key attribute of a ringbuffer is that it can be safely accessed + * by two threads simultaneously -- one reading from the buffer and + * the other writing to it -- without using any synchronization or + * mutual exclusion primitives. For this to work correctly, there can + * only be a single reader and a single writer thread. Their + * identities cannot be interchanged. + */ + +typedef struct +{ + char *buf; + size_t len; +} +jack_ringbuffer_data_t ; + +typedef struct +{ + char *buf; + volatile size_t write_ptr; + volatile size_t read_ptr; + size_t size; + size_t size_mask; + int mlocked; +} +jack_ringbuffer_t ; + +/** + * Allocates a ringbuffer data structure of a specified size. The + * caller must arrange for a call to jack_ringbuffer_free() to release + * the memory associated with the ringbuffer. + * + * @param sz the ringbuffer size in bytes. + * + * @return a pointer to a new jack_ringbuffer_t, if successful; NULL + * otherwise. + */ +jack_ringbuffer_t *jack_ringbuffer_create(size_t sz); + +/** + * Frees the ringbuffer data structure allocated by an earlier call to + * jack_ringbuffer_create(). + * + * @param rb a pointer to the ringbuffer structure. + */ +void jack_ringbuffer_free(jack_ringbuffer_t *rb); + +/** + * Fill a data structure with a description of the current readable + * data held in the ringbuffer. This description is returned in a two + * element array of jack_ringbuffer_data_t. Two elements are needed + * because the data to be read may be split across the end of the + * ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be read in a contiguous fashion using the address given in the + * corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be read from the address given in + * its corresponding @a buf field. + * + * @param rb a pointer to the ringbuffer structure. + * @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. + * + */ +void jack_ringbuffer_get_read_vector(const jack_ringbuffer_t *rb, + jack_ringbuffer_data_t *vec); + +/** + * Fill a data structure with a description of the current writable + * space in the ringbuffer. The description is returned in a two + * element array of jack_ringbuffer_data_t. Two elements are needed + * because the space available for writing may be split across the end + * of the ringbuffer. + * + * The first element will always contain a valid @a len field, which + * may be zero or greater. If the @a len field is non-zero, then data + * can be written in a contiguous fashion using the address given in + * the corresponding @a buf field. + * + * If the second element has a non-zero @a len field, then a second + * contiguous stretch of data can be written to the address given in + * the corresponding @a buf field. + * + * @param rb a pointer to the ringbuffer structure. + * @param vec a pointer to a 2 element array of jack_ringbuffer_data_t. + */ +void jack_ringbuffer_get_write_vector(const jack_ringbuffer_t *rb, + jack_ringbuffer_data_t *vec); + +/** + * Read data from the ringbuffer. + * + * @param rb a pointer to the ringbuffer structure. + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ +size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt); + +/** + * Read data from the ringbuffer. Opposed to jack_ringbuffer_read() + * this function does not move the read pointer. Thus it's + * a convenient way to inspect data in the ringbuffer in a + * continous fashion. The price is that the data is copied + * into a user provided buffer. For "raw" non-copy inspection + * of the data in the ringbuffer use jack_ringbuffer_get_read_vector(). + * + * @param rb a pointer to the ringbuffer structure. + * @param dest a pointer to a buffer where data read from the + * ringbuffer will go. + * @param cnt the number of bytes to read. + * + * @return the number of bytes read, which may range from 0 to cnt. + */ +size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt); + +/** + * Advance the read pointer. + * + * After data have been read from the ringbuffer using the pointers + * returned by jack_ringbuffer_get_read_vector(), use this function to + * advance the buffer pointers, making that space available for future + * write operations. + * + * @param rb a pointer to the ringbuffer structure. + * @param cnt the number of bytes read. + */ +void jack_ringbuffer_read_advance(jack_ringbuffer_t *rb, size_t cnt); + +/** + * Return the number of bytes available for reading. + * + * @param rb a pointer to the ringbuffer structure. + * + * @return the number of bytes available to read. + */ +size_t jack_ringbuffer_read_space(const jack_ringbuffer_t *rb); + +/** + * Lock a ringbuffer data block into memory. + * + * Uses the mlock() system call. This is not a realtime operation. + * + * @param rb a pointer to the ringbuffer structure. + */ +int jack_ringbuffer_mlock(jack_ringbuffer_t *rb); + +/** + * Reset the read and write pointers, making an empty buffer. + * + * This is not thread safe. + * + * @param rb a pointer to the ringbuffer structure. + */ +void jack_ringbuffer_reset(jack_ringbuffer_t *rb); + +/** + * Write data into the ringbuffer. + * + * @param rb a pointer to the ringbuffer structure. + * @param src a pointer to the data to be written to the ringbuffer. + * @param cnt the number of bytes to write. + * + * @return the number of bytes write, which may range from 0 to cnt + */ +size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src, + size_t cnt); + +/** + * Advance the write pointer. + * + * After data have been written the ringbuffer using the pointers + * returned by jack_ringbuffer_get_write_vector(), use this function + * to advance the buffer pointer, making the data available for future + * read operations. + * + * @param rb a pointer to the ringbuffer structure. + * @param cnt the number of bytes written. + */ +void jack_ringbuffer_write_advance(jack_ringbuffer_t *rb, size_t cnt); + +/** + * Return the number of bytes available for writing. + * + * @param rb a pointer to the ringbuffer structure. + * + * @return the amount of free space (in bytes) available for writing. + */ +size_t jack_ringbuffer_write_space(const jack_ringbuffer_t *rb); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sanitycheck.h b/sanitycheck.h new file mode 100644 index 0000000..5c98896 --- /dev/null +++ b/sanitycheck.h @@ -0,0 +1,22 @@ +#ifndef __jack_sanitycheck_h__ +#define __jack_sanitycheck_h__ + +/** + * GPL etc. + * + * @author Florian Faber + * + * @version 0.1 (2009-01-17) [FF] + * - initial version + **/ + +/** + * Performs a range of sanity checks on the system. The number of + * found problems is returned. + * + **/ + +int sanitycheck (int do_realtime_check, + int do_freqscaling_check); + +#endif /* __jack_sanitycheck_h__ */ diff --git a/session.h b/session.h new file mode 100644 index 0000000..0f78594 --- /dev/null +++ b/session.h @@ -0,0 +1,289 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004 Jack O'Quin + Copyright (C) 2010 Torben Hohn + + 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 __jack_session_h__ +#define __jack_session_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @defgroup SessionClientFunctions Session API for clients. + * @{ + */ + + +/** + * Session event type. + * + * if a client cant save templates, i might just do a normal save. + * + * There is no "quit without saving" event because a client might refuse to + * quit when it has unsaved data, but other clients may have already quit. + * This results in too much confusion, so it is unsupported. + */ +enum JackSessionEventType { + /** + * Save the session completely. + * + * The client may save references to data outside the provided directory, + * but it must do so by creating a link inside the provided directory and + * referring to that in any save files. The client must not refer to data + * files outside the provided directory directly in save files, because + * this makes it impossible for the session manager to create a session + * archive for distribution or archival. + */ + JackSessionSave = 1, + + /** + * Save the session completly, then quit. + * + * The rules for saving are exactly the same as for JackSessionSave. + */ + JackSessionSaveAndQuit = 2, + + /** + * Save a session template. + * + * A session template is a "skeleton" of the session, but without any data. + * Clients must save a session that, when restored, will create the same + * ports as a full save would have. However, the actual data contained in + * the session may not be saved (e.g. a DAW would create the necessary + * tracks, but not save the actual recorded data). + */ + JackSessionSaveTemplate = 3 +}; + +typedef enum JackSessionEventType jack_session_event_type_t; + +/** + * @ref jack_session_flags_t bits + */ +enum JackSessionFlags { + /** + * An error occured while saving. + */ + JackSessionSaveError = 0x01, + + /** + * Client needs to be run in a terminal. + */ + JackSessionNeedTerminal = 0x02 +}; + +/** + * Session flags. + */ +typedef enum JackSessionFlags jack_session_flags_t; + +struct _jack_session_event { + /** + * The type of this session event. + */ + jack_session_event_type_t type; + + /** + * Session directory path, with trailing separator. + * + * This directory is exclusive to the client; when saving the client may + * create any files it likes in this directory. + */ + const char *session_dir; + + /** + * Client UUID which must be passed to jack_client_open on session load. + * + * The client can specify this in the returned command line, or save it + * in a state file within the session directory. + */ + const char *client_uuid; + + /** + * Reply (set by client): the command line needed to restore the client. + * + * This is a platform dependent command line. It must contain + * ${SESSION_DIR} instead of the actual session directory path. More + * generally, just as in session files, clients should not include any + * paths outside the session directory here as this makes + * archival/distribution impossible. + * + * This field is set to NULL by Jack when the event is delivered to the + * client. The client must set to allocated memory that is safe to + * free(). This memory will be freed by jack_session_event_free. + */ + char *command_line; + + /** + * Reply (set by client): Session flags. + */ + jack_session_flags_t flags; + + /** + * Future flags. Set to zero for now. + */ + uint32_t future; +}; + +typedef struct _jack_session_event jack_session_event_t; + +/** + * Prototype for the client supplied function that is called + * whenever a session notification is sent via jack_session_notify(). + * + * Ownership of the memory of @a event is passed to the application. + * It must be freed using jack_session_event_free when its not used anymore. + * + * The client must promptly call jack_session_reply for this event. + * + * @param event The event structure. + * @param arg Pointer to a client supplied structure. + */ +typedef void (*JackSessionCallback)(jack_session_event_t *event, + void *arg); + +/** + * Tell the JACK server to call @a session_callback when a session event + * is to be delivered. + * + * setting more than one session_callback per process is probably a design + * error. if you have a multiclient application its more sensible to create + * a jack_client with only a session callback set. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_set_session_callback (jack_client_t *client, + JackSessionCallback session_callback, + void *arg) JACK_WEAK_EXPORT; + +/** + * Reply to a session event. + * + * This can either be called directly from the callback, or later from a + * different thread. For example, it is possible to push the event through a + * queue and execute the save code from the GUI thread. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_session_reply (jack_client_t *client, + jack_session_event_t *event) JACK_WEAK_EXPORT; + + +/** + * free memory used by a jack_session_event_t + * this also frees the memory used by the command_line pointer. + * if its non NULL. + */ +void jack_session_event_free (jack_session_event_t *event) JACK_WEAK_EXPORT; + + +/** + * get the assigned uuid for client. + * safe to call from callback and all other threads. + * memory needs to be freed. + */ + +char *jack_client_get_uuid (jack_client_t *client) JACK_WEAK_EXPORT; + +/** + * @} + */ + +/** + * @defgroup JackSessionManagerAPI API for a session manager. + * + * @{ + */ + +typedef struct { + const char *uuid; + const char *client_name; + const char *command; + jack_session_flags_t flags; +} jack_session_command_t; + +/** + * Send an event to all clients listening for session callbacks. + * + * The returned strings of the clients are accumulated and returned as an array + * of jack_session_command_t. its terminated by ret[i].uuid == NULL target == + * NULL means send to all interested clients. otherwise a clientname + */ +jack_session_command_t *jack_session_notify ( + jack_client_t* client, + const char *target, + jack_session_event_type_t type, + const char *path) JACK_WEAK_EXPORT; + +/** + * Free the memory allocated by a session command. + */ +void jack_session_commands_free (jack_session_command_t *cmds) JACK_WEAK_EXPORT; + +/** + * Get the session ID for a client name. + * The session manager needs this to reassociate a client name to the session_id. + */ +char *jack_get_uuid_for_client_name (jack_client_t *client, + const char *client_name) JACK_WEAK_EXPORT; + +/** + * Get the client name for a session_id. + * + * In order to snapshot the graph connections, the session manager needs to map + * session_ids to client names. + */ +char *jack_get_client_name_by_uuid (jack_client_t *client, + const char *client_uuid ) JACK_WEAK_EXPORT; + +/** + * Reserve a client name and associate it with a UUID. + * + * When a client later calls jack_client_open() and specifies the UUID, jackd + * will assign the reserved name. This allows a session manager to know in + * advance under which client name its managed clients will appear. + * + * @return 0 on success, otherwise a non-zero error code + */ +int +jack_reserve_client_name (jack_client_t *client, + const char *name, + const char *uuid) JACK_WEAK_EXPORT; + +/** + * Find out whether a client has set up a session callback. + * + * @return 0 when the client has no session callback, 1 when it has one. + * -1 on error. + */ +int +jack_client_has_session_callback (jack_client_t *client, const char *client_name) JACK_WEAK_EXPORT; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/shm.h b/shm.h new file mode 100644 index 0000000..8103ce9 --- /dev/null +++ b/shm.h @@ -0,0 +1,110 @@ +#ifndef __jack_shm_h__ +#define __jack_shm_h__ + +#include +#include +#include + +#define MAX_SERVERS 8 /* maximum concurrent servers */ +#define MAX_SHM_ID 256 /* generally about 16 per server */ +#define JACK_SERVER_NAME_SIZE 256 /* maximum length of server name */ +#define JACK_SHM_MAGIC 0x4a41434b /* shm magic number: "JACK" */ +#define JACK_SHM_NULL_INDEX -1 /* NULL SHM index */ +#define JACK_SHM_REGISTRY_INDEX -2 /* pseudo SHM index for registry */ + + +/* On Mac OS X, SHM_NAME_MAX is the maximum length of a shared memory + * segment name (instead of NAME_MAX or PATH_MAX as defined by the + * standard). + */ +#ifdef USE_POSIX_SHM +#ifndef SHM_NAME_MAX +#define SHM_NAME_MAX NAME_MAX +#endif +typedef char shm_name_t[SHM_NAME_MAX]; +typedef shm_name_t jack_shm_id_t; +#else /* System V SHM */ +typedef int jack_shm_id_t; +#endif /* SHM type */ + +/* shared memory type */ +typedef enum { + shm_POSIX = 1, /* POSIX shared memory */ + shm_SYSV = 2 /* System V shared memory */ +} jack_shmtype_t; + +typedef int16_t jack_shm_registry_index_t; + +/** + * A structure holding information about shared memory allocated by + * JACK. this persists across invocations of JACK, and can be used by + * multiple JACK servers. It contains no pointers and is valid across + * address spaces. + * + * The registry consists of two parts: a header including an array of + * server names, followed by an array of segment registry entries. + */ +typedef struct _jack_shm_server { + pid_t pid; /* process ID */ + char name[JACK_SERVER_NAME_SIZE]; +} jack_shm_server_t; + +typedef struct _jack_shm_header { + uint32_t magic; /* magic number */ + uint16_t protocol; /* JACK protocol version */ + jack_shmtype_t type; /* shm type */ + jack_shmsize_t size; /* total registry segment size */ + jack_shmsize_t hdr_len; /* size of header */ + jack_shmsize_t entry_len; /* size of registry entry */ + jack_shm_server_t server[MAX_SERVERS]; /* current server array */ +} jack_shm_header_t; + +typedef struct _jack_shm_registry { + jack_shm_registry_index_t index; /* offset into the registry */ + pid_t allocator; /* PID that created shm segment */ + jack_shmsize_t size; /* for POSIX unattach */ + jack_shm_id_t id; /* API specific, see above */ +} jack_shm_registry_t; + +#define JACK_SHM_REGISTRY_SIZE (sizeof (jack_shm_header_t) \ + + sizeof (jack_shm_registry_t) * MAX_SHM_ID) + +/** + * a structure holding information about shared memory + * allocated by JACK. this version is valid only + * for a given address space. It contains a pointer + * indicating where the shared memory has been + * attached to the address space. + */ +typedef struct _jack_shm_info { + jack_shm_registry_index_t index; /* offset into the registry */ + void *attached_at; /* address where attached */ +} jack_shm_info_t; + +/* utility functions used only within JACK */ + +extern void jack_shm_copy_from_registry (jack_shm_info_t*, + jack_shm_registry_index_t); +extern void jack_shm_copy_to_registry (jack_shm_info_t*, + jack_shm_registry_index_t*); +extern void jack_release_shm_info (jack_shm_registry_index_t); + +static inline char* jack_shm_addr (jack_shm_info_t* si) { + return si->attached_at; +} + +/* here beginneth the API */ + +extern int jack_register_server (const char *server_name, int new_registry); +extern void jack_unregister_server (const char *server_name); + +extern int jack_initialize_shm (const char *server_name); +extern int jack_cleanup_shm (void); + +extern int jack_shmalloc (jack_shmsize_t size, jack_shm_info_t* result); +extern void jack_release_shm (jack_shm_info_t*); +extern void jack_destroy_shm (jack_shm_info_t*); +extern int jack_attach_shm (jack_shm_info_t*); +extern int jack_resize_shm (jack_shm_info_t*, jack_shmsize_t size); + +#endif /* __jack_shm_h__ */ diff --git a/start.h b/start.h new file mode 100644 index 0000000..00212e4 --- /dev/null +++ b/start.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2002 Fernando Lopez-Lezcano + + 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. + +*/ + +#define PIPE_READ_FD (3) +#define PIPE_WRITE_FD (4) diff --git a/statistics.h b/statistics.h new file mode 100644 index 0000000..c834662 --- /dev/null +++ b/statistics.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2004 Rui Nuno Capela, Lee Revell + * + * 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 __statistics_h__ +#define __statistics_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @return the maximum delay reported by the backend since + * startup or reset. When compared to the period size in usecs, this + * can be used to estimate the ideal period size for a given setup. + */ +float jack_get_max_delayed_usecs (jack_client_t *client); + +/** + * @return the delay in microseconds due to the most recent XRUN + * occurrence. This probably only makes sense when called from a @ref + * JackXRunCallback defined using jack_set_xrun_callback(). + */ +float jack_get_xrun_delayed_usecs (jack_client_t *client); + +/** + * Reset the maximum delay counter. This would be useful + * to estimate the effect that a change to the configuration of a running + * system (e.g. toggling kernel preemption) has on the delay + * experienced by JACK, without having to restart the JACK engine. + */ +void jack_reset_max_delayed_usecs (jack_client_t *client); + +#ifdef __cplusplus +} +#endif + +#endif /* __statistics_h__ */ diff --git a/systemtest.h b/systemtest.h new file mode 100644 index 0000000..27e0ae7 --- /dev/null +++ b/systemtest.h @@ -0,0 +1,97 @@ +#ifndef __jack_systemtest_h__ +#define __jack_systemtest_h__ + +/** + * GPL, yabbadabba + * + * Set of functions to gather system information for the jack setup wizard. + * + * @author Florian Faber, faber@faberman.de + * + * @version 0.1 (2009-01-15) [FF] + * - initial version + * + **/ + + +/** + * This function checks for the existence of known frequency scaling mechanisms + * in this system. + * + * @returns 0 if the system has no frequency scaling capabilities non-0 otherwise. + **/ +int system_has_frequencyscaling(); + + +/** + * This function determines wether the CPU has a variable clock speed if frequency + * scaling is available. + * + * @returns 0 if system doesn't use frequency scaling at the moment, non-0 otherwise + **/ +int system_uses_frequencyscaling(); + + +/*** + * Checks for a definition in /etc/security/limits.conf that looks + * as if it allows RT scheduling priority. + * + * @returns 1 if there appears to be such a line + **/ +int system_has_rtprio_limits_conf (); + +/** + * Checks for the existence of the 'audio' group on this system + * + * @returns 0 is there is no 'audio' group, non-0 otherwise + **/ +int system_has_audiogroup(); + + +/** + * Tests wether the owner of this process is in the 'audio' group. + * + * @returns 0 if the owner of this process is not in the audio group, non-0 otherwise + **/ +int system_user_in_audiogroup(); + + +/** + * Determines wether the owner of this process can enable rt priority. + * + * @returns 0 if this process can not be switched to rt prio, non-0 otherwise + **/ +int system_user_can_rtprio(); + + +long long unsigned int system_memlock_amount(); + + +/** + * Checks wether the memlock limit is unlimited + * + * @returns 0 if the memlock limit is limited, non-0 otherwise + **/ +int system_memlock_is_unlimited(); + + +long long unsigned int system_available_physical_mem(); + + +/** + * Gets the version of the currently running kernel + * + * @returns String with the full version of the kernel + **/ +char* system_kernel_version(); + + +/** + * Returns the username. The caller is in charge of disposal of + * the returned name. + * + * @returns Pointer to a username or NULL + **/ +char* system_get_username(); + +#endif /* __jack_systemtest_h__ */ diff --git a/thread.h b/thread.h new file mode 100644 index 0000000..1a33202 --- /dev/null +++ b/thread.h @@ -0,0 +1,135 @@ +/* + Copyright (C) 2004 Paul Davis + + 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 __jack_thread_h__ +#define __jack_thread_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/* use 512KB stack per thread - the default is way too high to be feasible + * with mlockall() on many systems */ +#define THREAD_STACK 524288 + +/** @file thread.h + * + * Library functions to standardize thread creation for JACK and its + * clients. These interfaces hide some system variations in the + * handling of realtime scheduling and associated privileges. + */ + +/** + * @defgroup ClientThreads Creating and managing client threads + * @{ + */ + +/** + * @returns if JACK is running with realtime scheduling, this returns + * the priority that any JACK-created client threads will run at. + * Otherwise returns -1. + */ + +int jack_client_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * @returns if JACK is running with realtime scheduling, this returns + * the maximum priority that a JACK client thread should use if the thread + * is subject to realtime scheduling. Otherwise returns -1. + */ + +int jack_client_max_real_time_priority (jack_client_t*) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Attempt to enable realtime scheduling for a thread. On some + * systems that may require special privileges. + * + * @param thread POSIX thread ID. + * @param priority requested thread priority. + * + * @returns 0, if successful; EPERM, if the calling process lacks + * required realtime privileges; otherwise some other error number. + */ +int jack_acquire_real_time_scheduling (jack_native_thread_t thread, int priority) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Create a thread for JACK or one of its clients. The thread is + * created executing @a start_routine with @a arg as its sole + * argument. + * + * @param client the JACK client for whom the thread is being created. May be + * NULL if the client is being created within the JACK server. + * @param thread place to return POSIX thread ID. + * @param priority thread priority, if realtime. + * @param realtime true for the thread to use realtime scheduling. On + * some systems that may require special privileges. + * @param start_routine function the thread calls when it starts. + * @param arg parameter passed to the @a start_routine. + * + * @returns 0, if successful; otherwise some error number. + */ +int jack_client_create_thread (jack_client_t* client, + jack_native_thread_t *thread, + int priority, + int realtime, /* boolean */ + void *(*start_routine)(void*), + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Drop realtime scheduling for a thread. + * + * @param thread POSIX thread ID. + * + * @returns 0, if successful; otherwise an error number. + */ +int jack_drop_real_time_scheduling (jack_native_thread_t thread) JACK_OPTIONAL_WEAK_EXPORT; + +typedef int (*jack_thread_creator_t)(jack_native_thread_t*, + const pthread_attr_t*, + void* (*function)(void*), + void* arg) JACK_OPTIONAL_WEAK_EXPORT; +/** + * This function can be used in very very specialized cases + * where it is necessary that client threads created by JACK + * are created by something other than pthread_create(). After + * it is used, any threads that JACK needs for the client will + * will be created by calling the function passed to this + * function. + * + * No normal application/client should consider calling this. + * The specific case for which it was created involves running + * win32/x86 plugins under Wine on Linux, where it is necessary + * that all threads that might call win32 functions are known + * to Wine. + * + * @param creator a function that creates a new thread + * + */ +void jack_set_thread_creator (jack_thread_creator_t creator) JACK_OPTIONAL_WEAK_EXPORT; + +/* @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_thread_h__ */ diff --git a/timestamps.h b/timestamps.h new file mode 100644 index 0000000..cbef55f --- /dev/null +++ b/timestamps.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002 Paul Davis + + 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 __jack_timestamps_h__ +#define __jack_timestamps_h__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void jack_init_timestamps (unsigned long howmany); +void jack_timestamp (const char *what); +void jack_dump_timestamps (FILE *out); +void jack_reset_timestamps (); + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_timestamps_h__ */ + + diff --git a/transport.h b/transport.h new file mode 100644 index 0000000..0f57a8c --- /dev/null +++ b/transport.h @@ -0,0 +1,544 @@ +/* + Copyright (C) 2002 Paul Davis + Copyright (C) 2003 Jack O'Quin + + 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 __jack_transport_h__ +#define __jack_transport_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#ifndef POST_PACKED_STRUCTURE +#ifdef __GNUC__ +/* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. +*/ +#define POST_PACKED_STRUCTURE __attribute__((__packed__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + + +/** + * Transport states. + */ +typedef enum { + + /* the order matters for binary compatibility */ + JackTransportStopped = 0, /**< Transport halted */ + JackTransportRolling = 1, /**< Transport playing */ + JackTransportLooping = 2, /**< For OLD_TRANSPORT, now ignored */ + JackTransportStarting = 3 /**< Waiting for sync ready */ + +} jack_transport_state_t; + +typedef uint64_t jack_unique_t; /**< Unique ID (opaque) */ + +/** + * Optional struct jack_position_t fields. + */ +typedef enum { + + JackPositionBBT = 0x10, /**< Bar, Beat, Tick */ + JackPositionTimecode = 0x20, /**< External timecode */ + JackBBTFrameOffset = 0x40, /**< Frame offset of BBT information */ + JackAudioVideoRatio = 0x80, /**< audio frames per video frame */ + JackVideoFrameOffset = 0x100 /**< frame offset of first video frame */ +} jack_position_bits_t; + +/** all valid position bits */ +#define JACK_POSITION_MASK (JackPositionBBT|JackPositionTimecode|JackBBTFrameOffset|JackAudioVideoRatio|JackVideoFrameOffset) +#define EXTENDED_TIME_INFO + +/** + * Struct for transport position information. + */ +typedef struct { + + /*@{*/ + /** @name Server-set fields + * these cannot be set from clients; the server sets them */ + jack_unique_t unique_1; /**< unique ID */ + jack_time_t usecs; /**< microsecond timestamp that is guaranteed to be + monotonic, but not neccessarily + linear. + + The absolute value is + implementation-dependent (i.e. it + could be wall-clock, time since + jack started, uptime, etc). */ + jack_nframes_t frame_rate; /**< current frame rate, in frames per second */ + /*}@*/ + + /*@{*/ + /** @name Mandatory fields + */ + jack_nframes_t frame; /**< frame number, always present/required. + + This is the frame number on the + transport timeline, which is not + the same as what @ref + jack_frame_time returns. */ + jack_position_bits_t valid; /**< which other fields are valid, as a + bitmask constructed from values in + \ref jack_position_bits_t */ + /*}@*/ + + /*@{*/ + /** @name JackPositionBBT fields + * Bar:Beat.Tick-related information. + * + * Applications that support + * JackPositionBBT are encouraged to also fill the JackBBTFrameOffset + */ + int32_t bar; /**< current bar + + Should be >0: the first bar is + bar '1'. */ + int32_t beat; /**< current beat-within-bar + + Should be >0 and <=beats_per_bar: + the first beat is beat '1'. + */ + int32_t tick; /**< current tick-within-beat + + Should be >0 and <=ticks_per_beat: + the first tick is tick '0'. */ + double bar_start_tick; /**< number of ticks that have elapsed + between frame 0 and the first beat + of the current measure. */ + + float beats_per_bar; /**< time signature "numerator" */ + float beat_type; /**< time signature "denominator" */ + double ticks_per_beat; /**< number of ticks within a bar. + + Usually a moderately large integer + with many denominators, such as + 1920.0 */ + double beats_per_minute; /**< BPM, quantized to block size. This + means when the tempo is not constant + within this block, the BPM value should + adapted to compensate for this. This + is different from most fields in this + struct, which specify the value at + the beginning of the block rather + than an average.*/ + /*}@*/ + + /*@{*/ + /** @name JackPositionTimecode fields + * EXPERIMENTAL: could change */ + double frame_time; /**< current time in seconds */ + double next_time; /**< next sequential frame_time + (unless repositioned) */ + /*}@*/ + + /*@{*/ + /* JackBBTFrameOffset fields */ + jack_nframes_t bbt_offset; /**< frame offset for the BBT fields + (the given bar, beat, and tick + values actually refer to a time + frame_offset frames before the + start of the cycle), should + be assumed to be 0 if + JackBBTFrameOffset is not + set. If JackBBTFrameOffset is + set and this value is zero, the BBT + time refers to the first frame of this + cycle. If the value is positive, + the BBT time refers to a frame that + many frames before the start of the + cycle. */ + /*}@*/ + + /*@{*/ + /* JACK video positional data + * EXPERIMENTAL: could change */ + float audio_frames_per_video_frame; /**< number of audio frames + per video frame. Should be assumed + zero if JackAudioVideoRatio is not + set. If JackAudioVideoRatio is set + and the value is zero, no video + data exists within the JACK graph */ + + jack_nframes_t video_offset; /**< audio frame at which the first video + frame in this cycle occurs. Should + be assumed to be 0 if JackVideoFrameOffset + is not set. If JackVideoFrameOffset is + set, but the value is zero, there is + no video frame within this cycle. */ + /*}@*/ + + /*@{*/ + /** @name Other fields */ + /* For binary compatibility, new fields should be allocated from + * this padding area with new valid bits controlling access, so + * the existing structure size and offsets are preserved. */ + int32_t padding[7]; + /*}@*/ + + /* When (unique_1 == unique_2) the contents are consistent. */ + jack_unique_t unique_2; /**< unique ID */ + +} POST_PACKED_STRUCTURE jack_position_t; + +/** + * @defgroup TransportControl Transport and Timebase control + * @{ + */ + +/** + * Called by the timebase master to release itself from that + * responsibility. + * + * If the timebase master releases the timebase or leaves the JACK + * graph for any reason, the JACK engine takes over at the start of + * the next process cycle. The transport state does not change. If + * rolling, it continues to play, with frame numbers as the only + * available position information. + * + * @see jack_set_timebase_callback + * + * @param client the JACK client structure. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_release_timebase (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Prototype for the @a sync_callback defined by @ref slowsyncclients + * "slow-sync clients". When the client is active, this callback is + * invoked just before process() in the same thread. This occurs once + * after registration, then subsequently whenever some client requests + * a new position, or the transport enters the ::JackTransportStarting + * state. This realtime function must not wait. + * + * The transport @a state will be: + * + * - ::JackTransportStopped when a new position is requested; + * - ::JackTransportStarting when the transport is waiting to start; + * - ::JackTransportRolling when the timeout has expired, and the + * position is now a moving target. + * + * @param state current transport state. + * @param pos new transport position. + * @param arg the argument supplied by jack_set_sync_callback(). + * + * @return TRUE (non-zero) when ready to roll. + */ +typedef int (*JackSyncCallback)(jack_transport_state_t state, + jack_position_t *pos, + void *arg); + +/** + * Register (or unregister) as a @ref slowsyncclients "slow-sync client", that cannot + * respond immediately to transport position changes. + * + * The @a sync_callback will be invoked at the first available + * opportunity after its registration is complete. If the client is + * currently active this will be the following process cycle, + * otherwise it will be the first cycle after calling jack_activate(). + * After that, it runs according to the ::JackSyncCallback rules. + * Clients that don't set a @a sync_callback are assumed to be ready + * immediately any time the transport wants to start. + * + * @param client the JACK client structure. + * @param sync_callback is a realtime function that returns TRUE when + * the client is ready. Setting @a sync_callback to NULL declares that + * this client no longer requires slow-sync processing. + * @param arg an argument for the @a sync_callback function. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_sync_callback (jack_client_t *client, + JackSyncCallback sync_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Set the timeout value for @ref slowsyncclients "slow-sync clients". + * + * This timeout prevents unresponsive slow-sync clients from + * completely halting the transport mechanism. The default is two + * seconds. When the timeout expires, the transport starts rolling, + * even if some slow-sync clients are still unready. The @a + * sync_callbacks of these clients continue being invoked, giving them + * a chance to catch up. + * + * @see jack_set_sync_callback + * + * @param client the JACK client structure. + * @param timeout is delay (in microseconds) before the timeout expires. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_set_sync_timeout (jack_client_t *client, + jack_time_t timeout) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Prototype for the @a timebase_callback used to provide extended + * position information. Its output affects all of the following + * process cycle. This realtime function must not wait. + * + * This function is called immediately after process() in the same + * thread whenever the transport is rolling, or when any client has + * requested a new position in the previous cycle. The first cycle + * after jack_set_timebase_callback() is also treated as a new + * position, or the first cycle after jack_activate() if the client + * had been inactive. + * + * The timebase master may not use its @a pos argument to set @a + * pos->frame. To change position, use jack_transport_reposition() or + * jack_transport_locate(). These functions are realtime-safe, the @a + * timebase_callback can call them directly. + * + * @param state current transport state. + * @param nframes number of frames in current period. + * @param pos address of the position structure for the next cycle; @a + * pos->frame will be its frame number. If @a new_pos is FALSE, this + * structure contains extended position information from the current + * cycle. If TRUE, it contains whatever was set by the requester. + * The @a timebase_callback's task is to update the extended + * information here. + * @param new_pos TRUE (non-zero) for a newly requested @a pos, or for + * the first cycle after the @a timebase_callback is defined. + * @param arg the argument supplied by jack_set_timebase_callback(). + */ +typedef void (*JackTimebaseCallback)(jack_transport_state_t state, + jack_nframes_t nframes, + jack_position_t *pos, + int new_pos, + void *arg); + +/** + * Register as timebase master for the JACK subsystem. + * + * The timebase master registers a callback that updates extended + * position information such as beats or timecode whenever necessary. + * Without this extended information, there is no need for this + * function. + * + * There is never more than one master at a time. When a new client + * takes over, the former @a timebase_callback is no longer called. + * Taking over the timebase may be done conditionally, so it fails if + * there was a master already. + * + * The method may be called whether the client has been activated or not. + * + * @param client the JACK client structure. + * @param conditional non-zero for a conditional request. + * @param timebase_callback is a realtime function that returns + * position information. + * @param arg an argument for the @a timebase_callback function. + * + * @return + * - 0 on success; + * - EBUSY if a conditional request fails because there was already a + * timebase master; + * - other non-zero error code. + */ +int jack_set_timebase_callback (jack_client_t *client, + int conditional, + JackTimebaseCallback timebase_callback, + void *arg) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Reposition the transport to a new frame number. + * + * May be called at any time by any client. The new position takes + * effect in two process cycles. If there are @ref slowsyncclients + * "slow-sync clients" and the transport is already rolling, it will + * enter the ::JackTransportStarting state and begin invoking their @a + * sync_callbacks until ready. This function is realtime-safe. + * + * @see jack_transport_reposition, jack_set_sync_callback + * + * @param client the JACK client structure. + * @param frame frame number of new transport position. + * + * @return 0 if valid request, non-zero otherwise. + */ +int jack_transport_locate (jack_client_t *client, + jack_nframes_t frame) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Query the current transport state and position. + * + * This function is realtime-safe, and can be called from any thread. + * If called from the process thread, @a pos corresponds to the first + * frame of the current cycle and the state returned is valid for the + * entire cycle. + * + * @param client the JACK client structure. + * @param pos pointer to structure for returning current transport + * position; @a pos->valid will show which fields contain valid data. + * If @a pos is NULL, do not return position information. + * + * @return Current transport state. + */ +jack_transport_state_t jack_transport_query (const jack_client_t *client, + jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Return an estimate of the current transport frame, + * including any time elapsed since the last transport + * positional update. + * + * @param client the JACK client structure + */ +jack_nframes_t jack_get_current_transport_frame (const jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Request a new transport position. + * + * May be called at any time by any client. The new position takes + * effect in two process cycles. If there are @ref slowsyncclients + * "slow-sync clients" and the transport is already rolling, it will + * enter the ::JackTransportStarting state and begin invoking their @a + * sync_callbacks until ready. This function is realtime-safe. + * + * @see jack_transport_locate, jack_set_sync_callback + * + * @param client the JACK client structure. + * @param pos requested new transport position. Fill pos->valid to specify + * which fields should be taken into account. If you mark a set of fields + * as valid, you are expected to fill them all. + * + * @return 0 if valid request, EINVAL if position structure rejected. + */ +int jack_transport_reposition (jack_client_t *client, + const jack_position_t *pos) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Start the JACK transport rolling. + * + * Any client can make this request at any time. It takes effect no + * sooner than the next process cycle, perhaps later if there are + * @ref slowsyncclients "slow-sync clients". This function is realtime-safe. + * + * @see jack_set_sync_callback + * + * @param client the JACK client structure. + */ +void jack_transport_start (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/** + * Stop the JACK transport. + * + * Any client can make this request at any time. It takes effect on + * the next process cycle. This function is realtime-safe. + * + * @param client the JACK client structure. + */ +void jack_transport_stop (jack_client_t *client) JACK_OPTIONAL_WEAK_EXPORT; + +/*@}*/ + +/********************************************************************* + * The following interfaces are DEPRECATED. They are only provided + * for compatibility with the earlier JACK transport implementation. + *********************************************************************/ + +/** + * Optional struct jack_transport_info_t fields. + * + * @see jack_position_bits_t. + */ +typedef enum { + + JackTransportState = 0x1, /**< Transport state */ + JackTransportPosition = 0x2, /**< Frame number */ + JackTransportLoop = 0x4, /**< Loop boundaries (ignored) */ + JackTransportSMPTE = 0x8, /**< SMPTE (ignored) */ + JackTransportBBT = 0x10 /**< Bar, Beat, Tick */ + +} jack_transport_bits_t; + +/** + * Deprecated struct for transport position information. + * + * @deprecated This is for compatibility with the earlier transport + * interface. Use the jack_position_t struct, instead. + */ +typedef struct { + + /* these two cannot be set from clients: the server sets them */ + + jack_nframes_t frame_rate; /**< current frame rate (per second) */ + jack_time_t usecs; /**< monotonic, free-rolling */ + + jack_transport_bits_t valid; /**< which fields are legal to read */ + jack_transport_state_t transport_state; + jack_nframes_t frame; + jack_nframes_t loop_start; + jack_nframes_t loop_end; + + long smpte_offset; /**< SMPTE offset (from frame 0) */ + float smpte_frame_rate; /**< 29.97, 30, 24 etc. */ + + int bar; + int beat; + int tick; + double bar_start_tick; + + float beats_per_bar; + float beat_type; + double ticks_per_beat; + double beats_per_minute; + +} jack_transport_info_t; + +/** + * Gets the current transport info structure (deprecated). + * + * @param client the JACK client structure. + * @param tinfo current transport info structure. The "valid" field + * describes which fields contain valid data. + * + * @deprecated This is for compatibility with the earlier transport + * interface. Use jack_transport_query(), instead. + * + * @pre Must be called from the process thread. + */ +void jack_get_transport_info (jack_client_t *client, + jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +/** + * Set the transport info structure (deprecated). + * + * @deprecated This function still exists for compatibility with the + * earlier transport interface, but it does nothing. Instead, define + * a ::JackTimebaseCallback. + */ +void jack_set_transport_info (jack_client_t *client, + jack_transport_info_t *tinfo) JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT; + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_transport_h__ */ diff --git a/types.h b/types.h new file mode 100644 index 0000000..d2a20b1 --- /dev/null +++ b/types.h @@ -0,0 +1,506 @@ +/* + Copyright (C) 2001 Paul Davis + Copyright (C) 2004 Jack O'Quin + + 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 __jack_types_h__ +#define __jack_types_h__ + +#include +#include + +typedef int32_t jack_shmsize_t; + +/** + * Type used to represent sample frame counts. + */ +typedef uint32_t jack_nframes_t; + +/** + * Maximum value that can be stored in jack_nframes_t + */ +#define JACK_MAX_FRAMES (4294967295U) /* This should be UINT32_MAX, but + C++ has a problem with that. */ + +/** + * Type used to represent the value of free running + * monotonic clock with units of microseconds. + */ +typedef uint64_t jack_time_t; + +/** + * Maximum size of @a load_init string passed to an internal client + * jack_initialize() function via jack_internal_client_load(). + */ +#define JACK_LOAD_INIT_LIMIT 1024 + +/** + * jack_intclient_t is an opaque type representing a loaded internal + * client. You may only access it using the API provided in @ref + * intclient.h "". + */ +typedef uint64_t jack_intclient_t; + +/** + * jack_port_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_port jack_port_t; + +/** + * jack_client_t is an opaque type. You may only access it using the + * API provided. + */ +typedef struct _jack_client jack_client_t; + +/** + * Ports have unique ids. A port registration callback is the only + * place you ever need to know their value. + */ +typedef uint32_t jack_port_id_t; + +/** + * to make jack API independent of different thread implementations, + * we define jack_native_thread_t to pthread_t here. + * (all platforms that jack1 runs on, have pthread) + */ +typedef pthread_t jack_native_thread_t; + +/** + * @ref jack_options_t bits + */ +enum JackOptions { + + /** + * Null value to use when no option bits are needed. + */ + JackNullOption = 0x00, + + /** + * Do not automatically start the JACK server when it is not + * already running. This option is always selected if + * \$JACK_NO_START_SERVER is defined in the calling process + * environment. + */ + JackNoStartServer = 0x01, + + /** + * Use the exact client name requested. Otherwise, JACK + * automatically generates a unique one, if needed. + */ + JackUseExactName = 0x02, + + /** + * Open with optional (char *) server_name parameter. + */ + JackServerName = 0x04, + + /** + * Load internal client from optional (char *) + * load_name. Otherwise use the @a client_name. + */ + JackLoadName = 0x08, + + /** + * Pass optional (char *) load_init string to the + * jack_initialize() entry point of an internal client. + */ + JackLoadInit = 0x10, + + /** + * pass a SessionID Token this allows the sessionmanager to identify the client again. + */ + JackSessionID = 0x20 +}; + +/** Valid options for opening an external client. */ +#define JackOpenOptions (JackSessionID|JackServerName|JackNoStartServer|JackUseExactName) + +/** Valid options for loading an internal client. */ +#define JackLoadOptions (JackLoadInit|JackLoadName|JackUseExactName) + +/** + * Options for several JACK operations, formed by OR-ing together the + * relevant @ref JackOptions bits. + */ +typedef enum JackOptions jack_options_t; + +/** + * @ref jack_status_t bits + */ +enum JackStatus { + + /** + * Overall operation failed. + */ + JackFailure = 0x01, + + /** + * The operation contained an invalid or unsupported option. + */ + JackInvalidOption = 0x02, + + /** + * The desired client name was not unique. With the @ref + * JackUseExactName option this situation is fatal. Otherwise, + * the name was modified by appending a dash and a two-digit + * number in the range "-01" to "-99". The + * jack_get_client_name() function will return the exact string + * that was used. If the specified @a client_name plus these + * extra characters would be too long, the open fails instead. + */ + JackNameNotUnique = 0x04, + + /** + * The JACK server was started as a result of this operation. + * Otherwise, it was running already. In either case the caller + * is now connected to jackd, so there is no race condition. + * When the server shuts down, the client will find out. + */ + JackServerStarted = 0x08, + + /** + * Unable to connect to the JACK server. + */ + JackServerFailed = 0x10, + + /** + * Communication error with the JACK server. + */ + JackServerError = 0x20, + + /** + * Requested client does not exist. + */ + JackNoSuchClient = 0x40, + + /** + * Unable to load internal client + */ + JackLoadFailure = 0x80, + + /** + * Unable to initialize client + */ + JackInitFailure = 0x100, + + /** + * Unable to access shared memory + */ + JackShmFailure = 0x200, + + /** + * Client's protocol version does not match + */ + JackVersionError = 0x400, + + /* + * BackendError + */ + JackBackendError = 0x800, + + /* + * Client is being shutdown against its will + */ + JackClientZombie = 0x1000 +}; + +/** + * Status word returned from several JACK operations, formed by + * OR-ing together the relevant @ref JackStatus bits. + */ +typedef enum JackStatus jack_status_t; + +/** + * @ref jack_latency_callback_mode_t + */ +enum JackLatencyCallbackMode { + + /** + * Latency Callback for Capture Latency. + * Input Ports have their latency value setup. + * In the Callback the client needs to set the latency of the output ports + */ + JackCaptureLatency, + + /** + * Latency Callback for Playback Latency. + * Output Ports have their latency value setup. + * In the Callback the client needs to set the latency of the input ports + */ + JackPlaybackLatency + +}; + +/** + * Type of Latency Callback (Capture or Playback) + */ +typedef enum JackLatencyCallbackMode jack_latency_callback_mode_t; + +/** + * Prototype for the client supplied function that is called + * by the engine when port latencies need to be recalculated + * + * @param mode playback or capture latency + * @param arg pointer to a client supplied data + * + * @return zero on success, non-zero on error + */ +typedef void (*JackLatencyCallback)(jack_latency_callback_mode_t mode, void *arg); + +/** + * the new latency API operates on Ranges. + */ +struct _jack_latency_range +{ + /** + * minimum latency + */ + jack_nframes_t min; + /** + * maximum latency + */ + jack_nframes_t max; +}; + +typedef struct _jack_latency_range jack_latency_range_t; + +/** + * 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 data + * + * @return zero on success, non-zero on error + */ +typedef int (*JackProcessCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for the client supplied function that is called + * once after the creation of the thread in which other + * callbacks will be made. Special thread characteristics + * can be set from this callback, for example. This is a + * highly specialized callback and most clients will not + * and should not use it. + * + * @param arg pointer to a client supplied structure + * + * @return void + */ +typedef void (*JackThreadInitCallback)(void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever the processing graph is reordered. + * + * @param arg pointer to a client supplied data + * + * @return zero on success, non-zero on error + */ +typedef int (*JackGraphOrderCallback)(void *arg); + +/** + * Prototype for the client-supplied function that is called whenever + * an xrun has occured. + * + * @see jack_get_xrun_delayed_usecs() + * + * @param arg pointer to a client supplied data + * + * @return zero on success, non-zero on error + */ +typedef int (*JackXRunCallback)(void *arg); + +/** + * Prototype for the @a bufsize_callback that is invoked whenever the + * JACK engine buffer size changes. Although this function is called + * in the JACK process thread, the normal process cycle is suspended + * during its operation, causing a gap in the audio flow. So, the @a + * bufsize_callback can allocate storage, touch memory not previously + * referenced, and perform other operations that are not realtime + * safe. + * + * @param nframes buffer size + * @param arg pointer supplied by jack_set_buffer_size_callback(). + * + * @return zero on success, non-zero on error + */ +typedef int (*JackBufferSizeCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for the client supplied function that is called + * when the engine sample rate changes. + * + * @param nframes new engine sample rate + * @param arg pointer to a client supplied data + * + * @return zero on success, non-zero on error + */ +typedef int (*JackSampleRateCallback)(jack_nframes_t nframes, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever a port is registered or unregistered. + * + * @param port the ID of the port + * @param arg pointer to a client supplied data + * @param register non-zero if the port is being registered, + * zero if the port is being unregistered + */ +typedef void (*JackPortRegistrationCallback)(jack_port_id_t port, int register, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever a client is registered or unregistered. + * + * @param name a null-terminated string containing the client name + * @param register non-zero if the client is being registered, + * zero if the client is being unregistered + * @param arg pointer to a client supplied data + */ +typedef void (*JackClientRegistrationCallback)(const char* name, int register, void *arg); + +/** + * Prototype for the client supplied function that is called + * whenever a client is registered or unregistered. + * + * @param a one of two ports connected or disconnected + * @param b one of two ports connected or disconnected + * @param connect non-zero if ports were connected + * zero if ports were disconnected + * @param arg pointer to a client supplied data + */ +typedef void (*JackPortConnectCallback)(jack_port_id_t a, jack_port_id_t b, int connect, void* arg); + +/** + * Prototype for the client supplied function that is called + * whenever jackd starts or stops freewheeling. + * + * @param starting non-zero if we start starting to freewheel, zero otherwise + * @param arg pointer to a client supplied structure + */ +typedef void (*JackFreewheelCallback)(int starting, void *arg); + +typedef void *(*JackThreadCallback)(void* arg); + +/** + * 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 + */ +typedef void (*JackShutdownCallback)(void *arg); + +/** + * 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 code a shutdown code + * @param reason a string describing the shutdown reason (backend failure, server crash... etc...) + * @param arg pointer to a client supplied structure + */ +typedef void (*JackInfoShutdownCallback)(jack_status_t code, const char* reason, void *arg); + +/** + * Used for the type argument of jack_port_register() for default + * audio and midi ports. + */ +#define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" +#define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" + +/** + * For convenience, use this typedef if you want to be able to change + * between float and double. You may want to typedef sample_t to + * jack_default_audio_sample_t in your application. + */ +typedef float jack_default_audio_sample_t; + +/** + * A port has a set of flags that are formed by OR-ing together the + * desired values from the list below. The flags "JackPortIsInput" and + * "JackPortIsOutput" are mutually exclusive and it is an error to use + * them both. + */ +enum JackPortFlags { + + /** + * if JackPortIsInput is set, then the port can receive + * data. + */ + JackPortIsInput = 0x1, + + /** + * if JackPortIsOutput is set, then data can be read from + * the port. + */ + JackPortIsOutput = 0x2, + + /** + * if JackPortIsPhysical is set, then the port corresponds + * to some kind of physical I/O connector. + */ + JackPortIsPhysical = 0x4, + + /** + * if JackPortCanMonitor is set, then a call to + * jack_port_request_monitor() makes sense. + * + * Precisely what this means is dependent on the client. A typical + * result of it being called with TRUE as the second argument is + * that data that would be available from an output port (with + * JackPortIsPhysical set) is sent to a physical output connector + * as well, so that it can be heard/seen/whatever. + * + * Clients that do not control physical interfaces + * should never create ports with this bit set. + */ + JackPortCanMonitor = 0x8, + + /** + * JackPortIsTerminal means: + * + * for an input port: the data received by the port + * will not be passed on or made + * available at any other port + * + * for an output port: the data available at the port + * does not originate from any other port + * + * Audio synthesizers, I/O hardware interface clients, HDR + * systems are examples of clients that would set this flag for + * their ports. + */ + JackPortIsTerminal = 0x10 +}; + + +#endif /* __jack_types_h__ */ diff --git a/unlock.h b/unlock.h new file mode 100644 index 0000000..3979efb --- /dev/null +++ b/unlock.h @@ -0,0 +1,26 @@ +/* -*- mode: c; c-file-style: "bsd"; -*- */ +/* + Copyright (C) 2001-2003 Paul Davis + + 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 __jack_mlock_h__ +#define __jack_mlock_h__ + +extern void cleanup_mlock (void); + +#endif /* __jack_mlock_h__ */ diff --git a/varargs.h b/varargs.h new file mode 100644 index 0000000..ae9e58a --- /dev/null +++ b/varargs.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004 Jack O'Quin + * + * 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 __jack_varargs_h__ +#define __jack_varargs_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* variable argument structure */ +typedef struct { + char *server_name; /* server name */ + char *load_name; /* load module name */ + char *load_init; /* initialization string */ + char *sess_uuid; +} jack_varargs_t; + +static inline void +jack_varargs_init (jack_varargs_t *va) +{ + memset (va, 0, sizeof(jack_varargs_t)); + va->server_name = jack_default_server_name (); +} + +static inline void +jack_varargs_parse (jack_options_t options, va_list ap, jack_varargs_t *va) +{ + /* initialize default settings */ + jack_varargs_init (va); + + if ((options & JackServerName)) { + char *sn = va_arg(ap, char *); + if (sn) + va->server_name = sn; + } + if ((options & JackLoadName)) + va->load_name = va_arg(ap, char *); + if ((options & JackLoadInit)) + va->load_init = va_arg(ap, char *); + if ((options & JackSessionID)) + va->sess_uuid = va_arg(ap, char *); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __jack_varargs_h__ */ diff --git a/version.h.in b/version.h.in new file mode 100644 index 0000000..d262665 --- /dev/null +++ b/version.h.in @@ -0,0 +1,20 @@ +/* + Copyright (C) 2003 Paul Davis + + @configure_input@ + + 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. +*/ +#define jack_protocol_version @JACK_PROTOCOL_VERSION@ diff --git a/weakjack.h b/weakjack.h new file mode 100644 index 0000000..cd68b4d --- /dev/null +++ b/weakjack.h @@ -0,0 +1,125 @@ +/* + Copyright (C) 2010 Paul Davis + + 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 __weakjack_h__ +#define __weakjack_h__ + +/** + * @defgroup WeakLinkage managing support for newer/older versions of JACK + * @{ One challenge faced by developers is that of taking + * advantage of new features introduced in new versions + * of [ JACK ] while still supporting older versions of + * the system. Normally, if an application uses a new + * feature in a library/API, it is unable to run on + * earlier versions of the library/API that do not + * support that feature. Such applications would either + * fail to launch or crash when an attempt to use the + * feature was made. This problem cane be solved using + * weakly-linked symbols. + * + * When a symbol in a framework is defined as weakly + * linked, the symbol does not have to be present at + * runtime for a process to continue running. The static + * linker identifies a weakly linked symbol as such in + * any code module that references the symbol. The + * dynamic linker uses this same information at runtime + * to determine whether a process can continue + * running. If a weakly linked symbol is not present in + * the framework, the code module can continue to run as + * long as it does not reference the symbol. However, if + * the symbol is present, the code can use it normally. + * + * (adapted from: http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html) + * + * A concrete example will help. Suppose that someone uses a version + * of a JACK client we'll call "Jill". Jill was linked against a version + * of JACK that contains a newer part of the API (say, jack_set_latency_callback()) + * and would like to use it if it is available. + * + * When Jill is run on a system that has a suitably "new" version of + * JACK, this function will be available entirely normally. But if Jill + * is run on a system with an old version of JACK, the function isn't + * available. + * + * With normal symbol linkage, this would create a startup error whenever + * someone tries to run Jill with the "old" version of JACK. However, functions + * added to JACK after version 0.116.2 are all declared to have "weak" linkage + * which means that their abscence doesn't cause an error during program + * startup. Instead, Jill can test whether or not the symbol jack_set_latency_callback + * is null or not. If its null, it means that the JACK installed on this machine + * is too old to support this function. If its not null, then Jill can use it + * just like any other function in the API. For example: + * + * \code + * if (jack_set_latency_callback) { + * jack_set_latency_callback (jill_client, jill_latency_callback, arg); + * } + * \endcode + * + * However, there are clients that may want to use this approach to parts of the + * the JACK API that predate 0.116.2. For example, they might want to see if even + * really old basic parts of the API like jack_client_open() exist at runtime. + * + * Such clients should include before any other JACK header. + * This will make the \b entire JACK API be subject to weak linkage, so that any + * and all functions can be checked for existence at runtime. It is important + * to understand that very few clients need to do this - if you use this + * feature you should have a clear reason to do so. + * + * + */ + +#ifdef __APPLE__ +#define WEAK_ATTRIBUTE weak_import +#else +#define WEAK_ATTRIBUTE __weak__ +#endif + +#ifndef JACK_OPTIONAL_WEAK_EXPORT +/* JACK_OPTIONAL_WEAK_EXPORT needs to be a macro which + expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of + the symbol it used with. For this to work fully may + require linker arguments for the client as well. +*/ +#ifdef __GNUC__ +#define JACK_OPTIONAL_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +/* JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT needs to be a macro + which expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of the + symbol it is used with AND optionally to mark the symbol + as deprecated. For this to work fully may require + linker arguments for the client as well. +*/ +#ifdef __GNUC__ +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((WEAK_ATTRIBUTE,__deprecated__)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +/*@}*/ + +#endif /* weakjack */ diff --git a/weakmacros.h b/weakmacros.h new file mode 100644 index 0000000..1fe34e2 --- /dev/null +++ b/weakmacros.h @@ -0,0 +1,67 @@ +/* + Copyright (C) 2010 Paul Davis + + 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 __weakmacros_h__ +#define __weakmacros_h__ + +/************************************************************* + * NOTE: JACK_WEAK_EXPORT ***MUST*** be used on every function + * added to the JACK API after the 0.116.2 release. + * + * Functions that predate this release are marked with + * JACK_WEAK_OPTIONAL_EXPORT which can be defined at compile + * time in a variety of ways. The default definition is empty, + * so that these symbols get normal linkage. If you wish to + * use all JACK symbols with weak linkage, include + * before jack.h. + *************************************************************/ + +#ifdef __APPLE__ +#define WEAK_ATTRIBUTE weak_import +#else +#define WEAK_ATTRIBUTE __weak__ +#endif + +#ifndef JACK_WEAK_EXPORT +#ifdef __GNUC__ +/* JACK_WEAK_EXPORT needs to be a macro which + expands into a compiler directive. If non-null, the directive + must tell the compiler to arrange for weak linkage of + the symbol it used with. For this to work full may + require linker arguments in the client as well. +*/ +#define JACK_WEAK_EXPORT __attribute__((WEAK_ATTRIBUTE)) +#else +/* Add other things here for non-gcc platforms */ +#endif +#endif + +#ifndef JACK_OPTIONAL_WEAK_EXPORT +#define JACK_OPTIONAL_WEAK_EXPORT +#endif + +#ifndef JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT +#ifdef __GNUC__ +#define JACK_OPTIONAL_WEAK_DEPRECATED_EXPORT __attribute__((__deprecated__)) +#else +/* Add other things here for non-gcc platforms */ +#endif /* __GNUC__ */ +#endif + +#endif /* __weakmacros_h__ */