root/trunk/libffado/support/jack/jack-for-ffado.patch

Revision 466, 44.0 kB (checked in by ppalmers, 17 years ago)

- introduce patch with jackd support

  • configure.ac

    old new  
    612612fi 
    613613AM_CONDITIONAL(HAVE_FREEBOB,$HAVE_FREEBOB) 
    614614 
     615AC_ARG_ENABLE(firewire, [  --disable-firewire          ignore FireWire driver (FFADO) ], 
     616                        TRY_FIREWIRE=$enableval , TRY_FIREWIRE=yes )  
     617HAVE_FIREWIRE="false" 
     618if test "x$TRY_FIREWIRE" = "xyes" 
     619then 
     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 
     629fi 
     630AM_CONDITIONAL(HAVE_FIREWIRE,$HAVE_FIREWIRE) 
     631 
    615632AC_ARG_ENABLE(alsa, [  --disable-alsa          ignore ALSA driver ], 
    616633                        TRY_ALSA=$enableval , TRY_ALSA=yes )  
    617634HAVE_ALSA="false" 
     
    698715drivers/portaudio/Makefile 
    699716drivers/coreaudio/Makefile 
    700717drivers/freebob/Makefile 
     718drivers/firewire/Makefile 
    701719example-clients/Makefile 
    702720jack.pc 
    703721jack.spec 
     
    716734echo $PACKAGE $VERSION : 
    717735echo 
    718736echo \| Build with ALSA support............................... : $HAVE_ALSA 
    719 echo \| Build with FreeBob support............................ : $HAVE_FREEBOB 
     737echo \| Build with old FireWire \(FreeBob\) support............. : $HAVE_FREEBOB 
     738echo \| Build with new FireWire \(FFADO\) support............... : $HAVE_FIREWIRE 
    720739echo \| Build with OSS support................................ : $HAVE_OSS 
    721740echo \| Build with CoreAudio support.......................... : $HAVE_COREAUDIO 
    722741echo \| Build with PortAudio support.......................... : $HAVE_PA 
  • drivers/freebob/freebob_driver.c

    old new  
    182182 
    183183        for (node = driver->capture_ports; node && node->data; 
    184184             node = jack_slist_next (node)) { 
    185                 jack_port_unregister (driver->client, 
     185                if(node->data != NULL) { 
     186                        jack_port_unregister (driver->client, 
    186187                                      ((jack_port_t *) node->data)); 
     188                } 
    187189        } 
    188190 
    189191        jack_slist_free (driver->capture_ports); 
     
    191193                 
    192194        for (node = driver->playback_ports; node && node->data; 
    193195             node = jack_slist_next (node)) { 
    194                 jack_port_unregister (driver->client, 
     196                if(node->data != NULL) { 
     197                        jack_port_unregister (driver->client, 
    195198                                      ((jack_port_t *) node->data)); 
     199                } 
    196200        } 
    197201 
    198202        jack_slist_free (driver->playback_ports); 
  • drivers/Makefile.am

    old new  
    3030FREEBOB_DIR = 
    3131endif 
    3232 
    33 SUBDIRS = $(ALSA_DIR) dummy $(OSS_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) 
    34 DIST_SUBDIRS = alsa dummy oss portaudio coreaudio freebob 
     33if HAVE_FIREWIRE 
     34FIREWIRE_DIR = firewire 
     35else 
     36FIREWIRE_DIR = 
     37endif 
     38 
     39SUBDIRS = $(ALSA_DIR) dummy $(OSS_DIR) $(PA_DIR) $(CA_DIR) $(FREEBOB_DIR) $(FIREWIRE_DIR) 
     40DIST_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 
     130typedef struct _ffado_driver ffado_driver_t; 
     131 
     132/* 
     133 * Jack Driver command line parameters 
     134 */ 
     135 
     136typedef struct _ffado_jack_settings ffado_jack_settings_t; 
     137struct _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 
     164typedef 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 
     171typedef 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 
     200struct _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 
     5MAINTAINERCLEANFILES=Makefile.in 
     6 
     7AM_CFLAGS = $(JACK_CFLAGS) $(LIBFFADO_CFLAGS) $(ALSA_CFLAGS) 
     8 
     9plugindir = $(ADDON_DIR) 
     10 
     11plugin_LTLIBRARIES = jack_firewire.la 
     12 
     13jack_firewire_la_SOURCES = ffado_driver.c 
     14 
     15jack_firewire_la_LIBADD = $(LIBFFADO_LIBS) $(ALSA_LIBS) 
     16 
     17jack_firewire_la_LDFLAGS = -module -avoid-version 
     18 
     19noinst_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 
     50static 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 
     60static int g_verbose=0; 
     61 
     62static int 
     63ffado_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 
     199static int  
     200ffado_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 
     245static inline void  
     246ffado_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 
     274static int 
     275ffado_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 
     309static inline void  
     310ffado_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 
     343static int 
     344ffado_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  
     388static jack_nframes_t  
     389ffado_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 
     446static int 
     447ffado_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 */ 
     475static int 
     476ffado_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 
     525static int 
     526ffado_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 
     553static int 
     554ffado_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 
     575static int 
     576ffado_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 
     593typedef void (*JackDriverFinishFunction) (jack_driver_t *); 
     594 
     595ffado_driver_t * 
     596ffado_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 
     667static void 
     668ffado_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 
     681void * 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) 
     738void *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 
     783static 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 
     949static int 
     950ffado_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 
     982static int 
     983ffado_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 
     996static void 
     997ffado_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 
     1022const char driver_client_name[] = "firewire_pcm"; 
     1023 
     1024const jack_driver_desc_t * 
     1025driver_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 
     1107jack_driver_t * 
     1108driver_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 
     1206void 
     1207driver_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.