1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
23 #include <timefuncs.h>
40 #include "mp3_playback.h"
41 #include "backlight.h"
45 #include "powermgmt.h"
47 #ifdef HAVE_LCD_BITMAP
48 #include "peakmeter.h"
55 #include "plugin-win32.h"
59 #define PREFIX(_x_) sim_ ## _x_
61 #define PREFIX(_x_) _x_
64 #define PLUGIN_BUFFER_SIZE 0x8000
67 static unsigned char pluginbuf
[PLUGIN_BUFFER_SIZE
];
69 extern unsigned char pluginbuf
[];
73 static bool plugin_loaded
= false;
74 static int plugin_size
= 0;
76 static void (*pfn_timer
)(void) = NULL
; /* user timer handler */
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
= {
93 #ifdef HAVE_LCD_CHARCELLS
95 lcd_get_locked_pattern
,
120 &lcd_framebuffer
[0][0],
137 (open_func
)PREFIX(open
),
141 (creat_func
)PREFIX(creat
),
164 default_event_handler
,
167 reset_poweroff_timer
,
169 /* strings and memory */
194 /* playback control */
205 mpeg_has_changed_track
,
208 /* MAS communication */
214 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
228 plugin_get_mp3_buffer
,
230 plugin_register_timer
,
231 plugin_unregister_timer
,
234 #if defined(DEBUG) || defined(SIMULATOR)
238 backlight_set_timeout
,
244 /* new stuff at the end, sort into place next time
245 the API gets incompatible */
247 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
250 peak_meter_scale_value
,
251 peak_meter_set_use_dbfs
,
252 peak_meter_get_use_dbfs
,
254 #ifdef HAVE_LCD_BITMAP
255 lcd_puts_scroll_style
,
257 mpeg_flush_and_reload_tracks
,
261 mpeg_get_last_header
,
267 int plugin_load(const char* plugin
, void* parameter
)
269 enum plugin_status (*plugin_start
)(struct plugin_api
* api
, void* param
);
278 #ifdef HAVE_LCD_BITMAP
282 if (pfn_tsr_exit
!= NULL
) /* if we have a resident old plugin: */
284 pfn_tsr_exit(); /* force it to exit now */
288 #ifdef HAVE_LCD_BITMAP
290 xm
= lcd_getxmargin();
291 ym
= lcd_getymargin();
298 snprintf(path
, sizeof path
, "archos%s", plugin
);
300 pd
= dlopen(path
, RTLD_NOW
);
302 snprintf(buf
, sizeof buf
, str(LANG_PLUGIN_CANT_OPEN
), plugin
);
303 splash(HZ
*2, true, buf
);
304 DEBUGF("dlopen(%s): %s\n",path
,dlerror());
309 plugin_start
= dlsym(pd
, "plugin_start");
311 plugin_start
= dlsym(pd
, "_plugin_start");
313 splash(HZ
*2, true, "Can't find entry point");
319 fd
= open(plugin
, O_RDONLY
);
321 snprintf(buf
, sizeof buf
, str(LANG_PLUGIN_CANT_OPEN
), plugin
);
322 splash(HZ
*2, true, buf
);
326 plugin_start
= (void*)&pluginbuf
;
327 plugin_size
= read(fd
, plugin_start
, PLUGIN_BUFFER_SIZE
);
329 if (plugin_size
< 0) {
331 snprintf(buf
, sizeof buf
, str(LANG_READ_FAILED
), plugin
);
332 splash(HZ
*2, true, buf
);
335 if (plugin_size
== 0) {
336 /* loaded a 0-byte plugin, implying it's not for this model */
337 splash(HZ
*2, true, str(LANG_PLUGIN_WRONG_MODEL
));
342 plugin_loaded
= true;
343 rc
= plugin_start((struct plugin_api
*) &rockbox_api
, parameter
);
344 /* explicitly casting the pointer here to avoid touching every plugin. */
346 button_clear_queue();
348 plugin_loaded
= false;
354 case PLUGIN_USB_CONNECTED
:
355 return PLUGIN_USB_CONNECTED
;
357 case PLUGIN_WRONG_API_VERSION
:
358 splash(HZ
*2, true, str(LANG_PLUGIN_WRONG_VERSION
));
361 case PLUGIN_WRONG_MODEL
:
362 splash(HZ
*2, true, str(LANG_PLUGIN_WRONG_MODEL
));
366 splash(HZ
*2, true, str(LANG_PLUGIN_ERROR
));
374 #ifdef HAVE_LCD_BITMAP
375 /* restore margins */
376 lcd_setmargins(xm
,ym
);
382 /* Returns a pointer to the portion of the plugin buffer that is not already
383 being used. If no plugin is loaded, returns the entire plugin buffer */
384 void* plugin_get_buffer(int* buffer_size
)
390 if (plugin_size
>= PLUGIN_BUFFER_SIZE
)
393 *buffer_size
= PLUGIN_BUFFER_SIZE
-plugin_size
;
394 buffer_pos
= plugin_size
;
398 *buffer_size
= PLUGIN_BUFFER_SIZE
;
402 return &pluginbuf
[buffer_pos
];
405 /* Returns a pointer to the mp3 buffer.
406 Playback gets stopped, to avoid conflicts. */
407 void* plugin_get_mp3_buffer(int* buffer_size
)
410 static unsigned char buf
[1700*1024];
411 *buffer_size
= sizeof(buf
);
415 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
416 *buffer_size
= mp3end
- mp3buf
;
422 /* Register a periodic time callback, called every "cycles" CPU clocks.
423 Note that this function will be called in interrupt context! */
424 int plugin_register_timer(int cycles
, int prio
, void (*timer_callback
)(void))
426 int phi
= 0; /* bits for the prescaler */
429 while (cycles
> 0x10000)
430 { /* work out the smallest prescaler that makes it fit */
436 if (prescale
> 8 || cycles
== 0 || prio
< 1 || prio
> 15)
437 return 0; /* error, we can't do such period, bad argument */
439 and_b(~0x10, &TSTR
); /* Stop the timer 4 */
440 and_b(~0x10, &TSNC
); /* No synchronization */
441 and_b(~0x10, &TMDR
); /* Operate normally */
443 pfn_timer
= timer_callback
; /* install 2nd level ISR */
446 TIER4
= 0xF9; /* Enable GRA match interrupt */
448 GRA4
= (unsigned short)(cycles
- 1);
449 TCR4
= 0x20 | phi
; /* clear at GRA match, set prescaler */
450 IPRD
= (IPRD
& 0xFF0F) | prio
<< 4; /* interrupt priority */
451 or_b(0x10, &TSTR
); /* start timer 4 */
453 return cycles
* prescale
; /* return the actual period, in CPU clocks */
456 /* disable the user timer */
457 void plugin_unregister_timer(void)
459 and_b(~0x10, &TSTR
); /* stop the timer 4 */
460 IPRD
= (IPRD
& 0xFF0F); /* disable interrupt */
464 /* interrupt handler for user timer */
468 if (pfn_timer
!= NULL
)
469 pfn_timer(); /* call the user timer function */
470 and_b(~0x01, &TSR4
); /* clear the interrupt */
472 #endif /* #ifndef SIMULATOR */
474 /* The plugin wants to stay resident after leaving its main function, e.g.
475 runs from timer or own thread. The callback is registered to later
476 instruct it to free its resources before a new plugin gets loaded. */
477 void plugin_tsr(void (*exit_callback
)(void))
479 pfn_tsr_exit
= exit_callback
; /* remember the callback for later */
483 static int plugin_test(int api_version
, int model
, int memsize
)
485 if (api_version
< PLUGIN_MIN_API_VERSION
||
486 api_version
> PLUGIN_API_VERSION
)
487 return PLUGIN_WRONG_API_VERSION
;
490 return PLUGIN_WRONG_MODEL
;
493 return PLUGIN_WRONG_MODEL
;