root/trunk/libffado/src/ffado.cpp

Revision 864, 13.6 kB (checked in by ppalmers, 16 years ago)

update license to GPLv2 or GPLv3 instead of GPLv2 or any later version. Update copyrights to reflect the new year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2  * Copyright (C) 2005-2008 by Daniel Wagner
3  * Copyright (C) 2005-2008 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 2 of the License, or
13  * (at your option) version 3 of the License.
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 #include "libstreaming/generic/StreamProcessor.h"
33 #include "libstreaming/generic/Port.h"
34
35 #include "debugmodule/debugmodule.h"
36 #include "fbtypes.h"
37 #include "devicemanager.h"
38 #include "ffadodevice.h"
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <string>
45
46 DECLARE_GLOBAL_DEBUG_MODULE;
47 IMPL_GLOBAL_DEBUG_MODULE( FFADO, DEBUG_LEVEL_VERBOSE );
48
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
52
53 // this is very much nescessary, as otherwise the
54 // message buffer thread doesn't get killed when the
55 // library is dlclose()'d
56
57 static void exitfunc(void) __attribute__((destructor));
58
59 static void exitfunc(void)
60 {
61     delete DebugModuleManager::instance();
62
63 }
64 #ifdef __cplusplus
65 }
66 #endif
67
68 const char*
69 ffado_get_version() {
70     return PACKAGE_STRING;
71 }
72
73 int
74 ffado_get_api_version() {
75     return FFADO_API_VERSION;
76 }
77
78 #warning this should be cleaned up
79 #include "libavc/general/avc_generic.h"
80 void ffado_sleep_after_avc_command( int time )
81 {
82     AVC::AVCCommand::setSleepAfterAVCCommand( time );
83 }
84
85 struct _ffado_device
86 {
87     DeviceManager * m_deviceManager;
88
89     ffado_options_t options;
90     ffado_device_info_t device_info;
91 };
92
93 ffado_device_t *ffado_streaming_init (ffado_device_info_t device_info, ffado_options_t options) {
94     unsigned int i=0;
95     setDebugLevel(options.verbose);
96
97     struct _ffado_device *dev = new struct _ffado_device;
98
99     debugWarning("%s built %s %s\n", ffado_get_version(), __DATE__, __TIME__);
100
101     if(!dev) {
102         debugFatal( "Could not allocate streaming device\n" );
103         return 0;
104     }
105
106     memcpy((void *)&dev->options, (void *)&options, sizeof(dev->options));
107
108     dev->m_deviceManager = new DeviceManager();
109     if ( !dev->m_deviceManager ) {
110         debugFatal( "Could not allocate device manager\n" );
111         delete dev;
112         return 0;
113     }
114
115     dev->m_deviceManager->setVerboseLevel(dev->options.verbose);
116     dev->m_deviceManager->setThreadParameters(dev->options.realtime, dev->options.packetizer_priority);
117
118     for (i = 0; i < device_info.nb_device_spec_strings; i++) {
119         char *s = device_info.device_spec_strings[i];
120         if ( !dev->m_deviceManager->addSpecString(s) ) {
121             debugFatal( "Could not add spec string %s to device manager\n", s );
122             delete dev->m_deviceManager;
123             delete dev;
124             return 0;
125         }
126     }
127     // create a processor manager to manage the actual stream
128     // processors
129     if ( !dev->m_deviceManager->setStreamingParams(dev->options.period_size,
130                                                    dev->options.sample_rate,
131                                                    dev->options.nb_buffers))
132     {
133         debugFatal( "Could not set streaming parameters of device manager\n" );
134         delete dev->m_deviceManager;
135         delete dev;
136         return 0;
137     }
138
139     // set slave mode option
140     bool slaveMode=(dev->options.slave_mode != 0);
141     debugOutput(DEBUG_LEVEL_VERBOSE, "setting slave mode to %d\n", slaveMode);
142     if(!dev->m_deviceManager->setOption("slaveMode", slaveMode)) {
143             debugWarning("Failed to set slave mode option\n");
144     }
145     // set snoop mode option
146     bool snoopMode=(dev->options.snoop_mode != 0);
147     debugOutput(DEBUG_LEVEL_VERBOSE, "setting snoop mode to %d\n", snoopMode);
148     if(!dev->m_deviceManager->setOption("snoopMode", snoopMode)) {
149             debugWarning("Failed to set snoop mode option\n");
150     }
151
152     if ( !dev->m_deviceManager->initialize() ) {
153         debugFatal( "Could not initialize device manager\n" );
154         delete dev->m_deviceManager;
155         delete dev;
156         return 0;
157     }
158     // discover the devices on the bus
159     if(!dev->m_deviceManager->discover()) {
160         debugFatal("Could not discover devices\n");
161         delete dev->m_deviceManager;
162         delete dev;
163         return 0;
164     }
165     // are there devices on the bus?
166     if(dev->m_deviceManager->getAvDeviceCount() == 0) {
167         debugFatal("There are no devices on the bus\n");
168         delete dev->m_deviceManager;
169         delete dev;
170         return 0;
171     }
172     // prepare here or there are no ports for jack
173     if(!dev->m_deviceManager->initStreaming()) {
174         debugFatal("Could not init the streaming system\n");
175         return 0;
176     }
177     // we are ready!
178     return dev;
179 }
180
181 int ffado_streaming_prepare(ffado_device_t *dev) {
182     debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n");
183     // prepare here or there are no ports for jack
184     if(!dev->m_deviceManager->prepareStreaming()) {
185         debugFatal("Could not prepare the streaming system\n");
186         return -1;
187     }
188     return 0;
189 }
190
191 void ffado_streaming_finish(ffado_device_t *dev) {
192     assert(dev);
193     if(!dev->m_deviceManager->finishStreaming()) {
194         debugError("Could not finish the streaming\n");
195     }
196     delete dev->m_deviceManager;
197     delete dev;
198     return;
199 }
200
201 int ffado_streaming_start(ffado_device_t *dev) {
202     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Start -------------\n");
203     if(!dev->m_deviceManager->startStreaming()) {
204         debugFatal("Could not start the streaming system\n");
205         return -1;
206     }
207     return 0;
208 }
209
210 int ffado_streaming_stop(ffado_device_t *dev) {
211     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Stop -------------\n");
212     if(!dev->m_deviceManager->stopStreaming()) {
213         debugFatal("Could not stop the streaming system\n");
214         return -1;
215     }
216     return 0;
217 }
218
219 int ffado_streaming_reset(ffado_device_t *dev) {
220     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Reset -------------\n");
221     if(!dev->m_deviceManager->resetStreaming()) {
222         debugFatal("Could not reset the streaming system\n");
223         return -1;
224     }
225     return 0;
226 }
227
228 ffado_wait_response
229 ffado_streaming_wait(ffado_device_t *dev) {
230     static int periods=0;
231     static int periods_print=0;
232     static int xruns=0;
233
234     periods++;
235     if(periods>periods_print) {
236         debugOutputShort(DEBUG_LEVEL_NORMAL, "\nffado_streaming_wait\n");
237         debugOutputShort(DEBUG_LEVEL_NORMAL, "============================================\n");
238         debugOutputShort(DEBUG_LEVEL_NORMAL, "Xruns: %d\n", xruns);
239         debugOutputShort(DEBUG_LEVEL_NORMAL, "============================================\n");
240         dev->m_deviceManager->showStreamingInfo();
241         debugOutputShort(DEBUG_LEVEL_NORMAL, "\n");
242         periods_print+=100;
243     }
244
245     enum DeviceManager::eWaitResult result;
246     result = dev->m_deviceManager->waitForPeriod();
247     if(result == DeviceManager::eWR_OK) {
248         return ffado_wait_ok;
249     } else if (result == DeviceManager::eWR_Xrun) {
250         debugWarning("Handled XRUN\n");
251         xruns++;
252         return ffado_wait_xrun;
253     } else {
254         debugError("Unhandled XRUN (BUG)\n");
255         xruns++;
256         return ffado_wait_error;
257     }
258 }
259
260 int ffado_streaming_transfer_capture_buffers(ffado_device_t *dev) {
261     return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Receive);
262 }
263
264 int ffado_streaming_transfer_playback_buffers(ffado_device_t *dev) {
265     return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Transmit);
266 }
267
268 int ffado_streaming_transfer_buffers(ffado_device_t *dev) {
269     return dev->m_deviceManager->getStreamProcessorManager().transfer();
270 }
271
272 int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) {
273     return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Capture);
274 }
275
276 int ffado_streaming_get_nb_playback_streams(ffado_device_t *dev) {
277     return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Playback);
278 }
279
280 int ffado_streaming_get_capture_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
281     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
282     if(!p) {
283         debugWarning("Could not get capture port at index %d\n",i);
284         return -1;
285     }
286
287     std::string name=p->getName();
288     if (!strncpy(buffer, name.c_str(), buffersize)) {
289         debugWarning("Could not copy name\n");
290         return -1;
291     } else return 0;
292 }
293
294 int ffado_streaming_get_playback_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
295     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
296     if(!p) {
297         debugWarning("Could not get playback port at index %d\n",i);
298         return -1;
299     }
300
301     std::string name=p->getName();
302     if (!strncpy(buffer, name.c_str(), buffersize)) {
303         debugWarning("Could not copy name\n");
304         return -1;
305     } else return 0;
306 }
307
308 ffado_streaming_stream_type ffado_streaming_get_capture_stream_type(ffado_device_t *dev, int i) {
309     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
310     if(!p) {
311         debugWarning("Could not get capture port at index %d\n",i);
312         return ffado_stream_type_invalid;
313     }
314     switch(p->getPortType()) {
315     case Streaming::Port::E_Audio:
316         return ffado_stream_type_audio;
317     case Streaming::Port::E_Midi:
318         return ffado_stream_type_midi;
319     case Streaming::Port::E_Control:
320         return ffado_stream_type_control;
321     default:
322         return ffado_stream_type_unknown;
323     }
324 }
325
326 ffado_streaming_stream_type ffado_streaming_get_playback_stream_type(ffado_device_t *dev, int i) {
327     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
328     if(!p) {
329         debugWarning("Could not get playback port at index %d\n",i);
330         return ffado_stream_type_invalid;
331     }
332     switch(p->getPortType()) {
333     case Streaming::Port::E_Audio:
334         return ffado_stream_type_audio;
335     case Streaming::Port::E_Midi:
336         return ffado_stream_type_midi;
337     case Streaming::Port::E_Control:
338         return ffado_stream_type_control;
339     default:
340         return ffado_stream_type_unknown;
341     }
342 }
343
344 int ffado_streaming_set_audio_datatype(ffado_device_t *dev,
345     ffado_streaming_audio_datatype t) {
346     switch(t) {
347         case ffado_audio_datatype_int24:
348             if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType(
349                Streaming::StreamProcessorManager::eADT_Int24)) {
350                 debugError("Could not set datatype\n");
351                 return -1;
352             }
353             break;
354         case ffado_audio_datatype_float:
355             if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType(
356                Streaming::StreamProcessorManager::eADT_Float)) {
357                 debugError("Could not set datatype\n");
358                 return -1;
359             }
360             break;
361         default:
362             debugError("Invalid audio datatype\n");
363             return -1;
364     }
365     return 0;
366 }
367
368 ffado_streaming_audio_datatype ffado_streaming_get_audio_datatype(ffado_device_t *dev) {
369     switch(dev->m_deviceManager->getStreamProcessorManager().getAudioDataType()) {
370         case Streaming::StreamProcessorManager::eADT_Int24:
371             return ffado_audio_datatype_int24;
372         case Streaming::StreamProcessorManager::eADT_Float:
373             return ffado_audio_datatype_float;
374         default:
375             debugError("Invalid audio datatype\n");
376             return ffado_audio_datatype_error;
377     }
378     #warning FIXME
379 }
380
381 int ffado_streaming_stream_onoff(ffado_device_t *dev, int i,
382     int on, enum Streaming::Port::E_Direction direction) {
383     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, direction);
384     if(!p) {
385         debugWarning("Could not get %s port at index %d\n",
386             (direction==Streaming::Port::E_Playback?"Playback":"Capture"),i);
387         return -1;
388     }
389     if(on) {
390         p->enable();
391     } else {
392         p->disable();
393     }
394     return 0;
395 }
396
397 int ffado_streaming_playback_stream_onoff(ffado_device_t *dev, int number, int on) {
398     return ffado_streaming_stream_onoff(dev, number, on, Streaming::Port::E_Playback);
399 }
400
401 int ffado_streaming_capture_stream_onoff(ffado_device_t *dev, int number, int on) {
402     return ffado_streaming_stream_onoff(dev, number, on, Streaming::Port::E_Capture);
403 }
404
405 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) {
406     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
407     // use an assert here performancewise,
408     // it should already have failed before, if not correct
409     assert(p);
410     p->setBufferAddress((void *)buff);
411     return 0;
412 }
413
414 int ffado_streaming_set_playback_stream_buffer(ffado_device_t *dev, int i, char *buff) {
415     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
416     // use an assert here performancewise,
417     // it should already have failed before, if not correct
418     assert(p);
419     p->setBufferAddress((void *)buff);
420     return 0;
421 }
Note: See TracBrowser for help on using the browser.