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

Revision 419, 18.0 kB (checked in by pieterpalmers, 17 years ago)

namespace simplification

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