root/trunk/libffado/src/freebob_streaming.cpp

Revision 436, 17.9 kB (checked in by pieterpalmers, 14 years ago)

- fixed verbose level setting
- debugged DICE code, works with EVM

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,2006 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.h"
36 #include "libfreebob/freebob_streaming.h"
37 #include "devicemanager.h"
38 #include "iavdevice.h"
39
40 #include "libstreaming/StreamProcessorManager.h"
41
42 #include <assert.h>
43
44 #include <string.h>
45 #include <string>
46
47 /**
48 * Device structure
49 */
50
51 DECLARE_GLOBAL_DEBUG_MODULE;
52
53 using namespace Streaming;
54
55 struct _freebob_device
56 {
57     DeviceManager * m_deviceManager;
58     StreamProcessorManager *processorManager;
59
60     freebob_options_t options;
61     freebob_device_info_t device_info;
62 };
63
64 freebob_device_t *freebob_streaming_init (freebob_device_info_t *device_info, freebob_options_t options) {
65     unsigned int i=0;
66
67     struct _freebob_device *dev = new struct _freebob_device;
68
69     debugFatal("%s built %s %s\n", freebob_get_version(), __DATE__, __TIME__);
70
71     if(!dev) {
72             debugFatal( "Could not allocate streaming device\n" );
73             return 0;
74     }
75
76     memcpy((void *)&dev->options, (void *)&options, sizeof(dev->options));
77     memcpy((void *)&dev->device_info, (void *)device_info, sizeof(dev->device_info));
78
79     dev->m_deviceManager = new DeviceManager();
80     if ( !dev->m_deviceManager ) {
81             debugFatal( "Could not allocate device manager\n" );
82             delete dev;
83             return 0;
84     }
85    
86     dev->m_deviceManager->setVerboseLevel(DEBUG_LEVEL_VERBOSE);
87     if ( !dev->m_deviceManager->initialize( dev->options.port ) ) {
88             debugFatal( "Could not initialize device manager\n" );
89             delete dev->m_deviceManager;
90             delete dev;
91             return 0;
92     }
93
94     // create a processor manager to manage the actual stream
95     // processors       
96     dev->processorManager = new StreamProcessorManager(dev->options.period_size,dev->options.nb_buffers);
97     if(!dev->processorManager) {
98             debugFatal("Could not create StreamProcessorManager\n");
99             delete dev->m_deviceManager;
100             delete dev;
101             return 0;
102     }
103    
104     dev->processorManager->setThreadParameters(dev->options.realtime, dev->options.packetizer_priority);
105    
106     dev->processorManager->setVerboseLevel(DEBUG_LEVEL_VERBOSE);
107     if(!dev->processorManager->init()) {
108             debugFatal("Could not init StreamProcessorManager\n");
109             delete dev->processorManager;
110             delete dev->m_deviceManager;
111             delete dev;
112             return 0;
113     }
114    
115     // set slave mode option
116     bool slaveMode=(dev->options.slave_mode != 0);
117     debugOutput(DEBUG_LEVEL_VERBOSE, "setting slave mode to %d\n", slaveMode);
118     if(!dev->m_deviceManager->setOption("slaveMode", slaveMode)) {
119             debugWarning("Failed to set slave mode option\n");
120     }
121     // set snoop mode option
122     bool snoopMode=(dev->options.snoop_mode != 0);
123     debugOutput(DEBUG_LEVEL_VERBOSE, "setting snoop mode to %d\n", snoopMode);
124     if(!dev->m_deviceManager->setOption("snoopMode", snoopMode)) {
125             debugWarning("Failed to set snoop mode option\n");
126     }
127    
128     // discover the devices on the bus
129     if(!dev->m_deviceManager->discover()) {
130             debugFatal("Could not discover devices\n");
131             delete dev->processorManager;
132             delete dev->m_deviceManager;
133             delete dev;
134             return 0;
135     }
136    
137     // are there devices on the bus?
138     if(dev->m_deviceManager->getAvDeviceCount()==0) {
139             debugFatal("There are no devices on the bus\n");
140             delete dev->processorManager;
141             delete dev->m_deviceManager;
142             delete dev;
143             return 0;
144     }
145    
146     // iterate over the found devices
147     // add the stream processors of the devices to the managers
148     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
149         IAvDevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
150         assert(device);
151
152         debugOutput(DEBUG_LEVEL_VERBOSE, "Locking device (%p)\n", device);
153        
154         if (!device->lock()) {
155             debugWarning("Could not lock device, skipping device (%p)!\n", device);
156             continue;
157         }
158        
159         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting samplerate to %d for (%p)\n",
160                     dev->options.sample_rate, device);
161                    
162         // Set the device's sampling rate to that requested
163         // FIXME: does this really belong here?  If so we need to handle errors.
164         if (!device->setSamplingFrequency(parseSampleRate(dev->options.sample_rate))) {
165             debugOutput(DEBUG_LEVEL_VERBOSE, " => Retry setting samplerate to %d for (%p)\n",
166                         dev->options.sample_rate, device);
167        
168             // try again:
169             if (!device->setSamplingFrequency(parseSampleRate(dev->options.sample_rate))) {
170                 delete dev->processorManager;
171                 delete dev->m_deviceManager;
172                 delete dev;
173                 debugFatal("Could not set sampling frequency to %d\n",dev->options.sample_rate);
174                 return 0;
175             }
176         }
177
178         // prepare the device
179         device->prepare();
180
181         int j=0;
182         for(j=0; j<device->getStreamCount();j++) {
183             StreamProcessor *streamproc=device->getStreamProcessorByIndex(j);
184             debugOutput(DEBUG_LEVEL_VERBOSE, "Registering stream processor %d of device %d with processormanager\n",j,i);
185             if (!dev->processorManager->registerProcessor(streamproc)) {
186                 debugWarning("Could not register stream processor (%p) with the Processor manager\n",streamproc);
187             }
188         }
189     }
190    
191     // set the sync source
192     if (!dev->processorManager->setSyncSource(dev->m_deviceManager->getSyncSource())) {
193         debugWarning("Could not set processorManager sync source (%p)\n",
194             dev->m_deviceManager->getSyncSource());
195     }
196
197     // we are ready!
198     debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n\n");
199     return dev;
200
201 }
202
203 int freebob_streaming_prepare(freebob_device_t *dev) {
204     debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n");
205        
206     if (!dev->processorManager->prepare()) {
207         debugFatal("Could not prepare streaming...\n");
208         return false;
209     }
210
211     return true;
212 }
213
214 void freebob_streaming_finish(freebob_device_t *dev) {
215     unsigned int i=0;
216    
217     assert(dev);
218    
219     // iterate over the found devices
220     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
221         IAvDevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
222         assert(device);
223
224         debugOutput(DEBUG_LEVEL_VERBOSE, "Unlocking device (%p)\n", device);
225
226         if (!device->unlock()) {
227             debugWarning("Could not unlock device (%p)!\n", device);
228         }
229     }
230    
231     delete dev->processorManager;
232     delete dev->m_deviceManager;
233     delete dev;
234
235     return;
236 }
237
238 int freebob_streaming_start(freebob_device_t *dev) {
239     unsigned int i=0;
240     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Start -------------\n");
241    
242     // create the connections for all devices
243     // iterate over the found devices
244     // add the stream processors of the devices to the managers
245     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
246         IAvDevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
247         assert(device);
248    
249         int j=0;
250         for(j=0; j<device->getStreamCount();j++) {
251         debugOutput(DEBUG_LEVEL_VERBOSE,"Starting stream %d of device %d\n",j,i);
252             // start the stream
253             if (!device->startStreamByIndex(j)) {
254                 debugWarning("Could not start stream %d of device %d\n",j,i);
255                 continue;
256             }
257         }
258
259         if (!device->enableStreaming()) {
260             debugWarning("Could not enable streaming on device %d!\n",i);
261         }
262     }
263
264     if(dev->processorManager->start()) {
265         return 0;
266     } else {
267         freebob_streaming_stop(dev);
268         return -1;
269     }
270 }
271
272 int freebob_streaming_stop(freebob_device_t *dev) {
273     unsigned int i;
274     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Stop -------------\n");
275
276     dev->processorManager->stop();
277
278     // create the connections for all devices
279     // iterate over the found devices
280     // add the stream processors of the devices to the managers
281     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
282         IAvDevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
283         assert(device);
284
285         if (!device->disableStreaming()) {
286             debugWarning("Could not disable streaming on device %d!\n",i);
287         }
288        
289         int j=0;
290         for(j=0; j<device->getStreamCount();j++) {
291             debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %d\n",j,i);
292             // stop the stream
293             // start the stream
294             if (!device->stopStreamByIndex(j)) {
295                 debugWarning("Could not stop stream %d of device %d\n",j,i);
296                 continue;
297             }
298         }
299     }
300
301     return 0;
302 }
303
304 int freebob_streaming_reset(freebob_device_t *dev) {
305     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Reset -------------\n");
306
307     // dev->processorManager->reset();
308
309     return 0;
310 }
311
312 int freebob_streaming_wait(freebob_device_t *dev) {
313     static int periods=0;
314     static int periods_print=0;
315     static int xruns=0;
316    
317     periods++;
318     if(periods>periods_print) {
319         debugOutputShort(DEBUG_LEVEL_VERBOSE, "\nfreebob_streaming_wait\n");
320         debugOutputShort(DEBUG_LEVEL_VERBOSE, "============================================\n");
321         debugOutputShort(DEBUG_LEVEL_VERBOSE, "Xruns: %d\n",xruns);
322         debugOutputShort(DEBUG_LEVEL_VERBOSE, "============================================\n");
323         dev->processorManager->dumpInfo();
324         debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n");
325         periods_print+=100;
326     }
327    
328     if(dev->processorManager->waitForPeriod()) {
329         return dev->options.period_size;
330     } else {
331         debugWarning("XRUN detected\n");
332        
333         // do xrun recovery
334         dev->processorManager->handleXrun();
335         xruns++;
336         return -1;
337     }
338 }
339
340 int freebob_streaming_transfer_capture_buffers(freebob_device_t *dev) {
341     return dev->processorManager->transfer(StreamProcessor::E_Receive);
342 }
343
344 int freebob_streaming_transfer_playback_buffers(freebob_device_t *dev) {
345     return dev->processorManager->transfer(StreamProcessor::E_Transmit);
346 }
347
348 int freebob_streaming_transfer_buffers(freebob_device_t *dev) {
349     return dev->processorManager->transfer();
350 }
351
352
353 int freebob_streaming_write(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) {
354     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
355     // use an assert here performancewise,
356     // it should already have failed before, if not correct
357     assert(p);
358        
359     return p->writeEvents((void *)buffer, nsamples);
360 }
361
362 int freebob_streaming_read(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) {
363     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
364     // use an assert here performancewise,
365     // it should already have failed before, if not correct
366     assert(p);
367        
368     return p->readEvents((void *)buffer, nsamples);
369 }
370
371 int freebob_streaming_get_nb_capture_streams(freebob_device_t *dev) {
372     return dev->processorManager->getPortCount(Port::E_Capture);
373 }
374
375 int freebob_streaming_get_nb_playback_streams(freebob_device_t *dev) {
376     return dev->processorManager->getPortCount(Port::E_Playback);
377 }
378
379 int freebob_streaming_get_capture_stream_name(freebob_device_t *dev, int i, char* buffer, size_t buffersize) {
380     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
381     if(!p) {
382         debugWarning("Could not get capture port at index %d\n",i);
383         return -1;
384     }
385
386     std::string name=p->getName();
387     if (!strncpy(buffer, name.c_str(), buffersize)) {
388         debugWarning("Could not copy name\n");
389         return -1;
390     } else return 0;
391 }
392
393 int freebob_streaming_get_playback_stream_name(freebob_device_t *dev, int i, char* buffer, size_t buffersize) {
394     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
395     if(!p) {
396         debugWarning("Could not get playback port at index %d\n",i);
397         return -1;
398     }
399
400     std::string name=p->getName();
401     if (!strncpy(buffer, name.c_str(), buffersize)) {
402         debugWarning("Could not copy name\n");
403         return -1;
404     } else return 0;
405 }
406
407 freebob_streaming_stream_type freebob_streaming_get_capture_stream_type(freebob_device_t *dev, int i) {
408     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
409     if(!p) {
410         debugWarning("Could not get capture port at index %d\n",i);
411         return freebob_stream_type_invalid;
412     }
413     switch(p->getPortType()) {
414     case Port::E_Audio:
415         return freebob_stream_type_audio;
416     case Port::E_Midi:
417         return freebob_stream_type_midi;
418     case Port::E_Control:
419         return freebob_stream_type_control;
420     default:
421         return freebob_stream_type_unknown;
422     }
423 }
424
425 freebob_streaming_stream_type freebob_streaming_get_playback_stream_type(freebob_device_t *dev, int i) {
426     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
427     if(!p) {
428         debugWarning("Could not get playback port at index %d\n",i);
429         return freebob_stream_type_invalid;
430     }
431     switch(p->getPortType()) {
432     case Port::E_Audio:
433         return freebob_stream_type_audio;
434     case Port::E_Midi:
435         return freebob_stream_type_midi;
436     case Port::E_Control:
437         return freebob_stream_type_control;
438     default:
439         return freebob_stream_type_unknown;
440     }
441 }
442
443 int freebob_streaming_set_stream_buffer_type(freebob_device_t *dev, int i,
444     freebob_streaming_buffer_type t, enum Port::E_Direction direction) {
445
446     Port *p=dev->processorManager->getPortByIndex(i, direction);
447     if(!p) {
448         debugWarning("Could not get %s port at index %d\n",
449             (direction==Port::E_Playback?"Playback":"Capture"),i);
450         return -1;
451     }
452        
453     switch(t) {
454     case freebob_buffer_type_int24:
455         if (!p->setDataType(Port::E_Int24)) {
456             debugWarning("%s: Could not set data type to Int24\n",p->getName().c_str());
457             return -1;
458         }
459         if (!p->setBufferType(Port::E_PointerBuffer)) {
460             debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str());
461             return -1;
462         }
463         break;
464     case freebob_buffer_type_float:
465         if (!p->setDataType(Port::E_Float)) {
466             debugWarning("%s: Could not set data type to Float\n",p->getName().c_str());
467             return -1;
468         }
469         if (!p->setBufferType(Port::E_PointerBuffer)) {
470             debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str());
471             return -1;
472         }
473         break;
474     case freebob_buffer_type_midi:
475         if (!p->setDataType(Port::E_MidiEvent)) {
476             debugWarning("%s: Could not set data type to MidiEvent\n",p->getName().c_str());
477             return -1;
478         }
479         if (!p->setBufferType(Port::E_RingBuffer)) {
480             debugWarning("%s: Could not set buffer type to Ringbuffer\n",p->getName().c_str());
481             return -1;
482         }
483         break;
484     default:
485         debugWarning("%s: Unsupported buffer type\n",p->getName().c_str());
486         return -1;
487     }
488     return 0;
489
490 }
491
492 int freebob_streaming_set_playback_buffer_type(freebob_device_t *dev, int i, freebob_streaming_buffer_type t) {
493     return freebob_streaming_set_stream_buffer_type(dev, i, t, Port::E_Playback);
494 }
495
496 int freebob_streaming_set_capture_buffer_type(freebob_device_t *dev, int i, freebob_streaming_buffer_type t) {
497     return freebob_streaming_set_stream_buffer_type(dev, i, t, Port::E_Capture);
498 }
499
500 int freebob_streaming_stream_onoff(freebob_device_t *dev, int i,
501     int on, enum Port::E_Direction direction) {
502     Port *p=dev->processorManager->getPortByIndex(i, direction);
503     if(!p) {
504         debugWarning("Could not get %s port at index %d\n",
505             (direction==Port::E_Playback?"Playback":"Capture"),i);
506         return -1;
507     }
508     if(on) {
509         p->enable();
510     } else {
511         p->disable();
512     }
513     return 0;
514 }
515
516 int freebob_streaming_playback_stream_onoff(freebob_device_t *dev, int number, int on) {
517     return freebob_streaming_stream_onoff(dev, number, on, Port::E_Playback);
518 }
519
520 int freebob_streaming_capture_stream_onoff(freebob_device_t *dev, int number, int on) {
521     return freebob_streaming_stream_onoff(dev, number, on, Port::E_Capture);
522 }
523
524 // TODO: the way port buffers are set in the C api doesn't satisfy me
525 int freebob_streaming_set_capture_stream_buffer(freebob_device_t *dev, int i, char *buff) {
526         Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
527        
528         // use an assert here performancewise,
529         // it should already have failed before, if not correct
530         assert(p);
531        
532         p->useExternalBuffer(true);
533         p->setExternalBufferAddress((void *)buff);
534
535         return 0;
536
537 }
538
539 int freebob_streaming_set_playback_stream_buffer(freebob_device_t *dev, int i, char *buff) {
540         Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
541         // use an assert here performancewise,
542         // it should already have failed before, if not correct
543         assert(p);
544        
545         p->useExternalBuffer(true);
546         p->setExternalBufferAddress((void *)buff);
547
548         return 0;
549 }
550
Note: See TracBrowser for help on using the browser.