-/************************************************************************/
+/************************************************************************/
/*! \class RtAudio
\brief Realtime audio i/o C++ classes.
return RTAUDIO_VERSION;
}
-void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
-{
- apis.clear();
+// Define API names and display names.
+// Must be in same order as API enum.
+extern "C" {
+const char* rtaudio_api_names[][2] = {
+ { "unspecified" , "Unknown" },
+ { "alsa" , "ALSA" },
+ { "pulse" , "Pulse" },
+ { "oss" , "OpenSoundSystem" },
+ { "jack" , "Jack" },
+ { "core" , "CoreAudio" },
+ { "wasapi" , "WASAPI" },
+ { "asio" , "ASIO" },
+ { "ds" , "DirectSound" },
+ { "dummy" , "Dummy" },
+};
+const unsigned int rtaudio_num_api_names =
+ sizeof(rtaudio_api_names)/sizeof(rtaudio_api_names[0]);
- // The order here will control the order of RtAudio's API search in
- // the constructor.
+// The order here will control the order of RtAudio's API search in
+// the constructor.
+extern "C" const RtAudio::Api rtaudio_compiled_apis[] = {
#if defined(__UNIX_JACK__)
- apis.push_back( UNIX_JACK );
+ RtAudio::UNIX_JACK,
#endif
#if defined(__LINUX_PULSE__)
- apis.push_back( LINUX_PULSE );
+ RtAudio::LINUX_PULSE,
#endif
#if defined(__LINUX_ALSA__)
- apis.push_back( LINUX_ALSA );
+ RtAudio::LINUX_ALSA,
#endif
#if defined(__LINUX_OSS__)
- apis.push_back( LINUX_OSS );
+ RtAudio::LINUX_OSS,
#endif
#if defined(__WINDOWS_ASIO__)
- apis.push_back( WINDOWS_ASIO );
+ RtAudio::WINDOWS_ASIO,
#endif
#if defined(__WINDOWS_WASAPI__)
- apis.push_back( WINDOWS_WASAPI );
+ RtAudio::WINDOWS_WASAPI,
#endif
#if defined(__WINDOWS_DS__)
- apis.push_back( WINDOWS_DS );
+ RtAudio::WINDOWS_DS,
#endif
#if defined(__MACOSX_CORE__)
- apis.push_back( MACOSX_CORE );
+ RtAudio::MACOSX_CORE,
#endif
#if defined(__RTAUDIO_DUMMY__)
- apis.push_back( RTAUDIO_DUMMY );
+ RtAudio::RTAUDIO_DUMMY,
#endif
+ RtAudio::UNSPECIFIED,
+};
+extern "C" const unsigned int rtaudio_num_compiled_apis =
+ sizeof(rtaudio_compiled_apis)/sizeof(rtaudio_compiled_apis[0])-1;
+}
+
+// This is a compile-time check that rtaudio_num_api_names == RtAudio::NUM_APIS.
+// If the build breaks here, check that they match.
+template<bool b> class StaticAssert { private: StaticAssert() {} };
+template<> class StaticAssert<true>{ public: StaticAssert() {} };
+class StaticAssertions { StaticAssertions() {
+ StaticAssert<rtaudio_num_api_names == RtAudio::NUM_APIS>();
+}};
+
+void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
+{
+ apis = std::vector<RtAudio::Api>(rtaudio_compiled_apis,
+ rtaudio_compiled_apis + rtaudio_num_compiled_apis);
+}
+
+std::string RtAudio :: getApiName( RtAudio::Api api )
+{
+ if (api < 0 || api >= RtAudio::NUM_APIS)
+ return "";
+ return rtaudio_api_names[api][0];
+}
+
+std::string RtAudio :: getApiDisplayName( RtAudio::Api api )
+{
+ if (api < 0 || api >= RtAudio::NUM_APIS)
+ return "Unknown";
+ return rtaudio_api_names[api][1];
+}
+
+RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name )
+{
+ unsigned int i=0;
+ for (i = 0; i < rtaudio_num_compiled_apis; ++i)
+ if (name == rtaudio_api_names[rtaudio_compiled_apis[i]][0])
+ return rtaudio_compiled_apis[i];
+ return RtAudio::UNSPECIFIED;
}
void RtAudio :: openRtApi( RtAudio::Api api )
result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
if ( result != ASE_OK ) {
// Standard method failed. This can happen with strict/misbehaving drivers that return valid buffer size ranges
- // but only accept the preferred buffer size as parameter for ASIOCreateBuffers. eg. Creatives ASIO driver
- // in that case, let's be naïve and try that instead
+ // but only accept the preferred buffer size as parameter for ASIOCreateBuffers (e.g. Creative's ASIO driver).
+ // In that case, let's be naïve and try that instead.
*bufferSize = preferSize;
stream_.bufferSize = *bufferSize;
result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks );
#ifndef INITGUID
#define INITGUID
#endif
-#include <audioclient.h>
-#include <avrt.h>
-#include <mmdeviceapi.h>
-#include <functiondiscoverykeys_devpkey.h>
#include <mfapi.h>
#include <mferror.h>
#include <mfplay.h>
+#include <mftransform.h>
#include <wmcodecdsp.h>
-#pragma comment( lib, "mfplat.lib" )
-#pragma comment( lib, "mfuuid.lib" )
-#pragma comment( lib, "wmcodecdspuuid" )
+#include <audioclient.h>
+#include <avrt.h>
+#include <mmdeviceapi.h>
+#include <functiondiscoverykeys_devpkey.h>
+
+#ifndef MF_E_TRANSFORM_NEED_MORE_INPUT
+ #define MF_E_TRANSFORM_NEED_MORE_INPUT _HRESULT_TYPEDEF_(0xc00d6d72)
+#endif
+
+#ifndef MFSTARTUP_NOSOCKET
+ #define MFSTARTUP_NOSOCKET 0x1
+#endif
+
+#ifdef _MSC_VER
+ #pragma comment( lib, "ksuser" )
+ #pragma comment( lib, "mfplat.lib" )
+ #pragma comment( lib, "mfuuid.lib" )
+ #pragma comment( lib, "wmcodecdspuuid" )
+#endif
//=============================================================================
, _sampleRatio( ( float ) outSampleRate / inSampleRate )
, _transformUnk( NULL )
, _transform( NULL )
- , _resamplerProps( NULL )
, _mediaType( NULL )
, _inputMediaType( NULL )
, _outputMediaType( NULL )
+
+ #ifdef __IWMResamplerProps_FWD_DEFINED__
+ , _resamplerProps( NULL )
+ #endif
{
// 1. Initialization
_transformUnk->QueryInterface( IID_PPV_ARGS( &_transform ) );
- _transformUnk->QueryInterface( IID_PPV_ARGS( &_resamplerProps ) );
- _resamplerProps->SetHalfFilterLength( 60 ); // best conversion quality
+ #ifdef __IWMResamplerProps_FWD_DEFINED__
+ _transformUnk->QueryInterface( IID_PPV_ARGS( &_resamplerProps ) );
+ _resamplerProps->SetHalfFilterLength( 60 ); // best conversion quality
+ #endif
// 3. Specify input / output format
// 4. Send stream start messages to Resampler
- _transform->ProcessMessage( MFT_MESSAGE_COMMAND_FLUSH, NULL );
- _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL );
- _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_START_OF_STREAM, NULL );
+ _transform->ProcessMessage( MFT_MESSAGE_COMMAND_FLUSH, 0 );
+ _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0 );
+ _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0 );
}
~WasapiResampler()
{
// 8. Send stream stop messages to Resampler
- _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_OF_STREAM, NULL );
- _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_STREAMING, NULL );
+ _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_OF_STREAM, 0 );
+ _transform->ProcessMessage( MFT_MESSAGE_NOTIFY_END_STREAMING, 0 );
// 9. Cleanup
SAFE_RELEASE( _transformUnk );
SAFE_RELEASE( _transform );
- SAFE_RELEASE( _resamplerProps );
SAFE_RELEASE( _mediaType );
SAFE_RELEASE( _inputMediaType );
SAFE_RELEASE( _outputMediaType );
+
+ #ifdef __IWMResamplerProps_FWD_DEFINED__
+ SAFE_RELEASE( _resamplerProps );
+ #endif
}
void Convert( char* outBuffer, const char* inBuffer, unsigned int inSampleCount, unsigned int& outSampleCount )
IUnknown* _transformUnk;
IMFTransform* _transform;
- IWMResamplerProps* _resamplerProps;
IMFMediaType* _mediaType;
IMFMediaType* _inputMediaType;
IMFMediaType* _outputMediaType;
+
+ #ifdef __IWMResamplerProps_FWD_DEFINED__
+ IWMResamplerProps* _resamplerProps;
+ #endif
};
//-----------------------------------------------------------------------------
CLSCTX_ALL, __uuidof( IMMDeviceEnumerator ),
( void** ) &deviceEnumerator_ );
- if ( FAILED( hr ) ) {
- errorText_ = "RtApiWasapi::RtApiWasapi: Unable to instantiate device enumerator";
- error( RtAudioError::DRIVER_ERROR );
- }
+ // If this runs on an old Windows, it will fail. Ignore and proceed.
+ if ( FAILED( hr ) )
+ deviceEnumerator_ = NULL;
}
//-----------------------------------------------------------------------------
IMMDeviceCollection* captureDevices = NULL;
IMMDeviceCollection* renderDevices = NULL;
+ if ( !deviceEnumerator_ )
+ return 0;
+
// Count capture devices
errorText_.clear();
HRESULT hr = deviceEnumerator_->EnumAudioEndpoints( eCapture, DEVICE_STATE_ACTIVE, &captureDevices );
}
// Convert callback buffer to user sample rate
- unsigned int deviceBufferOffset = convBufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.userFormat );
+ unsigned int deviceBufferOffset = convBufferSize * stream_.nDeviceChannels[INPUT] * formatBytes( stream_.deviceFormat[INPUT] );
unsigned int convSamples = 0;
captureResampler->Convert( stream_.deviceBuffer + deviceBufferOffset,
CoUninitialize();
+ if ( !errorText_.empty() )
+ error( errorType );
+
// update stream state
stream_.state = STREAM_STOPPED;
-
- if ( errorText_.empty() )
- return;
- else
- error( errorType );
}
//******************** End of __WINDOWS_WASAPI__ *********************//
if ( result == 0 ) {
if ( nDevices == device ) {
strcpy( name, "default" );
+ snd_ctl_close( chandle );
goto foundDevice;
}
nDevices++;
}
+ snd_ctl_close( chandle );
if ( nDevices == 0 ) {
// This should not happen because a check is made before this function is called.
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
stream_.callbackInfo.doRealtime = true;
struct sched_param param;
RtApiAlsa *object = (RtApiAlsa *) info->object;
bool *isRunning = &info->isRunning;
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
if ( info->doRealtime ) {
std::cerr << "RtAudio alsa: " <<
(sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
RtApiPulse *context = static_cast<RtApiPulse *>( cbi->object );
volatile bool *isRunning = &cbi->isRunning;
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
if (cbi->doRealtime) {
std::cerr << "RtAudio pulse: " <<
(sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
stream_.callbackInfo.doRealtime = true;
struct sched_param param;
pthread_attr_t attr;
pthread_attr_init( &attr );
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
stream_.callbackInfo.doRealtime = true;
struct sched_param param;
RtApiOss *object = (RtApiOss *) info->object;
bool *isRunning = &info->isRunning;
-#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+#ifdef SCHED_RR // Undefined with some OSes (e.g. NetBSD 1.6.x with GNU Pthread)
if (info->doRealtime) {
std::cerr << "RtAudio oss: " <<
(sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<