Remove tabs (I wonder why Anjuta decided to insert them there)
[maemo-rb.git] / apps / plugin.c
blobe81ae25ed1606c2666f7439bafd4059efe48fa59
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"
36 #if CONFIG_CHARGING
37 #include "power.h"
38 #endif
40 #ifdef HAVE_LCD_BITMAP
41 #include "scrollbar.h"
42 #include "peakmeter.h"
43 #include "bmp.h"
44 #include "bidi.h"
45 #endif
47 #ifdef SIMULATOR
48 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
49 void *sim_plugin_load(char *plugin, void **pd);
50 void sim_plugin_close(void *pd);
51 void sim_lcd_ex_init(int shades, unsigned long (*getpixel)(int, int));
52 void sim_lcd_ex_update_rect(int x, int y, int width, int height);
53 #else
54 #define sim_plugin_close(x)
55 extern unsigned char pluginbuf[];
56 #include "bitswap.h"
57 #endif
59 /* for actual plugins only, not for codecs */
60 static bool plugin_loaded = false;
61 static int plugin_size = 0;
62 static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
63 static char current_plugin[MAX_PATH];
65 extern struct thread_entry threads[MAXTHREADS];
67 static const struct plugin_api rockbox_api = {
69 /* lcd */
70 lcd_set_contrast,
71 lcd_update,
72 lcd_clear_display,
73 lcd_setmargins,
74 lcd_getstringsize,
75 lcd_putsxy,
76 lcd_puts,
77 lcd_puts_scroll,
78 lcd_stop_scroll,
79 #ifdef HAVE_LCD_CHARCELLS
80 lcd_define_pattern,
81 lcd_get_locked_pattern,
82 lcd_unlock_pattern,
83 lcd_putc,
84 lcd_put_cursor,
85 lcd_remove_cursor,
86 lcd_icon,
87 lcd_double_height,
88 #else
89 lcd_set_drawmode,
90 lcd_get_drawmode,
91 lcd_setfont,
92 lcd_drawpixel,
93 lcd_drawline,
94 lcd_hline,
95 lcd_vline,
96 lcd_drawrect,
97 lcd_fillrect,
98 lcd_mono_bitmap_part,
99 lcd_mono_bitmap,
100 #if LCD_DEPTH > 1
101 lcd_set_foreground,
102 lcd_get_foreground,
103 lcd_set_background,
104 lcd_get_background,
105 lcd_bitmap_part,
106 lcd_bitmap,
107 lcd_get_backdrop,
108 lcd_set_backdrop,
109 #endif
110 #if LCD_DEPTH == 16
111 lcd_bitmap_transparent_part,
112 lcd_bitmap_transparent,
113 #endif
114 bidi_l2v,
115 font_get_bits,
116 font_load,
117 lcd_puts_style,
118 lcd_puts_scroll_style,
119 &lcd_framebuffer[0][0],
120 lcd_blit,
121 lcd_update_rect,
122 gui_scrollbar_draw,
123 font_get,
124 font_getstringsize,
125 font_get_width,
126 #endif
127 backlight_on,
128 backlight_off,
129 backlight_set_timeout,
130 gui_syncsplash,
131 #ifdef HAVE_REMOTE_LCD
132 /* remote lcd */
133 lcd_remote_set_contrast,
134 lcd_remote_clear_display,
135 lcd_remote_puts,
136 lcd_remote_puts_scroll,
137 lcd_remote_stop_scroll,
138 lcd_remote_set_drawmode,
139 lcd_remote_get_drawmode,
140 lcd_remote_setfont,
141 lcd_remote_getstringsize,
142 lcd_remote_drawpixel,
143 lcd_remote_drawline,
144 lcd_remote_hline,
145 lcd_remote_vline,
146 lcd_remote_drawrect,
147 lcd_remote_fillrect,
148 lcd_remote_mono_bitmap_part,
149 lcd_remote_mono_bitmap,
150 lcd_remote_putsxy,
151 lcd_remote_puts_style,
152 lcd_remote_puts_scroll_style,
153 &lcd_remote_framebuffer[0][0],
154 lcd_remote_update,
155 lcd_remote_update_rect,
157 remote_backlight_on,
158 remote_backlight_off,
159 #endif
160 #if NB_SCREENS == 2
161 {&screens[SCREEN_MAIN], &screens[SCREEN_REMOTE]},
162 #else
163 {&screens[SCREEN_MAIN]},
164 #endif
165 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
166 lcd_remote_set_foreground,
167 lcd_remote_get_foreground,
168 lcd_remote_set_background,
169 lcd_remote_get_background,
170 lcd_remote_bitmap_part,
171 lcd_remote_bitmap,
172 #endif
174 #if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR)
175 lcd_yuv_blit,
176 #endif
177 /* list */
178 gui_synclist_init,
179 gui_synclist_set_nb_items,
180 gui_synclist_set_icon_callback,
181 gui_synclist_get_nb_items,
182 gui_synclist_get_sel_pos,
183 gui_synclist_draw,
184 gui_synclist_select_item,
185 gui_synclist_add_item,
186 gui_synclist_del_item,
187 gui_synclist_limit_scroll,
188 gui_synclist_flash,
189 gui_synclist_do_button,
190 gui_synclist_set_title,
192 /* button */
193 button_get,
194 button_get_w_tmo,
195 button_status,
196 button_clear_queue,
197 #ifdef HAS_BUTTON_HOLD
198 button_hold,
199 #endif
201 /* file */
202 (open_func)PREFIX(open),
203 close,
204 (read_func)read,
205 PREFIX(lseek),
206 (creat_func)PREFIX(creat),
207 (write_func)write,
208 PREFIX(remove),
209 PREFIX(rename),
210 PREFIX(ftruncate),
211 PREFIX(filesize),
212 fdprintf,
213 read_line,
214 settings_parseline,
215 #ifndef SIMULATOR
216 ata_sleep,
217 ata_disk_is_active,
218 #endif
219 ata_spindown,
220 reload_directory,
221 create_numbered_filename,
223 /* dir */
224 PREFIX(opendir),
225 PREFIX(closedir),
226 PREFIX(readdir),
227 PREFIX(mkdir),
228 PREFIX(rmdir),
230 /* dir, cached */
231 #ifdef HAVE_DIRCACHE
232 opendir_cached,
233 readdir_cached,
234 closedir_cached,
235 #endif
237 /* kernel/ system */
238 PREFIX(sleep),
239 yield,
240 #ifdef HAVE_PRIORITY_SCHEDULING
241 priority_yield,
242 #endif
243 &current_tick,
244 default_event_handler,
245 default_event_handler_ex,
246 threads,
247 create_thread,
248 remove_thread,
249 reset_poweroff_timer,
250 #ifndef SIMULATOR
251 system_memory_guard,
252 &cpu_frequency,
254 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
255 #ifdef CPU_BOOST_LOGGING
256 cpu_boost_,
257 #else
258 cpu_boost,
259 #endif
260 #endif
261 timer_register,
262 timer_unregister,
263 timer_set_period,
264 #endif
265 queue_init,
266 queue_delete,
267 queue_post,
268 queue_wait_w_tmo,
269 usb_acknowledge,
270 #ifdef RB_PROFILE
271 profile_thread,
272 profstop,
273 profile_func_enter,
274 profile_func_exit,
275 #endif
277 #ifdef SIMULATOR
278 /* special simulator hooks */
279 #if defined(HAVE_LCD_BITMAP) && LCD_DEPTH < 8
280 sim_lcd_ex_init,
281 sim_lcd_ex_update_rect,
282 #endif
283 #endif
285 /* strings and memory */
286 snprintf,
287 vsnprintf,
288 strcpy,
289 strncpy,
290 strlen,
291 strrchr,
292 strcmp,
293 strncmp,
294 strcasecmp,
295 strncasecmp,
296 memset,
297 memcpy,
298 memmove,
299 _ctype_,
300 atoi,
301 strchr,
302 strcat,
303 memchr,
304 memcmp,
305 strcasestr,
306 strtok_r,
307 /* unicode stuff */
308 utf8decode,
309 iso_decode,
310 utf16LEdecode,
311 utf16BEdecode,
312 utf8encode,
313 utf8length,
314 utf8seek,
316 /* sound */
317 #if CONFIG_CODEC == SWCODEC
318 sound_default,
319 #endif
320 sound_set,
321 set_sound,
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 set_option,
409 set_bool_options,
410 set_int,
411 set_bool,
412 #ifdef HAVE_LCD_COLOR
413 set_color,
414 #endif
416 /* action handling */
417 get_custom_action,
418 get_action,
419 action_signalscreenchange,
420 action_userabort,
422 /* power */
423 battery_level,
424 battery_level_safe,
425 battery_time,
426 #ifndef SIMULATOR
427 battery_voltage,
428 #endif
429 #if CONFIG_CHARGING
430 charger_inserted,
431 # if CONFIG_CHARGING == CHARGING_MONITOR
432 charging_state,
433 # endif
434 #endif
435 #ifdef HAVE_USB_POWER
436 usb_powered,
437 #endif
439 /* misc */
440 srand,
441 rand,
442 (qsort_func)qsort,
443 kbd_input,
444 get_time,
445 set_time,
446 plugin_get_buffer,
447 plugin_get_audio_buffer,
448 plugin_tsr,
449 #ifdef IRAM_STEAL
450 plugin_iram_init,
451 #endif
452 #if defined(DEBUG) || defined(SIMULATOR)
453 debugf,
454 #endif
455 #ifdef ROCKBOX_HAS_LOGF
456 _logf,
457 #endif
458 &global_settings,
459 &global_status,
460 mp3info,
461 count_mp3_frames,
462 create_xing_header,
463 find_next_frame,
464 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
465 peak_meter_scale_value,
466 peak_meter_set_use_dbfs,
467 peak_meter_get_use_dbfs,
468 #endif
469 #ifdef HAVE_LCD_BITMAP
470 read_bmp_file,
471 screen_dump_set_hook,
472 #endif
473 show_logo,
474 tree_get_context,
476 #ifdef HAVE_WHEEL_POSITION
477 wheel_status,
478 wheel_send_events,
479 #endif
481 #ifdef IRIVER_H100_SERIES
482 /* Routines for the iriver_flash -plugin. */
483 detect_original_firmware,
484 detect_flashed_ramimage,
485 detect_flashed_romimage,
486 #endif
487 /* new stuff at the end, sort into place next time
488 the API gets incompatible */
489 #if NUM_CORES > 1
490 spinlock_init,
491 spinlock_lock,
492 spinlock_unlock,
493 #endif
495 #if (CONFIG_CODEC == SWCODEC)
496 codec_load_file,
497 get_codec_filename,
498 get_metadata,
499 #endif
502 int plugin_load(const char* plugin, void* parameter)
504 int rc;
505 struct plugin_header *hdr;
506 const char *p = strrchr(plugin,'/');
507 #ifdef SIMULATOR
508 void *pd;
509 #else
510 int fd;
511 ssize_t readsize;
512 #endif
513 int xm, ym;
514 #ifdef HAVE_REMOTE_LCD
515 int rxm, rym;
516 #endif
518 #if LCD_DEPTH > 1
519 fb_data* old_backdrop;
520 #endif
522 if (!p)
523 p = plugin;
524 action_signalscreenchange();
526 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
528 if (pfn_tsr_exit(!strcmp(current_plugin,p)) == false )
530 /* not allowing another plugin to load */
531 return PLUGIN_OK;
533 pfn_tsr_exit = NULL;
534 plugin_loaded = false;
537 gui_syncsplash(0, str(LANG_WAIT));
538 strcpy(current_plugin,p);
540 #ifdef SIMULATOR
541 hdr = sim_plugin_load((char *)plugin, &pd);
542 if (pd == NULL) {
543 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
544 return -1;
546 if (hdr == NULL
547 || hdr->magic != PLUGIN_MAGIC
548 || hdr->target_id != TARGET_ID) {
549 sim_plugin_close(pd);
550 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
551 return -1;
553 if (hdr->api_version > PLUGIN_API_VERSION
554 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
555 sim_plugin_close(pd);
556 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
557 return -1;
559 #else
560 fd = open(plugin, O_RDONLY);
561 if (fd < 0) {
562 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
563 return fd;
566 readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE);
567 close(fd);
569 if (readsize < 0) {
570 gui_syncsplash(HZ*2, str(LANG_READ_FAILED), plugin);
571 return -1;
573 hdr = (struct plugin_header *)pluginbuf;
575 if ((unsigned)readsize <= sizeof(struct plugin_header)
576 || hdr->magic != PLUGIN_MAGIC
577 || hdr->target_id != TARGET_ID
578 || hdr->load_addr != pluginbuf
579 || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) {
580 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
581 return -1;
583 if (hdr->api_version > PLUGIN_API_VERSION
584 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
585 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
586 return -1;
588 plugin_size = hdr->end_addr - pluginbuf;
590 /* zero out bss area only, above guards end of pluginbuf */
591 if (plugin_size > readsize)
592 memset(pluginbuf + readsize, 0, plugin_size - readsize);
593 #endif
595 plugin_loaded = true;
597 xm = lcd_getxmargin();
598 ym = lcd_getymargin();
599 lcd_setmargins(0,0);
601 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
602 old_backdrop = lcd_get_backdrop();
603 #endif
604 lcd_clear_display();
605 lcd_update();
607 #ifdef HAVE_REMOTE_LCD
608 rxm = lcd_remote_getxmargin();
609 rym = lcd_remote_getymargin();
610 lcd_remote_setmargins(0, 0);
611 lcd_remote_clear_display();
612 lcd_remote_update();
613 #endif
615 invalidate_icache();
617 rc = hdr->entry_point((struct plugin_api*) &rockbox_api, parameter);
618 /* explicitly casting the pointer here to avoid touching every plugin. */
620 action_signalscreenchange();
621 button_clear_queue();
623 #ifdef HAVE_LCD_BITMAP
624 #if LCD_DEPTH > 1
625 lcd_set_backdrop(old_backdrop);
626 #ifdef HAVE_LCD_COLOR
627 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color,
628 global_settings.bg_color);
629 #else
630 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG);
631 #endif
632 #else /* LCD_DEPTH == 1 */
633 lcd_set_drawmode(DRMODE_SOLID);
634 #endif /* LCD_DEPTH */
635 #endif /* HAVE_LCD_BITMAP */
637 /* restore margins */
638 lcd_setmargins(xm,ym);
639 lcd_clear_display();
640 lcd_update();
642 #ifdef HAVE_REMOTE_LCD
643 #if LCD_REMOTE_DEPTH > 1
644 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG,
645 LCD_REMOTE_DEFAULT_BG);
646 #else
647 lcd_remote_set_drawmode(DRMODE_SOLID);
648 #endif
649 lcd_remote_setmargins(rxm, rym);
650 lcd_remote_clear_display();
651 lcd_remote_update();
652 #endif
654 if (pfn_tsr_exit == NULL)
655 plugin_loaded = false;
657 sim_plugin_close(pd);
659 switch (rc) {
660 case PLUGIN_OK:
661 break;
663 case PLUGIN_USB_CONNECTED:
664 return PLUGIN_USB_CONNECTED;
666 default:
667 gui_syncsplash(HZ*2, str(LANG_PLUGIN_ERROR));
668 break;
670 return PLUGIN_OK;
673 /* Returns a pointer to the portion of the plugin buffer that is not already
674 being used. If no plugin is loaded, returns the entire plugin buffer */
675 void* plugin_get_buffer(size_t *buffer_size)
677 int buffer_pos;
679 if (plugin_loaded)
681 if (plugin_size >= PLUGIN_BUFFER_SIZE)
682 return NULL;
684 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
685 buffer_pos = plugin_size;
687 else
689 *buffer_size = PLUGIN_BUFFER_SIZE;
690 buffer_pos = 0;
693 return &pluginbuf[buffer_pos];
696 /* Returns a pointer to the mp3 buffer.
697 Playback gets stopped, to avoid conflicts.
698 Talk buffer is stolen as well.
700 void* plugin_get_audio_buffer(size_t *buffer_size)
702 #if CONFIG_CODEC == SWCODEC
703 return audio_get_buffer(true, buffer_size);
704 #else
705 audio_stop();
706 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
707 *buffer_size = audiobufend - audiobuf;
708 return audiobuf;
709 #endif
712 #ifdef IRAM_STEAL
713 /* Initializes plugin IRAM */
714 void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
715 char *iedata, size_t iedata_size)
717 audio_iram_steal();
718 memcpy(iramstart, iramcopy, iram_size);
719 memset(iedata, 0, iedata_size);
720 memset(iramcopy, 0, iram_size);
722 #endif /* IRAM_STEAL */
724 /* The plugin wants to stay resident after leaving its main function, e.g.
725 runs from timer or own thread. The callback is registered to later
726 instruct it to free its resources before a new plugin gets loaded. */
727 void plugin_tsr(bool (*exit_callback)(bool))
729 pfn_tsr_exit = exit_callback; /* remember the callback for later */