Updates to GAUDOUT.
Add Events to the GAUDOUT api.
This commit is contained in:
parent
68a0be8110
commit
e762e91bd5
5 changed files with 117 additions and 33 deletions
|
@ -77,16 +77,14 @@ static bool_t senddata(WAVEHDR *pwh) {
|
||||||
pwh->dwFlags = 0;
|
pwh->dwFlags = 0;
|
||||||
pwh->dwLoops = 0;
|
pwh->dwLoops = 0;
|
||||||
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
|
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
|
||||||
pwh->lpData = 0;
|
|
||||||
fprintf(stderr, "GAUDOUT: Failed to prepare a buffer");
|
fprintf(stderr, "GAUDOUT: Failed to prepare a buffer");
|
||||||
return FALSE;
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send it to windows
|
// Send it to windows
|
||||||
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
|
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
|
||||||
pwh->lpData = 0;
|
|
||||||
fprintf(stderr, "GAUDOUT: Failed to write the buffer");
|
fprintf(stderr, "GAUDOUT: Failed to write the buffer");
|
||||||
return FALSE;
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
nQueuedBuffers++;
|
nQueuedBuffers++;
|
||||||
|
@ -114,8 +112,11 @@ static DWORD WINAPI waveProc(LPVOID arg) {
|
||||||
nQueuedBuffers--;
|
nQueuedBuffers--;
|
||||||
|
|
||||||
// Try and get a new block
|
// Try and get a new block
|
||||||
if (isRunning)
|
if ((!isRunning || !senddata(pwh)) && !nQueuedBuffers) {
|
||||||
senddata(pwh);
|
gfxSystemLock();
|
||||||
|
gaudoutDoneI();
|
||||||
|
gfxSystemUnlock();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -145,7 +146,7 @@ bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat fo
|
||||||
if (!waveThread) {
|
if (!waveThread) {
|
||||||
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
|
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
|
||||||
fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n");
|
fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n");
|
||||||
return FALSE;
|
exit(-1);
|
||||||
}
|
}
|
||||||
CloseHandle(waveThread);
|
CloseHandle(waveThread);
|
||||||
}
|
}
|
||||||
|
@ -160,7 +161,7 @@ bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat fo
|
||||||
|
|
||||||
if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
|
if (waveOutOpen(&ah, WAVE_MAPPER, &wfx, (DWORD_PTR)threadID, 0, CALLBACK_THREAD)) {
|
||||||
fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n");
|
fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n");
|
||||||
return FALSE;
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -22,28 +22,21 @@
|
||||||
/* Driver hardware support. */
|
/* Driver hardware support. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The audio input sample type
|
|
||||||
*/
|
|
||||||
//typedef uint8_t audout_sample_t;
|
|
||||||
typedef int16_t audout_sample_t;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The maximum sample frequency supported by this audio device
|
* @brief The maximum sample frequency supported by this audio device
|
||||||
*/
|
*/
|
||||||
#define GAUDOUT_MAX_SAMPLE_FREQUENCY 44100
|
#define GAUDOUT_MAX_SAMPLE_FREQUENCY 44100
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The number of bits in a sample
|
* @brief The number of audio formats supported by this driver
|
||||||
*/
|
*/
|
||||||
//#define GAUDOUT_BITS_PER_SAMPLE 8
|
#define GAUDOUT_NUM_FORMATS 2
|
||||||
#define GAUDOUT_BITS_PER_SAMPLE 16
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The format of an audio sample
|
* @brief The available audio sample formats in order of preference
|
||||||
*/
|
*/
|
||||||
//#define GAUDOUT_SAMPLE_FORMAT ARRAY_DATA_8BITUNSIGNED
|
#define GAUDOUT_FORMAT1 ARRAY_DATA_16BITSIGNED
|
||||||
#define GAUDOUT_SAMPLE_FORMAT ARRAY_DATA_16BITSIGNED
|
#define GAUDOUT_FORMAT2 ARRAY_DATA_8BITUNSIGNED
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The number of audio channels supported by this driver
|
* @brief The number of audio channels supported by this driver
|
||||||
|
|
|
@ -56,6 +56,16 @@ GAudioData *gaudoutGetDataBlockI(void);
|
||||||
*/
|
*/
|
||||||
void gaudoutReleaseDataBlockI(GAudioData *paud);
|
void gaudoutReleaseDataBlockI(GAudioData *paud);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Signal that all playing has now stopped
|
||||||
|
*
|
||||||
|
* @note Defined in the high level GAUDOUT code for use by the GAUDOUT drivers.
|
||||||
|
*
|
||||||
|
* @iclass
|
||||||
|
* @notapi
|
||||||
|
*/
|
||||||
|
void gaudoutDoneI(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialise the driver
|
* @brief Initialise the driver
|
||||||
* @return TRUE if the channel and frequency are valid.
|
* @return TRUE if the channel and frequency are valid.
|
||||||
|
|
|
@ -21,32 +21,33 @@
|
||||||
static gfxQueueASync playlist;
|
static gfxQueueASync playlist;
|
||||||
static gfxQueueGSync freelist;
|
static gfxQueueGSync freelist;
|
||||||
|
|
||||||
static uint16_t audFlags;
|
static uint16_t PlayFlags;
|
||||||
#define AUDOUTFLG_RUNNING 0x0001
|
#define PLAYFLG_USEEVENTS 0x0001
|
||||||
#define AUDOUTFLG_USE_EVENTS 0x0002
|
#define PLAYFLG_PLAYING 0x0002
|
||||||
|
|
||||||
#if GFX_USE_GEVENT
|
#if GFX_USE_GEVENT
|
||||||
static GTimer AudGTimer;
|
static GTimer PlayTimer;
|
||||||
|
|
||||||
static void AudGTimerCallback(void *param) {
|
static void PlayTimerCallback(void *param) {
|
||||||
(void) param;
|
(void) param;
|
||||||
GSourceListener *psl;
|
GSourceListener *psl;
|
||||||
GEventADC *pe;
|
GEventAudioOut *pe;
|
||||||
|
|
||||||
psl = 0;
|
psl = 0;
|
||||||
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
|
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
|
||||||
if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
|
if (!(pe = (GEventAudioOut *)geventGetEventBuffer(psl))) {
|
||||||
// This listener is missing - save this.
|
// This listener is missing - save this.
|
||||||
psl->srcflags |= GAUDIN_LOSTEVENT;
|
psl->srcflags |= GAUDOUT_LOSTEVENT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pe->type = GEVENT_AUDIO_IN;
|
pe->type = GEVENT_AUDIO_OUT;
|
||||||
pe->channel = aud.channel;
|
|
||||||
pe->count = lastcount;
|
|
||||||
pe->buffer = lastbuffer;
|
|
||||||
pe->flags = psl->srcflags;
|
pe->flags = psl->srcflags;
|
||||||
psl->srcflags = 0;
|
psl->srcflags = 0;
|
||||||
|
if ((PlayFlags & PLAYFLG_PLAYING))
|
||||||
|
pe->flags |= GAUDOUT_PLAYING;
|
||||||
|
if (!gfxQueueGSyncIsEmpty(&freelist))
|
||||||
|
pe->flags |= GAUDOUT_FREEBLOCK;
|
||||||
geventSendEvent(psl);
|
geventSendEvent(psl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,11 +58,17 @@ void _gaudoutInit(void)
|
||||||
{
|
{
|
||||||
gfxQueueASyncInit(&playlist);
|
gfxQueueASyncInit(&playlist);
|
||||||
gfxQueueGSyncInit(&freelist);
|
gfxQueueGSyncInit(&freelist);
|
||||||
|
#if GFX_USE_GEVENT
|
||||||
|
gtimerInit(&PlayTimer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gaudoutDeinit(void)
|
void _gaudoutDeinit(void)
|
||||||
{
|
{
|
||||||
/* ToDo */
|
/* ToDo */
|
||||||
|
#if GFX_USE_GEVENT
|
||||||
|
gtimerDeinit(&PlayTimer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gaudioAllocBuffers(unsigned num, size_t size) {
|
bool_t gaudioAllocBuffers(unsigned num, size_t size) {
|
||||||
|
@ -103,6 +110,7 @@ bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat form
|
||||||
void gaudioPlay(GAudioData *paud) {
|
void gaudioPlay(GAudioData *paud) {
|
||||||
if (paud)
|
if (paud)
|
||||||
gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
|
gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
|
||||||
|
PlayFlags |= PLAYFLG_PLAYING;
|
||||||
gaudout_lld_start();
|
gaudout_lld_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,12 +124,22 @@ void gaudioPlayStop(void) {
|
||||||
gaudout_lld_stop();
|
gaudout_lld_stop();
|
||||||
while((paud = (GAudioData *)gfxQueueASyncGet(&playlist)))
|
while((paud = (GAudioData *)gfxQueueASyncGet(&playlist)))
|
||||||
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
|
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
|
||||||
|
PlayFlags &= ~PLAYFLG_PLAYING;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_t gaudioPlaySetVolume(uint8_t vol) {
|
bool_t gaudioPlaySetVolume(uint8_t vol) {
|
||||||
return gaudout_lld_set_volume(vol);
|
return gaudout_lld_set_volume(vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
|
||||||
|
GSourceHandle gaudioPlayGetSource(void) {
|
||||||
|
if (!gtimerIsActive(&PlayTimer))
|
||||||
|
gtimerStart(&PlayTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
|
||||||
|
PlayFlags |= PLAYFLG_USEEVENTS;
|
||||||
|
return (GSourceHandle)&PlayFlags;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routines provided for use by drivers.
|
* Routines provided for use by drivers.
|
||||||
*/
|
*/
|
||||||
|
@ -132,8 +150,19 @@ GAudioData *gaudoutGetDataBlockI(void) {
|
||||||
|
|
||||||
void gaudoutReleaseDataBlockI(GAudioData *paud) {
|
void gaudoutReleaseDataBlockI(GAudioData *paud) {
|
||||||
gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud);
|
gfxQueueGSyncPutI(&freelist, (gfxQueueGSyncItem *)paud);
|
||||||
|
#if GFX_USE_GEVENT
|
||||||
|
if (PlayFlags & PLAYFLG_USEEVENTS)
|
||||||
|
gtimerJabI(&PlayTimer);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gaudoutDoneI(void) {
|
||||||
|
PlayFlags &= ~PLAYFLG_PLAYING;
|
||||||
|
#if GFX_USE_GEVENT
|
||||||
|
if (PlayFlags & PLAYFLG_USEEVENTS)
|
||||||
|
gtimerJabI(&PlayTimer);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* GFX_USE_GAUDOUT */
|
#endif /* GFX_USE_GAUDOUT */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
|
@ -42,6 +42,36 @@ typedef struct GAudioData {
|
||||||
size_t len; // @< The length of the data in the buffer area (in bytes)
|
size_t len; // @< The length of the data in the buffer area (in bytes)
|
||||||
} GAudioData;
|
} GAudioData;
|
||||||
|
|
||||||
|
|
||||||
|
// Event types for GAUDOUT
|
||||||
|
#define GEVENT_AUDIO_OUT (GEVENT_GAUDOUT_FIRST+0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The Audio output event structure.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
typedef struct GEventAudioOut_t {
|
||||||
|
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief The type of this event (GEVENT_AUDIO_OUT)
|
||||||
|
*/
|
||||||
|
GEventType type;
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief The event flags
|
||||||
|
*/
|
||||||
|
uint16_t flags;
|
||||||
|
/**
|
||||||
|
* @brief The event flag values.
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define GAUDOUT_LOSTEVENT 0x0001 /**< @brief The last GEVENT_AUDIO_OUT event was lost */
|
||||||
|
#define GAUDOUT_PLAYING 0x0002 /**< @brief The audio out system is currently playing */
|
||||||
|
#define GAUDOUT_FREEBLOCK 0x0004 /**< @brief An audio buffer has been freed */
|
||||||
|
/** @} */
|
||||||
|
} GEventAudioOut;
|
||||||
|
/** @} */
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -96,6 +126,8 @@ void gaudioReleaseBuffer(GAudioData *paud);
|
||||||
*
|
*
|
||||||
* @note Some channels are mono, and some are stereo. See your driver config file
|
* @note Some channels are mono, and some are stereo. See your driver config file
|
||||||
* to determine which channels to use and whether they are stereo or not.
|
* to determine which channels to use and whether they are stereo or not.
|
||||||
|
* @note Only one channel can be playing at a time. Calling this will stop any
|
||||||
|
* currently playing channel.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
|
@ -155,6 +187,25 @@ void gaudioPlayStop(void);
|
||||||
*/
|
*/
|
||||||
bool_t gaudioPlaySetVolume(uint8_t vol);
|
bool_t gaudioPlaySetVolume(uint8_t vol);
|
||||||
|
|
||||||
|
#if GFX_USE_GEVENT || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Turn on sending results to the GEVENT sub-system.
|
||||||
|
* @details Returns a GSourceHandle to listen for GEVENT_AUDIO_OUT events.
|
||||||
|
*
|
||||||
|
* @note The audio output will not use the GEVENT system unless this is
|
||||||
|
* called first. This saves processing time if the application does
|
||||||
|
* not want to use the GEVENT sub-system for audio output.
|
||||||
|
* Once turned on it can only be turned off by calling @p gaudioPlayInit() again.
|
||||||
|
* @note The audio output is capable of signalling via this method and other methods
|
||||||
|
* at the same time.
|
||||||
|
*
|
||||||
|
* @return The GSourceHandle
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
GSourceHandle gaudioPlayGetSource(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue