diff options
Diffstat (limited to 'apps/plugins/databox/databox.c')
-rw-r--r-- | apps/plugins/databox/databox.c | 307 |
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 */ | ||
26 | struct plugin_api* rb; | ||
27 | struct token tokenbuf[200]; | ||
28 | |||
29 | struct print printing; | ||
30 | struct editor editor; | ||
31 | struct editing editing; | ||
32 | |||
33 | extern int acceptedmask; | ||
34 | |||
35 | void 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 | |||
46 | void 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 | |||
60 | void 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 | |||
72 | void 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 */ | ||
126 | int 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 | |||
151 | int 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 | |||
167 | int 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 */ | ||
182 | enum 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 | } | ||