aboutsummaryrefslogtreecommitdiffstats
path: root/src/gaudio/gaudio_gaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gaudio/gaudio_gaudio.c')
-rw-r--r--src/gaudio/gaudio_gaudio.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/src/gaudio/gaudio_gaudio.c b/src/gaudio/gaudio_gaudio.c
new file mode 100644
index 00000000..bb12e6d2
--- /dev/null
+++ b/src/gaudio/gaudio_gaudio.c
@@ -0,0 +1,283 @@
+/*
+ * This file is subject to the terms of the GFX License. If a copy of
+ * the license was not distributed with this file, you can obtain one at:
+ *
+ * http://ugfx.org/license.html
+ */
+
+/**
+ * @file src/gaudio/gaudio_gaudio.c
+ * @brief GAUDIO sub-system code.
+ *
+ * @addtogroup GAUDIO
+ * @{
+ */
+#include "gfx.h"
+
+#if GFX_USE_GAUDIO
+
+#if GAUDIO_NEED_PLAY
+ #include "driver_play.h"
+
+ static gfxQueueASync playList;
+ static gfxSem playComplete;
+ static uint16_t playFlags;
+ #define PLAYFLG_USEEVENTS 0x0001
+ #define PLAYFLG_PLAYING 0x0002
+ #define PLAYFLG_ISINIT 0x0004
+ #if GFX_USE_GEVENT
+ static GTimer playTimer;
+ static void PlayTimerCallback(void *param);
+ #endif
+#endif
+
+#if GAUDIO_NEED_RECORD
+ #include "driver_record.h"
+
+ static gfxQueueGSync recordList;
+ static uint16_t recordFlags;
+ #define RECORDFLG_USEEVENTS 0x0001
+ #define RECORDFLG_RECORDING 0x0002
+ #define RECORDFLG_STALLED 0x0004
+ #define RECORDFLG_ISINIT 0x0008
+ #if GFX_USE_GEVENT
+ static GTimer recordTimer;
+ static void RecordTimerCallback(void *param);
+ #endif
+#endif
+
+
+void _gaudioInit(void)
+{
+ #if GAUDIO_NEED_PLAY
+ gfxQueueASyncInit(&playList);
+ #if GFX_USE_GEVENT
+ gtimerInit(&playTimer);
+ #endif
+ gfxSemInit(&playComplete, 0, 0);
+ #endif
+ #if GAUDIO_NEED_RECORD
+ gfxQueueGSyncInit(&recordList);
+ #if GFX_USE_GEVENT
+ gtimerInit(&recordTimer);
+ #endif
+ #endif
+}
+
+void _gaudioDeinit(void)
+{
+ #if GAUDIO_NEED_PLAY
+ gfxQueueASyncDeinit(&playList);
+ #if GFX_USE_GEVENT
+ gtimerDeinit(&playTimer);
+ #endif
+ gfxSemDestroy(&playComplete);
+ #endif
+ #if GAUDIO_NEED_RECORD
+ gfxQueueGSyncDeinit(&recordList);
+ #if GFX_USE_GEVENT
+ gtimerDeinit(&recordTimer);
+ #endif
+ #endif
+}
+
+#if GAUDIO_NEED_PLAY
+
+ bool_t gaudioPlayInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ gaudioPlayStop();
+ playFlags &= ~PLAYFLG_ISINIT;
+ if (!gaudio_play_lld_init(channel, frequency, format))
+ return FALSE;
+ playFlags |= PLAYFLG_ISINIT;
+ return TRUE;
+ }
+
+ void gaudioPlay(GDataBuffer *pd) {
+ if (!(playFlags & PLAYFLG_ISINIT)) {
+ // Oops - init failed - return it directly to the free-list
+ if (pd) {
+ gfxBufferRelease(pd);
+ gfxYield(); // Make sure we get no endless cpu hogging loops
+ }
+ return;
+ }
+
+ if (pd)
+ gfxQueueASyncPut(&playList, (gfxQueueASyncItem *)pd);
+ playFlags |= PLAYFLG_PLAYING;
+ gaudio_play_lld_start();
+ }
+
+ void gaudioPlayPause(void) {
+ if ((playFlags & (PLAYFLG_ISINIT|PLAYFLG_PLAYING)) == (PLAYFLG_ISINIT|PLAYFLG_PLAYING))
+ gaudio_play_lld_stop();
+ }
+
+ void gaudioPlayStop(void) {
+ GDataBuffer *pd;
+
+ if (playFlags & PLAYFLG_PLAYING)
+ gaudio_play_lld_stop();
+ while((pd = (GDataBuffer *)gfxQueueASyncGet(&playList)))
+ gfxBufferRelease(pd);
+ }
+
+ bool_t gaudioPlaySetVolume(uint8_t vol) {
+ return gaudio_play_lld_set_volume(vol);
+ }
+
+ bool_t gaudioPlayWait(delaytime_t ms) {
+ if (!(playFlags & PLAYFLG_PLAYING))
+ return TRUE;
+ return gfxSemWait(&playComplete, ms);
+ }
+
+ #if GFX_USE_GEVENT
+ static void PlayTimerCallback(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventAudioPlay *pe;
+
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)&playTimer, psl))) {
+ if (!(pe = (GEventAudioPlay *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save this.
+ psl->srcflags |= GAUDIO_PLAY_LOSTEVENT;
+ continue;
+ }
+
+ pe->type = GEVENT_AUDIO_PLAY;
+ pe->flags = psl->srcflags;
+ psl->srcflags = 0;
+ if ((playFlags & PLAYFLG_PLAYING))
+ pe->flags |= GAUDIO_PLAY_PLAYING;
+ if (gfxBufferIsAvailable())
+ pe->flags |= GAUDIO_PLAY_FREEBLOCK;
+ geventSendEvent(psl);
+ }
+ }
+
+ GSourceHandle gaudioPlayGetSource(void) {
+ if (!gtimerIsActive(&playTimer))
+ gtimerStart(&playTimer, PlayTimerCallback, 0, TRUE, TIME_INFINITE);
+ playFlags |= PLAYFLG_USEEVENTS;
+ return (GSourceHandle)&playTimer;
+ }
+ #endif
+
+ /**
+ * Routines provided for use by drivers.
+ */
+
+ GDataBuffer *gaudioPlayGetDataBlockI(void) {
+ return (GDataBuffer *)gfxQueueASyncGetI(&playList);
+ }
+
+ void gaudioPlayReleaseDataBlockI(GDataBuffer *pd) {
+ gfxBufferReleaseI(pd);
+ #if GFX_USE_GEVENT
+ if (playFlags & PLAYFLG_USEEVENTS)
+ gtimerJabI(&playTimer);
+ #endif
+ }
+
+ void gaudioPlayDoneI(void) {
+ playFlags &= ~PLAYFLG_PLAYING;
+ #if GFX_USE_GEVENT
+ if (playFlags & PLAYFLG_USEEVENTS)
+ gtimerJabI(&playTimer);
+ #endif
+ gfxSemSignalI(&playComplete); // This should really be gfxSemSignalAllI(&playComplete);
+ }
+#endif
+
+#if GAUDIO_NEED_RECORD
+ bool_t gaudioRecordInit(uint16_t channel, uint32_t frequency, ArrayDataFormat format) {
+ gaudioRecordStop();
+ recordFlags &= ~RECORDFLG_ISINIT;
+ if (!gaudio_record_lld_init(channel, frequency, format))
+ return FALSE;
+ recordFlags |= RECORDFLG_ISINIT;
+ return TRUE;
+ }
+
+ void gaudioRecordStart(void) {
+ if (!(recordFlags & RECORDFLG_ISINIT))
+ return; // Oops - init failed
+
+ recordFlags |= RECORDFLG_RECORDING;
+ recordFlags &= ~RECORDFLG_STALLED;
+ gaudio_record_lld_start();
+ }
+
+ void gaudioRecordStop(void) {
+ GDataBuffer *pd;
+
+ if ((recordFlags & (RECORDFLG_RECORDING|RECORDFLG_STALLED)) == RECORDFLG_RECORDING)
+ gaudio_record_lld_stop();
+ recordFlags &= ~(RECORDFLG_RECORDING|RECORDFLG_STALLED);
+ while((pd = (GDataBuffer *)gfxQueueGSyncGet(&recordList, TIME_IMMEDIATE)))
+ gfxBufferRelease(pd);
+ }
+
+ GDataBuffer *gaudioRecordGetData(delaytime_t ms) {
+ return (GDataBuffer *)gfxQueueGSyncGet(&recordList, ms);
+ }
+
+ #if GFX_USE_GEVENT
+ static void RecordTimerCallback(void *param) {
+ (void) param;
+ GSourceListener *psl;
+ GEventAudioRecord *pe;
+
+ psl = 0;
+ while ((psl = geventGetSourceListener((GSourceHandle)&recordTimer, psl))) {
+ if (!(pe = (GEventAudioRecord *)geventGetEventBuffer(psl))) {
+ // This listener is missing - save this.
+ psl->srcflags |= GAUDIO_RECORD_LOSTEVENT;
+ continue;
+ }
+ pe->type = GEVENT_AUDIO_RECORD;
+ pe->flags = psl->srcflags;
+ psl->srcflags = 0;
+ if ((recordFlags & RECORDFLG_RECORDING))
+ pe->flags |= GAUDIO_RECORD_RECORDING;
+ if ((recordFlags & RECORDFLG_STALLED))
+ pe->flags |= GAUDIO_RECORD_STALL;
+ if (!gfxQueueGSyncIsEmpty(&recordList))
+ pe->flags |= GAUDIO_RECORD_GOTBUFFER;
+ geventSendEvent(psl);
+ }
+ }
+
+ GSourceHandle gaudioRecordGetSource(void) {
+ if (!gtimerIsActive(&recordTimer))
+ gtimerStart(&recordTimer, RecordTimerCallback, 0, TRUE, TIME_INFINITE);
+ recordFlags |= RECORDFLG_USEEVENTS;
+ return (GSourceHandle)&recordTimer;
+ }
+ #endif
+
+ /**
+ * Routines provided for use by drivers.
+ */
+
+ void gaudioRecordSaveDataBlockI(GDataBuffer *paud) {
+ gfxQueueGSyncPutI(&recordList, (gfxQueueGSyncItem *)paud);
+ #if GFX_USE_GEVENT
+ if (recordFlags & RECORDFLG_USEEVENTS)
+ gtimerJabI(&recordTimer);
+ #endif
+ }
+
+ void gaudioRecordDoneI(void) {
+ recordFlags |= RECORDFLG_STALLED;
+ #if GFX_USE_GEVENT
+ if (recordFlags & RECORDFLG_USEEVENTS)
+ gtimerJabI(&recordTimer);
+ #endif
+ }
+#endif
+
+#endif /* GFX_USE_GAUDIO */
+/** @} */