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
,
104 lcd_puts_scroll_style
,
121 &lcd_framebuffer
[0][0],
129 backlight_set_timeout
,
139 (open_func
)PREFIX(open
),
143 (creat_func
)PREFIX(creat
),
165 default_event_handler
,
166 default_event_handler_ex
,
169 reset_poweroff_timer
,
174 /* strings and memory */
200 /* playback control */
211 mpeg_has_changed_track
,
213 mpeg_flush_and_reload_tracks
,
215 mpeg_get_last_header
,
216 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
220 /* MAS communication */
226 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
240 plugin_get_mp3_buffer
,
242 plugin_register_timer
,
243 plugin_unregister_timer
,
246 #if defined(DEBUG) || defined(SIMULATOR)
256 #if (CONFIG_HWCODEC == MAS3587F) || (CONFIG_HWCODEC == MAS3539F)
257 peak_meter_scale_value
,
258 peak_meter_set_use_dbfs
,
259 peak_meter_get_use_dbfs
,
262 /* new stuff at the end, sort into place next time
263 the API gets incompatible */
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 /* zero out plugin buffer to ensure a properly zeroed bss area */
327 memset(pluginbuf
, 0, PLUGIN_BUFFER_SIZE
);
329 plugin_start
= (void*)&pluginbuf
;
330 plugin_size
= read(fd
, plugin_start
, PLUGIN_BUFFER_SIZE
);
332 if (plugin_size
< 0) {
334 snprintf(buf
, sizeof buf
, str(LANG_READ_FAILED
), plugin
);
335 splash(HZ
*2, true, buf
);
338 if (plugin_size
== 0) {
339 /* loaded a 0-byte plugin, implying it's not for this model */
340 splash(HZ
*2, true, str(LANG_PLUGIN_WRONG_MODEL
));
345 plugin_loaded
= true;
346 rc
= plugin_start((struct plugin_api
*) &rockbox_api
, parameter
);
347 /* explicitly casting the pointer here to avoid touching every plugin. */
349 button_clear_queue();
351 plugin_loaded
= false;
357 case PLUGIN_USB_CONNECTED
:
358 return PLUGIN_USB_CONNECTED
;
360 case PLUGIN_WRONG_API_VERSION
:
361 splash(HZ
*2, true, str(LANG_PLUGIN_WRONG_VERSION
));
364 case PLUGIN_WRONG_MODEL
:
365 splash(HZ
*2, true, str(LANG_PLUGIN_WRONG_MODEL
));
369 splash(HZ
*2, true, str(LANG_PLUGIN_ERROR
));
377 #ifdef HAVE_LCD_BITMAP
378 /* restore margins */
379 lcd_setmargins(xm
,ym
);
385 /* Returns a pointer to the portion of the plugin buffer that is not already
386 being used. If no plugin is loaded, returns the entire plugin buffer */
387 void* plugin_get_buffer(int* buffer_size
)
393 if (plugin_size
>= PLUGIN_BUFFER_SIZE
)
396 *buffer_size
= PLUGIN_BUFFER_SIZE
-plugin_size
;
397 buffer_pos
= plugin_size
;
401 *buffer_size
= PLUGIN_BUFFER_SIZE
;
405 return &pluginbuf
[buffer_pos
];
408 /* Returns a pointer to the mp3 buffer.
409 Playback gets stopped, to avoid conflicts. */
410 void* plugin_get_mp3_buffer(int* buffer_size
)
413 static unsigned char buf
[1700*1024];
414 *buffer_size
= sizeof(buf
);
418 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
419 *buffer_size
= mp3end
- mp3buf
;
425 /* Register a periodic time callback, called every "cycles" CPU clocks.
426 Note that this function will be called in interrupt context! */
427 int plugin_register_timer(int cycles
, int prio
, void (*timer_callback
)(void))
429 int phi
= 0; /* bits for the prescaler */
432 while (cycles
> 0x10000)
433 { /* work out the smallest prescaler that makes it fit */
439 if (prescale
> 8 || cycles
== 0 || prio
< 1 || prio
> 15)
440 return 0; /* error, we can't do such period, bad argument */
442 and_b(~0x10, &TSTR
); /* Stop the timer 4 */
443 and_b(~0x10, &TSNC
); /* No synchronization */
444 and_b(~0x10, &TMDR
); /* Operate normally */
446 pfn_timer
= timer_callback
; /* install 2nd level ISR */
449 TIER4
= 0xF9; /* Enable GRA match interrupt */
451 GRA4
= (unsigned short)(cycles
- 1);
452 TCR4
= 0x20 | phi
; /* clear at GRA match, set prescaler */
453 IPRD
= (IPRD
& 0xFF0F) | prio
<< 4; /* interrupt priority */
454 or_b(0x10, &TSTR
); /* start timer 4 */
456 return cycles
* prescale
; /* return the actual period, in CPU clocks */
459 /* disable the user timer */
460 void plugin_unregister_timer(void)
462 and_b(~0x10, &TSTR
); /* stop the timer 4 */
463 IPRD
= (IPRD
& 0xFF0F); /* disable interrupt */
467 /* interrupt handler for user timer */
471 if (pfn_timer
!= NULL
)
472 pfn_timer(); /* call the user timer function */
473 and_b(~0x01, &TSR4
); /* clear the interrupt */
475 #endif /* #ifndef SIMULATOR */
477 /* The plugin wants to stay resident after leaving its main function, e.g.
478 runs from timer or own thread. The callback is registered to later
479 instruct it to free its resources before a new plugin gets loaded. */
480 void plugin_tsr(void (*exit_callback
)(void))
482 pfn_tsr_exit
= exit_callback
; /* remember the callback for later */
486 static int plugin_test(int api_version
, int model
, int memsize
)
488 if (api_version
< PLUGIN_MIN_API_VERSION
||
489 api_version
> PLUGIN_API_VERSION
)
490 return PLUGIN_WRONG_API_VERSION
;
493 return PLUGIN_WRONG_MODEL
;
496 return PLUGIN_WRONG_MODEL
;