root/trunk/libfreebob/src/libfreebobstreaming/freebob_streaming.c

Revision 165, 82.4 kB (checked in by wagi, 18 years ago)

2006-03-02 Daniel Wagner <wagi@monom.org>

  • configure.ac: bumb minor version to 0.4
  • src/libfreebobavc/avc_extended_cmd_generic.h: plugAddressPlugDirectionToString
    and plugAddressAddressModeToString added.
  • src/libfreebobavc/avc_extended_cmd_generic.cpp: Likewise.
  • src/avplug.h: Enum EAvPlugType renamed to EAvPlugAddressType.
    getPlugAddressType added. getPlugType returns now real plug type.
    (class AvPlugManager?): getPlugByType added.
  • src/avdevice.h: getPlugByType added.
  • src/avdevice.cpp: Likewise.
    (discoverSyncModes): Use getPlugByType instead
    of hardcoded id to find sync plugs.
  • src/devicemanager.h: Verbose argument not in constructor
    instead in discover method.
  • src/devicemanager.cpp: Likewise.
  • libfreebob/freebob.h (freebob_discover_devices): Verbose argument
    added.
  • src/libfreebobstreaming/freebob_streaming.c: Likewise.
  • src/freebob.cpp: Likewise.
  • tests/test-freebob.c: Likewise.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* $Id$ */
