diff options
Diffstat (limited to 'pd/portaudio_v18/pa_unix_oss/pa_unix_oss.c')
-rw-r--r-- | pd/portaudio_v18/pa_unix_oss/pa_unix_oss.c | 385 |
1 files changed, 0 insertions, 385 deletions
diff --git a/pd/portaudio_v18/pa_unix_oss/pa_unix_oss.c b/pd/portaudio_v18/pa_unix_oss/pa_unix_oss.c deleted file mode 100644 index 386cd75b..00000000 --- a/pd/portaudio_v18/pa_unix_oss/pa_unix_oss.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.portaudio.com - * Linux OSS Implementation by douglas repetto and Phil Burk - * - * Copyright (c) 1999-2000 Phil Burk - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * Any person wishing to distribute modifications to the Software is - * requested to send the modifications to the original developer so that - * they can be incorporated into the canonical version. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -/* Modification history: - 20020621: pa_unix_oss.c split into pa_unix.c, pa_unix.h, pa_unix_oss.c by - Augustus Saunders. See pa_unix.c for previous history. Pa_FlushStream - added by Augustus Saunders for Solaris compatibility. - PLB20021018 - Fill device info table with actual sample rates instead of wished for rates. - - Allow stream to open if sample rate within 10% of desired rate. - 20030630 - Thomas Richter - eliminated unused variable warnings. -*/ - -#include "pa_unix.h" - -#ifdef __linux__ -#include <linux/soundcard.h> -#else -#include <machine/soundcard.h> /* JH20010905 */ -#endif - - -#ifndef AFMT_S16_NE -#define AFMT_S16_NE Get_AFMT_S16_NE() -/********************************************************************* - * Some versions of OSS do not define AFMT_S16_NE. So check CPU. - * PowerPC is Big Endian. X86 is Little Endian. - */ -int Get_AFMT_S16_NE( void ) -{ - long testData = 1; - char *ptr = (char *) &testData; - int isLittle = ( *ptr == 1 ); /* Does address point to least significant byte? */ - return isLittle ? AFMT_S16_LE : AFMT_S16_BE; -} -#endif /* AFMT_S16_NE */ - - -/********************************************************************* - * Try to open the named device. - * If it opens, try to set various rates and formats and fill in - * the device info structure. - */ -PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad ) -{ - int result = paHostError; - int tempDevHandle; - int numChannels, maxNumChannels; - int format; - int numSampleRates; - int sampleRate; - int numRatesToTry; - int lastRate; - int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000}; - int i; - - /* douglas: - we have to do this querying in a slightly different order. apparently - some sound cards will give you different info based on their settings. - e.g. a card might give you stereo at 22kHz but only mono at 44kHz. - the correct order for OSS is: format, channels, sample rate - - */ - if ( (tempDevHandle = open(deviceName,O_WRONLY|O_NONBLOCK)) == -1 ) - { - DBUG(("Pa_QueryDevice: could not open %s\n", deviceName )); - return paHostError; - } - - /* Ask OSS what formats are supported by the hardware. */ - pad->pad_Info.nativeSampleFormats = 0; - - if (ioctl(tempDevHandle, SNDCTL_DSP_GETFMTS, &format) == -1) - { - ERR_RPT(("Pa_QueryDevice: could not get format info\n" )); - goto error; - } - if( format & AFMT_U8 ) pad->pad_Info.nativeSampleFormats |= paUInt8; - if( format & AFMT_S16_NE ) pad->pad_Info.nativeSampleFormats |= paInt16; - - /* Negotiate for the maximum number of channels for this device. PLB20010927 - * Consider up to 16 as the upper number of channels. - * Variable numChannels should contain the actual upper limit after the call. - * Thanks to John Lazzaro and Heiko Purnhagen for suggestions. - */ - maxNumChannels = 0; - for( numChannels = 1; numChannels <= 16; numChannels++ ) - { - int temp = numChannels; - DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels )) - if(ioctl(tempDevHandle, SNDCTL_DSP_CHANNELS, &temp) < 0 ) - { - /* ioctl() failed so bail out if we already have stereo */ - if( numChannels > 2 ) break; - } - else - { - /* ioctl() worked but bail out if it does not support numChannels. - * We don't want to leave gaps in the numChannels supported. - */ - if( (numChannels > 2) && (temp != numChannels) ) break; - DBUG(("Pa_QueryDevice: temp = %d\n", temp )) - if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */ - } - } - - /* The above negotiation may fail for an old driver so try this older technique. */ - if( maxNumChannels < 1 ) - { - int stereo = 1; - if(ioctl(tempDevHandle, SNDCTL_DSP_STEREO, &stereo) < 0) - { - maxNumChannels = 1; - } - else - { - maxNumChannels = (stereo) ? 2 : 1; - } - DBUG(("Pa_QueryDevice: use SNDCTL_DSP_STEREO, maxNumChannels = %d\n", maxNumChannels )) - } - - pad->pad_Info.maxOutputChannels = maxNumChannels; - DBUG(("Pa_QueryDevice: maxNumChannels = %d\n", maxNumChannels)) - - /* During channel negotiation, the last ioctl() may have failed. This can - * also cause sample rate negotiation to fail. Hence the following, to return - * to a supported number of channels. SG20011005 */ - { - int temp = maxNumChannels; - if( temp > 2 ) temp = 2; /* use most reasonable default value */ - ioctl(tempDevHandle, SNDCTL_DSP_CHANNELS, &temp); - } - - /* FIXME - for now, assume maxInputChannels = maxOutputChannels. - * Eventually do separate queries for O_WRONLY and O_RDONLY - */ - pad->pad_Info.maxInputChannels = pad->pad_Info.maxOutputChannels; - - DBUG(("Pa_QueryDevice: maxInputChannels = %d\n", - pad->pad_Info.maxInputChannels)) - - - /* Determine available sample rates by trying each one and seeing result. - * OSS often supports funky rates such as 44188 instead of 44100! - */ - numSampleRates = 0; - lastRate = 0; - numRatesToTry = sizeof(ratesToTry)/sizeof(int); - for (i = 0; i < numRatesToTry; i++) - { - sampleRate = ratesToTry[i]; - - if (ioctl(tempDevHandle, SNDCTL_DSP_SPEED, &sampleRate) >= 0 ) /* PLB20010817 */ - { - /* Use whatever rate OSS tells us. PLB20021018 */ - if (sampleRate != lastRate) - { - DBUG(("Pa_QueryDevice: adding sample rate: %d\n", sampleRate)) - pad->pad_SampleRates[numSampleRates] = (float)sampleRate; - numSampleRates++; - lastRate = sampleRate; - } - else - { - DBUG(("Pa_QueryDevice: dang - got sample rate %d again!\n", sampleRate)) - } - } - } - - DBUG(("Pa_QueryDevice: final numSampleRates = %d\n", numSampleRates)) - if (numSampleRates==0) /* HP20010922 */ - { - /* Desparate attempt to keep running even though no good rates found! */ - ERR_RPT(("Pa_QueryDevice: no supported sample rate (or SNDCTL_DSP_SPEED ioctl call failed). Force 44100 Hz\n" )); - pad->pad_SampleRates[numSampleRates++] = 44100; - } - - pad->pad_Info.numSampleRates = numSampleRates; - pad->pad_Info.sampleRates = pad->pad_SampleRates; /* use pointer to embedded array */ - - pad->pad_Info.name = deviceName; - - result = paNoError; - -error: - /* We MUST close the handle here or we won't be able to reopen it later!!! */ - close(tempDevHandle); - - return result; -} - -/*******************************************************************************************/ -PaError Pa_SetupDeviceFormat( int devHandle, int numChannels, int sampleRate ) -{ - PaError result = paNoError; - int tmp; - - /* Set format, channels, and rate in this order to keep OSS happy. */ - /* Set data format. FIXME - handle more native formats. */ - tmp = AFMT_S16_NE; - if( ioctl(devHandle,SNDCTL_DSP_SETFMT,&tmp) == -1) - { - ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_SETFMT\n" )); - return paHostError; - } - if( tmp != AFMT_S16_NE ) - { - ERR_RPT(("Pa_SetupDeviceFormat: HW does not support AFMT_S16_NE\n" )); - return paHostError; - } - - - /* Set number of channels. */ - tmp = numChannels; - if (ioctl(devHandle, SNDCTL_DSP_CHANNELS, &numChannels) == -1) - { - ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_CHANNELS\n" )); - return paHostError; - } - if( tmp != numChannels) - { - ERR_RPT(("Pa_SetupDeviceFormat: HW does not support %d channels\n", numChannels )); - return paHostError; - } - - /* Set playing frequency. */ - tmp = sampleRate; - if( ioctl(devHandle,SNDCTL_DSP_SPEED,&tmp) == -1) - { - ERR_RPT(("Pa_SetupDeviceFormat: could not SNDCTL_DSP_SPEED\n" )); - return paHostError; - } - else if( tmp != sampleRate ) - { - int percentError = abs( (100 * (sampleRate - tmp)) / sampleRate ); - PRINT(("Pa_SetupDeviceFormat: warning - requested sample rate = %d Hz - closest = %d\n", - sampleRate, tmp )); - /* Allow sample rate within 10% off of requested rate. PLB20021018 - * Sometimes OSS uses a funky rate like 44188 instead of 44100. - */ - if( percentError > 10 ) - { - ERR_RPT(("Pa_SetupDeviceFormat: HW does not support %d Hz sample rate\n",sampleRate )); - return paHostError; - } - } - - return result; -} - -PaError Pa_SetupOutputDeviceFormat( int devHandle, int numChannels, int sampleRate ) -{ - return Pa_SetupDeviceFormat(devHandle, numChannels, sampleRate); -} - -PaError Pa_SetupInputDeviceFormat( int devHandle, int numChannels, int sampleRate ) -{ - return Pa_SetupDeviceFormat(devHandle, numChannels, sampleRate); -} - - -/******************************************************************************************* -** Set number of fragments and size of fragments to achieve desired latency. -*/ - -static int CalcHigherLogTwo( int n ) -{ - int log2 = 0; - while( (1<<log2) < n ) log2++; - return log2; -} - -void Pa_SetLatency( int devHandle, int numBuffers, int framesPerBuffer, int channelsPerFrame ) -{ - int tmp; - int bufferSize, powerOfTwo; - - /* Increase size of buffers and reduce number of buffers to reduce latency inside driver. */ - while( numBuffers > 8 ) - { - numBuffers = (numBuffers + 1) >> 1; - framesPerBuffer = framesPerBuffer << 1; - } - - /* calculate size of buffers in bytes */ - bufferSize = framesPerBuffer * channelsPerFrame * sizeof(short); /* FIXME - other sizes? */ - - /* Calculate next largest power of two */ - powerOfTwo = CalcHigherLogTwo( bufferSize ); - DBUG(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d, powerOfTwo = %d\n", - numBuffers, framesPerBuffer, powerOfTwo )); - - /* Encode info into a single int */ - tmp=(numBuffers<<16) + powerOfTwo; - - if(ioctl(devHandle,SNDCTL_DSP_SETFRAGMENT,&tmp) == -1) - { - ERR_RPT(("Pa_SetLatency: could not SNDCTL_DSP_SETFRAGMENT\n" )); - /* Don't return an error. Best to just continue and hope for the best. */ - ERR_RPT(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d, powerOfTwo = %d\n", - numBuffers, framesPerBuffer, powerOfTwo )); - } -} - -/***********************************************************************/ -PaTimestamp Pa_StreamTime( PortAudioStream *stream ) -{ - internalPortAudioStream *past = (internalPortAudioStream *) stream; - PaHostSoundControl *pahsc; - - count_info info; - int delta; - - if( past == NULL ) return paBadStreamPtr; - - pahsc = (PaHostSoundControl *) past->past_DeviceData; - - if( pahsc->pahsc_NativeOutputBuffer ) - { - ioctl(pahsc->pahsc_OutputHandle, SNDCTL_DSP_GETOPTR, &info); - delta = (info.bytes - pahsc->pahsc_LastPosPtr) & 0x000FFFFF; - return (pahsc->pahsc_LastStreamBytes + delta) / (past->past_NumOutputChannels * sizeof(short)); - } - else - { - ioctl(pahsc->pahsc_InputHandle, SNDCTL_DSP_GETIPTR, &info); - delta = (info.bytes - pahsc->pahsc_LastPosPtr) & 0x000FFFFF; - return (pahsc->pahsc_LastStreamBytes + delta) / (past->past_NumInputChannels * sizeof(short)); - } -} - -void Pa_UpdateStreamTime(PaHostSoundControl *pahsc) -{ - count_info info; - int delta; - - /* Update current stream time (using a double so that - we don't wrap around like info.bytes does) */ - if( pahsc->pahsc_NativeOutputBuffer ) - { - ioctl(pahsc->pahsc_OutputHandle, SNDCTL_DSP_GETOPTR, &info); - } - else - { - ioctl(pahsc->pahsc_InputHandle, SNDCTL_DSP_GETIPTR, &info); - } - delta = (info.bytes - pahsc->pahsc_LastPosPtr) & 0x000FFFFF; - pahsc->pahsc_LastStreamBytes += delta; - pahsc->pahsc_LastPosPtr = info.bytes; -} - -PaError Pa_FlushStream(int devHandle) -{ - /* AS: This doesn't do anything under OSS; it was added for Solaris.*/ - devHandle = devHandle; /* unused */ - return paNoError; -} |