390 lines
13 KiB
ObjectPascal
390 lines
13 KiB
ObjectPascal
{This unit is part of United Openlibraries of Sound (uos)}
|
|
|
|
{This is the Dynamic loading version of PortAudio Pascal Wrapper.
|
|
Load library with pa_load() and release with pa_unload().
|
|
License : modified LGPL.
|
|
Fred van Stappen / fiens@hotmail.com
|
|
Reference counting added by Max Karpushin / homeplaner@yandex.ru}
|
|
|
|
unit uos_portaudio;
|
|
|
|
{$mode objfpc}{$H+}
|
|
{$PACKRECORDS C}
|
|
|
|
interface
|
|
|
|
uses
|
|
dynlibs, CTypes;
|
|
|
|
const
|
|
libpa=
|
|
{$IFDEF unix}
|
|
{$IFDEF darwin}
|
|
'libportaudio.2.dylib';
|
|
{$ELSE}
|
|
'libportaudio.so.2';
|
|
{$ENDIF}
|
|
{$ELSE}
|
|
'portaudio.dll';
|
|
{$ENDIF}
|
|
|
|
type
|
|
PaError = CInt32;
|
|
PaErrorCode =(
|
|
paNotInitialized := -10000,
|
|
paUnanticipatedHostError,
|
|
paInvalidChannelCount,
|
|
paInvalidSampleRate,
|
|
paInvalidDevice,
|
|
paInvalidFlag,
|
|
paSampleFormatNotSupported,
|
|
paBadIODeviceCombination,
|
|
paInsufficientMemory,
|
|
paBufferTooBig,
|
|
paBufferTooSmall,
|
|
paNullCallback,
|
|
paBadStreamPtr,
|
|
paTimedOut,
|
|
paInternalError,
|
|
paDeviceUnavailable,
|
|
paIncompatibleHostApiSpecificStreamInfo,
|
|
paStreamIsStopped,
|
|
paStreamIsNotStopped,
|
|
paInputOverflowed,
|
|
paOutputUnderflowed,
|
|
paHostApiNotFound,
|
|
paInvalidHostApi,
|
|
paCanNotReadFromACallbackStream,
|
|
paCanNotWriteToACallbackStream,
|
|
paCanNotReadFromAnOutputOnlyStream,
|
|
paCanNotWriteToAnInputOnlyStream,
|
|
paIncompatibleStreamHostApi,
|
|
paBadBufferPtr,
|
|
paNoError := 0
|
|
);
|
|
|
|
PaDeviceIndex = CInt32;
|
|
|
|
PaHostApiIndex = CInt32;
|
|
|
|
PaHostApiTypeId =(paInDevelopment := 0,
|
|
paDirectSound := 1,
|
|
paMME := 2,
|
|
paASIO := 3,
|
|
paSoundManager := 4,
|
|
paCoreAudio := 5,
|
|
paOSS := 7,
|
|
paALSA := 8,
|
|
paAL := 9,
|
|
paBeOS := 10,
|
|
paWDMKS := 11,
|
|
paJACK := 12,
|
|
paWASAPI := 13,
|
|
paAudioScienceHPI := 14
|
|
);
|
|
|
|
PaHostApiInfo = record
|
|
structVersion : CInt32;
|
|
_type : PaHostApiTypeId ;
|
|
_name : Pchar;
|
|
deviceCount : CInt32;
|
|
defaultInputDevice : PaDeviceIndex;
|
|
defaultOutputDevice : PaDeviceIndex;
|
|
end;
|
|
PPaHostApiInfo = ^PaHostApiInfo;
|
|
|
|
PaHostErrorInfo = record
|
|
hostApiType : PaHostApiTypeId;
|
|
errorCode : CLong;
|
|
errorText : PChar;
|
|
end;
|
|
PPaHostErrorInfo = ^PaHostErrorInfo;
|
|
|
|
PaTime = CDouble;
|
|
|
|
PaSampleFormat = pCULongLong;
|
|
|
|
PaDeviceInfo = record
|
|
structVersion : CInt32;
|
|
_name : PChar;
|
|
hostApi : PaHostApiIndex;
|
|
maxInputChannels : CInt32;
|
|
maxOutputChannels : CInt32;
|
|
defaultLowInputLatency : PaTime;
|
|
defaultLowOutputLatency : PaTime;
|
|
defaultHighInputLatency : PaTime;
|
|
defaultHighOutputLatency : PaTime;
|
|
defaultSampleRate : CDouble;
|
|
end;
|
|
PPaDeviceInfo = ^PaDeviceInfo;
|
|
|
|
PaStreamParameters = record
|
|
device : PaDeviceIndex;
|
|
channelCount : CInt32;
|
|
sampleFormat : PaSampleFormat;
|
|
suggestedLatency : PaTime;
|
|
hostApiSpecificStreamInfo : Pointer;
|
|
end;
|
|
PPaStreamParameters = ^PaStreamParameters;
|
|
|
|
// ************************* Streaming types *************************
|
|
|
|
PaStream = Pointer;
|
|
PPaStream = ^PaStream;
|
|
PPPaStream = ^PPaStream;
|
|
|
|
PaStreamFlags = CULong;
|
|
|
|
PaStreamCallbackTimeInfo = record
|
|
inputBufferAdcTime : PaTime;
|
|
currentTime : PaTime;
|
|
outputBufferDacTime : PaTime;
|
|
end;
|
|
PPaStreamCallbackTimeInfo = ^PaStreamCallbackTimeInfo;
|
|
|
|
PaStreamCallbackFlags = CULong;
|
|
|
|
PaStreamCallbackResult =(
|
|
paContinue := 0,
|
|
paComplete := 1,
|
|
paAbort := 2);
|
|
|
|
PaStreamCallback = function(
|
|
input : Pointer;
|
|
output : Pointer;
|
|
frameCount : CULong;
|
|
timeInfo : PPaStreamCallbackTimeInfo;
|
|
statusFlags : PaStreamCallbackFlags;
|
|
userData : Pointer) : CInt32;
|
|
PPaStreamCallback = ^PaStreamCallback;
|
|
|
|
PaStreamFinishedCallback = procedure(userData : Pointer);
|
|
PPaStreamFinishedCallback = ^PaStreamFinishedCallback;
|
|
|
|
PaStreamInfo = record
|
|
structVersion : CInt32;
|
|
inputLatency : PaTime;
|
|
outputLatency : PaTime;
|
|
sampleRate : CDouble;
|
|
end;
|
|
PPaStreamInfo = ^PaStreamInfo;
|
|
|
|
const
|
|
paFormatIsSupported = 0;
|
|
paFramesPerBufferUnspecified = 0;
|
|
paNoDevice = PaDeviceIndex(-1);
|
|
paUseHostApiSpecificDeviceSpecification = PaDeviceIndex(-2);
|
|
paFloat32 = PaSampleFormat($00000001);
|
|
paInt32 = PaSampleFormat($00000002);
|
|
paInt24 = PaSampleFormat($00000004);
|
|
paInt16 = PaSampleFormat($00000008);
|
|
paInt8 = PaSampleFormat($00000010);
|
|
paUInt8 = PaSampleFormat($00000020);
|
|
paCustomFormat = PaSampleFormat($00010000);
|
|
paNonInterleaved = PaSampleFormat($80000000);
|
|
paNoFlag = PaStreamFlags(0);
|
|
paClipOff = PaStreamFlags($00000001);
|
|
paDitherOff = PaStreamFlags($00000002);
|
|
paNeverDropInput = PaStreamFlags($00000004);
|
|
paPrimeOutputBuffersUsingStreamCallback = PaStreamFlags($00000008);
|
|
paPlatformSpecificFlags = PaStreamFlags($FFFF0000);
|
|
paInputUnderflow = PaStreamCallbackFlags($00000001);
|
|
paInputOverflow = PaStreamCallbackFlags($00000002);
|
|
paOutputUnderflow = PaStreamCallbackFlags($00000004);
|
|
paOutputOverflow = PaStreamCallbackFlags($00000008);
|
|
paPrimingOutput = PaStreamCallbackFlags($00000010);
|
|
|
|
////// Dynamic load : Vars that will hold our dynamically loaded functions...
|
|
|
|
// *************************** functions *******************************
|
|
|
|
var Pa_GetVersion: function():CInt32 ; cdecl;
|
|
|
|
var Pa_GetVersionText: function():PChar ; cdecl;
|
|
|
|
var Pa_GetErrorText: function(errorCode : PaError):PChar ; cdecl;
|
|
|
|
var Pa_Initialize: function():PaError ; cdecl;
|
|
|
|
var Pa_Terminate: function():PaError ; cdecl;
|
|
|
|
var Pa_GetHostApiCount: function():PaHostApiIndex ; cdecl;
|
|
|
|
var Pa_GetDefaultHostApi: function():PaHostApiIndex ; cdecl;
|
|
|
|
var Pa_GetHostApiInfo: function(hostApi : PaHostApiIndex):PPaHostApiInfo ; cdecl;
|
|
|
|
var Pa_HostApiTypeIdToHostApiIndex: function(_type : PaHostApiTypeId):PaHostApiIndex ; cdecl;
|
|
|
|
var Pa_HostApiDeviceIndexToDeviceIndex: function(hostApi : PaHostApiIndex;hostApiDeviceIndex : CInt32):PaDeviceIndex ; cdecl;
|
|
|
|
var Pa_GetLastHostErrorInfo: function():PPaHostErrorInfo ; cdecl;
|
|
|
|
// ************** Device enumeration and capabilities ******************
|
|
|
|
var Pa_GetDeviceCount: function:PaDeviceIndex ; cdecl;
|
|
|
|
var Pa_GetDefaultInputDevice: function:PaDeviceIndex ; cdecl;
|
|
|
|
var Pa_GetDefaultOutputDevice: function:PaDeviceIndex ; cdecl;
|
|
|
|
var Pa_GetDeviceInfo: function(device : PaDeviceIndex):PPaDeviceInfo ; cdecl;
|
|
|
|
var Pa_IsFormatSupported: function(inputParameters,outputParameters : PPaStreamParameters; sampleRate : CDouble):PaError ; cdecl;
|
|
|
|
// *********************** Stream function *****************************
|
|
|
|
var Pa_OpenStream: function(stream : PPPaStream;
|
|
inputParameters : PPaStreamParameters;
|
|
outputParameters : PPaStreamParameters;
|
|
sampleRate : CDouble;
|
|
framesPerBuffer : CULong;
|
|
streamFlags : PaStreamFlags;
|
|
streamCallback : PPaStreamCallback;
|
|
userData : Pointer):PaError ; cdecl;
|
|
|
|
var Pa_OpenDefaultStream: function(stream : PPPaStream;
|
|
numInputChannels : CInt32;
|
|
numOutputChannels : CInt32;
|
|
sampleFormat : PaSampleFormat;
|
|
sampleRate : CDouble;
|
|
framesPerBuffer : CULong;
|
|
streamCallback : PPaStreamCallback;
|
|
userData : Pointer):PaError ; cdecl;
|
|
|
|
var Pa_CloseStream: function(stream : PPaStream):PaError ; cdecl;
|
|
|
|
var Pa_SetStreamFinishedCallback: function(stream : PPaStream;
|
|
streamFinishedCallback : PPaStreamFinishedCallback):PaError ; cdecl;
|
|
|
|
var Pa_StartStream: function(stream : PPaStream):PaError ; cdecl;
|
|
|
|
var Pa_StopStream: function(stream : PPaStream):PaError ; cdecl;
|
|
|
|
var Pa_AbortStream: function(stream : PPaStream):PaError ; cdecl;
|
|
|
|
var Pa_IsStreamStopped: function(stream : PPaStream):PaError ; cdecl;
|
|
|
|
var Pa_IsStreamActive: function(stream : PPaStream):PaError ; cdecl;
|
|
|
|
var Pa_GetStreamInfo: function(stream : PPaStream):PPaStreamInfo ; cdecl;
|
|
|
|
var Pa_GetStreamTime: function(stream : PPaStream):Patime ; cdecl;
|
|
|
|
var Pa_GetStreamCpuLoad: function(stream : PPaStream):CDouble ; cdecl;
|
|
|
|
var Pa_ReadStream: function(stream : PPaStream; buffer : pcfloat ;frames : CULong):PaError ; cdecl;
|
|
|
|
var Pa_WriteStream: function(stream : PPaStream; buffer : pcfloat ;frames : CULong):PaError ; cdecl;
|
|
|
|
var Pa_GetStreamReadAvailable: function(stream : PPaStream):CSLong ; cdecl;
|
|
|
|
var Pa_GetStreamWriteAvailable: function(stream : PPaStream):CSLong ; cdecl;
|
|
|
|
// ****************** Miscellaneous utilities **************************
|
|
|
|
var Pa_GetSampleSize: function(format : PaSampleFormat):PaError ; cdecl;
|
|
|
|
var Pa_Sleep: function(msec : CLong) : integer; cdecl;
|
|
|
|
///////////////////////////////////////////////
|
|
|
|
{Special function for dynamic loading of lib ...}
|
|
|
|
var Pa_Handle:TLibHandle=dynlibs.NilHandle; // this will hold our handle for the lib; it functions nicely as a mutli-lib prevention unit as well...
|
|
|
|
var ReferenceCounter : cardinal = 0; // Reference counter
|
|
|
|
function Pa_IsLoaded : boolean; inline;
|
|
|
|
Function Pa_Load(const libfilename:string) :boolean; // load the lib
|
|
|
|
Procedure Pa_Unload(); // unload and frees the lib from memory : do not forget to call it before close application.
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
implementation
|
|
|
|
function Pa_IsLoaded: boolean;
|
|
begin
|
|
Result := (Pa_Handle <> dynlibs.NilHandle);
|
|
end;
|
|
|
|
Function Pa_Load (const libfilename:string) :boolean;
|
|
var
|
|
thelib: string;
|
|
begin
|
|
Result := False;
|
|
if Pa_Handle<>0 then
|
|
begin
|
|
Inc(ReferenceCounter);
|
|
result:=true {is it already there ?}
|
|
end else
|
|
begin {go & load the library}
|
|
if Length(libfilename) = 0 then thelib := libpa else thelib := libfilename;
|
|
Pa_Handle:=DynLibs.SafeLoadLibrary(thelib); // obtain the handle we want
|
|
if Pa_Handle <> DynLibs.NilHandle then
|
|
begin {now we tie the functions to the VARs from above}
|
|
|
|
Pointer(Pa_GetVersion):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetVersion'));
|
|
Pointer(Pa_GetVersionText):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetVersionText'));
|
|
Pointer(Pa_GetErrorText):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetErrorText'));
|
|
Pointer(Pa_Initialize):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Initialize'));
|
|
Pointer(Pa_Terminate):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Terminate'));
|
|
Pointer(Pa_GetHostApiCount):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetHostApiCount'));
|
|
Pointer(Pa_GetDefaultHostApi):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultHostApi'));
|
|
Pointer(Pa_GetHostApiInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetHostApiInfo'));
|
|
Pointer(Pa_HostApiTypeIdToHostApiIndex):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_HostApiTypeIdToHostApiIndex'));
|
|
Pointer(Pa_HostApiDeviceIndexToDeviceIndex):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_HostApiDeviceIndexToDeviceIndex'));
|
|
Pointer(Pa_GetLastHostErrorInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetLastHostErrorInfo'));
|
|
//////////////////
|
|
Pointer(Pa_GetDeviceCount):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDeviceCount'));
|
|
Pointer(Pa_GetDefaultInputDevice):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultInputDevice'));
|
|
Pointer(Pa_GetDefaultOutputDevice):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDefaultOutputDevice'));
|
|
Pointer(Pa_GetDeviceInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetDeviceInfo'));
|
|
Pointer(Pa_IsFormatSupported):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsFormatSupported'));
|
|
//////////////////////
|
|
Pointer(Pa_OpenStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_OpenStream'));
|
|
Pointer(Pa_OpenDefaultStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_OpenDefaultStream'));
|
|
Pointer(Pa_CloseStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_CloseStream'));
|
|
Pointer(Pa_SetStreamFinishedCallback):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_SetStreamFinishedCallback'));
|
|
Pointer(Pa_StartStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_StartStream'));
|
|
Pointer(Pa_StopStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_StopStream'));
|
|
Pointer(Pa_AbortStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_AbortStream'));
|
|
Pointer(Pa_IsStreamStopped):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsStreamStopped'));
|
|
Pointer(Pa_IsStreamActive):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_IsStreamActive'));
|
|
Pointer(Pa_GetStreamInfo):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamInfo'));
|
|
Pointer(Pa_GetStreamTime):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamTime'));
|
|
Pointer(Pa_GetStreamCpuLoad):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamCpuLoad'));
|
|
Pointer(Pa_ReadStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_ReadStream'));
|
|
Pointer(Pa_WriteStream):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_WriteStream'));
|
|
Pointer(Pa_GetStreamReadAvailable):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamReadAvailable'));
|
|
Pointer(Pa_GetStreamWriteAvailable):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetStreamWriteAvailable'));
|
|
Pointer(Pa_GetSampleSize):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_GetSampleSize'));
|
|
Pointer(Pa_Sleep):=DynLibs.GetProcedureAddress(PA_Handle,PChar('Pa_Sleep'));
|
|
end;
|
|
Result := Pa_IsLoaded;
|
|
ReferenceCounter:=1;
|
|
end;
|
|
|
|
end;
|
|
|
|
Procedure Pa_Unload;
|
|
begin
|
|
// < Reference counting
|
|
if ReferenceCounter > 0 then
|
|
dec(ReferenceCounter);
|
|
if ReferenceCounter > 0 then
|
|
exit;
|
|
// >
|
|
if Pa_IsLoaded then
|
|
begin
|
|
Pa_Terminate();
|
|
DynLibs.UnloadLibrary(Pa_Handle);
|
|
Pa_Handle:=DynLibs.NilHandle;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|