📄 pa_unix_oss.c
字号:
DBUG(("PaOSS BuildDeviceList: trying device %s\n", deviceName )); testResult = PaOSS_QueryDevice(deviceName, &deviceInfo); DBUG(("PaOSS BuildDeviceList: PaOSS_QueryDevice returned %d\n", testResult )); if (testResult == paNoError) { DBUG(("PaOSS BuildDeviceList: Adding device %s to list\n", deviceName)); deviceInfo.hostApi = ossApi->hostApiIndex; deviceInfo.name = PaUtil_GroupAllocateMemory( ossApi->allocations, strlen(deviceName)+1); strcpy((char *)deviceInfo.name, deviceName); entry = (PaOSS_DeviceList *)PaUtil_AllocateMemory(sizeof(PaOSS_DeviceList)); entry->deviceInfo = (PaDeviceInfo*)PaUtil_GroupAllocateMemory( ossApi->allocations, sizeof(PaDeviceInfo) ); entry->next = NULL; memcpy(entry->deviceInfo, &deviceInfo, sizeof(PaDeviceInfo)); if (tail) tail->next = entry; else { head = entry; tail = entry; } } } /* Make an array of PaDeviceInfo pointers out of the linked list */ numDevices = 0; entry = head; while(entry) { numDevices++; entry = entry->next; } DBUG(("PaOSS BuildDeviceList: Total number of devices found: %d\n", numDevices)); commonApi->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( ossApi->allocations, sizeof(PaDeviceInfo*) *numDevices ); entry = head; i = 0; while(entry) { commonApi->deviceInfos[i] = entry->deviceInfo; i++; entry = entry->next; } commonApi->info.deviceCount = numDevices; commonApi->info.defaultInputDevice = 0; commonApi->info.defaultOutputDevice = 0; return paNoError;}static void Terminate( struct PaUtilHostApiRepresentation *hostApi ){ PaOSSHostApiRepresentation *ossHostApi = (PaOSSHostApiRepresentation*)hostApi; if( ossHostApi->allocations ) { PaUtil_FreeAllAllocations( ossHostApi->allocations ); PaUtil_DestroyAllocationGroup( ossHostApi->allocations ); } PaUtil_FreeMemory( ossHostApi );}static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate ){ PaDeviceIndex device; PaDeviceInfo *deviceInfo; PaError result = paNoError; char *deviceName; int inputChannelCount, outputChannelCount; int tempDevHandle = 0; int flags; PaSampleFormat inputSampleFormat, outputSampleFormat; if( inputParameters ) { inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that input device can support inputChannelCount */ if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels ) return paInvalidChannelCount; /* validate inputStreamInfo */ if( inputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ } else { inputChannelCount = 0; } if( outputParameters ) { outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that output device can support inputChannelCount */ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels ) return paInvalidChannelCount; /* validate outputStreamInfo */ if( outputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ } else { outputChannelCount = 0; } if (inputChannelCount == 0 && outputChannelCount == 0) return paInvalidChannelCount; /* if full duplex, make sure that they're the same device */ if (inputChannelCount > 0 && outputChannelCount > 0 && inputParameters->device != outputParameters->device) return paInvalidDevice; /* if full duplex, also make sure that they're the same number of channels */ if (inputChannelCount > 0 && outputChannelCount > 0 && inputChannelCount != outputChannelCount) return paInvalidChannelCount; /* open the device so we can do more tests */ if (inputChannelCount > 0) { result = PaUtil_DeviceIndexToHostApiDeviceIndex(&device, inputParameters->device, hostApi); if (result != paNoError) return result; } else { result = PaUtil_DeviceIndexToHostApiDeviceIndex(&device, outputParameters->device, hostApi); if (result != paNoError) return result; } deviceInfo = hostApi->deviceInfos[device]; deviceName = (char *)deviceInfo->name; flags = O_NONBLOCK; if (inputChannelCount > 0 && outputChannelCount > 0) flags |= O_RDWR; else if (inputChannelCount > 0) flags |= O_RDONLY; else flags |= O_WRONLY; if ( (tempDevHandle = open(deviceInfo->name, flags)) == -1 ) { DBUG(("PaOSS IsFormatSupported: could not open %s\n", deviceName )); return paDeviceUnavailable; } /* PaOSS_SetFormat will do the rest of the checking for us */ if ((result = PaOSS_SetFormat("PaOSS IsFormatSupported", tempDevHandle, deviceName, inputChannelCount, outputChannelCount, &sampleRate)) != paNoError) { goto error; } /* everything succeeded! */ close(tempDevHandle); return paFormatIsSupported; error: if (tempDevHandle) close(tempDevHandle); return paSampleFormatNotSupported;}/* PaOSSStream - a stream data structure specifically for this implementation */typedef struct PaOSSStream{ PaUtilStreamRepresentation streamRepresentation; PaUtilCpuLoadMeasurer cpuLoadMeasurer; PaUtilBufferProcessor bufferProcessor; int deviceHandle; int stopSoon; int stopNow; int isActive; int inputChannelCount; int outputChannelCount; pthread_t thread; void *inputBuffer; void *outputBuffer; int lastPosPtr; double lastStreamBytes; int framesProcessed; double sampleRate; unsigned long framesPerHostCallback;}PaOSSStream;/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaStream** s, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ){ PaError result = paNoError; PaOSSHostApiRepresentation *ossHostApi = (PaOSSHostApiRepresentation*)hostApi; PaOSSStream *stream = 0; PaDeviceIndex device; PaDeviceInfo *deviceInfo; audio_buf_info bufinfo; int bytesPerHostBuffer; int flags; int deviceHandle = 0; char *deviceName; unsigned long framesPerHostBuffer; int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat = paInt16, outputSampleFormat = paInt16; PaSampleFormat hostInputSampleFormat = paInt16, hostOutputSampleFormat = paInt16; if( inputParameters ) { inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that input device can support inputChannelCount */ if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels ) return paInvalidChannelCount; /* validate inputStreamInfo */ if( inputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( paInt16, inputSampleFormat ); } else { inputChannelCount = 0; } if( outputParameters ) { outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that output device can support inputChannelCount */ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels ) return paInvalidChannelCount; /* validate outputStreamInfo */ if( outputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( paInt16, outputSampleFormat ); } else { outputChannelCount = 0; } if( inputChannelCount == 0 && outputChannelCount == 0 ) { DBUG(("Both inputChannelCount and outputChannelCount are zero!\n")); return paUnanticipatedHostError; } /* validate platform specific flags */ if( (streamFlags & paPlatformSpecificFlags) != 0 ) return paInvalidFlag; /* unexpected platform specific flag */ /* * open the device and set parameters here */ if (inputChannelCount == 0 && outputChannelCount == 0) return paInvalidChannelCount; /* if full duplex, make sure that they're the same device */ if (inputChannelCount > 0 && outputChannelCount > 0 && inputParameters->device != outputParameters->device) return paInvalidDevice; /* if full duplex, also make sure that they're the same number of channels */ if (inputChannelCount > 0 && outputChannelCount > 0 && inputChannelCount != outputChannelCount) return paInvalidChannelCount; /* note that inputParameters and outputParameters device indicies are * already in host format */ device = (inputChannelCount > 0 ) ? inputParameters->device : outputParameters->device; deviceInfo = hostApi->deviceInfos[device]; deviceName = (char *)deviceInfo->name; flags = O_NONBLOCK; if (inputChannelCount > 0 && outputChannelCount > 0) flags |= O_RDWR; else if (inputChannelCount > 0) flags |= O_RDONLY; else flags |= O_WRONLY; /* open first in nonblocking mode, in case it's busy... */ if ( (deviceHandle = open(deviceInfo->name, flags)) == -1 ) { DBUG(("PaOSS OpenStream: could not open %s\n", deviceName )); return paDeviceUnavailable; } /* if that succeeded, immediately open it again in blocking mode */ close(deviceHandle); flags -= O_NONBLOCK; if ( (deviceHandle = open(deviceInfo->name, flags)) == -1 ) { DBUG(("PaOSS OpenStream: could not open %s in blocking mode\n", deviceName )); return paDeviceUnavailable; } if ((result = PaOSS_SetFormat("PaOSS OpenStream", deviceHandle, deviceName, inputChannelCount, outputChannelCount, &sampleRate)) != paNoError) { goto error; } /* Compute number of frames per host buffer - if we can't retrieve the * value, use the user's value instead */ if ( ioctl(deviceHandle, SNDCTL_DSP_GETBLKSIZE, &bytesPerHostBuffer) == 0) { framesPerHostBuffer = bytesPerHostBuffer / 2 / (inputChannelCount>0? inputChannelCount: outputChannelCount); } else framesPerHostBuffer = framesPerBuffer; /* Allocate stream and fill in structure */ stream = (PaOSSStream*)PaUtil_AllocateMemory( sizeof(PaOSSStream) ); if( !stream ) { result = paInsufficientMemory; goto error; } if( streamCallback )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -