summaryrefslogtreecommitdiffstats
path: root/apps/audio_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/audio_thread.c')
-rw-r--r--apps/audio_thread.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/apps/audio_thread.c b/apps/audio_thread.c
new file mode 100644
index 0000000000..2f01f7a8c2
--- /dev/null
+++ b/apps/audio_thread.c
@@ -0,0 +1,162 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005-2007 Miika Pekkarinen
+ * Copyright (C) 2007-2008 Nicolas Pennequin
+ * Copyright (C) 2011-2013 Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include "kernel.h"
+#include "logf.h"
+#include "usb.h"
+#include "pcm.h"
+#include "sound.h"
+#include "audio_thread.h"
+#ifdef AUDIO_HAVE_RECORDING
+#include "pcm_record.h"
+#endif
+#include "codec_thread.h"
+#include "voice_thread.h"
+#include "talk.h"
+#include "settings.h"
+
+/* Macros to enable logf for queues
+ logging on SYS_TIMEOUT can be disabled */
+#ifdef SIMULATOR
+/* Define this for logf output of all queuing except SYS_TIMEOUT */
+#define AUDIO_LOGQUEUES
+/* Define this to logf SYS_TIMEOUT messages */
+/*#define AUDIO_LOGQUEUES_SYS_TIMEOUT*/
+#endif
+
+#ifdef AUDIO_LOGQUEUES
+#define LOGFQUEUE logf
+#else
+#define LOGFQUEUE(...)
+#endif
+
+bool audio_is_initialized = false;
+
+/* Event queues */
+struct event_queue audio_queue SHAREDBSS_ATTR;
+static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
+
+/* Audio thread */
+static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
+static const char audio_thread_name[] = "audio";
+unsigned int audio_thread_id = 0;
+
+static void NORETURN_ATTR audio_thread(void)
+{
+ struct queue_event ev;
+ ev.id = SYS_TIMEOUT; /* something not in switch below */
+
+ pcm_postinit();
+
+ while (1)
+ {
+ switch (ev.id)
+ {
+ /* Starts the playback engine branch */
+ case Q_AUDIO_PLAY:
+ LOGFQUEUE("audio < Q_AUDIO_PLAY");
+ audio_playback_handler(&ev);
+ continue;
+
+#ifdef AUDIO_HAVE_RECORDING
+ /* Starts the recording engine branch */
+ case Q_AUDIO_INIT_RECORDING:
+ LOGFQUEUE("audio < Q_AUDIO_INIT_RECORDING");
+ audio_recording_handler(&ev);
+ continue;
+#endif
+
+ /* All return upon USB */
+ case SYS_USB_CONNECTED:
+ LOGFQUEUE("audio < SYS_USB_CONNECTED");
+ voice_stop();
+ usb_acknowledge(SYS_USB_CONNECTED_ACK);
+ usb_wait_for_disconnect(&audio_queue);
+ break;
+ }
+
+ queue_wait(&audio_queue, &ev);
+ }
+}
+
+/* Return the playback and recording status */
+int audio_status(void)
+{
+ return playback_status()
+#ifdef AUDIO_HAVE_RECORDING
+ | pcm_rec_status()
+#endif
+ ;
+}
+
+/* Clear all accumulated audio errors for playback and recording */
+void audio_error_clear(void)
+{
+#ifdef AUDIO_HAVE_RECORDING
+ pcm_rec_error_clear();
+#endif
+}
+
+/** -- Startup -- **/
+
+/* Initialize the audio system - called from init() in main.c */
+void audio_init(void)
+{
+ /* Can never do this twice */
+ if (audio_is_initialized)
+ {
+ logf("audio: already initialized");
+ return;
+ }
+
+ logf("audio: initializing");
+
+ playback_init();
+
+ /* Recording doesn't need init call */
+
+ /* Initialize queues before giving control elsewhere in case it likes
+ to send messages. Thread creation will be delayed however so nothing
+ starts running until ready if something yields such as talk_init. */
+ queue_init(&audio_queue, true);
+ codec_thread_init();
+
+ /* This thread does buffer, so match its priority */
+ audio_thread_id = create_thread(audio_thread, audio_stack,
+ sizeof(audio_stack), 0, audio_thread_name
+ IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE))
+ IF_COP(, CPU));
+
+ queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
+ audio_thread_id);
+
+ /* ...now...audio_reset_buffer must know the size of voicefile buffer so
+ init talk first which will init the buffers */
+ talk_init();
+
+ /* Probably safe to say */
+ audio_is_initialized = true;
+
+ sound_settings_apply();
+}