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

Revision 523, 13.6 kB (checked in by ppalmers, 17 years ago)

fix uninitialized struct params bugs

  • 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         return 0;
131 }
132
133 int main(int argc, char *argv[])
134 {
135
136         #define PERIOD_SIZE 512
137
138         int samplesread=0, sampleswritten=0;
139         int nb_in_channels=0, nb_out_channels=0;
140         int retval=0;
141         int i=0;
142         int start_flag = 0;
143
144         int nb_periods=0;
145
146         ffado_sample_t **audiobuffers_in;
147         ffado_sample_t **audiobuffers_out;
148         ffado_sample_t *nullbuffer;
149        
150         run=1;
151
152         printf("Ffado MIDI streaming test application (1)\n");
153
154         signal (SIGINT, sighandler);
155         signal (SIGPIPE, sighandler);
156
157         ffado_device_info_t device_info;
158
159         ffado_options_t dev_options;
160
161         dev_options.sample_rate=-1; // -1 = detect from discovery
162         dev_options.period_size=PERIOD_SIZE;
163
164         dev_options.nb_buffers=3;
165
166         dev_options.port=1;
167         dev_options.node_id=-1;
168        
169         dev_options.realtime=0;
170         dev_options.packetizer_priority=60;
171        
172         dev_options.verbose=5;
173        
174         dev_options.slave_mode=0;
175         dev_options.snoop_mode=0;
176
177         ffado_device_t *dev=ffado_streaming_init(&device_info, dev_options);
178         if (!dev) {
179                 fprintf(stderr,"Could not init Ffado Streaming layer\n");
180                 exit(-1);
181         }
182
183         nb_in_channels=ffado_streaming_get_nb_capture_streams(dev);
184         nb_out_channels=ffado_streaming_get_nb_playback_streams(dev);
185
186         int midi_in_nbchannels=0;
187         int midi_out_nbchannels=0;
188        
189         /* allocate intermediate buffers */
190         audiobuffers_in=calloc(nb_in_channels,sizeof(ffado_sample_t *));
191         audiobuffers_out=calloc(nb_in_channels,sizeof(ffado_sample_t));
192         for (i=0;i<nb_in_channels;i++) {
193                 audiobuffers_in[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
194                 audiobuffers_out[i]=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
195                        
196                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
197                         case ffado_stream_type_audio:
198                                 /* assign the audiobuffer to the stream */
199                                 ffado_streaming_set_capture_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
200                                 ffado_streaming_set_capture_buffer_type(dev, i, ffado_buffer_type_float);
201                                 break;
202                                
203                         // this is done with read/write routines because the nb of bytes can differ.
204                         case ffado_stream_type_midi:
205                                 midi_in_nbchannels++;
206                         default:
207                                 break;
208                 }
209         }
210        
211         nullbuffer=calloc(PERIOD_SIZE+1,sizeof(ffado_sample_t));
212        
213         for (i=0;i<nb_out_channels;i++) {
214                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
215                         case ffado_stream_type_audio:
216                                 if (i<nb_in_channels) {
217                                         /* assign the audiobuffer to the stream */
218                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)(audiobuffers_in[i]));
219                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_float);
220                                 } else {
221                                         ffado_streaming_set_playback_stream_buffer(dev, i, (char *)nullbuffer);
222                                         ffado_streaming_set_playback_buffer_type(dev, i, ffado_buffer_type_int24);     
223                                 }
224                                 break;
225                                 // this is done with read/write routines because the nb of bytes can differ.
226                         case ffado_stream_type_midi:
227                                 midi_out_nbchannels++;
228                         default:
229                                 break;
230                 }
231         }
232        
233         /* open the files to write to*/
234         FILE* fid_out[nb_out_channels];
235         FILE* fid_in[nb_in_channels];
236         char name[256];
237
238         for (i=0;i<nb_out_channels;i++) {
239                 snprintf(name,sizeof(name),"out_ch_%02d",i);
240
241                 fid_out[i]=fopen(name,"w");
242
243                 ffado_streaming_get_playback_stream_name(dev,i,name,sizeof(name));
244                 fprintf(fid_out[i],"Channel name: %s\n",name);
245                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
246                 case ffado_stream_type_audio:
247                         fprintf(fid_out[i],"Channel type: audio\n");
248                         break;
249                 case ffado_stream_type_midi:
250                         fprintf(fid_out[i],"Channel type: midi\n");
251                         break;
252                 case ffado_stream_type_unknown:
253                         fprintf(fid_out[i],"Channel type: unknown\n");
254                         break;
255                 default:
256                 case ffado_stream_type_invalid:
257                         fprintf(fid_out[i],"Channel type: invalid\n");
258                         break;
259                 }
260
261         }
262         for (i=0;i<nb_in_channels;i++) {
263                 snprintf(name,sizeof(name),"in_ch_%02d",i);
264                 fid_in[i]=fopen(name,"w");
265
266                 ffado_streaming_get_capture_stream_name(dev,i,name,sizeof(name));
267                 fprintf(fid_in[i], "Channel name: %s\n", name);
268                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
269                 case ffado_stream_type_audio:
270                         fprintf(fid_in[i], "Channel type: audio\n");
271                         break;
272                 case ffado_stream_type_midi:
273                         fprintf(fid_in[i], "Channel type: midi\n");
274                         break;
275                 case ffado_stream_type_unknown:
276                         fprintf(fid_in[i],"Channel type: unknown\n");
277                         break;
278                 default:
279                 case ffado_stream_type_invalid:
280                         fprintf(fid_in[i],"Channel type: invalid\n");
281                         break;
282                 }
283         }
284
285         // setup the ALSA midi seq clients
286         snd_seq_t *seq_handle;
287         int in_ports[midi_in_nbchannels], out_ports[midi_out_nbchannels];
288        
289     // open sequencer
290         // the number of midi ports is statically set to 2
291         if (open_seq(&seq_handle, in_ports, out_ports, midi_in_nbchannels, midi_out_nbchannels) < 0) {
292                 fprintf(stderr, "ALSA Error.\n");
293                 exit(1);
294         }
295
296         ffado_midi_port_t* midi_out_portmap[nb_out_channels];
297         ffado_midi_port_t* midi_in_portmap[nb_in_channels];
298        
299         int cnt=0;
300        
301         for (i=0;i<nb_out_channels;i++) {
302                 ffado_midi_port_t *midi_out_port;
303                 switch (ffado_streaming_get_playback_stream_type(dev,i)) {
304                         case ffado_stream_type_audio:
305                                 midi_out_portmap[i]=NULL;
306                                 break;
307                         case ffado_stream_type_midi:
308                                 midi_out_port=malloc(sizeof(ffado_midi_port_t));
309                                 if(!midi_out_port) {
310                                         fprintf(stderr, "Could not allocate memory for MIDI OUT port %d\n",i);
311                                         exit(1); // this could be/is a memory leak, I know...
312                                 } else {
313                                         midi_out_port->seq_port_nr=in_ports[cnt++];
314                                         midi_out_port->seq_handle=seq_handle;
315                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_out_port->parser)) < 0) {
316                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI OUT port %d\n",i);
317                                                 exit(1); // this too
318                                         }   
319                                         midi_out_portmap[i]=midi_out_port;
320                                 }
321                                 break;
322                         default: break;
323                 }
324         }
325        
326         cnt=0;
327         for (i=0;i<nb_in_channels;i++) {
328                 ffado_midi_port_t *midi_in_port;
329                 switch (ffado_streaming_get_capture_stream_type(dev,i)) {
330                         case ffado_stream_type_audio:
331                                 midi_in_portmap[i]=NULL;
332                                 break;
333                         case ffado_stream_type_midi:
334                
335                                 midi_in_port=malloc(sizeof(ffado_midi_port_t));
336                                 if(!midi_in_port) {
337                                         fprintf(stderr, "Could not allocate memory for MIDI IN port %d\n",i);
338                                         exit(1); // this could be/is a memory leak, I know...
339                                 } else {
340                                         midi_in_port->seq_port_nr=out_ports[cnt++];
341                                         midi_in_port->seq_handle=seq_handle;
342                        
343                                         if (snd_midi_event_new  ( ALSA_SEQ_BUFF_SIZE, &(midi_in_port->parser)) < 0) {
344                                                 fprintf(stderr, "ALSA Error: could not init parser for MIDI IN port %d\n",i);
345                                                 exit(1); // this too
346                                         }   
347                                         midi_in_portmap[i]=midi_in_port;
348                                 }
349                                 break;
350                         default: break;
351                 }
352         }       
353        
354         // start the streaming layer
355         start_flag = ffado_streaming_start(dev);
356
357         fprintf(stderr,"Entering receive loop (%d,%d)\n",nb_in_channels,nb_out_channels);
358         while(run && start_flag==0) {
359                 retval = ffado_streaming_wait(dev);
360                 if (retval < 0) {
361                         fprintf(stderr,"Xrun\n");
362                         ffado_streaming_reset(dev);
363                         continue;
364                 }
365                
366 //              ffado_streaming_transfer_buffers(dev);
367                 ffado_streaming_transfer_capture_buffers(dev);
368                 ffado_streaming_transfer_playback_buffers(dev);
369                
370                 nb_periods++;
371
372                 if((nb_periods % 32)==0) {
373 //                      fprintf(stderr,"\r%05d periods",nb_periods);
374                 }
375
376                 for(i=0;i<nb_in_channels;i++) {
377                         int s;
378                        
379                         switch (ffado_streaming_get_capture_stream_type(dev,i)) {
380                         case ffado_stream_type_audio:
381                                 // no need to get the buffers manually, we have set the API internal buffers to the audiobuffer[i]'s
382 //                              //samplesread=ffado_streaming_read(dev, i, audiobuffer[i], PERIOD_SIZE);
383                                 samplesread=PERIOD_SIZE;
384                                 break;
385                         case ffado_stream_type_midi:
386                                 samplesread=ffado_streaming_read(dev, i, audiobuffers_in[i], PERIOD_SIZE);
387                                 quadlet_t *buff=(quadlet_t *)audiobuffers_in[i];
388                                 for (s=0;s<samplesread;s++) {
389                                         quadlet_t *byte=(buff+s) ;
390 //                                      printf("%08X ",*byte);
391                                         decode_midi_byte (midi_in_portmap[i], (*byte) & 0xFF);
392                                 }
393                                 if(samplesread>0) {
394                                         fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
395                                         hexDumpToFile(fid_in[i],(unsigned char*)audiobuffers_in[i],samplesread*sizeof(ffado_sample_t));
396                                 }
397                                 break;
398                         default: break;
399                         }
400 //                      fprintf(fid_in[i], "---- Period read (%d samples) ----\n",samplesread);
401 //                      hexDumpToFile(fid_in[i],(unsigned char*)buff,samplesread*sizeof(ffado_sample_t));
402        
403                 }
404
405                 for(i=0;i<nb_out_channels;i++) {
406                         ffado_sample_t *buff;
407                         int b=0;
408                         unsigned char* byte_buff;
409                        
410                         if (i<nb_in_channels) {
411                                 buff=audiobuffers_out[i];
412                         } else {
413                                 buff=nullbuffer;
414                         }
415                        
416                         switch (ffado_streaming_get_playback_stream_type(dev,i)) {
417                         case ffado_stream_type_audio:
418 //                              sampleswritten=ffado_streaming_write(dev, i, buff, PERIOD_SIZE);
419 //                              sampleswritten=PERIOD_SIZE;
420                                 break;
421                         case ffado_stream_type_midi:
422                                
423                                 #define max_midi_bytes_to_write PERIOD_SIZE/8
424                                 byte_buff=(unsigned char*)buff;
425                                
426                                 sampleswritten=encode_midi_bytes(midi_out_portmap[i], byte_buff, max_midi_bytes_to_write);
427                                
428                                 for(b=0;b<sampleswritten;b++) {
429                                         ffado_sample_t tmp_event=*(byte_buff+b);
430                                         ffado_streaming_write(dev, i, &tmp_event, 1);
431                                 }
432                                
433                                
434                                 fprintf(fid_out[i], "---- Period write (%d samples) ----\n",sampleswritten);
435                                 hexDumpToFile(fid_out[i],(unsigned char*)buff,sampleswritten*sizeof(ffado_sample_t));
436                                 break;
437                         default: break;
438                         }
439                 }
440
441         }
442
443         fprintf(stderr,"\n");
444
445         fprintf(stderr,"Exiting receive loop\n");
446        
447         ffado_streaming_stop(dev);
448
449         ffado_streaming_finish(dev);
450
451         for (i=0;i<nb_out_channels;i++) {
452                 fclose(fid_out[i]);
453
454         }
455         for (i=0;i<nb_in_channels;i++) {
456                 fclose(fid_in[i]);
457         }
458        
459         for (i=0;i<nb_in_channels;i++) {
460                 free(audiobuffers_in[i]);
461                 free(audiobuffers_out[i]);
462         }
463         free(nullbuffer);
464         free(audiobuffers_in);
465         free(audiobuffers_out);
466        
467         // free the MIDI to seq parsers and port structures
468         for(i=0;i<midi_in_nbchannels;i++) {
469                 ffado_midi_port_t *midi_in_port=midi_in_portmap[i];
470                
471                 if(midi_in_port) {
472                         snd_midi_event_free  (  midi_in_port->parser );
473                         free(midi_in_port);
474                 }
475         }
476         // free the MIDI to seq parsers and port structures
477         for(i=0;i<midi_out_nbchannels;i++) {
478                 ffado_midi_port_t *midi_out_port=midi_out_portmap[i];
479
480                 if(midi_out_port) {
481                         snd_midi_event_free  (  midi_out_port->parser );
482                         free(midi_out_port);
483                 }
484         }
485
486   return EXIT_SUCCESS;
487 }
Note: See TracBrowser for help on using the browser.