A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 299 lines 6.9 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 Björn Stenberg 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 2 15 * of the License, or (at your option) any later version. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "config.h" 22 23#include <stdbool.h> 24#include <string.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <timefuncs.h> 28#include <ctype.h> 29#include <stdarg.h> 30#include "string-extra.h" 31#include "load_code.h" 32#include "debug.h" 33#include "button.h" 34#include "dir.h" 35#include "file.h" 36#include "kernel.h" 37#include "screens.h" 38#include "misc.h" 39#include "codecs.h" 40#include "lang.h" 41#include "keyboard.h" 42#include "buffering.h" 43#include "backlight.h" 44#include "storage.h" 45#include "talk.h" 46#include "mp3data.h" 47#include "powermgmt.h" 48#include "system.h" 49#include "sound.h" 50#include "splash.h" 51#include "general.h" 52#include "rbpaths.h" 53 54#define LOGF_ENABLE 55#include "logf.h" 56 57#if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) 58#define PREFIX(_x_) sim_ ## _x_ 59#else 60#define PREFIX(_x_) _x_ 61#endif 62 63#if (CONFIG_PLATFORM & PLATFORM_HOSTED) 64/* For PLATFORM_HOSTED this buffer must be define here. */ 65static unsigned char codecbuf[CODEC_SIZE]; 66#else 67/* For PLATFORM_NATIVE this buffer is defined in *.lds files. */ 68extern unsigned char codecbuf[]; 69#endif 70 71static size_t codec_size; 72 73struct codec_api ci = { 74 75 0, /* filesize */ 76 0, /* curpos */ 77 NULL, /* id3 */ 78 ERR_HANDLE_NOT_FOUND, /* audio_hid */ 79 NULL, /* struct dsp_config *dsp */ 80 NULL, /* codec_get_buffer */ 81 NULL, /* pcmbuf_insert */ 82 NULL, /* set_elapsed */ 83 NULL, /* read_filebuf */ 84 NULL, /* request_buffer */ 85 NULL, /* advance_buffer */ 86 NULL, /* seek_buffer */ 87 NULL, /* seek_complete */ 88 NULL, /* set_offset */ 89 NULL, /* configure */ 90 NULL, /* get_command */ 91 NULL, /* loop_track */ 92 NULL, /* strip_filesize */ 93 94 /* kernel/ system */ 95#if defined(ARM_NEED_DIV0) 96 __div0, 97#endif 98 sleep, 99 yield, 100 101#if NUM_CORES > 1 102 create_thread, 103 thread_thaw, 104 thread_wait, 105 semaphore_init, 106 semaphore_wait, 107 semaphore_release, 108#endif 109 110 commit_dcache, 111 commit_discard_dcache, 112 commit_discard_idcache, 113 114 /* strings and memory */ 115 strcpy, 116 strlen, 117 strcmp, 118 strcat, 119 memset, 120 memcpy, 121 memmove, 122 memcmp, 123 memchr, 124#if defined(DEBUG) || defined(SIMULATOR) 125 debugf, 126#endif 127#ifdef ROCKBOX_HAS_LOGF 128 logf, 129#endif 130 131 (void *)qsort, 132 133#ifdef RB_PROFILE 134 profile_thread, 135 profstop, 136 __cyg_profile_func_enter, 137 __cyg_profile_func_exit, 138#endif 139 140#ifdef HAVE_RECORDING 141 NULL, /* enc_pcmbuf_read */ 142 NULL, /* enc_pcmbuf_advance */ 143 NULL, /* enc_encbuf_get_buffer */ 144 NULL, /* enc_encbuf_finish_buffer */ 145 NULL, /* enc_stream_read */ 146 NULL, /* enc_stream_lseek */ 147 NULL, /* enc_stream_write */ 148 round_value_to_list32, 149#endif /* HAVE_RECORDING */ 150 151 /* new stuff at the end, sort into place next time 152 the API gets incompatible */ 153 154}; 155 156void codec_get_full_path(char *path, const char *codec_root_fn) 157{ 158 snprintf(path, MAX_PATH-1, CODECS_DIR "/" CODEC_PREFIX "%s." 159 CODEC_EXTENSION, codec_root_fn); 160} 161 162/* Returns pointer to and size of free codec RAM. Aligns to CACHEALIGN_SIZE. */ 163void *codec_get_buffer_callback(size_t *size) 164{ 165 void *buf = &codecbuf[codec_size]; 166 ssize_t s = CODEC_SIZE - codec_size; 167 168 if (s <= 0) 169 return NULL; 170 171 *size = s; 172 ALIGN_BUFFER(buf, *size, CACHEALIGN_SIZE); 173 174 return buf; 175} 176 177/** codec loading and call interface **/ 178static void *curr_handle = NULL; 179static struct codec_header *c_hdr = NULL; 180 181static int codec_load_ram(struct codec_api *api) 182{ 183 struct lc_header *hdr; 184 185 c_hdr = lc_get_header(curr_handle); 186 hdr = c_hdr ? &c_hdr->lc_hdr : NULL; 187 188 if (hdr == NULL 189 || (hdr->magic != CODEC_MAGIC 190#ifdef HAVE_RECORDING 191 && hdr->magic != CODEC_ENC_MAGIC 192#endif 193 ) 194 || hdr->target_id != TARGET_ID 195#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 196 || hdr->load_addr != codecbuf 197 || hdr->end_addr > codecbuf + CODEC_SIZE 198#endif 199 ) 200 { 201 logf("codec header error"); 202 lc_close(curr_handle); 203 curr_handle = NULL; 204 return CODEC_ERROR; 205 } 206 207 if (hdr->api_version != CODEC_API_VERSION || 208 c_hdr->api_size > sizeof(struct codec_api)) 209 { 210 logf("codec api version error"); 211 lc_close(curr_handle); 212 curr_handle = NULL; 213 return CODEC_ERROR; 214 } 215 216#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 217 codec_size = hdr->end_addr - codecbuf; 218#else 219 codec_size = 0; 220#endif 221 222 *(c_hdr->api) = api; 223 224 logf("Codec: calling entrypoint"); 225 return c_hdr->entry_point(CODEC_LOAD); 226} 227 228int codec_load_buf(int hid, struct codec_api *api) 229{ 230 int rc = bufread(hid, CODEC_SIZE, codecbuf); 231 232 if (rc < 0) { 233 logf("Codec: cannot read buf handle"); 234 return CODEC_ERROR; 235 } 236 237 curr_handle = lc_open_from_mem(codecbuf, rc); 238 239 if (curr_handle == NULL) { 240 logf("Codec: load error"); 241 return CODEC_ERROR; 242 } 243 244 return codec_load_ram(api); 245} 246 247int codec_load_file(const char *plugin, struct codec_api *api) 248{ 249 char path[MAX_PATH]; 250 251 codec_get_full_path(path, plugin); 252 253 curr_handle = lc_open(path, codecbuf, CODEC_SIZE); 254 255 if (curr_handle == NULL) { 256 logf("Codec: cannot read file"); 257 return CODEC_ERROR; 258 } 259 260 return codec_load_ram(api); 261} 262 263int codec_run_proc(void) 264{ 265 if (curr_handle == NULL) { 266 logf("Codec: no codec to run"); 267 return CODEC_ERROR; 268 } 269 270 logf("Codec: entering run state"); 271 return c_hdr->run_proc(); 272} 273 274int codec_close(void) 275{ 276 int status = CODEC_OK; 277 278 if (curr_handle != NULL) { 279 logf("Codec: cleaning up"); 280 status = c_hdr->entry_point(CODEC_UNLOAD); 281 lc_close(curr_handle); 282 curr_handle = NULL; 283 } 284 285 return status; 286} 287 288#ifdef HAVE_RECORDING 289enc_callback_t codec_get_enc_callback(void) 290{ 291 if (curr_handle == NULL || 292 c_hdr->lc_hdr.magic != CODEC_ENC_MAGIC) { 293 logf("Codec: not an encoder"); 294 return NULL; 295 } 296 297 return c_hdr->rec_extension[0]; 298} 299#endif /* HAVE_RECORDING */