summaryrefslogtreecommitdiff
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005-2007 Miika Pekkarinen
11 * Copyright (C) 2007-2008 Nicolas Pennequin
12 * Copyright (C) 2011-2013 Michael Sevakis
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23#include "config.h"
24#include "system.h"
25#include "kernel.h"
26#include "logf.h"
27#include "usb.h"
28#include "pcm.h"
29#include "sound.h"
30#include "audio_thread.h"
31#ifdef AUDIO_HAVE_RECORDING
32#include "pcm_record.h"
33#endif
34#include "codec_thread.h"
35#include "voice_thread.h"
36#include "talk.h"
37#include "settings.h"
38
39/* Macros to enable logf for queues
40 logging on SYS_TIMEOUT can be disabled */
41#ifdef SIMULATOR
42/* Define this for logf output of all queuing except SYS_TIMEOUT */
43#define AUDIO_LOGQUEUES
44/* Define this to logf SYS_TIMEOUT messages */
45/*#define AUDIO_LOGQUEUES_SYS_TIMEOUT*/
46#endif
47
48#ifdef AUDIO_LOGQUEUES
49#define LOGFQUEUE logf
50#else
51#define LOGFQUEUE(...)
52#endif
53
54bool audio_is_initialized = false;
55
56/* Event queues */
57struct event_queue audio_queue SHAREDBSS_ATTR;
58static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
59
60/* Audio thread */
61static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
62static const char audio_thread_name[] = "audio";
63unsigned int audio_thread_id = 0;
64
65static void NORETURN_ATTR audio_thread(void)
66{
67 struct queue_event ev;
68 ev.id = SYS_TIMEOUT; /* something not in switch below */
69
70 pcm_postinit();
71
72 while (1)
73 {
74 switch (ev.id)
75 {
76 /* Starts the playback engine branch */
77 case Q_AUDIO_PLAY:
78 LOGFQUEUE("audio < Q_AUDIO_PLAY");
79 audio_playback_handler(&ev);
80 continue;
81
82#ifdef AUDIO_HAVE_RECORDING
83 /* Starts the recording engine branch */
84 case Q_AUDIO_INIT_RECORDING:
85 LOGFQUEUE("audio < Q_AUDIO_INIT_RECORDING");
86 audio_recording_handler(&ev);
87 continue;
88#endif
89
90 /* All return upon USB */
91 case SYS_USB_CONNECTED:
92 LOGFQUEUE("audio < SYS_USB_CONNECTED");
93 voice_stop();
94 usb_acknowledge(SYS_USB_CONNECTED_ACK);
95 usb_wait_for_disconnect(&audio_queue);
96 break;
97 }
98
99 queue_wait(&audio_queue, &ev);
100 }
101}
102
103/* Return the playback and recording status */
104int audio_status(void)
105{
106 return playback_status()
107#ifdef AUDIO_HAVE_RECORDING
108 | pcm_rec_status()
109#endif
110 ;
111}
112
113/* Clear all accumulated audio errors for playback and recording */
114void audio_error_clear(void)
115{
116#ifdef AUDIO_HAVE_RECORDING
117 pcm_rec_error_clear();
118#endif
119}
120
121/** -- Startup -- **/
122
123/* Initialize the audio system - called from init() in main.c */
124void audio_init(void)
125{
126 /* Can never do this twice */
127 if (audio_is_initialized)
128 {
129 logf("audio: already initialized");
130 return;
131 }
132
133 logf("audio: initializing");
134
135 playback_init();
136
137 /* Recording doesn't need init call */
138
139 /* Initialize queues before giving control elsewhere in case it likes
140 to send messages. Thread creation will be delayed however so nothing
141 starts running until ready if something yields such as talk_init. */
142 queue_init(&audio_queue, true);
143 codec_thread_init();
144
145 /* This thread does buffer, so match its priority */
146 audio_thread_id = create_thread(audio_thread, audio_stack,
147 sizeof(audio_stack), 0, audio_thread_name
148 IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE))
149 IF_COP(, CPU));
150
151 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
152 audio_thread_id);
153
154 /* ...now...audio_reset_buffer must know the size of voicefile buffer so
155 init talk first which will init the buffers */
156 talk_init();
157
158 /* Probably safe to say */
159 audio_is_initialized = true;
160
161 sound_settings_apply();
162}