📄 pa_sgi.c
字号:
Pa_StartUsageCalculation(past); /* Convert 16 bit native data to */
/* user data and call user routine. */
inBuffer = pahsc->pahsc_InputHostBuffer; /* Short pointers for now, care! */
outBuffer = pahsc->pahsc_OutputHostBuffer;
n = pahsc->pahsc_UserBuffersPerHostBuffer; /* 'n' may never start at NULL ! */
do {
result = Pa_CallConvertInt16(past, inBuffer, outBuffer);
if (result) /* This is apparently NOT an error! Just letting the userCallBack stop us. */
{ DBUG(("Pa_CallConvertInt16() returned %d, stopping...\n", result)); goto skip; }
inBuffer += samplesPerInputUserBuffer; /* Num channels is accounted for. */
outBuffer += samplesPerOutputUserBuffer;
} while (--n);
Pa_EndUsageCalculation(past);
}
/*------------------------------------ FREE-EVENT FROM OUTPUT BUFFER: ---------------------------*/
if (pahsc->pahsc_OutputHostBuffer && ioEvent) /* Don't wait for outputEvent solely (that may cause clicks). */
{ /* Just assume it's time to write, outputEvent may not yet be there. */
if (ALwritesamps(pahsc->pahsc_ALportOUT, (void*)pahsc->pahsc_OutputHostBuffer,
pahsc->pahsc_SamplesPerOutputHostBuffer))
{
ERR_RPT(("ALwritesamps() failed.\n")); /* Better use SEMAS for messaging back to parent! */
sPaHostError = paInternalError;
goto skip;
}
}
}
skip:
/*------------------------------- close AL-ports ----------------------------*/
if (pahsc->pahsc_ALportIN)
{
if (ALcloseport(pahsc->pahsc_ALportIN))
translateSGIerror(); /* Translates SGI AL-code to PA-code and ERR_RPTs string. */
else /* But go on anyway... to release other stuff... */
pahsc->pahsc_ALportIN = (ALport)0;
}
if (pahsc->pahsc_ALportOUT)
{
if (ALcloseport(pahsc->pahsc_ALportOUT))
translateSGIerror();
else
pahsc->pahsc_ALportOUT = (ALport)0;
}
noPahsc:
past->past_IsActive = 0;
if (semaEvent)
{
uspsema(SendSema); /* StopEngine() was still waiting for this acknowledgement. */
usvsema(RcvSema); /* (semaEvent initialized with 0.) */
}
noPast:
DBUG(("Leaving sproc-thread.\n"));
}
/*--------------------------------------------------------------------------------------*/
PaError PaHost_OpenStream(internalPortAudioStream *past)
{
PaError result = paNoError;
PaHostSoundControl *pahsc;
unsigned int minNumBuffers;
internalPortAudioDevice *padIN, *padOUT; /* For looking up native AL-numbers. */
long pvbuf[8], sr, alq; /* To get/set hardware configs. */
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 ?? */
/*------------------------------------------ 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 both input and output :-) */
/*-----------------------------------------------------------------------------*/
/* OVERWRITE 'past_NumUserBuffers'-field in the struct supplied by the caller. */
/* This field may be set to zero by a client application to ask for minimum */
/* latency. It is used below, to set both input- and output-AL-queuesizes. */
minNumBuffers = Pa_GetMinNumBuffers(past->past_FramesPerUserBuffer,
past->past_SampleRate); /* Take biggest. */
past->past_NumUserBuffers = (minNumBuffers > past->past_NumUserBuffers) ?
minNumBuffers : past->past_NumUserBuffers;
DBUG(("past->past_NumUserBuffers=%d\n", past->past_NumUserBuffers));
/*----------------------------------------------------------------------------------*/
pahsc->pahsc_UserBuffersPerHostBuffer = past->past_NumUserBuffers >> 1;
DBUG(("pahsc_UserBuffersPerHostBuffer=%d\n",pahsc->pahsc_UserBuffersPerHostBuffer));
/* 1 is minimum because Pa_GetMinNumBuffers() returns >= 2.
Callback will be called 'pahsc_UserBuffersPerHostBuffer' times (with 'past_FramesPerUserBuffer')
per host transfer. */
/*---------------------------------------------------- SET INPUT CONFIGURATION: ---------------------*/
if (past->past_NumInputChannels > 0) /* We need to lookup the corre- */
{ /* sponding native AL-number(s). */
/*--------------------------------------------------- Allocate native buffers: --------------*/
pahsc->pahsc_SamplesPerInputHostBuffer = pahsc->pahsc_UserBuffersPerHostBuffer *
past->past_FramesPerUserBuffer * /* Needed by the */
past->past_NumInputChannels; /* audio-thread. */
DBUG(("pahsc_SamplesPerInputHostBuffer=%d\n", pahsc->pahsc_SamplesPerInputHostBuffer));
pahsc->pahsc_BytesPerInputHostBuffer = pahsc->pahsc_SamplesPerInputHostBuffer * sizeof(short);
pahsc->pahsc_InputHostBuffer = (short*)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerInputHostBuffer);
if (!pahsc->pahsc_InputHostBuffer)
{
ERR_RPT(("Fast memory allocation failed (in).\n"));
result = paInsufficientMemory;
goto done;
}
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 Hz.\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? */
pahsc->pahsc_ALconfigIN = ALnewconfig(); /* Released at PaHost_CloseStream(). */
if (pahsc->pahsc_ALconfigIN == (ALconfig)0)
goto sgiError;
if (ALsetsampfmt(pahsc->pahsc_ALconfigIN, AL_SAMPFMT_TWOSCOMP))/* Choose paInt16 as native i/o-format. */
goto sgiError;
if (ALsetwidth (pahsc->pahsc_ALconfigIN, 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(pahsc_ALconfigIN, AL_SAMPFMT_FLOAT)) (Then also call another CallConvert-func.)
goto sgiError;
if (ALsetfloatmax (pahsc_ALconfigIN, 1.0)) Only meaningful when sample format for config
goto sgiError; is set to AL_SAMPFMT_FLOAT or AL_SAMPFMT_DOUBLE. */
/*--------- Set internal AL queuesize (in samples, not in frames!) -------------------------------*/
alq = (long)past->past_NumUserBuffers * past->past_FramesPerUserBuffer * past->past_NumInputChannels;
DBUG(("AL input queuesize = %ld samples.\n", alq));
if (ALsetqueuesize(pahsc->pahsc_ALconfigIN, alq))
goto sgiError;
if (ALsetchannels (pahsc->pahsc_ALconfigIN, (long)(past->past_NumInputChannels)))
goto sgiError; /* Returns 0 on success, -1 on failure. */
}
else
pahsc->pahsc_InputHostBuffer = (short*)NULL; /* Added 2003! Is checked in callback-routine. */
/*---------------------------------------------------- SET OUTPUT CONFIGURATION: ------------------------*/
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. */
pahsc->pahsc_SamplesPerOutputHostBuffer = pahsc->pahsc_UserBuffersPerHostBuffer *
past->past_FramesPerUserBuffer * /* Needed by the */
past->past_NumOutputChannels; /* audio-thread. */
DBUG(("pahsc_SamplesPerOutputHostBuffer=%d\n", pahsc->pahsc_SamplesPerOutputHostBuffer));
pahsc->pahsc_BytesPerOutputHostBuffer = pahsc->pahsc_SamplesPerOutputHostBuffer * sizeof(short);
pahsc->pahsc_OutputHostBuffer = (short*)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerOutputHostBuffer);
if (!pahsc->pahsc_OutputHostBuffer)
{
ERR_RPT(("Fast memory allocation failed (out).\n"));
result = paInsufficientMemory;
goto done;
}
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 (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 Hz.\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;
}
pahsc->pahsc_ALconfigOUT = ALnewconfig(); /* Released at PaHost_CloseStream(). */
if (pahsc->pahsc_ALconfigOUT == (ALconfig)0)
goto sgiError;
if (ALsetsampfmt(pahsc->pahsc_ALconfigOUT, AL_SAMPFMT_TWOSCOMP)) /* Choose paInt16 as native i/o-format. */
goto sgiError;
if (ALsetwidth (pahsc->pahsc_ALconfigOUT, 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. **/
alq = (long)past->past_NumUserBuffers * past->past_FramesPerUserBuffer * past->past_NumOutputChannels;
DBUG(("AL output queuesize = %ld samples.\n", alq));
if (ALsetqueuesize(pahsc->pahsc_ALconfigOUT, alq))
goto sgiError;
if (ALsetchannels (pahsc->pahsc_ALconfigOUT, (long)(past->past_NumOutputChannels)))
goto sgiError;
}
else
pahsc->pahsc_OutputHostBuffer = (short*)NULL;
/*----------------------------------------------- TEST DEVICE ID's: --------------------*/
if ((past->past_OutputDeviceID != past->past_InputDeviceID) && /* Who SETS these devive-numbers? */
(past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0))
{
ERR_RPT(("Cannot setup bidirectional stream between different devices.\n"));
result = paHostError;
goto done;
}
goto done; /* (no errors occured) */
sgiError:
result = translateSGIerror(); /* Translates SGI AL-code to PA-code and ERR_RPTs string. */
done:
if (result != paNoError)
PaHost_CloseStream(past); /* Frees memory (only if really allocated!). */
return result;
}
/*-----------------------------------------------------*/
PaError PaHost_StartOutput(internalPortAudioStream *past)
{
return paNoError; /* Hmm, not implemented yet? */
}
PaError PaHost_StartInput(internalPortAudioStream *past)
{
return paNoError;
}
/*------------------------------------------------------------------------------*/
PaError PaHost_StartEngine(internalPortAudioStream *past)
{
PaHostSoundControl *pahsc;
usptr_t *arena;
if (!past) /* Test argument. */
{
ERR_RPT(("PaHost_StartEngine(NULL)!\n"));
return paBadStreamPtr;
}
pahsc = (PaHostSoundControl*)past->past_DeviceData;
if (!pahsc)
{
ERR_RPT(("PaHost_StartEngine(arg): arg->past_DeviceData = NULL!\n"));
return paHostError;
}
past->past_StopSoon = 0; /* Assume SGI ALport is already opened! */
past->past_StopNow = 0; /* Why don't we check pahsc for NULL? */
past->past_IsActive = 1;
/* Although the pthread_create() function, as well as <pthread.h>, may be */
/* available in IRIX, use sproc() on SGI to create audio-background-thread. */
/* (Linux/oss uses pthread_create() instead of __clone() because: */
/* - pthread_create also works for other UNIX systems like Solaris, */
/* - Java HotSpot VM crashes in pthread_setcanceltype() using __clone().) */
usconfig(CONF_ARENATYPE, US_SHAREDONLY); /* (From SGI-AL-examples, file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -