Index: /unk/libffado/support/jack/jack-for-ffado.patch =================================================================== --- /trunk/libffado/support/jack/jack-for-ffado.patch (revision 467) +++ (revision ) @@ -1,1587 +1,0 @@ -Index: configure.ac -=================================================================== ---- configure.ac (revision 1029) -+++ configure.ac (working copy) -@@ -612,6 +612,23 @@ - fi - AM_CONDITIONAL(HAVE_FREEBOB,$HAVE_FREEBOB) - -+AC_ARG_ENABLE(firewire, [ --disable-firewire ignore FireWire driver (FFADO) ], -+ TRY_FIREWIRE=$enableval , TRY_FIREWIRE=yes ) -+HAVE_FIREWIRE="false" -+if test "x$TRY_FIREWIRE" = "xyes" -+then -+ # check for FFADO libraries -+ PKG_CHECK_MODULES(LIBFFADO, libffado >= 1.999.0, -+ [HAVE_FIREWIRE="true" -+ JACK_DEFAULT_DRIVER=\"firewire\" -+ ], AC_MSG_RESULT([no])) -+ -+ AC_SUBST([LIBFFADO_CFLAGS]) -+ AC_SUBST([LIBFFADO_LIBS]) -+ -+fi -+AM_CONDITIONAL(HAVE_FIREWIRE,$HAVE_FIREWIRE) -+ - AC_ARG_ENABLE(alsa, [ --disable-alsa ignore ALSA driver ], - TRY_ALSA=$enableval , TRY_ALSA=yes ) - HAVE_ALSA="false" -@@ -698,6 +715,7 @@ - drivers/portaudio/Makefile - drivers/coreaudio/Makefile - drivers/freebob/Makefile -+drivers/firewire/Makefile - example-clients/Makefile - jack.pc - jack.spec -@@ -716,7 +734,8 @@ - echo $PACKAGE $VERSION : - echo - echo \| Build with ALSA support............................... : $HAVE_ALSA --echo \| Build with FreeBob support............................ : $HAVE_FREEBOB -+echo \| Build with old FireWire \(FreeBob\) support............. : $HAVE_FREEBOB -+echo \| Build with new FireWire \(FFADO\) support............... : $HAVE_FIREWIRE - echo \| Build with OSS support................................ : $HAVE_OSS - echo \| Build with CoreAudio support.......................... : $HAVE_COREAUDIO - echo \| Build with PortAudio support.......................... : $HAVE_PA -Index: drivers/freebob/freebob_driver.c -=================================================================== ---- drivers/freebob/freebob_driver.c (revision 1029) -+++ drivers/freebob/freebob_driver.c (working copy) -@@ -182,8 +182,10 @@ - - for (node = driver->capture_ports; node && node->data; - node = jack_slist_next (node)) { -- jack_port_unregister (driver->client, -+ if(node->data != NULL) { -+ jack_port_unregister (driver->client, - ((jack_port_t *) node->data)); -+ } - } - - jack_slist_free (driver->capture_ports); -@@ -191,8 +193,10 @@ - - for (node = driver->playback_ports; node && node->data; - node = jack_slist_next (node)) { -- jack_port_unregister (driver->client, -+ if(node->data != NULL) { -+ jack_port_unregister (driver->client, - ((jack_port_t *) node->data)); -+ } - } - - jack_slist_free (driver->playback_ports); -Index: drivers/Makefile.am -=================================================================== ---- drivers/Makefile.am (revision 1029) -+++ drivers/Makefile.am (working copy) -@@ -30,5 +30,11 @@ - FREEBOB_DIR = - endif - --SUBDIRS = $(ALSA_DIR) dummy $(OSS_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) --DIST_SUBDIRS = alsa dummy oss portaudio coreaudio freebob -+if HAVE_FIREWIRE -+FIREWIRE_DIR = firewire -+else -+FIREWIRE_DIR = -+endif -+ -+SUBDIRS = $(ALSA_DIR) dummy $(OSS_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) $(FIREWIRE_DIR) -+DIST_SUBDIRS = alsa dummy oss portaudio coreaudio freebob firewire -Index: drivers/firewire/ffado_driver.h -=================================================================== ---- drivers/firewire/ffado_driver.h (revision 0) -+++ drivers/firewire/ffado_driver.h (revision 0) -@@ -0,0 +1,244 @@ -+/* -+ * FireWire Backend for Jack -+ * using FFADO -+ * FFADO = Firewire (pro-)audio for linux -+ * -+ * http://www.ffado.org -+ * http://www.jackaudio.org -+ * -+ * Copyright (C) 2005-2007 Pieter Palmers -+ * -+ * 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. -+ */ -+ -+/* -+ * Main Jack driver entry routines -+ * -+ */ -+ -+#ifndef __JACK_FFADO_DRIVER_H__ -+#define __JACK_FFADO_DRIVER_H__ -+ -+#define FFADO_DRIVER_WITH_ASEQ_MIDI -+ -+#include -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+// debug print control flags -+#define DEBUG_LEVEL_BUFFERS (1<<0) -+#define DEBUG_LEVEL_HANDLERS (1<<1) -+#define DEBUG_LEVEL_XRUN_RECOVERY (1<<2) -+#define DEBUG_LEVEL_WAIT (1<<3) -+ -+#define DEBUG_LEVEL_RUN_CYCLE (1<<8) -+ -+#define DEBUG_LEVEL_PACKETCOUNTER (1<<16) -+#define DEBUG_LEVEL_STARTUP (1<<17) -+#define DEBUG_LEVEL_THREADS (1<<18) -+ -+ -+#ifdef DEBUG_ENABLED -+ -+ // default debug level -+ #define DEBUG_LEVEL ( DEBUG_LEVEL_RUN_CYCLE | \ -+ (DEBUG_LEVEL_XRUN_RECOVERY)| DEBUG_LEVEL_STARTUP | DEBUG_LEVEL_WAIT | DEBUG_LEVEL_PACKETCOUNTER) -+ -+ #warning Building debug build! -+ -+ #define printMessage(format, args...) jack_error( "FreeBoB MSG: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args ) -+ #define printError(format, args...) jack_error( "FreeBoB ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args ) -+ -+ //#define printEnter() jack_error( "FBDRV ENTERS: %s (%s)\n", __FUNCTION__, __FILE__) -+ //#define printExit() jack_error( "FBDRV EXITS: %s (%s)\n", __FUNCTION__, __FILE__) -+ #define printEnter() -+ #define printExit() -+ -+ #define debugError(format, args...) jack_error( "FREEBOB ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args ) -+ #define debugPrint(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error("DEBUG %s:%d (%s) :" format, __FILE__, __LINE__, __FUNCTION__, ##args ); -+ #define debugPrintShort(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( format,##args ); -+ #define debugPrintWithTimeStamp(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( "%16lu: "format, debugGetCurrentUTime(),##args ); -+ #define SEGFAULT int *test=NULL; *test=1; -+#else -+ #define DEBUG_LEVEL -+ -+ #define printMessage(format, args...) if(g_verbose) \ -+ jack_error("FreeBoB MSG: " format, ##args ) -+ #define printError(format, args...) jack_error("FreeBoB ERR: " format, ##args ) -+ -+ #define printEnter() -+ #define printExit() -+ -+ #define debugError(format, args...) -+ #define debugPrint(Level, format, args...) -+ #define debugPrintShort(Level, format, args...) -+ #define debugPrintWithTimeStamp(Level, format, args...) -+#endif -+ -+// thread priority setup -+#define FFADO_RT_PRIORITY_PACKETIZER_RELATIVE 5 -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ -+ #define ALSA_SEQ_BUFF_SIZE 1024 -+ #define MIDI_TRANSMIT_BUFFER_SIZE 1024 -+ #define MIDI_THREAD_SLEEP_TIME_USECS 100 -+ // midi priority should be higher than the audio priority in order to -+ // make sure events are not only delivered on period boundarys -+ // but I think it should be smaller than the packetizer thread in order not -+ // to lose any packets -+ #define FFADO_RT_PRIORITY_MIDI_RELATIVE 4 -+ -+#endif -+ -+typedef struct _ffado_driver ffado_driver_t; -+ -+/* -+ * Jack Driver command line parameters -+ */ -+ -+typedef struct _ffado_jack_settings ffado_jack_settings_t; -+struct _ffado_jack_settings { -+ int period_size_set; -+ jack_nframes_t period_size; -+ -+ int sample_rate_set; -+ int sample_rate; -+ -+ int buffer_size_set; -+ jack_nframes_t buffer_size; -+ -+ int port_set; -+ int port; -+ -+ int node_id_set; -+ int node_id; -+ -+ int playback_ports; -+ int capture_ports; -+ -+ int slave_mode; -+ int snoop_mode; -+ -+ ffado_handle_t fb_handle; -+}; -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ -+typedef struct { -+ int stream_nr; -+ int seq_port_nr; -+ snd_midi_event_t *parser; -+ snd_seq_t *seq_handle; -+} ffado_midi_port_t; -+ -+typedef struct _ffado_driver_midi_handle { -+ ffado_device_t *dev; -+ ffado_driver_t *driver; -+ -+ snd_seq_t *seq_handle; -+ -+ pthread_t queue_thread; -+ pthread_t dequeue_thread; -+ int queue_thread_realtime; -+ int queue_thread_priority; -+ -+ int nb_input_ports; -+ int nb_output_ports; -+ -+ ffado_midi_port_t **input_ports; -+ ffado_midi_port_t **output_ports; -+ -+ ffado_midi_port_t **input_stream_port_map; -+ int *output_port_stream_map; -+ -+ -+} ffado_driver_midi_handle_t; -+ -+#endif -+/* -+ * JACK driver structure -+ */ -+ -+ -+struct _ffado_driver -+{ -+ JACK_DRIVER_NT_DECL -+ -+ jack_nframes_t sample_rate; -+ jack_nframes_t period_size; -+ unsigned long wait_time; -+ -+ jack_time_t wait_last; -+ jack_time_t wait_next; -+ int wait_late; -+ -+ jack_client_t *client; -+ -+ int xrun_detected; -+ int xrun_count; -+ -+ int process_count; -+ -+ /* settings from the command line */ -+ ffado_jack_settings_t settings; -+ -+ /* the freebob virtual device */ -+ ffado_device_t *dev; -+ -+ JSList *capture_ports; -+ JSList *playback_ports; -+ JSList *monitor_ports; -+ channel_t playback_nchannels; -+ channel_t capture_nchannels; -+ -+ ffado_device_info_t device_info; -+ ffado_options_t device_options; -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ ffado_driver_midi_handle_t *midi_handle; -+#endif -+ -+}; -+ -+ -+ -+#endif /* __JACK_FFADO_DRIVER_H__ */ -+ -+ -Index: drivers/firewire/Makefile.am -=================================================================== ---- drivers/firewire/Makefile.am (revision 0) -+++ drivers/firewire/Makefile.am (revision 0) -@@ -0,0 +1,20 @@ -+# plugin is called 'firewire', -+# driver code is called 'ffado*' because it is an implementation -+# of a firewire backend -+ -+MAINTAINERCLEANFILES=Makefile.in -+ -+AM_CFLAGS = $(JACK_CFLAGS) $(LIBFFADO_CFLAGS) $(ALSA_CFLAGS) -+ -+plugindir = $(ADDON_DIR) -+ -+plugin_LTLIBRARIES = jack_firewire.la -+ -+jack_firewire_la_SOURCES = ffado_driver.c -+ -+jack_firewire_la_LIBADD = $(LIBFFADO_LIBS) $(ALSA_LIBS) -+ -+jack_firewire_la_LDFLAGS = -module -avoid-version -+ -+noinst_HEADERS = ffado_driver.h -+ -Index: drivers/firewire/ffado_driver.c -=================================================================== ---- drivers/firewire/ffado_driver.c (revision 0) -+++ drivers/firewire/ffado_driver.c (revision 0) -@@ -0,0 +1,1216 @@ -+/* -+ * FireWire Backend for Jack -+ * using FFADO -+ * FFADO = Firewire (pro-)audio for linux -+ * -+ * http://www.ffado.org -+ * http://www.jackaudio.org -+ * -+ * Copyright (C) 2005-2007 Pieter Palmers -+ * -+ * 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. -+ */ -+ -+/* -+ * Main Jack driver entry routines -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "ffado_driver.h" -+ -+#define SAMPLE_MAX_24BIT 8388608.0f -+#define SAMPLE_MAX_16BIT 32768.0f -+ -+static int ffado_driver_stop (ffado_driver_t *driver); -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ static ffado_driver_midi_handle_t *ffado_driver_midi_init(ffado_driver_t *driver); -+ static void ffado_driver_midi_finish (ffado_driver_midi_handle_t *m); -+ static int ffado_driver_midi_start (ffado_driver_midi_handle_t *m); -+ static int ffado_driver_midi_stop (ffado_driver_midi_handle_t *m); -+#endif -+ -+// enable verbose messages -+static int g_verbose=0; -+ -+static int -+ffado_driver_attach (ffado_driver_t *driver) -+{ -+ char buf[64]; -+ channel_t chn; -+ jack_port_t *port; -+ int port_flags; -+ -+ g_verbose=driver->engine->verbose; -+ driver->device_options.verbose=g_verbose; -+ -+ driver->engine->set_buffer_size (driver->engine, driver->period_size); -+ driver->engine->set_sample_rate (driver->engine, driver->sample_rate); -+ -+ /* packetizer thread options */ -+ driver->device_options.realtime=(driver->engine->control->real_time? 1 : 0); -+ -+ driver->device_options.packetizer_priority=driver->engine->control->client_priority + -+ FFADO_RT_PRIORITY_PACKETIZER_RELATIVE; -+ if (driver->device_options.packetizer_priority>98) { -+ driver->device_options.packetizer_priority=98; -+ } -+ -+ driver->dev=ffado_streaming_init(&driver->device_info,driver->device_options); -+ -+ if(!driver->dev) { -+ printError("Error creating FFADO streaming device"); -+ return -1; -+ } -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ driver->midi_handle=ffado_driver_midi_init(driver); -+ if(!driver->midi_handle) { -+ printError("-----------------------------------------------------------"); -+ printError("Error creating midi device!"); -+ printError("The FireWire backend will run without MIDI support."); -+ printError("Consult the above error messages to solve the problem. "); -+ printError("-----------------------------------------------------------\n\n"); -+ } -+#endif -+ -+ if (driver->device_options.realtime) { -+ printMessage("Streaming thread running with Realtime scheduling, priority %d", -+ driver->device_options.packetizer_priority); -+ } else { -+ printMessage("Streaming thread running without Realtime scheduling"); -+ } -+ -+ /* ports */ -+ port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal; -+ -+ driver->capture_nchannels=ffado_streaming_get_nb_capture_streams(driver->dev); -+ -+ for (chn = 0; chn < driver->capture_nchannels; chn++) { -+ -+ ffado_streaming_get_capture_stream_name(driver->dev, chn, buf, sizeof(buf) - 1); -+ -+ if(ffado_streaming_get_capture_stream_type(driver->dev, chn) != ffado_stream_type_audio) { -+ printMessage ("Don't register capture port %s", buf); -+ -+ // we have to add a NULL entry in the list to be able to loop over the channels in the read/write routines -+ driver->capture_ports = -+ jack_slist_append (driver->capture_ports, NULL); -+ } else { -+ printMessage ("Registering capture port %s", buf); -+ if ((port = jack_port_register (driver->client, buf, -+ JACK_DEFAULT_AUDIO_TYPE, -+ port_flags, 0)) == NULL) { -+ printError (" cannot register port for %s", buf); -+ break; -+ } -+ driver->capture_ports = -+ jack_slist_append (driver->capture_ports, port); -+ // setup port parameters -+ if(ffado_streaming_set_capture_buffer_type(driver->dev, chn, ffado_buffer_type_float)) { -+ printError(" cannot set port buffer type for %s", buf); -+ } -+ if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) { -+ printError(" cannot configure initial port buffer for %s", buf); -+ } -+ if(ffado_streaming_capture_stream_onoff(driver->dev, chn, 1)) { -+ printError(" cannot enable port %s", buf); -+ } -+ } -+// jack_port_set_latency (port, driver->period_size); -+ -+ } -+ -+ port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; -+ -+ driver->playback_nchannels=ffado_streaming_get_nb_playback_streams(driver->dev); -+ -+ for (chn = 0; chn < driver->playback_nchannels; chn++) { -+ -+ ffado_streaming_get_playback_stream_name(driver->dev, chn, buf, sizeof(buf) - 1); -+ -+ if(ffado_streaming_get_playback_stream_type(driver->dev, chn) != ffado_stream_type_audio) { -+ printMessage ("Don't register playback port %s", buf); -+ -+ // we have to add a NULL entry in the list to be able to loop over the channels in the read/write routines -+ driver->playback_ports = -+ jack_slist_append (driver->playback_ports, NULL); -+ } else { -+ printMessage ("Registering playback port %s", buf); -+ if ((port = jack_port_register (driver->client, buf, -+ JACK_DEFAULT_AUDIO_TYPE, -+ port_flags, 0)) == NULL) { -+ printError(" cannot register port for %s", buf); -+ break; -+ } -+ driver->playback_ports = -+ jack_slist_append (driver->playback_ports, port); -+ -+ // setup port parameters -+ if(ffado_streaming_set_playback_buffer_type(driver->dev, chn, ffado_buffer_type_float)) { -+ printError(" cannot set port buffer type for %s", buf); -+ } -+ if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) { -+ printError(" cannot configure initial port buffer for %s", buf); -+ } -+ if(ffado_streaming_playback_stream_onoff(driver->dev, chn, 1)) { -+ printError(" cannot enable port %s", buf); -+ } -+ } -+// jack_port_set_latency (port, (driver->period_size * (driver->user_nperiods - 1)) + driver->playback_frame_latency); -+ -+ } -+ -+ if(!ffado_streaming_prepare(driver->dev)) { -+ printError("Could not prepare streaming device!"); -+ return -1; -+ } -+ -+ -+ return jack_activate (driver->client); -+} -+ -+static int -+ffado_driver_detach (ffado_driver_t *driver) -+{ -+ JSList *node; -+ -+ if (driver->engine == NULL) { -+ return 0; -+ } -+ -+ for (node = driver->capture_ports; node; -+ node = jack_slist_next (node)) { -+ // Don't try to unregister NULL entries added for non-audio -+ // ffado ports by ffado_driver_attach(). -+ if (node->data != NULL) { -+ jack_port_unregister (driver->client, -+ ((jack_port_t *) node->data)); -+ } -+ } -+ -+ jack_slist_free (driver->capture_ports); -+ driver->capture_ports = 0; -+ -+ for (node = driver->playback_ports; node; -+ node = jack_slist_next (node)) { -+ if (node->data != NULL) { -+ jack_port_unregister (driver->client, -+ ((jack_port_t *) node->data)); -+ } -+ } -+ -+ jack_slist_free (driver->playback_ports); -+ driver->playback_ports = 0; -+ -+ ffado_streaming_finish(driver->dev); -+ driver->dev=NULL; -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ if(driver->midi_handle) { -+ ffado_driver_midi_finish(driver->midi_handle); -+ } -+ driver->midi_handle=NULL; -+#endif -+ -+ return 0; -+} -+ -+static inline void -+ffado_driver_read_from_channel (ffado_driver_t *driver, -+ channel_t channel, -+ jack_default_audio_sample_t *dst, -+ jack_nframes_t nsamples) -+{ -+ -+ ffado_sample_t buffer[nsamples]; -+ char *src=(char *)buffer; -+ -+ ffado_streaming_read(driver->dev, channel, buffer, nsamples); -+ -+ /* ALERT: signed sign-extension portability !!! */ -+ -+ while (nsamples--) { -+ int x; -+#if __BYTE_ORDER == __LITTLE_ENDIAN -+ memcpy((char*)&x + 1, src, 3); -+#elif __BYTE_ORDER == __BIG_ENDIAN -+ memcpy(&x, src, 3); -+#endif -+ x >>= 8; -+ *dst = x / SAMPLE_MAX_24BIT; -+ dst++; -+ src += sizeof(ffado_sample_t); -+ } -+ -+} -+ -+static int -+ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nframes) -+{ -+ jack_default_audio_sample_t* buf; -+ channel_t chn; -+ JSList *node; -+ jack_port_t* port; -+ -+ ffado_sample_t nullbuffer[nframes]; -+ -+ ffado_streaming_stream_type stream_type; -+ -+ printEnter(); -+ -+ for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) { -+ stream_type = ffado_streaming_get_capture_stream_type(driver->dev, chn); -+ if(stream_type == ffado_stream_type_audio) { -+ port = (jack_port_t *) node->data; -+ -+ buf = jack_port_get_buffer (port, nframes); -+ if(!buf) buf=(jack_default_audio_sample_t*)nullbuffer; -+ -+ ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf)); -+ } -+ } -+ -+ // now transfer the buffers -+ ffado_streaming_transfer_capture_buffers(driver->dev); -+ -+ printExit(); -+ -+ return 0; -+ -+} -+ -+static inline void -+ffado_driver_write_to_channel (ffado_driver_t *driver, -+ channel_t channel, -+ jack_default_audio_sample_t *buf, -+ jack_nframes_t nsamples) -+{ -+ long long y; -+ ffado_sample_t buffer[nsamples]; -+ unsigned int i=0; -+ char *dst=(char *)buffer; -+ -+ // convert from float to integer -+ for(;i (INT_MAX >> 8 )) { -+ y = (INT_MAX >> 8); -+ } else if (y < (INT_MIN >> 8 )) { -+ y = (INT_MIN >> 8 ); -+ } -+#if __BYTE_ORDER == __LITTLE_ENDIAN -+ memcpy (dst, &y, 3); -+#elif __BYTE_ORDER == __BIG_ENDIAN -+ memcpy (dst, (char *)&y + 5, 3); -+#endif -+ dst += sizeof(ffado_sample_t); -+ buf++; -+ } -+ -+ // write to the ffado streaming device -+ ffado_streaming_write(driver->dev, channel, buffer, nsamples); -+ -+} -+ -+static int -+ffado_driver_write (ffado_driver_t * driver, jack_nframes_t nframes) -+{ -+ channel_t chn; -+ JSList *node; -+ jack_default_audio_sample_t* buf; -+ -+ jack_port_t *port; -+ -+ ffado_streaming_stream_type stream_type; -+ -+ ffado_sample_t nullbuffer[nframes]; -+ -+ memset(&nullbuffer,0,nframes*sizeof(ffado_sample_t)); -+ -+ printEnter(); -+ -+ driver->process_count++; -+ -+ assert(driver->dev); -+ -+ if (driver->engine->freewheeling) { -+ return 0; -+ } -+ -+ for (chn = 0, node = driver->playback_ports; node; node = jack_slist_next (node), chn++) { -+ stream_type=ffado_streaming_get_playback_stream_type(driver->dev, chn); -+ if(stream_type == ffado_stream_type_audio) { -+ port = (jack_port_t *) node->data; -+ -+ buf = jack_port_get_buffer (port, nframes); -+ if(!buf) buf=(jack_default_audio_sample_t*)nullbuffer; -+ -+ ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf)); -+ } -+ } -+ -+ ffado_streaming_transfer_playback_buffers(driver->dev); -+ -+ printExit(); -+ -+ return 0; -+} -+ -+//static inline jack_nframes_t -+static jack_nframes_t -+ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *status, -+ float *delayed_usecs) -+{ -+ int nframes; -+ jack_time_t wait_enter; -+ jack_time_t wait_ret; -+ -+ printEnter(); -+ -+ wait_enter = jack_get_microseconds (); -+ if (wait_enter > driver->wait_next) { -+ /* -+ * This processing cycle was delayed past the -+ * next due interrupt! Do not account this as -+ * a wakeup delay: -+ */ -+ driver->wait_next = 0; -+ driver->wait_late++; -+ } -+// *status = -2; interrupt -+// *status = -3; timeout -+// *status = -4; extra FD -+ -+ nframes=ffado_streaming_wait(driver->dev); -+ -+ wait_ret = jack_get_microseconds (); -+ -+ if (driver->wait_next && wait_ret > driver->wait_next) { -+ *delayed_usecs = wait_ret - driver->wait_next; -+ } -+ driver->wait_last = wait_ret; -+ driver->wait_next = wait_ret + driver->period_usecs; -+ driver->engine->transport_cycle_start (driver->engine, wait_ret); -+ -+ // transfer the streaming buffers -+ // we now do this in the read/write functions -+// ffado_streaming_transfer_buffers(driver->dev); -+ -+ if (nframes < 0) { -+ *status=0; -+ -+ return 0; -+ //nframes=driver->period_size; //debug -+ } -+ -+ *status = 0; -+ driver->last_wait_ust = wait_ret; -+ -+ // FIXME: this should do something more usefull -+ *delayed_usecs = 0; -+ -+ printExit(); -+ -+ return nframes - nframes % driver->period_size; -+ -+} -+ -+static int -+ffado_driver_run_cycle (ffado_driver_t *driver) -+{ -+ jack_engine_t *engine = driver->engine; -+ int wait_status=0; -+ float delayed_usecs=0.0; -+ -+ jack_nframes_t nframes = ffado_driver_wait (driver, -1, -+ &wait_status, &delayed_usecs); -+ -+ if ((wait_status < 0)) { -+ printError( "wait status < 0! (= %d)",wait_status); -+ return -1; -+ } -+ -+ if ((nframes == 0)) { -+ /* we detected an xrun and restarted: notify -+ * clients about the delay. */ -+ printMessage("xrun detected"); -+ engine->delay (engine, delayed_usecs); -+ return 0; -+ } -+ -+ return engine->run_cycle (engine, nframes, delayed_usecs); -+ -+} -+/* -+ * in a null cycle we should discard the input and write silence to the outputs -+ */ -+static int -+ffado_driver_null_cycle (ffado_driver_t* driver, jack_nframes_t nframes) -+{ -+ channel_t chn; -+ JSList *node; -+ snd_pcm_sframes_t nwritten; -+ -+ ffado_streaming_stream_type stream_type; -+ -+ jack_default_audio_sample_t buff[nframes]; -+ jack_default_audio_sample_t* buffer=(jack_default_audio_sample_t*)buff; -+ -+ printEnter(); -+ -+ memset(buffer,0,nframes*sizeof(jack_default_audio_sample_t)); -+ -+ assert(driver->dev); -+ -+ if (driver->engine->freewheeling) { -+ return 0; -+ } -+ -+ // write silence to buffer -+ nwritten = 0; -+ -+ for (chn = 0, node = driver->playback_ports; node; node = jack_slist_next (node), chn++) { -+ stream_type=ffado_streaming_get_playback_stream_type(driver->dev, chn); -+ -+ if(stream_type == ffado_stream_type_audio) { -+ ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buffer)); -+ } -+ } -+ -+ ffado_streaming_transfer_playback_buffers(driver->dev); -+ -+ // read & discard from input ports -+ for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) { -+ stream_type=ffado_streaming_get_capture_stream_type(driver->dev, chn); -+ if(stream_type == ffado_stream_type_audio) { -+ ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buffer)); -+ } -+ } -+ -+ // now transfer the buffers -+ ffado_streaming_transfer_capture_buffers(driver->dev); -+ -+ printExit(); -+ return 0; -+} -+ -+static int -+ffado_driver_start (ffado_driver_t *driver) -+{ -+ int retval=0; -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ if(driver->midi_handle) { -+ if((retval=ffado_driver_midi_start(driver->midi_handle))) { -+ printError("Could not start MIDI threads"); -+ return retval; -+ } -+ } -+#endif -+ -+ if((retval=ffado_streaming_start(driver->dev))) { -+ printError("Could not start streaming threads"); -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ if(driver->midi_handle) { -+ ffado_driver_midi_stop(driver->midi_handle); -+ } -+#endif -+ return retval; -+ } -+ -+ return 0; -+ -+} -+ -+static int -+ffado_driver_stop (ffado_driver_t *driver) -+{ -+ int retval=0; -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+ if(driver->midi_handle) { -+ if((retval=ffado_driver_midi_stop(driver->midi_handle))) { -+ printError("Could not stop MIDI threads"); -+ return retval; -+ } -+ } -+#endif -+ if((retval=ffado_streaming_stop(driver->dev))) { -+ printError("Could not stop streaming threads"); -+ return retval; -+ } -+ -+ return 0; -+} -+ -+ -+static int -+ffado_driver_bufsize (ffado_driver_t* driver, jack_nframes_t nframes) -+{ -+ printError("Buffer size change requested but not supported!!!"); -+ -+ /* -+ driver->period_size = nframes; -+ driver->period_usecs = -+ (jack_time_t) floor ((((float) nframes) / driver->sample_rate) -+ * 1000000.0f); -+ */ -+ -+ /* tell the engine to change its buffer size */ -+ //driver->engine->set_buffer_size (driver->engine, nframes); -+ -+ return -1; // unsupported -+} -+ -+typedef void (*JackDriverFinishFunction) (jack_driver_t *); -+ -+ffado_driver_t * -+ffado_driver_new (jack_client_t * client, -+ char *name, -+ ffado_jack_settings_t *params) -+{ -+ ffado_driver_t *driver; -+ -+ assert(params); -+ -+ if(ffado_get_api_version() != 2) { -+ printError("Incompatible libffado version! (%s)", ffado_get_version()); -+ return NULL; -+ } -+ -+ printMessage("Starting Freebob backend (%s)", ffado_get_version()); -+ -+ driver = calloc (1, sizeof (ffado_driver_t)); -+ -+ /* Setup the jack interfaces */ -+ jack_driver_nt_init ((jack_driver_nt_t *) driver); -+ -+ driver->nt_attach = (JackDriverNTAttachFunction) ffado_driver_attach; -+ driver->nt_detach = (JackDriverNTDetachFunction) ffado_driver_detach; -+ driver->nt_start = (JackDriverNTStartFunction) ffado_driver_start; -+ driver->nt_stop = (JackDriverNTStopFunction) ffado_driver_stop; -+ driver->nt_run_cycle = (JackDriverNTRunCycleFunction) ffado_driver_run_cycle; -+ driver->null_cycle = (JackDriverNullCycleFunction) ffado_driver_null_cycle; -+ driver->write = (JackDriverReadFunction) ffado_driver_write; -+ driver->read = (JackDriverReadFunction) ffado_driver_read; -+ driver->nt_bufsize = (JackDriverNTBufSizeFunction) ffado_driver_bufsize; -+ -+ /* copy command line parameter contents to the driver structure */ -+ memcpy(&driver->settings,params,sizeof(ffado_jack_settings_t)); -+ -+ /* prepare all parameters */ -+ driver->sample_rate = params->sample_rate; -+ driver->period_size = params->period_size; -+ driver->last_wait_ust = 0; -+ -+ driver->period_usecs = -+ (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate); -+ -+ driver->client = client; -+ driver->engine = NULL; -+ -+ memset(&driver->device_options,0,sizeof(driver->device_options)); -+ driver->device_options.sample_rate=params->sample_rate; -+ driver->device_options.period_size=params->period_size; -+ driver->device_options.nb_buffers=params->buffer_size; -+ driver->device_options.node_id=params->node_id; -+ driver->device_options.port=params->port; -+ driver->device_options.slave_mode=params->slave_mode; -+ driver->device_options.snoop_mode=params->snoop_mode; -+ -+ if(!params->capture_ports) { -+ driver->device_options.directions |= FFADO_IGNORE_CAPTURE; -+ } -+ -+ if(!params->playback_ports) { -+ driver->device_options.directions |= FFADO_IGNORE_PLAYBACK; -+ } -+ -+ debugPrint(DEBUG_LEVEL_STARTUP, " Driver compiled on %s %s", __DATE__, __TIME__); -+ debugPrint(DEBUG_LEVEL_STARTUP, " Created driver %s", name); -+ debugPrint(DEBUG_LEVEL_STARTUP, " period_size: %d", driver->period_size); -+ debugPrint(DEBUG_LEVEL_STARTUP, " period_usecs: %d", driver->period_usecs); -+ debugPrint(DEBUG_LEVEL_STARTUP, " sample rate: %d", driver->sample_rate); -+ -+ return (ffado_driver_t *) driver; -+ -+} -+ -+static void -+ffado_driver_delete (ffado_driver_t *driver) -+{ -+ jack_driver_nt_finish ((jack_driver_nt_t *) driver); -+ free (driver); -+} -+ -+#ifdef FFADO_DRIVER_WITH_ASEQ_MIDI -+/* -+ * MIDI support -+ */ -+ -+// the thread that will queue the midi events from the seq to the stream buffers -+ -+void * ffado_driver_midi_queue_thread(void *arg) -+{ -+ ffado_driver_midi_handle_t *m=(ffado_driver_midi_handle_t *)arg; -+ assert(m); -+ snd_seq_event_t *ev; -+ unsigned char work_buffer[MIDI_TRANSMIT_BUFFER_SIZE]; -+ int bytes_to_send; -+ int b; -+ int i; -+ -+ printMessage("MIDI queue thread started"); -+ -+ while(1) { -+ // get next event, if one is present -+ while ((snd_seq_event_input(m->seq_handle, &ev) > 0)) { -+ // get the port this event is originated from -+ ffado_midi_port_t *port=NULL; -+ for (i=0;inb_output_ports;i++) { -+ if(m->output_ports[i]->seq_port_nr == ev->dest.port) { -+ port=m->output_ports[i]; -+ break; -+ } -+ } -+ -+ if(!port) { -+ printError(" Could not find target port for event: dst=%d src=%d", ev->dest.port, ev->source.port); -+ -+ break; -+ } -+ -+ // decode it to the work buffer -+ if((bytes_to_send = snd_midi_event_decode ( port->parser, -+ work_buffer, -+ MIDI_TRANSMIT_BUFFER_SIZE, -+ ev))<0) -+ { // failed -+ printError(" Error decoding event for port %d (errcode=%d)", port->seq_port_nr,bytes_to_send); -+ bytes_to_send=0; -+ //return -1; -+ } -+ -+ for(b=0;bdev, port->stream_nr, &tmp_event, 1)<1) { -+ printError(" Midi send buffer overrun"); -+ } -+ } -+ -+ } -+ -+ // sleep for some time -+ usleep(MIDI_THREAD_SLEEP_TIME_USECS); -+ } -+ return NULL; -+} -+ -+// the dequeue thread (maybe we need one thread per stream) -+void *ffado_driver_midi_dequeue_thread (void *arg) { -+ ffado_driver_midi_handle_t *m=(ffado_driver_midi_handle_t *)arg; -+ -+ int i; -+ int s; -+ -+ int samples_read; -+ -+ assert(m); -+ -+ while(1) { -+ // read incoming events -+ -+ for (i=0;inb_input_ports;i++) { -+ unsigned int buff[64]; -+ -+ ffado_midi_port_t *port=m->input_ports[i]; -+ -+ if(!port) { -+ printError(" something went wrong when setting up the midi input port map (%d)",i); -+ } -+ -+ do { -+ samples_read=ffado_streaming_read(m->dev, port->stream_nr, buff, 64); -+ -+ for (s=0;sparser,(*byte) & 0xFF, &ev)) > 0) { -+ // a midi message is complete, send it out to ALSA -+ snd_seq_ev_set_subs(&ev); -+ snd_seq_ev_set_direct(&ev); -+ snd_seq_ev_set_source(&ev, port->seq_port_nr); -+ snd_seq_event_output_direct(port->seq_handle, &ev); -+ } -+ } -+ } while (samples_read>0); -+ } -+ -+ // sleep for some time -+ usleep(MIDI_THREAD_SLEEP_TIME_USECS); -+ } -+ return NULL; -+} -+ -+static ffado_driver_midi_handle_t *ffado_driver_midi_init(ffado_driver_t *driver) { -+// int err; -+ -+ char buf[256]; -+ channel_t chn; -+ int nchannels; -+ int i=0; -+ -+ ffado_device_t *dev=driver->dev; -+ -+ assert(dev); -+ -+ ffado_driver_midi_handle_t *m=calloc(1,sizeof(ffado_driver_midi_handle_t)); -+ if (!m) { -+ printError("not enough memory to create midi structure"); -+ return NULL; -+ } -+ -+ if (snd_seq_open(&m->seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) { -+ printError("Error opening ALSA sequencer."); -+ free(m); -+ return NULL; -+ } -+ -+ snd_seq_set_client_name(m->seq_handle, "FreeBoB Jack MIDI"); -+ -+ // find out the number of midi in/out ports we need to setup -+ nchannels=ffado_streaming_get_nb_capture_streams(dev); -+ -+ m->nb_input_ports=0; -+ -+ for (chn = 0; chn < nchannels; chn++) { -+ if(ffado_streaming_get_capture_stream_type(dev, chn) == ffado_stream_type_midi) { -+ m->nb_input_ports++; -+ } -+ } -+ -+ m->input_ports=calloc(m->nb_input_ports,sizeof(ffado_midi_port_t *)); -+ if(!m->input_ports) { -+ printError("not enough memory to create midi structure"); -+ free(m); -+ return NULL; -+ } -+ -+ i=0; -+ for (chn = 0; chn < nchannels; chn++) { -+ if(ffado_streaming_get_capture_stream_type(dev, chn) == ffado_stream_type_midi) { -+ m->input_ports[i]=calloc(1,sizeof(ffado_midi_port_t)); -+ if(!m->input_ports[i]) { -+ // fixme -+ printError("Could not allocate memory for seq port"); -+ continue; -+ } -+ -+ ffado_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf) - 1); -+ printMessage("Register MIDI IN port %s", buf); -+ -+ m->input_ports[i]->seq_port_nr=snd_seq_create_simple_port(m->seq_handle, buf, -+ SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -+ SND_SEQ_PORT_TYPE_MIDI_GENERIC); -+ -+ if(m->input_ports[i]->seq_port_nr<0) { -+ printError("Could not create seq port"); -+ m->input_ports[i]->stream_nr=-1; -+ m->input_ports[i]->seq_port_nr=-1; -+ } else { -+ m->input_ports[i]->stream_nr=chn; -+ m->input_ports[i]->seq_handle=m->seq_handle; -+ if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->input_ports[i]->parser)) < 0) { -+ printError("could not init parser for MIDI IN port %d",i); -+ m->input_ports[i]->stream_nr=-1; -+ m->input_ports[i]->seq_port_nr=-1; -+ } else { -+ if(ffado_streaming_set_capture_buffer_type(dev, chn, ffado_buffer_type_midi)) { -+ printError(" cannot set port buffer type for %s", buf); -+ m->input_ports[i]->stream_nr=-1; -+ m->input_ports[i]->seq_port_nr=-1; -+ } -+ if(ffado_streaming_capture_stream_onoff(dev, chn, 1)) { -+ printError(" cannot enable port %s", buf); -+ m->input_ports[i]->stream_nr=-1; -+ m->input_ports[i]->seq_port_nr=-1; -+ } -+ -+ } -+ } -+ -+ i++; -+ } -+ } -+ -+ // playback -+ nchannels=ffado_streaming_get_nb_playback_streams(dev); -+ -+ m->nb_output_ports=0; -+ -+ for (chn = 0; chn < nchannels; chn++) { -+ if(ffado_streaming_get_playback_stream_type(dev, chn) == ffado_stream_type_midi) { -+ m->nb_output_ports++; -+ } -+ } -+ -+ m->output_ports=calloc(m->nb_output_ports,sizeof(ffado_midi_port_t *)); -+ if(!m->output_ports) { -+ printError("not enough memory to create midi structure"); -+ for (i = 0; i < m->nb_input_ports; i++) { -+ free(m->input_ports[i]); -+ } -+ free(m->input_ports); -+ free(m); -+ return NULL; -+ } -+ -+ i=0; -+ for (chn = 0; chn < nchannels; chn++) { -+ if(ffado_streaming_get_playback_stream_type(dev, chn) == ffado_stream_type_midi) { -+ m->output_ports[i]=calloc(1,sizeof(ffado_midi_port_t)); -+ if(!m->output_ports[i]) { -+ // fixme -+ printError("Could not allocate memory for seq port"); -+ continue; -+ } -+ -+ ffado_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf) - 1); -+ printMessage("Register MIDI OUT port %s", buf); -+ -+ m->output_ports[i]->seq_port_nr=snd_seq_create_simple_port(m->seq_handle, buf, -+ SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -+ SND_SEQ_PORT_TYPE_MIDI_GENERIC); -+ -+ -+ if(m->output_ports[i]->seq_port_nr<0) { -+ printError("Could not create seq port"); -+ m->output_ports[i]->stream_nr=-1; -+ m->output_ports[i]->seq_port_nr=-1; -+ } else { -+ m->output_ports[i]->stream_nr=chn; -+ m->output_ports[i]->seq_handle=m->seq_handle; -+ if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->output_ports[i]->parser)) < 0) { -+ printError("could not init parser for MIDI OUT port %d",i); -+ m->output_ports[i]->stream_nr=-1; -+ m->output_ports[i]->seq_port_nr=-1; -+ } else { -+ if(ffado_streaming_set_playback_buffer_type(dev, chn, ffado_buffer_type_midi)) { -+ printError(" cannot set port buffer type for %s", buf); -+ m->input_ports[i]->stream_nr=-1; -+ m->input_ports[i]->seq_port_nr=-1; -+ } -+ if(ffado_streaming_playback_stream_onoff(dev, chn, 1)) { -+ printError(" cannot enable port %s", buf); -+ m->input_ports[i]->stream_nr=-1; -+ m->input_ports[i]->seq_port_nr=-1; -+ } -+ } -+ } -+ -+ i++; -+ } -+ } -+ -+ m->dev=dev; -+ m->driver=driver; -+ -+ return m; -+} -+ -+static int -+ffado_driver_midi_start (ffado_driver_midi_handle_t *m) -+{ -+ assert(m); -+ // start threads -+ -+ m->queue_thread_realtime=(m->driver->engine->control->real_time? 1 : 0); -+ m->queue_thread_priority= -+ m->driver->engine->control->client_priority + -+ FFADO_RT_PRIORITY_MIDI_RELATIVE; -+ -+ if (m->queue_thread_priority>98) { -+ m->queue_thread_priority=98; -+ } -+ if (m->queue_thread_realtime) { -+ printMessage("MIDI threads running with Realtime scheduling, priority %d", -+ m->queue_thread_priority); -+ } else { -+ printMessage("MIDI threads running without Realtime scheduling"); -+ } -+ -+ if (jack_client_create_thread(NULL, &m->queue_thread, m->queue_thread_priority, m->queue_thread_realtime, ffado_driver_midi_queue_thread, (void *)m)) { -+ printError(" cannot create midi queueing thread"); -+ return -1; -+ } -+ -+ if (jack_client_create_thread(NULL, &m->dequeue_thread, m->queue_thread_priority, m->queue_thread_realtime, ffado_driver_midi_dequeue_thread, (void *)m)) { -+ printError(" cannot create midi dequeueing thread"); -+ return -1; -+ } -+ return 0; -+} -+ -+static int -+ffado_driver_midi_stop (ffado_driver_midi_handle_t *m) -+{ -+ assert(m); -+ -+ pthread_cancel (m->queue_thread); -+ pthread_join (m->queue_thread, NULL); -+ -+ pthread_cancel (m->dequeue_thread); -+ pthread_join (m->dequeue_thread, NULL); -+ return 0; -+ -+} -+ -+static void -+ffado_driver_midi_finish (ffado_driver_midi_handle_t *m) -+{ -+ assert(m); -+ -+ int i; -+ // TODO: add state info here, if not stopped then stop -+ -+ for (i=0;inb_input_ports;i++) { -+ free(m->input_ports[i]); -+ -+ } -+ free(m->input_ports); -+ -+ for (i=0;inb_output_ports;i++) { -+ free(m->output_ports[i]); -+ } -+ free(m->output_ports); -+ -+ free(m); -+} -+#endif -+/* -+ * dlopen plugin stuff -+ */ -+ -+const char driver_client_name[] = "firewire_pcm"; -+ -+const jack_driver_desc_t * -+driver_get_descriptor () -+{ -+ jack_driver_desc_t * desc; -+ jack_driver_param_desc_t * params; -+ unsigned int i; -+ -+ desc = calloc (1, sizeof (jack_driver_desc_t)); -+ -+ strcpy (desc->name, "firewire"); -+ desc->nparams = 8; -+ -+ params = calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); -+ desc->params = params; -+ -+ i = 0; -+ strcpy (params[i].name, "device"); -+ params[i].character = 'd'; -+ params[i].type = JackDriverParamString; -+ strcpy (params[i].value.str, "hw:0"); -+ strcpy (params[i].short_desc, "The FireWire device to use. Format is: 'hw:port[,node]'."); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "period"); -+ params[i].character = 'p'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 1024; -+ strcpy (params[i].short_desc, "Frames per period"); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "nperiods"); -+ params[i].character = 'n'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 3; -+ strcpy (params[i].short_desc, "Number of periods of playback latency"); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "rate"); -+ params[i].character = 'r'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 48000U; -+ strcpy (params[i].short_desc, "Sample rate"); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "capture"); -+ params[i].character = 'i'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 1U; -+ strcpy (params[i].short_desc, "Provide capture ports."); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "playback"); -+ params[i].character = 'o'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 1U; -+ strcpy (params[i].short_desc, "Provide playback ports."); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "slave"); -+ params[i].character = 'x'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 0U; -+ strcpy (params[i].short_desc, "Act as a BounceDevice slave"); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ i++; -+ strcpy (params[i].name, "slave"); -+ params[i].character = 'X'; -+ params[i].type = JackDriverParamUInt; -+ params[i].value.ui = 0U; -+ strcpy (params[i].short_desc, "Operate in snoop mode"); -+ strcpy (params[i].long_desc, params[i].short_desc); -+ -+ return desc; -+} -+ -+ -+jack_driver_t * -+driver_initialize (jack_client_t *client, JSList * params) -+{ -+ jack_driver_t *driver; -+ -+ unsigned int port=0; -+ unsigned int node_id=-1; -+ int nbitems; -+ -+ const JSList * node; -+ const jack_driver_param_t * param; -+ -+ ffado_jack_settings_t cmlparams; -+ -+ char *device_name="hw:0"; -+ -+ cmlparams.period_size_set=0; -+ cmlparams.sample_rate_set=0; -+ cmlparams.buffer_size_set=0; -+ cmlparams.port_set=0; -+ cmlparams.node_id_set=0; -+ -+ /* default values */ -+ cmlparams.period_size=1024; -+ cmlparams.sample_rate=48000; -+ cmlparams.buffer_size=3; -+ cmlparams.port=0; -+ cmlparams.node_id=-1; -+ cmlparams.playback_ports=1; -+ cmlparams.capture_ports=1; -+ cmlparams.slave_mode=0; -+ cmlparams.snoop_mode=0; -+ -+ for (node = params; node; node = jack_slist_next (node)) -+ { -+ param = (jack_driver_param_t *) node->data; -+ -+ switch (param->character) -+ { -+ case 'd': -+ device_name = strdup (param->value.str); -+ break; -+ case 'p': -+ cmlparams.period_size = param->value.ui; -+ cmlparams.period_size_set = 1; -+ break; -+ case 'n': -+ cmlparams.buffer_size = param->value.ui; -+ cmlparams.buffer_size_set = 1; -+ break; -+ case 'r': -+ cmlparams.sample_rate = param->value.ui; -+ cmlparams.sample_rate_set = 1; -+ break; -+ case 'i': -+ cmlparams.capture_ports = param->value.ui; -+ break; -+ case 'o': -+ cmlparams.playback_ports = param->value.ui; -+ break; -+ case 'x': -+ cmlparams.slave_mode = param->value.ui; -+ break; -+ case 'X': -+ cmlparams.snoop_mode = param->value.ui; -+ break; -+ } -+ } -+ -+ nbitems=sscanf(device_name,"hw:%u,%u",&port,&node_id); -+ if (nbitems<2) { -+ nbitems=sscanf(device_name,"hw:%u",&port); -+ -+ if(nbitems < 1) { -+ free(device_name); -+ printError("device (-d) argument not valid\n"); -+ return NULL; -+ } else { -+ cmlparams.port = port; -+ cmlparams.port_set=1; -+ -+ cmlparams.node_id = -1; -+ cmlparams.node_id_set=0; -+ } -+ } else { -+ cmlparams.port = port; -+ cmlparams.port_set=1; -+ -+ cmlparams.node_id = node_id; -+ cmlparams.node_id_set=1; -+ } -+ -+ jack_error("Freebob using Firewire port %d, node %d",cmlparams.port,cmlparams.node_id); -+ -+ driver=(jack_driver_t *)ffado_driver_new (client, "ffado_pcm", &cmlparams); -+ -+ return driver; -+} -+ -+void -+driver_finish (jack_driver_t *driver) -+{ -+ ffado_driver_t *drv=(ffado_driver_t *) driver; -+ // If jack hasn't called the detach method, do it now. As of jack 0.101.1 -+ // the detach method was not being called explicitly on closedown, and -+ // we need it to at least deallocate the iso resources. -+ if (drv->dev != NULL) -+ ffado_driver_detach(drv); -+ ffado_driver_delete (drv); -+}