$NetBSD: patch-src_hostapi_oss_pa__unix__oss.c,v 1.5 2022/06/14 14:18:45 nia Exp $ - Add 24-bit and 32-bit sample formats. - NetBSD-specific changes to make this map better to the emulation layer: We don't need to initialize the stream by writing silence, etc. PaOssStream_WaitForFrames hangs forever unless disabled, this may be a bug. - Add features needed to make portmixer work with audacity. --- src/hostapi/oss/pa_unix_oss.c.orig 2016-10-30 01:23:04.000000000 +0000 +++ src/hostapi/oss/pa_unix_oss.c @@ -65,7 +65,7 @@ #ifdef HAVE_SYS_SOUNDCARD_H # include -# ifdef __NetBSD__ +# if defined(__NetBSD__) || defined(__OpenBSD__) # define DEVICE_NAME_BASE "/dev/audio" # else # define DEVICE_NAME_BASE "/dev/dsp" @@ -417,7 +417,12 @@ static PaError QueryDirection( const cha /* Get supported sample rate closest to 44100 Hz */ if( *defaultSampleRate < 0 ) { +#ifdef __NetBSD__ + /* Less likely to require in-kernel conversion. */ + sr = 48000; +#else sr = 44100; +#endif ENSURE_( ioctl( devHandle, SNDCTL_DSP_SPEED, &sr ), paUnanticipatedHostError ); *defaultSampleRate = sr; @@ -756,7 +761,7 @@ static PaError PaOssStreamComponent_Init component->devName = deviceName; component->userChannelCount = parameters->channelCount; component->userFormat = parameters->sampleFormat; - component->latency = parameters->suggestedLatency; + component->latency = parameters->suggestedLatency > 0 ? parameters->suggestedLatency : 1; component->userInterleaved = !(parameters->sampleFormat & paNonInterleaved); if( !callbackMode && !component->userInterleaved ) @@ -938,6 +943,16 @@ static PaError Pa2OssFormat( PaSampleFor case paInt16: *ossFormat = AFMT_S16_NE; break; +#ifdef AFMT_S24_NE + case paInt24: + *ossFormat = AFMT_S24_NE; + break; +#endif +#ifdef AFMT_S32_NE + case paInt32: + *ossFormat = AFMT_S32_NE; + break; +#endif default: return paInternalError; /* This shouldn't happen */ } @@ -961,6 +976,14 @@ static PaError GetAvailableFormats( PaOs frmts |= paInt8; if( mask & AFMT_S16_NE ) frmts |= paInt16; +#ifdef AFMT_S24_NE + if( mask & AFMT_S24_NE ) + frmts |= paInt24; +#endif +#ifdef AFMT_S32_NE + if( mask & AFMT_S32_NE ) + frmts |= paInt32; +#endif else result = paSampleFormatNotSupported; @@ -1040,12 +1063,23 @@ static PaError PaOssStreamComponent_Conf PA_ENSURE( Pa2OssFormat( hostFormat, &temp ) ); nativeFormat = temp; ENSURE_( ioctl( component->fd, SNDCTL_DSP_SETFMT, &temp ), paUnanticipatedHostError ); + PA_DEBUG(("%s: Wanted %d, selected format was %d\n", __FUNCTION__, nativeFormat, temp )); PA_UNLESS( temp == nativeFormat, paInternalError ); /* try to set the number of channels */ ENSURE_( ioctl( component->fd, SNDCTL_DSP_CHANNELS, &chans ), paSampleFormatNotSupported ); /* XXX: Should be paInvalidChannelCount? */ +#ifndef __NetBSD__ /* It's possible that the minimum number of host channels is greater than what the user requested */ + /* On NetBSD it's possible that the number is less than what the user requested, e.g. if the device is a mono mic */ PA_UNLESS( chans >= component->userChannelCount, paInvalidChannelCount ); +#endif + +#ifdef __NetBSD__ + /* Make the sample rate conform to hard kernel limits */ + /* This can likely be removed after NetBSD 10... SNDCTL_DSP_SPEED should never return an error code. */ + sr = sr > 192000 ? 192000 : sr; + sr = sr < 1000 ? 1000 : sr; +#endif /* try to set the sample rate */ ENSURE_( ioctl( component->fd, SNDCTL_DSP_SPEED, &sr ), paInvalidSampleRate ); @@ -1477,6 +1511,7 @@ static PaError PaOssStream_Prepare( PaOs size_t bufSz = PaOssStreamComponent_BufferSize( stream->playback ); memset( stream->playback->buffer, 0, bufSz ); +#ifndef __NetBSD__ /* Looks like we have to turn off blocking before we try this, but if we don't fill the buffer * OSS will complain. */ PA_ENSURE( ModifyBlocking( stream->playback->fd, 0 ) ); @@ -1486,6 +1521,7 @@ static PaError PaOssStream_Prepare( PaOs break; } PA_ENSURE( ModifyBlocking( stream->playback->fd, 1 ) ); +#endif } if( stream->sharedDevice ) @@ -1652,6 +1688,7 @@ static void *PaOSS_AudioThreadProc( void callbackResult = paComplete; } +#ifndef __NetBSD__ /* Aspect StreamState: Because of the messy OSS scheme we can't explicitly trigger device start unless * the stream has been recently started, we will have to go right ahead and read/write in blocking * fashion to trigger operation. Therefore we begin with processing one host buffer before we switch @@ -1667,6 +1704,9 @@ static void *PaOSS_AudioThreadProc( void { framesAvail = stream->framesPerHostBuffer; } +#else + framesAvail = stream->framesPerHostBuffer; +#endif while( framesAvail > 0 ) { @@ -1749,11 +1789,13 @@ static void *PaOSS_AudioThreadProc( void if( initiateProcessing || !triggered ) { +#ifndef __NetBSD__ /* Non-blocking */ if( stream->capture ) PA_ENSURE( ModifyBlocking( stream->capture->fd, 0 ) ); if( stream->playback && !stream->sharedDevice ) PA_ENSURE( ModifyBlocking( stream->playback->fd, 0 ) ); +#endif initiateProcessing = 0; sem_post( &stream->semaphore ); @@ -2043,3 +2085,26 @@ error: #endif } +const char *PaOSS_GetStreamInputDevice( PaStream* s ) +{ + PaOssStream *stream = (PaOssStream*)s; + + if( stream->capture ) + { + return stream->capture->devName; + } + + return NULL; +} + +const char *PaOSS_GetStreamOutputDevice( PaStream* s ) +{ + PaOssStream *stream = (PaOssStream*)s; + + if( stream->playback ) + { + return stream->playback->devName; + } + + return NULL; +}