A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
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 */