Rockbox as an application: add get_user_file_path().
[kugel-rb.git] / apps / plugin.c
blobb3baea757cfef82edd0e536842e43bc685d06f5c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
22 #include <ctype.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "debug.h"
26 #include "i2c.h"
27 #include "lang.h"
28 #include "led.h"
29 #include "keyboard.h"
30 #include "buffer.h"
31 #include "backlight.h"
32 #include "sound_menu.h"
33 #include "mp3data.h"
34 #include "powermgmt.h"
35 #include "splash.h"
36 #include "logf.h"
37 #include "option_select.h"
38 #include "talk.h"
39 #include "version.h"
40 #include "storage.h"
41 #include "pcmbuf.h"
42 #include "errno.h"
43 #include "diacritic.h"
44 #include "filefuncs.h"
46 #if CONFIG_CHARGING
47 #include "power.h"
48 #endif
50 #ifdef HAVE_LCD_BITMAP
51 #include "scrollbar.h"
52 #include "peakmeter.h"
53 #include "bmp.h"
54 #include "bidi.h"
55 #endif
57 #ifdef USB_ENABLE_HID
58 #include "usbstack/usb_hid.h"
59 #endif
61 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
62 #define PREFIX(_x_) sim_ ## _x_
63 #else
64 #define PREFIX
65 #endif
67 #if defined(HAVE_PLUGIN_CHECK_OPEN_CLOSE) && (MAX_OPEN_FILES>32)
68 #warning "MAX_OPEN_FILES>32, disabling plugin file open/close checking"
69 #undef HAVE_PLUGIN_CHECK_OPEN_CLOSE
70 #endif
72 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
73 static unsigned int open_files;
74 #endif
76 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
77 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
78 void *sim_plugin_load(char *plugin, void **pd);
79 void sim_plugin_close(void *pd);
80 void sim_lcd_ex_init(unsigned long (*getpixel)(int, int));
81 void sim_lcd_ex_update_rect(int x, int y, int width, int height);
82 #else
83 #define sim_plugin_close(x)
84 extern unsigned char pluginbuf[];
85 #include "bitswap.h"
86 #endif
88 /* for actual plugins only, not for codecs */
89 static bool plugin_loaded = false;
90 static int plugin_size = 0;
91 static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
92 static char current_plugin[MAX_PATH];
94 char *plugin_get_current_filename(void);
96 /* Some wrappers used to monitor open and close and detect leaks*/
97 static int open_wrapper(const char* pathname, int flags, ...);
98 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
99 static int close_wrapper(int fd);
100 static int creat_wrapper(const char *pathname, mode_t mode);
101 #endif
103 static const struct plugin_api rockbox_api = {
105 /* lcd */
106 #ifdef HAVE_LCD_CONTRAST
107 lcd_set_contrast,
108 #endif
109 lcd_update,
110 lcd_clear_display,
111 lcd_getstringsize,
112 lcd_putsxy,
113 lcd_puts,
114 lcd_puts_scroll,
115 lcd_stop_scroll,
116 #ifdef HAVE_LCD_CHARCELLS
117 lcd_define_pattern,
118 lcd_get_locked_pattern,
119 lcd_unlock_pattern,
120 lcd_putc,
121 lcd_put_cursor,
122 lcd_remove_cursor,
123 lcd_icon,
124 lcd_double_height,
125 #else
126 &lcd_framebuffer[0][0],
127 lcd_update_rect,
128 lcd_set_drawmode,
129 lcd_get_drawmode,
130 lcd_setfont,
131 lcd_drawpixel,
132 lcd_drawline,
133 lcd_hline,
134 lcd_vline,
135 lcd_drawrect,
136 lcd_fillrect,
137 lcd_mono_bitmap_part,
138 lcd_mono_bitmap,
139 #if LCD_DEPTH > 1
140 lcd_set_foreground,
141 lcd_get_foreground,
142 lcd_set_background,
143 lcd_get_background,
144 lcd_bitmap_part,
145 lcd_bitmap,
146 lcd_get_backdrop,
147 lcd_set_backdrop,
148 #endif
149 #if LCD_DEPTH == 16
150 lcd_bitmap_transparent_part,
151 lcd_bitmap_transparent,
152 #if MEMORYSIZE > 2
153 lcd_blit_yuv,
154 #if defined(TOSHIBA_GIGABEAT_F) || defined(SANSA_E200) || defined(SANSA_C200) \
155 || defined(IRIVER_H10) || defined(COWON_D2) || defined(PHILIPS_HDD1630) \
156 || defined(SANSA_FUZE) || defined(SANSA_E200V2) || defined(SANSA_FUZEV2) \
157 || defined(TOSHIBA_GIGABEAT_S)
158 lcd_yuv_set_options,
159 #endif
160 #endif /* MEMORYSIZE > 2 */
161 #elif (LCD_DEPTH < 4) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
162 lcd_blit_mono,
163 lcd_blit_grey_phase,
164 #endif /* LCD_DEPTH */
165 #if defined(HAVE_LCD_MODES) && (HAVE_LCD_MODES & LCD_MODE_PAL256)
166 lcd_blit_pal256,
167 lcd_pal256_update_pal,
168 #endif
169 lcd_puts_style,
170 lcd_puts_scroll_style,
171 #ifdef HAVE_LCD_INVERT
172 lcd_set_invert_display,
173 #endif /* HAVE_LCD_INVERT */
174 #if defined(HAVE_LCD_MODES)
175 lcd_set_mode,
176 #endif
177 #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
178 &button_queue,
179 #endif
180 bidi_l2v,
181 #ifdef HAVE_LCD_BITMAP
182 is_diacritic,
183 #endif
184 font_get_bits,
185 font_load,
186 font_get,
187 font_getstringsize,
188 font_get_width,
189 screen_clear_area,
190 gui_scrollbar_draw,
191 #endif /* HAVE_LCD_BITMAP */
192 get_codepage_name,
194 backlight_on,
195 backlight_off,
196 backlight_set_timeout,
197 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
198 backlight_set_brightness,
199 #endif /* HAVE_BACKLIGHT_BRIGHTNESS */
201 #if CONFIG_CHARGING
202 backlight_set_timeout_plugged,
203 #endif
204 is_backlight_on,
205 splash,
206 splashf,
208 #ifdef HAVE_REMOTE_LCD
209 /* remote lcd */
210 lcd_remote_set_contrast,
211 lcd_remote_clear_display,
212 lcd_remote_puts,
213 lcd_remote_puts_scroll,
214 lcd_remote_stop_scroll,
215 lcd_remote_set_drawmode,
216 lcd_remote_get_drawmode,
217 lcd_remote_setfont,
218 lcd_remote_getstringsize,
219 lcd_remote_drawpixel,
220 lcd_remote_drawline,
221 lcd_remote_hline,
222 lcd_remote_vline,
223 lcd_remote_drawrect,
224 lcd_remote_fillrect,
225 lcd_remote_mono_bitmap_part,
226 lcd_remote_mono_bitmap,
227 lcd_remote_putsxy,
228 lcd_remote_puts_style,
229 lcd_remote_puts_scroll_style,
230 &lcd_remote_framebuffer[0][0],
231 lcd_remote_update,
232 lcd_remote_update_rect,
234 remote_backlight_on,
235 remote_backlight_off,
236 remote_backlight_set_timeout,
237 #if CONFIG_CHARGING
238 remote_backlight_set_timeout_plugged,
239 #endif
240 #endif /* HAVE_REMOTE_LCD */
241 #if NB_SCREENS == 2
242 {&screens[SCREEN_MAIN], &screens[SCREEN_REMOTE]},
243 #else
244 {&screens[SCREEN_MAIN]},
245 #endif
246 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
247 lcd_remote_set_foreground,
248 lcd_remote_get_foreground,
249 lcd_remote_set_background,
250 lcd_remote_get_background,
251 lcd_remote_bitmap_part,
252 lcd_remote_bitmap,
253 #endif
254 viewport_set_defaults,
255 #ifdef HAVE_LCD_BITMAP
256 viewportmanager_theme_enable,
257 viewportmanager_theme_undo,
258 #endif
260 /* list */
261 gui_synclist_init,
262 gui_synclist_set_nb_items,
263 gui_synclist_set_icon_callback,
264 gui_synclist_get_nb_items,
265 gui_synclist_get_sel_pos,
266 gui_synclist_draw,
267 gui_synclist_select_item,
268 gui_synclist_add_item,
269 gui_synclist_del_item,
270 gui_synclist_limit_scroll,
271 gui_synclist_do_button,
272 gui_synclist_set_title,
273 gui_syncyesno_run,
274 simplelist_info_init,
275 simplelist_show_list,
277 /* button */
278 button_get,
279 button_get_w_tmo,
280 button_status,
281 #ifdef HAVE_BUTTON_DATA
282 button_get_data,
283 button_status_wdata,
284 #endif
285 button_clear_queue,
286 button_queue_count,
287 #ifdef HAS_BUTTON_HOLD
288 button_hold,
289 #endif
290 #ifdef HAVE_TOUCHSCREEN
291 touchscreen_set_mode,
292 #endif
294 #ifdef HAVE_BUTTON_LIGHT
295 buttonlight_set_timeout,
296 buttonlight_off,
297 buttonlight_on,
298 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
299 buttonlight_set_brightness,
300 #endif /* HAVE_BUTTONLIGHT_BRIGHTNESS */
301 #endif /* HAVE_BUTTON_LIGHT */
303 /* file */
304 open_utf8,
305 (open_func)open_wrapper,
306 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
307 close_wrapper,
308 #else
309 PREFIX(close),
310 #endif
311 (read_func)PREFIX(read),
312 PREFIX(lseek),
313 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
314 (creat_func)creat_wrapper,
315 #else
316 (creat_func)PREFIX(creat),
317 #endif
318 (write_func)PREFIX(write),
319 PREFIX(remove),
320 PREFIX(rename),
321 PREFIX(ftruncate),
322 PREFIX(filesize),
323 fdprintf,
324 read_line,
325 settings_parseline,
326 storage_sleep,
327 storage_spin,
328 storage_spindown,
329 #if USING_STORAGE_CALLBACK
330 register_storage_idle_func,
331 unregister_storage_idle_func,
332 #endif /* USING_STORAGE_CALLBACK */
333 reload_directory,
334 create_numbered_filename,
335 file_exists,
336 strip_extension,
337 crc_32,
339 /* dir */
340 opendir,
341 closedir,
342 readdir,
343 mkdir,
344 rmdir,
345 dir_exists,
347 /* kernel/ system */
348 #ifdef CPU_ARM
349 __div0,
350 #endif
351 PREFIX(sleep),
352 yield,
353 &current_tick,
354 default_event_handler,
355 default_event_handler_ex,
356 create_thread,
357 thread_exit,
358 thread_wait,
359 #if (CONFIG_CODEC == SWCODEC)
360 thread_thaw,
361 #ifdef HAVE_PRIORITY_SCHEDULING
362 thread_set_priority,
363 #endif
364 mutex_init,
365 mutex_lock,
366 mutex_unlock,
367 #endif
369 reset_poweroff_timer,
370 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
371 system_memory_guard,
372 &cpu_frequency,
374 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
375 #ifdef CPU_BOOST_LOGGING
376 cpu_boost_,
377 #else
378 cpu_boost,
379 #endif
380 #endif /* HAVE_ADJUSTABLE_CPU_FREQ */
381 #endif /* PLATFORM_NATIVE */
382 #ifdef HAVE_SCHEDULER_BOOSTCTRL
383 trigger_cpu_boost,
384 cancel_cpu_boost,
385 #endif
386 #if NUM_CORES > 1
387 cpucache_flush,
388 cpucache_invalidate,
389 #endif
390 timer_register,
391 timer_unregister,
392 timer_set_period,
394 queue_init,
395 queue_delete,
396 queue_post,
397 queue_wait_w_tmo,
398 #if CONFIG_CODEC == SWCODEC
399 queue_enable_queue_send,
400 queue_empty,
401 queue_wait,
402 queue_send,
403 queue_reply,
404 #endif
405 usb_acknowledge,
406 #ifdef USB_ENABLE_HID
407 usb_hid_send,
408 #endif
409 #ifdef RB_PROFILE
410 profile_thread,
411 profstop,
412 __cyg_profile_func_enter,
413 __cyg_profile_func_exit,
414 #endif
415 add_event,
416 remove_event,
417 send_event,
419 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
420 /* special simulator hooks */
421 #if defined(HAVE_LCD_BITMAP) && LCD_DEPTH < 8
422 sim_lcd_ex_init,
423 sim_lcd_ex_update_rect,
424 #endif
425 #endif
427 /* strings and memory */
428 snprintf,
429 vsnprintf,
430 strcpy,
431 strlcpy,
432 strlen,
433 strrchr,
434 strcmp,
435 strncmp,
436 strcasecmp,
437 strncasecmp,
438 memset,
439 memcpy,
440 memmove,
441 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
442 _ctype_,
443 #endif
444 atoi,
445 strchr,
446 strcat,
447 strlcat,
448 memchr,
449 memcmp,
450 strcasestr,
451 strtok_r,
452 /* unicode stuff */
453 utf8decode,
454 iso_decode,
455 utf16LEdecode,
456 utf16BEdecode,
457 utf8encode,
458 utf8length,
459 utf8seek,
461 /* sound */
462 sound_set,
463 sound_default,
464 sound_min,
465 sound_max,
466 sound_unit,
467 sound_val2phys,
468 #ifdef AUDIOHW_HAVE_EQ
469 sound_enum_hw_eq_band_setting,
470 #endif
471 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
472 mp3_play_data,
473 mp3_play_pause,
474 mp3_play_stop,
475 mp3_is_playing,
476 #if CONFIG_CODEC != SWCODEC
477 bitswap,
478 #endif
479 #endif
480 #if CONFIG_CODEC == SWCODEC
481 &audio_master_sampr_list[0],
482 &hw_freq_sampr[0],
483 pcm_apply_settings,
484 pcm_play_data,
485 pcm_play_stop,
486 pcm_set_frequency,
487 pcm_is_playing,
488 pcm_is_paused,
489 pcm_play_pause,
490 pcm_get_bytes_waiting,
491 pcm_calculate_peaks,
492 pcm_get_peak_buffer,
493 pcm_play_lock,
494 pcm_play_unlock,
495 pcmbuf_beep,
496 #ifdef HAVE_RECORDING
497 &rec_freq_sampr[0],
498 pcm_init_recording,
499 pcm_close_recording,
500 pcm_record_data,
501 pcm_stop_recording,
502 pcm_calculate_rec_peaks,
503 audio_set_recording_gain,
504 #endif /* HAVE_RECORDING */
505 #if INPUT_SRC_CAPS != 0
506 audio_set_output_source,
507 audio_set_input_source,
508 #endif
509 dsp_set_crossfeed,
510 dsp_set_eq,
511 dsp_dither_enable,
512 dsp_configure,
513 dsp_process,
514 dsp_input_count,
515 dsp_output_count,
516 #endif /* CONFIG_CODEC == SWCODEC */
518 /* playback control */
519 playlist_amount,
520 playlist_resume,
521 playlist_start,
522 playlist_add,
523 playlist_sync,
524 playlist_remove_all_tracks,
525 playlist_create,
526 playlist_insert_track,
527 playlist_insert_directory,
528 playlist_shuffle,
529 PREFIX(audio_play),
530 audio_stop,
531 audio_pause,
532 audio_resume,
533 audio_next,
534 audio_prev,
535 audio_ff_rewind,
536 audio_next_track,
537 audio_status,
538 audio_current_track,
539 audio_flush_and_reload_tracks,
540 audio_get_file_pos,
541 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
542 mpeg_get_last_header,
543 #endif
544 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
545 (CONFIG_CODEC == SWCODEC)
546 sound_set_pitch,
547 #endif
549 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
550 /* MAS communication */
551 mas_readmem,
552 mas_writemem,
553 mas_readreg,
554 mas_writereg,
555 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
556 mas_codec_writereg,
557 mas_codec_readreg,
558 i2c_begin,
559 i2c_end,
560 i2c_write,
561 #endif
562 #endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
564 /* menu */
565 do_menu,
566 /* statusbars */
567 &statusbars,
568 gui_syncstatusbar_draw,
570 /* options */
571 get_settings_list,
572 find_setting,
573 option_screen,
574 set_option,
575 set_bool_options,
576 set_int,
577 set_bool,
578 #ifdef HAVE_LCD_COLOR
579 set_color,
580 #endif
582 /* action handling */
583 get_custom_action,
584 get_action,
585 #ifdef HAVE_TOUCHSCREEN
586 action_get_touchscreen_press,
587 #endif
588 action_userabort,
590 /* power */
591 battery_level,
592 battery_level_safe,
593 battery_time,
594 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
595 battery_voltage,
596 #endif
597 #if CONFIG_CHARGING
598 charger_inserted,
599 # if CONFIG_CHARGING >= CHARGING_MONITOR
600 charging_state,
601 # endif
602 #endif
603 #ifdef HAVE_USB_POWER
604 usb_powered,
605 #endif
607 /* misc */
608 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
609 &errno,
610 #endif
611 srand,
612 rand,
613 (qsort_func)qsort,
614 kbd_input,
615 get_time,
616 set_time,
617 #if CONFIG_RTC
618 mktime,
619 #endif
620 plugin_get_buffer,
621 plugin_get_audio_buffer,
622 plugin_tsr,
623 plugin_get_current_filename,
624 #ifdef PLUGIN_USE_IRAM
625 plugin_iram_init,
626 #endif
627 #if defined(DEBUG) || defined(SIMULATOR)
628 debugf,
629 #endif
630 #ifdef ROCKBOX_HAS_LOGF
631 _logf,
632 #endif
633 &global_settings,
634 &global_status,
635 talk_disable,
636 #if CONFIG_CODEC == SWCODEC
637 codec_thread_do_callback,
638 codec_load_file,
639 get_codec_filename,
640 find_array_ptr,
641 remove_array_ptr,
642 round_value_to_list32,
643 #endif /* CONFIG_CODEC == SWCODEC */
644 get_metadata,
645 mp3info,
646 count_mp3_frames,
647 create_xing_header,
648 find_next_frame,
649 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
650 peak_meter_scale_value,
651 peak_meter_set_use_dbfs,
652 peak_meter_get_use_dbfs,
653 #endif
654 #ifdef HAVE_LCD_BITMAP
655 read_bmp_file,
656 read_bmp_fd,
657 #ifdef HAVE_JPEG
658 read_jpeg_file,
659 read_jpeg_fd,
660 #endif
661 screen_dump_set_hook,
662 #endif
663 show_logo,
664 tree_get_context,
665 set_current_file,
666 set_dirfilter,
668 #ifdef HAVE_WHEEL_POSITION
669 wheel_status,
670 wheel_send_events,
671 #endif
673 #ifdef IRIVER_H100_SERIES
674 /* Routines for the iriver_flash -plugin. */
675 detect_original_firmware,
676 detect_flashed_ramimage,
677 detect_flashed_romimage,
678 #endif
679 led,
680 #if (CONFIG_CODEC == SWCODEC)
681 bufopen,
682 bufalloc,
683 bufclose,
684 bufseek,
685 bufadvance,
686 bufread,
687 bufgetdata,
688 bufgettail,
689 bufcuttail,
691 buf_get_offset,
692 buf_handle_offset,
693 buf_request_buffer_handle,
694 buf_set_base_handle,
695 buf_used,
696 #endif
698 #ifdef HAVE_TAGCACHE
699 tagcache_search,
700 tagcache_search_set_uniqbuf,
701 tagcache_search_add_filter,
702 tagcache_get_next,
703 tagcache_retrieve,
704 tagcache_search_finish,
705 tagcache_get_numeric,
706 #ifdef HAVE_TC_RAMCACHE
707 tagcache_fill_tags,
708 #endif
709 #endif
711 #ifdef HAVE_ALBUMART
712 search_albumart_files,
713 #endif
715 #ifdef HAVE_SEMAPHORE_OBJECTS
716 semaphore_init,
717 semaphore_wait,
718 semaphore_release,
719 #endif
721 rbversion,
723 /* new stuff at the end, sort into place next time
724 the API gets incompatible */
727 int plugin_load(const char* plugin, const void* parameter)
729 int rc, i;
730 struct plugin_header *hdr;
731 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
732 void *pd;
733 #else /* PLATFOR_NATIVE */
734 int fd;
735 ssize_t readsize;
736 #if NUM_CORES > 1
737 unsigned my_core;
738 #endif
739 #endif /* CONFIG_PLATFORM */
741 #if LCD_DEPTH > 1
742 fb_data* old_backdrop;
743 #endif
745 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
747 if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false )
749 /* not allowing another plugin to load */
750 return PLUGIN_OK;
752 pfn_tsr_exit = NULL;
753 plugin_loaded = false;
756 splash(0, ID2P(LANG_WAIT));
757 strcpy(current_plugin, plugin);
759 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
760 hdr = sim_plugin_load((char *)plugin, &pd);
761 if (pd == NULL) {
762 splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
763 return -1;
765 if (hdr == NULL
766 || hdr->magic != PLUGIN_MAGIC
767 || hdr->target_id != TARGET_ID) {
768 sim_plugin_close(pd);
769 splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
770 return -1;
772 if (hdr->api_version > PLUGIN_API_VERSION
773 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
774 sim_plugin_close(pd);
775 splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
776 return -1;
778 #else
779 fd = open(plugin, O_RDONLY);
780 if (fd < 0) {
781 splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
782 return fd;
784 #if NUM_CORES > 1
785 /* Make sure COP cache is flushed and invalidated before loading */
786 my_core = switch_core(CURRENT_CORE ^ 1);
787 cpucache_invalidate();
788 switch_core(my_core);
789 #endif
791 readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE);
792 close(fd);
794 if (readsize < 0) {
795 splashf(HZ*2, str(LANG_READ_FAILED), plugin);
796 return -1;
798 hdr = (struct plugin_header *)pluginbuf;
800 if ((unsigned)readsize <= sizeof(struct plugin_header)
801 || hdr->magic != PLUGIN_MAGIC
802 || hdr->target_id != TARGET_ID
803 || hdr->load_addr != pluginbuf
804 || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) {
805 splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
806 return -1;
808 if (hdr->api_version > PLUGIN_API_VERSION
809 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
810 splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
811 return -1;
813 plugin_size = hdr->end_addr - pluginbuf;
815 /* zero out bss area only, above guards end of pluginbuf */
816 if (plugin_size > readsize)
817 memset(pluginbuf + readsize, 0, plugin_size - readsize);
818 #endif
820 *(hdr->api) = &rockbox_api;
821 plugin_loaded = true;
824 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
825 old_backdrop = lcd_get_backdrop();
826 #endif
827 lcd_clear_display();
828 lcd_update();
830 #ifdef HAVE_REMOTE_LCD
831 lcd_remote_clear_display();
832 lcd_remote_update();
833 #endif
835 FOR_NB_SCREENS(i)
836 viewportmanager_theme_enable(i, false, NULL);
838 cpucache_invalidate();
840 #ifdef HAVE_TOUCHSCREEN
841 touchscreen_set_mode(TOUCHSCREEN_BUTTON);
842 #endif
844 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
845 open_files = 0;
846 #endif
848 rc = hdr->entry_point(parameter);
850 /* Go back to the global setting in case the plugin changed it */
851 #ifdef HAVE_TOUCHSCREEN
852 touchscreen_set_mode(global_settings.touch_mode);
853 #endif
855 button_clear_queue();
857 #ifdef HAVE_LCD_BITMAP
858 lcd_setfont(FONT_UI);
859 #if LCD_DEPTH > 1
860 lcd_set_backdrop(old_backdrop);
861 #ifdef HAVE_LCD_COLOR
862 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color,
863 global_settings.bg_color);
864 #else
865 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG);
866 #endif
867 #else /* LCD_DEPTH == 1 */
868 lcd_set_drawmode(DRMODE_SOLID);
869 #endif /* LCD_DEPTH */
870 #endif /* HAVE_LCD_BITMAP */
873 #ifdef HAVE_REMOTE_LCD
874 #if LCD_REMOTE_DEPTH > 1
875 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG,
876 LCD_REMOTE_DEFAULT_BG);
877 #else
878 lcd_remote_set_drawmode(DRMODE_SOLID);
879 #endif
880 #endif
882 lcd_clear_display();
883 #ifdef HAVE_REMOTE_LCD
884 lcd_remote_clear_display();
885 #endif
887 FOR_NB_SCREENS(i)
888 viewportmanager_theme_undo(i, false);
890 if (pfn_tsr_exit == NULL)
891 plugin_loaded = false;
893 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
894 if(open_files != 0 && !plugin_loaded)
896 int fd;
897 logf("Plugin '%s' leaks file handles", plugin);
899 static const char *lines[] =
900 { ID2P(LANG_PLUGIN_ERROR),
901 "#leak-file-handles" };
902 static const struct text_message message={ lines, 2 };
903 button_clear_queue(); /* Empty the keyboard buffer */
904 gui_syncyesno_run(&message, NULL, NULL);
906 for(fd=0; fd < MAX_OPEN_FILES; fd++)
907 if(open_files & (1<<fd))
908 close_wrapper(fd);
910 #endif
912 sim_plugin_close(pd);
914 if (rc == PLUGIN_ERROR)
915 splash(HZ*2, str(LANG_PLUGIN_ERROR));
917 return rc;
920 /* Returns a pointer to the portion of the plugin buffer that is not already
921 being used. If no plugin is loaded, returns the entire plugin buffer */
922 void* plugin_get_buffer(size_t *buffer_size)
924 int buffer_pos;
926 if (plugin_loaded)
928 if (plugin_size >= PLUGIN_BUFFER_SIZE)
929 return NULL;
931 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
932 buffer_pos = plugin_size;
934 else
936 *buffer_size = PLUGIN_BUFFER_SIZE;
937 buffer_pos = 0;
940 return &pluginbuf[buffer_pos];
943 /* Returns a pointer to the mp3 buffer.
944 Playback gets stopped, to avoid conflicts.
945 Talk buffer is stolen as well.
947 void* plugin_get_audio_buffer(size_t *buffer_size)
949 #if CONFIG_CODEC == SWCODEC
950 return audio_get_buffer(true, buffer_size);
951 #else
952 audio_stop();
953 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
954 *buffer_size = audiobufend - audiobuf;
955 return audiobuf;
956 #endif
959 #ifdef PLUGIN_USE_IRAM
960 /* Initializes plugin IRAM */
961 void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
962 char *iedata, size_t iedata_size)
964 /* We need to stop audio playback in order to use codec IRAM */
965 audio_hard_stop();
966 memcpy(iramstart, iramcopy, iram_size);
967 memset(iedata, 0, iedata_size);
968 memset(iramcopy, 0, iram_size);
969 #if NUM_CORES > 1
970 /* writeback cleared iedata and iramcopy areas */
971 cpucache_flush();
972 #endif
974 #endif /* PLUGIN_USE_IRAM */
976 /* The plugin wants to stay resident after leaving its main function, e.g.
977 runs from timer or own thread. The callback is registered to later
978 instruct it to free its resources before a new plugin gets loaded. */
979 void plugin_tsr(bool (*exit_callback)(bool))
981 pfn_tsr_exit = exit_callback; /* remember the callback for later */
984 char *plugin_get_current_filename(void)
986 return current_plugin;
989 static int open_wrapper(const char* pathname, int flags, ...)
991 /* we don't have an 'open' function. it's a define. and we need
992 * the real file_open, hence PREFIX() doesn't work here */
993 int fd;
994 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
995 if (flags & O_CREAT)
997 va_list ap;
998 va_start(ap, flags);
999 fd = sim_open(pathname, flags, va_arg(ap, unsigned int));
1000 va_end(ap);
1002 else
1003 fd = sim_open(pathname, flags);
1004 #else
1005 fd = file_open(pathname,flags);
1006 #endif
1008 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
1009 if(fd >= 0)
1010 open_files |= 1<<fd;
1011 #endif
1012 return fd;
1015 #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
1016 static int close_wrapper(int fd)
1018 if((~open_files) & (1<<fd))
1020 logf("double close from plugin");
1022 if(fd >= 0)
1023 open_files &= (~(1<<fd));
1025 return PREFIX(close)(fd);
1028 static int creat_wrapper(const char *pathname, mode_t mode)
1030 int fd = PREFIX(creat)(pathname, mode);
1032 if(fd >= 0)
1033 open_files |= (1<<fd);
1035 return fd;
1037 #endif /* HAVE_PLUGIN_CHECK_OPEN_CLOSE */