root/branches/streaming-rework/src/freebob_streaming.cpp

Revision 435, 17.6 kB (checked in by pieterpalmers, 15 years ago)

src/devicemanager:
- start OSC server for the device manager

src/devicemanager,
src/iavdevice,
src/libieee1394/configrom:
- inherit from OscNode? to become Osc'able

src/bounce,
src/libstreaming/AmdtpStreamProcessor,
src/libstreaming/AmdtpSlaveStreamProcessor:
- fixed bounce device implementation, now working

src/bebob:
- fixed midi bug

General:
- removed 'intermediate XML'
- removed obsolete tests
- removed obsolete files
- removed obsolete API calls

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