#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
if ( result == 0 ) {
if ( nDevices == device ) {
strcpy( name, "default" );
+ snd_ctl_close( chandle );
goto foundDevice;
}
nDevices++;
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();