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

Revision 384, 16.6 kB (checked in by pieterpalmers, 16 years ago)

- temporary commit as backup measure
- rewrote synchronisation code
- receive streaming based on SYT works
- transmit streaming synced to received stream sort of works, still

have to iron out some issues.

NOTE: all devices but the bebob's are disabled in this code,

because they still have to be ported to the new sync
mechanism.

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