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

Revision 386, 16.8 kB (checked in by pieterpalmers, 17 years ago)

- moved files around to the place they belong
- fixed all compile warnings

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