diff options
| author | Gary Scavone <gary@music.mcgill.ca> | 2012-12-10 20:30:46 +0000 |
|---|---|---|
| committer | Stephen Sinclair <sinclair@music.mcgill.ca> | 2013-10-11 01:38:32 +0200 |
| commit | bee81ff356bbec279facb50dab5e6069c6475fcc (patch) | |
| tree | 616131a39345439599b0db44d4af82e86ed14e6e /RtAudio.cpp | |
| parent | 6befb5faa6fa95ca63ec62e240263f79c79432e2 (diff) | |
Various updates for pulseaudio API and default ALSA device enumeration (gs).
Diffstat (limited to 'RtAudio.cpp')
| -rw-r--r-- | RtAudio.cpp | 158 |
1 files changed, 106 insertions, 52 deletions
diff --git a/RtAudio.cpp b/RtAudio.cpp index 68dabff..70414a6 100644 --- a/RtAudio.cpp +++ b/RtAudio.cpp @@ -5160,6 +5160,12 @@ unsigned int RtApiAlsa :: getDeviceCount( void ) snd_card_next( &card );
}
+ result = snd_ctl_open( &handle, "default", 0 );
+ if (result == 0) {
+ nDevices++;
+ snd_ctl_close( handle );
+ }
+
return nDevices;
}
@@ -5206,6 +5212,15 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) snd_card_next( &card );
}
+ result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK );
+ if ( result == 0 ) {
+ if ( nDevices == device ) {
+ strcpy( name, "default" );
+ goto foundDevice;
+ }
+ nDevices++;
+ }
+
if ( nDevices == 0 ) {
errorText_ = "RtApiAlsa::getDeviceInfo: no devices found!";
error( RtError::INVALID_USE );
@@ -5239,16 +5254,18 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) snd_pcm_hw_params_t *params;
snd_pcm_hw_params_alloca( ¶ms );
- // First try for playback
+ // First try for playback unless default device (which has subdev -1)
stream = SND_PCM_STREAM_PLAYBACK;
- snd_pcm_info_set_device( pcminfo, subdevice );
- snd_pcm_info_set_subdevice( pcminfo, 0 );
snd_pcm_info_set_stream( pcminfo, stream );
+ if ( subdevice != -1 ) {
+ snd_pcm_info_set_device( pcminfo, subdevice );
+ snd_pcm_info_set_subdevice( pcminfo, 0 );
- result = snd_ctl_pcm_info( chandle, pcminfo );
- if ( result < 0 ) {
- // Device probably doesn't support playback.
- goto captureProbe;
+ result = snd_ctl_pcm_info( chandle, pcminfo );
+ if ( result < 0 ) {
+ // Device probably doesn't support playback.
+ goto captureProbe;
+ }
}
result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK );
@@ -5283,16 +5300,18 @@ RtAudio::DeviceInfo RtApiAlsa :: getDeviceInfo( unsigned int device ) snd_pcm_close( phandle );
captureProbe:
- // Now try for capture
stream = SND_PCM_STREAM_CAPTURE;
snd_pcm_info_set_stream( pcminfo, stream );
- result = snd_ctl_pcm_info( chandle, pcminfo );
- snd_ctl_close( chandle );
- if ( result < 0 ) {
- // Device probably doesn't support capture.
- if ( info.outputChannels == 0 ) return info;
- goto probeParameters;
+ // Now try for capture unless default device (with subdev = -1)
+ if ( subdevice != -1 ) {
+ result = snd_ctl_pcm_info( chandle, pcminfo );
+ snd_ctl_close( chandle );
+ if ( result < 0 ) {
+ // Device probably doesn't support capture.
+ if ( info.outputChannels == 0 ) return info;
+ goto probeParameters;
+ }
}
result = snd_pcm_open( &phandle, name, stream, openMode | SND_PCM_NONBLOCK);
@@ -5483,6 +5502,15 @@ bool RtApiAlsa :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne snd_card_next( &card );
}
+ result = snd_ctl_open( &chandle, "default", SND_CTL_NONBLOCK );
+ if ( result == 0 ) {
+ if ( nDevices == device ) {
+ strcpy( name, "default" );
+ goto foundDevice;
+ }
+ nDevices++;
+ }
+
if ( nDevices == 0 ) {
// This should not happen because a check is made before this function is called.
errorText_ = "RtApiAlsa::probeDeviceOpen: no devices found!";
@@ -6474,7 +6502,7 @@ void RtApiPulse::callbackEvent( void ) RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback;
double streamTime = getStreamTime();
RtAudioStreamStatus status = 0;
- int doStopStream = callback( stream_.userBuffer[0], stream_.userBuffer[1],
+ int doStopStream = callback( stream_.userBuffer[OUTPUT], stream_.userBuffer[INPUT],
stream_.bufferSize, streamTime, status,
stream_.callbackInfo.userData );
@@ -6484,50 +6512,52 @@ void RtApiPulse::callbackEvent( void ) }
MUTEX_LOCK( &stream_.mutex );
+ void *pulse_in = stream_.doConvertBuffer[INPUT] ? stream_.deviceBuffer : stream_.userBuffer[INPUT];
+ void *pulse_out = stream_.doConvertBuffer[OUTPUT] ? stream_.deviceBuffer : stream_.userBuffer[OUTPUT];
if ( stream_.state != STREAM_RUNNING )
goto unlock;
int pa_error;
size_t bytes;
- switch ( stream_.mode ) {
- case INPUT:
- bytes = stream_.nUserChannels[1] * stream_.bufferSize * formatBytes( stream_.userFormat );
- if ( pa_simple_read( pah->s_rec, stream_.userBuffer[1], bytes, &pa_error ) < 0 ) {
- errorStream_ << "RtApiPulse::callbackEvent: audio read error, " <<
- pa_strerror( pa_error ) << ".";
- errorText_ = errorStream_.str();
- error( RtError::WARNING );
- }
- break;
- case OUTPUT:
- bytes = stream_.nUserChannels[0] * stream_.bufferSize * formatBytes( stream_.userFormat );
- if ( pa_simple_write( pah->s_play, stream_.userBuffer[0], bytes, &pa_error ) < 0 ) {
+ if (stream_.mode == OUTPUT || stream_.mode == DUPLEX ) {
+ if ( stream_.doConvertBuffer[OUTPUT] ) {
+ convertBuffer( stream_.deviceBuffer,
+ stream_.userBuffer[OUTPUT],
+ stream_.convertInfo[OUTPUT] );
+ bytes = stream_.nDeviceChannels[OUTPUT] * stream_.bufferSize *
+ formatBytes( stream_.deviceFormat[OUTPUT] );
+ } else
+ bytes = stream_.nUserChannels[OUTPUT] * stream_.bufferSize *
+ formatBytes( stream_.userFormat );
+
+ if ( pa_simple_write( pah->s_play, pulse_out, bytes, &pa_error ) < 0 ) {
errorStream_ << "RtApiPulse::callbackEvent: audio write error, " <<
pa_strerror( pa_error ) << ".";
errorText_ = errorStream_.str();
error( RtError::WARNING );
}
- break;
- case DUPLEX:
- bytes = stream_.nUserChannels[1] * stream_.bufferSize * formatBytes( stream_.userFormat );
- if ( pa_simple_read( pah->s_rec, stream_.userBuffer[1], bytes, &pa_error ) < 0 ) {
+ }
+
+ if ( stream_.mode == INPUT || stream_.mode == DUPLEX) {
+ if ( stream_.doConvertBuffer[INPUT] )
+ bytes = stream_.nDeviceChannels[INPUT] * stream_.bufferSize *
+ formatBytes( stream_.deviceFormat[INPUT] );
+ else
+ bytes = stream_.nUserChannels[INPUT] * stream_.bufferSize *
+ formatBytes( stream_.userFormat );
+
+ if ( pa_simple_read( pah->s_rec, pulse_in, bytes, &pa_error ) < 0 ) {
errorStream_ << "RtApiPulse::callbackEvent: audio read error, " <<
pa_strerror( pa_error ) << ".";
errorText_ = errorStream_.str();
error( RtError::WARNING );
}
- bytes = stream_.nUserChannels[0] * stream_.bufferSize * formatBytes( stream_.userFormat );
- if ( pa_simple_write( pah->s_play, stream_.userBuffer[0], bytes, &pa_error ) < 0) {
- errorStream_ << "RtApiPulse::callbackEvent: audio write error, " <<
- pa_strerror( pa_error ) << ".";
- errorText_ = errorStream_.str();
- error( RtError::WARNING );
+ if ( stream_.doConvertBuffer[INPUT] ) {
+ convertBuffer( stream_.userBuffer[INPUT],
+ stream_.deviceBuffer,
+ stream_.convertInfo[INPUT] );
}
- break;
- default:
- // ERROR
- break;
}
unlock:
@@ -6676,20 +6706,16 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode, return false;
}
- if ( options && ( options->flags & RTAUDIO_NONINTERLEAVED ) ) {
- errorText_ = "RtApiPulse::probeDeviceOpen: only interleaved audio data supported.";
- return false;
- }
-
- stream_.userInterleaved = true;
- stream_.nBuffers = 1;
-
+ // Set interleaving parameters.
+ if ( options && options->flags & RTAUDIO_NONINTERLEAVED ) stream_.userInterleaved = false;
+ else stream_.userInterleaved = true;
stream_.deviceInterleaved[mode] = true;
+ stream_.nBuffers = 1;
stream_.doByteSwap[mode] = false;
- stream_.doConvertBuffer[mode] = false;
+ stream_.doConvertBuffer[mode] = channels > 1 && !stream_.userInterleaved;
stream_.deviceFormat[mode] = stream_.userFormat;
stream_.nUserChannels[mode] = channels;
- stream_.nDeviceChannels[mode] = channels;
+ stream_.nDeviceChannels[mode] = channels + firstChannel;
stream_.channelOffset[mode] = 0;
// Allocate necessary internal buffers.
@@ -6701,6 +6727,34 @@ bool RtApiPulse::probeDeviceOpen( unsigned int device, StreamMode mode, }
stream_.bufferSize = *bufferSize;
+ if ( stream_.doConvertBuffer[mode] ) {
+
+ bool makeBuffer = true;
+ bufferBytes = stream_.nDeviceChannels[mode] * formatBytes( stream_.deviceFormat[mode] );
+ if ( mode == INPUT ) {
+ if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) {
+ unsigned long bytesOut = stream_.nDeviceChannels[0] * formatBytes( stream_.deviceFormat[0] );
+ if ( bufferBytes <= bytesOut ) makeBuffer = false;
+ }
+ }
+
+ if ( makeBuffer ) {
+ bufferBytes *= *bufferSize;
+ if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
+ stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
+ if ( stream_.deviceBuffer == NULL ) {
+ errorText_ = "RtApiPulse::probeDeviceOpen: error allocating device buffer memory.";
+ goto error;
+ }
+ }
+ }
+
+ stream_.device[mode] = device;
+ stream_.state = STREAM_STOPPED;
+
+ // Setup the buffer conversion information structure.
+ if ( stream_.doConvertBuffer[mode] ) setConvertInfo( mode, firstChannel );
+
if ( !stream_.apiHandle ) {
PulseAudioHandle *pah = new PulseAudioHandle;
if ( !pah ) {
|
