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

Revision 742, 13.8 kB (checked in by ppalmers, 16 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2007 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  * This program 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 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
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.