root/branches/api-cleanup/src/ffado.cpp

Revision 816, 13.4 kB (checked in by ppalmers, 16 years ago)

remove support for per-port datatypes. It's too much hassle and it doesn't add enough value.
It also prevents thorough performance optimizations, especially for larger channel counts (e.g. SSE based).

Audio ports are now either all float or all int24. This can be specified by the ffado_streaming_set_audio_datatype
API function before the streaming is prepared. Hence we can still support the direct conversion to the
clients datatype when demuxing the packets.

  • 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 #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 int ffado_streaming_wait(ffado_device_t *dev) {
229     static int periods=0;
230     static int periods_print=0;
231     static int xruns=0;
232
233     periods++;
234     if(periods>periods_print) {
235         debugOutputShort(DEBUG_LEVEL_NORMAL, "\nffado_streaming_wait\n");
236         debugOutputShort(DEBUG_LEVEL_NORMAL, "============================================\n");
237         debugOutputShort(DEBUG_LEVEL_NORMAL, "Xruns: %d\n", xruns);
238         debugOutputShort(DEBUG_LEVEL_NORMAL, "============================================\n");
239         dev->m_deviceManager->showStreamingInfo();
240         debugOutputShort(DEBUG_LEVEL_NORMAL, "\n");
241         periods_print+=100;
242     }
243
244     if(dev->m_deviceManager->waitForPeriod()) {
245         return dev->options.period_size;
246     } else {
247         debugWarning("XRUN\n");
248         xruns++;
249         return -1;
250     }
251 }
252
253 int ffado_streaming_transfer_capture_buffers(ffado_device_t *dev) {
254     return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Receive);
255 }
256
257 int ffado_streaming_transfer_playback_buffers(ffado_device_t *dev) {
258     return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Transmit);
259 }
260
261 int ffado_streaming_transfer_buffers(ffado_device_t *dev) {
262     return dev->m_deviceManager->getStreamProcessorManager().transfer();
263 }
264
265 int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) {
266     return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Capture);
267 }
268
269 int ffado_streaming_get_nb_playback_streams(ffado_device_t *dev) {
270     return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Playback);
271 }
272
273 int ffado_streaming_get_capture_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
274     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
275     if(!p) {
276         debugWarning("Could not get capture port at index %d\n",i);
277         return -1;
278     }
279
280     std::string name=p->getName();
281     if (!strncpy(buffer, name.c_str(), buffersize)) {
282         debugWarning("Could not copy name\n");
283         return -1;
284     } else return 0;
285 }
286
287 int ffado_streaming_get_playback_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
288     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
289     if(!p) {
290         debugWarning("Could not get playback port at index %d\n",i);
291         return -1;
292     }
293
294     std::string name=p->getName();
295     if (!strncpy(buffer, name.c_str(), buffersize)) {
296         debugWarning("Could not copy name\n");
297         return -1;
298     } else return 0;
299 }
300
301 ffado_streaming_stream_type ffado_streaming_get_capture_stream_type(ffado_device_t *dev, int i) {
302     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
303     if(!p) {
304         debugWarning("Could not get capture port at index %d\n",i);
305         return ffado_stream_type_invalid;
306     }
307     switch(p->getPortType()) {
308     case Streaming::Port::E_Audio:
309         return ffado_stream_type_audio;
310     case Streaming::Port::E_Midi:
311         return ffado_stream_type_midi;
312     case Streaming::Port::E_Control:
313         return ffado_stream_type_control;
314     default:
315         return ffado_stream_type_unknown;
316     }
317 }
318
319 ffado_streaming_stream_type ffado_streaming_get_playback_stream_type(ffado_device_t *dev, int i) {
320     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
321     if(!p) {
322         debugWarning("Could not get playback port at index %d\n",i);
323         return ffado_stream_type_invalid;
324     }
325     switch(p->getPortType()) {
326     case Streaming::Port::E_Audio:
327         return ffado_stream_type_audio;
328     case Streaming::Port::E_Midi:
329         return ffado_stream_type_midi;
330     case Streaming::Port::E_Control:
331         return ffado_stream_type_control;
332     default:
333         return ffado_stream_type_unknown;
334     }
335 }
336
337 int ffado_streaming_set_audio_datatype(ffado_device_t *dev,
338     ffado_streaming_audio_datatype t) {
339     switch(t) {
340         case ffado_audio_datatype_int24:
341             if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType(
342                Streaming::StreamProcessorManager::eADT_Int24)) {
343                 debugError("Could not set datatype\n");
344                 return -1;
345             }
346             break;
347         case ffado_audio_datatype_float:
348             if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType(
349                Streaming::StreamProcessorManager::eADT_Float)) {
350                 debugError("Could not set datatype\n");
351                 return -1;
352             }
353             break;
354         default:
355             debugError("Invalid audio datatype\n");
356             return -1;
357     }
358     return 0;
359 }
360
361 ffado_streaming_audio_datatype ffado_streaming_get_audio_datatype(ffado_device_t *dev) {
362     switch(dev->m_deviceManager->getStreamProcessorManager().getAudioDataType()) {
363         case Streaming::StreamProcessorManager::eADT_Int24:
364             return ffado_audio_datatype_int24;
365         case Streaming::StreamProcessorManager::eADT_Float:
366             return ffado_audio_datatype_float;
367         default:
368             debugError("Invalid audio datatype\n");
369             return ffado_audio_datatype_error;
370     }
371     #warning FIXME
372 }
373
374 int ffado_streaming_stream_onoff(ffado_device_t *dev, int i,
375     int on, enum Streaming::Port::E_Direction direction) {
376     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, direction);
377     if(!p) {
378         debugWarning("Could not get %s port at index %d\n",
379             (direction==Streaming::Port::E_Playback?"Playback":"Capture"),i);
380         return -1;
381     }
382     if(on) {
383         p->enable();
384     } else {
385         p->disable();
386     }
387     return 0;
388 }
389
390 int ffado_streaming_playback_stream_onoff(ffado_device_t *dev, int number, int on) {
391     return ffado_streaming_stream_onoff(dev, number, on, Streaming::Port::E_Playback);
392 }
393
394 int ffado_streaming_capture_stream_onoff(ffado_device_t *dev, int number, int on) {
395     return ffado_streaming_stream_onoff(dev, number, on, Streaming::Port::E_Capture);
396 }
397
398 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) {
399     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
400     // use an assert here performancewise,
401     // it should already have failed before, if not correct
402     assert(p);
403     p->setBufferAddress((void *)buff);
404     return 0;
405 }
406
407 int ffado_streaming_set_playback_stream_buffer(ffado_device_t *dev, int i, char *buff) {
408     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
409     // use an assert here performancewise,
410     // it should already have failed before, if not correct
411     assert(p);
412     p->setBufferAddress((void *)buff);
413     return 0;
414 }
Note: See TracBrowser for help on using the browser.