Index: CATEGORIES =================================================================== --- CATEGORIES (revision 14282) +++ CATEGORIES (working copy) @@ -86,6 +86,7 @@ wavplay,viewers wavrecord,apps wavview,viewers +wavsplit,viewers wormlet,games xobox,games zxbox,viewers Index: SOURCES =================================================================== --- SOURCES (revision 14282) +++ SOURCES (working copy) @@ -20,6 +20,7 @@ stopwatch.c vbrfix.c viewer.c +wavsplit.c #if CONFIG_CODEC == SWCODEC metronome.c Index: viewers.config =================================================================== --- viewers.config (revision 14282) +++ viewers.config (working copy) @@ -22,6 +22,7 @@ ss,games/sudoku,1 wav,viewers/wav2wv,- wav,viewers/mp3_encoder,- +wav,viewers/wavsplit,- wav,viewers/wavplay,10 wav,viewers/wavview,10 wav,viewers/test_codec,- Index: wavsplit.c =================================================================== --- wavsplit.c (revision 0) +++ wavsplit.c (revision 0) @@ -0,0 +1,848 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: wavsplit.c 14133 2007-08-01 23:42:41Z domonoky $ + * + * Copyright (C) 2007 Dominik Wenger + * ported from: http://sourceforge.net/projects/wavsplit/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "plugin.h" + +PLUGIN_HEADER + +static struct plugin_api* rb; + +#define BUFFERSIZE 65536 +#define PCM_WAVE_FORMAT 1 + +typedef enum { + USE_HOURS, + USE_FRAMES, + USE_SECONDS +} TIMEFORMAT; + +typedef struct { + int32_t dwSize; + int16_t wFormatTag; + int16_t wChannels; + int32_t dwSamplesPerSec; + int32_t dwAvgBytesPerSec; + int16_t wBlockAlign; + int16_t wBitsPerSample; +} WAVEFORMAT; + +typedef struct { + int8_t RiffID[4]; + int32_t RiffSize; + int8_t WaveID[4]; + int8_t FmtID[4]; + int32_t FmtSize; + int16_t wFormatTag; + int16_t nChannels; + int32_t nSamplesPerSec; + int32_t nAvgBytesPerSec; + int16_t nBlockAlign; + int16_t wBitsPerSample; + int8_t DataID[4]; + int32_t nDataBytes; +} WAVE_HEADER; + +typedef struct { + int hr; + int min; + double sek; /* APF allow decimal point in seconds */ + int seki; /* integer seconds for use with frames */ + double frames; /* specify in frames - default 25fps */ +} timepos; + +static WAVE_HEADER waveheader = { + {'R', 'I', 'F', 'F'}, + 0, + {'W', 'A', 'V', 'E'}, + {'f', 'm', 't', ' '}, + 16, +/* FmtSize*/ + PCM_WAVE_FORMAT, +/* wFormatTag*/ + 0, +/* nChannels*/ + 0, + 0, + 0, + 0, + {'d', 'a', 't', 'a'}, + 0 +}; /* waveheader */ + + +static char *ptr; +static WAVEFORMAT waveformat; +static unsigned long databytes; +static int ifd, ofd; +static char basename[MAX_PATH + 1], ifile[MAX_PATH + 1]; +static char ibuffer[BUFFERSIZE]; +static timepos splitpos[10]; +static int splits=1; +static bool UseHours, UseFrames, UseSeconds, UseTrackLens; +static unsigned long fps; +#define IN_BLK_SIZE 8192 +static char inbuf[IN_BLK_SIZE+1]; + +#define WAV_HEADER_FORMAT "4L44LSSLLSS4L" +/* helper function copied from libwavpack bits.c */ +void little_endian_to_native (void *data, char *format) +{ + unsigned char *cp = (unsigned char *) data; + + while (*format) { + switch (*format) { + case 'L': + *(long *)cp = letoh32(*(long *)cp); + cp += 4; + break; + + case 'S': + *(short *)cp = letoh16(*(short *)cp); + cp += 2; + break; + + default: + if (*format >= '0' && *format <= '9') + cp += *format - '0'; + + break; + } + format++; + } +} +void native_to_little_endian(void *data, char *format) +{ + unsigned char *cp = (unsigned char *) data; + + while (*format) { + switch (*format) { + case 'L': + *(long *)cp = htole32(*(long *)cp); + cp += 4; + break; + + case 'S': + *(short *)cp = htole16(*(short *)cp); + cp += 2; + break; + + default: + if (*format >= '0' && *format <= '9') + cp += *format - '0'; + + break; + } + format++; + } +} + + + +char *findchunk (char *pstart, char *fourcc, size_t n) +{ + char *pend; + int k, test; + pend = pstart + n; + while (pstart < pend) { + if (*pstart == *fourcc) { /* found match for first char */ + test = 1; + for (k = 1; fourcc[k] != 0; k++) + test = (test ? (pstart[k] == fourcc[k]) : 0); + if (test) + return pstart; + }; + pstart++; + }; + return NULL; +} + +int readheader(void) +{ + unsigned long offset; + + if (rb->lseek(ifd, 0L, SEEK_SET)) { + rb->splash(HZ,"Could not locate beginning of input file"); + return 1; + } + + rb->read(ifd, ibuffer, BUFFERSIZE); + if(findchunk (ibuffer, "RIFF", BUFFERSIZE) != ibuffer) { + rb->splash(HZ,"Bad format: Cannot find RIFF file marker"); + return 1; + } + + if(!findchunk (ibuffer, "WAVE", BUFFERSIZE)) { + rb->splash(HZ,"Bad format: Cannot find WAVE file marker"); + return 1; + } + + ptr = findchunk (ibuffer, "fmt ", BUFFERSIZE); + if (!ptr) { + rb->splash(HZ,"Bad format: Cannot find 'fmt' file marker"); + return 1; + } + + little_endian_to_native((WAVE_HEADER *) &ibuffer, WAV_HEADER_FORMAT ); + + ptr += 4; /* we move past fmt_ */ + rb->memcpy(&waveformat, ptr, sizeof (WAVEFORMAT)); + + if (waveformat.dwSize < (sizeof (WAVEFORMAT) - sizeof (unsigned long))) { + rb->splash(HZ,"Bad format: Bad fmt size"); + return 1; + } + + if (waveformat.wFormatTag != PCM_WAVE_FORMAT) { + rb->splash(HZ,"Only supports PCM wave format"); + rb->splash(HZ*2,"tag = %d, PCM = %x\n", waveformat.wFormatTag, + PCM_WAVE_FORMAT); + return 1; + } + + ptr = findchunk(ibuffer, "data", BUFFERSIZE); + + if (!ptr) { + rb->splash(HZ,"Bad format: unable to find 'data' file marker"); + return 1; + } + + ptr += 4; /* we move past data */ + rb->memcpy(&databytes, ptr, sizeof (unsigned long)); + + offset = (unsigned long) ptr + 4 - (unsigned long) ibuffer; + if (rb->lseek (ifd, offset, SEEK_SET) == -1) { + rb->splash(HZ,"Error seeking to WAV data at %lu\n", offset); + //fprintf (stderr, "Error seeking to WAV data at %lu\n", offset); + return 1; + } + + if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / + waveformat.wBlockAlign) { + rb->splash(HZ,"Bad file format"); + return 1; + } + + if (waveformat.dwSamplesPerSec != waveformat.dwAvgBytesPerSec / + waveformat.wChannels / ((waveformat.wBitsPerSample == 16) ? 2 : 1)) { + rb->splash(HZ,"Bad file format"); + return 1; + } + + return 0; +} + + + +int createout (int num, long datasize) +{ + char ofile[MAX_PATH + 1]; + rb->snprintf(ofile,MAX_PATH, "%s/%02d.wav", basename, num); + ofd = rb->creat(ofile); + if (ofd == -1) { + rb->splash(HZ,"Could not create output file '%s'.", ofile); + return 1; + } + waveheader.RiffSize = sizeof (WAVE_HEADER) + datasize - 8; + waveheader.wFormatTag = PCM_WAVE_FORMAT; + waveheader.nChannels = waveformat.wChannels; + waveheader.nSamplesPerSec = waveformat.dwSamplesPerSec; + waveheader.nAvgBytesPerSec = waveformat.dwAvgBytesPerSec; + waveheader.nBlockAlign = waveformat.wBlockAlign; + waveheader.wBitsPerSample = waveformat.wBitsPerSample; + waveheader.nDataBytes = datasize; + + native_to_little_endian( &waveheader,WAV_HEADER_FORMAT); + + if (rb->write (ofd, &waveheader, sizeof (WAVE_HEADER)) != sizeof (WAVE_HEADER)) { + rb->splash(HZ,"Could not write header"); + return 1; + } + + little_endian_to_native(&waveheader,WAV_HEADER_FORMAT); + + return 0; +} + +/* Calculate split point in samples as follows +UseHours =0, UseFrames = 0: + TimeFloat min * 60.0 + sek; + +UseHours = 0, UseFrames= 1: + TimeFloat = min * 60.0 + sek + (frames/fps); + +UseHours = 1, UseFrames =0: + TimeFloat = hr* 3600.0 + min * 60.0 + sek; + +UseHours = 1, UseFrames =1: + TimeFloat = hr* 3600.0 + min * 60.0 + sek + (frames/fps); + +*/ +long calcsplit(unsigned int UseHours, unsigned int UseFrames, + unsigned int fps, unsigned int UseTrackLens, + int splitnr, timepos * split) +{ + static double CumulativeTime = 0.0; /* Static variable to accumulate time for track length mode */ + static double LastSplitTimeFloat = 0.0; /* Allows check for ascending split times */ + + double TimeFloat = 0.0; + double SplitTimeFloat = 0.0; + long pos; + unsigned int Opt = 2 * UseHours + UseFrames; + + switch (Opt) { + case 0: /* UseHours =0, UseFrames = 0 */ + TimeFloat = (double) split[splitnr].min * 60.0 + split[splitnr].sek; + break; /* UseHours =0, UseFrames = 1 */ + case 1: + TimeFloat = (double) split[splitnr].min * 60.0 + + (double) split[splitnr].seki + + (double) split[splitnr].frames / (double) fps; + break; + case 2: /* UseHours = 1, UseFrames = 0 */ + TimeFloat = (double) split[splitnr].hr * 3600.0 + + (double) split[splitnr].min * 60.0 + split[splitnr].sek; + break; + case 3: /* UseHours = 1, UseFrames = 1 */ + TimeFloat = (double) split[splitnr].hr * 3600.0 + + (double) split[splitnr].min * 60.0 + + (double) split[splitnr].seki + + (double) split[splitnr].frames / (double) fps; + break; + default: + break; + } + + /* Accumulate track lengths if necessary. */ + if (UseTrackLens) { + CumulativeTime = CumulativeTime + TimeFloat; + SplitTimeFloat = CumulativeTime; + } + else + SplitTimeFloat = TimeFloat; + + /* Check for ascending split times */ + if (SplitTimeFloat <= LastSplitTimeFloat) + { + rb->splash(HZ,"Split times must be in ascending order"); + } + //Report ("Split times must be in ascending order", "ERROR", verbose); + /* Remember last split time so check can be carried out next time */ + LastSplitTimeFloat = SplitTimeFloat; + + /* first calculate to the nearest sample, then scale by the */ + /* block size to avoid getting e.g. half a block */ + + pos = (long) ((SplitTimeFloat * (double) waveformat.dwSamplesPerSec)); + pos = pos * waveformat.wBlockAlign; + + return pos; +} + +long stdread (char *buf, long nchars) +{ + int n_read; + int to_be_read = nchars; + + while (to_be_read) { + n_read = rb->read(ifd, buf, to_be_read); + if (n_read < 0) + return -1; + if (n_read == 0) + break; + to_be_read -= n_read; + buf += n_read; + } + return nchars - to_be_read; +} + + + + +int split (unsigned int UseHours, unsigned int UseFrames, + unsigned int fps, unsigned int UseTrackLens, int splits, + timepos * split) +{ + + char *bp_out; + long to_write, to_read, n_read, pos; + int fnr = 0; + + + + rb->lcd_clear_display(); + rb->lcd_puts(1,1,"calk splittime"); + rb->lcd_update(); + + /* Erste Datei öffnen */ + to_write = calcsplit(UseHours, UseFrames, fps, UseTrackLens, fnr, split); + pos = to_write; + rb->lcd_puts(1,1,"creatout"); + rb->lcd_update(); + if (createout (fnr + 1, to_write) > 0) + return 1; + + rb->lcd_puts(1,1,"begin splitting"); + rb->lcd_update(); + int counter=0; + do { + char text[30]; + rb->snprintf(text,30,"counter: %x", counter++); + rb->lcd_puts(1,1,text); + rb->lcd_update(); + n_read = (long) stdread (inbuf, IN_BLK_SIZE + 1); + if (n_read < 0) { + rb->splash(HZ,"Error while reading"); + return 1; + } + bp_out = inbuf; + to_read = n_read; + for (;;) { + if (to_read < to_write) { + if (to_read) { /* do not write 0 bytes! */ + if (rb->write (ofd, bp_out, to_read) == -1) { + rb->splash(HZ,"Error while writing"); + return 1; + } + to_write -= to_read; + } + break; + } + else { + if (rb->write (ofd, bp_out, to_write) == -1) { + rb->splash(HZ,"Error while writing"); + return 1; + } + bp_out += to_write; + to_read -= to_write; + + if (++fnr < splits) { + to_write = + calcsplit (UseHours, UseFrames, fps, UseTrackLens, fnr, + split) - pos; + } + else { + to_write = databytes - pos; + if (to_write == 0) { + /* Nothing to write any more */ + n_read = 0; + break; + } + else { + // if (verbose) + // printf + // ("[%02d]\tuntil the end %12ld 100.00%%\n", + // fnr + 1, databytes); + } + } + pos += to_write; + rb->close (ofd); + if (to_write > 0) { + if (createout (fnr + 1, to_write) > 0) + return 1; + } + } + } + } + while (n_read == IN_BLK_SIZE + 1); + + // if (verbose) + // printf ("Success.\n\n"); + rb->splash(HZ,"Success."); + rb->close(ofd); + + //free (buf); + return 0; +} +/***************************************** +* Draws the main screen +*******************************************/ +void showscreen(int selectedsplit,int selectedpos) +{ + int i; + int selected; + int fontheight; + int fontwidth; + int x=2; + int y=2; + char buf[256]; + rb->lcd_clear_display(); + rb->lcd_putsxy(x,y,"Splitting points"); + rb->lcd_getstringsize("Splitting points",&fontwidth,&fontheight); + y += fontheight; + if(UseSeconds) + { + rb->lcd_putsxy(x,y,"Seconds: sss.sss"); + selected = 3; + } + else if(UseHours && UseFrames) + { + rb->lcd_putsxy(x,y,"hh:mm:ss:ff.ff"); + selected = selectedpos; + } + else if(UseHours && !UseFrames ) + { + rb->lcd_putsxy(x,y,"hh:mm:ss.ss"); + selected = selectedpos; + } + else if(UseFrames && !UseHours ) + { + rb->lcd_putsxy(x,y,"ss:ff.ff"); + if(selectedpos==1) selected = 3; + else if(selectedpos == 2) selected = 4; + } + + y += fontheight; + + for(i = 0 ; i < splits ; i++) + { + int drawmode; + if(UseHours) + { + snprintf(buf,256,"%02d:",splitpos[i].hr); + rb->lcd_putsxy(x,y,buf); + rb->lcd_getstringsize(buf,&fontwidth,&fontheight); + if(selectedsplit==i && selected ==1) + { + drawmode = rb->lcd_get_drawmode(); + rb->lcd_set_drawmode(DRMODE_COMPLEMENT ); + rb->lcd_fillrect(x,y,fontwidth,fontheight); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + x+= fontwidth; + + snprintf(buf,256,"%02d:",splitpos[i].min); + rb->lcd_putsxy(x,y,buf); + rb->lcd_getstringsize(buf,&fontwidth,&fontheight); + if(selectedsplit==i && selected ==2) + { + drawmode = rb->lcd_get_drawmode(); + rb->lcd_set_drawmode(DRMODE_COMPLEMENT ); + rb->lcd_fillrect(x,y,fontwidth,fontheight); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + x+= fontwidth; + } + + if(!UseSeconds ) + { + snprintf(buf,256,"%02d:",splitpos[i].seki); + rb->lcd_putsxy(x,y,buf); + rb->lcd_getstringsize(buf,&fontwidth,&fontheight); + if(selectedsplit==i && selected ==3) + { + drawmode = rb->lcd_get_drawmode(); + rb->lcd_set_drawmode(DRMODE_COMPLEMENT ); + rb->lcd_fillrect(x,y,fontwidth,fontheight); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + x+= fontwidth; + } + else + { + snprintf(buf,256,"%02.02f",splitpos[i].sek); + rb->lcd_putsxy(x,y,buf); + rb->lcd_getstringsize(buf,&fontwidth,&fontheight); + if(selectedsplit==i && selected ==3) + { + drawmode = rb->lcd_get_drawmode(); + rb->lcd_set_drawmode(DRMODE_COMPLEMENT ); + rb->lcd_fillrect(x,y,fontwidth,fontheight); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + x+= fontwidth; + } + + if(UseFrames) + { + snprintf(buf,256,"%02.02f",splitpos[i].frames); + rb->lcd_putsxy(x,y,buf); + rb->lcd_getstringsize(buf,&fontwidth,&fontheight); + if(selectedsplit==i && selected ==4) + { + drawmode = rb->lcd_get_drawmode(); + rb->lcd_set_drawmode(DRMODE_COMPLEMENT ); + rb->lcd_fillrect(x,y,fontwidth,fontheight); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + } + x=2; + y += fontheight*2; + } + + rb->lcd_putsxy(x,y,"Start Splitting"); + rb->lcd_getstringsize("Start Splitting",&fontwidth,&fontheight); + if(selectedsplit == splits) + { + rb->lcd_set_drawmode(DRMODE_COMPLEMENT ); + rb->lcd_fillrect(x,y,fontwidth,fontheight); + rb->lcd_set_drawmode(DRMODE_SOLID); + } + + rb->lcd_update(); +} + +/************************************************ + * handles the menü +**************************************************/ +bool showmenu() +{ + MENUITEM_STRINGLIST(menu,"WavSplit Menu",NULL,"Num Splitpoints","Use Hours/Minutes","Use Frames", + "Frames per Second","Relativ Splitpoints","Return","Quit"); + bool menu_quit = false, result = false; + int selection; + + static const struct opt_items fps_option[5] = { + { "12", -1 }, + { "24", -1 }, + { "25", -1 }, + { "30", -1 }, + { "75", -1 }, + }; + static int fps_values[] = { 12, 24, 25, 30, 75}; + int fps_index; + + while (!menu_quit) + { + switch(rb->do_menu(&menu, &selection)) + { + case 0: /* Num Splitpoints */ + rb->set_int("Num Splitpoints", "", UNIT_INT, &splits, + NULL, 1, 1, 20, NULL ); + break; + case 1: /* Use Hours/Minutes */ + rb->set_bool("Use Hours/Minutes",&UseHours); + break; + case 2: /* Use Frames */ + rb->set_bool("Use Frames",&UseFrames); + if(UseFrames) UseSeconds = false; + else UseSeconds = true; + break; /* Frames per Second */ + case 3: + rb->set_option("Frames per Second", &fps_index, INT, + fps_option, + sizeof(fps_values)/sizeof(int), NULL); + fps=fps_values[fps_index]; + break; + case 4: /*relativ splitpoints */ + rb->set_bool("Relativ Splitpoints",&UseTrackLens); + break; + case 5: /* return from menü */ + menu_quit = true; + result = true; + break; + case 6: /* quit */ + menu_quit = true; + result = false; + break; + default: + menu_quit = true; + result = false; + break; + } + } + + return result; +} + +/************************************************ + * handles keyboard actions for the main screen +**************************************************/ +bool doscreen() +{ + + unsigned int action = 0; + + int selectedsplit=0; + int selectedpos=1; + int max; + + while(1) + { + showscreen(selectedsplit,selectedpos); + + action = rb->get_action(CONTEXT_KEYBOARD, TIMEOUT_BLOCK); + + switch(action) + { + case ACTION_KBD_UP: + if(selectedpos ==1) + { + splitpos[selectedsplit].hr +=1; + } + else if(selectedpos ==2) + { + splitpos[selectedsplit].min +=1; + if(splitpos[selectedsplit].min > 60) splitpos[selectedsplit].min = 0; + } + else if(selectedpos ==3) + { + if(UseSeconds) + { + splitpos[selectedsplit].sek +=0.01; + } + else + { + splitpos[selectedsplit].seki +=1; + if(splitpos[selectedsplit].sek > 60) splitpos[selectedsplit].sek = 0; + } + } + else if(selectedpos ==4) + { + splitpos[selectedsplit].frames +=0.01; + if(splitpos[selectedsplit].frames > fps) splitpos[selectedsplit].frames = 0; + } + break; + case ACTION_KBD_DOWN: + if(selectedpos ==1) + { + splitpos[selectedsplit].hr -=1; + if(splitpos[selectedsplit].hr < 0 ) splitpos[selectedsplit].hr = 0; + } + else if(selectedpos ==2) + { + splitpos[selectedsplit].min -=1; + if(splitpos[selectedsplit].min < 0) splitpos[selectedsplit].min = 60; + } + else if(selectedpos ==3) + { + if(UseSeconds) + { + splitpos[selectedsplit].sek -=0.01; + if(splitpos[selectedsplit].sek < 0) splitpos[selectedsplit].sek = 60; + + } + else + { + splitpos[selectedsplit].seki -=1; + if(splitpos[selectedsplit].seki < 0) splitpos[selectedsplit].seki = 60; + } + + } + else if(selectedpos ==4) + { + splitpos[selectedsplit].frames -=0.01; + if(splitpos[selectedsplit].frames < 0) splitpos[selectedsplit].frames = fps; + } + break; + case ACTION_KBD_LEFT: + + selectedpos--; + if(UseSeconds) max = 1; + if(UseHours && UseFrames) max = 4; + if(UseHours && !UseFrames) max = 3; + + if(selectedpos < 1) + { + selectedpos=max; + selectedsplit--; + if(selectedsplit <0) selectedsplit =splits; + } + break; + case ACTION_KBD_RIGHT: + + selectedpos++; + if(UseSeconds) max = 1; + if(UseHours && UseFrames) max = 4; + if(UseHours && !UseFrames) max = 3; + + if(selectedpos > max) + { + selectedpos=1; + selectedsplit++; + if(selectedsplit > splits) selectedsplit =0; + } + break; + case ACTION_KBD_ABORT: + return false; + case ACTION_KBD_SELECT: + if(selectedsplit==splits) + return true; + break; + case ACTION_KBD_PAGE_FLIP: + //menü + if(!showmenu()) + { + return false; + } + break; + default: + //return false; + break; + } + } +} + + +/* this is the plugin entry point */ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + + + rb = api; /* use the "standard" rb pointer */ + rb->lcd_puts(1,1,"Starting"); + rb->lcd_update(); + + splits=2; + fps = 25; + + UseHours=1; + UseFrames=1; + UseSeconds=0; + UseTrackLens=1; + fps = 25; + splits=2; + + if(!doscreen()) + { + return PLUGIN_USB_CONNECTED; + } + + + /* Clear screen */ + rb->lcd_clear_display(); + rb->lcd_update(); + rb->splash(HZ,parameter); + rb->strcpy (ifile, parameter); + rb->strcpy (basename, ifile); + + //rb->lcd_update(); + if (rb->strcmp(basename + rb->strlen(basename) - 4, ".wav") == 0 || + rb->strcmp(basename + rb->strlen(basename) - 4, ".WAV") == 0) + basename[rb->strlen(basename) - 4] = '\0'; + + rb->mkdir(basename); + + ifd = rb->open (ifile, O_RDONLY); + if (ifd == -1) { + return 1; + } + if (readheader() > 0) + { + rb->splash(HZ,"read Header failed"); + return 1; + } + if (split(UseHours, UseFrames, fps, UseTrackLens, splits, splitpos) > 0) + return 1; + rb->close(ifd); + + // return (game == 0) ? PLUGIN_OK : PLUGIN_USB_CONNECTED; + return PLUGIN_OK; +} + +