2015-02-16 21:04:18 +01:00
/** @file
* @ author Edouard DUPIN
* @ copyright 2015 , Edouard DUPIN , all right reserved
* @ license APACHE v2 .0 ( see license file )
*/
2015-04-11 09:38:30 +02:00
# ifdef AUDIO_RIVER_BUILD_ORCHESTRA
2015-02-23 22:14:48 +01:00
2015-04-11 09:38:30 +02:00
# include <audio/river/io/NodeOrchestra.h>
# include <audio/river/debug.h>
2015-09-14 21:11:04 +02:00
# include <memory>
2015-02-16 21:04:18 +01:00
# undef __class__
2015-04-11 09:38:30 +02:00
# define __class__ "io::NodeOrchestra"
2015-02-16 21:04:18 +01:00
2015-04-11 09:38:30 +02:00
int32_t audio : : river : : io : : NodeOrchestra : : recordCallback ( const void * _inputBuffer ,
2015-04-13 21:49:48 +02:00
const audio : : Time & _timeInput ,
2015-04-11 09:38:30 +02:00
uint32_t _nbChunk ,
const std : : vector < audio : : orchestra : : status > & _status ) {
2015-02-24 22:20:11 +01:00
std11 : : unique_lock < std11 : : mutex > lock ( m_mutex ) ;
2015-02-17 21:08:15 +01:00
// TODO : Manage status ...
RIVER_VERBOSE ( " data Input size request : " < < _nbChunk < < " [BEGIN] status= " < < _status < < " nbIO= " < < m_list . size ( ) ) ;
newInput ( _inputBuffer , _nbChunk , _timeInput ) ;
return 0 ;
}
2015-04-11 09:38:30 +02:00
int32_t audio : : river : : io : : NodeOrchestra : : playbackCallback ( void * _outputBuffer ,
2015-04-13 21:49:48 +02:00
const audio : : Time & _timeOutput ,
2015-04-11 09:38:30 +02:00
uint32_t _nbChunk ,
const std : : vector < audio : : orchestra : : status > & _status ) {
2015-02-24 22:20:11 +01:00
std11 : : unique_lock < std11 : : mutex > lock ( m_mutex ) ;
2015-02-17 21:08:15 +01:00
// TODO : Manage status ...
RIVER_VERBOSE ( " data Output size request : " < < _nbChunk < < " [BEGIN] status= " < < _status < < " nbIO= " < < m_list . size ( ) ) ;
newOutput ( _outputBuffer , _nbChunk , _timeOutput ) ;
return 0 ;
}
2015-02-16 21:04:18 +01:00
2015-04-11 09:38:30 +02:00
std11 : : shared_ptr < audio : : river : : io : : NodeOrchestra > audio : : river : : io : : NodeOrchestra : : create ( const std : : string & _name , const std11 : : shared_ptr < const ejson : : Object > & _config ) {
return std11 : : shared_ptr < audio : : river : : io : : NodeOrchestra > ( new audio : : river : : io : : NodeOrchestra ( _name , _config ) ) ;
2015-02-16 21:04:18 +01:00
}
2015-04-11 09:38:30 +02:00
audio : : river : : io : : NodeOrchestra : : NodeOrchestra ( const std : : string & _name , const std11 : : shared_ptr < const ejson : : Object > & _config ) :
2015-02-16 21:04:18 +01:00
Node ( _name , _config ) {
2015-04-11 09:38:30 +02:00
audio : : drain : : IOFormatInterface interfaceFormat = getInterfaceFormat ( ) ;
audio : : drain : : IOFormatInterface hardwareFormat = getHarwareFormat ( ) ;
2015-02-16 21:04:18 +01:00
/**
map - on : { # select hardware interface and name
interface : " alsa " , # interface : " alsa " , " pulse " , " core " , . . .
name : " default " , # name of the interface
} ,
nb - chunk : 1024 # number of chunk to open device ( create the latency anf the frequency to call user )
*/
2015-06-14 18:33:24 +02:00
std : : string typeInterface = audio : : orchestra : : type_undefined ;
2015-02-16 21:04:18 +01:00
std : : string streamName = " default " ;
2015-02-24 22:20:11 +01:00
const std11 : : shared_ptr < const ejson : : Object > tmpObject = m_config - > getObject ( " map-on " ) ;
2015-02-16 21:04:18 +01:00
if ( tmpObject = = nullptr ) {
RIVER_WARNING ( " missing node : 'map-on' ==> auto map : 'auto:default' " ) ;
} else {
2015-06-14 18:33:24 +02:00
typeInterface = tmpObject - > getStringValue ( " interface " , audio : : orchestra : : type_undefined ) ;
if ( typeInterface = = " auto " ) {
typeInterface = audio : : orchestra : : type_undefined ;
}
2015-02-16 21:04:18 +01:00
streamName = tmpObject - > getStringValue ( " name " , " default " ) ;
}
int32_t nbChunk = m_config - > getNumberValue ( " nb-chunk " , 1024 ) ;
// intanciate specific API ...
2015-06-11 22:17:17 +02:00
m_interface . instanciate ( typeInterface ) ;
m_interface . setName ( _name ) ;
2015-02-16 21:04:18 +01:00
// TODO : Check return ...
std : : string type = m_config - > getStringValue ( " type " , " int16 " ) ;
if ( streamName = = " " ) {
streamName = " default " ;
}
// search device ID :
RIVER_INFO ( " Open : " ) ;
RIVER_INFO ( " m_streamName= " < < streamName ) ;
RIVER_INFO ( " m_freq= " < < hardwareFormat . getFrequency ( ) ) ;
RIVER_INFO ( " m_map= " < < hardwareFormat . getMap ( ) ) ;
RIVER_INFO ( " m_format= " < < hardwareFormat . getFormat ( ) ) ;
RIVER_INFO ( " m_isInput= " < < m_isInput ) ;
2015-02-26 21:44:16 +01:00
int32_t deviceId = - 1 ;
2015-06-11 22:17:17 +02:00
/*
2015-02-26 21:44:16 +01:00
// TODO : Remove this from here (create an extern interface ...)
2015-02-16 21:04:18 +01:00
RIVER_INFO ( " Device list: " ) ;
2015-06-11 22:17:17 +02:00
for ( int32_t iii = 0 ; iii < m_interface . getDeviceCount ( ) ; + + iii ) {
m_info = m_interface . getDeviceInfo ( iii ) ;
2015-02-16 21:04:18 +01:00
RIVER_INFO ( " " < < iii < < " name : " < < m_info . name ) ;
2015-02-26 21:44:16 +01:00
m_info . display ( 2 ) ;
}
2015-06-11 22:17:17 +02:00
*/
2015-02-26 21:44:16 +01:00
// special case for default IO:
if ( streamName = = " default " ) {
if ( m_isInput = = true ) {
2015-06-11 22:17:17 +02:00
deviceId = m_interface . getDefaultInputDevice ( ) ;
2015-02-26 21:44:16 +01:00
} else {
2015-06-11 22:17:17 +02:00
deviceId = m_interface . getDefaultOutputDevice ( ) ;
2015-02-26 21:44:16 +01:00
}
} else {
2015-06-11 22:17:17 +02:00
for ( int32_t iii = 0 ; iii < m_interface . getDeviceCount ( ) ; + + iii ) {
m_info = m_interface . getDeviceInfo ( iii ) ;
2015-02-26 21:44:16 +01:00
if ( m_info . name = = streamName ) {
RIVER_INFO ( " Select ... id = " < < iii ) ;
deviceId = iii ;
}
2015-02-16 21:04:18 +01:00
}
}
2015-02-26 22:06:31 +01:00
// TODO : Check if the devace with the specific name exist ...
/*
2015-02-26 21:44:16 +01:00
if ( deviceId = = - 1 ) {
RIVER_ERROR ( " Can not find the " < < streamName < < " audio interface ... (use O default ...) " ) ;
deviceId = 0 ;
}
2015-02-26 22:06:31 +01:00
*/
2015-02-16 21:04:18 +01:00
// Open specific ID :
2015-02-26 22:06:31 +01:00
if ( deviceId = = - 1 ) {
2015-06-11 22:17:17 +02:00
m_info = m_interface . getDeviceInfo ( streamName ) ;
2015-02-26 22:06:31 +01:00
} else {
2015-06-11 22:17:17 +02:00
m_info = m_interface . getDeviceInfo ( deviceId ) ;
2015-02-26 22:06:31 +01:00
}
2015-02-16 21:04:18 +01:00
// display property :
{
2015-02-26 22:06:31 +01:00
RIVER_INFO ( " Device " < < deviceId < < " - ' " < < streamName < < " ' property : " ) ;
2015-02-26 21:44:16 +01:00
m_info . display ( ) ;
2015-02-16 21:04:18 +01:00
if ( etk : : isIn ( hardwareFormat . getFormat ( ) , m_info . nativeFormats ) = = false ) {
if ( type = = " auto " ) {
if ( etk : : isIn ( audio : : format_int16 , m_info . nativeFormats ) = = true ) {
hardwareFormat . setFormat ( audio : : format_int16 ) ;
RIVER_INFO ( " auto set format: " < < hardwareFormat . getFormat ( ) ) ;
} else if ( etk : : isIn ( audio : : format_float , m_info . nativeFormats ) = = true ) {
hardwareFormat . setFormat ( audio : : format_float ) ;
RIVER_INFO ( " auto set format: " < < hardwareFormat . getFormat ( ) ) ;
} else if ( etk : : isIn ( audio : : format_int16_on_int32 , m_info . nativeFormats ) = = true ) {
hardwareFormat . setFormat ( audio : : format_int16_on_int32 ) ;
RIVER_INFO ( " auto set format: " < < hardwareFormat . getFormat ( ) ) ;
} else if ( etk : : isIn ( audio : : format_int24 , m_info . nativeFormats ) = = true ) {
hardwareFormat . setFormat ( audio : : format_int24 ) ;
RIVER_INFO ( " auto set format: " < < hardwareFormat . getFormat ( ) ) ;
} else if ( m_info . nativeFormats . size ( ) ! = 0 ) {
hardwareFormat . setFormat ( m_info . nativeFormats [ 0 ] ) ;
RIVER_INFO ( " auto set format: " < < hardwareFormat . getFormat ( ) ) ;
} else {
RIVER_CRITICAL ( " auto set format no element in the configuration: " < < m_info . nativeFormats ) ;
}
} else {
RIVER_CRITICAL ( " Can not manage input transforamtion: " < < hardwareFormat . getFormat ( ) < < " not in " < < m_info . nativeFormats ) ;
}
}
if ( etk : : isIn ( hardwareFormat . getFrequency ( ) , m_info . sampleRates ) = = false ) {
if ( etk : : isIn ( 48000 , m_info . sampleRates ) = = true ) {
hardwareFormat . setFrequency ( 48000 ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) ) ;
} else if ( etk : : isIn ( 44100 , m_info . sampleRates ) = = true ) {
hardwareFormat . setFrequency ( 44100 ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) ) ;
} else if ( etk : : isIn ( 32000 , m_info . sampleRates ) = = true ) {
hardwareFormat . setFrequency ( 32000 ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) ) ;
} else if ( etk : : isIn ( 16000 , m_info . sampleRates ) = = true ) {
hardwareFormat . setFrequency ( 16000 ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) ) ;
} else if ( etk : : isIn ( 8000 , m_info . sampleRates ) = = true ) {
hardwareFormat . setFrequency ( 8000 ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) ) ;
} else if ( etk : : isIn ( 96000 , m_info . sampleRates ) = = true ) {
hardwareFormat . setFrequency ( 96000 ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) ) ;
} else if ( m_info . sampleRates . size ( ) ! = 0 ) {
hardwareFormat . setFrequency ( m_info . sampleRates [ 0 ] ) ;
RIVER_INFO ( " auto set frequency: " < < hardwareFormat . getFrequency ( ) < < " (first element in list) in " < < m_info . sampleRates ) ;
} else {
RIVER_CRITICAL ( " Can not manage input transforamtion: " < < hardwareFormat . getFrequency ( ) < < " not in " < < m_info . sampleRates ) ;
}
interfaceFormat . setFrequency ( hardwareFormat . getFrequency ( ) ) ;
}
}
// open Audio device:
2015-04-11 09:38:30 +02:00
audio : : orchestra : : StreamParameters params ;
2015-02-16 21:04:18 +01:00
params . deviceId = deviceId ;
2015-02-26 22:06:31 +01:00
params . deviceName = streamName ;
2015-03-23 22:46:21 +01:00
params . nChannels = hardwareFormat . getMap ( ) . size ( ) ;
2015-06-14 18:33:24 +02:00
if ( m_info . channels . size ( ) < params . nChannels ) {
RIVER_CRITICAL ( " Can not open hardware device with more channel ( " < < params . nChannels < < " ) that is autorized by hardware ( " < < m_info . channels . size ( ) < < " ). " ) ;
2015-02-16 21:04:18 +01:00
}
2015-04-11 09:38:30 +02:00
audio : : orchestra : : StreamOptions option ;
2015-03-03 21:28:07 +01:00
etk : : from_string ( option . mode , tmpObject - > getStringValue ( " timestamp-mode " , " soft " ) ) ;
2015-02-16 21:04:18 +01:00
2015-03-13 23:22:17 +01:00
RIVER_DEBUG ( " interfaceFormat= " < < interfaceFormat ) ;
RIVER_DEBUG ( " hardwareFormat= " < < hardwareFormat ) ;
2015-02-16 21:04:18 +01:00
m_rtaudioFrameSize = nbChunk ;
RIVER_INFO ( " Open output stream nbChannels= " < < params . nChannels ) ;
2015-04-11 09:38:30 +02:00
enum audio : : orchestra : : error err = audio : : orchestra : : error_none ;
2015-02-16 21:04:18 +01:00
if ( m_isInput = = true ) {
2015-03-13 23:22:17 +01:00
m_process . setInputConfig ( hardwareFormat ) ;
m_process . setOutputConfig ( interfaceFormat ) ;
2015-06-11 22:17:17 +02:00
err = m_interface . openStream ( nullptr , & params ,
2015-02-16 21:04:18 +01:00
hardwareFormat . getFormat ( ) , hardwareFormat . getFrequency ( ) , & m_rtaudioFrameSize ,
2015-04-11 09:38:30 +02:00
std11 : : bind ( & audio : : river : : io : : NodeOrchestra : : recordCallback ,
2015-02-24 22:20:11 +01:00
this ,
2015-02-24 23:55:28 +01:00
std11 : : placeholders : : _1 ,
std11 : : placeholders : : _2 ,
std11 : : placeholders : : _5 ,
2015-02-27 22:21:54 +01:00
std11 : : placeholders : : _6 ) ,
option
2015-02-16 21:04:18 +01:00
) ;
} else {
2015-03-13 23:22:17 +01:00
m_process . setInputConfig ( interfaceFormat ) ;
m_process . setOutputConfig ( hardwareFormat ) ;
2015-06-11 22:17:17 +02:00
err = m_interface . openStream ( & params , nullptr ,
2015-02-16 21:04:18 +01:00
hardwareFormat . getFormat ( ) , hardwareFormat . getFrequency ( ) , & m_rtaudioFrameSize ,
2015-04-11 09:38:30 +02:00
std11 : : bind ( & audio : : river : : io : : NodeOrchestra : : playbackCallback ,
2015-02-24 22:20:11 +01:00
this ,
2015-02-24 23:55:28 +01:00
std11 : : placeholders : : _3 ,
std11 : : placeholders : : _4 ,
std11 : : placeholders : : _5 ,
2015-02-27 22:21:54 +01:00
std11 : : placeholders : : _6 ) ,
option
2015-02-16 21:04:18 +01:00
) ;
}
2015-04-11 09:38:30 +02:00
if ( err ! = audio : : orchestra : : error_none ) {
2015-02-16 21:04:18 +01:00
RIVER_ERROR ( " Create stream : ' " < < m_name < < " ' mode= " < < ( m_isInput ? " input " : " output " ) < < " can not create stream " < < err ) ;
}
m_process . updateInterAlgo ( ) ;
}
2015-04-11 09:38:30 +02:00
audio : : river : : io : : NodeOrchestra : : ~ NodeOrchestra ( ) {
2015-02-24 22:20:11 +01:00
std11 : : unique_lock < std11 : : mutex > lock ( m_mutex ) ;
2015-02-16 21:04:18 +01:00
RIVER_INFO ( " close input stream " ) ;
2015-06-11 22:17:17 +02:00
if ( m_interface . isStreamOpen ( ) ) {
m_interface . closeStream ( ) ;
2015-02-16 21:04:18 +01:00
}
} ;
2015-04-11 09:38:30 +02:00
void audio : : river : : io : : NodeOrchestra : : start ( ) {
2015-02-24 22:20:11 +01:00
std11 : : unique_lock < std11 : : mutex > lock ( m_mutex ) ;
2015-02-16 21:04:18 +01:00
RIVER_INFO ( " Start stream : ' " < < m_name < < " ' mode= " < < ( m_isInput ? " input " : " output " ) ) ;
2015-06-11 22:17:17 +02:00
enum audio : : orchestra : : error err = m_interface . startStream ( ) ;
2015-04-11 09:38:30 +02:00
if ( err ! = audio : : orchestra : : error_none ) {
2015-02-16 21:04:18 +01:00
RIVER_ERROR ( " Start stream : ' " < < m_name < < " ' mode= " < < ( m_isInput ? " input " : " output " ) < < " can not start stream ... " < < err ) ;
}
}
2015-04-11 09:38:30 +02:00
void audio : : river : : io : : NodeOrchestra : : stop ( ) {
2015-02-24 22:20:11 +01:00
std11 : : unique_lock < std11 : : mutex > lock ( m_mutex ) ;
2015-02-16 21:04:18 +01:00
RIVER_INFO ( " Stop stream : ' " < < m_name < < " ' mode= " < < ( m_isInput ? " input " : " output " ) ) ;
2015-06-11 22:17:17 +02:00
enum audio : : orchestra : : error err = m_interface . stopStream ( ) ;
2015-04-11 09:38:30 +02:00
if ( err ! = audio : : orchestra : : error_none ) {
2015-02-16 21:04:18 +01:00
RIVER_ERROR ( " Stop stream : ' " < < m_name < < " ' mode= " < < ( m_isInput ? " input " : " output " ) < < " can not stop stream ... " < < err ) ;
}
}
2015-02-23 22:14:48 +01:00
# endif