From 9369d4867d3bf033e0e3bbcff05cd7f0a9bb83e8 Mon Sep 17 00:00:00 2001 From: Michiel Van Der Kolk Date: Thu, 28 Apr 2005 12:33:38 +0000 Subject: Search engine core for database v2, has an hardcoded "songs for year >= 1980 and year < 1990" at the moment. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6367 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 6 + apps/plugin.h | 7 +- apps/plugins/Makefile | 2 +- apps/plugins/searchengine/Makefile | 105 ++++++++++++++ apps/plugins/searchengine/dbinterface.c | 97 +++++++++++++ apps/plugins/searchengine/dbinterface.h | 32 +++++ apps/plugins/searchengine/parser.c | 240 +++++++++++++++++++++++++++++++ apps/plugins/searchengine/parser.h | 12 ++ apps/plugins/searchengine/searchengine.c | 101 +++++++++++++ apps/plugins/searchengine/searchengine.h | 37 +++++ apps/plugins/searchengine/token.c | 61 ++++++++ apps/plugins/searchengine/token.h | 40 ++++++ 12 files changed, 738 insertions(+), 2 deletions(-) create mode 100644 apps/plugins/searchengine/Makefile create mode 100644 apps/plugins/searchengine/dbinterface.c create mode 100644 apps/plugins/searchengine/dbinterface.h create mode 100644 apps/plugins/searchengine/parser.c create mode 100644 apps/plugins/searchengine/parser.h create mode 100644 apps/plugins/searchengine/searchengine.c create mode 100644 apps/plugins/searchengine/searchengine.h create mode 100644 apps/plugins/searchengine/token.c create mode 100644 apps/plugins/searchengine/token.h (limited to 'apps') diff --git a/apps/plugin.c b/apps/plugin.c index 76c9ddb8bf..384ab22ede 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -45,6 +45,7 @@ #include "powermgmt.h" #include "system.h" #include "sound.h" +#include "database.h" #if (CONFIG_HWCODEC == MASNONE) #include "pcm_playback.h" #endif @@ -319,6 +320,11 @@ static const struct plugin_api rockbox_api = { #ifdef HAVE_LCD_BITMAP read_bmp_file, #endif + &tagdbheader, + &tagdb_fd, + &tagdb_initialized, + tagdb_init, + strcasestr, }; int plugin_load(const char* plugin, void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index 0bb57b27f1..2604cae4f9 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -78,7 +78,7 @@ #endif /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 38 +#define PLUGIN_API_VERSION 39 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -375,6 +375,11 @@ struct plugin_api { int (*read_bmp_file)(char* filename, int *get_width, int *get_height, char *bitmap, int maxsize); #endif + struct tagdb_header *tagdbheader; + int *tagdb_fd; + int *tagdb_initialized; + int (*tagdb_init) (void); + char *(*strcasestr) (const char* phaystack, const char* pneedle); }; /* defined by the plugin loader (plugin.c) */ diff --git a/apps/plugins/Makefile b/apps/plugins/Makefile index 9c3ff4adc2..83617278d5 100644 --- a/apps/plugins/Makefile +++ b/apps/plugins/Makefile @@ -37,7 +37,7 @@ DIRS = . #for any recorder and iRiver model ifneq (,$(strip $(foreach tgt,RECORDER IRIVER,$(findstring $(tgt),$(TARGET))))) - SUBDIRS += rockboy + SUBDIRS += rockboy searchengine endif .PHONY: $(SUBDIRS) diff --git a/apps/plugins/searchengine/Makefile b/apps/plugins/searchengine/Makefile new file mode 100644 index 0000000000..d7253e2e10 --- /dev/null +++ b/apps/plugins/searchengine/Makefile @@ -0,0 +1,105 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +INCLUDES = -I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \ + -I$(FIRMDIR)/common -I$(FIRMDIR)/drivers +CFLAGS = $(GCCOPTS) -O3 $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) \ + -DMEM=${MEMORYSIZE} -DPLUGIN + +ifdef APPEXTRA + INCLUDES += -I$(APPSDIR)/$(APPEXTRA) +endif + +LINKFILE := $(OBJDIR)/link.lds +DEPFILE = $(OBJDIR)/dep-searchengine +SRC = searchengine.c parser.c token.c dbinterface.c + +SOURCES = $(SRC) +OBJS := $(SRC:%.c=$(OBJDIR)/%.o) +DIRS = . + + +ifndef SIMVER +ifneq (,$(findstring RECORDER,$(TARGET))) ## Archos recorder targets + OUTPUT = $(OUTDIR)/searchengine.rock +else ## iRiver target + LDS := ../plugin.lds + OUTPUT = $(OUTDIR)/searchengine.rock +endif +else ## simulators + OUTPUT = $(OUTDIR)/searchengine.rock +endif + +all: $(OUTPUT) + +ifndef SIMVER +$(OBJDIR)/searchengine.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)/searchengine.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 searchengine" + @rm -rf $(OBJDIR)/searchengine + @rm -f $(OBJDIR)/searchengine.* $(DEPFILE) + +-include $(DEPFILE) + diff --git a/apps/plugins/searchengine/dbinterface.c b/apps/plugins/searchengine/dbinterface.c new file mode 100644 index 0000000000..bf2a6cfa5c --- /dev/null +++ b/apps/plugins/searchengine/dbinterface.c @@ -0,0 +1,97 @@ +#include "searchengine.h" +#include "dbinterface.h" + +#undef SONGENTRY_SIZE +#undef FILEENTRY_SIZE +#undef ALBUMENTRY_SIZE +#undef ARTISTENTRY_SIZE +#undef FILERECORD2OFFSET + +#define SONGENTRY_SIZE (rb->tagdbheader->songlen+12+rb->tagdbheader->genrelen+4) +#define FILEENTRY_SIZE (rb->tagdbheader->filelen+12) +#define ALBUMENTRY_SIZE (rb->tagdbheader->albumlen+4+rb->tagdbheader->songarraylen*4) +#define ARTISTENTRY_SIZE (rb->tagdbheader->artistlen+rb->tagdbheader->albumarraylen*4) + +#define FILERECORD2OFFSET(_x_) (rb->tagdbheader->filestart + _x_ * FILEENTRY_SIZE) + +struct entry *currententry; + +static struct entry *entryarray; + +int database_init() { + char *p; + unsigned int i; + // allocate room for all entries + entryarray=(struct entry *)my_malloc(sizeof(struct entry)*rb->tagdbheader->filecount); + p=(char *)entryarray; + // zero all entries. + for(i=0;itagdbheader->filecount;i++) + *(p++)=0; + if(*rb->tagdb_initialized!=1) { + if(!rb->tagdb_init()) { + // failed loading db + return -1; + } + } + return 0; +} + +void loadentry(int filerecord) { + if(entryarray[filerecord].loadedfiledata==0) { + rb->lseek(*rb->tagdb_fd,FILERECORD2OFFSET(filerecord),SEEK_SET); + entryarray[filerecord].filename=(char *)my_malloc(rb->tagdbheader->filelen); + rb->read(*rb->tagdb_fd,entryarray[filerecord].filename,rb->tagdbheader->filelen); + rb->read(*rb->tagdb_fd,&entryarray[filerecord].hash,4); + rb->read(*rb->tagdb_fd,&entryarray[filerecord].songentry,4); + rb->read(*rb->tagdb_fd,&entryarray[filerecord].rundbentry,4); + entryarray[filerecord].loadedfiledata=1; + } + currententry=&entryarray[filerecord]; +} + +void loadsongdata() { + if(currententry->loadedsongdata || + !currententry->loadedfiledata) + return; + currententry->title=(char *)my_malloc(rb->tagdbheader->songlen); + currententry->genre=(char *)my_malloc(rb->tagdbheader->genrelen); + rb->lseek(*rb->tagdb_fd,currententry->songentry,SEEK_SET); + rb->read(*rb->tagdb_fd,currententry->title,rb->tagdbheader->songlen); + rb->read(*rb->tagdb_fd,¤tentry->artistoffset,4); + rb->read(*rb->tagdb_fd,¤tentry->albumoffset,4); + rb->lseek(*rb->tagdb_fd,4,SEEK_CUR); + rb->read(*rb->tagdb_fd,currententry->genre,rb->tagdbheader->genrelen); + rb->read(*rb->tagdb_fd,¤tentry->bitrate,2); + rb->read(*rb->tagdb_fd,¤tentry->year,2); + currententry->loadedsongdata=1; +} + +void loadrundbdata() { + // we don't do this yet. + currententry->loadedrundbdata=1; +} + +void loadartistname() { + /* memory optimization possible, only malloc for an album name once, then + * write that pointer to the entrys using it. + */ + currententry->artistname=(char *)my_malloc(rb->tagdbheader->artistlen); + rb->lseek(*rb->tagdb_fd,currententry->artistoffset,SEEK_SET); + rb->read(*rb->tagdb_fd,currententry->artistname,rb->tagdbheader->artistlen); + currententry->loadedartistname=1; +} + +void loadalbumname() { + /* see the note at loadartistname */ + currententry->albumname=(char *)my_malloc(rb->tagdbheader->albumlen); + rb->lseek(*rb->tagdb_fd,currententry->albumoffset,SEEK_SET); + rb->read(*rb->tagdb_fd,currententry->albumname,rb->tagdbheader->albumlen); + currententry->loadedalbumname=1; +} + +char *getfilename(int entry) { + if(entryarray[entry].loadedfiledata==0) + return "error O.o;;;"; + else + return entryarray[entry].filename; +} diff --git a/apps/plugins/searchengine/dbinterface.h b/apps/plugins/searchengine/dbinterface.h new file mode 100644 index 0000000000..32363b11c6 --- /dev/null +++ b/apps/plugins/searchengine/dbinterface.h @@ -0,0 +1,32 @@ +struct entry { + int loadedfiledata, + loadedsongdata, + loadedrundbdata, + loadedalbumname, + loadedartistname; + char *filename; + int hash; + int songentry; + int rundbentry; + short year; + short bitrate; + int rating; + int playcount; + char *title; + char *genre; + int artistoffset; + int albumoffset; + char *artistname; + char *albumname; +}; + +extern struct entry *currententry; +extern struct entry *entryarray; + +int database_init(void); +void loadentry(int filerecord); +void loadsongdata(void); +void loadrundbdata(void); +void loadartistname(void); +void loadalbumname(void); +char *getfilename(int entry); diff --git a/apps/plugins/searchengine/parser.c b/apps/plugins/searchengine/parser.c new file mode 100644 index 0000000000..fe10452c17 --- /dev/null +++ b/apps/plugins/searchengine/parser.c @@ -0,0 +1,240 @@ +#include "searchengine.h" +#include "token.h" +#include "dbinterface.h" +#include "parser.h" + +struct token *tokenbuffer,*currentToken; +int currentindex; +int syntaxerror; +char errormsg[250]; + +unsigned char *parse(struct token *tokenbuf) { + unsigned char *ret=0; + currentindex=0; + syntaxerror=0; + tokenbuffer=tokenbuf; + database_init(); + currentToken=&tokenbuffer[currentindex]; + PUTS("parse"); + ret=parseMExpr(); + if(syntaxerror) { + PUTS("Syntaxerror"); + rb->splash(HZ*3,true,errormsg); + } + parser_accept(TOKEN_EOF); + return ret; +} + +void parser_acceptIt(void) { + if(syntaxerror) return; + currentToken=&tokenbuffer[++currentindex]; +} + +int parser_accept(unsigned char kind) { + if(currentToken->kind!=kind) { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where '%d' expected\n",currentToken->kind,kind); + return 0; + } + else { + parser_acceptIt(); + return 1; + } +} + +unsigned char *parseCompareNum() { + struct token *number1,*number2; + unsigned char *ret; + int i,n1=-1,n2=-1; + int op; + if(syntaxerror) return 0; + PUTS("parseCompareNum"); + if(currentToken->kind==TOKEN_NUM || + currentToken->kind==TOKEN_NUMIDENTIFIER) { + number1=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind); + return 0; + } + if(currentToken->kind>=TOKEN_GT && currentToken->kind <= TOKEN_NE) { + op=currentToken->kind; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where NUMOP expected\n",currentToken->kind); + return 0; + } + if(currentToken->kind==TOKEN_NUM || + currentToken->kind==TOKEN_NUMIDENTIFIER) { + number2=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where NUM/NUMID expected\n",currentToken->kind); + return 0; + } + ret=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount); + if(number1->kind==TOKEN_NUM) + n1=getvalue(number1); + if(number2->kind==TOKEN_NUM) + n2=getvalue(number2); + for(i=0;itagdbheader->filecount;i++) { + loadentry(i); + if(number1->kind==TOKEN_NUMIDENTIFIER) + n1=getvalue(number1); + if(number2->kind==TOKEN_NUMIDENTIFIER) + n2=getvalue(number2); + switch(op) { + case TOKEN_GT: + ret[i]=n1 > n2; + break; + case TOKEN_GTE: + ret[i]=n1 >= n2; + break; + case TOKEN_LT: + ret[i]=n1 < n2; + break; + case TOKEN_LTE: + ret[i]=n1 <= n2; + break; + case TOKEN_EQ: + ret[i]=n1 == n2; + break; + case TOKEN_NE: + ret[i]=n1 != n2; + break; + } + } + return ret; +} + +unsigned char *parseCompareString() { + struct token *string1,*string2; + unsigned char *ret; + char *s1=NULL,*s2=NULL; + int i,contains; + if(syntaxerror) return 0; + PUTS("parseCompareString"); + if(currentToken->kind==TOKEN_STRING || + currentToken->kind==TOKEN_STRINGIDENTIFIER) { + string1=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind); + return 0; + } + + contains=currentToken->kind==TOKEN_CONTAINS; + if(currentToken->kind==TOKEN_CONTAINS || + currentToken->kind==TOKEN_EQUALS) + parser_acceptIt(); + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where CONTAINS/EQUALS expected\n",currentToken->kind); + return 0; + } + + if(currentToken->kind==TOKEN_STRING || + currentToken->kind==TOKEN_STRINGIDENTIFIER) { + string2=currentToken; + parser_acceptIt(); + } + else { + syntaxerror=1; + rb->snprintf(errormsg,250,"'%d' found where STRING/STRINGID expected\n",currentToken->kind); + return 0; + } + ret=my_malloc(sizeof(unsigned char)*rb->tagdbheader->filecount); + if(string1->kind==TOKEN_STRING) + s1=getstring(string1); + if(string2->kind==TOKEN_STRING) + s2=getstring(string2); + for(i=0;itagdbheader->filecount;i++) { + loadentry(i); + if(string1->kind==TOKEN_STRINGIDENTIFIER) + s1=getstring(string1); + if(string2->kind==TOKEN_STRINGIDENTIFIER) + s2=getstring(string2); + if(contains) + ret[i]=rb->strcasestr(s1,s2)!=0; + else + ret[i]=rb->strcasecmp(s1,s2)==0; + } + return ret; +} + +unsigned char *parseExpr() { + unsigned char *ret; + int i; + if(syntaxerror) return 0; + PUTS("parseExpr"); + switch(currentToken->kind) { + case TOKEN_NOT: + parser_accept(TOKEN_NOT); + PUTS("parseNot"); + ret = parseExpr(); + if(ret==NULL) return 0; + for(i=0;itagdbheader->filecount;i++) + ret[i]=!ret[i]; + break; + case TOKEN_LPAREN: + parser_accept(TOKEN_LPAREN); + ret = parseMExpr(); + if(ret==NULL) return 0; + parser_accept(TOKEN_RPAREN); + break; + case TOKEN_NUM: + case TOKEN_NUMIDENTIFIER: + ret = parseCompareNum(); + if(ret==NULL) return 0; + break; + case TOKEN_STRING: + case TOKEN_STRINGIDENTIFIER: + ret = parseCompareString(); + if(ret==NULL) return 0; + break; + default: + // error, unexpected symbol + syntaxerror=1; + rb->snprintf(errormsg,250,"unexpected '%d' found at parseExpr\n",currentToken->kind); + ret=0; + break; + } + return ret; +} + +unsigned char *parseMExpr() { + unsigned char *ret,*ret2; + int i; + if(syntaxerror) return 0; + PUTS("parseMExpr"); + ret=parseExpr(); + while(currentToken->kind==TOKEN_AND||currentToken->kind==TOKEN_OR) { + switch(currentToken->kind) { + case TOKEN_AND: + parser_accept(TOKEN_AND); + PUTS("parseAnd"); + ret2 = parseExpr(); + if(ret2==NULL) return 0; + for(i=0;itagdbheader->filecount;i++) + ret[i]=ret[i] && ret2[i]; + break; + case TOKEN_OR: + parser_accept(TOKEN_OR); + PUTS("parseOr"); + ret2 = parseExpr(); + if(ret2==NULL) return 0; + for(i=0;itagdbheader->filecount;i++) + ret[i]=ret[i] || ret2[i]; + break; + } + } + return ret; +} diff --git a/apps/plugins/searchengine/parser.h b/apps/plugins/searchengine/parser.h new file mode 100644 index 0000000000..e63f15f39b --- /dev/null +++ b/apps/plugins/searchengine/parser.h @@ -0,0 +1,12 @@ +extern struct token *tokenbuffer,*currentToken; + +extern int syntaxerror; +extern char errormsg[250]; + +unsigned char *parse(struct token *tokenbuf); +void parser_acceptIt(void); +int parser_accept(unsigned char kind); +unsigned char *parseCompareNum(void); +unsigned char *parseCompareString(void); +unsigned char *parseExpr(void); +unsigned char *parseMExpr(void); diff --git a/apps/plugins/searchengine/searchengine.c b/apps/plugins/searchengine/searchengine.c new file mode 100644 index 0000000000..4b14836ddc --- /dev/null +++ b/apps/plugins/searchengine/searchengine.c @@ -0,0 +1,101 @@ +/*************************************************************************** + * __________ __ ___. + * 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 "searchengine.h" +#include "parser.h" +#include "token.h" +#include "dbinterface.h" + +void *audio_bufferbase; +void *audio_bufferpointer; +unsigned int audio_buffer_free; +struct plugin_api* rb; +int w, h, y; + +void *my_malloc(size_t size) +{ + void *alloc; + + if (!audio_bufferbase) + { + audio_bufferbase = audio_bufferpointer + = rb->plugin_get_audio_buffer(&audio_buffer_free); + } + if (size + 4 > audio_buffer_free) + return 0; + alloc = audio_bufferpointer; + audio_bufferpointer += size + 4; + audio_buffer_free -= size + 4; + return alloc; +} + +void setmallocpos(void *pointer) +{ + audio_bufferpointer = pointer; + audio_buffer_free = audio_bufferpointer - audio_bufferbase; +} + +struct token tokenstream[10]; + +/* this is the plugin entry point */ +enum plugin_status plugin_start(struct plugin_api* api, void* parameter) +{ + unsigned char *result,buf[500]; + /* 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); + + (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; + + audio_bufferbase=audio_bufferpointer=0; + audio_buffer_free=0; + + /* now go ahead and have fun! */ + rb->splash(HZ*2, true, "SearchEngine v0.1"); + tokenstream[0].kind=TOKEN_NUMIDENTIFIER; + tokenstream[0].intvalue=INTVALUE_YEAR; + tokenstream[1].kind=TOKEN_GTE; + tokenstream[2].kind=TOKEN_NUM; + tokenstream[2].intvalue=1980; + tokenstream[3].kind=TOKEN_AND; + tokenstream[4].kind=TOKEN_NUMIDENTIFIER; + tokenstream[4].intvalue=INTVALUE_YEAR; + tokenstream[5].kind=TOKEN_LT; + tokenstream[6].kind=TOKEN_NUM; + tokenstream[6].intvalue=1990; + tokenstream[7].kind=TOKEN_EOF; + result=parse(tokenstream); + rb->snprintf(buf,250,"Retval: 0x%x",result); + PUTS(buf); + if(result!=0) { + int fd=rb->open("/search.m3u", O_WRONLY|O_CREAT|O_TRUNC); + int i; + for(i=0;itagdbheader->filecount;i++) + if(result[i]) + rb->fdprintf(fd,"%s\n",getfilename(i)); +/* rb->write(fd,result,rb->tagdbheader->filecount);*/ + rb->close(fd); + } + rb->sleep(HZ*10); + return PLUGIN_OK; +} diff --git a/apps/plugins/searchengine/searchengine.h b/apps/plugins/searchengine/searchengine.h new file mode 100644 index 0000000000..3f7e4c609e --- /dev/null +++ b/apps/plugins/searchengine/searchengine.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * __________ __ ___. + * 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 SEARCHENGINE_H +#define SEARCHENGINE_H +#include +#include + +extern int w, h, y; +#define PUTS(str) do { \ + rb->lcd_putsxy(1, y, str); \ + rb->lcd_getstringsize(str, &w, &h); \ + y += h + 1; \ +} while (0); \ +rb->lcd_update() + +extern struct plugin_api* rb; + +void *my_malloc(size_t size); +void setmallocpos(void *pointer); + +#endif diff --git a/apps/plugins/searchengine/token.c b/apps/plugins/searchengine/token.c new file mode 100644 index 0000000000..d2da94ab52 --- /dev/null +++ b/apps/plugins/searchengine/token.c @@ -0,0 +1,61 @@ +#include "token.h" +#include "dbinterface.h" + +#define REQUIRESONGDATA() if(!currententry->loadedsongdata) loadsongdata(); +#define REQUIRERUNDBDATA() if(!currententry->loadedrundbdata) loadrundbdata(); +#define REQUIREALBUMNAME() if(!currententry->loadedalbumname) { REQUIRESONGDATA(); loadalbumname(); } +#define REQUIREARTISTNAME() if(!currententry->loadedartistname) { REQUIRESONGDATA(); loadartistname(); } + +char *getstring(struct token *token) { + switch(token->kind) { + case TOKEN_STRING: + return token->spelling; + case TOKEN_STRINGIDENTIFIER: + switch(token->intvalue) { + case INTVALUE_TITLE: + REQUIRESONGDATA(); + return currententry->title; + case INTVALUE_ARTIST: + REQUIREARTISTNAME(); + return currententry->artistname; + case INTVALUE_ALBUM: + REQUIREALBUMNAME(); + return currententry->albumname; + case INTVALUE_GENRE: + REQUIRESONGDATA(); + return currententry->genre; + case INTVALUE_FILENAME: + return currententry->filename; + default: + return 0; + } + break; + default: + // report error + return 0; + } +} + +int getvalue(struct token *token) { + switch(token->kind) { + case TOKEN_NUM: + return token->intvalue; + case TOKEN_NUMIDENTIFIER: + switch(token->intvalue) { + case INTVALUE_YEAR: + REQUIRESONGDATA(); + return currententry->year; + case INTVALUE_RATING: + REQUIRERUNDBDATA(); + return currententry->rating; + case INTVALUE_PLAYCOUNT: + REQUIRERUNDBDATA(); + return currententry->playcount; + default: + // report error. + return 0; + } + default: + return 0; + } +} diff --git a/apps/plugins/searchengine/token.h b/apps/plugins/searchengine/token.h new file mode 100644 index 0000000000..b858f4f217 --- /dev/null +++ b/apps/plugins/searchengine/token.h @@ -0,0 +1,40 @@ +#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 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 + +static char *spelling[] = { "not", "and", "or",">",">=","<", "<=","==","!=", + "contains","(",")" }; + +struct token { + unsigned char kind; + char spelling[256]; + int intvalue; +}; + +char *getstring(struct token *token); +int getvalue(struct token *token); -- cgit v1.2.3