Updates to GAUDOUT.

Add Events to the GAUDOUT api.
ugfx_release_2.6
inmarket 2014-03-05 13:45:37 +10:00
parent 68a0be8110
commit e762e91bd5
5 changed files with 117 additions and 33 deletions

View File

@ -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;

View File

@ -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

View File

@ -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.

View File

@ -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 */
/** @} */ /** @} */

View File

@ -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