forked from len0rd/rockbox
Add MikMod plugin, ported by Jason Yu, with some minor work by Craig Mann and William Peters (FS#8806)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28810 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
d192bdf11e
commit
26f2bfde03
47 changed files with 22320 additions and 1 deletions
943
apps/plugins/mikmod/mikmod.c
Normal file
943
apps/plugins/mikmod/mikmod.c
Normal file
|
@ -0,0 +1,943 @@
|
|||
#define NO_MMSUPP_DEFINES
|
||||
|
||||
#include "plugin.h"
|
||||
#include "lib/configfile.h"
|
||||
#include "mikmod.h"
|
||||
|
||||
|
||||
#undef SYNC
|
||||
#ifdef SIMULATOR
|
||||
#define SYNC
|
||||
#elif NUM_CORES > 1
|
||||
#define USETHREADS
|
||||
#endif
|
||||
|
||||
#define MAX_CHARS LCD_WIDTH/6
|
||||
#define MAX_LINES LCD_HEIGHT/8
|
||||
#define LINE_LENGTH 80
|
||||
|
||||
#define DIR_PREV 1
|
||||
#define DIR_NEXT -1
|
||||
#define DIR_NONE 0
|
||||
|
||||
#define PLUGIN_NEWSONG 10
|
||||
|
||||
/* Persistent configuration */
|
||||
#define MIKMOD_CONFIGFILE "mikmod.cfg"
|
||||
#define MIKMOD_SETTINGS_MINVERSION 1
|
||||
#define MIKMOD_SETTINGS_VERSION 1
|
||||
|
||||
#ifdef USETHREADS
|
||||
#define EV_EXIT 9999
|
||||
#define THREAD_STACK_SIZE DEFAULT_STACK_SIZE + 0x200
|
||||
static unsigned int thread_id;
|
||||
static struct event_queue thread_q;
|
||||
/* use long for aligning */
|
||||
unsigned long thread_stack[THREAD_STACK_SIZE/sizeof(long)];
|
||||
#endif
|
||||
|
||||
/* the current full file name */
|
||||
static char np_file[MAX_PATH];
|
||||
static int curfile = 0, direction = DIR_NEXT, entries = 0;
|
||||
|
||||
/* list of the mod files */
|
||||
static char **file_pt;
|
||||
|
||||
|
||||
/* The MP3 audio buffer which we will use as heap memory */
|
||||
static unsigned char* audio_buffer;
|
||||
/* amount of bytes left in audio_buffer */
|
||||
static size_t audio_buffer_free;
|
||||
|
||||
|
||||
/* The rockbox plugin interface */
|
||||
MEM_FUNCTION_WRAPPERS;
|
||||
|
||||
bool quit;
|
||||
int playingtime IBSS_ATTR;
|
||||
MODULE *module IBSS_ATTR;
|
||||
char gmbuf[BUF_SIZE*NBUF];
|
||||
|
||||
|
||||
int textlines;
|
||||
int vscroll = 0;
|
||||
int hscroll = 0;
|
||||
bool screenupdated = false;
|
||||
|
||||
enum {
|
||||
DISPLAY_INFO = 0,
|
||||
DISPLAY_SAMPLE,
|
||||
DISPLAY_INST,
|
||||
DISPLAY_COMMENTS,
|
||||
} display;
|
||||
|
||||
|
||||
/*
|
||||
* strncat wrapper
|
||||
*/
|
||||
char* mmsupp_strncat(char *s1, const char *s2, size_t n)
|
||||
{
|
||||
char *s = s1;
|
||||
/* Loop over the data in s1. */
|
||||
while (*s != '\0')
|
||||
s++;
|
||||
/* s now points to s1's trailing null character, now copy
|
||||
up to n bytes from s2 into s1 stopping if a null character
|
||||
is encountered in s2.
|
||||
It is not safe to use strncpy here since it copies EXACTLY n
|
||||
characters, NULL padding if necessary. */
|
||||
while (n != 0 && (*s = *s2++) != '\0')
|
||||
{
|
||||
n--;
|
||||
s++;
|
||||
}
|
||||
if (*s != '\0')
|
||||
*s = '\0';
|
||||
return s1;
|
||||
}
|
||||
|
||||
/*
|
||||
* sprintf wrapper
|
||||
*/
|
||||
int mmsupp_sprintf(char *buf, const char *fmt, ... )
|
||||
{
|
||||
bool ok;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ok = rb->vsnprintf(buf, LINE_LENGTH, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* printf wrapper
|
||||
*/
|
||||
void mmsupp_printf(const char *fmt, ...)
|
||||
{
|
||||
static int p_xtpt = 0;
|
||||
char p_buf[LINE_LENGTH];
|
||||
bool ok;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ok = rb->vsnprintf(p_buf, sizeof(p_buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
int i=0;
|
||||
|
||||
/* Device LCDs display newlines funny. */
|
||||
for(i=0; p_buf[i]!=0; i++)
|
||||
if(p_buf[i] == '\n')
|
||||
p_buf[i] = ' ';
|
||||
|
||||
rb->lcd_putsxy(1, p_xtpt, (unsigned char *)p_buf);
|
||||
rb->lcd_update();
|
||||
|
||||
p_xtpt += 8;
|
||||
if(p_xtpt > LCD_HEIGHT-8)
|
||||
{
|
||||
p_xtpt = 0;
|
||||
rb->lcd_clear_display();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************* File Access ***************************/
|
||||
|
||||
/* support function for qsort() */
|
||||
static int compare(const void* p1, const void* p2)
|
||||
{
|
||||
return rb->strcasecmp(*((char **)p1), *((char **)p2));
|
||||
}
|
||||
|
||||
bool mod_ext(const char ext[])
|
||||
{
|
||||
if(!ext)
|
||||
return false;
|
||||
if(!rb->strcasecmp(ext,".669") ||
|
||||
!rb->strcasecmp(ext,".amf") ||
|
||||
!rb->strcasecmp(ext,".asy") ||
|
||||
!rb->strcasecmp(ext,".dsm") ||
|
||||
!rb->strcasecmp(ext,".far") ||
|
||||
!rb->strcasecmp(ext,".gdm") ||
|
||||
!rb->strcasecmp(ext,".gt2") ||
|
||||
!rb->strcasecmp(ext,".imf") ||
|
||||
!rb->strcasecmp(ext,".it") ||
|
||||
!rb->strcasecmp(ext,".m15") ||
|
||||
!rb->strcasecmp(ext,".med") ||
|
||||
!rb->strcasecmp(ext,".mod") ||
|
||||
!rb->strcasecmp(ext,".mtm") ||
|
||||
!rb->strcasecmp(ext,".okt") ||
|
||||
!rb->strcasecmp(ext,".s3m") ||
|
||||
!rb->strcasecmp(ext,".stm") ||
|
||||
!rb->strcasecmp(ext,".stx") ||
|
||||
!rb->strcasecmp(ext,".ult") ||
|
||||
!rb->strcasecmp(ext,".uni") ||
|
||||
!rb->strcasecmp(ext,".xm") )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/*Read directory contents for scrolling. */
|
||||
void get_mod_list(void)
|
||||
{
|
||||
struct tree_context *tree = rb->tree_get_context();
|
||||
struct entry *dircache = tree->dircache;
|
||||
int i;
|
||||
char *pname;
|
||||
|
||||
file_pt = (char **) audio_buffer;
|
||||
|
||||
/* Remove path and leave only the name.*/
|
||||
pname = rb->strrchr(np_file,'/');
|
||||
pname++;
|
||||
|
||||
for (i = 0; i < tree->filesindir && audio_buffer_free > sizeof(char**); i++)
|
||||
{
|
||||
if (!(dircache[i].attr & ATTR_DIRECTORY)
|
||||
&& mod_ext(rb->strrchr(dircache[i].name,'.')))
|
||||
{
|
||||
file_pt[entries] = dircache[i].name;
|
||||
/* Set Selected File. */
|
||||
if (!rb->strcmp(file_pt[entries], pname))
|
||||
curfile = entries;
|
||||
entries++;
|
||||
|
||||
audio_buffer += (sizeof(char**));
|
||||
audio_buffer_free -= (sizeof(char**));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int change_filename(int direct)
|
||||
{
|
||||
bool file_erased = (file_pt[curfile] == NULL);
|
||||
direction = direct;
|
||||
|
||||
curfile += (direct == DIR_PREV? entries - 1: 1);
|
||||
if (curfile >= entries)
|
||||
curfile -= entries;
|
||||
|
||||
if (file_erased)
|
||||
{
|
||||
/* remove 'erased' file names from list. */
|
||||
int count, i;
|
||||
for (count = i = 0; i < entries; i++)
|
||||
{
|
||||
if (curfile == i)
|
||||
curfile = count;
|
||||
if (file_pt[i] != NULL)
|
||||
file_pt[count++] = file_pt[i];
|
||||
}
|
||||
entries = count;
|
||||
}
|
||||
|
||||
if (entries == 0)
|
||||
{
|
||||
rb->splash(HZ, "No supported files");
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
rb->strcpy(rb->strrchr(np_file, '/')+1, file_pt[curfile]);
|
||||
|
||||
return PLUGIN_NEWSONG;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Playback
|
||||
*/
|
||||
|
||||
bool swap = false;
|
||||
bool lastswap = true;
|
||||
|
||||
static inline void synthbuf(void)
|
||||
{
|
||||
char *outptr;
|
||||
|
||||
#ifndef SYNC
|
||||
if (lastswap == swap) return;
|
||||
lastswap = swap;
|
||||
|
||||
outptr = (swap ? gmbuf : gmbuf + BUF_SIZE);
|
||||
#else
|
||||
outptr = gmbuf;
|
||||
#endif
|
||||
|
||||
VC_WriteBytes(outptr, BUF_SIZE);
|
||||
}
|
||||
|
||||
void get_more(unsigned char** start, size_t* size)
|
||||
{
|
||||
#ifndef SYNC
|
||||
if (lastswap != swap)
|
||||
{
|
||||
//printf("Buffer miss!");
|
||||
}
|
||||
|
||||
#else
|
||||
synthbuf();
|
||||
#endif
|
||||
|
||||
*size = BUF_SIZE;
|
||||
#ifndef SYNC
|
||||
*start = (unsigned char*)((swap ? gmbuf : gmbuf + BUF_SIZE));
|
||||
swap = !swap;
|
||||
#else
|
||||
*start = (unsigned char*)(gmbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
void showinfo()
|
||||
{
|
||||
char statustext[LINE_LENGTH];
|
||||
|
||||
if (!module)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rb->lcd_clear_display();
|
||||
|
||||
playingtime = (int)(module->sngtime >> 10);
|
||||
sprintf(statustext, "Name: %s", module->songname);
|
||||
rb->lcd_putsxy(1, 1, statustext);
|
||||
sprintf(statustext, "Type: %s", module->modtype);
|
||||
rb->lcd_putsxy(1, 11, statustext);
|
||||
|
||||
sprintf(statustext, "Samples: %d", module->numsmp);
|
||||
rb->lcd_putsxy(1, 21, statustext);
|
||||
|
||||
if ( module->flags & UF_INST )
|
||||
{
|
||||
sprintf(statustext, "Instruments: %d", module->numins);
|
||||
rb->lcd_putsxy(1, 31, statustext);
|
||||
}
|
||||
|
||||
sprintf(statustext, "pat: %03d/%03d %2.2X",
|
||||
module->sngpos, module->numpos - 1, module->patpos);
|
||||
rb->lcd_putsxy(1, 51, statustext);
|
||||
|
||||
sprintf(statustext, "spd: %d/%d",
|
||||
module->sngspd, module->bpm);
|
||||
rb->lcd_putsxy(1, 61, statustext);
|
||||
|
||||
sprintf(statustext, "vol: %ddB", rb->global_settings->volume);
|
||||
rb->lcd_putsxy(1, 71, statustext);
|
||||
|
||||
sprintf(statustext, "time: %d:%02d",
|
||||
(playingtime / 60) % 60, playingtime % 60);
|
||||
rb->lcd_putsxy(1, 81, statustext);
|
||||
|
||||
if (module->flags & UF_NNA)
|
||||
{
|
||||
sprintf(statustext, "chn: %d/%d+%d->%d",
|
||||
module->realchn, module->numchn,
|
||||
module->totalchn - module->realchn,
|
||||
module->totalchn);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(statustext, "chn: %d/%d",
|
||||
module->realchn, module->numchn);
|
||||
}
|
||||
rb->lcd_putsxy(0, 91, statustext);
|
||||
|
||||
rb->lcd_update();
|
||||
}
|
||||
|
||||
void showsamples()
|
||||
{
|
||||
int i, j;
|
||||
char statustext[LINE_LENGTH];
|
||||
|
||||
if ( screenupdated )
|
||||
{
|
||||
return;
|
||||
}
|
||||
rb->lcd_clear_display();
|
||||
for( i=0; i<MAX_LINES && i+vscroll<module->numsmp; i++ )
|
||||
{
|
||||
sprintf(statustext, "%02d %s", i+vscroll+1, module->samples[i+vscroll].samplename);
|
||||
rb->lcd_putsxy(1, 1+(8*i), statustext);
|
||||
}
|
||||
rb->lcd_update();
|
||||
screenupdated = true;
|
||||
}
|
||||
|
||||
void showinstruments()
|
||||
{
|
||||
int i, j;
|
||||
char statustext[LINE_LENGTH];
|
||||
|
||||
if ( screenupdated )
|
||||
{
|
||||
return;
|
||||
}
|
||||
rb->lcd_clear_display();
|
||||
for( i=0; i<MAX_LINES && i+vscroll<module->numins; i++ )
|
||||
{
|
||||
sprintf(statustext, "%02d %s", i+vscroll+1, module->instruments[i+vscroll].insname);
|
||||
rb->lcd_putsxy(1, 1+(8*i), statustext);
|
||||
}
|
||||
rb->lcd_update();
|
||||
screenupdated = true;
|
||||
}
|
||||
|
||||
void showcomments()
|
||||
{
|
||||
int i, j=0, k=0, l;
|
||||
char statustext[LINE_LENGTH];
|
||||
|
||||
if ( screenupdated )
|
||||
{
|
||||
return;
|
||||
}
|
||||
rb->lcd_clear_display();
|
||||
|
||||
for(i=0; module->comment[i]!='\0'; i++)
|
||||
{
|
||||
if(module->comment[i] != '\n')
|
||||
{
|
||||
statustext[j] = module->comment[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
if(module->comment[i] == '\n' || j>LINE_LENGTH-1)
|
||||
{
|
||||
rb->lcd_putsxy(1-(6*hscroll), 1+(8*k)-(8*vscroll), statustext);
|
||||
for( l=0; l<LINE_LENGTH; l++ )
|
||||
{
|
||||
statustext[l] = 0;
|
||||
}
|
||||
k++;
|
||||
j=0;
|
||||
}
|
||||
}
|
||||
if (j>0)
|
||||
{
|
||||
rb->lcd_putsxy(1-(6*hscroll), 1+(8*k)-(8*vscroll), statustext);
|
||||
}
|
||||
|
||||
rb->lcd_update();
|
||||
screenupdated = true;
|
||||
}
|
||||
|
||||
int changedisplay()
|
||||
{
|
||||
display = (display+1) % 4;
|
||||
|
||||
if (display == DISPLAY_SAMPLE)
|
||||
{
|
||||
textlines = module->numsmp;
|
||||
}
|
||||
|
||||
if (display == DISPLAY_INST)
|
||||
{
|
||||
if ( module->flags & UF_INST )
|
||||
{
|
||||
textlines = module->numins;
|
||||
}
|
||||
else
|
||||
{
|
||||
display = DISPLAY_COMMENTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (display == DISPLAY_COMMENTS)
|
||||
{
|
||||
if (module->comment)
|
||||
{
|
||||
textlines = 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
display = DISPLAY_INFO;
|
||||
}
|
||||
}
|
||||
screenupdated = false;
|
||||
vscroll = 0;
|
||||
hscroll = 0;
|
||||
}
|
||||
|
||||
struct mikmod_settings
|
||||
{
|
||||
int pansep;
|
||||
int reverb;
|
||||
bool interp;
|
||||
bool reverse;
|
||||
bool surround;
|
||||
bool boost;
|
||||
};
|
||||
|
||||
static struct mikmod_settings settings =
|
||||
{
|
||||
128,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1
|
||||
};
|
||||
|
||||
static struct mikmod_settings old_settings;
|
||||
|
||||
static struct configdata config[] =
|
||||
{
|
||||
{ TYPE_INT, 0, 128, { .int_p = &settings.pansep }, "Panning Separation", NULL},
|
||||
{ TYPE_INT, 0, 15, { .int_p = &settings.reverb }, "Reverberation", NULL},
|
||||
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.interp }, "Interpolation", NULL},
|
||||
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.reverse }, "Reverse Channels", NULL},
|
||||
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.surround }, "Surround", NULL},
|
||||
{ TYPE_BOOL, 0, 1, { .bool_p = &settings.boost }, "CPU Boost", NULL},
|
||||
};
|
||||
|
||||
void applysettings()
|
||||
{
|
||||
md_pansep = settings.pansep;
|
||||
md_reverb = settings.reverb;
|
||||
md_mode = DMODE_STEREO | DMODE_16BITS | DMODE_SOFT_MUSIC | DMODE_SOFT_SNDFX;
|
||||
if ( settings.interp )
|
||||
{
|
||||
md_mode |= DMODE_INTERP;
|
||||
}
|
||||
if ( settings.reverse )
|
||||
{
|
||||
md_mode |= DMODE_REVERSE;
|
||||
}
|
||||
if ( settings.surround )
|
||||
{
|
||||
md_mode |= DMODE_SURROUND;
|
||||
}
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
if ( Player_Active() )
|
||||
{
|
||||
rb->cpu_boost(settings.boost);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Shows the settings menu
|
||||
*/
|
||||
int settings_menu(void)
|
||||
{
|
||||
int selection = 0;
|
||||
bool old_val;
|
||||
|
||||
MENUITEM_STRINGLIST(settings_menu, "Mikmod Settings", NULL, "Panning Separation",
|
||||
"Reverberation", "Interpolation", "Reverse Channels", "Surround",
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
"CPU Boost"
|
||||
#endif
|
||||
);
|
||||
|
||||
do
|
||||
{
|
||||
selection=rb->do_menu(&settings_menu,&selection, NULL, false);
|
||||
switch(selection)
|
||||
{
|
||||
case 0:
|
||||
rb->set_int("Panning Separation", "", 1,
|
||||
&(settings.pansep),
|
||||
NULL, 8, 0, 128, NULL );
|
||||
applysettings();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
rb->set_int("Reverberation", "", 1,
|
||||
&(settings.reverb),
|
||||
NULL, 1, 0, 15, NULL );
|
||||
applysettings();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
rb->set_bool("Interpolation", &(settings.interp));
|
||||
applysettings();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
rb->set_bool("Reverse Channels", &(settings.reverse));
|
||||
applysettings();
|
||||
break;
|
||||
|
||||
case 4:
|
||||
rb->set_bool("Surround", &(settings.surround));
|
||||
applysettings();
|
||||
break;
|
||||
|
||||
case 5:
|
||||
rb->set_bool("CPU Boost", &(settings.boost));
|
||||
applysettings();
|
||||
break;
|
||||
|
||||
case MENU_ATTACHED_USB:
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
}
|
||||
} while ( selection >= 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Show the main menu
|
||||
*/
|
||||
int main_menu(void)
|
||||
{
|
||||
int selection = 0;
|
||||
int result;
|
||||
|
||||
MENUITEM_STRINGLIST(main_menu,"Mikmod Main Menu",NULL,
|
||||
"Settings", "Return", "Quit");
|
||||
while (1)
|
||||
{
|
||||
switch (rb->do_menu(&main_menu,&selection, NULL, false))
|
||||
{
|
||||
case 0:
|
||||
result = settings_menu();
|
||||
if ( result != 0 ) return result;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
return 0;
|
||||
|
||||
case 2:
|
||||
return -1;
|
||||
|
||||
case MENU_ATTACHED_USB:
|
||||
return PLUGIN_USB_CONNECTED;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USETHREADS
|
||||
/* double buffering thread */
|
||||
void thread(void)
|
||||
{
|
||||
struct queue_event ev;
|
||||
|
||||
while (1)
|
||||
{
|
||||
synthbuf();
|
||||
rb->queue_wait_w_tmo(&thread_q, &ev, HZ/20);
|
||||
switch (ev.id) {
|
||||
case EV_EXIT:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void mm_errorhandler(void)
|
||||
{
|
||||
rb->splashf(HZ, "%s", MikMod_strerror(MikMod_errno));
|
||||
quit = true;
|
||||
}
|
||||
|
||||
int playfile(char* filename)
|
||||
{
|
||||
int vol = 0;
|
||||
int button;
|
||||
int retval = PLUGIN_OK;
|
||||
bool changingpos = false;
|
||||
int menureturn;
|
||||
|
||||
playingtime = 0;
|
||||
|
||||
rb->splashf(HZ, "Loading %s", filename);
|
||||
|
||||
module = Player_Load(filename, 64, 0);
|
||||
|
||||
if (!module)
|
||||
{
|
||||
rb->splashf(HZ, "%s", MikMod_strerror(MikMod_errno));
|
||||
retval = PLUGIN_ERROR;
|
||||
quit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
display = DISPLAY_INFO;
|
||||
Player_Start(module);
|
||||
rb->pcm_play_data(&get_more, NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
if ( settings.boost )
|
||||
rb->cpu_boost(true);
|
||||
#endif
|
||||
#ifdef USETHREADS
|
||||
rb->queue_init(&thread_q, true);
|
||||
if ((thread_id = rb->create_thread(thread, thread_stack,
|
||||
sizeof(thread_stack), 0, "render buffering thread"
|
||||
IF_PRIO(, PRIORITY_PLAYBACK)
|
||||
IF_COP(, CPU))) == 0)
|
||||
{
|
||||
rb->splash(HZ, "Cannot create thread!");
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (!quit && Player_Active() && retval == PLUGIN_OK)
|
||||
{
|
||||
#if !defined(SYNC) && !defined(USETHREADS)
|
||||
synthbuf();
|
||||
#endif
|
||||
switch (display)
|
||||
{
|
||||
case DISPLAY_SAMPLE:
|
||||
showsamples();
|
||||
break;
|
||||
case DISPLAY_INST:
|
||||
showinstruments();
|
||||
break;
|
||||
case DISPLAY_COMMENTS:
|
||||
showcomments();
|
||||
break;
|
||||
default:
|
||||
showinfo();
|
||||
}
|
||||
|
||||
rb->yield();
|
||||
|
||||
/* Prevent idle poweroff */
|
||||
rb->reset_poweroff_timer();
|
||||
|
||||
button = rb->get_action(CONTEXT_WPS, TIMEOUT_NOBLOCK);
|
||||
switch (button)
|
||||
{
|
||||
case ACTION_WPS_VOLUP:
|
||||
if ( display != DISPLAY_INFO )
|
||||
{
|
||||
if ( textlines-vscroll >= MAX_LINES )
|
||||
{
|
||||
vscroll++;
|
||||
screenupdated = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
vol = rb->global_settings->volume;
|
||||
if (vol < rb->sound_max(SOUND_VOLUME))
|
||||
{
|
||||
vol++;
|
||||
rb->sound_set(SOUND_VOLUME, vol);
|
||||
rb->global_settings->volume = vol;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTION_WPS_VOLDOWN:
|
||||
if ( display != DISPLAY_INFO )
|
||||
{
|
||||
if ( vscroll > 0 )
|
||||
{
|
||||
vscroll--;
|
||||
screenupdated = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
vol = rb->global_settings->volume;
|
||||
if (vol > rb->sound_min(SOUND_VOLUME))
|
||||
{
|
||||
vol--;
|
||||
rb->sound_set(SOUND_VOLUME, vol);
|
||||
rb->global_settings->volume = vol;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACTION_WPS_SKIPPREV:
|
||||
if(entries>1 && !changingpos)
|
||||
{
|
||||
if ((int)(module->sngtime >> 10) > 2)
|
||||
{
|
||||
Player_SetPosition(0);
|
||||
module->sngtime = 0;
|
||||
}
|
||||
else {
|
||||
retval = change_filename(DIR_PREV);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
changingpos = false;
|
||||
}
|
||||
break;
|
||||
case ACTION_WPS_SEEKBACK:
|
||||
if ( display != DISPLAY_INFO )
|
||||
{
|
||||
if ( hscroll > 0 )
|
||||
{
|
||||
hscroll--;
|
||||
screenupdated = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
Player_PrevPosition();
|
||||
changingpos = true;
|
||||
break;
|
||||
|
||||
case ACTION_WPS_SKIPNEXT:
|
||||
if(entries>1 && !changingpos)
|
||||
{
|
||||
retval = change_filename(DIR_NEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
changingpos = false;
|
||||
}
|
||||
break;
|
||||
case ACTION_WPS_SEEKFWD:
|
||||
if ( display != DISPLAY_INFO )
|
||||
{
|
||||
hscroll++;
|
||||
screenupdated = false;
|
||||
break;
|
||||
}
|
||||
Player_NextPosition();
|
||||
changingpos = true;
|
||||
break;
|
||||
|
||||
case ACTION_WPS_PLAY:
|
||||
if(!Player_Paused())
|
||||
{
|
||||
rb->pcm_play_stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
rb->pcm_play_data(&get_more, NULL, 0);
|
||||
}
|
||||
Player_TogglePause();
|
||||
break;
|
||||
|
||||
case ACTION_WPS_BROWSE:
|
||||
changedisplay();
|
||||
break;
|
||||
|
||||
case ACTION_WPS_MENU:
|
||||
menureturn = main_menu();
|
||||
if ( menureturn != 0 )
|
||||
{
|
||||
quit = true;
|
||||
if ( menureturn == PLUGIN_USB_CONNECTED )
|
||||
{
|
||||
retval = menureturn;
|
||||
}
|
||||
}
|
||||
rb->lcd_setfont(0);
|
||||
screenupdated = false;
|
||||
break;
|
||||
|
||||
case ACTION_WPS_STOP:
|
||||
quit = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
|
||||
{
|
||||
quit = true;
|
||||
retval = PLUGIN_USB_CONNECTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USETHREADS
|
||||
rb->queue_post(&thread_q, EV_EXIT, 0);
|
||||
rb->thread_wait(thread_id);
|
||||
rb->queue_delete(&thread_q);
|
||||
#endif
|
||||
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
||||
if ( settings.boost )
|
||||
rb->cpu_boost(false);
|
||||
#endif
|
||||
|
||||
Player_Stop();
|
||||
Player_Free(module);
|
||||
|
||||
memset(gmbuf, '\0', sizeof(gmbuf));
|
||||
|
||||
if ( retval == PLUGIN_OK && entries > 1 && !quit )
|
||||
{
|
||||
retval = change_filename(DIR_NEXT);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Plugin entry point
|
||||
*
|
||||
*/
|
||||
enum plugin_status plugin_start(const void* parameter)
|
||||
{
|
||||
enum plugin_status retval;
|
||||
|
||||
if (parameter == NULL)
|
||||
{
|
||||
rb->splash(HZ*2, " Play .mod, .it, .s3m, .xm file ");
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
rb->lcd_setfont(0);
|
||||
|
||||
rb->pcm_play_stop();
|
||||
#if INPUT_SRC_CAPS != 0
|
||||
/* Select playback */
|
||||
rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
|
||||
rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
|
||||
#endif
|
||||
rb->pcm_set_frequency(SAMPLE_RATE);
|
||||
|
||||
audio_buffer = rb->plugin_get_audio_buffer((size_t *)&audio_buffer_free);
|
||||
|
||||
rb->strcpy(np_file, parameter);
|
||||
get_mod_list();
|
||||
if(!entries) {
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
//add_pool(audio_buffer, audio_buffer_free);
|
||||
init_memory_pool(audio_buffer_free, audio_buffer);
|
||||
|
||||
MikMod_RegisterDriver(&drv_nos);
|
||||
MikMod_RegisterAllLoaders();
|
||||
MikMod_RegisterErrorHandler(mm_errorhandler);
|
||||
|
||||
md_mixfreq = SAMPLE_RATE;
|
||||
|
||||
configfile_load(MIKMOD_CONFIGFILE, config,
|
||||
ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION);
|
||||
rb->memcpy(&old_settings, &settings, sizeof (settings));
|
||||
applysettings();
|
||||
|
||||
if (MikMod_Init(""))
|
||||
{
|
||||
rb->splashf(HZ, "%s", MikMod_strerror(MikMod_errno));
|
||||
return PLUGIN_ERROR;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
retval = playfile(np_file);
|
||||
} while (retval == PLUGIN_NEWSONG);
|
||||
|
||||
MikMod_Exit();
|
||||
|
||||
rb->pcm_play_stop();
|
||||
rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
|
||||
|
||||
if (retval == PLUGIN_OK)
|
||||
{
|
||||
rb->splash(0, "Saving Settings");
|
||||
if (rb->memcmp(&settings, &old_settings, sizeof (settings)))
|
||||
{
|
||||
configfile_save(MIKMOD_CONFIGFILE, config,
|
||||
ARRAYLEN(config), MIKMOD_SETTINGS_MINVERSION);
|
||||
}
|
||||
}
|
||||
|
||||
destroy_memory_pool(audio_buffer);
|
||||
|
||||
return retval;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue