summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichiel Van Der Kolk <not.valid@email.address>2005-05-08 14:41:41 +0000
committerMichiel Van Der Kolk <not.valid@email.address>2005-05-08 14:41:41 +0000
commitb0e010fc5142acc09b10aa4f6453dd6fbdcb8265 (patch)
tree10e9186fcc373354ff387efbcb29ff941fee5fcb
parenta559cf2e3949fcc0482b656411ed68c1e79bb245 (diff)
downloadrockbox-b0e010fc5142acc09b10aa4f6453dd6fbdcb8265.tar.gz
rockbox-b0e010fc5142acc09b10aa4f6453dd6fbdcb8265.zip
Databox!
The frontend plugin for the searchengine, creates searchengine files (rsp) Its not pretty, but it works. Only compiling for recorder and iriver for now....since i don't know about players... Also, i'm hoping someone will beautify the interface someday. PS. Editing modes aren't fully operational yet. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6432 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/Makefile2
-rw-r--r--apps/plugins/databox/Makefile96
-rw-r--r--apps/plugins/databox/databox.c307
-rw-r--r--apps/plugins/databox/databox.h58
-rw-r--r--apps/plugins/databox/editparser.c203
-rw-r--r--apps/plugins/databox/editparser.h34
-rw-r--r--apps/plugins/databox/edittoken.c186
-rw-r--r--apps/plugins/databox/edittoken.h79
8 files changed, 964 insertions, 1 deletions
diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile
index 23bc12d71a..a8dc01e4e7 100644
--- a/apps/plugins/Makefile
+++ b/apps/plugins/Makefile
@@ -43,7 +43,7 @@ SUBDIRS += searchengine
#for any recorder and iRiver model
ifneq (,$(strip $(foreach tgt,RECORDER IRIVER,$(findstring $(tgt),$(TARGET)))))
- SUBDIRS += rockboy
+ SUBDIRS += rockboy databox
endif
diff --git a/apps/plugins/databox/Makefile b/apps/plugins/databox/Makefile
new file mode 100644
index 0000000000..25457b8c6c
--- /dev/null
+++ b/apps/plugins/databox/Makefile
@@ -0,0 +1,96 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
+ -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(OUTDIR)
+CFLAGS = $(GCCOPTS) -O3 $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \
+ -DMEM=${MEMORYSIZE} -DPLUGIN
+
+ifdef APPEXTRA
+ INCLUDES += -I$(APPSDIR)/$(APPEXTRA)
+endif
+
+LINKFILE := $(OBJDIR)/link.lds
+DEPFILE = $(OBJDIR)/dep-databox
+SRC = databox.c editparser.c edittoken.c
+
+SOURCES = $(SRC)
+OBJS := $(SRC:%.c=$(OBJDIR)/%.o)
+DIRS = .
+
+LDS := ../plugin.lds
+OUTPUT = $(OUTDIR)/databox.rock
+
+all: $(OUTPUT)
+
+ifndef SIMVER
+$(OBJDIR)/databox.elf: $(OBJS) $(LINKFILE) $(OUTDIR)/libplugin.a
+ @echo "LD $@"
+ @$(CC) $(GCCOPTS) -O -nostdlib -o $@ $(OBJS) -L$(OUTDIR) -lplugin -lgcc \
+ -T$(LINKFILE) -Wl,-Map,$(OBJDIR)/searchengine.map
+
+$(OUTPUT): $(OBJDIR)/databox.elf
+ @echo "OBJCOPY $<"
+ @$(OC) -O binary $< $@
+else
+
+ifeq ($(SIMVER), x11)
+###################################################
+# This is the X11 simulator version
+
+$(OUTPUT): $(OBJS) $(OUTDIR)/libplugin.a
+ @echo "LD $@"
+ @$(CC) $(CFLAGS) -shared $(OBJS) -L$(OUTDIR) -lplugin -o $@
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+# 'x' must be kept or you'll have "Win32 error 5"
+# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
+# #define ERROR_ACCESS_DENIED 5L
+else
+ @chmod -x $@
+endif
+
+else # end of x11-simulator
+###################################################
+# This is the win32 simulator version
+DLLTOOLFLAGS = --export-all
+DLLWRAPFLAGS = -s --entry _DllMain@12 --target=i386-mingw32 -mno-cygwin
+
+$(OUTPUT): $(OBJS) $(OUTDIR)/libplugin.a
+ @echo "DLL $@"
+ @$(DLLTOOL) $(DLLTOOLFLAGS) -z $(OBJDIR)/$*.def $(OBJS)
+ @$(DLLWRAP) $(DLLWRAPFLAGS) --def $(OBJDIR)/$*.def $(OBJS) \
+ $(OUTDIR)/libplugin.a -o $@
+ifeq ($(findstring CYGWIN,$(UNAME)),CYGWIN)
+# 'x' must be kept or you'll have "Win32 error 5"
+# $ fgrep 5 /usr/include/w32api/winerror.h | head -1
+# #define ERROR_ACCESS_DENIED 5L
+else
+ @chmod -x $@
+endif
+endif # end of win32-simulator
+
+endif # end of simulator section
+
+
+include $(TOOLSDIR)/make.inc
+
+# MEM should be passed on to this makefile with the chosen memory size given
+# in number of MB
+$(LINKFILE): $(LDS)
+ @echo "build $@"
+ @cat $< | $(CC) -DMEMORYSIZE=$(MEMORYSIZE) $(INCLUDES) $(TARGET) $(DEFINES) \
+ -E -P - >$@
+
+clean:
+ @echo "cleaning databox"
+ @rm -rf $(OBJDIR)/databox
+ @rm -f $(OBJDIR)/databox.* $(DEPFILE)
+
+-include $(DEPFILE)
+
diff --git a/apps/plugins/databox/databox.c b/apps/plugins/databox/databox.c
new file mode 100644
index 0000000000..811b97e222
--- /dev/null
+++ b/apps/plugins/databox/databox.c
@@ -0,0 +1,307 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Björn Stenberg
+ *
+ * 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 "databox.h"
+
+/* welcome to the example rockbox plugin */
+
+/* here is a global api struct pointer. while not strictly necessary,
+ it's nice not to have to pass the api pointer in all function calls
+ in the plugin */
+struct plugin_api* rb;
+struct token tokenbuf[200];
+
+struct print printing;
+struct editor editor;
+struct editing editing;
+
+extern int acceptedmask;
+
+void databox_init(void) {
+ printing.fontfixed = rb->font_get(FONT_SYSFIXED);
+ rb->lcd_setfont(FONT_SYSFIXED);
+ printing.font_w = printing.fontfixed->maxwidth;
+ printing.font_h = printing.fontfixed->height;
+ printing.line=0;
+ printing.position=0;
+ editor.editingmode = INVALID_MARK;
+ editor.token = tokenbuf;
+}
+
+void print(char *word, int invert) {
+ int strlen=rb->strlen(word), newpos=printing.position+strlen+1;
+ if(newpos*printing.font_w>LCD_WIDTH) {
+ printing.line++;
+ printing.position=0;
+ newpos=printing.position+strlen+1;
+ }
+ rb->lcd_putsxy(printing.font_w*printing.position,printing.font_h*printing.line,word);
+ if(invert)
+ rb->lcd_invertrect(printing.font_w*printing.position,printing.font_h*printing.line,printing.font_w*strlen,printing.font_h);
+ rb->lcd_update_rect(printing.font_w*printing.position,printing.font_h*printing.line,printing.font_w*strlen,printing.font_h);
+ printing.position=newpos;
+}
+
+void displaytstream(struct token *token) {
+ int index=0;
+ while(token[index].kind!=TOKEN_EOF||index==editor.currentindex) {
+ if(editing.selecting&&index==editor.currentindex) {
+ print(tokentypetostring(editing.selection_candidates[editing.currentselection]),1);
+ }
+ else
+ print(tokentostring(&token[index]),index==editor.currentindex ? 1 : 0);
+ index++;
+ }
+}
+
+void buildchoices(int mask) {
+ int i;
+ for(i=0;i<20;i++)
+ editing.selection_candidates[i]=-1;
+ i=0;
+ if(editing.selecting&&
+ editing.old_token.kind!=TOKEN_EOF &&
+ editing.old_token.kind!=TOKEN_INVALID) {
+ editing.selection_candidates[i++]=TOKEN_EDIT;
+ }
+ if((mask&ACCEPT_EOF)&&editor.valid)
+ editing.selection_candidates[i++]=TOKEN_EOF;
+ if(mask&ACCEPT_NOT)
+ editing.selection_candidates[i++]=TOKEN_NOT;
+ if(mask&ACCEPT_BOOLOP) {
+ editing.selection_candidates[i++]=TOKEN_AND;
+ editing.selection_candidates[i++]=TOKEN_OR;
+ }
+ if(mask&ACCEPT_NUMOP) {
+ editing.selection_candidates[i++]=TOKEN_GT;
+ editing.selection_candidates[i++]=TOKEN_GTE;
+ editing.selection_candidates[i++]=TOKEN_LT;
+ editing.selection_candidates[i++]=TOKEN_LTE;
+ editing.selection_candidates[i++]=TOKEN_NE;
+ editing.selection_candidates[i++]=TOKEN_EQ;
+ }
+ if(mask&ACCEPT_STROP) {
+ editing.selection_candidates[i++]=TOKEN_CONTAINS;
+ editing.selection_candidates[i++]=TOKEN_EQUALS;
+ }
+ if(mask&ACCEPT_LPAREN) {
+ editing.selection_candidates[i++]=TOKEN_LPAREN;
+ }
+ if(mask&ACCEPT_RPAREN) {
+ editing.selection_candidates[i++]=TOKEN_RPAREN;
+ }
+ if(mask&ACCEPT_NUMARG) {
+ editing.selection_candidates[i++]=TOKEN_NUM;
+ editing.selection_candidates[i++]=TOKEN_YEAR;
+ editing.selection_candidates[i++]=TOKEN_RATING;
+ editing.selection_candidates[i++]=TOKEN_PLAYCOUNT;
+ }
+ if(mask&ACCEPT_STRARG) {
+ editing.selection_candidates[i++]=TOKEN_STRING;
+ editing.selection_candidates[i++]=TOKEN_TITLE;
+ editing.selection_candidates[i++]=TOKEN_ARTIST;
+ editing.selection_candidates[i++]=TOKEN_ALBUM;
+ editing.selection_candidates[i++]=TOKEN_GENRE;
+ editing.selection_candidates[i++]=TOKEN_FILENAME;
+ }
+ editing.selectionmax=i;
+}
+
+/* returns tokencount or 0 if error */
+int readtstream(char *filename,struct token *token,int max) {
+ int tokencount=0;
+ int filelen,i;
+ int fd;
+ rb->memset(token,0,max*sizeof(struct token));
+ fd=rb->open(filename,O_RDONLY);
+ if(fd>=0) {
+ filelen=rb->filesize(fd);
+ if(filelen>0) {
+ if(filelen % sizeof(struct token)) {
+ rb->splash(HZ*2,true,"Filesize not a multiple of sizeof(struct token)");
+ rb->close(fd);
+ return 0;
+ }
+ tokencount=(filelen/sizeof(struct token))-1;
+ for(i=0;i<tokencount&&i<max;i++) {
+ rb->read(fd,&token[i],sizeof(struct token));
+ token[i].intvalue=BE32(token[i].intvalue);
+ }
+ }
+ rb->close(fd);
+ }
+ return tokencount;
+}
+
+int writetstream(char *filename,struct token *token) {
+ int fd,i;
+ fd=rb->open(filename,O_WRONLY|O_CREAT|O_TRUNC);
+ if(fd<0)
+ return 0;
+ i=0;
+ while(token[i].kind!=TOKEN_EOF) {
+ token[i].intvalue=BE32(token[i].intvalue);
+ rb->write(fd,&token[i++],sizeof(struct token));
+ }
+ token[i].intvalue=BE32(token[i].intvalue);
+ rb->write(fd,&token[i++],sizeof(struct token));
+ rb->close(fd);
+ return i;
+}
+
+int hcl_button_get(void) {
+ int oldbuttonstate,newbuttonstate,pressed=0;
+ oldbuttonstate = rb->button_status();
+ do {
+ newbuttonstate = rb->button_status();
+ pressed = newbuttonstate & ~oldbuttonstate;
+ oldbuttonstate = newbuttonstate;
+ rb->yield();
+ }
+ while(!pressed);
+ rb->button_clear_queue();
+ return pressed;
+}
+
+/* this is the plugin entry point */
+enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
+{
+ int button,done=0;
+ char filename[100],buf[100];
+ /* this macro should be called as the first thing you do in the plugin.
+ it test that the api version and model the plugin was compiled for
+ matches the machine it is running on */
+ TEST_PLUGIN_API(api);
+
+ /* if you don't use the parameter, you can do like
+ this to avoid the compiler warning about it */
+ (void)parameter;
+
+ /* if you are using a global api pointer, don't forget to copy it!
+ otherwise you will get lovely "I04: IllInstr" errors... :-) */
+ rb = api;
+
+ /* now go ahead and have fun! */
+ rb->splash(HZ*2, true, "Databox! Enter filename ^.^");
+ databox_init();
+ if(rb->kbd_input(filename, 100)) {
+ rb->splash(HZ*2, true, "Something went wrong with the filename.. exiting..");
+ return PLUGIN_ERROR;
+ }
+ /* add / in front if omitted */
+ if(filename[0]!='/') {
+ rb->strncpy(buf+1,filename,99);
+ buf[0]='/';
+ rb->strcpy(filename,buf);
+ }
+ /* add extension if omitted */
+ if(rb->strncasecmp(filename+rb->strlen(filename)-4,".rsp",4)) {
+ rb->strcat(filename,".rsp");
+ }
+ rb->lcd_clear_display();
+ rb->lcd_update();
+ editor.currentindex=editor.tokencount=readtstream(filename,editor.token,200);
+ editing.currentselection=0;
+ editing.selecting=editor.currentindex==0 ? 1 : 0;
+ do {
+ rb->lcd_clear_display();
+ rb->lcd_update();
+ printing.line=0;
+ printing.position=0;
+ displaytstream(editor.token);
+ editor.valid=check_tokenstream(editor.token,editor.editingmode);
+ check_accepted(editor.token,editor.currentindex);
+ rb->lcd_update();
+ button=hcl_button_get();
+ if(editing.selecting) {
+ // button handling, up, down, select,stop
+ // up/right = move currentselection one up
+ // down/left = move currentselection one down
+ // select = build token in place.
+ // stop = cancel editing
+ if(button&BUTTON_LEFT
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+ ||button&BUTTON_DOWN
+#endif
+ ) {
+ editing.currentselection=(editing.currentselection+
+ 1) %editing.selectionmax;
+ }
+ if(button&BUTTON_RIGHT
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+ ||button&BUTTON_UP
+#endif
+ ) {
+ editing.currentselection=(editing.currentselection +
+ editing.selectionmax-1) % editing.selectionmax;
+ }
+ if(button&BUTTON_SELECT) {
+ buildtoken(editing.selection_candidates[editing.currentselection],&editor.token[editor.currentindex]);
+ editing.selecting=0;
+ if(editor.token[editor.currentindex].kind==TOKEN_EOF)
+ done=1;
+ else if(editor.currentindex==editor.tokencount) {
+ editor.tokencount++;
+ editor.currentindex++;
+ editor.valid=check_tokenstream(editor.token,editor.editingmode);
+ check_accepted(editor.token,editor.currentindex);
+ editing.selecting=1;
+ editing.currentselection=0;
+ buildchoices(acceptedmask);
+ rb->memcpy(&editing.old_token,&editor.token[editor.currentindex],sizeof(struct token));
+ }
+ }
+ }
+ else {
+ // button handling, left, right, select, stop
+ // left/down = move currentindex down
+ // right/up = move currentindex up
+ // select = enter selecting mode.
+ // stop = quit editor.
+ if(button&BUTTON_LEFT
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+ ||button&BUTTON_DOWN
+#endif
+ ) {
+ editor.currentindex=(editor.currentindex +
+ editor.tokencount) % (editor.tokencount+1);
+ }
+ if(button&BUTTON_RIGHT
+#if CONFIG_KEYPAD == IRIVER_H100_PAD
+ ||button&BUTTON_UP
+#endif
+ ) {
+ editor.currentindex=(editor.currentindex+1) % (editor.tokencount+1);
+ }
+ if(button&BUTTON_SELECT) {
+ editing.selecting=1;
+ editing.currentselection=0;
+ buildchoices(acceptedmask);
+ rb->memcpy(&editing.old_token,&editor.token[editor.currentindex],sizeof(struct token));
+ }
+ }
+ } while (!done);
+ if(writetstream(filename,editor.token)) {
+ rb->splash(HZ*2,true,"Wrote file succesfully ^.^");
+ return PLUGIN_OK;
+ }
+ else {
+ rb->splash(HZ*2,true,"Error while writing rsp :(");
+ return PLUGIN_ERROR;
+ }
+}
diff --git a/apps/plugins/databox/databox.h b/apps/plugins/databox/databox.h
new file mode 100644
index 0000000000..ffbaf1d35d
--- /dev/null
+++ b/apps/plugins/databox/databox.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Michiel van der Kolk
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#ifndef DATABOX_H
+#define DATABOX_H
+#include <stdio.h>
+#include <stdlib.h>
+#include <plugin.h>
+#include <database.h>
+
+#include "edittoken.h"
+#include "editparser.h"
+
+extern struct plugin_api* rb;
+
+struct print {
+ struct font *fontfixed;
+ int font_w,font_h;
+ int line;
+ int position;
+};
+
+struct editor {
+ struct token *token; /* tokenstream */
+ int currentindex; /* index of the token to change.(+1, 1=0 2=1 3=2 etc.) */
+ int tokencount; /* total amount of tokens */
+ int editingmode; /* defined in databox.h */
+ int valid; /* is the current tokenstream valid ? */
+};
+
+struct editing {
+ int selection_candidates[30]; /* possible options for this selecting */
+ struct token old_token; /* only set when selecting, stores old token */
+ int currentselection; /* current selection index */
+ int selectionmax;
+ int selecting; /* boolean */
+};
+
+extern struct print printing;
+extern struct editor editor;
+extern struct editing editing;
+
+#endif
diff --git a/apps/plugins/databox/editparser.c b/apps/plugins/databox/editparser.c
new file mode 100644
index 0000000000..d2fcbc4e6d
--- /dev/null
+++ b/apps/plugins/databox/editparser.c
@@ -0,0 +1,203 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Michiel van der Kolk
+ *
+ * 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 "databox.h"
+#include "edittoken.h"
+#include "editparser.h"
+
+struct token *currenttoken,*lasttoken,*tokenstream;
+int currentindex;
+int lparencount,acceptedmask;
+int tokensleft;
+int invalid;
+int invalid_mode;
+
+void check_accepted(struct token *tstream, int count) {
+ parse_stream(tstream,count+1,INVALID_EXPERT);
+}
+
+void parse_stream(struct token *tstream, int count, int inv_mode) {
+ invalid_mode=inv_mode;
+ acceptedmask=0;
+ lparencount=0;
+ tokensleft=count;
+ currentindex=0;
+ invalid=0;
+ tokenstream=tstream;
+ currenttoken=&tokenstream[currentindex];
+ parseMExpr();
+}
+
+int check_tokenstream(struct token *tstream, int inv_mode) {
+ int inval=0;
+ int i;
+ parse_stream(tstream,-1,inv_mode);
+ inval=invalid;
+ while( (inv_mode==INVALID_STRIP||inv_mode==INVALID_MARK) && invalid)
+ parse_stream(tstream,-1,inv_mode);
+ i=0;
+ while(tstream[i].kind!=TOKEN_EOF)
+ if(tstream[i++].kind==TOKEN_INVALID) {
+ inval=1;
+ break;
+ }
+ return inval==0;
+}
+
+
+void parse_accept_rparen(void) {
+ if(!tokensleft) return;
+ if(lparencount) {
+ acceptedmask|=ACCEPT_RPAREN;
+ }
+}
+
+void parse_accept(int bitmask) {
+ if(!tokensleft) return;
+ acceptedmask|=bitmask;
+ if(lparencount) {
+ acceptedmask&=~ACCEPT_EOF;
+ }
+}
+
+void parse_checktoken() {
+ int ok=0;
+ if(!tokensleft) return;
+ lasttoken=currenttoken;
+ switch(lasttoken->kind) {
+ case TOKEN_EOF:
+ ok=acceptedmask&ACCEPT_EOF;
+ break;
+ case TOKEN_NOT:
+ ok=acceptedmask&ACCEPT_NOT;
+ break;
+ case TOKEN_AND:
+ case TOKEN_OR:
+ ok=acceptedmask&ACCEPT_BOOLOP;
+ break;
+ case TOKEN_GT:
+ case TOKEN_GTE:
+ case TOKEN_LT:
+ case TOKEN_LTE:
+ case TOKEN_NE:
+ case TOKEN_EQ:
+ ok=acceptedmask&ACCEPT_NUMOP;
+ break;
+ case TOKEN_EQUALS:
+ case TOKEN_CONTAINS:
+ ok=acceptedmask&ACCEPT_STROP;
+ break;
+ case TOKEN_STRING:
+ case TOKEN_STRINGIDENTIFIER:
+ ok=acceptedmask&ACCEPT_STRARG;
+ break;
+ case TOKEN_NUM:
+ case TOKEN_NUMIDENTIFIER:
+ ok=acceptedmask&ACCEPT_NUMARG;
+ break;
+ case TOKEN_LPAREN:
+ ok=acceptedmask&ACCEPT_LPAREN;
+ if(ok) lparencount++;
+ break;
+ case TOKEN_RPAREN:
+ ok=acceptedmask&ACCEPT_RPAREN;
+ if(ok) lparencount--;
+ break;
+ case TOKEN_INVALID:
+ if(invalid_mode!=INVALID_STRIP)
+ ok=1;
+ break;
+ }
+ tokensleft--;
+ if(lasttoken->kind==TOKEN_EOF)
+ tokensleft=0;
+ if(!ok&&tokensleft) {
+ // delete token
+ int i=currentindex;
+ //printf("Syntax error. accepted: 0x%x index:%d token: %d %s\n",acceptedmask,currentindex,currenttoken->kind,tokentostring(currenttoken));
+ switch (invalid_mode) {
+ case INVALID_STRIP:
+ do {
+ rb->memcpy(currenttoken,&tokenstream[++i],sizeof(struct token));;
+ currenttoken=&tokenstream[i];
+ } while (currenttoken->kind!=TOKEN_EOF);
+ currenttoken=&tokenstream[currentindex];
+ break;
+ case INVALID_MARK:
+ currenttoken->kind=TOKEN_INVALID;
+ break;
+ }
+ tokensleft=0;
+ invalid=1;
+ }
+ if(tokensleft) {
+ currenttoken=&tokenstream[++currentindex];
+ acceptedmask=0;
+ }
+}
+
+void parseCompareNum() {
+ parse_accept(ACCEPT_NUMOP);
+ parse_checktoken();
+ parse_accept(ACCEPT_NUMARG);
+ parse_checktoken();
+}
+
+void parseCompareString() {
+ parse_accept(ACCEPT_STROP);
+ parse_checktoken();
+ parse_accept(ACCEPT_STRARG);
+ parse_checktoken();
+}
+
+void parseExpr() {
+ if(!tokensleft) return;
+ parse_accept(ACCEPT_NOT|ACCEPT_LPAREN|ACCEPT_NUMARG|ACCEPT_STRARG);
+ parse_checktoken();
+ switch(lasttoken->kind) {
+ case TOKEN_NOT:
+ parseExpr();
+ break;
+ case TOKEN_LPAREN:
+ parseMExpr();
+ break;
+ case TOKEN_NUM:
+ case TOKEN_NUMIDENTIFIER:
+ parseCompareNum();
+ break;
+ case TOKEN_STRING:
+ case TOKEN_STRINGIDENTIFIER:
+ parseCompareString();
+ break;
+ }
+}
+
+void parseMExpr() {
+ parseExpr();
+ parse_accept_rparen();
+ parse_accept(ACCEPT_BOOLOP|ACCEPT_EOF);
+ parse_checktoken();
+ while(lasttoken->kind==TOKEN_OR || lasttoken->kind == TOKEN_AND) {
+ parseExpr();
+ parse_accept_rparen();
+ parse_accept(ACCEPT_BOOLOP|ACCEPT_EOF);
+ parse_checktoken();
+ if(!tokensleft)
+ return;
+ }
+}
diff --git a/apps/plugins/databox/editparser.h b/apps/plugins/databox/editparser.h
new file mode 100644
index 0000000000..3a26cbca70
--- /dev/null
+++ b/apps/plugins/databox/editparser.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Michiel van der Kolk
+ *
+ * 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.
+ *
+ ****************************************************************************/
+extern int acceptedmask;
+
+#define INVALID_STRIP 1
+#define INVALID_MARK 2
+#define INVALID_EXPERT 3
+
+void check_accepted(struct token *tstream, int count);
+void parse_stream(struct token *tstream, int count, int inv_mode);
+int check_tokenstream(struct token *tstream, int inv_mode);
+void parser_accept_rparen(void);
+void parser_accept(int bitmask);
+void parse_checktoken(void);
+void parseCompareNum(void);
+void parseCompareString(void);
+void parseExpr(void);
+void parseMExpr(void);
diff --git a/apps/plugins/databox/edittoken.c b/apps/plugins/databox/edittoken.c
new file mode 100644
index 0000000000..f5b869757b
--- /dev/null
+++ b/apps/plugins/databox/edittoken.c
@@ -0,0 +1,186 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Michiel van der Kolk
+ *
+ * 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 "databox.h"
+#include "edittoken.h"
+
+char *tokentypetostring(int tokentype) {
+ switch(tokentype) {
+ case TOKEN_EOF: return "<END>";
+ case TOKEN_NOT: return "not";
+ case TOKEN_AND: return "and";
+ case TOKEN_OR: return "or";
+ case TOKEN_GT: return ">";
+ case TOKEN_GTE: return ">=";
+ case TOKEN_LT: return "<";
+ case TOKEN_LTE: return "<=";
+ case TOKEN_EQ: return "==";
+ case TOKEN_NE: return "!=";
+ case TOKEN_LPAREN: return "(";
+ case TOKEN_RPAREN: return ")";
+ case TOKEN_CONTAINS: return "contains";
+ case TOKEN_EQUALS: return "equals";
+ case TOKEN_NUM: return "<number>";
+ case TOKEN_NUMIDENTIFIER: return "<numberproperty>";
+ case TOKEN_STRING: return "<string>";
+ case TOKEN_STRINGIDENTIFIER: return "<stringproperty>";
+ case TOKEN_INVALID: return "<INVALID>";
+ case TOKEN_EDIT: return tokentostring(&editing.old_token);
+ case TOKEN_YEAR: return "year";
+ case TOKEN_RATING: return "rating";
+ case TOKEN_PLAYCOUNT: return "playcount";
+ case TOKEN_TITLE: return "title";
+ case TOKEN_ARTIST: return "artist";
+ case TOKEN_ALBUM: return "album";
+ case TOKEN_GENRE: return "genre";
+ case TOKEN_FILENAME: return "filename";
+ }
+ return "tokentypeerror";
+}
+
+char *numidtostring(int numid) {
+ switch(numid) {
+ case INTVALUE_YEAR: return "<year>";
+ case INTVALUE_RATING: return "<rating>";
+ case INTVALUE_PLAYCOUNT: return "<playcount>";
+ }
+ return "numiderror";
+}
+
+char *stridtostring(int strid) {
+ switch(strid) {
+ case INTVALUE_TITLE: return "<title>";
+ case INTVALUE_ARTIST: return "<artist>";
+ case INTVALUE_ALBUM: return "<album>";
+ case INTVALUE_GENRE: return "<genre>";
+ case INTVALUE_FILENAME: return "<filename>";
+ }
+ return "striderror";
+}
+
+char bufbla[40];
+
+void buildtoken(int tokentype,struct token *token) {
+ // TODO
+ char buf[200];
+ rb->memset(token,0,sizeof(struct token));
+ rb->memset(buf,0,200);
+ token->kind=tokentype;
+ token->intvalue=0;
+ switch(token->kind) {
+ case TOKEN_STRING:
+ do {
+ rb->splash(HZ*2,true,"Enter String.");
+ } while(rb->kbd_input(token->spelling, 254));
+ break;
+ case TOKEN_YEAR:
+ token->kind=TOKEN_NUMIDENTIFIER;
+ token->intvalue=INTVALUE_YEAR;
+ break;
+ case TOKEN_RATING:
+ token->kind=TOKEN_NUMIDENTIFIER;
+ token->intvalue=INTVALUE_RATING;
+ break;
+ case TOKEN_PLAYCOUNT:
+ token->kind=TOKEN_NUMIDENTIFIER;
+ token->intvalue=INTVALUE_PLAYCOUNT;
+ break;
+ case TOKEN_TITLE:
+ token->kind=TOKEN_STRINGIDENTIFIER;
+ token->intvalue=INTVALUE_TITLE;
+ break;
+ case TOKEN_ARTIST:
+ token->kind=TOKEN_STRINGIDENTIFIER;
+ token->intvalue=INTVALUE_ARTIST;
+ break;
+ case TOKEN_ALBUM:
+ token->kind=TOKEN_STRINGIDENTIFIER;
+ token->intvalue=INTVALUE_ALBUM;
+ break;
+ case TOKEN_GENRE:
+ token->kind=TOKEN_STRINGIDENTIFIER;
+ token->intvalue=INTVALUE_GENRE;
+ break;
+ case TOKEN_FILENAME:
+ token->kind=TOKEN_STRINGIDENTIFIER;
+ token->intvalue=INTVALUE_TITLE;
+ break;
+ case TOKEN_NUM:
+ do {
+ rb->splash(HZ*2,true,"Enter Number.");
+ } while(rb->kbd_input(buf, 199));
+ token->intvalue=rb->atoi(buf);
+ break;
+ case TOKEN_EDIT:
+ rb->memcpy(token,&editing.old_token,sizeof(struct token));
+ break;
+ }
+}
+
+void removetoken(struct token *token,int index) {
+ struct token *currenttoken;
+ currenttoken=&token[index];
+ do {
+ rb->memcpy(currenttoken,&token[++index],sizeof(struct token));
+ currenttoken=&token[index];
+ } while (currenttoken->kind!=TOKEN_EOF);
+}
+
+void inserttoken(struct token *token,int index,int tokentype) {
+ struct token *currenttoken;
+ int max,i;
+ currenttoken=&token[0];
+ for(i=1;currenttoken->kind!=TOKEN_EOF;i++)
+ currenttoken=&token[i];
+ max=i;
+ for(i=max;i>=index;i--) {
+ rb->memcpy(&token[i+1],&token[i],sizeof(struct token));
+ }
+ buildtoken(tokentype,&token[index]);
+}
+
+
+char *tokentostring(struct token *token) {
+ switch(token->kind) {
+ case TOKEN_INVALID:
+ case TOKEN_EOF:
+ case TOKEN_NOT:
+ case TOKEN_AND:
+ case TOKEN_OR:
+ case TOKEN_GT:
+ case TOKEN_GTE:
+ case TOKEN_LT:
+ case TOKEN_LTE:
+ case TOKEN_EQ:
+ case TOKEN_NE:
+ case TOKEN_LPAREN:
+ case TOKEN_RPAREN:
+ case TOKEN_CONTAINS:
+ case TOKEN_EQUALS:
+ return tokentypetostring(token->kind);
+ case TOKEN_NUM: rb->snprintf(bufbla,40,"%d",token->intvalue);
+ return bufbla;
+ case TOKEN_NUMIDENTIFIER:
+ return numidtostring(token->intvalue);
+ case TOKEN_STRING: return token->spelling;
+ case TOKEN_STRINGIDENTIFIER:
+ return stridtostring(token->intvalue);
+ case TOKEN_EDIT: return tokentostring(&editing.old_token);
+ default: return "unknown token";
+ }
+}
diff --git a/apps/plugins/databox/edittoken.h b/apps/plugins/databox/edittoken.h
new file mode 100644
index 0000000000..a5c8d472e1
--- /dev/null
+++ b/apps/plugins/databox/edittoken.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Michiel van der Kolk
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#ifndef EDITTOKEN_H
+#define EDITTOKEN_H
+
+#define TOKEN_INVALID -1
+#define TOKEN_EOF 0 // EOF
+#define TOKEN_NOT 1 // "not"
+#define TOKEN_AND 2 // "and"
+#define TOKEN_OR 3 // "or"
+#define TOKEN_GT 4 // '>'
+#define TOKEN_GTE 5 // '>='
+#define TOKEN_LT 6 // '<'
+#define TOKEN_LTE 7 // '<='
+#define TOKEN_EQ 8 // '=='
+#define TOKEN_NE 9 // '!='
+#define TOKEN_CONTAINS 10 // "contains"
+#define TOKEN_EQUALS 11 // "equals"
+#define TOKEN_LPAREN 12 // '('
+#define TOKEN_RPAREN 13 // ')'
+#define TOKEN_NUM 14 // (0..9)+
+#define TOKEN_NUMIDENTIFIER 15 // year, trackid, bpm, etc.
+#define TOKEN_STRING 16 // (?)+
+#define TOKEN_STRINGIDENTIFIER 17 // album, artist, title, genre ...
+#define TOKEN_YEAR 18
+#define TOKEN_RATING 19
+#define TOKEN_PLAYCOUNT 20
+#define TOKEN_TITLE 21
+#define TOKEN_ARTIST 22
+#define TOKEN_ALBUM 23
+#define TOKEN_GENRE 24
+#define TOKEN_FILENAME 25
+#define TOKEN_EDIT 26
+
+#define ACCEPT_EOF 0x1
+#define ACCEPT_BOOLOP 0x2
+#define ACCEPT_NUMOP 0x4
+#define ACCEPT_STROP 0x8
+#define ACCEPT_LPAREN 0x10
+#define ACCEPT_RPAREN 0x20
+#define ACCEPT_NUMARG 0x40
+#define ACCEPT_STRARG 0x80
+#define ACCEPT_NOT 0x100
+#define ACCEPT_DELETE 0x200
+
+#define INTVALUE_YEAR 1
+#define INTVALUE_RATING 2
+#define INTVALUE_PLAYCOUNT 3
+#define INTVALUE_TITLE 4
+#define INTVALUE_ARTIST 5
+#define INTVALUE_ALBUM 6
+#define INTVALUE_GENRE 7
+#define INTVALUE_FILENAME 8
+
+struct token {
+ char kind;
+ char spelling[255];
+ long intvalue;
+};
+char *tokentypetostring(int tokentype);
+char *tokentostring(struct token *token);
+void buildtoken(int tokentype,struct token *token);
+#endif