📄 pthread-pa_sgi.c
字号:
Pa_EndUsageCalculation(past);
if (result)
{
DBUG(("Pa_CallConvertInt16() returned %d, stopping...\n", result));
goto done; /* This is apparently NOT an error! */
} /* Just letting the userCallBack stop us. */
/*---------------------------------------- OUTPUT: ------------------------------------*/
if (pahsc->pahsc_NativeOutputBuffer) /* Then pahsc_ALportOUT should also be there! */
{
while (ALgetfillable(pahsc->pahsc_ALportOUT) < pahsc->pahsc_SamplesPerOutputBuffer)
{
/* Trying sginap(1); and usleep(); here... things get blocked under IRIX6.2. */
if (past->past_StopNow) /* Don't let ALwritesamps() block */
goto done;
}
if (ALwritesamps(pahsc->pahsc_ALportOUT, (void*)pahsc->pahsc_NativeOutputBuffer,
pahsc->pahsc_SamplesPerOutputBuffer))
{
ERR_RPT(("ALwritesamps() failed.\n"));
result = paInternalError;
goto done;
}
}
/*-------------------------------------------------------------------------------------*/
}
done:
/* pahsc->pahsc_ThreadPID = -1; Hu? doesn't help!! (added by Pieter) */
past->past_IsActive = 0;
DBUG(("leaving thread.\n"));
return result;
}
/*--------------------------------------------------------------------------------------*/
PaError PaHost_OpenStream(internalPortAudioStream *past)
{
PaError result = paNoError;
PaHostSoundControl *pahsc;
unsigned int minNumBuffers;
internalPortAudioDevice *padIN, *padOUT; /* For looking up native AL-numbers. */
ALconfig sgiALconfig = NULL; /* IRIX-datatype. */
long pvbuf[8]; /* To get/set hardware configs. */
long sr, ALqsize;
DBUG(("PaHost_OpenStream() called.\n")); /* Alloc FASTMEM and init host data. */
if (!past)
{
ERR_RPT(("Streampointer NULL!\n"));
result = paBadStreamPtr; goto done;
}
pahsc = (PaHostSoundControl*)PaHost_AllocateFastMemory(sizeof(PaHostSoundControl));
if (pahsc == NULL)
{
ERR_RPT(("FAST Memory allocation failed.\n")); /* Pass trough some ERR_RPT-exit- */
result = paInsufficientMemory; goto done; /* code (nothing will be freed). */
}
memset(pahsc, 0, sizeof(PaHostSoundControl));
/* pahsc->pahsc_threadPID = -1; Should pahsc_threadPID be inited to */
past->past_DeviceData = (void*)pahsc; /* -1 instead of 0 ?? */
/*--------------------------------------------------- Allocate native buffers: --------*/
pahsc->pahsc_SamplesPerInputBuffer = past->past_FramesPerUserBuffer * /* Needed by the */
past->past_NumInputChannels; /* audio-thread. */
pahsc->pahsc_BytesPerInputBuffer = pahsc->pahsc_SamplesPerInputBuffer * sizeof(short);
if (past->past_NumInputChannels > 0) /* Assumes short = 16 bits! */
{
pahsc->pahsc_NativeInputBuffer = (short*)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerInputBuffer);
if( pahsc->pahsc_NativeInputBuffer == NULL )
{
ERR_RPT(("Fast memory allocation for input-buffer failed.\n"));
result = paInsufficientMemory; goto done;
}
}
pahsc->pahsc_SamplesPerOutputBuffer = past->past_FramesPerUserBuffer * /* Needed by the */
past->past_NumOutputChannels; /* audio-thread. */
pahsc->pahsc_BytesPerOutputBuffer = pahsc->pahsc_SamplesPerOutputBuffer * sizeof(short);
if (past->past_NumOutputChannels > 0) /* Assumes short = 16 bits! */
{
pahsc->pahsc_NativeOutputBuffer = (short*)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerOutputBuffer);
if (pahsc->pahsc_NativeOutputBuffer == NULL)
{
ERR_RPT(("Fast memory allocation for output-buffer failed.\n"));
result = paInsufficientMemory; goto done;
}
}
/*------------------------------------------ Manipulate hardware if necessary and allowed: --*/
ALseterrorhandler(0); /* 0 = turn off the default error handler. */
pvbuf[0] = AL_INPUT_RATE;
pvbuf[2] = AL_INPUT_COUNT;
pvbuf[4] = AL_OUTPUT_RATE; /* TO FIX: rates may be logically, not always in Hz! */
pvbuf[6] = AL_OUTPUT_COUNT;
sr = (long)(past->past_SampleRate + 0.5); /* Common for input and output :-) */
if (past->past_NumInputChannels > 0) /* We need to lookup the corre- */
{ /* sponding native AL-number(s). */
padIN = Pa_GetInternalDevice(past->past_InputDeviceID);
if (!padIN)
{
ERR_RPT(("Pa_GetInternalDevice() for input failed.\n"));
result = paHostError; goto done;
}
if (ALgetparams(padIN->pad_ALdevice, &pvbuf[0], 4)) /* Although input and output will both be on */
goto sgiError; /* the same AL-device, the AL-library might */
if (pvbuf[1] != sr) /* contain more than AL_DEFAULT_DEVICE in */
{ /* Rate different from current harware-rate? the future. Therefore 2 seperate queries. */
if (pvbuf[3] > 0) /* Means, there's other clients using AL-input-ports */
{
ERR_RPT(("Sorry, not allowed to switch input-hardware to %ld Hz because \
another process is currently using input at %ld kHz.\n", sr, pvbuf[1]));
result = paHostError; goto done;
}
pvbuf[1] = sr; /* Then set input-rate. */
if (ALsetparams(padIN->pad_ALdevice, &pvbuf[0], 2))
goto sgiError; /* WHETHER THIS SAMPLERATE WAS REALLY PRESENT IN OUR ARRAY OF RATES, */
} /* IS NOT CHECKED, AT LEAST NOT BY ME, WITHIN THIS FILE! Does PA do? */
}
if (past->past_NumOutputChannels > 0) /* CARE: padOUT/IN may NOT be NULL if Channels <= 0! */
{ /* We use padOUT/IN later on, or at least 1 of both. */
padOUT = Pa_GetInternalDevice(past->past_OutputDeviceID);
if (!padOUT)
{
ERR_RPT(("Pa_GetInternalDevice() for output failed.\n"));
result = paHostError; goto done;
}
if (ALgetparams(padOUT->pad_ALdevice,&pvbuf[4], 4))
goto sgiError;
if ((past->past_NumOutputChannels > 0) && (pvbuf[5] != sr))
{ /* Output needed and rate different from current harware-rate. */
if (pvbuf[7] > 0) /* Means, there's other clients using AL-output-ports */
{
ERR_RPT(("Sorry, not allowed to switch output-hardware to %ld Hz because \
another process is currently using output at %ld kHz.\n", sr, pvbuf[5]));
result = paHostError; goto done; /* Will free again the inputbuffer */
} /* that was just created above. */
pvbuf[5] = sr; /* Then set output-rate. */
if (ALsetparams(padOUT->pad_ALdevice, &pvbuf[4], 2))
goto sgiError;
}
}
/*------------------------------------------ Construct an audio-port-configuration ----------*/
sgiALconfig = ALnewconfig(); /* Change the SGI-AL-default-settings. */
if (sgiALconfig == (ALconfig)0) /* sgiALconfig is released here after use! */
goto sgiError; /* See that sgiALconfig is NOT released! */
if (ALsetsampfmt(sgiALconfig, AL_SAMPFMT_TWOSCOMP)) /* Choose paInt16 as native i/o-format. */
goto sgiError;
if (ALsetwidth (sgiALconfig, AL_SAMPLE_16)) /* Only meaningful when sample format for */
goto sgiError; /* config is set to two's complement format. */
/************************ Future versions might (dynamically) switch to 32-bit floats? *******
if (ALsetsampfmt(sgiALconfig, AL_SAMPFMT_FLOAT)) (Then also call another CallConvert-func.)
goto sgiError;
if (ALsetfloatmax (sgiALconfig, 1.0)) Only meaningful when sample format for config
goto sgiError; is set to AL_SAMPFMT_FLOAT or AL_SAMPFMT_DOUBLE. */
/*---------- ?? --------------------*/
/* DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); */
minNumBuffers = Pa_GetMinNumBuffers(past->past_FramesPerUserBuffer, past->past_SampleRate);
past->past_NumUserBuffers = (minNumBuffers > past->past_NumUserBuffers) ?
minNumBuffers : past->past_NumUserBuffers;
/*------------------------------------------------ Set internal AL queuesize (in samples) ----*/
if (pahsc->pahsc_SamplesPerInputBuffer >= pahsc->pahsc_SamplesPerOutputBuffer)
ALqsize = (long)pahsc->pahsc_SamplesPerInputBuffer;
else /* Take the largest of the two amounts. */
ALqsize = (long)pahsc->pahsc_SamplesPerOutputBuffer;
ALqsize *= 4; /* 4 times as large as amount per transfer! */
if (ALsetqueuesize(sgiALconfig, ALqsize)) /* Or should we use past_NumUserBuffers here? */
goto sgiError; /* Using 2 times may give glitches... */
/* Have to work on ALsetqueuesize() above. */
/* Do ALsetchannels() later, apart per input and/or output. */
/*----------------------------------------------- OPEN 1 OR 2 AL-DEVICES: --------------------*/
if (past->past_OutputDeviceID == past->past_InputDeviceID) /* Who SETS these devive-numbers? */
{
if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0))
{
DBUG(("PaHost_OpenStream: opening both input and output channels.\n"));
/*------------------------- open output port: ----------------------------------*/
if (ALsetchannels (sgiALconfig, (long)(past->past_NumOutputChannels)))
goto sgiError; /* Returns 0 on success, -1 on failure. */
pahsc->pahsc_ALportOUT = ALopenport("PA sgi out", "w", sgiALconfig);
if (pahsc->pahsc_ALportOUT == (ALport)0)
goto sgiError;
/*------------------------- open input port: -----------------------------------*/
if (ALsetchannels (sgiALconfig, (long)(past->past_NumInputChannels)))
goto sgiError; /* Returns 0 on success, -1 on failure. */
pahsc->pahsc_ALportIN = ALopenport("PA sgi in", "r", sgiALconfig);
if (pahsc->pahsc_ALportIN == (ALport)0)
goto sgiError; /* For some reason the "patest_wire.c"-test crashes! */
} /* Probably due to too small buffersizes?.... */
else
{
ERR_RPT(("Cannot setup bidirectional stream between different devices.\n"));
result = paHostError;
goto done;
}
}
else /* (OutputDeviceID != InputDeviceID) */
{
if (past->past_NumOutputChannels > 0) /* WRITE-ONLY: */
{
/*------------------------- open output port: ----------------------------------*/
DBUG(("PaHost_OpenStream: opening %d output channel(s) on %s.\n",
past->past_NumOutputChannels, padOUT->pad_DeviceName));
if (ALsetchannels (sgiALconfig, (long)(past->past_NumOutputChannels)))
goto sgiError; /* Returns 0 on success, -1 on failure. */
pahsc->pahsc_ALportOUT = ALopenport("PA sgi out", "w", sgiALconfig);
if (pahsc->pahsc_ALportOUT == (ALport)0)
goto sgiError;
}
if (past->past_NumInputChannels > 0) /* READ-ONLY: */
{
/*------------------------- open input port: -----------------------------------*/
DBUG(("PaHost_OpenStream: opening %d input channel(s) on %s.\n",
past->past_NumInputChannels, padIN->pad_DeviceName));
if (ALsetchannels (sgiALconfig, (long)(past->past_NumInputChannels)))
goto sgiError; /* Returns 0 on success, -1 on failure. */
pahsc->pahsc_ALportIN = ALopenport("PA sgi in", "r", sgiALconfig);
if (pahsc->pahsc_ALportIN == (ALport)0)
goto sgiError;
}
}
DBUG(("PaHost_OpenStream() succeeded.\n"));
goto done; /* (no errors occured) */
sgiError:
result = translateSGIerror(); /* Translates SGI AL-code to PA-code and ERR_RPTs string. */
done:
if (sgiALconfig)
ALfreeconfig(sgiALconfig); /* We don't need that struct anymore. */
if (result != paNoError)
PaHost_CloseStream(past); /* Frees memory (only if really allocated!). */
return result;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -