#if defined(__UNIX_JACK__)
apis.push_back( UNIX_JACK );
#endif
-#if defined(__LINUX_ALSA__)
- apis.push_back( LINUX_ALSA );
-#endif
#if defined(__LINUX_PULSE__)
apis.push_back( LINUX_PULSE );
#endif
+#if defined(__LINUX_ALSA__)
+ apis.push_back( LINUX_ALSA );
+#endif
#if defined(__LINUX_OSS__)
apis.push_back( LINUX_OSS );
#endif
#endif
}
+const std::string &RtAudio :: getCompiledApiName( RtAudio::Api api )
+{
+#if defined(__UNIX_JACK__)
+ if ( api == UNIX_JACK ) {
+ static std::string name( "jack" );
+ return name;
+ }
+#endif
+#if defined(__LINUX_PULSE__)
+ if ( api == LINUX_PULSE ) {
+ static std::string name( "pulse" );
+ return name;
+ }
+#endif
+#if defined(__LINUX_ALSA__)
+ if ( api == LINUX_ALSA ) {
+ static std::string name( "alsa" );
+ return name;
+ }
+#endif
+#if defined(__LINUX_OSS__)
+ if ( api == LINUX_OSS ) {
+ static std::string name( "oss" );
+ return name;
+ }
+#endif
+#if defined(__WINDOWS_ASIO__)
+ if ( api == WINDOWS_ASIO ) {
+ static std::string name( "asio" );
+ return name;
+ }
+#endif
+#if defined(__WINDOWS_WASAPI__)
+ if ( api == WINDOWS_WASAPI ) {
+ static std::string name( "wasapi" );
+ return name;
+ }
+#endif
+#if defined(__WINDOWS_DS__)
+ if ( api == WINDOWS_DS ) {
+ static std::string name( "ds" );
+ return name;
+ }
+#endif
+#if defined(__MACOSX_CORE__)
+ if ( api == MACOSX_CORE ) {
+ static std::string name( "core" );
+ return name;
+ }
+#endif
+#if defined(__RTAUDIO_DUMMY__)
+ if ( api == RTAUDIO_DUMMY ) {
+ static std::string name( "dummy" );
+ return name;
+ }
+#endif
+ static std::string name;
+ return name;
+}
+
+const std::string &RtAudio :: getCompiledApiDisplayName( RtAudio::Api api )
+{
+#if defined(__UNIX_JACK__)
+ if ( api == UNIX_JACK ) {
+ static std::string name( "JACK" );
+ return name;
+ }
+#endif
+#if defined(__LINUX_PULSE__)
+ if ( api == LINUX_PULSE ) {
+ static std::string name( "PulseAudio" );
+ return name;
+ }
+#endif
+#if defined(__LINUX_ALSA__)
+ if ( api == LINUX_ALSA ) {
+ static std::string name( "ALSA" );
+ return name;
+ }
+#endif
+#if defined(__LINUX_OSS__)
+ if ( api == LINUX_OSS ) {
+ static std::string name( "OSS" );
+ return name;
+ }
+#endif
+#if defined(__WINDOWS_ASIO__)
+ if ( api == WINDOWS_ASIO ) {
+ static std::string name( "ASIO" );
+ return name;
+ }
+#endif
+#if defined(__WINDOWS_WASAPI__)
+ if ( api == WINDOWS_WASAPI ) {
+ static std::string name( "WASAPI" );
+ return name;
+ }
+#endif
+#if defined(__WINDOWS_DS__)
+ if ( api == WINDOWS_DS ) {
+ static std::string name( "DirectSound" );
+ return name;
+ }
+#endif
+#if defined(__MACOSX_CORE__)
+ if ( api == MACOSX_CORE ) {
+ static std::string name( "Core Audio" );
+ return name;
+ }
+#endif
+#if defined(__RTAUDIO_DUMMY__)
+ if ( api == RTAUDIO_DUMMY ) {
+ static std::string name( "RtAudio Dummy" );
+ return name;
+ }
+#endif
+ static std::string name;
+ return name;
+}
+
+RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name )
+{
+ unsigned int api_number = RtAudio::UNSPECIFIED;
+ size_t nameLength = name.size();
+
+ if ( nameLength == 0 )
+ return RtAudio::UNSPECIFIED;
+
+ while ( api_number <= RtAudio::RTAUDIO_DUMMY ) {
+ const std::string &otherName =
+ getCompiledApiName((RtAudio::Api)api_number);
+
+ if ( name == otherName )
+ return (RtAudio::Api)api_number;
+
+ ++api_number;
+ }
+
+ return RtAudio::UNSPECIFIED;
+}
+
void RtAudio :: openRtApi( RtAudio::Api api )
{
if ( rtapi_ )
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)
if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
- // We previously attempted to increase the audio callback priority
- // to SCHED_RR here via the attributes. However, while no errors
- // were reported in doing so, it did not work. So, now this is
- // done in the alsaCallbackHandler function.
stream_.callbackInfo.doRealtime = true;
+ struct sched_param param;
int priority = options->priority;
int min = sched_get_priority_min( SCHED_RR );
int max = sched_get_priority_max( SCHED_RR );
if ( priority < min ) priority = min;
else if ( priority > max ) priority = max;
- stream_.callbackInfo.priority = priority;
+ param.sched_priority = priority;
+
+ // Set the policy BEFORE the priority. Otherwise it fails.
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
+ // This is definitely required. Otherwise it fails.
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedparam(&attr, ¶m);
}
+ else
+ pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
+#else
+ pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
#endif
stream_.callbackInfo.isRunning = true;
result = pthread_create( &stream_.callbackInfo.thread, &attr, alsaCallbackHandler, &stream_.callbackInfo );
pthread_attr_destroy( &attr );
if ( result ) {
- stream_.callbackInfo.isRunning = false;
- errorText_ = "RtApiAlsa::error creating callback thread!";
- goto error;
+ // Failed. Try instead with default attributes.
+ result = pthread_create( &stream_.callbackInfo.thread, NULL, alsaCallbackHandler, &stream_.callbackInfo );
+ if ( result ) {
+ stream_.callbackInfo.isRunning = false;
+ errorText_ = "RtApiAlsa::error creating callback thread!";
+ goto error;
+ }
}
}
#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
if ( info->doRealtime ) {
- pthread_t tID = pthread_self(); // ID of this thread
- sched_param prio = { info->priority }; // scheduling priority of thread
- pthread_setschedparam( tID, SCHED_RR, &prio );
+ std::cerr << "RtAudio alsa: " <<
+ (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
+ "running realtime scheduling" << std::endl;
}
#endif
CallbackInfo *cbi = static_cast<CallbackInfo *>( user );
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)
+ if (cbi->doRealtime) {
+ std::cerr << "RtAudio pulse: " <<
+ (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
+ "running realtime scheduling" << std::endl;
+ }
+#endif
+
while ( *isRunning ) {
pthread_testcancel();
context->callbackEvent();
if ( !stream_.callbackInfo.isRunning ) {
stream_.callbackInfo.object = this;
+
+ stream_.state = STREAM_STOPPED;
+ // Set the thread attributes for joinable and realtime scheduling
+ // priority (optional). The higher priority will only take affect
+ // if the program is run as root or suid. Note, under Linux
+ // processes with CAP_SYS_NICE privilege, a user can change
+ // scheduling policy and priority (thus need not be root). See
+ // POSIX "capabilities".
+ 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)
+ if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
+ stream_.callbackInfo.doRealtime = true;
+ struct sched_param param;
+ int priority = options->priority;
+ int min = sched_get_priority_min( SCHED_RR );
+ int max = sched_get_priority_max( SCHED_RR );
+ if ( priority < min ) priority = min;
+ else if ( priority > max ) priority = max;
+ param.sched_priority = priority;
+
+ // Set the policy BEFORE the priority. Otherwise it fails.
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
+ // This is definitely required. Otherwise it fails.
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedparam(&attr, ¶m);
+ }
+ else
+ pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
+#else
+ pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
+#endif
+
stream_.callbackInfo.isRunning = true;
- if ( pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo) != 0 ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread.";
- goto error;
+ int result = pthread_create( &pah->thread, &attr, pulseaudio_callback, (void *)&stream_.callbackInfo);
+ pthread_attr_destroy(&attr);
+ if(result != 0) {
+ // Failed. Try instead with default attributes.
+ result = pthread_create( &pah->thread, NULL, pulseaudio_callback, (void *)&stream_.callbackInfo);
+ if(result != 0) {
+ stream_.callbackInfo.isRunning = false;
+ errorText_ = "RtApiPulse::probeDeviceOpen: error creating thread.";
+ goto error;
+ }
}
}
- stream_.state = STREAM_STOPPED;
- return true;
+ return SUCCESS;
error:
if ( pah && stream_.callbackInfo.isRunning ) {
stream_.deviceBuffer = 0;
}
+ stream_.state = STREAM_CLOSED;
return FAILURE;
}
pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );
#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
if ( options && options->flags & RTAUDIO_SCHEDULE_REALTIME ) {
+ stream_.callbackInfo.doRealtime = true;
struct sched_param param;
int priority = options->priority;
int min = sched_get_priority_min( SCHED_RR );
if ( priority < min ) priority = min;
else if ( priority > max ) priority = max;
param.sched_priority = priority;
- pthread_attr_setschedparam( &attr, ¶m );
- pthread_attr_setschedpolicy( &attr, SCHED_RR );
+
+ // Set the policy BEFORE the priority. Otherwise it fails.
+ pthread_attr_setschedpolicy(&attr, SCHED_RR);
+ pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM);
+ // This is definitely required. Otherwise it fails.
+ pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
+ pthread_attr_setschedparam(&attr, ¶m);
}
else
pthread_attr_setschedpolicy( &attr, SCHED_OTHER );
result = pthread_create( &stream_.callbackInfo.thread, &attr, ossCallbackHandler, &stream_.callbackInfo );
pthread_attr_destroy( &attr );
if ( result ) {
- stream_.callbackInfo.isRunning = false;
- errorText_ = "RtApiOss::error creating callback thread!";
- goto error;
+ // Failed. Try instead with default attributes.
+ result = pthread_create( &stream_.callbackInfo.thread, NULL, ossCallbackHandler, &stream_.callbackInfo );
+ if ( result ) {
+ stream_.callbackInfo.isRunning = false;
+ errorText_ = "RtApiOss::error creating callback thread!";
+ goto error;
+ }
}
}
stream_.deviceBuffer = 0;
}
+ stream_.state = STREAM_CLOSED;
return FAILURE;
}
RtApiOss *object = (RtApiOss *) info->object;
bool *isRunning = &info->isRunning;
+#ifdef SCHED_RR // Undefined with some OSes (eg: NetBSD 1.6.x with GNU Pthread)
+ if (info->doRealtime) {
+ std::cerr << "RtAudio oss: " <<
+ (sched_getscheduler(0) == SCHED_RR ? "" : "_NOT_ ") <<
+ "running realtime scheduling" << std::endl;
+ }
+#endif
+
while ( *isRunning == true ) {
pthread_testcancel();
object->callbackEvent();