2
3 /*
4  *   FreeBob Streaming API
5  *   FreeBob = Firewire (pro-)audio for linux
6  *
7  *   http://freebob.sf.net
8  *
9  *   Copyright (C) 2005 Pieter Palmers <pieterpalmers@users.sourceforge.net>
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  */
28
29 /* freebob_streaming.c
30  *
31  * Implementation of the FreeBob Streaming API
32  *
33  */
34
35 #include "libfreebob/freebob_streaming.h"
36 #include "freebob_streaming_private.h"
37 #include "freebob_connections.h"
38 #include "freebob_debug.h"
39 #include "thread.h"
40 #include "messagebuffer.h"
41
42 #include <signal.h>
43 #include <unistd.h>
44
45 /**
46  * Callbacks
47  */
48
49 static enum raw1394_iso_disposition
50 iso_slave_receive_handler(raw1394handle_t handle, unsigned char *data,
51         unsigned int length, unsigned char channel,
52         unsigned char tag, unsigned char sy, unsigned int cycle,
53         unsigned int dropped);
54        
55 static enum raw1394_iso_disposition
56 iso_master_receive_handler(raw1394handle_t handle, unsigned char *data,
57         unsigned int length, unsigned char channel,
58         unsigned char tag, unsigned char sy, unsigned int cycle,
59         unsigned int dropped);
60        
61 static enum raw1394_iso_disposition
62 iso_slave_transmit_handler(raw1394handle_t handle,
63                 unsigned char *data, unsigned int *length,
64                 unsigned char *tag, unsigned char *sy,
65                 int cycle, unsigned int dropped);
66                
67 static enum raw1394_iso_disposition
68 iso_master_transmit_handler(raw1394handle_t handle,
69                 unsigned char *data, unsigned int *length,
70                 unsigned char *tag, unsigned char *sy,
71                 int cycle, unsigned int dropped);
72                        
73 static int freebob_am824_recv(char *data,
74                                                           int nevents, unsigned int offset, unsigned int dbc,
75                                                           freebob_connection_t *connection);
76
77 static int freebob_am824_xmit(char *data,
78                                                           int nevents, unsigned int offset, unsigned int dbc,
79                                                           freebob_connection_t *connection);
80                                
81
82 freebob_device_t *freebob_streaming_init (freebob_device_info_t *device_info, freebob_options_t options) {
83         int i;
84         int c;
85         int err=0;
86         freebob_device_t* dev=NULL;
87        
88         freebob_messagebuffer_init();
89                
90         assert(device_info);
91        
92         printMessage("FreeBob Streaming Device Init\n");
93         printMessage(" Using FreeBob lib version %s\n",freebob_get_version());
94         printMessage(" Device information:\n");
95        
96         printMessage(" Device options:\n");
97         /* driver related setup */
98         printMessage("  Port                     : %d\n",options.port);
99         printMessage("  Device Node Id           : %d\n",options.node_id);
100         printMessage("  Samplerate               : %d\n",options.sample_rate);
101         printMessage("  Period Size              : %d\n",options.period_size);
102         printMessage("  Nb Buffers               : %d\n",options.nb_buffers);
103         printMessage("  RAW1394 ISO Buffers      : %d\n",options.iso_buffers);
104         printMessage("  RAW1394 ISO Prebuffers   : %d\n",options.iso_prebuffers);
105         printMessage("  RAW1394 ISO IRQ Interval : %d\n",options.iso_irq_interval);
106        
107         // initialize the freebob_device
108         // allocate memory
109         dev=calloc(1,sizeof(freebob_device_t));
110        
111         if(!dev) {
112                 printError("FREEBOB: cannot allocate memory for dev structure!\n");
113                 return NULL;
114         }
115        
116         // clear the device structure
117         memset(dev,0,sizeof(freebob_device_t));
118        
119         // copy the arguments to the device structure
120         memcpy(&dev->device_info, device_info, sizeof(freebob_device_info_t));
121         memcpy(&dev->options, &options, sizeof(freebob_options_t));
122        
123         // read in the device specification
124        
125         /* load the connections*/
126         /*
127          * This info should be provided by the Freebob CML application
128          *
129          */
130         freebob_connection_info_t *libfreebob_capture_connections=NULL;
131         freebob_connection_info_t *libfreebob_playback_connections=NULL;
132
133         dev->fb_handle = freebob_new_handle(options.port);
134         if (!dev->fb_handle) {
135                 free(dev);
136                 printError("FREEBOB: cannot create libfreebob handle\n");
137                 return NULL;
138         }
139
140         if (freebob_discover_devices(dev->fb_handle, 0)!=0) {
141                 freebob_destroy_handle(dev->fb_handle);
142                 free(dev);
143                 printError("FREEBOB: device discovering failed\n");
144                 return NULL;
145         }
146
147         /* Try and set the samplerate
148          * This should be done after device discovery
149          * but before reading the bus description as the device capabilities can change
150          */
151
152         if(options.node_id > -1) {
153             if (! freebob_set_samplerate(dev->fb_handle, options.node_id, options.sample_rate)) {
154                 freebob_destroy_handle(dev->fb_handle);
155                 free(dev);
156                 printError("FREEBOB: Failed to set samplerate...\n");
157                 return NULL;
158             }
159
160         } else {
161             int devices_on_bus = freebob_get_nb_devices_on_bus(dev->fb_handle);
162             debugPrint(DEBUG_LEVEL_STARTUP,"port = %d, devices_on_bus = %d\n", options.port, devices_on_bus);
163                        
164             for(i=0;i<devices_on_bus;i++) {
165                 int node_id=freebob_get_device_node_id(dev->fb_handle, i);
166                 debugPrint(DEBUG_LEVEL_STARTUP,"set samplerate for device = %d, node = %d\n", i, node_id);
167                                
168                 if (! freebob_set_samplerate(dev->fb_handle, node_id, options.sample_rate)) {
169                         freebob_destroy_handle(dev->fb_handle);
170                         free(dev);
171                         printError("FREEBOB: Failed to set samplerate...\n");
172                         return NULL;
173                 }
174             }
175
176         }
177
178         /* Read the connection specification
179          */
180        
181         libfreebob_capture_connections=freebob_get_connection_info(dev->fb_handle, options.node_id, 0);
182         libfreebob_playback_connections=freebob_get_connection_info(dev->fb_handle, options.node_id, 1);
183                        
184         if (libfreebob_capture_connections) {
185                 dev->nb_connections_capture=libfreebob_capture_connections->nb_connections;
186                 // FIXME:
187                 //dev->nb_connections_capture=0;
188         } else {
189                 dev->nb_connections_capture=0;
190         }       
191        
192         if (libfreebob_playback_connections) {
193                 dev->nb_connections_playback=libfreebob_playback_connections->nb_connections;
194                 // FIXME:
195 //              dev->nb_connections_playback=0;
196         } else {
197                 dev->nb_connections_playback=0;
198         }
199         // FIXME: temporary disable the playback
200 //      dev->nb_connections_playback=0;
201        
202         dev->nb_connections=dev->nb_connections_playback+dev->nb_connections_capture;
203         /* see if there are any connections */
204         if (!dev->nb_connections) {
205                 printError("No connections specified, bailing out\n");
206                 if(libfreebob_capture_connections) { free(libfreebob_capture_connections); libfreebob_capture_connections=NULL; }
207                 if(libfreebob_playback_connections) { free(libfreebob_playback_connections); libfreebob_playback_connections=NULL; }
208                 freebob_destroy_handle(dev->fb_handle);
209                 free(dev);
210                
211                 return NULL;
212         }
213        
214         dev->connections=calloc(dev->nb_connections_playback+dev->nb_connections_capture, sizeof(freebob_connection_t));
215        
216        
217         for (c=0;c<dev->nb_connections_capture;c++) {
218                 memcpy(&dev->connections[c].spec, libfreebob_capture_connections->connections[c], sizeof(freebob_connection_spec_t));
219                 dev->connections[c].spec.direction=FREEBOB_CAPTURE;
220         }
221         for (c=0;c<dev->nb_connections_playback;c++) {
222                 memcpy(&dev->connections[c+dev->nb_connections_capture].spec, libfreebob_playback_connections->connections[c], sizeof(freebob_connection_spec_t));
223                 dev->connections[c+dev->nb_connections_capture].spec.direction=FREEBOB_PLAYBACK;
224         }
225        
226         /* Figure out a master connection.
227          * Either it is given in the spec libfreebob
228          * Or it is the first connection defined (capture connections first)
229          */
230         int master_found=FALSE;
231        
232         for (c=0;c<dev->nb_connections_capture+dev->nb_connections_playback;c++) {
233                 if (dev->connections[c].spec.is_master==TRUE) {
234                         master_found=TRUE;
235                         if(dev->options.sample_rate<0) {
236                                 dev->options.sample_rate=dev->connections[c].spec.samplerate;
237                         }
238                         break;
239                 }
240         }
241        
242         if((!master_found) && (dev->nb_connections_capture+dev->nb_connections_playback > 0)) {
243                 dev->connections[0].spec.is_master=TRUE;
244                 if(dev->options.sample_rate<0) {
245                         dev->options.sample_rate=dev->connections[0].spec.samplerate;
246                 }
247         }
248
249         // initialize all connections
250         for(i=0; i < dev->nb_connections; i++) {
251                 freebob_connection_t *connection= &(dev->connections[i]);
252                 if ((err=freebob_streaming_init_connection(dev, connection))<0) {
253                         printError("FREEBOB: failed to init connection %d\n",i);
254                         break;
255                 }
256         }
257        
258         if(libfreebob_capture_connections) { freebob_free_connection_info(libfreebob_capture_connections); libfreebob_capture_connections=NULL; }
259         if(libfreebob_playback_connections) { freebob_free_connection_info(libfreebob_playback_connections); libfreebob_playback_connections=NULL; }
260        
261         // prepare the FD map   
262         // the FD map is not stricly nescessary due to dev->fdmap[i]=dev->connections[i];
263         // but makes things flexible at the moment
264        
265         assert(dev->nb_connections==dev->nb_connections_capture+dev->nb_connections_playback);
266        
267         dev->nfds   = dev->nb_connections;
268         dev->pfds   = malloc (sizeof (struct pollfd) * dev->nfds);
269         dev->fdmap  = malloc (sizeof (freebob_connection_t *) * dev->nfds); // holds the connection idx of this fd
270        
271         for(i=0; i < dev->nb_connections; i++) {
272                 freebob_connection_t *connection= &(dev->connections[i]);
273                 dev->fdmap[i]=connection;
274                 dev->pfds[i].fd = raw1394_get_fd (connection->raw_handle);
275                 dev->pfds[i].events = POLLIN;
276                 connection->pfd=&dev->pfds[i];
277         }
278        
279         // check for errors
280         if(err) {
281                 debugPrint(DEBUG_LEVEL_STARTUP, "Cleaning up connections\n");
282                
283                 // the connection that failed doesn't have to be cleaned
284                 i-=1;
285                
286                 for(; i >= 0; i--) {
287                         freebob_connection_t *connection= &(dev->connections[i]);
288                         debugPrint(DEBUG_LEVEL_STARTUP, "Cleaning up connection %d\n",i);
289                         if ((freebob_streaming_cleanup_connection(dev, connection))<0) {
290                                 printError( "Failed to clean connection %d\n",i);
291                         }
292                 }
293                 free(dev->pfds);
294                 free(dev->fdmap);
295                 free(dev->connections);
296                 free(dev);
297                 return NULL;
298         }
299        
300         freebob_destroy_handle(dev->fb_handle);
301        
302         return dev;
303
304 }
305
306 void freebob_streaming_finish(freebob_device_t *dev) {
307         debugPrint(DEBUG_LEVEL_STARTUP,"Cleaning up connections\n");
308         unsigned int i;
309         int err=0;
310        
311         // cleanup all connections
312         for(i=0; i < dev->nb_connections; i++) {
313                 freebob_connection_t *connection= &(dev->connections[i]);
314                 if ((err=freebob_streaming_cleanup_connection(dev, connection))<0) {
315                         printError("Failed to cleanup connection %d\n",i);
316                         return;
317                 }
318         }
319        
320         // free stream structures
321         if(dev->capture_streams) {
322                 free(dev->capture_streams);
323         }
324         if(dev->playback_streams) {
325                 free(dev->playback_streams);
326         }
327         if(dev->synced_capture_streams) {
328                 free(dev->synced_capture_streams);
329         }
330         if(dev->synced_playback_streams) {
331                 free(dev->synced_playback_streams);
332         }
333        
334         // cleanup data structures
335         free(dev->pfds);
336         free(dev->fdmap);
337         free(dev->connections);
338         free(dev);
339        
340         freebob_messagebuffer_exit();
341        
342         return;
343 }
344
345 int freebob_streaming_get_nb_capture_streams(freebob_device_t *dev) {
346         return dev->nb_capture_streams;
347 }
348
349 int freebob_streaming_get_nb_playback_streams(freebob_device_t *dev) {
350         return dev->nb_playback_streams;
351 }
352
353 int freebob_streaming_get_capture_stream_name(freebob_device_t *dev, int i, char* buffer, size_t buffersize) {
354         freebob_stream_t *stream;
355         if(i<dev->nb_capture_streams) {
356                 stream=*(dev->capture_streams+i);
357                 return snprintf (buffer, buffersize, "%s_%d_%d_%d_%s",
358                                                 "cap", (int) stream->parent->spec.port, stream->parent->spec.node & 0x3F, stream->parent->spec.plug, stream->spec.name);               
359         } else {
360                 return -1;
361         }
362 }
363
364 int freebob_streaming_get_playback_stream_name(freebob_device_t *dev, int i, char* buffer, size_t buffersize) {
365         freebob_stream_t *stream;
366         if(i<dev->nb_playback_streams) {
367                 stream=*(dev->playback_streams+i);
368                 return snprintf (buffer, buffersize, "%s_%d_%d_%d_%s",
369                                                 "pbk", (int) stream->parent->spec.port, stream->parent->spec.node & 0x3F, stream->parent->spec.plug, stream->spec.name);               
370         } else {
371                 return -1;
372         }
373 }
374
375 freebob_streaming_stream_type freebob_streaming_get_capture_stream_type(freebob_device_t *dev, int i) {
376         freebob_stream_t *stream;
377         if(i<dev->nb_capture_streams) {
378                 stream=*(dev->capture_streams+i);
379                 switch (stream->spec.format) {
380                 case IEC61883_STREAM_TYPE_MBLA:
381                         return freebob_stream_type_audio;
382                 case IEC61883_STREAM_TYPE_MIDI:
383                         return freebob_stream_type_midi;
384                 case IEC61883_STREAM_TYPE_SPDIF:
385                 default:
386                         return freebob_stream_type_unknown;
387                 }
388         } else {
389                 return freebob_stream_type_invalid;
390         }
391 }
392
393 freebob_streaming_stream_type freebob_streaming_get_playback_stream_type(freebob_device_t *dev, int i) {
394         freebob_stream_t *stream;
395         if(i<dev->nb_playback_streams) {
396                 stream=*(dev->playback_streams+i);
397                 switch (stream->spec.format) {
398                 case IEC61883_STREAM_TYPE_MBLA:
399                         return freebob_stream_type_audio;
400                 case IEC61883_STREAM_TYPE_MIDI:
401                         return freebob_stream_type_midi;
402                 case IEC61883_STREAM_TYPE_SPDIF:
403                 default:
404                         return freebob_stream_type_unknown;
405                 }
406         } else {
407                 return freebob_stream_type_invalid;
408         }
409 }
410
411 int freebob_streaming_set_stream_buffer(freebob_device_t *dev,  freebob_stream_t *dst, char *b, freebob_streaming_buffer_type t) {
412         assert(dst);
413        
414         // free the preallocated buffer first
415         freebob_streaming_free_stream_buffer(dev,dst);
416        
417         switch (t) {
418                 case freebob_buffer_type_per_stream:
419                         dst->user_buffer=calloc(dev->options.period_size,sizeof(freebob_sample_t));
420                         dst->buffer_type=freebob_buffer_type_per_stream;
421                         break;
422                
423                 case freebob_buffer_type_uint24:
424                         if(b) {
425                                 dst->buffer_type=t;
426                                 dst->user_buffer=b;
427                         } else {
428                                 // allocate a default type
429                                 dst->buffer_type=freebob_buffer_type_per_stream;
430                                 dst->user_buffer=calloc(dev->options.period_size,sizeof(freebob_sample_t));
431                                 return -1;
432                         }
433                         break;
434                        
435                 case freebob_buffer_type_float:
436                         if(b) {
437                                 dst->buffer_type=t;
438                                 dst->user_buffer=b;
439                         } else {
440                                 // allocate a default type
441                                 dst->buffer_type=freebob_buffer_type_per_stream;
442                                 dst->user_buffer=calloc(dev->options.period_size,sizeof(freebob_sample_t));
443                                 return -1;
444                         }
445                         break;
446                
447                 default:
448                         // allocate a default type
449                         dst->buffer_type=freebob_buffer_type_per_stream;
450                         dst->user_buffer=calloc(dev->options.period_size,sizeof(freebob_sample_t));
451                         return -1;
452                        
453         }
454         return 0;
455 }
456
457 void freebob_streaming_free_stream_buffer(freebob_device_t* dev, freebob_stream_t *dst)
458 {
459        
460         if((dst->buffer_type==freebob_buffer_type_per_stream) && (dst->user_buffer)) {
461                 free(dst->user_buffer);
462                 dst->user_buffer=NULL;
463         }
464 }
465
466
467 int freebob_streaming_set_capture_stream_buffer(freebob_device_t *dev, int i, char *buff,  freebob_streaming_buffer_type t) {
468        
469         freebob_stream_t *stream;
470         if(i<dev->nb_capture_streams) {
471                 stream=*(dev->capture_streams+i);
472                 assert(stream);
473                 return freebob_streaming_set_stream_buffer(dev,  stream, buff, t);
474                
475         } else {
476                 return -1;
477         }
478        
479 }
480
481 int freebob_streaming_set_playback_stream_buffer(freebob_device_t *dev, int i, char *buff,  freebob_streaming_buffer_type t) {
482         freebob_stream_t *stream;
483         if(i<dev->nb_playback_streams) {
484                
485                 stream=*(dev->playback_streams+i);
486                
487                 assert(stream);
488                 return freebob_streaming_set_stream_buffer(dev, stream, buff, t);
489                
490         } else {
491                 return -1;
492         }
493 }
494
495 int freebob_streaming_start_thread(freebob_device_t *dev) {
496         int err;
497         // start the packetizer thread
498         // init the packetizer thread communication semaphores
499         if((err=sem_init(&dev->packetizer.transfer_boundary, 0, 0))) {
500                 printError( "Cannot init packet transfer semaphore\n");
501                 return err;
502         } else {
503                 debugPrint(DEBUG_LEVEL_STARTUP,"FREEBOB: successfull init of packet transfer semaphore\n");
504         }
505        
506         dev->packetizer.priority=dev->options.packetizer_priority;
507         dev->packetizer.realtime=dev->options.realtime;
508        
509         // start watchdog
510         if (dev->packetizer.realtime) {
511                 freebob_streaming_start_watchdog(dev);
512         }
513        
514         // start packetizer thread
515         dev->packetizer.run=1;
516        
517         if (freebob_streaming_create_thread(dev, &dev->packetizer.transfer_thread, dev->packetizer.priority, dev->packetizer.realtime, freebob_iso_packet_iterator, (void *)dev)) {
518                 printError("FREEBOB: cannot create packet transfer thread");
519                 return -1;
520         } else {
521                 debugPrint(DEBUG_LEVEL_STARTUP,"Created packet transfer thread\n");
522         }
523         return 0;
524 }
525
526 int freebob_streaming_stop_thread(freebob_device_t *dev) {
527         void *status;
528        
529         debugPrint(DEBUG_LEVEL_STARTUP," Stopping packetizer thread...\n");
530         dev->packetizer.run=0;
531        
532        
533         //sem_post(&dev->packetizer.transfer_ack);
534        
535         pthread_join(dev->packetizer.transfer_thread, &status);
536        
537         // stop watchdog
538         if (dev->packetizer.realtime) {
539                 freebob_streaming_stop_watchdog(dev);
540         }
541        
542         // cleanup semaphores
543         sem_destroy(&dev->packetizer.transfer_boundary);
544
545         return 0;
546 }
547
548
549 int freebob_streaming_start(freebob_device_t *dev) {
550         int err;
551         int i;
552        
553         for(i=0; i < dev->nb_connections; i++) {
554                 err=0;
555                 freebob_connection_t *connection= &(dev->connections[i]);
556                
557                 //connection->plug=0;
558                 connection->iso.hostplug=-1;
559                
560                 // create the CCM PTP connection
561                 connection->iso.do_disconnect=0;
562
563                 // start receiving
564                 switch (connection->spec.direction) {
565                 case FREEBOB_CAPTURE:
566                
567                         debugPrint(DEBUG_LEVEL_STARTUP," creating capture connections...\n");
568                         if (connection->spec.iso_channel < 0) {
569                                 // we need to make the connection ourself
570                                 debugPrint(DEBUG_LEVEL_STARTUP, "Executing CMP procedure...\n");
571                                
572                                 connection->iso.iso_channel = iec61883_cmp_connect(
573                                         connection->raw_handle,
574                                         connection->spec.node | 0xffc0,
575                                         &connection->spec.plug,
576                                         raw1394_get_local_id (connection->raw_handle),
577                                         &connection->iso.hostplug,
578                                         &connection->iso.bandwidth);
579                                        
580                                 connection->iso.do_disconnect=1;
581                                
582                         } else {
583                                 connection->iso.iso_channel=connection->spec.iso_channel;
584                         }
585                        
586                         if (connection->spec.is_master) { //master connection
587                                 dev->sync_master_connection=connection;
588                                 connection->status.master=NULL;
589                                
590                         }
591                        
592                         // this moved to iso_connection_start in order to work around a raw1394 bug
593 #if 0
594                         if (connection->spec.is_master) { //master connection
595                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO master receive handler on channel %d...\n",connection->iso.iso_channel);
596                                 debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
597                                 raw1394_iso_recv_init(
598                                         connection->raw_handle,
599                                         iso_master_receive_handler,
600                                         connection->iso.buffers,
601                                         AMDTP_MAX_PACKET_SIZE,
602                                         connection->iso.iso_channel,
603                                         RAW1394_DMA_BUFFERFILL,
604                                         connection->iso.irq_interval);
605                                                                                
606                                 dev->sync_master_connection=connection;
607                                 connection->status.master=NULL;
608                                
609                         } else {
610                                 //slave receive connection
611                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO slave receive handler on channel %d...\n",connection->iso.iso_channel);
612                                 debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n", connection->iso.buffers, AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
613                                 raw1394_iso_recv_init( 
614                                         connection->raw_handle,
615                                         iso_slave_receive_handler,
616                                         connection->iso.buffers,
617                                         AMDTP_MAX_PACKET_SIZE,
618                                         connection->iso.iso_channel,
619                                         RAW1394_DMA_BUFFERFILL,
620                                         connection->iso.irq_interval);
621                         }
622 #endif                 
623                 break;
624                 case FREEBOB_PLAYBACK:
625                         debugPrint(DEBUG_LEVEL_STARTUP," creating playback connections...\n");
626                
627                         if (connection->spec.iso_channel < 0) { // we need to make the connection ourself
628                                 debugPrint(DEBUG_LEVEL_STARTUP, "Executing CMP procedure...\n");
629                                 connection->iso.iso_channel = iec61883_cmp_connect(
630                                 connection->raw_handle,
631                                 raw1394_get_local_id (connection->raw_handle),
632                                 &connection->iso.hostplug,
633                                 connection->spec.node | 0xffc0,
634                                 &connection->spec.plug,
635                                 &connection->iso.bandwidth);
636                                
637                                 connection->iso.do_disconnect=1;
638                         } else {
639                                 connection->iso.iso_channel=connection->spec.iso_channel;
640                         }
641
642                         if (connection->spec.is_master) { // master connection
643                                 dev->sync_master_connection=connection;
644                                 connection->status.master=NULL;
645                         }
646                        
647                         // this moved to iso_connection_start in order to work around a raw1394 bug
648 #if 0
649                         if (connection->spec.is_master) { // master connection
650                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO master transmit handler on channel %d...\n",connection->iso.iso_channel);
651                                 debugPrint(DEBUG_LEVEL_STARTUP, "   other mode (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
652                                
653                                 raw1394_iso_xmit_init(
654                                         connection->raw_handle,
655                                         iso_master_transmit_handler,
656                                         connection->iso.buffers,
657                                         AMDTP_MAX_PACKET_SIZE,
658                                         connection->iso.iso_channel,
659                                         RAW1394_ISO_SPEED_400,
660                                         connection->iso.irq_interval);
661
662                                 dev->sync_master_connection=connection;
663                                 connection->status.master=NULL;
664                        
665                         } else {
666                        
667                                 debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO slave transmit handler on channel %d...\n",connection->iso.iso_channel);
668                                 debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
669                                 raw1394_iso_xmit_init(
670                                         connection->raw_handle,
671                                         iso_slave_transmit_handler,
672                                         connection->iso.buffers,
673                                         AMDTP_MAX_PACKET_SIZE,
674                                         connection->iso.iso_channel,
675                                         RAW1394_ISO_SPEED_400,
676                                         connection->iso.irq_interval);
677                         }
678 #endif                 
679                         int fdf, syt_interval;
680 // FIXME:               
681                         int samplerate=dev->options.sample_rate;
682 //                      int samplerate=connection->spec.samplerate;
683
684                         switch (samplerate) {
685                         case 32000:
686                                 syt_interval = 8;
687                                 fdf = IEC61883_FDF_SFC_32KHZ;
688                                 break;
689                         case 44100:
690                                 syt_interval = 8;
691                                 fdf = IEC61883_FDF_SFC_44K1HZ;
692                                 break;
693                         default:
694                         case 48000:
695                                 syt_interval = 8;
696                                 fdf = IEC61883_FDF_SFC_48KHZ;
697                                 break;
698                         case 88200:
699                                 syt_interval = 16;
700                                 fdf = IEC61883_FDF_SFC_88K2HZ;
701                                 break;
702                         case 96000:
703                                 syt_interval = 16;
704                                 fdf = IEC61883_FDF_SFC_96KHZ;
705                                 break;
706                         case 176400:
707                                 syt_interval = 32;
708                                 fdf = IEC61883_FDF_SFC_176K4HZ;
709                                 break;
710                         case 192000:
711                                 syt_interval = 32;
712                                 fdf = IEC61883_FDF_SFC_192KHZ;
713                                 break;
714                         }
715                                                                
716                         iec61883_cip_init (
717                                 &connection->status.cip,
718                                 IEC61883_FMT_AMDTP,
719                                 fdf,
720                                 samplerate,
721                                 connection->spec.dimension,
722                                 syt_interval);
723                                
724                         iec61883_cip_set_transmission_mode (
725                                 &connection->status.cip,
726                                 IEC61883_MODE_BLOCKING_EMPTY);
727
728                 break;
729                 }
730                
731                 if(connection->iso.iso_channel<0) {
732                         printError("Could not do CMP for connection %d\n",i);
733                         i-=1;
734                         while(i>=0) {
735                                 connection= &(dev->connections[i]);
736                
737                                 // not nescessary anymore since it moved to the iso_start function
738 /*                              debugPrint(DEBUG_LEVEL_STARTUP, "Shutdown connection %d on channel %d ...\n", i, connection->iso.iso_channel);
739                                
740                                 raw1394_iso_shutdown(connection->raw_handle);
741 */
742                
743                                 if (connection->iso.do_disconnect) {
744                                         // destroy the CCM PTP connection
745                                         switch (connection->spec.direction) {
746                                         case FREEBOB_CAPTURE:
747                                                 iec61883_cmp_disconnect(
748                                                         connection->raw_handle,
749                                                         connection->spec.node | 0xffc0,
750                                                         connection->spec.plug,
751                                                         raw1394_get_local_id (connection->raw_handle),
752                                                         connection->iso.hostplug,
753                                                         connection->iso.iso_channel,
754                                                         connection->iso.bandwidth);
755                                                
756                                         break;
757                                         case FREEBOB_PLAYBACK:
758                                                 iec61883_cmp_disconnect(
759                                                         connection->raw_handle,
760                                                         raw1394_get_local_id (connection->raw_handle),
761                                                         connection->iso.hostplug,
762                                                         connection->spec.node | 0xffc0,
763                                                         connection->spec.plug,
764                                                         connection->iso.iso_channel,
765                                                         connection->iso.bandwidth);
766                        
767                                         break;
768                                         }
769                                 }
770                                 i--;
771                         }
772                         return -1;
773                 }
774         }
775        
776         /* update the sync master pointer for all connections */
777         debugPrint(DEBUG_LEVEL_STARTUP,"Connection summary:\n");
778         int sync_masters_present=0;
779        
780         for(i=0; i < dev->nb_connections; i++) {
781                 err=0;
782                
783                 freebob_connection_t *connection= &(dev->connections[i]);
784                
785                 if (connection->spec.direction == FREEBOB_CAPTURE) {
786                         debugPrint(DEBUG_LEVEL_STARTUP,"  Capture : from node %02X.%02d to node %02X.%02d on channel %02d  {%p} ",
787                                 connection->spec.node & ~0xffc0, connection->spec.plug,
788                                 raw1394_get_local_id (connection->raw_handle) & ~0xffc0, connection->iso.hostplug,
789                                 connection->iso.iso_channel, connection);
790                 } else if (connection->spec.direction == FREEBOB_PLAYBACK) {
791                        
792                         debugPrint(DEBUG_LEVEL_STARTUP,"  Playback: from node %02X.%02d to node %02X.%02d on channel %02d  {%p} ",
793                                 raw1394_get_local_id (connection->raw_handle) & ~0xffc0, connection->iso.hostplug,
794                                 connection->spec.node & ~0xffc0, connection->spec.plug,
795                                 connection->iso.iso_channel, connection);
796                 }
797                
798                 if (connection->spec.is_master) {
799                         sync_masters_present++;
800                        
801                         debugPrintShort(DEBUG_LEVEL_STARTUP," [MASTER]");       
802                 } else {
803                         assert(dev->sync_master_connection);
804                         connection->status.master=&dev->sync_master_connection->status;
805                        
806                         debugPrintShort(DEBUG_LEVEL_STARTUP," [SLAVE]");
807                 }
808                 debugPrintShort(DEBUG_LEVEL_STARTUP,"\n");
809         }
810        
811         if (sync_masters_present == 0) {
812                 printError("FREEBOB: no sync master connection present!\n");
813                 // TODO: cleanup
814                 //freebob_streaming_stop(driver);
815                 return -1;
816         } else if (sync_masters_present > 1) {
817                 printError("FREEBOB: too many sync master connections present! (%d)\n",sync_masters_present);
818                 // TODO: cleanup
819                 //freebob_streaming_stop(driver);
820                 return -1;
821         }
822        
823         // put nb_periods*period_size of null frames into the playback buffers
824         if((err=freebob_streaming_prefill_playback_streams(dev))<0) {
825                 printError("Could not prefill playback streams.\n");
826                 return err;
827         }
828                
829         // we should transfer nb_buffers-1 periods of playback from the stream buffers to the event buffer
830         for (i=0;i<dev->options.nb_buffers;i++) {
831                 freebob_streaming_transfer_playback_buffers(dev);
832         }
833
834         freebob_streaming_print_bufferfill(dev);
835                
836         debugPrint(DEBUG_LEVEL_STARTUP,"Armed...\n");
837        
838         //freebob_streaming_start_iso(dev);
839        
840         freebob_streaming_start_thread(dev);
841
842         return 0;
843
844 }
845
846 int freebob_streaming_stop(freebob_device_t *dev) {
847         unsigned int i;
848        
849
850         freebob_streaming_stop_thread(dev);
851        
852         //freebob_streaming_stop_iso(dev);
853
854         // stop ISO xmit/receive
855         for(i=0; i < dev->nb_connections; i++) {
856                 freebob_connection_t *connection= &(dev->connections[i]);
857
858                 // this moved to iso_connection_stop in order to work around a raw1394 bug
859 #if 0
860                 debugPrint(DEBUG_LEVEL_STARTUP, "Shutdown connection %d on channel %d ...\n", i, connection->iso.iso_channel);
861                
862                 raw1394_iso_shutdown(connection->raw_handle);
863 #endif
864
865                 if (connection->iso.do_disconnect) {
866                         // destroy the CCM PTP connection
867                         switch (connection->spec.direction) {
868                         case FREEBOB_CAPTURE:
869                                 iec61883_cmp_disconnect(
870                                         connection->raw_handle,
871                                         connection->spec.node | 0xffc0,
872                                         connection->spec.plug,
873                                         raw1394_get_local_id (connection->raw_handle),
874                                         connection->iso.hostplug,
875                                         connection->iso.iso_channel,
876                                         connection->iso.bandwidth);
877                                
878                         break;
879                         case FREEBOB_PLAYBACK:
880                                 iec61883_cmp_disconnect(
881                                         connection->raw_handle,
882                                         raw1394_get_local_id (connection->raw_handle),
883                                         connection->iso.hostplug,
884                                         connection->spec.node | 0xffc0,
885                                         connection->spec.plug,
886                                         connection->iso.iso_channel,
887                                         connection->iso.bandwidth);
888        
889                         break;
890                         }
891                 }
892                
893         }
894         return 0;
895 }
896
897 void freebob_streaming_print_bufferfill(freebob_device_t *dev) {
898         int i=0;
899         for(i=0; i < dev->nb_connections; i++) {
900                 freebob_connection_t *connection= &(dev->connections[i]);
901                 debugPrint(DEBUG_LEVEL_XRUN_RECOVERY, "%i: %d\n",i,freebob_ringbuffer_read_space(connection->event_buffer));
902         }
903        
904 }
905
906 int freebob_streaming_prefill_playback_streams(freebob_device_t *dev) {
907         int i;
908         int err=0;
909        
910         for(i=0; i < dev->nb_playback_streams; i++) {
911                 freebob_stream_t *stream;
912
913                
914                 stream=*(dev->playback_streams+i);
915                
916                 assert(stream);
917                 err=freebob_streaming_prefill_stream(dev, stream);
918                 if (err) {
919                         printError("Could not prefill stream %d\n",i);
920                         return -1;
921                 }
922         }
923         return 0;
924        
925 }
926
927 int freebob_streaming_reset(freebob_device_t *dev) {
928         /*
929          * Reset means:
930          * 1) Stopping the packetizer thread
931          * 2) Bringing all buffers & connections into a know state
932          *    - Clear all capture buffers
933          *    - Put nb_periods*period_size of null frames into the playback buffers
934          * 3) Restarting the packetizer thread
935          */
936
937         unsigned long i;
938         int err;
939         assert(dev);
940
941         debugPrint(DEBUG_LEVEL_XRUN_RECOVERY, "Resetting streams...\n");
942        
943         if((err=freebob_streaming_stop_thread(dev))<0) {
944                 printError("Could not stop packetizer thread.\n");
945                 return err;
946         }
947
948         //freebob_streaming_stop_iso(dev);
949
950         // check if the packetizer is stopped
951         assert(!dev->packetizer.run);
952        
953         // reset all connections
954         for(i=0; i < dev->nb_connections; i++) {
955                 freebob_connection_t *connection= &(dev->connections[i]);
956                 freebob_streaming_reset_connection(dev,connection);
957         }
958        
959         // put nb_periods*period_size of null frames into the playback buffers
960         if((err=freebob_streaming_prefill_playback_streams(dev))<0) {
961                 printError("Could not prefill playback streams.\n");
962                 return err;
963         }
964        
965         // we should transfer nb_buffers-1 periods of playback from the stream buffers to the event buffer
966         for (i=0;i<dev->options.nb_buffers;i++) {
967                 freebob_streaming_transfer_playback_buffers(dev);
968         }
969                        
970         // clear the xrun flag
971         dev->xrun_detected=FALSE;
972        
973         //freebob_streaming_start_iso(dev);
974         freebob_streaming_print_bufferfill(dev);
975        
976         if((err=freebob_streaming_start_thread(dev))<0) {
977                 printError("Could not start packetizer thread.\n");
978                 return err;
979         }
980        
981        
982         return 0;
983 }
984
985 int freebob_streaming_xrun_recovery(freebob_device_t *dev) {
986         freebob_streaming_reset(dev);
987         dev->xrun_count++;
988        
989         return 0;
990 }
991
992 int freebob_streaming_wait(freebob_device_t *dev) {
993         int ret;
994
995         // Wait for packetizer thread to signal a period completion
996         sem_wait(&dev->packetizer.transfer_boundary);
997        
998         // acknowledge the reception of the period
999         //sem_post(&dev->packetizer.transfer_ack);
1000        
1001         if(dev->xrun_detected) {
1002                 // notify the driver of the underrun and the delay
1003                 ret = (-1) * freebob_streaming_xrun_recovery(dev);
1004         } else {
1005                 ret=dev->options.period_size;
1006         }
1007        
1008         return ret;
1009 }
1010
1011 int freebob_streaming_transfer_capture_buffers(freebob_device_t *dev) {
1012         int i;
1013         int xrun;
1014         unsigned int offset=0;
1015        
1016         freebob_ringbuffer_data_t vec[2];
1017         // transfer the received events into the stream buffers
1018         for (i=0;i<dev->nb_connections_capture;i++) {
1019                 freebob_connection_t *connection= &(dev->connections[i]); // capture connections are first in the array
1020                 assert(connection);
1021                
1022                 debugPrint(DEBUG_LEVEL_WAIT, "R: > %d\n",freebob_ringbuffer_read_space(connection->event_buffer));
1023                        
1024                         // we received one period of frames on each connection
1025                         // this is period_size*dimension of events
1026
1027                 int events2read=dev->options.period_size*connection->spec.dimension;
1028                 int bytes2read=events2read*sizeof(quadlet_t);
1029                        
1030                         // TODO: implement dbc for midi
1031                 int dbc=0;
1032                        
1033                         /*      read events2read bytes from the ringbuffer
1034                 *  first see if it can be done in one read.
1035                 *  if so, ok.
1036                 *  otherwise read up to a multiple of clusters directly from the buffer
1037                 *  then do the buffer wrap around using ringbuffer_read
1038                 *  then read the remaining data directly from the buffer in a third pass
1039                 *  Make sure that we cannot end up on a non-cluster aligned position!
1040                         */
1041                 int cluster_size=connection->spec.dimension*sizeof(quadlet_t);
1042 //              unsigned int frames2read=events2read/connection->spec.dimension;
1043                        
1044                 while(bytes2read>0) {
1045                         unsigned int framesread=(dev->options.period_size*cluster_size-bytes2read)/cluster_size;
1046                         offset=framesread;
1047 //                      offset=0;
1048                        
1049                         int bytesread=0;
1050                                                
1051                         freebob_ringbuffer_get_read_vector(connection->event_buffer, vec);
1052                                
1053                         if(vec[0].len==0) { // this indicates an empty event buffer
1054                                 printError("Event buffer underrun on capture connection %d\n",i);
1055                                 break;
1056                         }
1057                                
1058                                 /* if we don't take care we will get stuck in an infinite loop
1059                         * because we align to a cluster boundary later
1060                         * the remaining nb of bytes in one read operation can be smaller than one cluster
1061                         * this can happen because the ringbuffer size is always a power of 2
1062                                 */
1063                         if(vec[0].len<cluster_size) {
1064                                         // use the ringbuffer function to read one cluster (handles wrap around)
1065                                 freebob_ringbuffer_read(connection->event_buffer,connection->cluster_buffer,cluster_size);
1066                                        
1067                                 // decode the temporary buffer
1068                                 debugPrint(DEBUG_LEVEL_WAIT, "R: %5d [%5d %5d] %5d %5d\n",bytes2read,vec[0].len,vec[1].len,1, offset);
1069                                        
1070                                 xrun = freebob_am824_recv(connection->cluster_buffer, 1, offset, dbc, connection);
1071                                        
1072                                 if(xrun<0) {
1073                                                 // xrun detected
1074                                         printError("Frame buffer overrun on capture connection %d\n",i);
1075                                         break;
1076                                 }
1077                                        
1078                                         // we advanced one cluster_size
1079                                 bytes2read-=cluster_size;
1080                                        
1081                         } else { //
1082                                
1083                                 if(bytes2read>vec[0].len) {
1084                                                 // align to a cluster boundary
1085                                         bytesread=vec[0].len-(vec[0].len%cluster_size);
1086                                 } else {
1087                                         bytesread=bytes2read;
1088                                 }
1089                                        
1090                                 debugPrint(DEBUG_LEVEL_WAIT, "R: %5d [%5d %5d] %5d %5d\n",bytes2read,vec[0].len,vec[1].len,bytesread, offset);
1091                                        
1092                                 xrun = freebob_am824_recv(vec[0].buf, bytesread/sizeof(quadlet_t)/connection->spec.dimension, offset, dbc, connection);
1093                                        
1094                                 if(xrun<0) {
1095                                                 // xrun detected
1096                                         printError("Frame buffer overrun on capture connection %d\n",i);
1097                                         break;
1098                                 }
1099        
1100                                 freebob_ringbuffer_read_advance(connection->event_buffer, bytesread);
1101                                 bytes2read -= bytesread;
1102                         }
1103                                
1104                                 // the bytes2read should always be cluster aligned
1105                         assert(bytes2read%cluster_size==0);
1106                         debugPrint(DEBUG_LEVEL_WAIT, "R: < %d\n",freebob_ringbuffer_read_space(connection->event_buffer));
1107                                
1108                 }
1109
1110         }
1111         return 0;
1112 }
1113
1114 int freebob_streaming_transfer_playback_buffers(freebob_device_t *dev) {
1115         int i;
1116         int xrun;
1117         unsigned int offset=0;
1118        
1119         freebob_ringbuffer_data_t vec[2];
1120         // transfer the output stream buffers content to the event buffers
1121         for (i=dev->nb_connections_capture;i<dev->nb_connections_capture+dev->nb_connections_playback;i++) {
1122                 freebob_connection_t *connection= &(dev->connections[i]);
1123                 assert(connection);
1124                 debugPrint(DEBUG_LEVEL_WAIT, "W: < %d\n",freebob_ringbuffer_write_space(connection->event_buffer));
1125                        
1126                         // we received one period of frames on each connection
1127                         // this is period_size*dimension of events
1128
1129                 int events2write=dev->options.period_size*connection->spec.dimension;
1130                 int bytes2write=events2write*sizeof(quadlet_t);
1131                        
1132                         // TODO: implement dbc for midi
1133                 int dbc=0;
1134                        
1135                 /*      write events2write bytes to the ringbuffer
1136                 *  first see if it can be done in one read.
1137                 *  if so, ok.
1138                 *  otherwise write up to a multiple of clusters directly to the buffer
1139                 *  then do the buffer wrap around using ringbuffer_write
1140                 *  then write the remaining data directly to the buffer in a third pass
1141                 *  Make sure that we cannot end up on a non-cluster aligned position!
1142                 */
1143                 int cluster_size=connection->spec.dimension*sizeof(quadlet_t);
1144 //              unsigned int frames2write=events2write/connection->spec.dimension;
1145                        
1146                 while(bytes2write>0) {
1147                         int byteswritten=0;
1148                        
1149                         unsigned int frameswritten=(dev->options.period_size*cluster_size-bytes2write)/cluster_size;
1150                         offset=frameswritten;
1151 //                      offset=0;
1152                        
1153                         freebob_ringbuffer_get_write_vector(connection->event_buffer, vec);
1154                                
1155                         if(vec[0].len==0) { // this indicates a full event buffer
1156                                 printError("Event buffer overrun on playback connection %d\n",i);
1157                                 break;
1158                         }
1159                                
1160                         /* if we don't take care we will get stuck in an infinite loop
1161                         * because we align to a cluster boundary later
1162                         * the remaining nb of bytes in one write operation can be smaller than one cluster
1163                         * this can happen because the ringbuffer size is always a power of 2
1164                         */
1165                         if(vec[0].len<cluster_size) {
1166                                
1167                                 // encode to the temporary buffer
1168                                 debugPrint(DEBUG_LEVEL_WAIT, "W: %d [%d %d] %d\n",bytes2write,vec[0].len,vec[1].len,1);
1169                                        
1170                                 xrun = freebob_am824_xmit(connection->cluster_buffer, 1, offset, dbc, connection);
1171                                
1172                                 if(xrun<0) {
1173                                                 // xrun detected
1174                                         printError("Frame buffer underrun on playback connection %d\n",i);
1175                                         break;
1176                                 }
1177                                        
1178                                 // use the ringbuffer function to write one cluster (handles wrap around)
1179                                 freebob_ringbuffer_write(connection->event_buffer,connection->cluster_buffer,cluster_size);
1180                                        
1181                                 // we advanced one cluster_size
1182                                 bytes2write-=cluster_size;
1183                                        
1184                         } else { //
1185                                
1186                                 if(bytes2write>vec[0].len) {
1187                                         // align to a cluster boundary
1188                                         byteswritten=vec[0].len-(vec[0].len%cluster_size);
1189                                 } else {
1190                                         byteswritten=bytes2write;
1191                                 }
1192                                        
1193                                 debugPrint(DEBUG_LEVEL_WAIT, "W: %d [%d %d] %d\n",bytes2write,vec[0].len,vec[1].len,byteswritten);
1194                                        
1195                                 xrun = freebob_am824_xmit(vec[0].buf, byteswritten/sizeof(quadlet_t)/connection->spec.dimension, offset, dbc, connection);
1196                                        
1197                                 if(xrun<0) {
1198                                                 // xrun detected
1199                                         printError("Frame buffer underrun on playback connection %d\n",i);
1200                                         break;
1201                                 }
1202        
1203                                 freebob_ringbuffer_write_advance(connection->event_buffer, byteswritten);
1204                                 bytes2write -= byteswritten;
1205                         }
1206                                
1207                         // the bytes2write should always be cluster aligned
1208                         assert(bytes2write%cluster_size==0);
1209                                
1210                 }
1211
1212                 debugPrint(DEBUG_LEVEL_WAIT, "W: > %d\n",freebob_ringbuffer_write_space(connection->event_buffer));
1213         }
1214        
1215        
1216         return 0;
1217 }
1218
1219 int freebob_streaming_transfer_buffers(freebob_device_t *dev) {
1220         int err=0;
1221        
1222         err=freebob_streaming_transfer_capture_buffers(dev);
1223         if (err) return err;
1224        
1225         err=freebob_streaming_transfer_playback_buffers(dev);
1226         return err;
1227        
1228 }
1229
1230
1231 int freebob_streaming_write(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) {
1232         int retval;
1233        
1234         freebob_stream_t *stream;
1235         assert(i<dev->nb_playback_streams);
1236        
1237         stream=*(dev->playback_streams+i);
1238         assert(stream);
1239        
1240         retval=freebob_ringbuffer_write(stream->buffer,(char *)buffer,nsamples*sizeof(freebob_sample_t))/sizeof(freebob_sample_t);
1241                
1242         return retval;
1243 }
1244
1245 int freebob_streaming_read(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) {
1246         // this has one ringbuffer too many, but that will be solved shortly
1247         int retval=0;
1248
1249         freebob_stream_t *stream;
1250         assert(i<dev->nb_capture_streams);
1251        
1252         stream=*(dev->capture_streams+i);
1253         assert(stream);
1254        
1255         // now read from the stream ringbuffer
1256         retval=freebob_ringbuffer_read(stream->buffer, (char *)buffer, nsamples*sizeof(freebob_sample_t))/sizeof(freebob_sample_t);     
1257
1258 //      fprintf(stderr,"rb read1 [%02d: %08p %08p %08X, %d, %d]\n",stream->spec.position, stream, stream->buffer, *buffer, nsamples, retval);
1259        
1260         return retval;
1261 }
1262
1263 pthread_t freebob_streaming_get_packetizer_thread(freebob_device_t *dev) {
1264         return dev->packetizer.transfer_thread;
1265 }
1266
1267 /* --------------------- *
1268  * PRIVATE STUFF         *
1269  * --------------------- */
1270  
1271  
1272 unsigned int freebob_streaming_register_generic_stream(freebob_stream_t *stream, freebob_stream_t ***oldset, unsigned int set_size) {
1273         int i;
1274         int found=0;
1275         unsigned int new_set_size;
1276        
1277         freebob_stream_t **new_streams=calloc(set_size+1,sizeof(freebob_stream_t *));
1278         freebob_stream_t **set=*oldset;
1279        
1280         for (i=0;i<set_size;i++) {
1281                 *(new_streams+i)=*(set+i);
1282                 if(*(set+i)==stream) {
1283                         printError("FREEBOB: stream already registered\n");
1284                         found=1;
1285                 }
1286         }
1287         if (!found) {
1288                 *(new_streams+set_size)=stream;
1289                 new_set_size=set_size+1;
1290                
1291                 free(*oldset);
1292                 *oldset=new_streams;
1293         } else {
1294                 free(new_streams);
1295                 new_set_size=set_size;
1296         }
1297         return new_set_size;
1298        
1299 }
1300
1301 void freebob_streaming_register_capture_stream(freebob_device_t *dev, freebob_stream_t *stream) {
1302         dev->nb_capture_streams=
1303                 freebob_streaming_register_generic_stream(
1304                         stream,
1305                         &dev->capture_streams,
1306                         dev->nb_capture_streams);
1307         if (stream->spec.format==IEC61883_STREAM_TYPE_MBLA) {
1308                 dev->nb_synced_capture_streams=
1309                         freebob_streaming_register_generic_stream(
1310                                 stream,
1311                                 &dev->synced_capture_streams,
1312                                 dev->nb_synced_capture_streams);
1313         }
1314 }
1315
1316 void freebob_streaming_register_playback_stream(freebob_device_t *dev, freebob_stream_t *stream) {
1317         dev->nb_playback_streams=
1318                 freebob_streaming_register_generic_stream(
1319                         stream,
1320                         &dev->playback_streams,
1321                         dev->nb_playback_streams);
1322         if (stream->spec.format==IEC61883_STREAM_TYPE_MBLA) {
1323                 dev->nb_synced_playback_streams=
1324                         freebob_streaming_register_generic_stream(
1325                                 stream,
1326                                 &dev->synced_playback_streams,
1327                                 dev->nb_synced_playback_streams);
1328         }
1329 }
1330
1331 static inline int
1332 freebob_streaming_period_complete (freebob_device_t *dev) {
1333         unsigned long i;
1334         //unsigned int period_boundary_bytes=dev->options.period_size*sizeof(freebob_sample_t);
1335        
1336         assert(dev);
1337        
1338         for(i=0; i < dev->nb_connections; i++) {
1339                 freebob_connection_t *connection= &(dev->connections[i]);
1340                 if (connection->status.frames_left > 0) {
1341                         return FALSE;
1342                 }
1343         }
1344         return TRUE;
1345        
1346 #if 0   
1347         for(i=0; i < dev->nb_synced_capture_streams; i++) {
1348                 assert(dev->synced_capture_streams);
1349                 assert(dev->synced_capture_streams[i]);
1350                
1351                 /* We check if there is more than one period of samples in the buffer.
1352                  * if not the period isn't complete yet.
1353                  */
1354                 if (freebob_ringbuffer_read_space(dev->synced_capture_streams[i]->buffer) < period_boundary_bytes) {
1355                         return FALSE;
1356                 }
1357         }
1358        
1359         for(i=0; i < dev->nb_synced_playback_streams; i++) {
1360                 assert(dev->synced_playback_streams);
1361                 assert(dev->synced_playback_streams[i]);
1362                 //FIXME: check this!
1363                 /* We check if there is still one period of samples in the output buffer.
1364                  * if so, the period isn't complete yet.
1365                  */
1366                 if (freebob_ringbuffer_read_space(dev->synced_playback_streams[i]->buffer) > period_boundary_bytes) {
1367                         return FALSE;
1368                 }
1369         }
1370         return TRUE;
1371 #endif
1372 }
1373
1374 static inline void
1375 freebob_streaming_period_reset (freebob_device_t *dev) {
1376 //      unsigned long i;
1377         //unsigned int period_boundary_bytes=dev->options.period_size*sizeof(freebob_sample_t);
1378         unsigned long i;
1379         //unsigned int period_boundary_bytes=dev->options.period_size*sizeof(freebob_sample_t);
1380         printEnter();
1381         assert(dev);
1382        
1383         for(i=0; i < dev->nb_connections; i++) {
1384                 freebob_connection_t *connection= &(dev->connections[i]);
1385                 connection->status.frames_left+=dev->options.period_size;
1386                 // enable poll
1387                 connection->pfd->events=POLLIN;
1388         }
1389         printExit();
1390         return;
1391 }
1392
1393 static inline int
1394 freebob_streaming_xrun_detected_on_connection (freebob_device_t *dev, freebob_connection_t *connection) {
1395         assert((connection));
1396         if (connection->status.xruns>0) {
1397                 return TRUE;
1398         }
1399         return FALSE;
1400 }
1401
1402 static inline int
1403 freebob_streaming_xrun_detected (freebob_device_t *dev, freebob_connection_t **connections, int nb_connections) {
1404         int i;
1405        
1406         for(i=0; i < nb_connections; i++) {
1407                 assert((connections[i]));
1408
1409                 if (freebob_streaming_xrun_detected_on_connection (dev, connections[i])) {
1410                         return TRUE;
1411                 }
1412         }
1413         return FALSE;
1414 }
1415
1416 int freebob_streaming_start_iso_connection(freebob_device_t *dev, freebob_connection_t *connection) {
1417         int err;
1418
1419         err=0;
1420         if (connection->spec.direction == FREEBOB_CAPTURE) {
1421                 connection->status.packets=0;   
1422                 connection->status.dropped=0;           
1423                 if (connection->spec.is_master) { //master connection
1424                         debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO master receive handler on channel %d...\n",connection->iso.iso_channel);
1425                         debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
1426                         raw1394_iso_recv_init(
1427                                         connection->raw_handle,
1428                                         iso_master_receive_handler,
1429                                         connection->iso.buffers*2,  // use 2 times the transmit buffer for the receive buffer
1430                                         AMDTP_MAX_PACKET_SIZE,
1431                                         connection->iso.iso_channel,
1432                                         RAW1394_DMA_BUFFERFILL,
1433                                         connection->iso.irq_interval);
1434
1435                 } else {
1436                                 //slave receive connection
1437                         debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO slave receive handler on channel %d...\n",connection->iso.iso_channel);
1438                         debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n", connection->iso.buffers, AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
1439                         raw1394_iso_recv_init( 
1440                                         connection->raw_handle,
1441                                         iso_slave_receive_handler,
1442                                         connection->iso.buffers*2,  // use 2 times the transmit buffer for the receive buffer
1443                                         AMDTP_MAX_PACKET_SIZE,
1444                                         connection->iso.iso_channel,
1445                                         RAW1394_DMA_BUFFERFILL,
1446                                         connection->iso.irq_interval);
1447                 }
1448                
1449                 debugPrint(DEBUG_LEVEL_STARTUP, "Start ISO receive for connection on channel %d at cycle %d...\n",  connection->iso.iso_channel, connection->iso.startcycle);
1450                        
1451                 err = raw1394_iso_recv_start(
1452                                 connection->raw_handle,
1453                 connection->iso.startcycle,
1454                 -1,//IEC61883_TAG_WITH_CIP,
1455                 0);
1456
1457                 if (err) {
1458                         printError("FREEBOB: couldn't start receiving: %s\n",
1459                                            strerror (errno));
1460                                 // TODO: cleanup
1461                         return err;
1462                 }                                       
1463                
1464         } else if (connection->spec.direction == FREEBOB_PLAYBACK) {
1465                
1466                 if (connection->spec.is_master) { // master connection
1467                         debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO master transmit handler on channel %d...\n",connection->iso.iso_channel);
1468                         debugPrint(DEBUG_LEVEL_STARTUP, "   other mode (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
1469                                
1470                         raw1394_iso_xmit_init(
1471                                         connection->raw_handle,
1472                                         iso_master_transmit_handler,
1473                                         connection->iso.buffers,
1474                                         AMDTP_MAX_PACKET_SIZE,
1475                                         connection->iso.iso_channel,
1476                                         RAW1394_ISO_SPEED_400,
1477                                         connection->iso.irq_interval);                 
1478                 } else {
1479                        
1480                         debugPrint(DEBUG_LEVEL_STARTUP, "Init ISO slave transmit handler on channel %d...\n",connection->iso.iso_channel);
1481                         debugPrint(DEBUG_LEVEL_STARTUP, "   (BUFFER=%d,PACKET_MAX=%d,IRQ=%d)...\n",connection->iso.buffers,AMDTP_MAX_PACKET_SIZE, connection->iso.irq_interval);
1482                         raw1394_iso_xmit_init(
1483                                         connection->raw_handle,
1484                                         iso_slave_transmit_handler,
1485                                         connection->iso.buffers,
1486                                         AMDTP_MAX_PACKET_SIZE,
1487                                         connection->iso.iso_channel,
1488                                         RAW1394_ISO_SPEED_400,
1489                                         connection->iso.irq_interval);
1490                 }               
1491                 debugPrint(DEBUG_LEVEL_STARTUP, "Start ISO transmit for connection on channel %d at cycle %d\n", connection->iso.iso_channel, connection->iso.startcycle);
1492                        
1493                 err=raw1394_iso_xmit_start(
1494                                 connection->raw_handle,
1495                 connection->iso.startcycle,
1496                 connection->iso.prebuffers);
1497
1498                 if (err) {
1499                         printError("FREEBOB: couldn't start transmitting: %s\n",
1500                                            strerror (errno));
1501                                 // TODO: cleanup
1502                         return err;
1503                 }
1504         }
1505         return 0;
1506 }
1507
1508 int freebob_streaming_stop_iso_connection(freebob_device_t *dev, freebob_connection_t *connection) {
1509        
1510         debugPrintWithTimeStamp(DEBUG_LEVEL_STARTUP, "Stop connection on channel %d ...\n", connection->iso.iso_channel);
1511         if (connection->spec.direction == FREEBOB_CAPTURE) {
1512                 raw1394_iso_recv_flush(connection->raw_handle);
1513         } else {
1514                 raw1394_iso_xmit_sync(connection->raw_handle);
1515         }
1516                
1517         raw1394_iso_stop(connection->raw_handle);
1518        
1519         debugPrint(DEBUG_LEVEL_STARTUP, "Shutdown connection on channel %d ...\n", connection->iso.iso_channel);
1520                
1521         raw1394_iso_shutdown(connection->raw_handle);
1522        
1523         return 0;
1524 }
1525
1526 int freebob_streaming_wait_for_sync_stream(freebob_device_t *dev, freebob_connection_t *connection) {
1527         int err;
1528        
1529         debugPrint(DEBUG_LEVEL_STARTUP, "Waiting for the sync stream...\n");
1530        
1531         // start the sync master connection
1532        
1533         connection->iso.startcycle=-1; // don't care when we start this
1534         connection->status.events=0;
1535        
1536         freebob_streaming_start_iso_connection(dev,connection);
1537        
1538         // wait until something is received/sent on the connection
1539         while(connection->status.events==0) {
1540                 err=0;
1541                        
1542                 // get a packet on the sync master connection
1543                 err=raw1394_loop_iterate(connection->raw_handle);
1544                        
1545                 if (err == -1) {
1546                         printError("Possible raw1394 error: %s on sync master connection: %d\n",
1547                                            strerror (errno),connection->spec.id);
1548                 }
1549         }
1550        
1551         freebob_streaming_stop_iso_connection(dev,connection);
1552        
1553         // reset the connection
1554         freebob_streaming_reset_connection(dev, connection);
1555        
1556         // FIXME: only works for sync on receive stream because we don't prefill.
1557        
1558         debugPrint(DEBUG_LEVEL_STARTUP, "  stream is running.\n");
1559
1560         return 0;
1561 }
1562
1563 int freebob_streaming_start_iso(freebob_device_t *dev) {
1564         freebob_connection_t *connection=NULL;
1565         unsigned int c;
1566 //      int err;
1567
1568         // when starting the thread, we should wait with iterating the slave connections
1569         // until the master connection has processed some samples, because the devices
1570         // tend to start with a stream of no-data packets, leading to xruns on slave
1571         // transmit, leading to multiple restarts of the thread, which doesn't work correctly (yet)
1572 /*      debugPrint(DEBUG_LEVEL_STARTUP, "Waiting for the sync master...\n");
1573        
1574        
1575         connection=dev->sync_master_connection;
1576        
1577         // start the sync master connection
1578        
1579         connection->iso.startcycle=-1; // don't care when we start this
1580         connection->status.events=0;
1581        
1582         freebob_streaming_start_iso_connection(dev,connection);*/
1583        
1584         // wait until something is received/sent on the connection
1585 //      while(connection->status.events==0) {
1586 //              err=0;
1587 //             
1588 //              // get a packet on the sync master connection
1589 //              err=raw1394_loop_iterate(connection->raw_handle);
1590 //             
1591 //              if (err == -1) {
1592 //                      printError("Possible raw1394 error: %s on sync master connection: %d\n",
1593 //                                         strerror (errno),connection->spec.id);
1594 //              }
1595 //      }
1596        
1597 #define NB_CYCLES_TO_SKIP 100
1598
1599         // get the last timestamp & calculate the start times for the connections
1600         // start ISO xmit/receive
1601        
1602         // we introduce some delay to let the freebob devices start streaming.
1603         usleep(2000);
1604         freebob_streaming_wait_for_sync_stream(dev, dev->sync_master_connection);
1605        
1606         for(c=0; c < dev->nb_connections; c++) {
1607                 connection= &(dev->connections[c]);
1608                
1609 //              if(connection != dev->sync_master_connection) {
1610                        
1611                         connection->iso.startcycle=(dev->sync_master_connection->status.last_timestamp.cycle+NB_CYCLES_TO_SKIP)%8000;
1612                        
1613 //                      connection->iso.startcycle=0;
1614                        
1615                         freebob_streaming_start_iso_connection(dev, connection);
1616 //              }       
1617         }       
1618        
1619         return 0;
1620 }
1621
1622 int freebob_streaming_stop_iso(freebob_device_t *dev) {
1623         unsigned int c;
1624         // stop ISO xmit/receive
1625         for(c=0; c < dev->nb_connections; c++) {
1626                 freebob_connection_t *connection= &(dev->connections[c]);
1627
1628                 freebob_streaming_stop_iso_connection(dev,connection);
1629         }
1630         return 0;
1631 }
1632
1633 /*
1634  * The thread responsible for packet iteration
1635  */
1636
1637 void * freebob_iso_packet_iterator(void *arg)
1638 {
1639
1640         freebob_device_t * dev=(freebob_device_t *) arg;
1641         int err;
1642 //      int cycle=0;
1643         int underrun_detected=0;
1644        
1645         int notdone=TRUE;
1646        
1647         freebob_connection_t *connection=NULL;
1648        
1649         assert(dev);
1650         assert(dev->sync_master_connection);
1651         assert(dev->connections);
1652        
1653         debugPrint(DEBUG_LEVEL_STARTUP, "Entering packetizer thread...\n");
1654        
1655         freebob_streaming_start_iso(dev);
1656
1657         freebob_streaming_print_bufferfill(dev);
1658         // start xmit/receive
1659         debugPrint(DEBUG_LEVEL_STARTUP, "Go Go Go!!!\n");
1660        
1661         //sem_post(&dev->packetizer.transfer_ack);
1662 #define POLL_BASED     
1663 #ifdef POLL_BASED
1664         while (dev->packetizer.run && !underrun_detected) {
1665                 //sem_wait(&dev->packetizer.transfer_ack);
1666                
1667                 freebob_streaming_period_reset(dev);
1668                
1669                 dev->watchdog_check = 1;
1670                
1671                 notdone=TRUE;
1672                
1673                 while(notdone) {
1674                        
1675                         err = poll (dev->pfds, dev->nfds, -1);
1676                        
1677                         if (err == -1) {
1678                                 if (errno == EINTR) {
1679                                         continue;
1680                                 }
1681                                 printError("poll error: %s\n", strerror (errno));
1682                                 dev->packetizer.status = -2;
1683                                 dev->packetizer.retval = 0;
1684                                 notdone=FALSE;
1685                                 break;
1686                         }
1687                        
1688                         int i=0;
1689                
1690                         for (i = 0; i < dev->nfds; i++) {
1691                                 if (dev->pfds[i].revents & POLLERR) {
1692                                         printError ("error on fd for %d\n",i);
1693                                 }
1694
1695                                 if (dev->pfds[i].revents & POLLHUP) {
1696                                         printError ("hangup on fd for %d\n",i);
1697                                 }
1698                                
1699 //                              if(dev->pfds[i].revents & (POLLIN | POLLPRI)) {
1700                                 if(dev->pfds[i].revents & (POLLIN)) {
1701                                         // FIXME: this can segfault
1702                                         connection=dev->fdmap[i];
1703                                        
1704                                         assert(connection);
1705                                        
1706                                         err = raw1394_loop_iterate (connection->raw_handle);
1707                                        
1708                                         // detect underruns on the connection
1709                                         if (freebob_streaming_xrun_detected_on_connection(dev,connection)) {
1710                                                 printError("Xrun on connection %d\n", connection->spec.id);
1711                                                 underrun_detected=TRUE;
1712                                                 break; // we can exit as the underrun handler will flush the buffers anyway
1713                                         }
1714                                
1715                                         if (err == -1) {
1716                                                 printError ("possible raw1394 error: %s\n", strerror (errno));
1717                                                 dev->packetizer.status = -2;
1718                                                 dev->packetizer.retval = 0;
1719                                                 notdone=FALSE;
1720                                                 break;
1721                                         }
1722                                 }
1723
1724                                
1725
1726                         }
1727
1728                         notdone=(!freebob_streaming_period_complete(dev) && !underrun_detected && (dev->packetizer.run)) && notdone;
1729                 }
1730                
1731                 if(underrun_detected) {
1732                         dev->xrun_detected=TRUE;
1733                         //underrun_detected=0;
1734                 }
1735
1736 #else
1737         while (dev->packetizer.run && !underrun_detected) {
1738                 //sem_wait(&dev->packetizer.transfer_ack);
1739                
1740                 freebob_streaming_period_reset(dev);
1741                        
1742                 dev->watchdog_check = 1;
1743                        
1744                 notdone=TRUE;
1745                        
1746                 while(notdone) {
1747                                
1748                         err=0;
1749                        
1750                         // this makes sure the sync_master finishes before the others finish
1751                         connection=dev->sync_master_connection;
1752                         if (connection->status.frames_left > 0) {
1753                                 // process a packet on the sync master connection
1754                                 err=raw1394_loop_iterate(connection->raw_handle);
1755                                
1756                                 if (err == -1) {
1757                                         printError("Possible raw1394 error: %s on sync master connection: %d\n",
1758                                                         strerror (errno),connection->spec.id);
1759                                                
1760                                         dev->packetizer.status = -2;
1761                                         dev->packetizer.retval = 0;
1762                                         notdone=FALSE;
1763                                         break;
1764                                 }
1765                                
1766                                 // detect underruns on the sync master connection
1767                                 if (freebob_streaming_xrun_detected(dev,&connection,1)) {
1768                                         printError("Xrun on sync master connection %d\n", connection->spec.id);
1769                                         underrun_detected=TRUE;
1770                                         break; // we can exit as the underrun handler will flush the buffers anyway
1771                                 }
1772                         }
1773                                
1774                        
1775                         // now iterate on the slave connections
1776                         int c;
1777                         for(c=0; c<dev->nb_connections; c++) {
1778
1779                                 connection = &(dev->connections[c]);
1780                                
1781                                 // skip the sync master and the connections that are finished
1782                                 //if ((connection == dev->sync_master_connection) || (connection->status.frames_left <= 0))
1783                                        
1784                                 if ((connection == dev->sync_master_connection))
1785                                                 continue;
1786                                
1787                                 err=raw1394_loop_iterate(connection->raw_handle);
1788                                
1789                                 if (err == -1) {
1790                                         printError("Possible raw1394 error: %s on connection: %d\n",
1791                                                         strerror (errno),connection->spec.id);
1792                                         dev->packetizer.status = -2;
1793                                         dev->packetizer.retval = 0;
1794                                         notdone=FALSE;
1795                                 }
1796                                
1797                                 // detect underruns
1798                                 if (freebob_streaming_xrun_detected(dev,&connection,1)) {
1799                                         printError("Xrun on slave connection %d\n", connection->spec.id);
1800                                         underrun_detected=TRUE;
1801                                         break; // we can exit as the underrun handler will flush the buffers anyway
1802                                 }
1803                         }
1804                                
1805                         notdone=(!freebob_streaming_period_complete(dev) && !underrun_detected && (dev->packetizer.run)) && notdone;
1806                 }
1807                
1808                 if(underrun_detected) {
1809                         dev->xrun_detected=TRUE;
1810                                 //underrun_detected=0;
1811                 }
1812        
1813 #endif
1814                 // notify the waiting thread
1815 #ifdef DEBUG
1816                 debugPrint(DEBUG_LEVEL_HANDLERS, "Post semaphore ");
1817                 int c;
1818                 for(c=0; c<dev->nb_connections; c++) {
1819                         connection = &(dev->connections[c]);
1820                         debugPrintShort(DEBUG_LEVEL_HANDLERS,"[%d: %d]",c,connection->status.frames_left);
1821                 }
1822                 debugPrintShort(DEBUG_LEVEL_HANDLERS,"\n");
1823 #endif
1824
1825                 sem_post(&dev->packetizer.transfer_boundary);
1826
1827 #ifdef DEBUG
1828                 // update the packet counter
1829                 if((dev->sync_master_connection->status.packets - dev->sync_master_connection->status.total_packets_prev) > 1024*2) {
1830 //              if(1) {
1831                         unsigned int i;
1832                         debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER,"\r -> ");
1833                        
1834                         for(i=0; i < dev->nb_connections; i++) {
1835                                 freebob_connection_t *connection= &(dev->connections[i]);
1836                                 assert(connection);
1837                                
1838                                 /* Debug info format:
1839                                 * [direction, packetcount, bufferfill, packetdrop
1840                                 */
1841                                 debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER,"[%s, %02d, %10d, %04d, %4d, (R: %04d)]",
1842                                         (connection->spec.direction==FREEBOB_CAPTURE ? "C" : "P"),
1843                                         connection->status.fdf,
1844                                         connection->status.packets,
1845                                         connection->status.last_cycle,
1846                                         connection->status.dropped,
1847                                         freebob_ringbuffer_read_space(connection->event_buffer)/(sizeof(quadlet_t)*connection->spec.dimension)
1848                                    );
1849                         }
1850        
1851                         debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER," XRUNS (%2d)",dev->xrun_count);     
1852                         fflush (stderr);
1853                        
1854                         dev->sync_master_connection->status.total_packets_prev=dev->sync_master_connection->status.packets;
1855                 }
1856
1857 #endif
1858
1859         }
1860        
1861         freebob_streaming_stop_iso(dev);
1862        
1863         debugPrint(DEBUG_LEVEL_STARTUP, "Exiting packetizer thread...\n");
1864        
1865        
1866         pthread_exit (0);       
1867 }
1868
1869 void freebob_streaming_append_master_timestamp(freebob_device_t *dev, freebob_timestamp_t *t) {
1870         int c;
1871 //      int retval;
1872         freebob_connection_t *connection;
1873        
1874         assert(dev);
1875        
1876         for(c=0; c<dev->nb_connections; c++) {
1877
1878                 connection = &(dev->connections[c]);
1879                
1880                 // skip the sync master
1881                 if ((connection == dev->sync_master_connection))
1882                         continue;
1883                
1884                 // write the timestamp
1885
1886 /*              retval=freebob_ringbuffer_write(connection->timestamp_buffer,(char *)t,sizeof(freebob_timestamp_t));
1887                
1888                 if(retval!=sizeof(unsigned int)) {
1889                         printError("Timestamp buffer overrun on connection %d!\n",c);
1890                 }
1891 */             
1892         }
1893 }
1894
1895 int freebob_streaming_decode_midi(freebob_connection_t *connection,
1896                                                                   quadlet_t* events,
1897                                                                   unsigned int nsamples,
1898                                                                   unsigned int dbc
1899                                                                  ) {
1900         quadlet_t *target_event;
1901        
1902         assert (connection);
1903         assert (events);
1904
1905         freebob_stream_t *stream;
1906        
1907         unsigned int j=0;
1908         unsigned int s=0;
1909         int written=0;
1910         quadlet_t *buffer;
1911        
1912         for (s=0;s<connection->nb_streams;s++) {
1913                 stream=&connection->streams[s];
1914                
1915                 assert (stream);
1916                 assert (stream->spec.position < connection->spec.dimension);
1917                 assert(stream->user_buffer);
1918                
1919                 if (stream->spec.format == IEC61883_STREAM_TYPE_MIDI) {
1920                         /* idea:
1921                         spec says: current_midi_port=(dbc+j)%8;
1922                         => if we start at (dbc+stream->location-1)%8 [due to location_min=1],
1923                         we'll start at the right event for the midi port.
1924                         => if we increment j with 8, we stay at the right event.
1925                         */
1926                         buffer=((quadlet_t *)(stream->user_buffer));
1927                         written=0;
1928                        
1929 //                      debugPrint(DEBUG_LEVEL_PACKETCOUNTER, "Stream %d,%d,%d is midi, dbc=%d  [",s,stream->spec.location,stream->spec.position,dbc);
1930                                                
1931                         for(j = (dbc%8)+stream->spec.location-1; j < nsamples; j += 8) {
1932                                 target_event=(quadlet_t *)(events + ((j * connection->spec.dimension) + stream->spec.position));
1933                                 quadlet_t sample_int=ntohl(*target_event);
1934                                 if(IEC61883_AM824_GET_LABEL(sample_int) != IEC61883_AM824_LABEL_MIDI_NO_DATA) {
1935                                         *(buffer)=(sample_int >> 16);
1936 //                                      debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER, "%08X-%08X-%d ",*target_event,*buffer,((j * connection->spec.dimension) + stream->spec.position));
1937                                         buffer++;
1938                                         written++;
1939                                 }
1940                         }
1941                        
1942                         int written_to_rb=freebob_ringbuffer_write(stream->buffer, (char *)(stream->user_buffer), written*sizeof(quadlet_t))/sizeof(quadlet_t);
1943                         if(written_to_rb<written) {
1944                                 printMessage("MIDI OUT bytes lost (%d/%d)",written_to_rb,written);
1945                         }
1946 //                      debugPrintShort(DEBUG_LEVEL_PACKETCOUNTER, "]\n");
1947                        
1948                        
1949                         /*                                             
1950                         for(j = 0; j < nsamples; j += 1) {
1951                                 target_event=(quadlet_t *)(events + j);
1952                                 quadlet_t sample_int=ntohl(*target_event);
1953                                 *(buffer)=sample_int;
1954                                 buffer++;
1955                                 written++;
1956
1957                         }
1958                         written=freebob_ringbuffer_write(stream->buffer, (char *)(stream->user_buffer), written*sizeof(quadlet_t))/sizeof(quadlet_t);
1959                         */
1960                 }
1961         }
1962         return 0;
1963        
1964 }
1965
1966 /*
1967  * according to the MIDI over 1394 spec, we are only allowed to send a maximum of one midi byte every 320usec
1968  * therefore we can only send one byte on 1 out of 3 iso cycles (=325usec)
1969  */
1970
1971 int freebob_streaming_encode_midi(freebob_connection_t *connection,
1972                                                                 quadlet_t* events,
1973                                                                 unsigned int nsamples,
1974                                                                 unsigned int dbc
1975                                                                 ) {
1976         quadlet_t *target_event;
1977        
1978         assert (connection);
1979         assert (events);
1980
1981         freebob_stream_t *stream;
1982
1983         unsigned int j=0;
1984         unsigned int s=0;
1985         int read=0;
1986         quadlet_t *buffer;
1987        
1988         for (s=0;s<connection->nb_streams;s++) {
1989                 stream=&connection->streams[s];
1990
1991                 assert (stream);
1992                 assert (stream->spec.position < connection->spec.dimension);
1993                 assert(stream->user_buffer);
1994
1995                 if (stream->spec.format == IEC61883_STREAM_TYPE_MIDI) {
1996                         // first prefill the buffer with NO_DATA's on all time muxed channels
1997                         for(j=0; (j < nsamples); j++) {
1998                                 target_event=(quadlet_t *)(events + ((j * connection->spec.dimension) + stream->spec.position));
1999                                
2000                                 *target_event=htonl(IEC61883_AM824_SET_LABEL(0,IEC61883_AM824_LABEL_MIDI_NO_DATA));
2001
2002                         }
2003                        
2004                         /* idea:
2005                                 spec says: current_midi_port=(dbc+j)%8;
2006                                 => if we start at (dbc+stream->location-1)%8 [due to location_min=1],
2007                                 we'll start at the right event for the midi port.
2008                                 => if we increment j with 8, we stay at the right event.
2009                         */
2010                        
2011                         if(stream->midi_counter<=0) { // we can send a byte
2012                                 read=freebob_ringbuffer_read(stream->buffer, (char *)(stream->user_buffer), 1*sizeof(quadlet_t))/sizeof(quadlet_t);
2013                                 if(read) {
2014                                         j = (dbc%8)+stream->spec.location-1;
2015                                         target_event=(quadlet_t *)(events + ((j * connection->spec.dimension) + stream->spec.position));
2016                                         buffer=((quadlet_t *)(stream->user_buffer));
2017                                
2018                                         *target_event=htonl(IEC61883_AM824_SET_LABEL((*buffer)<<16,IEC61883_AM824_LABEL_MIDI_1X));
2019                                         stream->midi_counter=3; // only if we send a byte, we reset the counter
2020                                 }
2021                         } else {
2022                                 stream->midi_counter--;
2023                         }
2024                         /*                     
2025                         for(j=0; (j < nsamples); j++) {
2026                                 target_event=(quadlet_t *)(events + ((j * connection->spec.dimension) + stream->spec.position));
2027                                
2028                                 hexDumpQuadlets( target_event,1);
2029                         }
2030                         */
2031                        
2032                 }
2033         }
2034         return 0;
2035
2036 }
2037
2038
2039 /**
2040  * ISO send/receive callback handlers
2041  */
2042
2043 static enum raw1394_iso_disposition
2044 iso_master_receive_handler(raw1394handle_t handle, unsigned char *data,
2045         unsigned int length, unsigned char channel,
2046         unsigned char tag, unsigned char sy, unsigned int cycle,
2047         unsigned int dropped)
2048 {
2049     enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
2050 //      static quadlet_t cntr=0;
2051        
2052 //      int xrun=0;
2053
2054         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
2055         assert(connection);
2056        
2057         struct iec61883_packet *packet = (struct iec61883_packet *) data;
2058         assert(packet);
2059        
2060         // FIXME: dropped packets are very bad when transmitting and the other side is sync'ing on that!
2061         //connection->status.packets+=dropped;
2062         connection->status.dropped+=dropped;
2063        
2064         connection->status.last_cycle=cycle;
2065
2066         if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) {
2067                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
2068                
2069                 // add the data payload to the ringbuffer
2070
2071                 assert(connection->spec.dimension == packet->dbs);
2072                
2073 //              if(nevents>2) {
2074 //                      quadlet_t *t=(quadlet_t *)(data+8);
2075 //                      t+=2;
2076 //                     
2077 //                      t++;
2078 //                      *t=0x40000000 | ((cntr) & 0xFFFFFF);
2079 //                      t++;
2080 //                      *t=0x40000000 | ((cntr++) & 0xFFFFFF);
2081 //              }
2082                
2083                 if (freebob_ringbuffer_write(
2084                                 connection->event_buffer,(char *)(data+8),
2085                                 nevents*sizeof(quadlet_t)*connection->spec.dimension) <
2086                                 nevents*sizeof(quadlet_t)*connection->spec.dimension)
2087                 {
2088                         printError("MASTER RCV: Buffer overrun!\n");
2089                         connection->status.xruns++;
2090                         retval=RAW1394_ISO_DEFER;
2091                 } else {
2092                         retval=RAW1394_ISO_OK;
2093                         // we cannot offload midi encoding due to the need for a dbc value
2094                         freebob_streaming_decode_midi(connection,(quadlet_t *)(data+8), nevents, packet->dbc);
2095                 }
2096                
2097                 // keep the frame counter
2098                 connection->status.frames_left -= nevents;
2099                
2100                 // keep track of the total amount of events received
2101                 connection->status.events+=nevents;
2102                
2103                 connection->status.fdf=packet->fdf;
2104                
2105                 connection->status.last_timestamp.cycle=cycle;
2106                 connection->status.last_timestamp.syt=packet->syt;
2107                
2108                 freebob_streaming_append_master_timestamp(connection->parent, &connection->status.last_timestamp);
2109         } else {
2110                 // discard packet
2111                 // can be important for sync though
2112         }
2113
2114         // one packet received
2115         connection->status.packets++;
2116
2117         if(packet->dbs) {
2118                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
2119                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
2120                         "MASTER RCV: %08d, CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %4d, info->packets=%4d, events=%4d, %d, %d\n",
2121                         cycle,
2122                         channel, packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, length,
2123                         ((length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped,
2124                         connection->status.packets, connection->status.events, connection->status.frames_left,
2125                         nevents);
2126         }       
2127
2128         if((connection->status.frames_left<=0)) {
2129                 connection->pfd->events=0;
2130                 return RAW1394_ISO_DEFER;
2131         }
2132         if( (!(connection->status.packets % 2))) {
2133                 return RAW1394_ISO_DEFER;
2134         }
2135         return retval;
2136 }
2137
2138
2139 static enum raw1394_iso_disposition
2140                 iso_slave_receive_handler(raw1394handle_t handle, unsigned char *data,
2141                                                                   unsigned int length, unsigned char channel,
2142                                                                   unsigned char tag, unsigned char sy, unsigned int cycle,
2143                                                                   unsigned int dropped)
2144 {
2145         enum raw1394_iso_disposition retval=RAW1394_ISO_OK;
2146         /* slave receive is easy if you assume that the connections are synced
2147         * Synced connections have matched data rates, so just receiving and calling the rcv handler would
2148         * suffice in this case. As the connection is externally matched to the master connection, the buffer fill
2149         * will be ok.
2150         */
2151                
2152 //      int xrun=0;
2153
2154         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
2155         assert(connection);
2156        
2157         struct iec61883_packet *packet = (struct iec61883_packet *) data;
2158         assert(packet);
2159        
2160         // FIXME: dropped packets are very bad when transmitting and the other side is sync'ing on that!
2161         //connection->status.packets+=dropped;
2162         connection->status.dropped+=dropped;
2163
2164         connection->status.last_cycle=cycle;
2165
2166        
2167         if((packet->fmt == 0x10) && (packet->fdf != 0xFF) && (packet->dbs>0) && (length>=2*sizeof(quadlet_t))) {
2168                 unsigned int nevents=((length / sizeof (quadlet_t)) - 2)/packet->dbs;
2169                 connection->status.fdf=packet->fdf;
2170                
2171                 // add the data payload to the ringbuffer
2172
2173                 assert(connection->spec.dimension == packet->dbs);
2174
2175                 if (freebob_ringbuffer_write(
2176                                         connection->event_buffer,(char *)(data+8),
2177                                         nevents*sizeof(quadlet_t)*connection->spec.dimension) <
2178                         nevents*sizeof(quadlet_t)*connection->spec.dimension)
2179                 {
2180                         printError("SLAVE RCV: Buffer overrun!\n");
2181                         connection->status.xruns++;
2182                         retval=RAW1394_ISO_DEFER;
2183                 } else {
2184                         retval=RAW1394_ISO_OK;
2185                         // we cannot offload midi encoding due to the need for a dbc value
2186                         freebob_streaming_decode_midi(connection,(quadlet_t *)(data+8), nevents, packet->dbc);
2187                 }
2188
2189                 connection->status.frames_left-=nevents;
2190                
2191                 // keep track of the total amount of events received
2192                 connection->status.events+=nevents;
2193         } else {
2194                 // discard packet
2195                 // can be important for sync though
2196         }
2197
2198         // one packet received
2199         connection->status.packets++;
2200        
2201         if(packet->dbs) {
2202                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
2203                                                                 "SLAVE RCV: CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %6d\n",
2204                                                                 channel, packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, length,
2205                                                                 ((length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped);
2206         }
2207                
2208                
2209         if((connection->status.frames_left<=0)) {
2210                 connection->pfd->events=0;
2211                 return RAW1394_ISO_DEFER;
2212         }
2213         if( (!(connection->status.packets % 2))) {
2214                 return RAW1394_ISO_DEFER;
2215         }
2216         return retval;
2217 }
2218
2219 /**
2220  * The master transmit handler.
2221  *
2222  * This is the most difficult, because we have to generate timing information ourselves.
2223  *
2224  */
2225
2226 /*
2227  Includes code from libiec61883
2228  */
2229 static enum raw1394_iso_disposition
2230 iso_master_transmit_handler(raw1394handle_t handle,
2231                 unsigned char *data, unsigned int *length,
2232                 unsigned char *tag, unsigned char *sy,
2233                 int cycle, unsigned int dropped)
2234 {
2235         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
2236         assert(connection);
2237        
2238         struct iec61883_packet *packet = (struct iec61883_packet *) data;
2239         assert(packet);
2240         assert(length);
2241         assert(tag);
2242         assert(sy);     
2243        
2244         // construct the packet cip
2245         int nevents = iec61883_cip_fill_header (handle, &connection->status.cip, packet);
2246 //      int xrun=0;
2247         int nsamples=0;
2248         int bytes_read;
2249        
2250         freebob_timestamp_t tstamp;
2251        
2252 //      unsigned int syt;
2253
2254         connection->status.last_cycle=cycle;
2255        
2256         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
2257        
2258         int i;
2259         // if packets are dropped, also drop the same amount of timestamps from the ringbuffer
2260         for (i=0;i<dropped;i++) {
2261                 freebob_ringbuffer_read(connection->timestamp_buffer,(char *)&tstamp,sizeof(freebob_timestamp_t));
2262         }
2263                
2264 // debug
2265         if(packet->fdf != 0xFF) {
2266                 connection->status.fdf=packet->fdf;
2267         }
2268
2269         if (nevents > 0) {
2270                 nsamples = nevents;
2271         }
2272         else {
2273                 if (connection->status.cip.mode == IEC61883_MODE_BLOCKING_EMPTY) {
2274                         nsamples = 0;
2275                 }
2276                 else {
2277                         nsamples = connection->status.cip.syt_interval;
2278                 }
2279         }
2280        
2281         // dropped packets are very bad when transmitting and the other side is sync'ing on that!
2282         //connection->status.packets+=dropped;
2283         connection->status.dropped += dropped;
2284                
2285         if (nsamples > 0) {
2286                
2287                 if(freebob_ringbuffer_read(connection->timestamp_buffer,(char *)&tstamp,sizeof(freebob_timestamp_t))) {
2288                         packet->syt=tstamp.syt+connection->total_delay;
2289                 }
2290
2291                 assert(connection->spec.dimension == packet->dbs);
2292
2293                 if ((bytes_read=freebob_ringbuffer_read(connection->event_buffer,(char *)(data+8),nsamples*sizeof(quadlet_t)*connection->spec.dimension)) <
2294                                    nsamples*sizeof(quadlet_t)*connection->spec.dimension)
2295                 {
2296                         printError("MASTER XMT: Buffer underrun! (%d / %d) (%d / %d )\n",
2297                                            bytes_read,nsamples*sizeof(quadlet_t)*connection->spec.dimension,
2298                                            freebob_ringbuffer_read_space(connection->event_buffer),0);
2299                         connection->status.xruns++;
2300                         retval=RAW1394_ISO_DEFER;
2301                         nsamples=0;
2302                 } else {
2303                         retval=RAW1394_ISO_OK;
2304                         // we cannot offload midi encoding due to the need for a dbc value
2305                         freebob_streaming_encode_midi(connection,(quadlet_t *)(data+8), nevents, packet->dbc);
2306                 }
2307         }
2308        
2309 //      if (xrun) {
2310 //              printError("SLAVE XMT: Buffer underrun!\n");
2311 //              connection->status.xruns++;
2312 //              retval=RAW1394_ISO_DEFER;
2313 //              nsamples=0;
2314 //      }
2315
2316         *length = nsamples * connection->spec.dimension * sizeof (quadlet_t) + 8;
2317         *tag = IEC61883_TAG_WITH_CIP;
2318         *sy = 0;
2319        
2320         // keep track of the total amount of events transmitted
2321         connection->status.events+=nsamples;
2322        
2323         connection->status.frames_left-=nsamples;
2324                
2325         // one packet transmitted
2326         connection->status.packets++;
2327
2328         if(packet->dbs) {
2329                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
2330                                                                 "MASTER XMT: %08d, CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %4d, info->packets=%4d, events=%4d, %d, %d %d\n", cycle,
2331                                                                 connection->iso.iso_channel,  packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, *length,((*length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped,
2332                                                                 connection->status.packets, connection->status.events, connection->status.frames_left,
2333                                                                 nevents, nsamples);
2334         }
2335         // TODO: the -100 should be derrived from the buffer size
2336         if((connection->status.frames_left<=0)) {
2337                 connection->pfd->events=0;
2338                 return RAW1394_ISO_DEFER;
2339         }
2340         if( (!(connection->status.packets % 2))) {
2341                 return RAW1394_ISO_DEFER;
2342         }
2343         return retval;
2344
2345 }
2346
2347 static enum raw1394_iso_disposition
2348                 iso_slave_transmit_handler(raw1394handle_t handle,
2349                                                                    unsigned char *data, unsigned int *length,
2350                                                                    unsigned char *tag, unsigned char *sy,
2351                                                                    int cycle, unsigned int dropped)
2352 {
2353         freebob_connection_t *connection=(freebob_connection_t *) raw1394_get_userdata (handle);
2354         assert(connection);
2355        
2356         struct iec61883_packet *packet = (struct iec61883_packet *) data;
2357         assert(packet);
2358         assert(length);
2359         assert(tag);
2360         assert(sy);     
2361        
2362         // construct the packet cip
2363         struct iec61883_cip old_cip;
2364         memcpy(&old_cip,&connection->status.cip,sizeof(struct iec61883_cip));
2365        
2366         int nevents = iec61883_cip_fill_header (handle, &connection->status.cip, packet);
2367 //      int xrun=0;
2368         int nsamples=0;
2369         int bytes_read;
2370        
2371         freebob_timestamp_t tstamp;
2372        
2373 //      unsigned int syt;
2374         connection->status.last_cycle=cycle;
2375        
2376         enum raw1394_iso_disposition retval = RAW1394_ISO_OK;
2377        
2378         int i;
2379         // if packets are dropped, also drop the same amount of timestamps from the ringbuffer
2380         for (i=0;i<dropped;i++) {
2381                 freebob_ringbuffer_read(connection->timestamp_buffer,(char *)&tstamp,sizeof(freebob_timestamp_t));
2382         }
2383        
2384 // debug
2385         if(packet->fdf != 0xFF) {
2386                 connection->status.fdf=packet->fdf;
2387         }
2388
2389         if (nevents > 0) {
2390                 nsamples = nevents;
2391         }
2392         else {
2393                 if (connection->status.cip.mode == IEC61883_MODE_BLOCKING_EMPTY) {
2394                         nsamples = 0;
2395                 }
2396                 else {
2397                         nsamples = connection->status.cip.syt_interval;
2398                 }
2399         }
2400        
2401         // dropped packets are very bad when transmitting and the other side is sync'ing on that!
2402         //connection->status.packets+=dropped;
2403         connection->status.dropped += dropped;
2404                
2405         if (nsamples > 0) {
2406                 int bytes_to_read=nsamples*sizeof(quadlet_t)*connection->spec.dimension;
2407
2408                 if(freebob_ringbuffer_read(connection->timestamp_buffer,(char *)&tstamp,sizeof(freebob_timestamp_t))) {
2409                         packet->syt=tstamp.syt+connection->total_delay;
2410                 }
2411
2412                 assert(connection->spec.dimension == packet->dbs);
2413
2414                 if ((bytes_read=freebob_ringbuffer_read(connection->event_buffer,(char *)(data+8),bytes_to_read)) <
2415                         bytes_to_read)
2416                 {
2417                         /* there is no more data in the ringbuffer */
2418                        
2419                         /* If there are already more than on period
2420                         * of frames transfered to the XMIT buffer, there is no xrun.
2421                         *
2422                         */
2423                         if(connection->status.frames_left<=0) {
2424                                 // we stop processing this untill the next period boundary
2425                                 // that's when new data is ready
2426                                
2427                                 connection->pfd->events=0;
2428                                
2429                                 // reset the cip to the old value
2430                                 memcpy(&connection->status.cip,&old_cip,sizeof(struct iec61883_cip));
2431
2432                                 // retry this packed
2433                                 retval=RAW1394_ISO_AGAIN;
2434                                 nsamples=0;
2435                         } else {
2436                                 printError("SLAVE XMT : Buffer underrun! %d (%d / %d) (%d / %d )\n",
2437                                            connection->status.frames_left, bytes_read,bytes_to_read,
2438                                            freebob_ringbuffer_read_space(connection->event_buffer),0);
2439                                 connection->status.xruns++;
2440                                 retval=RAW1394_ISO_DEFER;
2441                                 nsamples=0;
2442                         }
2443                 } else {
2444                         retval=RAW1394_ISO_OK;
2445                         // we cannot offload midi encoding due to the need for a dbc value
2446                         freebob_streaming_encode_midi(connection,(quadlet_t *)(data+8), nevents, packet->dbc);
2447                 }
2448 //              hexDumpQuadlets( data,nsamples*connection->spec.dimension+2);
2449         }
2450        
2451         *length = nsamples * connection->spec.dimension * sizeof (quadlet_t) + 8;
2452         *tag = IEC61883_TAG_WITH_CIP;
2453         *sy = 0;
2454        
2455         // keep track of the total amount of events transmitted
2456         connection->status.events+=nsamples;
2457        
2458         connection->status.frames_left-=nsamples;
2459                
2460         // one packet transmitted
2461         connection->status.packets++;
2462
2463         if(packet->dbs) {
2464                 debugPrintWithTimeStamp(DEBUG_LEVEL_HANDLERS_LOWLEVEL,
2465                                                                 "SLAVE XMT : %08d, CH = %d, FDF = %X. SYT = %6d, DBS = %3d, DBC = %3d, FMT = %3d, LEN = %4d (%2d), DROPPED = %4d, info->packets=%4d, events=%4d, %d, %d %d\n", cycle,
2466                                                                 connection->iso.iso_channel,  packet->fdf,packet->syt,packet->dbs,packet->dbc,packet->fmt, *length,((*length / sizeof (quadlet_t)) - 2)/packet->dbs, dropped,
2467                                                                 connection->status.packets, connection->status.events, connection->status.frames_left,
2468                                                                 nevents, nsamples);
2469         }
2470
2471 /*      if((connection->status.frames_left<=0)) {
2472                 connection->pfd->events=0;
2473                 return RAW1394_ISO_DEFER;
2474         }
2475 */
2476 /*      if( (!(connection->status.packets % 2))) {
2477                 return RAW1394_ISO_DEFER;
2478         }*/
2479         return retval;
2480
2481 }
2482
2483 /*
2484  * Decoders and encoders
2485  */
2486        
2487 static inline int 
2488 freebob_decode_events_to_stream(freebob_connection_t *connection,
2489                                                                 freebob_stream_t *stream,
2490                                                                 quadlet_t* events,
2491                                                                 unsigned int nsamples,
2492                                                                 unsigned int dbc
2493                                                                 ) {
2494         quadlet_t *target_event;
2495         int do_ringbuffer_write=0;
2496        
2497         assert (stream);
2498         assert (connection);
2499         assert (events);
2500         assert (stream->spec.position < connection->spec.dimension);
2501                
2502         freebob_sample_t *buffer=NULL;
2503         float *floatbuff=NULL;
2504
2505         const float multiplier = 1.0f / (float)(1 << 23);
2506        
2507         assert(stream->user_buffer);
2508        
2509         switch(stream->buffer_type) {
2510                 case freebob_buffer_type_per_stream:
2511                 default:
2512 //                      assert(nsamples < dev->options.period_size);
2513                        
2514                         // use the preallocated buffer (at init time)
2515                         buffer=((freebob_sample_t *)(stream->user_buffer))+stream->user_buffer_position;
2516                        
2517                         do_ringbuffer_write=1;
2518                         break;
2519                                
2520                 case freebob_buffer_type_uint24:
2521                         buffer=((freebob_sample_t *)(stream->user_buffer))+stream->user_buffer_position;
2522                        
2523                         do_ringbuffer_write=0;
2524                         break;
2525                                
2526                 case freebob_buffer_type_float:
2527                         floatbuff=((float *)(stream->user_buffer))+stream->user_buffer_position;
2528                        
2529                         do_ringbuffer_write=0;
2530                         break;
2531         }
2532        
2533         int j=0;
2534         int written=0;
2535        
2536         if (stream->spec.format== IEC61883_STREAM_TYPE_MBLA) {
2537                 target_event=(quadlet_t *)(events + stream->spec.position);
2538                
2539                 // TODO: convert this into function pointer based
2540                 switch(stream->buffer_type) {
2541                         default:
2542                         case freebob_buffer_type_uint24:
2543                                 for(j = 0; j < nsamples; j += 1) { // decode max nsamples
2544                                         *(buffer)=(ntohl((*target_event) ) & 0x00FFFFFF);
2545                 //                      fprintf(stderr,"[%03d, %02d: %08p %08X %08X]\n",j, stream->spec.position, target_event, *target_event, *buffer);
2546                                         buffer++;
2547                                         target_event+=connection->spec.dimension;
2548                                 }
2549                                 break;
2550                         case freebob_buffer_type_float:
2551                                 for(j = 0; j < nsamples; j += 1) { // decode max nsamples               
2552
2553                                         unsigned int v = ntohl(*target_event) & 0x00FFFFFF;
2554                                         // sign-extend highest bit of 24-bit int
2555                                         int tmp = (int)(v << 8) / 256;
2556                
2557                                         *floatbuff = tmp * multiplier;
2558                                
2559                                         floatbuff++;
2560                                         target_event+=connection->spec.dimension;
2561                                 }
2562                                 break;
2563                 }
2564
2565 //              fprintf(stderr,"rb write [%02d: %08p %08p]\n",stream->spec.position, stream, stream->buffer);
2566        
2567 //      fprintf(stderr,"rb write [%02d: %08p %08p %08X, %d, %d]\n",stream->spec.position, stream, stream->buffer, *buffer, nsamples, written);
2568                 if(do_ringbuffer_write) {
2569                         // reset the buffer pointer
2570                         buffer=((freebob_sample_t *)(stream->user_buffer))+stream->user_buffer_position;
2571                         written=freebob_ringbuffer_write(stream->buffer, (char *)(buffer), nsamples*sizeof(freebob_sample_t))/sizeof(freebob_sample_t);
2572                 } else {
2573                         written=nsamples;
2574                 }
2575                
2576 //      fprintf(stderr,"rb write1[%02d: %08p %08p %08X, %d, %d]\n",stream->spec.position, stream, stream->buffer, *buffer, nsamples, written);
2577                
2578                 return written;
2579        
2580         } else if (stream->spec.format == IEC61883_STREAM_TYPE_MIDI) {
2581                 return nsamples; // for midi streams we always indicate a full write
2582        
2583         } else {//if (stream->spec.format == IEC61883_STREAM_TYPE_SPDIF) {
2584                 return nsamples; // for unsupported we always indicate a full read
2585        
2586         }
2587        
2588         return 0;
2589
2590
2591 }
2592
2593 static inline int
2594 freebob_encode_stream_to_events(freebob_connection_t *connection,
2595                                                                 freebob_stream_t *stream,
2596                                                                 quadlet_t* events,
2597                                                                 unsigned int nsamples,
2598                                                                 unsigned int dbc
2599                                                                 ) {
2600         quadlet_t *target_event;
2601         //freebob_sample_t buff[nsamples];
2602         int do_ringbuffer_read=0;
2603        
2604         freebob_sample_t *buffer=NULL;
2605         float *floatbuff=NULL;
2606
2607         const float multiplier = (float)(1u << 31);
2608        
2609         unsigned int j=0;
2610         unsigned int read=0;
2611
2612         assert (stream);
2613         assert (connection);
2614         assert (events);
2615         assert (stream->spec.position < connection->spec.dimension);
2616        
2617         switch(stream->buffer_type) {
2618                 case freebob_buffer_type_per_stream:
2619                 default:
2620 //                      assert(nsamples < dev->options.period_size);
2621                         // use the preallocated buffer (at init time)
2622                         buffer=((freebob_sample_t *)(stream->user_buffer))+stream->user_buffer_position;
2623                        
2624                         do_ringbuffer_read=1;
2625                         break;
2626                                
2627                 case freebob_buffer_type_uint24:
2628                         buffer=((freebob_sample_t *)(stream->user_buffer))+stream->user_buffer_position;
2629                        
2630                         do_ringbuffer_read=0;
2631                         break;
2632                                
2633                 case freebob_buffer_type_float:
2634                         floatbuff=((float *)(stream->user_buffer))+stream->user_buffer_position;
2635                        
2636                         do_ringbuffer_read=0;
2637                         break;
2638         }
2639        
2640        
2641         if(stream->spec.format == IEC61883_STREAM_TYPE_MBLA) { // MBLA
2642                 target_event=(quadlet_t *)(events + (stream->spec.position));
2643                
2644                 if(do_ringbuffer_read) {
2645                         read=freebob_ringbuffer_read(stream->buffer, (char *)buffer, nsamples*sizeof(freebob_sample_t))/sizeof(freebob_sample_t);
2646                 } else {
2647                         read=nsamples;
2648                 }
2649                
2650                 // TODO: convert this into function pointer based
2651                 switch(stream->buffer_type) {
2652                         default:
2653                         case freebob_buffer_type_uint24:
2654                                 for(j = 0; j < read; j += 1) { // decode max nsamples
2655                                         *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000);
2656                                         buffer++;
2657                                         target_event+=connection->spec.dimension;
2658                                        
2659                 //                      fprintf(stderr,"[%03d, %02d: %08p %08X %08X]\n",j, stream->spec.position, target_event, *target_event, *buffer);
2660
2661                                 }
2662                                 break;
2663                         case freebob_buffer_type_float:
2664                                 for(j = 0; j < read; j += 1) { // decode max nsamples
2665                                         // don't care for overflow
2666                                         float v = *floatbuff * multiplier;  // v: -231 .. 231
2667                                         unsigned int tmp = ((int)v);
2668                                         *target_event = htonl((tmp >> 8) | 0x40000000);
2669                                        
2670                                         floatbuff++;
2671                                         target_event += connection->spec.dimension;
2672                                 }
2673                                 break;
2674                 }
2675                
2676                 /*             
2677                 for(j = 0; j < nsamples; j+=1) {
2678                         *target_event = htonl((*(buffer) & 0x00FFFFFF) | 0x40000000);
2679                         buffer++;
2680                         target_event+=connection->spec.dimension;
2681                 }
2682                 */
2683                
2684                 return read;
2685                
2686         } else if (stream->spec.format == IEC61883_STREAM_TYPE_MIDI) {
2687                 return nsamples; // for midi we always indicate a full read
2688        
2689         } else { //if (stream->spec.format == IEC61883_STREAM_TYPE_SPDIF) {
2690                 return nsamples; // for unsupported we always indicate a full read
2691        
2692         }
2693         return 0;
2694
2695 }
2696
2697
2698 /*
2699  * write received events to the stream ringbuffers.
2700  */
2701
2702 int freebob_am824_recv(char *data,
2703                                            int nevents, unsigned int offset, unsigned int dbc,
2704                                freebob_connection_t *connection)
2705 {
2706         int xrun=0;
2707         unsigned int i=0;
2708        
2709         for(i = 0; i < connection->nb_streams; i++) {
2710                 freebob_stream_t *stream = &(connection->streams[i]);
2711                 size_t written=0;
2712                
2713                 assert(stream);
2714                
2715                 stream->user_buffer_position=offset;
2716                
2717                 debugPrintShort(DEBUG_LEVEL_HANDLERS,"[%d: %d ",i,freebob_ringbuffer_write_space(stream->buffer));
2718                 written = freebob_decode_events_to_stream(
2719                         connection,
2720                         stream,
2721                         (quadlet_t *)data,
2722                         nevents,
2723                         dbc
2724                         );
2725
2726                 if (written < nevents) {
2727                         xrun++;
2728                 }
2729                
2730                 debugPrintShort(DEBUG_LEVEL_HANDLERS, "%d %d]",written,freebob_ringbuffer_write_space(stream->buffer));
2731         }
2732        
2733 //      connection->status.frames_left-=nevents;
2734                
2735         debugPrintShort(DEBUG_LEVEL_HANDLERS, "\n");
2736        
2737         return xrun;
2738 }
2739
2740 /*
2741  * get xmit events from ringbuffer
2742  */
2743
2744 int freebob_am824_xmit( char *data,
2745                                                 int nevents, unsigned int offset, unsigned int dbc,
2746                                                 freebob_connection_t *connection)
2747 {
2748         int xrun=0;
2749         unsigned int i=0;
2750        
2751         for(i = 0; i < connection->nb_streams; i++) {
2752                 freebob_stream_t *stream = &(connection->streams[i]);
2753                 size_t read=0;
2754                
2755                 assert(stream);
2756                 debugPrintShort(DEBUG_LEVEL_HANDLERS, "[%d: %d ",i,freebob_ringbuffer_read_space(stream->buffer));
2757                
2758                 stream->user_buffer_position=offset;
2759                
2760                 read = freebob_encode_stream_to_events(
2761                         connection,
2762                         stream,
2763                         (quadlet_t *)data,
2764                         nevents,
2765                         dbc
2766                         );
2767                
2768                 debugPrintShort(DEBUG_LEVEL_HANDLERS, "%d %d]",read,freebob_ringbuffer_read_space(stream->buffer));
2769
2770                 if (read < nevents) {
2771                         xrun++;
2772                 }
2773                
2774         }
2775         debugPrintShort(DEBUG_LEVEL_HANDLERS, "\n");
2776        
2777 //      connection->status.frames_left-=nevents;
2778        
2779         return xrun;
2780 }
2781
2782 void *freebob_streaming_watchdog_thread (void *arg)
2783 {
2784         freebob_device_t *dev = (freebob_device_t *) arg;
2785
2786         dev->watchdog_check = 0;
2787
2788         while (1) {
2789                 sleep (2);
2790                 if (dev->watchdog_check == 0) {
2791
2792                         printError("watchdog: timeout");
2793
2794                         /* kill our process group, try to get a dump */
2795                         kill (-getpgrp(), SIGABRT);
2796                         /*NOTREACHED*/
2797                         exit (1);
2798                 }
2799                 dev->watchdog_check = 0;
2800         }
2801 }
2802
2803 int freebob_streaming_start_watchdog (freebob_device_t *dev)
2804 {
2805         int watchdog_priority = dev->packetizer.priority + 10;
2806         int max_priority = sched_get_priority_max (SCHED_FIFO);
2807
2808         debugPrint(DEBUG_LEVEL_STARTUP, "Starting Watchdog...\n");
2809        
2810         if ((max_priority != -1) &&
2811                         (max_priority < watchdog_priority))
2812                 watchdog_priority = max_priority;
2813        
2814         if (freebob_streaming_create_thread (dev, &dev->watchdog_thread, watchdog_priority,
2815                 TRUE, freebob_streaming_watchdog_thread, dev)) {
2816                         printError ("cannot start watchdog thread");
2817                         return -1;
2818                 }
2819
2820         return 0;
2821 }
2822
2823 void freebob_streaming_stop_watchdog (freebob_device_t *dev)
2824 {
2825         debugPrint(DEBUG_LEVEL_STARTUP, "Stopping Watchdog...\n");
2826        
2827         pthread_cancel (dev->watchdog_thread);
2828         pthread_join (dev->watchdog_thread, NULL);
2829 }
Note: See TracBrowser for help on using the browser.