root/trunk/libffado/src/ffado.cpp

Revision 2803, 14.4 kB (checked in by jwoithe, 3 years ago)

Cosmetic: capitalise "L" in "Linux".

"Linux" is a proper noun so it should start with a capital letter. These
changes are almost all within comments.

This patch was originally proposed by pander on the ffado-devel mailing
list. It has been expanded to cover all similar cases to maintain
consistency throughout the source tree.

  • 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 "version.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 struct _ffado_device
79 {
80     DeviceManager * m_deviceManager;
81
82     ffado_options_t options;
83     ffado_device_info_t device_info;
84 };
85
86 ffado_device_t *ffado_streaming_init (ffado_device_info_t device_info, ffado_options_t options) {
87     unsigned int i=0;
88     setDebugLevel(options.verbose);
89
90     struct _ffado_device *dev = new struct _ffado_device;
91
92     printMessage("%s built %s %s\n", ffado_get_version(), __DATE__, __TIME__);
93
94 #if DEBUG_USE_MESSAGE_BUFFER
95     // ok
96 #else
97     printMessage("FFADO built without realtime-safe message buffer support. This can cause xruns and is not recommended.\n");
98 #endif
99
100     if(!dev) {
101         debugFatal( "Could not allocate streaming device\n" );
102         return 0;
103     }
104
105     memcpy((void *)&dev->options, (void *)&options, sizeof(dev->options));
106
107     dev->m_deviceManager = new DeviceManager();
108     if ( !dev->m_deviceManager ) {
109         debugFatal( "Could not allocate device manager\n" );
110         delete dev;
111         return 0;
112     }
113
114     dev->m_deviceManager->setVerboseLevel(dev->options.verbose);
115
116     if(dev->options.realtime) {
117         debugOutput(DEBUG_LEVEL_VERBOSE,
118                     "Starting with realtime scheduling, base priority %d\n",
119                     dev->options.packetizer_priority);
120     } else {
121         debugWarning("Realtime scheduling is not enabled. This will cause significant reliability issues.\n");
122     }
123     dev->m_deviceManager->setThreadParameters(dev->options.realtime, dev->options.packetizer_priority);
124
125     for (i = 0; i < device_info.nb_device_spec_strings; i++) {
126         char *s = device_info.device_spec_strings[i];
127         if ( !dev->m_deviceManager->addSpecString(s) ) {
128             debugFatal( "Could not add spec string %s to device manager\n", s );
129             delete dev->m_deviceManager;
130             delete dev;
131             return 0;
132         }
133     }
134     // create a processor manager to manage the actual stream
135     // processors
136     if ( !dev->m_deviceManager->setStreamingParams(dev->options.period_size,
137                                                    dev->options.sample_rate,
138                                                    dev->options.nb_buffers))
139     {
140         debugFatal( "Could not set streaming parameters of device manager\n" );
141         delete dev->m_deviceManager;
142         delete dev;
143         return 0;
144     }
145
146     // set slave mode option
147     bool slaveMode=(dev->options.slave_mode != 0);
148     debugOutput(DEBUG_LEVEL_VERBOSE, "setting slave mode to %d\n", slaveMode);
149     if(!dev->m_deviceManager->setOption("slaveMode", slaveMode)) {
150             debugWarning("Failed to set slave mode option\n");
151     }
152     // set snoop mode option
153     bool snoopMode=(dev->options.snoop_mode != 0);
154     debugOutput(DEBUG_LEVEL_VERBOSE, "setting snoop mode to %d\n", snoopMode);
155     if(!dev->m_deviceManager->setOption("snoopMode", snoopMode)) {
156             debugWarning("Failed to set snoop mode option\n");
157     }
158
159     if ( !dev->m_deviceManager->initialize() ) {
160         debugFatal( "Could not initialize device manager\n" );
161         delete dev->m_deviceManager;
162         delete dev;
163         return 0;
164     }
165     // discover the devices on the bus
166     if(!dev->m_deviceManager->discover()) {
167         debugFatal("Could not discover devices\n");
168         delete dev->m_deviceManager;
169         delete dev;
170         return 0;
171     }
172     // are there devices on the bus?
173     if(dev->m_deviceManager->getAvDeviceCount() == 0) {
174         debugFatal("There are no devices on the bus\n");
175         delete dev->m_deviceManager;
176         delete dev;
177         return 0;
178     }
179     // prepare here or there are no ports for jack
180     if(!dev->m_deviceManager->initStreaming()) {
181         debugFatal("Could not init the streaming system\n");
182         return 0;
183     }
184     // we are ready!
185     return dev;
186 }
187
188 int ffado_streaming_set_period_size(ffado_device_t *dev, unsigned int period) {
189     if (!dev->m_deviceManager->setPeriodSize(period))
190     {
191         debugFatal( "Could not set period size of device manager\n" );
192         return -1;
193     }
194     return 0;
195 }
196
197 int ffado_streaming_prepare(ffado_device_t *dev) {
198     debugOutput(DEBUG_LEVEL_VERBOSE, "Preparing...\n");
199     // prepare here or there are no ports for jack
200     if(!dev->m_deviceManager->prepareStreaming()) {
201         debugFatal("Could not prepare the streaming system\n");
202         return -1;
203     }
204     return 0;
205 }
206
207 void ffado_streaming_finish(ffado_device_t *dev) {
208     assert(dev);
209     if(!dev->m_deviceManager->finishStreaming()) {
210         debugError("Could not finish the streaming\n");
211     }
212     delete dev->m_deviceManager;
213     delete dev;
214     return;
215 }
216
217 int ffado_streaming_start(ffado_device_t *dev) {
218     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Start -------------\n");
219     if(!dev->m_deviceManager->startStreaming()) {
220         debugFatal("Could not start the streaming system\n");
221         return -1;
222     }
223     return 0;
224 }
225
226 int ffado_streaming_stop(ffado_device_t *dev) {
227     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Stop -------------\n");
228     if(!dev->m_deviceManager->stopStreaming()) {
229         debugFatal("Could not stop the streaming system\n");
230         return -1;
231     }
232     return 0;
233 }
234
235 int ffado_streaming_reset(ffado_device_t *dev) {
236     debugOutput(DEBUG_LEVEL_VERBOSE,"------------- Reset -------------\n");
237     if(!dev->m_deviceManager->resetStreaming()) {
238         debugFatal("Could not reset the streaming system\n");
239         return -1;
240     }
241     return 0;
242 }
243
244 ffado_wait_response
245 ffado_streaming_wait(ffado_device_t *dev) {
246     static int periods=0;
247     static int periods_print=0;
248     static int xruns=0;
249
250     periods++;
251     if(periods>periods_print) {
252         debugOutputShort(DEBUG_LEVEL_NORMAL, "\nffado_streaming_wait\n");
253         debugOutputShort(DEBUG_LEVEL_NORMAL, "============================================\n");
254         debugOutputShort(DEBUG_LEVEL_NORMAL, "Xruns: %d\n", xruns);
255         debugOutputShort(DEBUG_LEVEL_NORMAL, "============================================\n");
256         dev->m_deviceManager->showStreamingInfo();
257         debugOutputShort(DEBUG_LEVEL_NORMAL, "\n");
258         periods_print+=100;
259     }
260
261     enum DeviceManager::eWaitResult result;
262     result = dev->m_deviceManager->waitForPeriod();
263     if(result == DeviceManager::eWR_OK) {
264         return ffado_wait_ok;
265     } else if (result == DeviceManager::eWR_Xrun) {
266         debugOutput(DEBUG_LEVEL_NORMAL, "Handled XRUN\n");
267         xruns++;
268         return ffado_wait_xrun;
269     } else if (result == DeviceManager::eWR_Shutdown) {
270         debugWarning("Streaming system requests shutdown.\n");
271         return ffado_wait_shutdown;
272     } else {
273         debugError("Error condition while waiting (Unhandled XRUN)\n");
274         xruns++;
275         return ffado_wait_error;
276     }
277 }
278
279 int ffado_streaming_transfer_capture_buffers(ffado_device_t *dev) {
280     return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Receive);
281 }
282
283 int ffado_streaming_transfer_playback_buffers(ffado_device_t *dev) {
284     return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Transmit);
285 }
286
287 int ffado_streaming_transfer_buffers(ffado_device_t *dev) {
288     return dev->m_deviceManager->getStreamProcessorManager().transfer();
289 }
290
291 int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) {
292     return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Capture);
293 }
294
295 int ffado_streaming_get_nb_playback_streams(ffado_device_t *dev) {
296     return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Playback);
297 }
298
299 int ffado_streaming_get_capture_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
300     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
301     if(!p) {
302         debugWarning("Could not get capture port at index %d\n",i);
303         return -1;
304     }
305
306     std::string name=p->getName();
307     if (!strncpy(buffer, name.c_str(), buffersize)) {
308         debugWarning("Could not copy name\n");
309         return -1;
310     } else return 0;
311 }
312
313 int ffado_streaming_get_playback_stream_name(ffado_device_t *dev, int i, char* buffer, size_t buffersize) {
314     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
315     if(!p) {
316         debugWarning("Could not get playback port at index %d\n",i);
317         return -1;
318     }
319
320     std::string name=p->getName();
321     if (!strncpy(buffer, name.c_str(), buffersize)) {
322         debugWarning("Could not copy name\n");
323         return -1;
324     } else return 0;
325 }
326
327 ffado_streaming_stream_type ffado_streaming_get_capture_stream_type(ffado_device_t *dev, int i) {
328     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
329     if(!p) {
330         debugWarning("Could not get capture port at index %d\n",i);
331         return ffado_stream_type_invalid;
332     }
333     switch(p->getPortType()) {
334     case Streaming::Port::E_Audio:
335         return ffado_stream_type_audio;
336     case Streaming::Port::E_Midi:
337         return ffado_stream_type_midi;
338     case Streaming::Port::E_Control:
339         return ffado_stream_type_control;
340     default:
341         return ffado_stream_type_unknown;
342     }
343 }
344
345 ffado_streaming_stream_type ffado_streaming_get_playback_stream_type(ffado_device_t *dev, int i) {
346     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
347     if(!p) {
348         debugWarning("Could not get playback port at index %d\n",i);
349         return ffado_stream_type_invalid;
350     }
351     switch(p->getPortType()) {
352     case Streaming::Port::E_Audio:
353         return ffado_stream_type_audio;
354     case Streaming::Port::E_Midi:
355         return ffado_stream_type_midi;
356     case Streaming::Port::E_Control:
357         return ffado_stream_type_control;
358     default:
359         return ffado_stream_type_unknown;
360     }
361 }
362
363 int ffado_streaming_set_audio_datatype(ffado_device_t *dev,
364     ffado_streaming_audio_datatype t) {
365     switch(t) {
366         case ffado_audio_datatype_int24:
367             if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType(
368                Streaming::StreamProcessorManager::eADT_Int24)) {
369                 debugError("Could not set datatype\n");
370                 return -1;
371             }
372             break;
373         case ffado_audio_datatype_float:
374             if(!dev->m_deviceManager->getStreamProcessorManager().setAudioDataType(
375                Streaming::StreamProcessorManager::eADT_Float)) {
376                 debugError("Could not set datatype\n");
377                 return -1;
378             }
379             break;
380         default:
381             debugError("Invalid audio datatype\n");
382             return -1;
383     }
384     return 0;
385 }
386
387 ffado_streaming_audio_datatype ffado_streaming_get_audio_datatype(ffado_device_t *dev) {
388     switch(dev->m_deviceManager->getStreamProcessorManager().getAudioDataType()) {
389         case Streaming::StreamProcessorManager::eADT_Int24:
390             return ffado_audio_datatype_int24;
391         case Streaming::StreamProcessorManager::eADT_Float:
392             return ffado_audio_datatype_float;
393         default:
394             debugError("Invalid audio datatype\n");
395             return ffado_audio_datatype_error;
396     }
397 }
398
399 int ffado_streaming_stream_onoff(ffado_device_t *dev, int i,
400     int on, enum Streaming::Port::E_Direction direction) {
401     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, direction);
402     if(!p) {
403         debugWarning("Could not get %s port at index %d\n",
404             (direction==Streaming::Port::E_Playback?"Playback":"Capture"),i);
405         return -1;
406     }
407     if(on) {
408         p->enable();
409     } else {
410         p->disable();
411     }
412     return 0;
413 }
414
415 int ffado_streaming_playback_stream_onoff(ffado_device_t *dev, int number, int on) {
416     return ffado_streaming_stream_onoff(dev, number, on, Streaming::Port::E_Playback);
417 }
418
419 int ffado_streaming_capture_stream_onoff(ffado_device_t *dev, int number, int on) {
420     return ffado_streaming_stream_onoff(dev, number, on, Streaming::Port::E_Capture);
421 }
422
423 int ffado_streaming_set_capture_stream_buffer(ffado_device_t *dev, int i, char *buff) {
424     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Capture);
425     // use an assert here performancewise,
426     // it should already have failed before, if not correct
427     assert(p);
428     p->setBufferAddress((void *)buff);
429     return 0;
430 }
431
432 int ffado_streaming_set_playback_stream_buffer(ffado_device_t *dev, int i, char *buff) {
433     Streaming::Port *p = dev->m_deviceManager->getStreamProcessorManager().getPortByIndex(i, Streaming::Port::E_Playback);
434     // use an assert here performancewise,
435     // it should already have failed before, if not correct
436     assert(p);
437     p->setBufferAddress((void *)buff);
438     return 0;
439 }
Note: See TracBrowser for help on using the browser.