aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-03-05 13:45:37 +1000
committerinmarket <andrewh@inmarket.com.au>2014-03-05 13:45:37 +1000
commite762e91bd5d5347071c3b43fbdb021376584c267 (patch)
treefdb17e76a67cc9eb163735dd7adf5d2911fd27ee
parent68a0be8110d2dea408890f819bae443b9b476f84 (diff)
downloaduGFX-e762e91bd5d5347071c3b43fbdb021376584c267.tar.gz
uGFX-e762e91bd5d5347071c3b43fbdb021376584c267.tar.bz2
uGFX-e762e91bd5d5347071c3b43fbdb021376584c267.zip
Updates to GAUDOUT.
Add Events to the GAUDOUT api.
-rw-r--r--drivers/audio/Win32/gaudout_lld.c17
-rw-r--r--drivers/audio/Win32/gaudout_lld_config.h19
-rw-r--r--src/gaudout/driver.h10
-rw-r--r--src/gaudout/gaudout.c53
-rw-r--r--src/gaudout/sys_defs.h51
5 files changed, 117 insertions, 33 deletions
diff --git a/drivers/audio/Win32/gaudout_lld.c b/drivers/audio/Win32/gaudout_lld.c
index fd70c80b..4fa6d605 100644
--- a/drivers/audio/Win32/gaudout_lld.c
+++ b/drivers/audio/Win32/gaudout_lld.c
@@ -77,16 +77,14 @@ static bool_t senddata(WAVEHDR *pwh) {
pwh->dwFlags = 0;
pwh->dwLoops = 0;
if (waveOutPrepareHeader(ah, pwh, sizeof(WAVEHDR))) {
- pwh->lpData = 0;
fprintf(stderr, "GAUDOUT: Failed to prepare a buffer");
- return FALSE;
+ exit(-1);
}
// Send it to windows
if (waveOutWrite(ah, pwh, sizeof(WAVEHDR))) {
- pwh->lpData = 0;
fprintf(stderr, "GAUDOUT: Failed to write the buffer");
- return FALSE;
+ exit(-1);
}
nQueuedBuffers++;
@@ -114,8 +112,11 @@ static DWORD WINAPI waveProc(LPVOID arg) {
nQueuedBuffers--;
// Try and get a new block
- if (isRunning)
- senddata(pwh);
+ if ((!isRunning || !senddata(pwh)) && !nQueuedBuffers) {
+ gfxSystemLock();
+ gaudoutDoneI();
+ gfxSystemUnlock();
+ }
break;
}
}
@@ -145,7 +146,7 @@ bool_t gaudout_lld_init(uint16_t channel, uint32_t frequency, ArrayDataFormat fo
if (!waveThread) {
if (!(waveThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)waveProc, 0, 0, &threadID))) {
fprintf(stderr, "GAUDOUT: Can't create WAVE play-back thread\n");
- return FALSE;
+ exit(-1);
}
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)) {
fprintf(stderr, "GAUDOUT: Can't open WAVE play-back device\n");
- return FALSE;
+ exit(-1);
}
return TRUE;
diff --git a/drivers/audio/Win32/gaudout_lld_config.h b/drivers/audio/Win32/gaudout_lld_config.h
index 157f33f0..0fb90508 100644
--- a/drivers/audio/Win32/gaudout_lld_config.h
+++ b/drivers/audio/Win32/gaudout_lld_config.h
@@ -23,27 +23,20 @@
/*===========================================================================*/
/**
- * @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
*/
-#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_BITS_PER_SAMPLE 16
+#define GAUDOUT_NUM_FORMATS 2
/**
- * @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_SAMPLE_FORMAT ARRAY_DATA_16BITSIGNED
+#define GAUDOUT_FORMAT1 ARRAY_DATA_16BITSIGNED
+#define GAUDOUT_FORMAT2 ARRAY_DATA_8BITUNSIGNED
/**
* @brief The number of audio channels supported by this driver
diff --git a/src/gaudout/driver.h b/src/gaudout/driver.h
index 8e72dff4..bd00d06d 100644
--- a/src/gaudout/driver.h
+++ b/src/gaudout/driver.h
@@ -57,6 +57,16 @@ GAudioData *gaudoutGetDataBlockI(void);
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
* @return TRUE if the channel and frequency are valid.
*
diff --git a/src/gaudout/gaudout.c b/src/gaudout/gaudout.c
index 275677c8..00b01e91 100644
--- a/src/gaudout/gaudout.c
+++ b/src/gaudout/gaudout.c
@@ -21,32 +21,33 @@
static gfxQueueASync playlist;
static gfxQueueGSync freelist;
-static uint16_t audFlags;
- #define AUDOUTFLG_RUNNING 0x0001
- #define AUDOUTFLG_USE_EVENTS 0x0002
+static uint16_t PlayFlags;
+ #define PLAYFLG_USEEVENTS 0x0001
+ #define PLAYFLG_PLAYING 0x0002
#if GFX_USE_GEVENT
- static GTimer AudGTimer;
+ static GTimer PlayTimer;
- static void AudGTimerCallback(void *param) {
+ static void PlayTimerCallback(void *param) {
(void) param;
GSourceListener *psl;
- GEventADC *pe;
+ GEventAudioOut *pe;
psl = 0;
while ((psl = geventGetSourceListener((GSourceHandle)(&aud), psl))) {
- if (!(pe = (GEventAudioIn *)geventGetEventBuffer(psl))) {
+ if (!(pe = (GEventAudioOut *)geventGetEventBuffer(psl))) {
// This listener is missing - save this.
- psl->srcflags |= GAUDIN_LOSTEVENT;
+ psl->srcflags |= GAUDOUT_LOSTEVENT;
continue;
}
- pe->type = GEVENT_AUDIO_IN;
- pe->channel = aud.channel;
- pe->count = lastcount;
- pe->buffer = lastbuffer;
+ pe->type = GEVENT_AUDIO_OUT;
pe->flags = psl->srcflags;
psl->srcflags = 0;
+ if ((PlayFlags & PLAYFLG_PLAYING))
+ pe->flags |= GAUDOUT_PLAYING;
+ if (!gfxQueueGSyncIsEmpty(&freelist))
+ pe->flags |= GAUDOUT_FREEBLOCK;
geventSendEvent(psl);
}
}
@@ -57,11 +58,17 @@ void _gaudoutInit(void)
{
gfxQueueASyncInit(&playlist);
gfxQueueGSyncInit(&freelist);
+ #if GFX_USE_GEVENT
+ gtimerInit(&PlayTimer);
+ #endif
}
void _gaudoutDeinit(void)
{
/* ToDo */
+ #if GFX_USE_GEVENT
+ gtimerDeinit(&PlayTimer);
+ #endif
}
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) {
if (paud)
gfxQueueASyncPut(&playlist, (gfxQueueASyncItem *)paud);
+ PlayFlags |= PLAYFLG_PLAYING;
gaudout_lld_start();
}
@@ -116,12 +124,22 @@ void gaudioPlayStop(void) {
gaudout_lld_stop();
while((paud = (GAudioData *)gfxQueueASyncGet(&playlist)))
gfxQueueGSyncPut(&freelist, (gfxQueueGSyncItem *)paud);
+ PlayFlags &= ~PLAYFLG_PLAYING;
}
bool_t gaudioPlaySetVolume(uint8_t 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.
*/
@@ -132,8 +150,19 @@ GAudioData *gaudoutGetDataBlockI(void) {
void gaudoutReleaseDataBlockI(GAudioData *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 */
/** @} */
diff --git a/src/gaudout/sys_defs.h b/src/gaudout/sys_defs.h
index 4f09678b..75cda243 100644
--- a/src/gaudout/sys_defs.h
+++ b/src/gaudout/sys_defs.h
@@ -42,6 +42,36 @@ typedef struct GAudioData {
size_t len; // @< The length of the data in the buffer area (in bytes)
} 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. */
/*===========================================================================*/
@@ -96,6 +126,8 @@ void gaudioReleaseBuffer(GAudioData *paud);
*
* @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.
+ * @note Only one channel can be playing at a time. Calling this will stop any
+ * currently playing channel.
*
* @api
*/
@@ -155,6 +187,25 @@ void gaudioPlayStop(void);
*/
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
}
#endif