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
31 #include "../libffado/ffado.h"
32 #include "libstreaming/generic/StreamProcessor.h"
33 #include "libstreaming/generic/Port.h"
35 #include "debugmodule/debugmodule.h"
37 #include "devicemanager.h"
38 #include "ffadodevice.h"
46 DECLARE_GLOBAL_DEBUG_MODULE
;
47 IMPL_GLOBAL_DEBUG_MODULE( FFADO
, DEBUG_LEVEL_VERBOSE
);
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();
70 return PACKAGE_STRING
;
74 ffado_get_api_version() {
75 return FFADO_API_VERSION
;
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
) {
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
97 printMessage("FFADO built without realtime-safe message buffer support. This can cause xruns and is not recommended.\n");
101 debugFatal( "Could not allocate streaming device\n" );
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" );
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
);
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
;
134 // create a processor manager to manage the actual stream
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
;
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
;
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
;
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
;
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");
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" );
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");
207 void ffado_streaming_finish(ffado_device_t
*dev
) {
209 if(!dev
->m_deviceManager
->finishStreaming()) {
210 debugError("Could not finish the streaming\n");
212 delete dev
->m_deviceManager
;
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");
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");
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");
245 ffado_streaming_wait(ffado_device_t
*dev
) {
246 static int periods
=0;
247 static int periods_print
=0;
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");
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");
268 return ffado_wait_xrun
;
269 } else if (result
== DeviceManager::eWR_Shutdown
) {
270 debugWarning("Streaming system requests shutdown.\n");
271 return ffado_wait_shutdown
;
273 debugError("Error condition while waiting (Unhandled XRUN)\n");
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
);
302 debugWarning("Could not get capture port at index %d\n",i
);
306 std::string name
=p
->getName();
307 if (!strncpy(buffer
, name
.c_str(), buffersize
)) {
308 debugWarning("Could not copy name\n");
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
);
316 debugWarning("Could not get playback port at index %d\n",i
);
320 std::string name
=p
->getName();
321 if (!strncpy(buffer
, name
.c_str(), buffersize
)) {
322 debugWarning("Could not copy name\n");
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
);
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
;
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
);
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
;
359 return ffado_stream_type_unknown
;
363 int ffado_streaming_set_audio_datatype(ffado_device_t
*dev
,
364 ffado_streaming_audio_datatype 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");
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");
381 debugError("Invalid audio datatype\n");
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
;
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
);
403 debugWarning("Could not get %s port at index %d\n",
404 (direction
==Streaming::Port::E_Playback
?"Playback":"Capture"),i
);
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
428 p
->setBufferAddress((void *)buff
);
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
437 p
->setBufferAddress((void *)buff
);