//\r
// *************************************************** //\r
\r
+std::string RtAudio :: getVersion( void ) throw()\r
+{\r
+ return std::string( RTAUDIO_VERSION );\r
+}\r
+\r
void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) throw()\r
{\r
apis.clear();\r
// definition __RTAUDIO_DUMMY__ is automatically defined if no\r
// API-specific definitions are passed to the compiler. But just in\r
// case something weird happens, we'll print out an error message.\r
- std::cerr << "\nRtAudio: no compiled API support found ... critical error!!\n\n";\r
+ std::string errorText = "\nRtAudio: no compiled API support found ... critical error!!\n\n";\r
+ throw( RtAudioError( errorText, RtAudioError::UNSPECIFIED ) );\r
}\r
\r
RtAudio :: ~RtAudio() throw()\r
stream_.userBuffer[1] = 0;\r
MUTEX_INITIALIZE( &stream_.mutex );\r
showWarnings_ = true;\r
- firstErrorOccurred = false;\r
+ firstErrorOccurred_ = false;\r
}\r
\r
RtApi :: ~RtApi()\r
return info;\r
}\r
\r
- Float64 minimumRate = 100000000.0, maximumRate = 0.0;\r
+ // The sample rate reporting mechanism is a bit of a mystery. It\r
+ // seems that it can either return individual rates or a range of\r
+ // rates. I assume that if the min / max range values are the same,\r
+ // then that represents a single supported rate and if the min / max\r
+ // range values are different, the device supports an arbitrary\r
+ // range of values (though there might be multiple ranges, so we'll\r
+ // use the most conservative range).\r
+ Float64 minimumRate = 1.0, maximumRate = 10000000000.0;\r
+ bool haveValueRange = false;\r
+ info.sampleRates.clear();\r
for ( UInt32 i=0; i<nRanges; i++ ) {\r
- if ( rangeList[i].mMinimum < minimumRate ) minimumRate = rangeList[i].mMinimum;\r
- if ( rangeList[i].mMaximum > maximumRate ) maximumRate = rangeList[i].mMaximum;\r
+ if ( rangeList[i].mMinimum == rangeList[i].mMaximum )\r
+ info.sampleRates.push_back( (unsigned int) rangeList[i].mMinimum );\r
+ else {\r
+ haveValueRange = true;\r
+ if ( rangeList[i].mMinimum > minimumRate ) minimumRate = rangeList[i].mMinimum;\r
+ if ( rangeList[i].mMaximum < maximumRate ) maximumRate = rangeList[i].mMaximum;\r
+ }\r
}\r
\r
- info.sampleRates.clear();\r
- for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {\r
- if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate )\r
- info.sampleRates.push_back( SAMPLE_RATES[k] );\r
+ if ( haveValueRange ) {\r
+ for ( unsigned int k=0; k<MAX_SAMPLE_RATES; k++ ) {\r
+ if ( SAMPLE_RATES[k] >= (unsigned int) minimumRate && SAMPLE_RATES[k] <= (unsigned int) maximumRate )\r
+ info.sampleRates.push_back( SAMPLE_RATES[k] );\r
+ }\r
}\r
\r
+ // Sort and remove any redundant values\r
+ std::sort( info.sampleRates.begin(), info.sampleRates.end() );\r
+ info.sampleRates.erase( unique( info.sampleRates.begin(), info.sampleRates.end() ), info.sampleRates.end() );\r
+\r
if ( info.sampleRates.size() == 0 ) {\r
errorStream_ << "RtApiCore::probeDeviceInfo: No supported sample rates found for device (" << device << ").";\r
errorText_ = errorStream_.str();\r
const AudioObjectPropertyAddress /*properties*/[],\r
void* ratePointer )\r
{\r
-\r
Float64 *rate = (Float64 *) ratePointer;\r
UInt32 dataSize = sizeof( Float64 );\r
AudioObjectPropertyAddress property = { kAudioDevicePropertyNominalSampleRate,\r
\r
result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, bufferList );\r
if (result != noErr || dataSize == 0) {\r
+ free( bufferList );\r
errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting stream configuration for device (" << device << ").";\r
errorText_ = errorStream_.str();\r
return FAILURE;\r
dataSize = sizeof( Float64 );\r
property.mSelector = kAudioDevicePropertyNominalSampleRate;\r
result = AudioObjectGetPropertyData( id, &property, 0, NULL, &dataSize, &nominalRate );\r
-\r
if ( result != noErr ) {\r
errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") getting current sample rate.";\r
errorText_ = errorStream_.str();\r
\r
nominalRate = (Float64) sampleRate;\r
result = AudioObjectSetPropertyData( id, &property, 0, NULL, dataSize, &nominalRate );\r
-\r
if ( result != noErr ) {\r
+ AudioObjectRemovePropertyListener( id, &tmp, rateListener, (void *) &reportedRate );\r
errorStream_ << "RtApiCore::probeDeviceOpen: system error (" << getErrorCode( result ) << ") setting sample rate for device (" << device << ").";\r
errorText_ = errorStream_.str();\r
return FAILURE;\r
if ( errorCallback ) {\r
// abortStream() can generate new error messages. Ignore them. Just keep original one.\r
\r
- if ( firstErrorOccurred )\r
+ if ( firstErrorOccurred_ )\r
return;\r
\r
- firstErrorOccurred = true;\r
+ firstErrorOccurred_ = true;\r
const std::string errorMessage = errorText_;\r
\r
if ( type != RtAudioError::WARNING && stream_.state != STREAM_STOPPED) {\r
}\r
\r
errorCallback( type, errorMessage );\r
- firstErrorOccurred = false;\r
+ firstErrorOccurred_ = false;\r
return;\r
}\r
\r