extend the text editor plugin to be able to modify the .colors file
[Rockbox.git] / apps / plugin.c
blobca0b8a2ba6ec9d3777c47c1eb47b5f148326d720
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_set_backdrop,
108 #endif
109 #if LCD_DEPTH == 16
110 lcd_bitmap_transparent_part,
111 lcd_bitmap_transparent,
112 #endif
113 bidi_l2v,
114 font_get_bits,
115 font_load,
116 lcd_puts_style,
117 lcd_puts_scroll_style,
118 &lcd_framebuffer[0][0],
119 lcd_blit,
120 lcd_update_rect,
121 gui_scrollbar_draw,
122 font_get,
123 font_getstringsize,
124 font_get_width,
125 #endif
126 backlight_on,
127 backlight_off,
128 backlight_set_timeout,
129 gui_syncsplash,
130 #ifdef HAVE_REMOTE_LCD
131 /* remote lcd */
132 lcd_remote_set_contrast,
133 lcd_remote_clear_display,
134 lcd_remote_puts,
135 lcd_remote_puts_scroll,
136 lcd_remote_stop_scroll,
137 lcd_remote_set_drawmode,
138 lcd_remote_get_drawmode,
139 lcd_remote_setfont,
140 lcd_remote_getstringsize,
141 lcd_remote_drawpixel,
142 lcd_remote_drawline,
143 lcd_remote_hline,
144 lcd_remote_vline,
145 lcd_remote_drawrect,
146 lcd_remote_fillrect,
147 lcd_remote_mono_bitmap_part,
148 lcd_remote_mono_bitmap,
149 lcd_remote_putsxy,
150 lcd_remote_puts_style,
151 lcd_remote_puts_scroll_style,
152 &lcd_remote_framebuffer[0][0],
153 lcd_remote_update,
154 lcd_remote_update_rect,
156 remote_backlight_on,
157 remote_backlight_off,
158 #endif
159 #if NB_SCREENS == 2
160 {&screens[SCREEN_MAIN], &screens[SCREEN_REMOTE]},
161 #else
162 {&screens[SCREEN_MAIN]},
163 #endif
164 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
165 lcd_remote_set_foreground,
166 lcd_remote_get_foreground,
167 lcd_remote_set_background,
168 lcd_remote_get_background,
169 lcd_remote_bitmap_part,
170 lcd_remote_bitmap,
171 #endif
173 #if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR)
174 lcd_yuv_blit,
175 #endif
176 /* list */
177 gui_synclist_init,
178 gui_synclist_set_nb_items,
179 gui_synclist_set_icon_callback,
180 gui_synclist_get_nb_items,
181 gui_synclist_get_sel_pos,
182 gui_synclist_draw,
183 gui_synclist_select_item,
184 gui_synclist_add_item,
185 gui_synclist_del_item,
186 gui_synclist_limit_scroll,
187 gui_synclist_flash,
188 gui_synclist_do_button,
189 gui_synclist_set_title,
191 /* button */
192 button_get,
193 button_get_w_tmo,
194 button_status,
195 button_clear_queue,
196 #ifdef HAS_BUTTON_HOLD
197 button_hold,
198 #endif
200 /* file */
201 (open_func)PREFIX(open),
202 close,
203 (read_func)read,
204 PREFIX(lseek),
205 (creat_func)PREFIX(creat),
206 (write_func)write,
207 PREFIX(remove),
208 PREFIX(rename),
209 PREFIX(ftruncate),
210 PREFIX(filesize),
211 fdprintf,
212 read_line,
213 settings_parseline,
214 #ifndef SIMULATOR
215 ata_sleep,
216 ata_disk_is_active,
217 #endif
218 ata_spindown,
219 reload_directory,
221 /* dir */
222 PREFIX(opendir),
223 PREFIX(closedir),
224 PREFIX(readdir),
225 PREFIX(mkdir),
226 PREFIX(rmdir),
228 /* dir, cached */
229 #ifdef HAVE_DIRCACHE
230 opendir_cached,
231 readdir_cached,
232 closedir_cached,
233 #endif
235 /* kernel/ system */
236 PREFIX(sleep),
237 yield,
238 #ifdef HAVE_PRIORITY_SCHEDULING
239 priority_yield,
240 #endif
241 &current_tick,
242 default_event_handler,
243 default_event_handler_ex,
244 create_thread,
245 remove_thread,
246 reset_poweroff_timer,
247 #ifndef SIMULATOR
248 system_memory_guard,
249 &cpu_frequency,
251 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
252 #ifdef CPU_BOOST_LOGGING
253 cpu_boost_,
254 #else
255 cpu_boost,
256 #endif
257 #endif
258 timer_register,
259 timer_unregister,
260 timer_set_period,
261 #endif
262 queue_init,
263 queue_delete,
264 queue_post,
265 queue_wait_w_tmo,
266 usb_acknowledge,
267 #ifdef RB_PROFILE
268 profile_thread,
269 profstop,
270 profile_func_enter,
271 profile_func_exit,
272 #endif
274 #ifdef SIMULATOR
275 /* special simulator hooks */
276 #if defined(HAVE_LCD_BITMAP) && LCD_DEPTH < 8
277 sim_lcd_ex_init,
278 sim_lcd_ex_update_rect,
279 #endif
280 #endif
282 /* strings and memory */
283 snprintf,
284 vsnprintf,
285 strcpy,
286 strncpy,
287 strlen,
288 strrchr,
289 strcmp,
290 strncmp,
291 strcasecmp,
292 strncasecmp,
293 memset,
294 memcpy,
295 memmove,
296 _ctype_,
297 atoi,
298 strchr,
299 strcat,
300 memchr,
301 memcmp,
302 strcasestr,
303 strtok_r,
304 /* unicode stuff */
305 utf8decode,
306 iso_decode,
307 utf16LEdecode,
308 utf16BEdecode,
309 utf8encode,
310 utf8length,
311 utf8seek,
313 /* sound */
314 #if CONFIG_CODEC == SWCODEC
315 sound_default,
316 #endif
317 sound_set,
318 set_sound,
320 sound_min,
321 sound_max,
322 #ifndef SIMULATOR
323 mp3_play_data,
324 mp3_play_pause,
325 mp3_play_stop,
326 mp3_is_playing,
327 #if CONFIG_CODEC != SWCODEC
328 bitswap,
329 #endif
330 #endif
331 #if CONFIG_CODEC == SWCODEC
332 &audio_master_sampr_list[0],
333 &hw_freq_sampr[0],
334 pcm_apply_settings,
335 pcm_play_data,
336 pcm_play_stop,
337 pcm_set_frequency,
338 pcm_is_playing,
339 pcm_is_paused,
340 pcm_play_pause,
341 pcm_get_bytes_waiting,
342 pcm_calculate_peaks,
343 #ifdef HAVE_RECORDING
344 &rec_freq_sampr[0],
345 pcm_init_recording,
346 pcm_close_recording,
347 pcm_record_data,
348 pcm_record_more,
349 pcm_stop_recording,
350 pcm_calculate_rec_peaks,
351 audio_set_recording_gain,
352 #endif /* HAVE_RECORDING */
353 #if INPUT_SRC_CAPS != 0
354 audio_set_output_source,
355 audio_set_input_source,
356 #endif
357 #endif /* CONFIG_CODEC == SWCODEC */
359 /* playback control */
360 playlist_amount,
361 playlist_resume,
362 playlist_start,
363 PREFIX(audio_play),
364 audio_stop,
365 audio_pause,
366 audio_resume,
367 audio_next,
368 audio_prev,
369 audio_ff_rewind,
370 audio_next_track,
371 audio_status,
372 audio_has_changed_track,
373 audio_current_track,
374 audio_flush_and_reload_tracks,
375 audio_get_file_pos,
376 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
377 mpeg_get_last_header,
378 #endif
379 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
380 (CONFIG_CODEC == SWCODEC)
381 sound_set_pitch,
382 #endif
384 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
385 /* MAS communication */
386 mas_readmem,
387 mas_writemem,
388 mas_readreg,
389 mas_writereg,
390 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
391 mas_codec_writereg,
392 mas_codec_readreg,
393 i2c_begin,
394 i2c_end,
395 i2c_write,
396 #endif
397 #endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
399 /* menu */
400 do_menu,
401 /* statusbars */
402 &statusbars,
403 gui_syncstatusbar_draw,
404 /* options */
405 set_option,
406 set_int,
407 set_bool,
409 /* action handling */
410 get_custom_action,
411 get_action,
412 action_signalscreenchange,
413 action_userabort,
415 /* power */
416 battery_level,
417 battery_level_safe,
418 battery_time,
419 #ifndef SIMULATOR
420 battery_voltage,
421 #endif
422 #if CONFIG_CHARGING
423 charger_inserted,
424 # if CONFIG_CHARGING == CHARGING_MONITOR
425 charging_state,
426 # endif
427 #endif
428 #ifdef HAVE_USB_POWER
429 usb_powered,
430 #endif
432 /* misc */
433 srand,
434 rand,
435 (qsort_func)qsort,
436 kbd_input,
437 get_time,
438 set_time,
439 plugin_get_buffer,
440 plugin_get_audio_buffer,
441 plugin_tsr,
442 #ifdef IRAM_STEAL
443 plugin_iram_init,
444 #endif
445 #if defined(DEBUG) || defined(SIMULATOR)
446 debugf,
447 #endif
448 #ifdef ROCKBOX_HAS_LOGF
449 _logf,
450 #endif
451 &global_settings,
452 &global_status,
453 mp3info,
454 count_mp3_frames,
455 create_xing_header,
456 find_next_frame,
457 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
458 peak_meter_scale_value,
459 peak_meter_set_use_dbfs,
460 peak_meter_get_use_dbfs,
461 #endif
462 #ifdef HAVE_LCD_BITMAP
463 read_bmp_file,
464 screen_dump_set_hook,
465 #endif
466 show_logo,
467 tree_get_context,
469 #ifdef HAVE_WHEEL_POSITION
470 wheel_status,
471 wheel_send_events,
472 #endif
473 #if LCD_DEPTH > 1
474 lcd_get_backdrop,
475 #endif
477 /* new stuff at the end, sort into place next time
478 the API gets incompatible */
480 #ifdef IRIVER_H100_SERIES
481 /* Routines for the iriver_flash -plugin. */
482 detect_original_firmware,
483 detect_flashed_ramimage,
484 detect_flashed_romimage,
485 #endif
487 #if NUM_CORES > 1
488 spinlock_init,
489 spinlock_lock,
490 spinlock_unlock,
491 #endif
493 #if (CONFIG_CODEC == SWCODEC)
494 codec_load_file,
495 get_metadata,
496 get_codec_filename,
497 #endif
498 threads,
499 create_numbered_filename,
500 set_bool_options,
501 #ifdef HAVE_LCD_COLOR
502 set_color,
503 #endif
506 int plugin_load(const char* plugin, void* parameter)
508 int rc;
509 struct plugin_header *hdr;
510 const char *p = strrchr(plugin,'/');
511 #ifdef SIMULATOR
512 void *pd;
513 #else
514 int fd;
515 ssize_t readsize;
516 #endif
517 int xm, ym;
518 #ifdef HAVE_REMOTE_LCD
519 int rxm, rym;
520 #endif
522 #if LCD_DEPTH > 1
523 fb_data* old_backdrop;
524 #endif
526 if (!p)
527 p = plugin;
528 action_signalscreenchange();
530 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
532 if (pfn_tsr_exit(!strcmp(current_plugin,p)) == false )
534 /* not allowing another plugin to load */
535 return PLUGIN_OK;
537 pfn_tsr_exit = NULL;
538 plugin_loaded = false;
541 gui_syncsplash(0, str(LANG_WAIT));
542 strcpy(current_plugin,p);
544 #ifdef SIMULATOR
545 hdr = sim_plugin_load((char *)plugin, &pd);
546 if (pd == NULL) {
547 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
548 return -1;
550 if (hdr == NULL
551 || hdr->magic != PLUGIN_MAGIC
552 || hdr->target_id != TARGET_ID) {
553 sim_plugin_close(pd);
554 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
555 return -1;
557 if (hdr->api_version > PLUGIN_API_VERSION
558 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
559 sim_plugin_close(pd);
560 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
561 return -1;
563 #else
564 fd = open(plugin, O_RDONLY);
565 if (fd < 0) {
566 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
567 return fd;
570 readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE);
571 close(fd);
573 if (readsize < 0) {
574 gui_syncsplash(HZ*2, str(LANG_READ_FAILED), plugin);
575 return -1;
577 hdr = (struct plugin_header *)pluginbuf;
579 if ((unsigned)readsize <= sizeof(struct plugin_header)
580 || hdr->magic != PLUGIN_MAGIC
581 || hdr->target_id != TARGET_ID
582 || hdr->load_addr != pluginbuf
583 || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) {
584 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
585 return -1;
587 if (hdr->api_version > PLUGIN_API_VERSION
588 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
589 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
590 return -1;
592 plugin_size = hdr->end_addr - pluginbuf;
594 /* zero out bss area only, above guards end of pluginbuf */
595 if (plugin_size > readsize)
596 memset(pluginbuf + readsize, 0, plugin_size - readsize);
597 #endif
599 plugin_loaded = true;
601 xm = lcd_getxmargin();
602 ym = lcd_getymargin();
603 lcd_setmargins(0,0);
605 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
606 old_backdrop = lcd_get_backdrop();
607 #endif
608 lcd_clear_display();
609 lcd_update();
611 #ifdef HAVE_REMOTE_LCD
612 rxm = lcd_remote_getxmargin();
613 rym = lcd_remote_getymargin();
614 lcd_remote_setmargins(0, 0);
615 lcd_remote_clear_display();
616 lcd_remote_update();
617 #endif
619 invalidate_icache();
621 rc = hdr->entry_point((struct plugin_api*) &rockbox_api, parameter);
622 /* explicitly casting the pointer here to avoid touching every plugin. */
624 action_signalscreenchange();
625 button_clear_queue();
627 #ifdef HAVE_LCD_BITMAP
628 #if LCD_DEPTH > 1
629 lcd_set_backdrop(old_backdrop);
630 #ifdef HAVE_LCD_COLOR
631 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color,
632 global_settings.bg_color);
633 #else
634 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG);
635 #endif
636 #else /* LCD_DEPTH == 1 */
637 lcd_set_drawmode(DRMODE_SOLID);
638 #endif /* LCD_DEPTH */
639 #endif /* HAVE_LCD_BITMAP */
641 /* restore margins */
642 lcd_setmargins(xm,ym);
643 lcd_clear_display();
644 lcd_update();
646 #ifdef HAVE_REMOTE_LCD
647 #if LCD_REMOTE_DEPTH > 1
648 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG,
649 LCD_REMOTE_DEFAULT_BG);
650 #else
651 lcd_remote_set_drawmode(DRMODE_SOLID);
652 #endif
653 lcd_remote_setmargins(rxm, rym);
654 lcd_remote_clear_display();
655 lcd_remote_update();
656 #endif
658 if (pfn_tsr_exit == NULL)
659 plugin_loaded = false;
661 sim_plugin_close(pd);
663 switch (rc) {
664 case PLUGIN_OK:
665 break;
667 case PLUGIN_USB_CONNECTED:
668 return PLUGIN_USB_CONNECTED;
670 default:
671 gui_syncsplash(HZ*2, str(LANG_PLUGIN_ERROR));
672 break;
674 return PLUGIN_OK;
677 /* Returns a pointer to the portion of the plugin buffer that is not already
678 being used. If no plugin is loaded, returns the entire plugin buffer */
679 void* plugin_get_buffer(size_t *buffer_size)
681 int buffer_pos;
683 if (plugin_loaded)
685 if (plugin_size >= PLUGIN_BUFFER_SIZE)
686 return NULL;
688 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
689 buffer_pos = plugin_size;
691 else
693 *buffer_size = PLUGIN_BUFFER_SIZE;
694 buffer_pos = 0;
697 return &pluginbuf[buffer_pos];
700 /* Returns a pointer to the mp3 buffer.
701 Playback gets stopped, to avoid conflicts.
702 Talk buffer is stolen as well.
704 void* plugin_get_audio_buffer(size_t *buffer_size)
706 #if CONFIG_CODEC == SWCODEC
707 return audio_get_buffer(true, buffer_size);
708 #else
709 audio_stop();
710 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
711 *buffer_size = audiobufend - audiobuf;
712 return audiobuf;
713 #endif
716 #ifdef IRAM_STEAL
717 /* Initializes plugin IRAM */
718 void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
719 char *iedata, size_t iedata_size)
721 audio_iram_steal();
722 memcpy(iramstart, iramcopy, iram_size);
723 memset(iedata, 0, iedata_size);
724 memset(iramcopy, 0, iram_size);
726 #endif /* IRAM_STEAL */
728 /* The plugin wants to stay resident after leaving its main function, e.g.
729 runs from timer or own thread. The callback is registered to later
730 instruct it to free its resources before a new plugin gets loaded. */
731 void plugin_tsr(bool (*exit_callback)(bool))
733 pfn_tsr_exit = exit_callback; /* remember the callback for later */