root/branches/ppalmers-streaming/src/ffado_streaming.cpp

Revision 714, 17.6 kB (checked in by ppalmers, 15 years ago)

- cleanup of streaming interfaces
- doesn't work yet

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License version 2.1, as published by the Free Software Foundation;
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21  * MA 02110-1301 USA
22  */
23
24 /*
25  * Implementation of the FFADO Streaming API
26  */
27
28 #include "../libffado/ffado.h"
29 #include "devicemanager.h"
30 #include "ffadodevice.h"
31
32 #include "libstreaming/StreamProcessorManager.h"
33
34 #include <assert.h>
35
36 #include <string.h>
37 #include <string>
38
39 /**
40 * Device structure
41 */
42
43 DECLARE_GLOBAL_DEBUG_MODULE;
44
45 using namespace Streaming;
46
47 struct _ffado_device
48 {
49     DeviceManager * m_deviceManager;
50     StreamProcessorManager *processorManager;
51
52     ffado_options_t options;
53     ffado_device_info_t device_info;
54 };
55
56 ffado_device_t *ffado_streaming_init (ffado_device_info_t *device_info, ffado_options_t options) {
57     unsigned int i=0;
58
59     struct _ffado_device *dev = new struct _ffado_device;
60
61     debugWarning("%s built %s %s\n", ffado_get_version(), __DATE__, __TIME__);
62
63     if(!dev) {
64             debugFatal( "Could not allocate streaming device\n" );
65             return 0;
66     }
67
68     memcpy((void *)&dev->options, (void *)&options, sizeof(dev->options));
69     memcpy((void *)&dev->device_info, (void *)device_info, sizeof(dev->device_info));
70
71     dev->m_deviceManager = new DeviceManager();
72     if ( !dev->m_deviceManager ) {
73             debugFatal( "Could not allocate device manager\n" );
74             delete dev;
75             return 0;
76     }
77
78     dev->m_deviceManager->setVerboseLevel(DEBUG_LEVEL_NORMAL);
79     if ( !dev->m_deviceManager->initialize( dev->options.port ) ) {
80             debugFatal( "Could not initialize device manager\n" );
81             delete dev->m_deviceManager;
82             delete dev;
83             return 0;
84     }
85
86     // create a processor manager to manage the actual stream
87     // processors
88     dev->processorManager = new StreamProcessorManager(dev->options.period_size,dev->options.nb_buffers);
89     if(!dev->processorManager) {
90             debugFatal("Could not create StreamProcessorManager\n");
91             delete dev->m_deviceManager;
92             delete dev;
93             return 0;
94     }
95
96     dev->processorManager->setThreadParameters(dev->options.realtime, dev->options.packetizer_priority);
97
98     dev->processorManager->setVerboseLevel(DEBUG_LEVEL_VERBOSE);
99     if(!dev->processorManager->init()) {
100             debugFatal("Could not init StreamProcessorManager\n");
101             delete dev->processorManager;
102             delete dev->m_deviceManager;
103             delete dev;
104             return 0;
105     }
106
107     // set slave mode option
108     bool slaveMode=(dev->options.slave_mode != 0);
109     debugOutput(DEBUG_LEVEL_VERBOSE, "setting slave mode to %d\n", slaveMode);
110     if(!dev->m_deviceManager->setOption("slaveMode", slaveMode)) {
111             debugWarning("Failed to set slave mode option\n");
112     }
113     // set snoop mode option
114     bool snoopMode=(dev->options.snoop_mode != 0);
115     debugOutput(DEBUG_LEVEL_VERBOSE, "setting snoop mode to %d\n", snoopMode);
116     if(!dev->m_deviceManager->setOption("snoopMode", snoopMode)) {
117             debugWarning("Failed to set snoop mode option\n");
118     }
119
120     // discover the devices on the bus
121     if(!dev->m_deviceManager->discover()) {
122             debugFatal("Could not discover devices\n");
123             delete dev->processorManager;
124             delete dev->m_deviceManager;
125             delete dev;
126             return 0;
127     }
128
129     // are there devices on the bus?
130     if(dev->m_deviceManager->getAvDeviceCount()==0) {
131             debugFatal("There are no devices on the bus\n");
132             delete dev->processorManager;
133             delete dev->m_deviceManager;
134             delete dev;
135             return 0;
136     }
137
138     // iterate over the found devices
139     // add the stream processors of the devices to the managers
140     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
141         FFADODevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
142         assert(device);
143
144         debugOutput(DEBUG_LEVEL_VERBOSE, "Locking device (%p)\n", device);
145
146         if (!device->lock()) {
147             debugWarning("Could not lock device, skipping device (%p)!\n", device);
148             continue;
149         }
150
151         debugOutput(DEBUG_LEVEL_VERBOSE, "Setting samplerate to %d for (%p)\n",
152                     dev->options.sample_rate, device);
153
154         // Set the device's sampling rate to that requested
155         // FIXME: does this really belong here?  If so we need to handle errors.
156         if (!device->setSamplingFrequency(dev->options.sample_rate)) {
157             debugOutput(DEBUG_LEVEL_VERBOSE, " => Retry setting samplerate to %d for (%p)\n",
158                         dev->options.sample_rate, device);
159
160             // try again:
161             if (!device->setSamplingFrequency(dev->options.sample_rate)) {
162                 delete dev->processorManager;
163                 delete dev->m_deviceManager;
164                 delete dev;
165                 debugFatal("Could not set sampling frequency to %d\n",dev->options.sample_rate);
166                 return 0;
167             }
168         }
169
170         // prepare the device
171         device->prepare();
172         int j=0;
173         for(j=0; j<device->getStreamCount();j++) {
174             StreamProcessor *streamproc=device->getStreamProcessorByIndex(j);
175             debugOutput(DEBUG_LEVEL_VERBOSE, "Registering stream processor %d of device %d with processormanager\n",j,i);
176             if (!dev->processorManager->registerProcessor(streamproc)) {
177                 delete dev->processorManager;
178                 delete dev->m_deviceManager;
179                 delete dev;
180                 debugFatal("Could not register stream processor (%p) with the Processor manager\n", streamproc);
181                 return 0;
182             }
183         }
184     }
185
186     // set the sync source
187     if (!dev->processorManager->setSyncSource(dev->m_deviceManager->getSyncSource())) {
188         debugWarning("Could not set processorManager sync source (%p)\n",
189             dev->m_deviceManager->getSyncSource());
190     }
191
192     // we are ready!
193     debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n\n");
194     return dev;
195
196 }
197
198 int ffado_streaming_prepare(ffado_device_t *dev) {
199     debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n");
200
201     if (!dev->processorManager->prepare()) {
202         debugFatal("Could not prepare streaming...\n");
203         return false;
204     }
205
206     return true;
207 }
208
209 void ffado_streaming_finish(ffado_device_t *dev) {
210     unsigned int i=0;
211
212     assert(dev);
213
214     // iterate over the found devices
215     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
216         FFADODevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
217         assert(device);
218
219         debugOutput(DEBUG_LEVEL_VERBOSE, "Unlocking device (%p)\n", device);
220
221         if (!device->unlock()) {
222             debugWarning("Could not unlock device (%p)!\n", device);
223         }
224     }
225
226     delete dev->processorManager;
227     delete dev->m_deviceManager;
228     delete dev;
229
230     return;
231 }
232
233 int ffado_streaming_start(ffado_device_t *dev) {
234     unsigned int i=0;
235     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Start -------------\n");
236
237     // create the connections for all devices
238     // iterate over the found devices
239     // add the stream processors of the devices to the managers
240     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
241         FFADODevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
242         assert(device);
243
244         int j=0;
245         for(j=0; j<device->getStreamCount();j++) {
246         debugOutput(DEBUG_LEVEL_VERBOSE,"Starting stream %d of device %d\n",j,i);
247             // start the stream
248             if (!device->startStreamByIndex(j)) {
249                 debugWarning("Could not start stream %d of device %d\n",j,i);
250                 continue;
251             }
252         }
253
254         if (!device->enableStreaming()) {
255             debugWarning("Could not enable streaming on device %d!\n",i);
256         }
257     }
258
259     if(dev->processorManager->start()) {
260         return 0;
261     } else {
262         ffado_streaming_stop(dev);
263         return -1;
264     }
265 }
266
267 int ffado_streaming_stop(ffado_device_t *dev) {
268     unsigned int i;
269     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Stop -------------\n");
270
271     dev->processorManager->stop();
272
273     // create the connections for all devices
274     // iterate over the found devices
275     // add the stream processors of the devices to the managers
276     for(i=0;i<dev->m_deviceManager->getAvDeviceCount();i++) {
277         FFADODevice *device=dev->m_deviceManager->getAvDeviceByIndex(i);
278         assert(device);
279
280         if (!device->disableStreaming()) {
281             debugWarning("Could not disable streaming on device %d!\n",i);
282         }
283
284         int j=0;
285         for(j=0; j<device->getStreamCount();j++) {
286             debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %d\n",j,i);
287             // stop the stream
288             // start the stream
289             if (!device->stopStreamByIndex(j)) {
290                 debugWarning("Could not stop stream %d of device %d\n",j,i);
291                 continue;
292             }
293         }
294     }
295
296     return 0;
297 }
298
299 int ffado_streaming_reset(ffado_device_t *dev) {
300     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Reset -------------\n");
301
302     // dev->processorManager->reset();
303
304     return 0;
305 }
306
307 int ffado_streaming_wait(ffado_device_t *dev) {
308     static int periods=0;
309     static int periods_print=0;
310     static int xruns=0;
311
312     periods++;
313     if(periods>periods_print) {
314         debugOutputShort(DEBUG_LEVEL_VERBOSE, "\nffado_streaming_wait\n");
315         debugOutputShort(DEBUG_LEVEL_VERBOSE, "============================================\n");
316         debugOutputShort(DEBUG_LEVEL_VERBOSE, "Xruns: %d\n",xruns);
317         debugOutputShort(DEBUG_LEVEL_VERBOSE, "============================================\n");
318         dev->processorManager->dumpInfo();
319         debugOutputShort(DEBUG_LEVEL_VERBOSE, "\n");
320         periods_print+=100;
321     }
322
323     if(dev->processorManager->waitForPeriod()) {
324         return dev->options.period_size;
325     } else {
326         debugWarning("XRUN detected\n");
327
328         // do xrun recovery
329         dev->processorManager->handleXrun();
330         xruns++;
331         return -1;
332     }
333 }
334
335 int ffado_streaming_transfer_capture_buffers(ffado_device_t *dev) {
336     return dev->processorManager->transfer(StreamProcessor::ePT_Receive);
337 }
338
339 int ffado_streaming_transfer_playback_buffers(ffado_device_t *dev) {
340     return dev->processorManager->transfer(StreamProcessor::ePT_Receive);
341 }
342
343 int ffado_streaming_transfer_buffers(ffado_device_t *dev) {
344     return dev->processorManager->transfer();
345 }
346
347
348 int ffado_streaming_write(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) {
349     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
350     // use an assert here performancewise,
351     // it should already have failed before, if not correct
352     assert(p);
353
354     return p->writeEvents((void *)buffer, nsamples);
355 }
356
357 int ffado_streaming_read(ffado_device_t *dev, int i, ffado_sample_t *buffer, int nsamples) {
358     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
359     // use an assert here performancewise,
360     // it should already have failed before, if not correct
361     assert(p);
362
363     return p->readEvents((void *)buffer, nsamples);
364 }
365
366 int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) {
367     return dev->processorManager->getPortCount(Port::E_Capture);
368 }
369
370 int ffado_streaming_get_nb_playback_streams(ffado_device_t *dev) {
371     return dev->processorManager->getPortCount(Port::E_Playback);
372 }
373
374 int ffado_streaming_get_capture_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
375     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
376     if(!p) {
377         debugWarning("Could not get capture port at index %d\n",i);
378         return -1;
379     }
380
381     std::string name=p->getName();
382     if (!strncpy(buffer, name.c_str(), buffersize)) {
383         debugWarning("Could not copy name\n");
384         return -1;
385     } else return 0;
386 }
387
388 int ffado_streaming_get_playback_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
389     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
390     if(!p) {
391         debugWarning("Could not get playback port at index %d\n",i);
392         return -1;
393     }
394
395     std::string name=p->getName();
396     if (!strncpy(buffer, name.c_str(), buffersize)) {
397         debugWarning("Could not copy name\n");
398         return -1;
399     } else return 0;
400 }
401
402 ffado_streaming_stream_type ffado_streaming_get_capture_stream_type(ffado_device_t *dev, int i) {
403     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
404     if(!p) {
405         debugWarning("Could not get capture port at index %d\n",i);
406         return ffado_stream_type_invalid;
407     }
408     switch(p->getPortType()) {
409     case Port::E_Audio:
410         return ffado_stream_type_audio;
411     case Port::E_Midi:
412         return ffado_stream_type_midi;
413     case Port::E_Control:
414         return ffado_stream_type_control;
415     default:
416         return ffado_stream_type_unknown;
417     }
418 }
419
420 ffado_streaming_stream_type ffado_streaming_get_playback_stream_type(ffado_device_t *dev, int i) {
421     Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
422     if(!p) {
423         debugWarning("Could not get playback port at index %d\n",i);
424         return ffado_stream_type_invalid;
425     }
426     switch(p->getPortType()) {
427     case Port::E_Audio:
428         return ffado_stream_type_audio;
429     case Port::E_Midi:
430         return ffado_stream_type_midi;
431     case Port::E_Control:
432         return ffado_stream_type_control;
433     default:
434         return ffado_stream_type_unknown;
435     }
436 }
437
438 int ffado_streaming_set_stream_buffer_type(ffado_device_t *dev, int i,
439     ffado_streaming_buffer_type t, enum Port::E_Direction direction) {
440
441     Port *p=dev->processorManager->getPortByIndex(i, direction);
442     if(!p) {
443         debugWarning("Could not get %s port at index %d\n",
444             (direction==Port::E_Playback?"Playback":"Capture"),i);
445         return -1;
446     }
447
448     switch(t) {
449     case ffado_buffer_type_int24:
450         if (!p->setDataType(Port::E_Int24)) {
451             debugWarning("%s: Could not set data type to Int24\n",p->getName().c_str());
452             return -1;
453         }
454         if (!p->setBufferType(Port::E_PointerBuffer)) {
455             debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str());
456             return -1;
457         }
458         break;
459     case ffado_buffer_type_float:
460         if (!p->setDataType(Port::E_Float)) {
461             debugWarning("%s: Could not set data type to Float\n",p->getName().c_str());
462             return -1;
463         }
464         if (!p->setBufferType(Port::E_PointerBuffer)) {
465             debugWarning("%s: Could not set buffer type to Pointerbuffer\n",p->getName().c_str());
466             return -1;
467         }
468         break;
469     case ffado_buffer_type_midi:
470         if (!p->setDataType(Port::E_MidiEvent)) {
471             debugWarning("%s: Could not set data type to MidiEvent\n",p->getName().c_str());
472             return -1;
473         }
474         if (!p->setBufferType(Port::E_RingBuffer)) {
475             debugWarning("%s: Could not set buffer type to Ringbuffer\n",p->getName().c_str());
476             return -1;
477         }
478         break;
479     default:
480         debugWarning("%s: Unsupported buffer type\n",p->getName().c_str());
481         return -1;
482     }
483     return 0;
484
485 }
486
487 int ffado_streaming_set_playback_buffer_type(ffado_device_t *dev, int i, ffado_streaming_buffer_type t) {
488     return ffado_streaming_set_stream_buffer_type(dev, i, t, Port::E_Playback);
489 }
490
491 int ffado_streaming_set_capture_buffer_type(ffado_device_t *dev, int i, ffado_streaming_buffer_type t) {
492     return ffado_streaming_set_stream_buffer_type(dev, i, t, Port::E_Capture);
493 }
494
495 int ffado_streaming_stream_onoff(ffado_device_t *dev, int i,
496     int on, enum Port::E_Direction direction) {
497     Port *p=dev->processorManager->getPortByIndex(i, direction);
498     if(!p) {
499         debugWarning("Could not get %s port at index %d\n",
500             (direction==Port::E_Playback?"Playback":"Capture"),i);
501         return -1;
502     }
503     if(on) {
504         p->enable();
505     } else {
506         p->disable();
507     }
508     return 0;
509 }
510
511 int ffado_streaming_playback_stream_onoff(ffado_device_t *dev, int number, int on) {
512     return ffado_streaming_stream_onoff(dev, number, on, Port::E_Playback);
513 }
514
515 int ffado_streaming_capture_stream_onoff(ffado_device_t *dev, int number, int on) {
516     return ffado_streaming_stream_onoff(dev, number, on, Port::E_Capture);
517 }
518
519 // TODO: the way port buffers are set in the C api doesn't satisfy me
520 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) {
521         Port *p=dev->processorManager->getPortByIndex(i, Port::E_Capture);
522
523         // use an assert here performancewise,
524         // it should already have failed before, if not correct
525         assert(p);
526
527         p->useExternalBuffer(true);
528         p->setExternalBufferAddress((void *)buff);
529
530         return 0;
531
532 }
533
534 int ffado_streaming_set_playback_stream_buffer(ffado_device_t *dev, int i, char *buff) {
535         Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback);
536         // use an assert here performancewise,
537         // it should already have failed before, if not correct
538         assert(p);
539
540         p->useExternalBuffer(true);
541         p->setExternalBufferAddress((void *)buff);
542
543         return 0;
544 }
545
Note: See TracBrowser for help on using the browser.