A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 188 lines 5.2 kB view raw
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 "pcmbuf.h" 31#include "appevents.h" 32#include "audio_thread.h" 33#ifdef AUDIO_HAVE_RECORDING 34#include "pcm_record.h" 35#endif 36#include "codec_thread.h" 37#include "voice_thread.h" 38#include "talk.h" 39#include "settings.h" 40 41/* Macros to enable logf for queues 42 logging on SYS_TIMEOUT can be disabled */ 43#ifdef SIMULATOR 44/* Define this for logf output of all queuing except SYS_TIMEOUT */ 45#define AUDIO_LOGQUEUES 46/* Define this to logf SYS_TIMEOUT messages */ 47/*#define AUDIO_LOGQUEUES_SYS_TIMEOUT*/ 48#endif 49 50#ifdef AUDIO_LOGQUEUES 51#define LOGFQUEUE logf 52#else 53#define LOGFQUEUE(...) 54#endif 55 56bool audio_is_initialized = false; 57 58/* Event queues */ 59struct event_queue audio_queue SHAREDBSS_ATTR; 60static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR; 61 62/* Audio thread */ 63static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; 64static const char audio_thread_name[] = "audio"; 65unsigned int audio_thread_id = 0; 66 67static void NORETURN_ATTR audio_thread(void) 68{ 69 struct queue_event ev; 70 ev.id = Q_NULL; /* something not in switch below */ 71 72 pcm_postinit(); 73 74 while (1) 75 { 76 switch (ev.id) 77 { 78 /* Starts the playback engine branch */ 79 case Q_AUDIO_PLAY: 80 LOGFQUEUE("audio < Q_AUDIO_PLAY"); 81 audio_playback_handler(&ev); 82 continue; 83 84 /* Playback has to handle these, even if not playing */ 85 case Q_AUDIO_REMAKE_AUDIO_BUFFER: 86#ifdef HAVE_DISK_STORAGE 87 case Q_AUDIO_UPDATE_WATERMARK: 88#endif 89 audio_playback_handler(&ev); 90 break; 91 92#ifdef AUDIO_HAVE_RECORDING 93 /* Starts the recording engine branch */ 94 case Q_AUDIO_INIT_RECORDING: 95 LOGFQUEUE("audio < Q_AUDIO_INIT_RECORDING"); 96 audio_recording_handler(&ev); 97 continue; 98#endif 99 100 /* All return upon USB */ 101 case SYS_USB_CONNECTED: 102 LOGFQUEUE("audio < SYS_USB_CONNECTED"); 103 voice_stop(); 104 usb_acknowledge(SYS_USB_CONNECTED_ACK); 105 usb_wait_for_disconnect(&audio_queue); 106 break; 107 } 108 109 queue_wait(&audio_queue, &ev); 110 } 111} 112 113void audio_voice_event(unsigned short id, void *data) 114{ 115 (void)id; 116 /* Make audio play softly while voice is speaking */ 117 pcmbuf_soft_mode(*(bool *)data); 118} 119 120void audio_queue_post(long id, intptr_t data) 121{ 122 queue_post(&audio_queue, id, data); 123} 124 125intptr_t audio_queue_send(long id, intptr_t data) 126{ 127 return queue_send(&audio_queue, id, data); 128} 129 130/* Return the playback and recording status */ 131int audio_status(void) 132{ 133 return playback_status() 134#ifdef AUDIO_HAVE_RECORDING 135 | pcm_rec_status() 136#endif 137 ; 138} 139 140/* Clear all accumulated audio errors for playback and recording */ 141void audio_error_clear(void) 142{ 143#ifdef AUDIO_HAVE_RECORDING 144 pcm_rec_error_clear(); 145#endif 146} 147 148/** -- Startup -- **/ 149 150/* Initialize the audio system - called from init() in main.c */ 151void INIT_ATTR audio_init(void) 152{ 153 /* Can never do this twice */ 154 if (audio_is_initialized) 155 { 156 logf("audio: already initialized"); 157 return; 158 } 159 160 logf("audio: initializing"); 161 162 /* Initialize queues before giving control elsewhere in case it likes 163 to send messages. Thread creation will be delayed however so nothing 164 starts running until ready if something yields such as talk_init. */ 165 queue_init(&audio_queue, true); 166 codec_thread_init(); 167 168 /* This thread does buffer, so match its priority */ 169 audio_thread_id = create_thread(audio_thread, audio_stack, 170 sizeof(audio_stack), 0, audio_thread_name 171 IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE)) 172 IF_COP(, CPU)); 173 174 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list, 175 audio_thread_id); 176 177 playback_init(); 178#ifdef AUDIO_HAVE_RECORDING 179 recording_init(); 180#endif 181 182 add_event(VOICE_EVENT_IS_PLAYING, audio_voice_event); 183 184 /* Probably safe to say */ 185 audio_is_initialized = true; 186 187 sound_settings_apply(); 188}