summaryrefslogtreecommitdiff
path: root/apps/plugins/databox/databox.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/databox/databox.c')
-rw-r--r--apps/plugins/databox/databox.c307
1 files changed, 307 insertions, 0 deletions
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Björn Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "databox.h"
20
21/* welcome to the example rockbox plugin */
22
23/* here is a global api struct pointer. while not strictly necessary,
24 it's nice not to have to pass the api pointer in all function calls
25 in the plugin */
26struct plugin_api* rb;
27struct token tokenbuf[200];
28
29struct print printing;
30struct editor editor;
31struct editing editing;
32
33extern int acceptedmask;
34
35void databox_init(void) {
36 printing.fontfixed = rb->font_get(FONT_SYSFIXED);
37 rb->lcd_setfont(FONT_SYSFIXED);
38 printing.font_w = printing.fontfixed->maxwidth;
39 printing.font_h = printing.fontfixed->height;
40 printing.line=0;
41 printing.position=0;
42 editor.editingmode = INVALID_MARK;
43 editor.token = tokenbuf;
44}
45
46void print(char *word, int invert) {
47 int strlen=rb->strlen(word), newpos=printing.position+strlen+1;
48 if(newpos*printing.font_w>LCD_WIDTH) {
49 printing.line++;
50 printing.position=0;
51 newpos=printing.position+strlen+1;
52 }
53 rb->lcd_putsxy(printing.font_w*printing.position,printing.font_h*printing.line,word);
54 if(invert)
55 rb->lcd_invertrect(printing.font_w*printing.position,printing.font_h*printing.line,printing.font_w*strlen,printing.font_h);
56 rb->lcd_update_rect(printing.font_w*printing.position,printing.font_h*printing.line,printing.font_w*strlen,printing.font_h);
57 printing.position=newpos;
58}
59
60void displaytstream(struct token *token) {
61 int index=0;
62 while(token[index].kind!=TOKEN_EOF||index==editor.currentindex) {
63 if(editing.selecting&&index==editor.currentindex) {
64 print(tokentypetostring(editing.selection_candidates[editing.currentselection]),1);
65 }
66 else
67 print(tokentostring(&token[index]),index==editor.currentindex ? 1 : 0);
68 index++;
69 }
70}
71
72void buildchoices(int mask) {
73 int i;
74 for(i=0;i<20;i++)
75 editing.selection_candidates[i]=-1;
76 i=0;
77 if(editing.selecting&&
78 editing.old_token.kind!=TOKEN_EOF &&
79 editing.old_token.kind!=TOKEN_INVALID) {
80 editing.selection_candidates[i++]=TOKEN_EDIT;
81 }
82 if((mask&ACCEPT_EOF)&&editor.valid)
83 editing.selection_candidates[i++]=TOKEN_EOF;
84 if(mask&ACCEPT_NOT)
85 editing.selection_candidates[i++]=TOKEN_NOT;
86 if(mask&ACCEPT_BOOLOP) {
87 editing.selection_candidates[i++]=TOKEN_AND;
88 editing.selection_candidates[i++]=TOKEN_OR;
89 }
90 if(mask&ACCEPT_NUMOP) {
91 editing.selection_candidates[i++]=TOKEN_GT;
92 editing.selection_candidates[i++]=TOKEN_GTE;
93 editing.selection_candidates[i++]=TOKEN_LT;
94 editing.selection_candidates[i++]=TOKEN_LTE;
95 editing.selection_candidates[i++]=TOKEN_NE;
96 editing.selection_candidates[i++]=TOKEN_EQ;
97 }
98 if(mask&ACCEPT_STROP) {
99 editing.selection_candidates[i++]=TOKEN_CONTAINS;
100 editing.selection_candidates[i++]=TOKEN_EQUALS;
101 }
102 if(mask&ACCEPT_LPAREN) {
103 editing.selection_candidates[i++]=TOKEN_LPAREN;
104 }
105 if(mask&ACCEPT_RPAREN) {
106 editing.selection_candidates[i++]=TOKEN_RPAREN;
107 }
108 if(mask&ACCEPT_NUMARG) {
109 editing.selection_candidates[i++]=TOKEN_NUM;
110 editing.selection_candidates[i++]=TOKEN_YEAR;
111 editing.selection_candidates[i++]=TOKEN_RATING;
112 editing.selection_candidates[i++]=TOKEN_PLAYCOUNT;
113 }
114 if(mask&ACCEPT_STRARG) {
115 editing.selection_candidates[i++]=TOKEN_STRING;
116 editing.selection_candidates[i++]=TOKEN_TITLE;
117 editing.selection_candidates[i++]=TOKEN_ARTIST;
118 editing.selection_candidates[i++]=TOKEN_ALBUM;
119 editing.selection_candidates[i++]=TOKEN_GENRE;
120 editing.selection_candidates[i++]=TOKEN_FILENAME;
121 }
122 editing.selectionmax=i;
123}
124
125/* returns tokencount or 0 if error */
126int readtstream(char *filename,struct token *token,int max) {
127 int tokencount=0;
128 int filelen,i;
129 int fd;
130 rb->memset(token,0,max*sizeof(struct token));
131 fd=rb->open(filename,O_RDONLY);
132 if(fd>=0) {
133 filelen=rb->filesize(fd);
134 if(filelen>0) {
135 if(filelen % sizeof(struct token)) {
136 rb->splash(HZ*2,true,"Filesize not a multiple of sizeof(struct token)");
137 rb->close(fd);
138 return 0;
139 }
140 tokencount=(filelen/sizeof(struct token))-1;
141 for(i=0;i<tokencount&&i<max;i++) {
142 rb->read(fd,&token[i],sizeof(struct token));
143 token[i].intvalue=BE32(token[i].intvalue);
144 }
145 }
146 rb->close(fd);
147 }
148 return tokencount;
149}
150
151int writetstream(char *filename,struct token *token) {
152 int fd,i;
153 fd=rb->open(filename,O_WRONLY|O_CREAT|O_TRUNC);
154 if(fd<0)
155 return 0;
156 i=0;
157 while(token[i].kind!=TOKEN_EOF) {
158 token[i].intvalue=BE32(token[i].intvalue);
159 rb->write(fd,&token[i++],sizeof(struct token));
160 }
161 token[i].intvalue=BE32(token[i].intvalue);
162 rb->write(fd,&token[i++],sizeof(struct token));
163 rb->close(fd);
164 return i;
165}
166
167int hcl_button_get(void) {
168 int oldbuttonstate,newbuttonstate,pressed=0;
169 oldbuttonstate = rb->button_status();
170 do {
171 newbuttonstate = rb->button_status();
172 pressed = newbuttonstate & ~oldbuttonstate;
173 oldbuttonstate = newbuttonstate;
174 rb->yield();
175 }
176 while(!pressed);
177 rb->button_clear_queue();
178 return pressed;
179}
180
181/* this is the plugin entry point */
182enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
183{
184 int button,done=0;
185 char filename[100],buf[100];
186 /* this macro should be called as the first thing you do in the plugin.
187 it test that the api version and model the plugin was compiled for
188 matches the machine it is running on */
189 TEST_PLUGIN_API(api);
190
191 /* if you don't use the parameter, you can do like
192 this to avoid the compiler warning about it */
193 (void)parameter;
194
195 /* if you are using a global api pointer, don't forget to copy it!
196 otherwise you will get lovely "I04: IllInstr" errors... :-) */
197 rb = api;
198
199 /* now go ahead and have fun! */
200 rb->splash(HZ*2, true, "Databox! Enter filename ^.^");
201 databox_init();
202 if(rb->kbd_input(filename, 100)) {
203 rb->splash(HZ*2, true, "Something went wrong with the filename.. exiting..");
204 return PLUGIN_ERROR;
205 }
206 /* add / in front if omitted */
207 if(filename[0]!='/') {
208 rb->strncpy(buf+1,filename,99);
209 buf[0]='/';
210 rb->strcpy(filename,buf);
211 }
212 /* add extension if omitted */
213 if(rb->strncasecmp(filename+rb->strlen(filename)-4,".rsp",4)) {
214 rb->strcat(filename,".rsp");
215 }
216 rb->lcd_clear_display();
217 rb->lcd_update();
218 editor.currentindex=editor.tokencount=readtstream(filename,editor.token,200);
219 editing.currentselection=0;
220 editing.selecting=editor.currentindex==0 ? 1 : 0;
221 do {
222 rb->lcd_clear_display();
223 rb->lcd_update();
224 printing.line=0;
225 printing.position=0;
226 displaytstream(editor.token);
227 editor.valid=check_tokenstream(editor.token,editor.editingmode);
228 check_accepted(editor.token,editor.currentindex);
229 rb->lcd_update();
230 button=hcl_button_get();
231 if(editing.selecting) {
232 // button handling, up, down, select,stop
233 // up/right = move currentselection one up
234 // down/left = move currentselection one down
235 // select = build token in place.
236 // stop = cancel editing
237 if(button&BUTTON_LEFT
238#if CONFIG_KEYPAD == IRIVER_H100_PAD
239 ||button&BUTTON_DOWN
240#endif
241 ) {
242 editing.currentselection=(editing.currentselection+
243 1) %editing.selectionmax;
244 }
245 if(button&BUTTON_RIGHT
246#if CONFIG_KEYPAD == IRIVER_H100_PAD
247 ||button&BUTTON_UP
248#endif
249 ) {
250 editing.currentselection=(editing.currentselection +
251 editing.selectionmax-1) % editing.selectionmax;
252 }
253 if(button&BUTTON_SELECT) {
254 buildtoken(editing.selection_candidates[editing.currentselection],&editor.token[editor.currentindex]);
255 editing.selecting=0;
256 if(editor.token[editor.currentindex].kind==TOKEN_EOF)
257 done=1;
258 else if(editor.currentindex==editor.tokencount) {
259 editor.tokencount++;
260 editor.currentindex++;
261 editor.valid=check_tokenstream(editor.token,editor.editingmode);
262 check_accepted(editor.token,editor.currentindex);
263 editing.selecting=1;
264 editing.currentselection=0;
265 buildchoices(acceptedmask);
266 rb->memcpy(&editing.old_token,&editor.token[editor.currentindex],sizeof(struct token));
267 }
268 }
269 }
270 else {
271 // button handling, left, right, select, stop
272 // left/down = move currentindex down
273 // right/up = move currentindex up
274 // select = enter selecting mode.
275 // stop = quit editor.
276 if(button&BUTTON_LEFT
277#if CONFIG_KEYPAD == IRIVER_H100_PAD
278 ||button&BUTTON_DOWN
279#endif
280 ) {
281 editor.currentindex=(editor.currentindex +
282 editor.tokencount) % (editor.tokencount+1);
283 }
284 if(button&BUTTON_RIGHT
285#if CONFIG_KEYPAD == IRIVER_H100_PAD
286 ||button&BUTTON_UP
287#endif
288 ) {
289 editor.currentindex=(editor.currentindex+1) % (editor.tokencount+1);
290 }
291 if(button&BUTTON_SELECT) {
292 editing.selecting=1;
293 editing.currentselection=0;
294 buildchoices(acceptedmask);
295 rb->memcpy(&editing.old_token,&editor.token[editor.currentindex],sizeof(struct token));
296 }
297 }
298 } while (!done);
299 if(writetstream(filename,editor.token)) {
300 rb->splash(HZ*2,true,"Wrote file succesfully ^.^");
301 return PLUGIN_OK;
302 }
303 else {
304 rb->splash(HZ*2,true,"Error while writing rsp :(");
305 return PLUGIN_ERROR;
306 }
307}