Fix radio screen, and use the actual card type name for the title in the disk screen...
[Rockbox.git] / apps / plugin.c
blob793114539ec09c5ce15b51efec69ddf481427213
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 "plugin.h"
20 #include <ctype.h>
21 #include <string.h>
22 #include <sprintf.h>
23 #include <atoi.h>
24 #include "debug.h"
25 #include "i2c.h"
26 #include "lang.h"
27 #include "keyboard.h"
28 #include "buffer.h"
29 #include "backlight.h"
30 #include "sound_menu.h"
31 #include "mp3data.h"
32 #include "powermgmt.h"
33 #include "splash.h"
34 #include "logf.h"
35 #include "option_select.h"
37 #if CONFIG_CHARGING
38 #include "power.h"
39 #endif
41 #ifdef HAVE_LCD_BITMAP
42 #include "scrollbar.h"
43 #include "peakmeter.h"
44 #include "bmp.h"
45 #include "bidi.h"
46 #endif
48 #ifdef SIMULATOR
49 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
50 void *sim_plugin_load(char *plugin, void **pd);
51 void sim_plugin_close(void *pd);
52 void sim_lcd_ex_init(int shades, unsigned long (*getpixel)(int, int));
53 void sim_lcd_ex_update_rect(int x, int y, int width, int height);
54 #else
55 #define sim_plugin_close(x)
56 extern unsigned char pluginbuf[];
57 #include "bitswap.h"
58 #endif
60 /* for actual plugins only, not for codecs */
61 static bool plugin_loaded = false;
62 static int plugin_size = 0;
63 static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
64 static char current_plugin[MAX_PATH];
66 extern struct thread_entry threads[MAXTHREADS];
68 static const struct plugin_api rockbox_api = {
70 /* lcd */
71 lcd_set_contrast,
72 lcd_update,
73 lcd_clear_display,
74 lcd_setmargins,
75 lcd_getstringsize,
76 lcd_putsxy,
77 lcd_puts,
78 lcd_puts_scroll,
79 lcd_stop_scroll,
80 #ifdef HAVE_LCD_CHARCELLS
81 lcd_define_pattern,
82 lcd_get_locked_pattern,
83 lcd_unlock_pattern,
84 lcd_putc,
85 lcd_put_cursor,
86 lcd_remove_cursor,
87 lcd_icon,
88 lcd_double_height,
89 #else
90 lcd_set_drawmode,
91 lcd_get_drawmode,
92 lcd_setfont,
93 lcd_drawpixel,
94 lcd_drawline,
95 lcd_hline,
96 lcd_vline,
97 lcd_drawrect,
98 lcd_fillrect,
99 lcd_mono_bitmap_part,
100 lcd_mono_bitmap,
101 #if LCD_DEPTH > 1
102 lcd_set_foreground,
103 lcd_get_foreground,
104 lcd_set_background,
105 lcd_get_background,
106 lcd_bitmap_part,
107 lcd_bitmap,
108 lcd_get_backdrop,
109 lcd_set_backdrop,
110 #endif
111 #if LCD_DEPTH == 16
112 lcd_bitmap_transparent_part,
113 lcd_bitmap_transparent,
114 #endif
115 bidi_l2v,
116 font_get_bits,
117 font_load,
118 lcd_puts_style,
119 lcd_puts_scroll_style,
120 &lcd_framebuffer[0][0],
121 lcd_blit,
122 lcd_update_rect,
123 gui_scrollbar_draw,
124 font_get,
125 font_getstringsize,
126 font_get_width,
127 #endif
128 backlight_on,
129 backlight_off,
130 backlight_set_timeout,
131 gui_syncsplash,
132 #ifdef HAVE_REMOTE_LCD
133 /* remote lcd */
134 lcd_remote_set_contrast,
135 lcd_remote_clear_display,
136 lcd_remote_puts,
137 lcd_remote_puts_scroll,
138 lcd_remote_stop_scroll,
139 lcd_remote_set_drawmode,
140 lcd_remote_get_drawmode,
141 lcd_remote_setfont,
142 lcd_remote_getstringsize,
143 lcd_remote_drawpixel,
144 lcd_remote_drawline,
145 lcd_remote_hline,
146 lcd_remote_vline,
147 lcd_remote_drawrect,
148 lcd_remote_fillrect,
149 lcd_remote_mono_bitmap_part,
150 lcd_remote_mono_bitmap,
151 lcd_remote_putsxy,
152 lcd_remote_puts_style,
153 lcd_remote_puts_scroll_style,
154 &lcd_remote_framebuffer[0][0],
155 lcd_remote_update,
156 lcd_remote_update_rect,
158 remote_backlight_on,
159 remote_backlight_off,
160 #endif
161 #if NB_SCREENS == 2
162 {&screens[SCREEN_MAIN], &screens[SCREEN_REMOTE]},
163 #else
164 {&screens[SCREEN_MAIN]},
165 #endif
166 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
167 lcd_remote_set_foreground,
168 lcd_remote_get_foreground,
169 lcd_remote_set_background,
170 lcd_remote_get_background,
171 lcd_remote_bitmap_part,
172 lcd_remote_bitmap,
173 #endif
175 #if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR)
176 lcd_yuv_blit,
177 #endif
178 /* list */
179 gui_synclist_init,
180 gui_synclist_set_nb_items,
181 gui_synclist_set_icon_callback,
182 gui_synclist_get_nb_items,
183 gui_synclist_get_sel_pos,
184 gui_synclist_draw,
185 gui_synclist_select_item,
186 gui_synclist_add_item,
187 gui_synclist_del_item,
188 gui_synclist_limit_scroll,
189 gui_synclist_flash,
190 gui_synclist_do_button,
191 gui_synclist_set_title,
193 /* button */
194 button_get,
195 button_get_w_tmo,
196 button_status,
197 button_clear_queue,
198 #ifdef HAS_BUTTON_HOLD
199 button_hold,
200 #endif
202 /* file */
203 (open_func)PREFIX(open),
204 close,
205 (read_func)read,
206 PREFIX(lseek),
207 (creat_func)PREFIX(creat),
208 (write_func)write,
209 PREFIX(remove),
210 PREFIX(rename),
211 PREFIX(ftruncate),
212 PREFIX(filesize),
213 fdprintf,
214 read_line,
215 settings_parseline,
216 #ifndef SIMULATOR
217 ata_sleep,
218 ata_disk_is_active,
219 #endif
220 ata_spindown,
221 reload_directory,
222 create_numbered_filename,
224 /* dir */
225 PREFIX(opendir),
226 PREFIX(closedir),
227 PREFIX(readdir),
228 PREFIX(mkdir),
229 PREFIX(rmdir),
231 /* dir, cached */
232 #ifdef HAVE_DIRCACHE
233 opendir_cached,
234 readdir_cached,
235 closedir_cached,
236 #endif
238 /* kernel/ system */
239 PREFIX(sleep),
240 yield,
241 #ifdef HAVE_PRIORITY_SCHEDULING
242 priority_yield,
243 #endif
244 &current_tick,
245 default_event_handler,
246 default_event_handler_ex,
247 threads,
248 create_thread,
249 remove_thread,
250 reset_poweroff_timer,
251 #ifndef SIMULATOR
252 system_memory_guard,
253 &cpu_frequency,
255 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
256 #ifdef CPU_BOOST_LOGGING
257 cpu_boost_,
258 #else
259 cpu_boost,
260 #endif
261 #endif
262 timer_register,
263 timer_unregister,
264 timer_set_period,
265 #endif
266 queue_init,
267 queue_delete,
268 queue_post,
269 queue_wait_w_tmo,
270 usb_acknowledge,
271 #ifdef RB_PROFILE
272 profile_thread,
273 profstop,
274 profile_func_enter,
275 profile_func_exit,
276 #endif
278 #ifdef SIMULATOR
279 /* special simulator hooks */
280 #if defined(HAVE_LCD_BITMAP) && LCD_DEPTH < 8
281 sim_lcd_ex_init,
282 sim_lcd_ex_update_rect,
283 #endif
284 #endif
286 /* strings and memory */
287 snprintf,
288 vsnprintf,
289 strcpy,
290 strncpy,
291 strlen,
292 strrchr,
293 strcmp,
294 strncmp,
295 strcasecmp,
296 strncasecmp,
297 memset,
298 memcpy,
299 memmove,
300 _ctype_,
301 atoi,
302 strchr,
303 strcat,
304 memchr,
305 memcmp,
306 strcasestr,
307 strtok_r,
308 /* unicode stuff */
309 utf8decode,
310 iso_decode,
311 utf16LEdecode,
312 utf16BEdecode,
313 utf8encode,
314 utf8length,
315 utf8seek,
317 /* sound */
318 #if CONFIG_CODEC == SWCODEC
319 sound_default,
320 #endif
321 sound_set,
323 sound_min,
324 sound_max,
325 #ifndef SIMULATOR
326 mp3_play_data,
327 mp3_play_pause,
328 mp3_play_stop,
329 mp3_is_playing,
330 #if CONFIG_CODEC != SWCODEC
331 bitswap,
332 #endif
333 #endif
334 #if CONFIG_CODEC == SWCODEC
335 &audio_master_sampr_list[0],
336 &hw_freq_sampr[0],
337 pcm_apply_settings,
338 pcm_play_data,
339 pcm_play_stop,
340 pcm_set_frequency,
341 pcm_is_playing,
342 pcm_is_paused,
343 pcm_play_pause,
344 pcm_get_bytes_waiting,
345 pcm_calculate_peaks,
346 #ifdef HAVE_RECORDING
347 &rec_freq_sampr[0],
348 pcm_init_recording,
349 pcm_close_recording,
350 pcm_record_data,
351 pcm_record_more,
352 pcm_stop_recording,
353 pcm_calculate_rec_peaks,
354 audio_set_recording_gain,
355 #endif /* HAVE_RECORDING */
356 #if INPUT_SRC_CAPS != 0
357 audio_set_output_source,
358 audio_set_input_source,
359 #endif
360 #endif /* CONFIG_CODEC == SWCODEC */
362 /* playback control */
363 playlist_amount,
364 playlist_resume,
365 playlist_start,
366 PREFIX(audio_play),
367 audio_stop,
368 audio_pause,
369 audio_resume,
370 audio_next,
371 audio_prev,
372 audio_ff_rewind,
373 audio_next_track,
374 audio_status,
375 audio_has_changed_track,
376 audio_current_track,
377 audio_flush_and_reload_tracks,
378 audio_get_file_pos,
379 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
380 mpeg_get_last_header,
381 #endif
382 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
383 (CONFIG_CODEC == SWCODEC)
384 sound_set_pitch,
385 #endif
387 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
388 /* MAS communication */
389 mas_readmem,
390 mas_writemem,
391 mas_readreg,
392 mas_writereg,
393 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
394 mas_codec_writereg,
395 mas_codec_readreg,
396 i2c_begin,
397 i2c_end,
398 i2c_write,
399 #endif
400 #endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
402 /* menu */
403 do_menu,
404 /* statusbars */
405 &statusbars,
406 gui_syncstatusbar_draw,
407 /* options */
408 find_setting,
409 option_screen,
410 set_option,
411 set_bool_options,
412 set_int,
413 set_bool,
414 #ifdef HAVE_LCD_COLOR
415 set_color,
416 #endif
418 /* action handling */
419 get_custom_action,
420 get_action,
421 action_signalscreenchange,
422 action_userabort,
424 /* power */
425 battery_level,
426 battery_level_safe,
427 battery_time,
428 #ifndef SIMULATOR
429 battery_voltage,
430 #endif
431 #if CONFIG_CHARGING
432 charger_inserted,
433 # if CONFIG_CHARGING == CHARGING_MONITOR
434 charging_state,
435 # endif
436 #endif
437 #ifdef HAVE_USB_POWER
438 usb_powered,
439 #endif
441 /* misc */
442 srand,
443 rand,
444 (qsort_func)qsort,
445 kbd_input,
446 get_time,
447 set_time,
448 plugin_get_buffer,
449 plugin_get_audio_buffer,
450 plugin_tsr,
451 #ifdef IRAM_STEAL
452 plugin_iram_init,
453 #endif
454 #if defined(DEBUG) || defined(SIMULATOR)
455 debugf,
456 #endif
457 #ifdef ROCKBOX_HAS_LOGF
458 _logf,
459 #endif
460 &global_settings,
461 &global_status,
462 mp3info,
463 count_mp3_frames,
464 create_xing_header,
465 find_next_frame,
466 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
467 peak_meter_scale_value,
468 peak_meter_set_use_dbfs,
469 peak_meter_get_use_dbfs,
470 #endif
471 #ifdef HAVE_LCD_BITMAP
472 read_bmp_file,
473 screen_dump_set_hook,
474 #endif
475 show_logo,
476 tree_get_context,
478 #ifdef HAVE_WHEEL_POSITION
479 wheel_status,
480 wheel_send_events,
481 #endif
483 #ifdef IRIVER_H100_SERIES
484 /* Routines for the iriver_flash -plugin. */
485 detect_original_firmware,
486 detect_flashed_ramimage,
487 detect_flashed_romimage,
488 #endif
489 /* new stuff at the end, sort into place next time
490 the API gets incompatible */
491 #if NUM_CORES > 1
492 spinlock_init,
493 spinlock_lock,
494 spinlock_unlock,
495 #endif
497 #if (CONFIG_CODEC == SWCODEC)
498 codec_load_file,
499 get_codec_filename,
500 get_metadata,
501 #endif
504 int plugin_load(const char* plugin, void* parameter)
506 int rc;
507 struct plugin_header *hdr;
508 const char *p = strrchr(plugin,'/');
509 #ifdef SIMULATOR
510 void *pd;
511 #else
512 int fd;
513 ssize_t readsize;
514 #endif
515 int xm, ym;
516 #ifdef HAVE_REMOTE_LCD
517 int rxm, rym;
518 #endif
520 #if LCD_DEPTH > 1
521 fb_data* old_backdrop;
522 #endif
524 if (!p)
525 p = plugin;
526 action_signalscreenchange();
528 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
530 if (pfn_tsr_exit(!strcmp(current_plugin,p)) == false )
532 /* not allowing another plugin to load */
533 return PLUGIN_OK;
535 pfn_tsr_exit = NULL;
536 plugin_loaded = false;
539 gui_syncsplash(0, str(LANG_WAIT));
540 strcpy(current_plugin,p);
542 #ifdef SIMULATOR
543 hdr = sim_plugin_load((char *)plugin, &pd);
544 if (pd == NULL) {
545 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
546 return -1;
548 if (hdr == NULL
549 || hdr->magic != PLUGIN_MAGIC
550 || hdr->target_id != TARGET_ID) {
551 sim_plugin_close(pd);
552 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
553 return -1;
555 if (hdr->api_version > PLUGIN_API_VERSION
556 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
557 sim_plugin_close(pd);
558 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
559 return -1;
561 #else
562 fd = open(plugin, O_RDONLY);
563 if (fd < 0) {
564 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
565 return fd;
568 readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE);
569 close(fd);
571 if (readsize < 0) {
572 gui_syncsplash(HZ*2, str(LANG_READ_FAILED), plugin);
573 return -1;
575 hdr = (struct plugin_header *)pluginbuf;
577 if ((unsigned)readsize <= sizeof(struct plugin_header)
578 || hdr->magic != PLUGIN_MAGIC
579 || hdr->target_id != TARGET_ID
580 || hdr->load_addr != pluginbuf
581 || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) {
582 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
583 return -1;
585 if (hdr->api_version > PLUGIN_API_VERSION
586 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
587 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
588 return -1;
590 plugin_size = hdr->end_addr - pluginbuf;
592 /* zero out bss area only, above guards end of pluginbuf */
593 if (plugin_size > readsize)
594 memset(pluginbuf + readsize, 0, plugin_size - readsize);
595 #endif
597 plugin_loaded = true;
599 xm = lcd_getxmargin();
600 ym = lcd_getymargin();
601 lcd_setmargins(0,0);
603 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
604 old_backdrop = lcd_get_backdrop();
605 #endif
606 lcd_clear_display();
607 lcd_update();
609 #ifdef HAVE_REMOTE_LCD
610 rxm = lcd_remote_getxmargin();
611 rym = lcd_remote_getymargin();
612 lcd_remote_setmargins(0, 0);
613 lcd_remote_clear_display();
614 lcd_remote_update();
615 #endif
617 invalidate_icache();
619 rc = hdr->entry_point((struct plugin_api*) &rockbox_api, parameter);
620 /* explicitly casting the pointer here to avoid touching every plugin. */
622 action_signalscreenchange();
623 button_clear_queue();
625 #ifdef HAVE_LCD_BITMAP
626 #if LCD_DEPTH > 1
627 lcd_set_backdrop(old_backdrop);
628 #ifdef HAVE_LCD_COLOR
629 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color,
630 global_settings.bg_color);
631 #else
632 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG);
633 #endif
634 #else /* LCD_DEPTH == 1 */
635 lcd_set_drawmode(DRMODE_SOLID);
636 #endif /* LCD_DEPTH */
637 #endif /* HAVE_LCD_BITMAP */
639 /* restore margins */
640 lcd_setmargins(xm,ym);
641 lcd_clear_display();
642 lcd_update();
644 #ifdef HAVE_REMOTE_LCD
645 #if LCD_REMOTE_DEPTH > 1
646 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG,
647 LCD_REMOTE_DEFAULT_BG);
648 #else
649 lcd_remote_set_drawmode(DRMODE_SOLID);
650 #endif
651 lcd_remote_setmargins(rxm, rym);
652 lcd_remote_clear_display();
653 lcd_remote_update();
654 #endif
656 if (pfn_tsr_exit == NULL)
657 plugin_loaded = false;
659 sim_plugin_close(pd);
661 switch (rc) {
662 case PLUGIN_OK:
663 break;
665 case PLUGIN_USB_CONNECTED:
666 return PLUGIN_USB_CONNECTED;
668 default:
669 gui_syncsplash(HZ*2, str(LANG_PLUGIN_ERROR));
670 break;
672 return PLUGIN_OK;
675 /* Returns a pointer to the portion of the plugin buffer that is not already
676 being used. If no plugin is loaded, returns the entire plugin buffer */
677 void* plugin_get_buffer(size_t *buffer_size)
679 int buffer_pos;
681 if (plugin_loaded)
683 if (plugin_size >= PLUGIN_BUFFER_SIZE)
684 return NULL;
686 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
687 buffer_pos = plugin_size;
689 else
691 *buffer_size = PLUGIN_BUFFER_SIZE;
692 buffer_pos = 0;
695 return &pluginbuf[buffer_pos];
698 /* Returns a pointer to the mp3 buffer.
699 Playback gets stopped, to avoid conflicts.
700 Talk buffer is stolen as well.
702 void* plugin_get_audio_buffer(size_t *buffer_size)
704 #if CONFIG_CODEC == SWCODEC
705 return audio_get_buffer(true, buffer_size);
706 #else
707 audio_stop();
708 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
709 *buffer_size = audiobufend - audiobuf;
710 return audiobuf;
711 #endif
714 #ifdef IRAM_STEAL
715 /* Initializes plugin IRAM */
716 void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
717 char *iedata, size_t iedata_size)
719 audio_iram_steal();
720 memcpy(iramstart, iramcopy, iram_size);
721 memset(iedata, 0, iedata_size);
722 memset(iramcopy, 0, iram_size);
724 #endif /* IRAM_STEAL */
726 /* The plugin wants to stay resident after leaving its main function, e.g.
727 runs from timer or own thread. The callback is registered to later
728 instruct it to free its resources before a new plugin gets loaded. */
729 void plugin_tsr(bool (*exit_callback)(bool))
731 pfn_tsr_exit = exit_callback; /* remember the callback for later */