root/trunk/libffado/src/ffado.cpp

Revision 742, 18.7 kB (checked in by ppalmers, 13 years ago)

- Remove some obsolete support files and dirs

- Clean up the license statements in the source files. Everything is

GPL version 3 now.

- Add license and copyright notices to scons scripts

- Clean up some other text files

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