Enable replaygain for the new FLAC decoder
[Rockbox.git] / apps / plugin.c
blob59c90a2a974b247811a7517e4a9bda8e792e2f33
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdbool.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <atoi.h>
23 #include <timefuncs.h>
24 #include <ctype.h>
25 #include "debug.h"
26 #include "button.h"
27 #include "lcd.h"
28 #include "dir.h"
29 #include "file.h"
30 #include "kernel.h"
31 #include "sprintf.h"
32 #include "logf.h"
33 #include "screens.h"
34 #include "misc.h"
35 #include "mas.h"
36 #include "plugin.h"
37 #include "lang.h"
38 #include "keyboard.h"
39 #include "mpeg.h"
40 #include "buffer.h"
41 #include "mp3_playback.h"
42 #include "backlight.h"
43 #include "ata.h"
44 #include "talk.h"
45 #include "mp3data.h"
46 #include "powermgmt.h"
47 #include "system.h"
48 #include "timer.h"
49 #include "sound.h"
50 #include "database.h"
51 #if (CONFIG_CODEC == SWCODEC)
52 #include "pcm_playback.h"
53 #endif
55 #ifdef HAVE_LCD_BITMAP
56 #include "peakmeter.h"
57 #include "widgets.h"
58 #include "bmp.h"
59 #endif
61 #ifdef HAVE_REMOTE_LCD
62 #include "lcd-remote.h"
63 #endif
65 #ifdef SIMULATOR
66 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
67 void *sim_plugin_load(char *plugin, int *fd);
68 void sim_plugin_close(int fd);
69 #else
70 #define sim_plugin_close(x)
71 extern unsigned char pluginbuf[];
72 #include "bitswap.h"
73 #endif
75 /* for actual plugins only, not for codecs */
76 static bool plugin_loaded = false;
77 static int plugin_size = 0;
78 static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */
80 static int plugin_test(int api_version, int model, int memsize);
82 static const struct plugin_api rockbox_api = {
83 PLUGIN_API_VERSION,
85 plugin_test,
87 /* lcd */
88 lcd_set_contrast,
89 lcd_clear_display,
90 lcd_puts,
91 lcd_puts_scroll,
92 lcd_stop_scroll,
93 #ifdef HAVE_LCD_CHARCELLS
94 lcd_define_pattern,
95 lcd_get_locked_pattern,
96 lcd_unlock_pattern,
97 lcd_putc,
98 lcd_put_cursor,
99 lcd_remove_cursor,
100 PREFIX(lcd_icon),
101 lcd_double_height,
102 #else
103 #ifndef SIMULATOR
104 lcd_roll,
105 #endif
106 lcd_set_drawmode,
107 lcd_get_drawmode,
108 lcd_setfont,
109 lcd_getstringsize,
110 lcd_drawpixel,
111 lcd_drawline,
112 lcd_hline,
113 lcd_vline,
114 lcd_drawrect,
115 lcd_fillrect,
116 lcd_mono_bitmap_part,
117 lcd_mono_bitmap,
118 #if LCD_DEPTH > 1
119 lcd_set_foreground,
120 lcd_get_foreground,
121 lcd_set_background,
122 lcd_get_background,
123 lcd_bitmap_part,
124 lcd_bitmap,
125 #endif
126 lcd_putsxy,
127 lcd_puts_style,
128 lcd_puts_scroll_style,
129 &lcd_framebuffer[0][0],
130 lcd_blit,
131 lcd_update,
132 lcd_update_rect,
133 scrollbar,
134 checkbox,
135 font_get,
136 font_getstringsize,
137 #endif
138 backlight_on,
139 backlight_off,
140 backlight_set_timeout,
141 splash,
142 #ifdef HAVE_REMOTE_LCD
143 /* remote lcd */
144 lcd_remote_set_contrast,
145 lcd_remote_clear_display,
146 lcd_remote_puts,
147 lcd_remote_puts_scroll,
148 lcd_remote_stop_scroll,
149 #ifndef SIMULATOR
150 lcd_remote_roll,
151 #endif
152 lcd_remote_set_drawmode,
153 lcd_remote_get_drawmode,
154 lcd_remote_setfont,
155 lcd_remote_getstringsize,
156 lcd_remote_drawpixel,
157 lcd_remote_drawline,
158 lcd_remote_hline,
159 lcd_remote_vline,
160 lcd_remote_drawrect,
161 lcd_remote_fillrect,
162 lcd_remote_mono_bitmap_part,
163 lcd_remote_mono_bitmap,
164 lcd_remote_putsxy,
165 lcd_remote_puts_style,
166 lcd_remote_puts_scroll_style,
167 &lcd_remote_framebuffer[0][0],
168 lcd_remote_update,
169 lcd_remote_update_rect,
171 lcd_remote_backlight_on,
172 lcd_remote_backlight_off,
173 #endif
174 /* button */
175 button_get,
176 button_get_w_tmo,
177 button_status,
178 button_clear_queue,
179 #if CONFIG_KEYPAD == IRIVER_H100_PAD
180 button_hold,
181 #endif
183 /* file */
184 (open_func)PREFIX(open),
185 close,
186 (read_func)read,
187 PREFIX(lseek),
188 (creat_func)PREFIX(creat),
189 (write_func)write,
190 PREFIX(remove),
191 PREFIX(rename),
192 PREFIX(ftruncate),
193 PREFIX(filesize),
194 fdprintf,
195 read_line,
196 settings_parseline,
197 #ifndef SIMULATOR
198 ata_sleep,
199 #endif
201 /* dir */
202 PREFIX(opendir),
203 PREFIX(closedir),
204 PREFIX(readdir),
205 PREFIX(mkdir),
207 /* kernel/ system */
208 PREFIX(sleep),
209 yield,
210 &current_tick,
211 default_event_handler,
212 default_event_handler_ex,
213 create_thread,
214 remove_thread,
215 reset_poweroff_timer,
216 #ifndef SIMULATOR
217 system_memory_guard,
218 &cpu_frequency,
219 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
220 cpu_boost,
221 #endif
222 timer_register,
223 timer_unregister,
224 timer_set_period,
225 #endif
227 /* strings and memory */
228 snprintf,
229 strcpy,
230 strncpy,
231 strlen,
232 strrchr,
233 strcmp,
234 strncmp,
235 strcasecmp,
236 strncasecmp,
237 memset,
238 memcpy,
239 _ctype_,
240 atoi,
241 strchr,
242 strcat,
243 memcmp,
244 strcasestr,
246 /* sound */
247 sound_set,
248 #ifndef SIMULATOR
249 mp3_play_data,
250 mp3_play_pause,
251 mp3_play_stop,
252 mp3_is_playing,
253 #if CONFIG_CODEC != SWCODEC
254 bitswap,
255 #endif
256 #if CONFIG_CODEC == SWCODEC
257 pcm_play_data,
258 pcm_play_stop,
259 pcm_set_frequency,
260 pcm_is_playing,
261 pcm_play_pause,
262 #endif
263 #endif
265 /* playback control */
266 PREFIX(audio_play),
267 audio_stop,
268 audio_pause,
269 audio_resume,
270 audio_next,
271 audio_prev,
272 audio_ff_rewind,
273 audio_next_track,
274 playlist_amount,
275 audio_status,
276 audio_has_changed_track,
277 audio_current_track,
278 audio_flush_and_reload_tracks,
279 audio_get_file_pos,
280 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
281 mpeg_get_last_header,
282 #endif
283 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
284 sound_set_pitch,
285 #endif
287 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
288 /* MAS communication */
289 mas_readmem,
290 mas_writemem,
291 mas_readreg,
292 mas_writereg,
293 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
294 mas_codec_writereg,
295 mas_codec_readreg,
296 #endif
297 #endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
299 /* tag database */
300 &tagdbheader,
301 &tagdb_fd,
302 &tagdb_initialized,
303 tagdb_init,
304 /* runtime database */
305 &rundbheader,
306 &rundb_fd,
307 &rundb_initialized,
309 /* misc */
310 srand,
311 rand,
312 (qsort_func)qsort,
313 kbd_input,
314 get_time,
315 set_time,
316 plugin_get_buffer,
317 plugin_get_audio_buffer,
318 plugin_tsr,
319 #if defined(DEBUG) || defined(SIMULATOR)
320 debugf,
321 #endif
322 #ifdef ROCKBOX_HAS_LOGF
323 logf,
324 #endif
325 &global_settings,
326 mp3info,
327 count_mp3_frames,
328 create_xing_header,
329 find_next_frame,
330 battery_level,
331 battery_level_safe,
332 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
333 peak_meter_scale_value,
334 peak_meter_set_use_dbfs,
335 peak_meter_get_use_dbfs,
336 #endif
337 #ifdef HAVE_LCD_BITMAP
338 read_bmp_file,
339 #endif
340 show_logo,
342 /* new stuff at the end, sort into place next time
343 the API gets incompatible */
345 menu_init,
346 menu_exit,
347 menu_show,
348 menu_run,
349 menu_cursor,
350 menu_description,
351 menu_delete,
352 menu_count,
353 menu_moveup,
354 menu_movedown,
355 menu_draw,
356 menu_insert,
357 menu_set_cursor,
359 #ifdef HAVE_LCD_BITMAP
360 screen_dump_set_hook,
361 #endif
364 int plugin_load(const char* plugin, void* parameter)
366 enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);
367 int rc;
368 #ifndef SIMULATOR
369 char buf[64];
370 #endif
371 int fd;
373 #ifdef HAVE_LCD_BITMAP
374 int xm,ym;
375 #endif
377 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
379 pfn_tsr_exit(); /* force it to exit now */
380 pfn_tsr_exit = NULL;
383 #ifdef HAVE_LCD_BITMAP
384 lcd_clear_display();
385 xm = lcd_getxmargin();
386 ym = lcd_getymargin();
387 lcd_setmargins(0,0);
388 lcd_update();
389 #else
390 lcd_clear_display();
391 #endif
392 #ifdef SIMULATOR
393 plugin_start = sim_plugin_load((char *)plugin, &fd);
394 if(!plugin_start)
395 return -1;
396 #else
397 fd = open(plugin, O_RDONLY);
398 if (fd < 0) {
399 snprintf(buf, sizeof buf, str(LANG_PLUGIN_CANT_OPEN), plugin);
400 splash(HZ*2, true, buf);
401 return fd;
404 /* zero out plugin buffer to ensure a properly zeroed bss area */
405 memset(pluginbuf, 0, PLUGIN_BUFFER_SIZE);
407 plugin_start = (void*)&pluginbuf;
408 plugin_size = read(fd, plugin_start, PLUGIN_BUFFER_SIZE);
409 close(fd);
410 if (plugin_size < 0) {
411 /* read error */
412 snprintf(buf, sizeof buf, str(LANG_READ_FAILED), plugin);
413 splash(HZ*2, true, buf);
414 return -1;
416 if (plugin_size == 0) {
417 /* loaded a 0-byte plugin, implying it's not for this model */
418 splash(HZ*2, true, str(LANG_PLUGIN_WRONG_MODEL));
419 return -1;
421 #endif
423 plugin_loaded = true;
425 invalidate_icache();
427 rc = plugin_start((struct plugin_api*) &rockbox_api, parameter);
428 /* explicitly casting the pointer here to avoid touching every plugin. */
430 button_clear_queue();
431 #ifdef HAVE_LCD_BITMAP
432 #if LCD_DEPTH > 1
433 lcd_set_drawinfo(DRMODE_SOLID, LCD_BLACK, LCD_WHITE);
434 #else /* LCD_DEPTH == 1 */
435 lcd_set_drawmode(DRMODE_SOLID);
436 #endif /* LCD_DEPTH */
437 #endif /* HAVE_LCD_BITMAP */
439 plugin_loaded = false;
441 switch (rc) {
442 case PLUGIN_OK:
443 break;
445 case PLUGIN_USB_CONNECTED:
446 return PLUGIN_USB_CONNECTED;
448 case PLUGIN_WRONG_API_VERSION:
449 splash(HZ*2, true, str(LANG_PLUGIN_WRONG_VERSION));
450 break;
452 case PLUGIN_WRONG_MODEL:
453 splash(HZ*2, true, str(LANG_PLUGIN_WRONG_MODEL));
454 break;
456 default:
457 splash(HZ*2, true, str(LANG_PLUGIN_ERROR));
458 break;
461 sim_plugin_close(fd);
463 #ifdef HAVE_LCD_BITMAP
464 /* restore margins */
465 lcd_setmargins(xm,ym);
466 #endif
468 return PLUGIN_OK;
471 /* Returns a pointer to the portion of the plugin buffer that is not already
472 being used. If no plugin is loaded, returns the entire plugin buffer */
473 void* plugin_get_buffer(int* buffer_size)
475 int buffer_pos;
477 if (plugin_loaded)
479 if (plugin_size >= PLUGIN_BUFFER_SIZE)
480 return NULL;
482 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
483 buffer_pos = plugin_size;
485 else
487 *buffer_size = PLUGIN_BUFFER_SIZE;
488 buffer_pos = 0;
491 return &pluginbuf[buffer_pos];
494 /* Returns a pointer to the mp3 buffer.
495 Playback gets stopped, to avoid conflicts. */
496 void* plugin_get_audio_buffer(int* buffer_size)
498 audio_stop();
499 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
500 *buffer_size = audiobufend - audiobuf;
501 return audiobuf;
504 /* The plugin wants to stay resident after leaving its main function, e.g.
505 runs from timer or own thread. The callback is registered to later
506 instruct it to free its resources before a new plugin gets loaded. */
507 void plugin_tsr(void (*exit_callback)(void))
509 pfn_tsr_exit = exit_callback; /* remember the callback for later */
513 static int plugin_test(int api_version, int model, int memsize)
515 if (api_version < PLUGIN_MIN_API_VERSION ||
516 api_version > PLUGIN_API_VERSION)
517 return PLUGIN_WRONG_API_VERSION;
519 if (model != MODEL)
520 return PLUGIN_WRONG_MODEL;
522 if (memsize != MEM)
523 return PLUGIN_WRONG_MODEL;
525 return PLUGIN_OK;