motu: the 4pre channel layout within packets is now believed to be correct. Thanks...
[ffado.git] / libffado / src / ffado.cpp
blobf702ce1c32bb5ad9db4f5abc3b63d733ab99844a
1 /*
2 * Copyright (C) 2005-2008 by Daniel Wagner
3 * Copyright (C) 2005-2008 by Pieter Palmers
5 * This file is part of FFADO
6 * FFADO = Free Firewire (pro-)audio drivers for linux
8 * FFADO is based upon FreeBoB
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.
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.
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/>.
26 * Implementation of the FFADO external C API
29 #include "version.h"
31 #include "../libffado/ffado.h"
32 #include "libstreaming/generic/StreamProcessor.h"
33 #include "libstreaming/generic/Port.h"
35 #include "debugmodule/debugmodule.h"
36 #include "fbtypes.h"
37 #include "devicemanager.h"
38 #include "ffadodevice.h"
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <string>
46 DECLARE_GLOBAL_DEBUG_MODULE;
47 IMPL_GLOBAL_DEBUG_MODULE( FFADO, DEBUG_LEVEL_VERBOSE );
49 #ifdef __cplusplus
50 extern "C" {
51 #endif
53 // this is very much nescessary, as otherwise the
54 // message buffer thread doesn't get killed when the
55 // library is dlclose()'d
57 static void exitfunc(void) __attribute__((destructor));
59 static void exitfunc(void)
61 delete DebugModuleManager::instance();
64 #ifdef __cplusplus
66 #endif
68 const char*
69 ffado_get_version() {
70 return PACKAGE_STRING;
73 int
74 ffado_get_api_version() {
75 return FFADO_API_VERSION;
78 struct _ffado_device
80 DeviceManager * m_deviceManager;
82 ffado_options_t options;
83 ffado_device_info_t device_info;
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);
90 struct _ffado_device *dev = new struct _ffado_device;
92 printMessage("%s built %s %s\n", ffado_get_version(), __DATE__, __TIME__);
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
100 if(!dev) {
101 debugFatal( "Could not allocate streaming device\n" );
102 return 0;
105 memcpy((void *)&dev->options, (void *)&options, sizeof(dev->options));
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;
114 dev->m_deviceManager->setVerboseLevel(dev->options.verbose);
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");
123 dev->m_deviceManager->setThreadParameters(dev->options.realtime, dev->options.packetizer_priority);
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;
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))
140 debugFatal( "Could not set streaming parameters of device manager\n" );
141 delete dev->m_deviceManager;
142 delete dev;
143 return 0;
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");
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");
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;
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;
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;
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;
184 // we are ready!
185 return dev;
188 int ffado_streaming_set_period_size(ffado_device_t *dev, unsigned int period) {
189 if (!dev->m_deviceManager->setPeriodSize(period))
191 debugFatal( "Could not set period size of device manager\n" );
192 return -1;
194 return 0;
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;
204 return 0;
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");
212 delete dev->m_deviceManager;
213 delete dev;
214 return;
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;
223 return 0;
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;
232 return 0;
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;
241 return 0;
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;
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;
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;
279 int ffado_streaming_transfer_capture_buffers(ffado_device_t *dev) {
280 return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Receive);
283 int ffado_streaming_transfer_playback_buffers(ffado_device_t *dev) {
284 return dev->m_deviceManager->getStreamProcessorManager().transfer(Streaming::StreamProcessor::ePT_Transmit);
287 int ffado_streaming_transfer_buffers(ffado_device_t *dev) {
288 return dev->m_deviceManager->getStreamProcessorManager().transfer();
291 int ffado_streaming_get_nb_capture_streams(ffado_device_t *dev) {
292 return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Capture);
295 int ffado_streaming_get_nb_playback_streams(ffado_device_t *dev) {
296 return dev->m_deviceManager->getStreamProcessorManager().getPortCount(Streaming::Port::E_Playback);
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
379 break;
380 default:
381 debugError("Invalid audio datatype\n");
382 return -1;
384 return 0;
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;
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;
407 if(on) {
408 p->enable();
409 } else {
410 p->disable();
412 return 0;
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);
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);
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;
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;