root/trunk/libffado/support/jack/jack-for-ffado.patch
Revision 467, 44.0 kB (checked in by ppalmers, 16 years ago) |
---|
-
configure.ac
old new 612 612 fi 613 613 AM_CONDITIONAL(HAVE_FREEBOB,$HAVE_FREEBOB) 614 614 615 AC_ARG_ENABLE(firewire, [ --disable-firewire ignore FireWire driver (FFADO) ], 616 TRY_FIREWIRE=$enableval , TRY_FIREWIRE=yes ) 617 HAVE_FIREWIRE="false" 618 if test "x$TRY_FIREWIRE" = "xyes" 619 then 620 # check for FFADO libraries 621 PKG_CHECK_MODULES(LIBFFADO, libffado >= 1.999.0, 622 [HAVE_FIREWIRE="true" 623 JACK_DEFAULT_DRIVER=\"firewire\" 624 ], AC_MSG_RESULT([no])) 625 626 AC_SUBST([LIBFFADO_CFLAGS]) 627 AC_SUBST([LIBFFADO_LIBS]) 628 629 fi 630 AM_CONDITIONAL(HAVE_FIREWIRE,$HAVE_FIREWIRE) 631 615 632 AC_ARG_ENABLE(alsa, [ --disable-alsa ignore ALSA driver ], 616 633 TRY_ALSA=$enableval , TRY_ALSA=yes ) 617 634 HAVE_ALSA="false" … … 698 715 drivers/portaudio/Makefile 699 716 drivers/coreaudio/Makefile 700 717 drivers/freebob/Makefile 718 drivers/firewire/Makefile 701 719 example-clients/Makefile 702 720 jack.pc 703 721 jack.spec … … 716 734 echo $PACKAGE $VERSION : 717 735 echo 718 736 echo \| Build with ALSA support............................... : $HAVE_ALSA 719 echo \| Build with FreeBob support............................ : $HAVE_FREEBOB 737 echo \| Build with old FireWire \(FreeBob\) support............. : $HAVE_FREEBOB 738 echo \| Build with new FireWire \(FFADO\) support............... : $HAVE_FIREWIRE 720 739 echo \| Build with OSS support................................ : $HAVE_OSS 721 740 echo \| Build with CoreAudio support.......................... : $HAVE_COREAUDIO 722 741 echo \| Build with PortAudio support.......................... : $HAVE_PA -
drivers/freebob/freebob_driver.c
old new 182 182 183 183 for (node = driver->capture_ports; node && node->data; 184 184 node = jack_slist_next (node)) { 185 jack_port_unregister (driver->client, 185 if(node->data != NULL) { 186 jack_port_unregister (driver->client, 186 187 ((jack_port_t *) node->data)); 188 } 187 189 } 188 190 189 191 jack_slist_free (driver->capture_ports); … … 191 193 192 194 for (node = driver->playback_ports; node && node->data; 193 195 node = jack_slist_next (node)) { 194 jack_port_unregister (driver->client, 196 if(node->data != NULL) { 197 jack_port_unregister (driver->client, 195 198 ((jack_port_t *) node->data)); 199 } 196 200 } 197 201 198 202 jack_slist_free (driver->playback_ports); -
drivers/Makefile.am
old new 30 30 FREEBOB_DIR = 31 31 endif 32 32 33 SUBDIRS = $(ALSA_DIR) dummy $(OSS_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) 34 DIST_SUBDIRS = alsa dummy oss portaudio coreaudio freebob 33 if HAVE_FIREWIRE 34 FIREWIRE_DIR = firewire 35 else 36 FIREWIRE_DIR = 37 endif 38 39 SUBDIRS = $(ALSA_DIR) dummy $(OSS_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) $(FIREWIRE_DIR) 40 DIST_SUBDIRS = alsa dummy oss portaudio coreaudio freebob firewire -
drivers/firewire/ffado_driver.h
old new 1 /* 2 * FireWire Backend for Jack 3 * using FFADO 4 * FFADO = Firewire (pro-)audio for linux 5 * 6 * http://www.ffado.org 7 * http://www.jackaudio.org 8 * 9 * Copyright (C) 2005-2007 Pieter Palmers 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 */ 25 26 /* 27 * Main Jack driver entry routines 28 * 29 */ 30 31 #ifndef __JACK_FFADO_DRIVER_H__ 32 #define __JACK_FFADO_DRIVER_H__ 33 34 #define FFADO_DRIVER_WITH_ASEQ_MIDI 35 36 #include <libffado/ffado.h> 37 38 #include <jack/driver.h> 39 #include <jack/engine.h> 40 #include <jack/types.h> 41 42 #include <string.h> 43 #include <stdlib.h> 44 #include <errno.h> 45 #include <stdio.h> 46 #include <poll.h> 47 #include <sys/time.h> 48 #include <netinet/in.h> 49 #include <endian.h> 50 51 #include <pthread.h> 52 #include <semaphore.h> 53 54 #include <jack/internal.h> 55 #include <jack/types.h> 56 #include <jack/ringbuffer.h> 57 #include <jack/driver.h> 58 #include <jack/engine.h> 59 #include <jack/types.h> 60 #include <jack/thread.h> 61 62 #include <alsa/asoundlib.h> 63 64 // debug print control flags 65 #define DEBUG_LEVEL_BUFFERS (1<<0) 66 #define DEBUG_LEVEL_HANDLERS (1<<1) 67 #define DEBUG_LEVEL_XRUN_RECOVERY (1<<2) 68 #define DEBUG_LEVEL_WAIT (1<<3) 69 70 #define DEBUG_LEVEL_RUN_CYCLE (1<<8) 71 72 #define DEBUG_LEVEL_PACKETCOUNTER (1<<16) 73 #define DEBUG_LEVEL_STARTUP (1<<17) 74 #define DEBUG_LEVEL_THREADS (1<<18) 75 76 77 #ifdef DEBUG_ENABLED 78 79 // default debug level 80 #define DEBUG_LEVEL ( DEBUG_LEVEL_RUN_CYCLE | \ 81 (DEBUG_LEVEL_XRUN_RECOVERY)| DEBUG_LEVEL_STARTUP | DEBUG_LEVEL_WAIT | DEBUG_LEVEL_PACKETCOUNTER) 82 83 #warning Building debug build! 84 85 #define printMessage(format, args...) jack_error( "FreeBoB MSG: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args ) 86 #define printError(format, args...) jack_error( "FreeBoB ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args ) 87 88 //#define printEnter() jack_error( "FBDRV ENTERS: %s (%s)\n", __FUNCTION__, __FILE__) 89 //#define printExit() jack_error( "FBDRV EXITS: %s (%s)\n", __FUNCTION__, __FILE__) 90 #define printEnter() 91 #define printExit() 92 93 #define debugError(format, args...) jack_error( "FREEBOB ERR: %s:%d (%s): " format, __FILE__, __LINE__, __FUNCTION__, ##args ) 94 #define debugPrint(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error("DEBUG %s:%d (%s) :" format, __FILE__, __LINE__, __FUNCTION__, ##args ); 95 #define debugPrintShort(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( format,##args ); 96 #define debugPrintWithTimeStamp(Level, format, args...) if(DEBUG_LEVEL & (Level)) jack_error( "%16lu: "format, debugGetCurrentUTime(),##args ); 97 #define SEGFAULT int *test=NULL; *test=1; 98 #else 99 #define DEBUG_LEVEL 100 101 #define printMessage(format, args...) if(g_verbose) \ 102 jack_error("FreeBoB MSG: " format, ##args ) 103 #define printError(format, args...) jack_error("FreeBoB ERR: " format, ##args ) 104 105 #define printEnter() 106 #define printExit() 107 108 #define debugError(format, args...) 109 #define debugPrint(Level, format, args...) 110 #define debugPrintShort(Level, format, args...) 111 #define debugPrintWithTimeStamp(Level, format, args...) 112 #endif 113 114 // thread priority setup 115 #define FFADO_RT_PRIORITY_PACKETIZER_RELATIVE 5 116 117 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 118 119 #define ALSA_SEQ_BUFF_SIZE 1024 120 #define MIDI_TRANSMIT_BUFFER_SIZE 1024 121 #define MIDI_THREAD_SLEEP_TIME_USECS 100 122 // midi priority should be higher than the audio priority in order to 123 // make sure events are not only delivered on period boundarys 124 // but I think it should be smaller than the packetizer thread in order not 125 // to lose any packets 126 #define FFADO_RT_PRIORITY_MIDI_RELATIVE 4 127 128 #endif 129 130 typedef struct _ffado_driver ffado_driver_t; 131 132 /* 133 * Jack Driver command line parameters 134 */ 135 136 typedef struct _ffado_jack_settings ffado_jack_settings_t; 137 struct _ffado_jack_settings { 138 int period_size_set; 139 jack_nframes_t period_size; 140 141 int sample_rate_set; 142 int sample_rate; 143 144 int buffer_size_set; 145 jack_nframes_t buffer_size; 146 147 int port_set; 148 int port; 149 150 int node_id_set; 151 int node_id; 152 153 int playback_ports; 154 int capture_ports; 155 156 int slave_mode; 157 int snoop_mode; 158 159 ffado_handle_t fb_handle; 160 }; 161 162 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 163 164 typedef struct { 165 int stream_nr; 166 int seq_port_nr; 167 snd_midi_event_t *parser; 168 snd_seq_t *seq_handle; 169 } ffado_midi_port_t; 170 171 typedef struct _ffado_driver_midi_handle { 172 ffado_device_t *dev; 173 ffado_driver_t *driver; 174 175 snd_seq_t *seq_handle; 176 177 pthread_t queue_thread; 178 pthread_t dequeue_thread; 179 int queue_thread_realtime; 180 int queue_thread_priority; 181 182 int nb_input_ports; 183 int nb_output_ports; 184 185 ffado_midi_port_t **input_ports; 186 ffado_midi_port_t **output_ports; 187 188 ffado_midi_port_t **input_stream_port_map; 189 int *output_port_stream_map; 190 191 192 } ffado_driver_midi_handle_t; 193 194 #endif 195 /* 196 * JACK driver structure 197 */ 198 199 200 struct _ffado_driver 201 { 202 JACK_DRIVER_NT_DECL 203 204 jack_nframes_t sample_rate; 205 jack_nframes_t period_size; 206 unsigned long wait_time; 207 208 jack_time_t wait_last; 209 jack_time_t wait_next; 210 int wait_late; 211 212 jack_client_t *client; 213 214 int xrun_detected; 215 int xrun_count; 216 217 int process_count; 218 219 /* settings from the command line */ 220 ffado_jack_settings_t settings; 221 222 /* the freebob virtual device */ 223 ffado_device_t *dev; 224 225 JSList *capture_ports; 226 JSList *playback_ports; 227 JSList *monitor_ports; 228 channel_t playback_nchannels; 229 channel_t capture_nchannels; 230 231 ffado_device_info_t device_info; 232 ffado_options_t device_options; 233 234 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 235 ffado_driver_midi_handle_t *midi_handle; 236 #endif 237 238 }; 239 240 241 242 #endif /* __JACK_FFADO_DRIVER_H__ */ 243 244 -
drivers/firewire/Makefile.am
old new 1 # plugin is called 'firewire', 2 # driver code is called 'ffado*' because it is an implementation 3 # of a firewire backend 4 5 MAINTAINERCLEANFILES=Makefile.in 6 7 AM_CFLAGS = $(JACK_CFLAGS) $(LIBFFADO_CFLAGS) $(ALSA_CFLAGS) 8 9 plugindir = $(ADDON_DIR) 10 11 plugin_LTLIBRARIES = jack_firewire.la 12 13 jack_firewire_la_SOURCES = ffado_driver.c 14 15 jack_firewire_la_LIBADD = $(LIBFFADO_LIBS) $(ALSA_LIBS) 16 17 jack_firewire_la_LDFLAGS = -module -avoid-version 18 19 noinst_HEADERS = ffado_driver.h 20 -
drivers/firewire/ffado_driver.c
old new 1 /* 2 * FireWire Backend for Jack 3 * using FFADO 4 * FFADO = Firewire (pro-)audio for linux 5 * 6 * http://www.ffado.org 7 * http://www.jackaudio.org 8 * 9 * Copyright (C) 2005-2007 Pieter Palmers 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24 */ 25 26 /* 27 * Main Jack driver entry routines 28 * 29 */ 30 31 #include <math.h> 32 #include <stdio.h> 33 #include <memory.h> 34 #include <unistd.h> 35 #include <stdlib.h> 36 #include <errno.h> 37 #include <stdarg.h> 38 #include <sys/mman.h> 39 40 #include <jack/types.h> 41 #include <jack/internal.h> 42 #include <jack/engine.h> 43 #include <sysdeps/time.h> 44 45 #include "ffado_driver.h" 46 47 #define SAMPLE_MAX_24BIT 8388608.0f 48 #define SAMPLE_MAX_16BIT 32768.0f 49 50 static int ffado_driver_stop (ffado_driver_t *driver); 51 52 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 53 static ffado_driver_midi_handle_t *ffado_driver_midi_init(ffado_driver_t *driver); 54 static void ffado_driver_midi_finish (ffado_driver_midi_handle_t *m); 55 static int ffado_driver_midi_start (ffado_driver_midi_handle_t *m); 56 static int ffado_driver_midi_stop (ffado_driver_midi_handle_t *m); 57 #endif 58 59 // enable verbose messages 60 static int g_verbose=0; 61 62 static int 63 ffado_driver_attach (ffado_driver_t *driver) 64 { 65 char buf[64]; 66 channel_t chn; 67 jack_port_t *port; 68 int port_flags; 69 70 g_verbose=driver->engine->verbose; 71 driver->device_options.verbose=g_verbose; 72 73 driver->engine->set_buffer_size (driver->engine, driver->period_size); 74 driver->engine->set_sample_rate (driver->engine, driver->sample_rate); 75 76 /* packetizer thread options */ 77 driver->device_options.realtime=(driver->engine->control->real_time? 1 : 0); 78 79 driver->device_options.packetizer_priority=driver->engine->control->client_priority + 80 FFADO_RT_PRIORITY_PACKETIZER_RELATIVE; 81 if (driver->device_options.packetizer_priority>98) { 82 driver->device_options.packetizer_priority=98; 83 } 84 85 driver->dev=ffado_streaming_init(&driver->device_info,driver->device_options); 86 87 if(!driver->dev) { 88 printError("Error creating FFADO streaming device"); 89 return -1; 90 } 91 92 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 93 driver->midi_handle=ffado_driver_midi_init(driver); 94 if(!driver->midi_handle) { 95 printError("-----------------------------------------------------------"); 96 printError("Error creating midi device!"); 97 printError("The FireWire backend will run without MIDI support."); 98 printError("Consult the above error messages to solve the problem. "); 99 printError("-----------------------------------------------------------\n\n"); 100 } 101 #endif 102 103 if (driver->device_options.realtime) { 104 printMessage("Streaming thread running with Realtime scheduling, priority %d", 105 driver->device_options.packetizer_priority); 106 } else { 107 printMessage("Streaming thread running without Realtime scheduling"); 108 } 109 110 /* ports */ 111 port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal; 112 113 driver->capture_nchannels=ffado_streaming_get_nb_capture_streams(driver->dev); 114 115 for (chn = 0; chn < driver->capture_nchannels; chn++) { 116 117 ffado_streaming_get_capture_stream_name(driver->dev, chn, buf, sizeof(buf) - 1); 118 119 if(ffado_streaming_get_capture_stream_type(driver->dev, chn) != ffado_stream_type_audio) { 120 printMessage ("Don't register capture port %s", buf); 121 122 // we have to add a NULL entry in the list to be able to loop over the channels in the read/write routines 123 driver->capture_ports = 124 jack_slist_append (driver->capture_ports, NULL); 125 } else { 126 printMessage ("Registering capture port %s", buf); 127 if ((port = jack_port_register (driver->client, buf, 128 JACK_DEFAULT_AUDIO_TYPE, 129 port_flags, 0)) == NULL) { 130 printError (" cannot register port for %s", buf); 131 break; 132 } 133 driver->capture_ports = 134 jack_slist_append (driver->capture_ports, port); 135 // setup port parameters 136 if(ffado_streaming_set_capture_buffer_type(driver->dev, chn, ffado_buffer_type_float)) { 137 printError(" cannot set port buffer type for %s", buf); 138 } 139 if (ffado_streaming_set_capture_stream_buffer(driver->dev, chn, NULL)) { 140 printError(" cannot configure initial port buffer for %s", buf); 141 } 142 if(ffado_streaming_capture_stream_onoff(driver->dev, chn, 1)) { 143 printError(" cannot enable port %s", buf); 144 } 145 } 146 // jack_port_set_latency (port, driver->period_size); 147 148 } 149 150 port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal; 151 152 driver->playback_nchannels=ffado_streaming_get_nb_playback_streams(driver->dev); 153 154 for (chn = 0; chn < driver->playback_nchannels; chn++) { 155 156 ffado_streaming_get_playback_stream_name(driver->dev, chn, buf, sizeof(buf) - 1); 157 158 if(ffado_streaming_get_playback_stream_type(driver->dev, chn) != ffado_stream_type_audio) { 159 printMessage ("Don't register playback port %s", buf); 160 161 // we have to add a NULL entry in the list to be able to loop over the channels in the read/write routines 162 driver->playback_ports = 163 jack_slist_append (driver->playback_ports, NULL); 164 } else { 165 printMessage ("Registering playback port %s", buf); 166 if ((port = jack_port_register (driver->client, buf, 167 JACK_DEFAULT_AUDIO_TYPE, 168 port_flags, 0)) == NULL) { 169 printError(" cannot register port for %s", buf); 170 break; 171 } 172 driver->playback_ports = 173 jack_slist_append (driver->playback_ports, port); 174 175 // setup port parameters 176 if(ffado_streaming_set_playback_buffer_type(driver->dev, chn, ffado_buffer_type_float)) { 177 printError(" cannot set port buffer type for %s", buf); 178 } 179 if (ffado_streaming_set_playback_stream_buffer(driver->dev, chn, NULL)) { 180 printError(" cannot configure initial port buffer for %s", buf); 181 } 182 if(ffado_streaming_playback_stream_onoff(driver->dev, chn, 1)) { 183 printError(" cannot enable port %s", buf); 184 } 185 } 186 // jack_port_set_latency (port, (driver->period_size * (driver->user_nperiods - 1)) + driver->playback_frame_latency); 187 188 } 189 190 if(!ffado_streaming_prepare(driver->dev)) { 191 printError("Could not prepare streaming device!"); 192 return -1; 193 } 194 195 196 return jack_activate (driver->client); 197 } 198 199 static int 200 ffado_driver_detach (ffado_driver_t *driver) 201 { 202 JSList *node; 203 204 if (driver->engine == NULL) { 205 return 0; 206 } 207 208 for (node = driver->capture_ports; node; 209 node = jack_slist_next (node)) { 210 // Don't try to unregister NULL entries added for non-audio 211 // ffado ports by ffado_driver_attach(). 212 if (node->data != NULL) { 213 jack_port_unregister (driver->client, 214 ((jack_port_t *) node->data)); 215 } 216 } 217 218 jack_slist_free (driver->capture_ports); 219 driver->capture_ports = 0; 220 221 for (node = driver->playback_ports; node; 222 node = jack_slist_next (node)) { 223 if (node->data != NULL) { 224 jack_port_unregister (driver->client, 225 ((jack_port_t *) node->data)); 226 } 227 } 228 229 jack_slist_free (driver->playback_ports); 230 driver->playback_ports = 0; 231 232 ffado_streaming_finish(driver->dev); 233 driver->dev=NULL; 234 235 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 236 if(driver->midi_handle) { 237 ffado_driver_midi_finish(driver->midi_handle); 238 } 239 driver->midi_handle=NULL; 240 #endif 241 242 return 0; 243 } 244 245 static inline void 246 ffado_driver_read_from_channel (ffado_driver_t *driver, 247 channel_t channel, 248 jack_default_audio_sample_t *dst, 249 jack_nframes_t nsamples) 250 { 251 252 ffado_sample_t buffer[nsamples]; 253 char *src=(char *)buffer; 254 255 ffado_streaming_read(driver->dev, channel, buffer, nsamples); 256 257 /* ALERT: signed sign-extension portability !!! */ 258 259 while (nsamples--) { 260 int x; 261 #if __BYTE_ORDER == __LITTLE_ENDIAN 262 memcpy((char*)&x + 1, src, 3); 263 #elif __BYTE_ORDER == __BIG_ENDIAN 264 memcpy(&x, src, 3); 265 #endif 266 x >>= 8; 267 *dst = x / SAMPLE_MAX_24BIT; 268 dst++; 269 src += sizeof(ffado_sample_t); 270 } 271 272 } 273 274 static int 275 ffado_driver_read (ffado_driver_t * driver, jack_nframes_t nframes) 276 { 277 jack_default_audio_sample_t* buf; 278 channel_t chn; 279 JSList *node; 280 jack_port_t* port; 281 282 ffado_sample_t nullbuffer[nframes]; 283 284 ffado_streaming_stream_type stream_type; 285 286 printEnter(); 287 288 for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) { 289 stream_type = ffado_streaming_get_capture_stream_type(driver->dev, chn); 290 if(stream_type == ffado_stream_type_audio) { 291 port = (jack_port_t *) node->data; 292 293 buf = jack_port_get_buffer (port, nframes); 294 if(!buf) buf=(jack_default_audio_sample_t*)nullbuffer; 295 296 ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buf)); 297 } 298 } 299 300 // now transfer the buffers 301 ffado_streaming_transfer_capture_buffers(driver->dev); 302 303 printExit(); 304 305 return 0; 306 307 } 308 309 static inline void 310 ffado_driver_write_to_channel (ffado_driver_t *driver, 311 channel_t channel, 312 jack_default_audio_sample_t *buf, 313 jack_nframes_t nsamples) 314 { 315 long long y; 316 ffado_sample_t buffer[nsamples]; 317 unsigned int i=0; 318 char *dst=(char *)buffer; 319 320 // convert from float to integer 321 for(;i<nsamples;i++) { 322 y = (long long)(*buf * SAMPLE_MAX_24BIT); 323 324 if (y > (INT_MAX >> 8 )) { 325 y = (INT_MAX >> 8); 326 } else if (y < (INT_MIN >> 8 )) { 327 y = (INT_MIN >> 8 ); 328 } 329 #if __BYTE_ORDER == __LITTLE_ENDIAN 330 memcpy (dst, &y, 3); 331 #elif __BYTE_ORDER == __BIG_ENDIAN 332 memcpy (dst, (char *)&y + 5, 3); 333 #endif 334 dst += sizeof(ffado_sample_t); 335 buf++; 336 } 337 338 // write to the ffado streaming device 339 ffado_streaming_write(driver->dev, channel, buffer, nsamples); 340 341 } 342 343 static int 344 ffado_driver_write (ffado_driver_t * driver, jack_nframes_t nframes) 345 { 346 channel_t chn; 347 JSList *node; 348 jack_default_audio_sample_t* buf; 349 350 jack_port_t *port; 351 352 ffado_streaming_stream_type stream_type; 353 354 ffado_sample_t nullbuffer[nframes]; 355 356 memset(&nullbuffer,0,nframes*sizeof(ffado_sample_t)); 357 358 printEnter(); 359 360 driver->process_count++; 361 362 assert(driver->dev); 363 364 if (driver->engine->freewheeling) { 365 return 0; 366 } 367 368 for (chn = 0, node = driver->playback_ports; node; node = jack_slist_next (node), chn++) { 369 stream_type=ffado_streaming_get_playback_stream_type(driver->dev, chn); 370 if(stream_type == ffado_stream_type_audio) { 371 port = (jack_port_t *) node->data; 372 373 buf = jack_port_get_buffer (port, nframes); 374 if(!buf) buf=(jack_default_audio_sample_t*)nullbuffer; 375 376 ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buf)); 377 } 378 } 379 380 ffado_streaming_transfer_playback_buffers(driver->dev); 381 382 printExit(); 383 384 return 0; 385 } 386 387 //static inline jack_nframes_t 388 static jack_nframes_t 389 ffado_driver_wait (ffado_driver_t *driver, int extra_fd, int *status, 390 float *delayed_usecs) 391 { 392 int nframes; 393 jack_time_t wait_enter; 394 jack_time_t wait_ret; 395 396 printEnter(); 397 398 wait_enter = jack_get_microseconds (); 399 if (wait_enter > driver->wait_next) { 400 /* 401 * This processing cycle was delayed past the 402 * next due interrupt! Do not account this as 403 * a wakeup delay: 404 */ 405 driver->wait_next = 0; 406 driver->wait_late++; 407 } 408 // *status = -2; interrupt 409 // *status = -3; timeout 410 // *status = -4; extra FD 411 412 nframes=ffado_streaming_wait(driver->dev); 413 414 wait_ret = jack_get_microseconds (); 415 416 if (driver->wait_next && wait_ret > driver->wait_next) { 417 *delayed_usecs = wait_ret - driver->wait_next; 418 } 419 driver->wait_last = wait_ret; 420 driver->wait_next = wait_ret + driver->period_usecs; 421 driver->engine->transport_cycle_start (driver->engine, wait_ret); 422 423 // transfer the streaming buffers 424 // we now do this in the read/write functions 425 // ffado_streaming_transfer_buffers(driver->dev); 426 427 if (nframes < 0) { 428 *status=0; 429 430 return 0; 431 //nframes=driver->period_size; //debug 432 } 433 434 *status = 0; 435 driver->last_wait_ust = wait_ret; 436 437 // FIXME: this should do something more usefull 438 *delayed_usecs = 0; 439 440 printExit(); 441 442 return nframes - nframes % driver->period_size; 443 444 } 445 446 static int 447 ffado_driver_run_cycle (ffado_driver_t *driver) 448 { 449 jack_engine_t *engine = driver->engine; 450 int wait_status=0; 451 float delayed_usecs=0.0; 452 453 jack_nframes_t nframes = ffado_driver_wait (driver, -1, 454 &wait_status, &delayed_usecs); 455 456 if ((wait_status < 0)) { 457 printError( "wait status < 0! (= %d)",wait_status); 458 return -1; 459 } 460 461 if ((nframes == 0)) { 462 /* we detected an xrun and restarted: notify 463 * clients about the delay. */ 464 printMessage("xrun detected"); 465 engine->delay (engine, delayed_usecs); 466 return 0; 467 } 468 469 return engine->run_cycle (engine, nframes, delayed_usecs); 470 471 } 472 /* 473 * in a null cycle we should discard the input and write silence to the outputs 474 */ 475 static int 476 ffado_driver_null_cycle (ffado_driver_t* driver, jack_nframes_t nframes) 477 { 478 channel_t chn; 479 JSList *node; 480 snd_pcm_sframes_t nwritten; 481 482 ffado_streaming_stream_type stream_type; 483 484 jack_default_audio_sample_t buff[nframes]; 485 jack_default_audio_sample_t* buffer=(jack_default_audio_sample_t*)buff; 486 487 printEnter(); 488 489 memset(buffer,0,nframes*sizeof(jack_default_audio_sample_t)); 490 491 assert(driver->dev); 492 493 if (driver->engine->freewheeling) { 494 return 0; 495 } 496 497 // write silence to buffer 498 nwritten = 0; 499 500 for (chn = 0, node = driver->playback_ports; node; node = jack_slist_next (node), chn++) { 501 stream_type=ffado_streaming_get_playback_stream_type(driver->dev, chn); 502 503 if(stream_type == ffado_stream_type_audio) { 504 ffado_streaming_set_playback_stream_buffer(driver->dev, chn, (char *)(buffer)); 505 } 506 } 507 508 ffado_streaming_transfer_playback_buffers(driver->dev); 509 510 // read & discard from input ports 511 for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) { 512 stream_type=ffado_streaming_get_capture_stream_type(driver->dev, chn); 513 if(stream_type == ffado_stream_type_audio) { 514 ffado_streaming_set_capture_stream_buffer(driver->dev, chn, (char *)(buffer)); 515 } 516 } 517 518 // now transfer the buffers 519 ffado_streaming_transfer_capture_buffers(driver->dev); 520 521 printExit(); 522 return 0; 523 } 524 525 static int 526 ffado_driver_start (ffado_driver_t *driver) 527 { 528 int retval=0; 529 530 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 531 if(driver->midi_handle) { 532 if((retval=ffado_driver_midi_start(driver->midi_handle))) { 533 printError("Could not start MIDI threads"); 534 return retval; 535 } 536 } 537 #endif 538 539 if((retval=ffado_streaming_start(driver->dev))) { 540 printError("Could not start streaming threads"); 541 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 542 if(driver->midi_handle) { 543 ffado_driver_midi_stop(driver->midi_handle); 544 } 545 #endif 546 return retval; 547 } 548 549 return 0; 550 551 } 552 553 static int 554 ffado_driver_stop (ffado_driver_t *driver) 555 { 556 int retval=0; 557 558 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 559 if(driver->midi_handle) { 560 if((retval=ffado_driver_midi_stop(driver->midi_handle))) { 561 printError("Could not stop MIDI threads"); 562 return retval; 563 } 564 } 565 #endif 566 if((retval=ffado_streaming_stop(driver->dev))) { 567 printError("Could not stop streaming threads"); 568 return retval; 569 } 570 571 return 0; 572 } 573 574 575 static int 576 ffado_driver_bufsize (ffado_driver_t* driver, jack_nframes_t nframes) 577 { 578 printError("Buffer size change requested but not supported!!!"); 579 580 /* 581 driver->period_size = nframes; 582 driver->period_usecs = 583 (jack_time_t) floor ((((float) nframes) / driver->sample_rate) 584 * 1000000.0f); 585 */ 586 587 /* tell the engine to change its buffer size */ 588 //driver->engine->set_buffer_size (driver->engine, nframes); 589 590 return -1; // unsupported 591 } 592 593 typedef void (*JackDriverFinishFunction) (jack_driver_t *); 594 595 ffado_driver_t * 596 ffado_driver_new (jack_client_t * client, 597 char *name, 598 ffado_jack_settings_t *params) 599 { 600 ffado_driver_t *driver; 601 602 assert(params); 603 604 if(ffado_get_api_version() != 2) { 605 printError("Incompatible libffado version! (%s)", ffado_get_version()); 606 return NULL; 607 } 608 609 printMessage("Starting Freebob backend (%s)", ffado_get_version()); 610 611 driver = calloc (1, sizeof (ffado_driver_t)); 612 613 /* Setup the jack interfaces */ 614 jack_driver_nt_init ((jack_driver_nt_t *) driver); 615 616 driver->nt_attach = (JackDriverNTAttachFunction) ffado_driver_attach; 617 driver->nt_detach = (JackDriverNTDetachFunction) ffado_driver_detach; 618 driver->nt_start = (JackDriverNTStartFunction) ffado_driver_start; 619 driver->nt_stop = (JackDriverNTStopFunction) ffado_driver_stop; 620 driver->nt_run_cycle = (JackDriverNTRunCycleFunction) ffado_driver_run_cycle; 621 driver->null_cycle = (JackDriverNullCycleFunction) ffado_driver_null_cycle; 622 driver->write = (JackDriverReadFunction) ffado_driver_write; 623 driver->read = (JackDriverReadFunction) ffado_driver_read; 624 driver->nt_bufsize = (JackDriverNTBufSizeFunction) ffado_driver_bufsize; 625 626 /* copy command line parameter contents to the driver structure */ 627 memcpy(&driver->settings,params,sizeof(ffado_jack_settings_t)); 628 629 /* prepare all parameters */ 630 driver->sample_rate = params->sample_rate; 631 driver->period_size = params->period_size; 632 driver->last_wait_ust = 0; 633 634 driver->period_usecs = 635 (jack_time_t) floor ((((float) driver->period_size) * 1000000.0f) / driver->sample_rate); 636 637 driver->client = client; 638 driver->engine = NULL; 639 640 memset(&driver->device_options,0,sizeof(driver->device_options)); 641 driver->device_options.sample_rate=params->sample_rate; 642 driver->device_options.period_size=params->period_size; 643 driver->device_options.nb_buffers=params->buffer_size; 644 driver->device_options.node_id=params->node_id; 645 driver->device_options.port=params->port; 646 driver->device_options.slave_mode=params->slave_mode; 647 driver->device_options.snoop_mode=params->snoop_mode; 648 649 if(!params->capture_ports) { 650 driver->device_options.directions |= FFADO_IGNORE_CAPTURE; 651 } 652 653 if(!params->playback_ports) { 654 driver->device_options.directions |= FFADO_IGNORE_PLAYBACK; 655 } 656 657 debugPrint(DEBUG_LEVEL_STARTUP, " Driver compiled on %s %s", __DATE__, __TIME__); 658 debugPrint(DEBUG_LEVEL_STARTUP, " Created driver %s", name); 659 debugPrint(DEBUG_LEVEL_STARTUP, " period_size: %d", driver->period_size); 660 debugPrint(DEBUG_LEVEL_STARTUP, " period_usecs: %d", driver->period_usecs); 661 debugPrint(DEBUG_LEVEL_STARTUP, " sample rate: %d", driver->sample_rate); 662 663 return (ffado_driver_t *) driver; 664 665 } 666 667 static void 668 ffado_driver_delete (ffado_driver_t *driver) 669 { 670 jack_driver_nt_finish ((jack_driver_nt_t *) driver); 671 free (driver); 672 } 673 674 #ifdef FFADO_DRIVER_WITH_ASEQ_MIDI 675 /* 676 * MIDI support 677 */ 678 679 // the thread that will queue the midi events from the seq to the stream buffers 680 681 void * ffado_driver_midi_queue_thread(void *arg) 682 { 683 ffado_driver_midi_handle_t *m=(ffado_driver_midi_handle_t *)arg; 684 assert(m); 685 snd_seq_event_t *ev; 686 unsigned char work_buffer[MIDI_TRANSMIT_BUFFER_SIZE]; 687 int bytes_to_send; 688 int b; 689 int i; 690 691 printMessage("MIDI queue thread started"); 692 693 while(1) { 694 // get next event, if one is present 695 while ((snd_seq_event_input(m->seq_handle, &ev) > 0)) { 696 // get the port this event is originated from 697 ffado_midi_port_t *port=NULL; 698 for (i=0;i<m->nb_output_ports;i++) { 699 if(m->output_ports[i]->seq_port_nr == ev->dest.port) { 700 port=m->output_ports[i]; 701 break; 702 } 703 } 704 705 if(!port) { 706 printError(" Could not find target port for event: dst=%d src=%d", ev->dest.port, ev->source.port); 707 708 break; 709 } 710 711 // decode it to the work buffer 712 if((bytes_to_send = snd_midi_event_decode ( port->parser, 713 work_buffer, 714 MIDI_TRANSMIT_BUFFER_SIZE, 715 ev))<0) 716 { // failed 717 printError(" Error decoding event for port %d (errcode=%d)", port->seq_port_nr,bytes_to_send); 718 bytes_to_send=0; 719 //return -1; 720 } 721 722 for(b=0;b<bytes_to_send;b++) { 723 ffado_sample_t tmp_event=work_buffer[b]; 724 if(ffado_streaming_write(m->dev, port->stream_nr, &tmp_event, 1)<1) { 725 printError(" Midi send buffer overrun"); 726 } 727 } 728 729 } 730 731 // sleep for some time 732 usleep(MIDI_THREAD_SLEEP_TIME_USECS); 733 } 734 return NULL; 735 } 736 737 // the dequeue thread (maybe we need one thread per stream) 738 void *ffado_driver_midi_dequeue_thread (void *arg) { 739 ffado_driver_midi_handle_t *m=(ffado_driver_midi_handle_t *)arg; 740 741 int i; 742 int s; 743 744 int samples_read; 745 746 assert(m); 747 748 while(1) { 749 // read incoming events 750 751 for (i=0;i<m->nb_input_ports;i++) { 752 unsigned int buff[64]; 753 754 ffado_midi_port_t *port=m->input_ports[i]; 755 756 if(!port) { 757 printError(" something went wrong when setting up the midi input port map (%d)",i); 758 } 759 760 do { 761 samples_read=ffado_streaming_read(m->dev, port->stream_nr, buff, 64); 762 763 for (s=0;s<samples_read;s++) { 764 unsigned int *byte=(buff+s) ; 765 snd_seq_event_t ev; 766 if ((snd_midi_event_encode_byte(port->parser,(*byte) & 0xFF, &ev)) > 0) { 767 // a midi message is complete, send it out to ALSA 768 snd_seq_ev_set_subs(&ev); 769 snd_seq_ev_set_direct(&ev); 770 snd_seq_ev_set_source(&ev, port->seq_port_nr); 771 snd_seq_event_output_direct(port->seq_handle, &ev); 772 } 773 } 774 } while (samples_read>0); 775 } 776 777 // sleep for some time 778 usleep(MIDI_THREAD_SLEEP_TIME_USECS); 779 } 780 return NULL; 781 } 782 783 static ffado_driver_midi_handle_t *ffado_driver_midi_init(ffado_driver_t *driver) { 784 // int err; 785 786 char buf[256]; 787 channel_t chn; 788 int nchannels; 789 int i=0; 790 791 ffado_device_t *dev=driver->dev; 792 793 assert(dev); 794 795 ffado_driver_midi_handle_t *m=calloc(1,sizeof(ffado_driver_midi_handle_t)); 796 if (!m) { 797 printError("not enough memory to create midi structure"); 798 return NULL; 799 } 800 801 if (snd_seq_open(&m->seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) { 802 printError("Error opening ALSA sequencer."); 803 free(m); 804 return NULL; 805 } 806 807 snd_seq_set_client_name(m->seq_handle, "FreeBoB Jack MIDI"); 808 809 // find out the number of midi in/out ports we need to setup 810 nchannels=ffado_streaming_get_nb_capture_streams(dev); 811 812 m->nb_input_ports=0; 813 814 for (chn = 0; chn < nchannels; chn++) { 815 if(ffado_streaming_get_capture_stream_type(dev, chn) == ffado_stream_type_midi) { 816 m->nb_input_ports++; 817 } 818 } 819 820 m->input_ports=calloc(m->nb_input_ports,sizeof(ffado_midi_port_t *)); 821 if(!m->input_ports) { 822 printError("not enough memory to create midi structure"); 823 free(m); 824 return NULL; 825 } 826 827 i=0; 828 for (chn = 0; chn < nchannels; chn++) { 829 if(ffado_streaming_get_capture_stream_type(dev, chn) == ffado_stream_type_midi) { 830 m->input_ports[i]=calloc(1,sizeof(ffado_midi_port_t)); 831 if(!m->input_ports[i]) { 832 // fixme 833 printError("Could not allocate memory for seq port"); 834 continue; 835 } 836 837 ffado_streaming_get_capture_stream_name(dev, chn, buf, sizeof(buf) - 1); 838 printMessage("Register MIDI IN port %s", buf); 839 840 m->input_ports[i]->seq_port_nr=snd_seq_create_simple_port(m->seq_handle, buf, 841 SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, 842 SND_SEQ_PORT_TYPE_MIDI_GENERIC); 843 844 if(m->input_ports[i]->seq_port_nr<0) { 845 printError("Could not create seq port"); 846 m->input_ports[i]->stream_nr=-1; 847 m->input_ports[i]->seq_port_nr=-1; 848 } else { 849 m->input_ports[i]->stream_nr=chn; 850 m->input_ports[i]->seq_handle=m->seq_handle; 851 if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->input_ports[i]->parser)) < 0) { 852 printError("could not init parser for MIDI IN port %d",i); 853 m->input_ports[i]->stream_nr=-1; 854 m->input_ports[i]->seq_port_nr=-1; 855 } else { 856 if(ffado_streaming_set_capture_buffer_type(dev, chn, ffado_buffer_type_midi)) { 857 printError(" cannot set port buffer type for %s", buf); 858 m->input_ports[i]->stream_nr=-1; 859 m->input_ports[i]->seq_port_nr=-1; 860 } 861 if(ffado_streaming_capture_stream_onoff(dev, chn, 1)) { 862 printError(" cannot enable port %s", buf); 863 m->input_ports[i]->stream_nr=-1; 864 m->input_ports[i]->seq_port_nr=-1; 865 } 866 867 } 868 } 869 870 i++; 871 } 872 } 873 874 // playback 875 nchannels=ffado_streaming_get_nb_playback_streams(dev); 876 877 m->nb_output_ports=0; 878 879 for (chn = 0; chn < nchannels; chn++) { 880 if(ffado_streaming_get_playback_stream_type(dev, chn) == ffado_stream_type_midi) { 881 m->nb_output_ports++; 882 } 883 } 884 885 m->output_ports=calloc(m->nb_output_ports,sizeof(ffado_midi_port_t *)); 886 if(!m->output_ports) { 887 printError("not enough memory to create midi structure"); 888 for (i = 0; i < m->nb_input_ports; i++) { 889 free(m->input_ports[i]); 890 } 891 free(m->input_ports); 892 free(m); 893 return NULL; 894 } 895 896 i=0; 897 for (chn = 0; chn < nchannels; chn++) { 898 if(ffado_streaming_get_playback_stream_type(dev, chn) == ffado_stream_type_midi) { 899 m->output_ports[i]=calloc(1,sizeof(ffado_midi_port_t)); 900 if(!m->output_ports[i]) { 901 // fixme 902 printError("Could not allocate memory for seq port"); 903 continue; 904 } 905 906 ffado_streaming_get_playback_stream_name(dev, chn, buf, sizeof(buf) - 1); 907 printMessage("Register MIDI OUT port %s", buf); 908 909 m->output_ports[i]->seq_port_nr=snd_seq_create_simple_port(m->seq_handle, buf, 910 SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, 911 SND_SEQ_PORT_TYPE_MIDI_GENERIC); 912 913 914 if(m->output_ports[i]->seq_port_nr<0) { 915 printError("Could not create seq port"); 916 m->output_ports[i]->stream_nr=-1; 917 m->output_ports[i]->seq_port_nr=-1; 918 } else { 919 m->output_ports[i]->stream_nr=chn; 920 m->output_ports[i]->seq_handle=m->seq_handle; 921 if (snd_midi_event_new ( ALSA_SEQ_BUFF_SIZE, &(m->output_ports[i]->parser)) < 0) { 922 printError("could not init parser for MIDI OUT port %d",i); 923 m->output_ports[i]->stream_nr=-1; 924 m->output_ports[i]->seq_port_nr=-1; 925 } else { 926 if(ffado_streaming_set_playback_buffer_type(dev, chn, ffado_buffer_type_midi)) { 927 printError(" cannot set port buffer type for %s", buf); 928 m->input_ports[i]->stream_nr=-1; 929 m->input_ports[i]->seq_port_nr=-1; 930 } 931 if(ffado_streaming_playback_stream_onoff(dev, chn, 1)) { 932 printError(" cannot enable port %s", buf); 933 m->input_ports[i]->stream_nr=-1; 934 m->input_ports[i]->seq_port_nr=-1; 935 } 936 } 937 } 938 939 i++; 940 } 941 } 942 943 m->dev=dev; 944 m->driver=driver; 945 946 return m; 947 } 948 949 static int 950 ffado_driver_midi_start (ffado_driver_midi_handle_t *m) 951 { 952 assert(m); 953 // start threads 954 955 m->queue_thread_realtime=(m->driver->engine->control->real_time? 1 : 0); 956 m->queue_thread_priority= 957 m->driver->engine->control->client_priority + 958 FFADO_RT_PRIORITY_MIDI_RELATIVE; 959 960 if (m->queue_thread_priority>98) { 961 m->queue_thread_priority=98; 962 } 963 if (m->queue_thread_realtime) { 964 printMessage("MIDI threads running with Realtime scheduling, priority %d", 965 m->queue_thread_priority); 966 } else { 967 printMessage("MIDI threads running without Realtime scheduling"); 968 } 969 970 if (jack_client_create_thread(NULL, &m->queue_thread, m->queue_thread_priority, m->queue_thread_realtime, ffado_driver_midi_queue_thread, (void *)m)) { 971 printError(" cannot create midi queueing thread"); 972 return -1; 973 } 974 975 if (jack_client_create_thread(NULL, &m->dequeue_thread, m->queue_thread_priority, m->queue_thread_realtime, ffado_driver_midi_dequeue_thread, (void *)m)) { 976 printError(" cannot create midi dequeueing thread"); 977 return -1; 978 } 979 return 0; 980 } 981 982 static int 983 ffado_driver_midi_stop (ffado_driver_midi_handle_t *m) 984 { 985 assert(m); 986 987 pthread_cancel (m->queue_thread); 988 pthread_join (m->queue_thread, NULL); 989 990 pthread_cancel (m->dequeue_thread); 991 pthread_join (m->dequeue_thread, NULL); 992 return 0; 993 994 } 995 996 static void 997 ffado_driver_midi_finish (ffado_driver_midi_handle_t *m) 998 { 999 assert(m); 1000 1001 int i; 1002 // TODO: add state info here, if not stopped then stop 1003 1004 for (i=0;i<m->nb_input_ports;i++) { 1005 free(m->input_ports[i]); 1006 1007 } 1008 free(m->input_ports); 1009 1010 for (i=0;i<m->nb_output_ports;i++) { 1011 free(m->output_ports[i]); 1012 } 1013 free(m->output_ports); 1014 1015 free(m); 1016 } 1017 #endif 1018 /* 1019 * dlopen plugin stuff 1020 */ 1021 1022 const char driver_client_name[] = "firewire_pcm"; 1023 1024 const jack_driver_desc_t * 1025 driver_get_descriptor () 1026 { 1027 jack_driver_desc_t * desc; 1028 jack_driver_param_desc_t * params; 1029 unsigned int i; 1030 1031 desc = calloc (1, sizeof (jack_driver_desc_t)); 1032 1033 strcpy (desc->name, "firewire"); 1034 desc->nparams = 8; 1035 1036 params = calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); 1037 desc->params = params; 1038 1039 i = 0; 1040 strcpy (params[i].name, "device"); 1041 params[i].character = 'd'; 1042 params[i].type = JackDriverParamString; 1043 strcpy (params[i].value.str, "hw:0"); 1044 strcpy (params[i].short_desc, "The FireWire device to use. Format is: 'hw:port[,node]'."); 1045 strcpy (params[i].long_desc, params[i].short_desc); 1046 1047 i++; 1048 strcpy (params[i].name, "period"); 1049 params[i].character = 'p'; 1050 params[i].type = JackDriverParamUInt; 1051 params[i].value.ui = 1024; 1052 strcpy (params[i].short_desc, "Frames per period"); 1053 strcpy (params[i].long_desc, params[i].short_desc); 1054 1055 i++; 1056 strcpy (params[i].name, "nperiods"); 1057 params[i].character = 'n'; 1058 params[i].type = JackDriverParamUInt; 1059 params[i].value.ui = 3; 1060 strcpy (params[i].short_desc, "Number of periods of playback latency"); 1061 strcpy (params[i].long_desc, params[i].short_desc); 1062 1063 i++; 1064 strcpy (params[i].name, "rate"); 1065 params[i].character = 'r'; 1066 params[i].type = JackDriverParamUInt; 1067 params[i].value.ui = 48000U; 1068 strcpy (params[i].short_desc, "Sample rate"); 1069 strcpy (params[i].long_desc, params[i].short_desc); 1070 1071 i++; 1072 strcpy (params[i].name, "capture"); 1073 params[i].character = 'i'; 1074 params[i].type = JackDriverParamUInt; 1075 params[i].value.ui = 1U; 1076 strcpy (params[i].short_desc, "Provide capture ports."); 1077 strcpy (params[i].long_desc, params[i].short_desc); 1078 1079 i++; 1080 strcpy (params[i].name, "playback"); 1081 params[i].character = 'o'; 1082 params[i].type = JackDriverParamUInt; 1083 params[i].value.ui = 1U; 1084 strcpy (params[i].short_desc, "Provide playback ports."); 1085 strcpy (params[i].long_desc, params[i].short_desc); 1086 1087 i++; 1088 strcpy (params[i].name, "slave"); 1089 params[i].character = 'x'; 1090 params[i].type = JackDriverParamUInt; 1091 params[i].value.ui = 0U; 1092 strcpy (params[i].short_desc, "Act as a BounceDevice slave"); 1093 strcpy (params[i].long_desc, params[i].short_desc); 1094 1095 i++; 1096 strcpy (params[i].name, "slave"); 1097 params[i].character = 'X'; 1098 params[i].type = JackDriverParamUInt; 1099 params[i].value.ui = 0U; 1100 strcpy (params[i].short_desc, "Operate in snoop mode"); 1101 strcpy (params[i].long_desc, params[i].short_desc); 1102 1103 return desc; 1104 } 1105 1106 1107 jack_driver_t * 1108 driver_initialize (jack_client_t *client, JSList * params) 1109 { 1110 jack_driver_t *driver; 1111 1112 unsigned int port=0; 1113 unsigned int node_id=-1; 1114 int nbitems; 1115 1116 const JSList * node; 1117 const jack_driver_param_t * param; 1118 1119 ffado_jack_settings_t cmlparams; 1120 1121 char *device_name="hw:0"; 1122 1123 cmlparams.period_size_set=0; 1124 cmlparams.sample_rate_set=0; 1125 cmlparams.buffer_size_set=0; 1126 cmlparams.port_set=0; 1127 cmlparams.node_id_set=0; 1128 1129 /* default values */ 1130 cmlparams.period_size=1024; 1131 cmlparams.sample_rate=48000; 1132 cmlparams.buffer_size=3; 1133 cmlparams.port=0; 1134 cmlparams.node_id=-1; 1135 cmlparams.playback_ports=1; 1136 cmlparams.capture_ports=1; 1137 cmlparams.slave_mode=0; 1138 cmlparams.snoop_mode=0; 1139 1140 for (node = params; node; node = jack_slist_next (node)) 1141 { 1142 param = (jack_driver_param_t *) node->data; 1143 1144 switch (param->character) 1145 { 1146 case 'd': 1147 device_name = strdup (param->value.str); 1148 break; 1149 case 'p': 1150 cmlparams.period_size = param->value.ui; 1151 cmlparams.period_size_set = 1; 1152 break; 1153 case 'n': 1154 cmlparams.buffer_size = param->value.ui; 1155 cmlparams.buffer_size_set = 1; 1156 break; 1157 case 'r': 1158 cmlparams.sample_rate = param->value.ui; 1159 cmlparams.sample_rate_set = 1; 1160 break; 1161 case 'i': 1162 cmlparams.capture_ports = param->value.ui; 1163 break; 1164 case 'o': 1165 cmlparams.playback_ports = param->value.ui; 1166 break; 1167 case 'x': 1168 cmlparams.slave_mode = param->value.ui; 1169 break; 1170 case 'X': 1171 cmlparams.snoop_mode = param->value.ui; 1172 break; 1173 } 1174 } 1175 1176 nbitems=sscanf(device_name,"hw:%u,%u",&port,&node_id); 1177 if (nbitems<2) { 1178 nbitems=sscanf(device_name,"hw:%u",&port); 1179 1180 if(nbitems < 1) { 1181 free(device_name); 1182 printError("device (-d) argument not valid\n"); 1183 return NULL; 1184 } else { 1185 cmlparams.port = port; 1186 cmlparams.port_set=1; 1187 1188 cmlparams.node_id = -1; 1189 cmlparams.node_id_set=0; 1190 } 1191 } else { 1192 cmlparams.port = port; 1193 cmlparams.port_set=1; 1194 1195 cmlparams.node_id = node_id; 1196 cmlparams.node_id_set=1; 1197 } 1198 1199 jack_error("Freebob using Firewire port %d, node %d",cmlparams.port,cmlparams.node_id); 1200 1201 driver=(jack_driver_t *)ffado_driver_new (client, "ffado_pcm", &cmlparams); 1202 1203 return driver; 1204 } 1205 1206 void 1207 driver_finish (jack_driver_t *driver) 1208 { 1209 ffado_driver_t *drv=(ffado_driver_t *) driver; 1210 // If jack hasn't called the detach method, do it now. As of jack 0.101.1 1211 // the detach method was not being called explicitly on closedown, and 1212 // we need it to at least deallocate the iso resources. 1213 if (drv->dev != NULL) 1214 ffado_driver_detach(drv); 1215 ffado_driver_delete (drv); 1216 }
Note: See TracBrowser for help on using the browser.