root/trunk/libffado/tests/streaming/testmidistreaming1.c

Revision 739, 13.9 kB (checked in by ppalmers, 15 years ago)

- Adapt the ffado external API (upgrade to v3)

NEEDS NEW JACK BACKEND

- simplify FFADODevice constructor even more
- implement first framework support for supporting multiple adapters.

currently all firewire adapters are scanned for supported devices unless specified otherwise
however attaching devices to separate adapters is not supported. using multiple adapters at
that are connected together might work.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 by by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB.
8  *
9  * FFADO is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * FFADO is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with FFADO; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA.
22  */
23
24
25 /**
26  * Test application for the direct decode stream API
27  * for floating point use
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 #include <signal.h>
39 #include <libiec61883/iec61883.h>
40 #include <stdio.h>
41 #include <sys/select.h>
42 #include <signal.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <alsa/asoundlib.h>
46
47 #include "libffado/ffado.h"
48
49 #include "debugtools.h"
50 #define IEC61883_AM824_LABEL_MIDI_NO_DATA 0x80
51 #define IEC61883_AM824_LABEL_MIDI_1X      0x81
52 #define IEC61883_AM824_LABEL_MIDI_2X      0x82
53 #define IEC61883_AM824_LABEL_MIDI_3X      0x83
54        
55 #define ALSA_SEQ_BUFF_SIZE 1024
56 #define MAX_MIDI_PORTS   20
57 #define MIDI_TRANSMIT_BUFFER_SIZE 1024
58
59 int run;
60
61 static void sighandler (int sig)
62 {
63         run = 0;
64 }
65
66 typedef struct {
67         int seq_port_nr;
68         snd_midi_event_t *parser;
69         snd_seq_t *seq_handle;
70 } ffado_midi_port_t;
71
72 typedef struct {
73         snd_seq_t *seq_handle;
74         int nb_seq_ports;
75         ffado_midi_port_t *ports[MAX_MIDI_PORTS];
76 } ffado_midi_ports_t;
77
78 int open_seq(snd_seq_t **seq_handle, int in_ports[], int out_ports[], int num_in, int num_out);
79
80 /* Open ALSA sequencer with num_in writeable ports and num_out readable ports. */
81 /* The sequencer handle and the port IDs are returned.                        */ 
82 int open_seq(snd_seq_t **seq_handle, int in_ports[], int out_ports[], int num_in, int num_out) {
83
84         int l1;
85         char portname[64];
86
87         if (snd_seq_open(seq_handle, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK) < 0) {
88                 fprintf(stderr, "Error opening ALSA sequencer.\n");
89                 return(-1);
90         }
91        
92         snd_seq_set_client_name(*seq_handle, "FreeBob MIDI I/O test");
93        
94         for (l1 = 0; l1 < num_in; l1++) {
95                 sprintf(portname, "MIDI OUT %d", l1);
96                 if ((in_ports[l1] = snd_seq_create_simple_port(*seq_handle, portname,
97                          SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE,
98                          SND_SEQ_PORT_TYPE_MIDI_GENERIC)) < 0) {
99                                  fprintf(stderr, "Error creating sequencer port.\n");
100                                  return(-1);
101                          }
102         }
103         for (l1 = 0; l1 < num_out; l1++) {
104                 sprintf(portname, "MIDI IN %d", l1);
105                 if ((out_ports[l1] = snd_seq_create_simple_port(*seq_handle, portname,
106                          SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ,
107                          SND_SEQ_PORT_TYPE_MIDI_GENERIC)) < 0) {
108                                  fprintf(stderr, "Error creating sequencer port.\n");
109                                  return(-1);
110                          }
111         }
112         return(0);
113 }
114
115 void decode_midi_byte (ffado_midi_port_t *port, int byte) {
116         snd_seq_event_t ev;
117         if ((snd_midi_event_encode_byte(port->parser,byte, &ev)) > 0) {
118 //              printf("message ok, sending it to %d\n", port->seq_port_nr);
119                 // a midi message is complete, send it out to ALSA
120                 snd_seq_ev_set_subs(&ev); 
121                 snd_seq_ev_set_direct(&ev);
122                 snd_seq_ev_set_source(&ev, port->seq_port_nr);
123                 snd_seq_event_output_direct(port->seq_handle, &ev);                                             
124         }       else {
125                
126         }
127 }
128
129 int encode_midi_bytes(ffado_midi_port_t *port, unsigned char *byte_buff, int len) {
130     static int cnt=0;
131     cnt++;
132     if (cnt>64) {
133         *byte_buff=0xFF;
134         return 1;
135     }
136     return 0;
137 }
138
139 int main(int argc, char *argv[])
140 {
141
142         #define PERIOD_SIZE 1024
143
144         int samplesread=0, sampleswritten=0;
145         int nb_in_channels=0, nb_out_channels=0;
146         int retval=0;
147         int i=0;
148         int start_flag = 0;
149
150         int nb_periods=0;
151
152         ffado_sample_t **audiobuffers_in;
153         ffado_sample_t **audiobuffers_out;
154         ffado_sample_t *nullbuffer;
155        
156         run=1;
157
158         printf("Ffado MIDI streaming test application (1)\n");
159
160         signal (SIGINT, sighandler);
161         signal (SIGPIPE, sighandler);
162
163         ffado_device_info_t device_info;
164
165         ffado_options_t dev_options;
166
167         dev_options.sample_rate=48000; // -1 = detect from discovery
168         dev_options.period_size=PERIOD_SIZE;
169
170         dev_options.nb_buffers=3;
171
172         dev_options.realtime=0;
173         dev_options.packetizer_priority=60;
174        
175         dev_options.verbose=5;
176        
177         dev_options.slave_mode=0;
178         dev_options.snoop_mode=0;
179
180         ffado_device_t *dev=ffado_streaming_init(device_info, dev_options);
181         if (!dev) {
182                 fprintf(stderr,"Could not init Ffado Streaming layer\n");
183                 exit(-1);
184         }
185
186         nb_in_channels=ffado_streaming_get_nb_capture_streams(dev);
187         nb_out_channels=ffado_streaming_get_nb_playback_streams(dev);
188
189         int midi_in_nbchannels=0;
190         int midi_out_nbchannels=0;
191        
192         /* allocate intermediate buffers */
193         audiobuffers_in=calloc(nb_in_channels,sizeof(ffado_sample_t *));
194         audiobuffers_out=calloc(nb_in_channels,sizeof(ffado_sample_t));
195         for (i=0;i<nb_in_channels;i++) {
196                 audiobuffers_in[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
197                 audiobuffers_out[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
198                        
199                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
200                         case ffado_stream_type_audio:
201                                 /* assign the audiobuffer to the stream */
202                                 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
203                                 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float);
204                                 break;
205                                
206                         // this is done with read/write routines because the nb of bytes can differ.
207                         case ffado_stream_type_midi:
208                                 midi_in_nbchannels++;
209                         default:
210                                 break;
211                 }
212         }
213        
214         nullbuffer=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
215        
216         for (i=0;i<nb_out_channels;i++) {
217                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
218                         case ffado_stream_type_audio:
219                                 if (i<nb_in_channels) {
220                                         /* assign the audiobuffer to the stream */
221                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
222                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float);
223                                 } else {
224                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)nullbuffer);
225                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_int24);     
226                                 }
227                                 break;
228                                 // this is done with read/write routines because the nb of bytes can differ.
229                         case ffado_stream_type_midi:
230                                 midi_out_nbchannels++;
231                         default:
232                                 break;
233                 }
234         }
235        
236         /* open the files to write to*/
237         FILE* fid_out[nb_out_channels];
238         FILE* fid_in[nb_in_channels];
239         char name[256];
240
241         for (i=0;i<nb_out_channels;i++) {
242                 snprintf(name,sizeof(name),"out_ch_%02d",i);
243
244                 fid_out[i]=fopen(name,"w");
245
246                 ffado_streaming_get_playback_stream_name(dev,i,name,sizeof(name));
247                 fprintf(fid_out[i],"Channel name: %s\n",name);
248                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
249                 case ffado_stream_type_audio:
250                         fprintf(fid_out[i],"Channel type: audio\n");
251                         break;
252                 case ffado_stream_type_midi:
253                         fprintf(fid_out[i],"Channel type: midi\n");
254                         break;
255                 case ffado_stream_type_unknown:
256                         fprintf(fid_out[i],"Channel type: unknown\n");
257                         break;
258                 default:
259                 case ffado_stream_type_invalid:
260                         fprintf(fid_out[i],"Channel type: invalid\n");
261                         break;
262                 }
263
264         }
265         for (i=0;i<nb_in_channels;i++) {
266                 snprintf(name,sizeof(name),"in_ch_%02d",i);
267                 fid_in[i]=fopen(name,"w");
268
269                 ffado_streaming_get_capture_stream_name(dev,i,name,sizeof(name));
270                 fprintf(fid_in[i], "Channel name: %s\n", name);
271                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
272                 case ffado_stream_type_audio:
273                         fprintf(fid_in[i], "Channel type: audio\n");
274                         break;
275                 case ffado_stream_type_midi:
276                         fprintf(fid_in[i], "Channel type: midi\n");
277                         break;
278                 case ffado_stream_type_unknown:
279                         fprintf(fid_in[i],"Channel type: unknown\n");
280                         break;
281                 default:
282                 case ffado_stream_type_invalid:
283                         fprintf(fid_in[i],"Channel type: invalid\n");
284                         break;
285                 }
286         }
287
288         // setup the ALSA midi seq clients
289         snd_seq_t *seq_handle;
290         int in_ports[midi_in_nbchannels], out_ports[midi_out_nbchannels];
291        
292     // open sequencer
293         // the number of midi ports is statically set to 2
294         if (open_seq(&seq_handle, in_ports, out_ports, midi_in_nbchannels, midi_out_nbchannels) < 0) {
295                 fprintf(stderr, "ALSA Error.\n");
296                 exit(1);
297         }
298
299         ffado_midi_port_t* midi_out_portmap[nb_out_channels];
300         ffado_midi_port_t* midi_in_portmap[nb_in_channels];
301        
302         int cnt=0;
303        
304         for (i=0;i<nb_out_channels;i++) {
305                 ffado_midi_port_t *midi_out_port;
306                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
307                         case ffado_stream_type_audio:
308                                 midi_out_portmap[i]=NULL;
309                                 break;
310                         case ffado_stream_type_midi:
311                                 midi_out_port=malloc(sizeof(ffado_midi_port_t));
312                                 if(!midi_out_port) {
313                                         fprintf(stderr, "Could not allocate memory for MIDI OUT port %d\n",i);
314                                         exit(1); // this could be/is a memory leak, I know...
315                                 } else {
316                                         midi_out_port->seq_port_nr=in_ports[cnt++];
317                                         midi_out_port->seq_handle=seq_handle;
318                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_out_port->parser)) < 0) {
319                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI OUT port %d\n",i);
320                                                 exit(1); // this too
321                                         }   
322                                         midi_out_portmap[i]=midi_out_port;
323                                 }
324                                 break;
325                         default: break;
326                 }
327         }
328        
329         cnt=0;
330         for (i=0;i<nb_in_channels;i++) {
331                 ffado_midi_port_t *midi_in_port;
332                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
333                         case ffado_stream_type_audio:
334                                 midi_in_portmap[i]=NULL;
335                                 break;
336                         case ffado_stream_type_midi:
337                
338                                 midi_in_port=malloc(sizeof(ffado_midi_port_t));
339                                 if(!midi_in_port) {
340                                         fprintf(stderr, "Could not allocate memory for MIDI IN port %d\n",i);
341                                         exit(1); // this could be/is a memory leak, I know...
342                                 } else {
343                                         midi_in_port->seq_port_nr=out_ports[cnt++];
344                                         midi_in_port->seq_handle=seq_handle;
345                        
346                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_in_port->parser)) < 0) {
347                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI IN port %d\n",i);
348                                                 exit(1); // this too
349                                         }   
350                                         midi_in_portmap[i]=midi_in_port;
351                                 }
352                                 break;
353                         default: break;
354                 }
355         }       
356        
357         // start the streaming layer
358         ffado_streaming_prepare(dev);
359         start_flag = ffado_streaming_start(dev);
360
361         fprintf(stderr,"Entering receive loop (%d,%d)\n",nb_in_channels,nb_out_channels);
362         while(run && start_flag==0) {
363                 retval = ffado_streaming_wait(dev);
364                 if (retval < 0) {
365                         fprintf(stderr,"Xrun\n");
366                         ffado_streaming_reset(dev);
367                         continue;
368                 }
369                
370 //              ffado_streaming_transfer_buffers(dev);
371                 ffado_streaming_transfer_capture_buffers(dev);
372                 ffado_streaming_transfer_playback_buffers(dev);
373                
374                 nb_periods++;
375
376                 if((nb_periods % 32)==0) {
377 //                      fprintf(stderr,"\r%05d periods",nb_periods);
378                 }
379
380                 for(i=0;i<nb_in_channels;i++) {
381                         int s;
382                        
383                         switch (ffado_streaming_get_capture_stream_type(dev,i)) {
384                         case ffado_stream_type_audio:
385                                 // no need to get the buffers manually, we have set the API internal buffers to the audiobuffer[i]'s
386 //                              //samplesread=ffado_streaming_read(dev, i, audiobuffer[i], PERIOD_SIZE);
387                                 samplesread=PERIOD_SIZE;
388                                 break;
389                         case ffado_stream_type_midi:
390                                 samplesread=ffado_streaming_read(dev, i, audiobuffers_in[i], 64);
391                                 quadlet_t *buff=(quadlet_t *)audiobuffers_in[i];
392                                 if (samplesread) printf("RECV (CH %02X): ", i);
393                                 for (s=0;s<samplesread;s++) {
394                                         quadlet_t *byte=(buff+s) ;
395                                         printf("%08X ",*byte);
396                                         decode_midi_byte (midi_in_portmap[i], (*byte) & 0xFF);
397                                 }
398                                 if (samplesread) printf("\n");
399                                 if(samplesread>0) {
400                                         fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
401                                         hexDumpToFile(fid_in[i],(unsigned char*)audiobuffers_in[i],samplesread*sizeof(ffado_sample_t));
402                                 }
403                                 break;
404                         default: break;
405                         }
406 //                      fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
407 //                      hexDumpToFile(fid_in[i],(unsigned char*)buff,samplesread*sizeof(ffado_sample_t));
408        
409                 }
410
411                 for(i=0;i<nb_out_channels;i++) {
412                         ffado_sample_t *buff;
413                         int b=0;
414                         unsigned char* byte_buff;
415                        
416                         if (i<nb_in_channels) {
417                                 buff=audiobuffers_out[i];
418                         } else {
419                                 buff=nullbuffer;
420                         }
421                        
422                         switch (ffado_streaming_get_playback_stream_type(dev,i)) {
423                         case ffado_stream_type_audio:
424 //                              sampleswritten=ffado_streaming_write(dev, i, buff, PERIOD_SIZE);
425 //                              sampleswritten=PERIOD_SIZE;
426                                 break;
427                         case ffado_stream_type_midi:
428                                
429                                 #define max_midi_bytes_to_write PERIOD_SIZE/8
430                                 byte_buff=(unsigned char*)buff;
431                                
432                                 sampleswritten=encode_midi_bytes(midi_out_portmap[i], byte_buff, max_midi_bytes_to_write);
433                                 if (sampleswritten) printf("SEND (CH %02X): ", i);
434                                 for(b=0;b<sampleswritten;b++) {
435                                         ffado_sample_t tmp_event=*(byte_buff+b);
436                                         printf("%08X ",*(byte_buff+b));
437                                         ffado_streaming_write(dev, i, &tmp_event, 1);
438                                 }
439                                 if (sampleswritten) printf("\n");
440
441                                 fprintf(fid_out[i], "---- Period write (%d samples) ----\n",sampleswritten);
442                                 hexDumpToFile(fid_out[i],(unsigned char*)buff,sampleswritten*sizeof(ffado_sample_t));
443                                 break;
444                         default: break;
445                         }
446                 }
447
448         }
449
450         fprintf(stderr,"\n");
451
452         fprintf(stderr,"Exiting receive loop\n");
453        
454         ffado_streaming_stop(dev);
455
456         ffado_streaming_finish(dev);
457
458         for (i=0;i<nb_out_channels;i++) {
459                 fclose(fid_out[i]);
460
461         }
462         for (i=0;i<nb_in_channels;i++) {
463                 fclose(fid_in[i]);
464         }
465        
466         for (i=0;i<nb_in_channels;i++) {
467                 free(audiobuffers_in[i]);
468                 free(audiobuffers_out[i]);
469         }
470         free(nullbuffer);
471         free(audiobuffers_in);
472         free(audiobuffers_out);
473        
474         // free the MIDI to seq parsers and port structures
475         for(i=0;i<midi_in_nbchannels;i++) {
476                 ffado_midi_port_t *midi_in_port=midi_in_portmap[i];
477                
478                 if(midi_in_port) {
479                         snd_midi_event_free  (  midi_in_port->parser );
480                         free(midi_in_port);
481                 }
482         }
483         // free the MIDI to seq parsers and port structures
484         for(i=0;i<midi_out_nbchannels;i++) {
485                 ffado_midi_port_t *midi_out_port=midi_out_portmap[i];
486
487                 if(midi_out_port) {
488                         snd_midi_event_free  (  midi_out_port->parser );
489                         free(midi_out_port);
490                 }
491         }
492
493   return EXIT_SUCCESS;
494 }
Note: See TracBrowser for help on using the browser.