root/trunk/libffado/support/jack/ffado_driver.c

Revision 445, 32.2 kB (checked in by pieterpalmers, 17 years ago)

* name change from FreeBoB to FFADO
* replaced tabs by 4 spaces
* got rid of end-of-line spaces
* made all license and copyrights conform

library becomes LGPL, apps become GPL
explicitly state LGPL v2.1 and GPL v2 (don't like v3 draft)

copyrights are 2005-2007 Daniel & Pieter
except for the MotU stuff (C) Jonathan, Pieter

Line 
1 /*
2  *   FireWire Backend for Jack
3  *   using FFADO
4  *   FFADO = Firewire (pro-)audio for linux
5  *
6  *   http://ffado.sf.net
7  *   http://jackit.sf.net
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.