1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2006 Jonathan Gordon
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "playback_control.h"
24 #if PLUGIN_BUFFER_SIZE > 0x45000
25 #define MAX_CHARS 0x40000 /* 128 kiB */
27 #define MAX_CHARS 0x6000 /* 24 kiB */
29 #define MAX_LINE_LEN 2048
31 static const struct plugin_api
* rb
;
33 static char buffer
[MAX_CHARS
];
35 static int char_count
= 0;
36 static int line_count
= 0;
37 static int last_action_line
= 0;
38 static int last_char_index
= 0;
40 #define ACTION_INSERT 0
42 #define ACTION_REMOVE 2
43 #define ACTION_UPDATE 3
44 #define ACTION_CONCAT 4
46 int _do_action(int action
, char* str
, int line
);
47 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
48 #define do_action _do_action
50 int do_action(int action
, char* str
, int line
)
54 r
= _do_action(action
,str
,line
);
60 int _do_action(int action
, char* str
, int line
)
64 if (line
>=last_action_line
)
69 while (i
<line
&& i
<line_count
)
71 c
+= rb
->strlen(&buffer
[c
])+1;
77 len
= rb
->strlen(str
)+1;
78 if ( char_count
+ len
> MAX_CHARS
)
80 rb
->memmove(&buffer
[c
+len
],&buffer
[c
],char_count
);
81 rb
->strcpy(&buffer
[c
],str
);
86 if (line
> line_count
)
93 if (line
> line_count
)
95 len
= rb
->strlen(&buffer
[c
])+1;
97 rb
->memmove(&buffer
[c
],&buffer
[c
+len
],char_count
);
101 if (line
> line_count
)
103 len
= rb
->strlen(&buffer
[c
])+1;
104 rb
->memmove(&buffer
[c
+rb
->strlen(str
)+1],&buffer
[c
+len
],char_count
);
105 rb
->strcpy(&buffer
[c
],str
);
106 char_count
+= rb
->strlen(str
)+1-len
;
109 if (line
> line_count
)
111 rb
->memmove(&buffer
[c
-1],&buffer
[c
],char_count
);
116 last_action_line
= i
;
120 char *list_get_name_cb(int selected_item
, void* data
,
121 char* buf
, size_t buf_len
)
124 char *b
= &buffer
[do_action(ACTION_GET
,0,selected_item
)];
125 if (rb
->strlen(b
) >= buf_len
)
127 char t
= b
[buf_len
-10];
128 b
[buf_len
-10] = '\0';
129 rb
->snprintf(buf
, buf_len
, "%s ...", b
);
132 else rb
->strncpy(buf
, b
, buf_len
);
135 char filename
[MAX_PATH
];
136 int get_eol_string(char* fn
)
144 fd
= rb
->PREFIX(open(fn
,O_RDONLY
));
150 if (!rb
->read(fd
,&t
,1))
152 rb
->strcpy(eol
,"\n");
157 if (rb
->read(fd
,&t
,1) && t
=='\n')
158 rb
->strcpy(eol
,"\r\n");
159 else rb
->strcpy(eol
,"\r");
163 rb
->strcpy(eol
,"\n");
170 void save_changes(int overwrite
)
175 if (!filename
[0] || !overwrite
)
177 rb
->strcpy(filename
,"/");
178 rb
->kbd_input(filename
,MAX_PATH
);
181 fd
= rb
->open(filename
,O_WRONLY
|O_CREAT
|O_TRUNC
);
184 rb
->splash(HZ
*2, "Changes NOT saved");
189 /* current directory may have changed */
190 rb
->reload_directory();
192 rb
->lcd_clear_display();
193 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
196 for (i
=0;i
<line_count
;i
++)
198 rb
->fdprintf(fd
,"%s%s",&buffer
[do_action(ACTION_GET
,0,i
)],eol
);
200 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
206 void setup_lists(struct gui_synclist
*lists
, int sel
)
208 rb
->gui_synclist_init(lists
,list_get_name_cb
,0, false, 1, NULL
);
209 rb
->gui_synclist_set_icon_callback(lists
,NULL
);
210 rb
->gui_synclist_set_nb_items(lists
,line_count
);
211 rb
->gui_synclist_limit_scroll(lists
,true);
212 rb
->gui_synclist_select_item(lists
, sel
);
213 rb
->gui_synclist_draw(lists
);
220 int do_item_menu(int cur_sel
, char* copy_buffer
)
223 MENUITEM_STRINGLIST(menu
, "Line Options", NULL
,
224 "Cut/Delete", "Copy",
225 "Insert Above", "Insert Below",
226 "Concat To Above", "Save",
227 "Show Playback Menu",);
229 switch (rb
->do_menu(&menu
, NULL
, NULL
, false))
232 rb
->strcpy(copy_buffer
,&buffer
[do_action(ACTION_GET
,0,cur_sel
)]);
233 do_action(ACTION_REMOVE
,0,cur_sel
);
234 ret
= MENU_RET_UPDATE
;
237 rb
->strcpy(copy_buffer
,&buffer
[do_action(ACTION_GET
,0,cur_sel
)]);
238 ret
= MENU_RET_NO_UPDATE
;
240 case 2: /* insert above */
241 if (!rb
->kbd_input(copy_buffer
,MAX_LINE_LEN
))
243 do_action(ACTION_INSERT
,copy_buffer
,cur_sel
);
245 ret
= MENU_RET_UPDATE
;
248 case 3: /* insert below */
249 if (!rb
->kbd_input(copy_buffer
,MAX_LINE_LEN
))
251 do_action(ACTION_INSERT
,copy_buffer
,cur_sel
+1);
253 ret
= MENU_RET_UPDATE
;
256 case 4: /* cat to above */
259 do_action(ACTION_CONCAT
,0,cur_sel
);
260 ret
= MENU_RET_UPDATE
;
266 case 6: /* playback menu */
267 playback_control(rb
, NULL
);
268 ret
= MENU_RET_UPDATE
;
271 ret
= MENU_RET_NO_UPDATE
;
277 #ifdef HAVE_LCD_COLOR
278 /* in misc.h but no need to polute the api */
279 #define toupper(c) (((c >= 'a') && (c <= 'z'))?c+'A':c)
280 #define isxdigit(c) ((c>='a' && c<= 'f') || (c>='A' && c<= 'F') \
281 || (c>='0' && c<= '9'))
282 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
283 (toupper(c)) - 'A' + 10)
284 int hex_to_rgb(const char* hex
, int* color
)
287 int red
, green
, blue
;
289 if (rb
->strlen(hex
) == 6) {
290 for (i
=0; i
< 6; i
++ ) {
291 if (!isxdigit(hex
[i
])) {
298 red
= (hex2dec(hex
[0]) << 4) | hex2dec(hex
[1]);
299 green
= (hex2dec(hex
[2]) << 4) | hex2dec(hex
[3]);
300 blue
= (hex2dec(hex
[4]) << 4) | hex2dec(hex
[5]);
301 *color
= LCD_RGBPACK(red
,green
,blue
);
308 #endif /* HAVE_LCD_COLOR */
310 /* this is the plugin entry point */
311 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
314 static char temp_line
[MAX_LINE_LEN
];
316 struct gui_synclist lists
;
319 bool changed
= false;
321 static char copy_buffer
[MAX_LINE_LEN
];
322 bool prev_show_statusbar
;
323 #ifdef HAVE_LCD_COLOR
324 bool edit_colors_file
= false;
330 prev_show_statusbar
= rb
->global_settings
->statusbar
;
331 rb
->global_settings
->statusbar
= false;
334 rb
->lcd_set_backdrop(NULL
);
337 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
342 #ifdef HAVE_LCD_COLOR
345 rb
->strcpy(filename
,(char*)parameter
);
346 if (!get_eol_string(filename
))
348 rb
->strcpy(eol
,"\n");
350 fd
= rb
->open(filename
,O_RDONLY
);
353 rb
->splash(HZ
*2,"Couldnt open file: %s",(char*)parameter
);
356 #ifdef HAVE_LCD_COLOR
357 c
= rb
->strrchr(filename
, '.');
358 if (c
&& !rb
->strcmp(c
, ".colours"))
359 edit_colors_file
= true;
361 /* read in the file */
362 while (rb
->read_line(fd
,temp_line
,MAX_LINE_LEN
))
364 if (!do_action(ACTION_INSERT
,temp_line
,line_count
))
366 rb
->splash(HZ
*2,"Error reading file: %s",(char*)parameter
);
376 rb
->strcpy(eol
,"\n");
378 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
381 /* now dump it in the list */
382 setup_lists(&lists
,0);
386 rb
->gui_synclist_draw(&lists
);
387 cur_sel
= rb
->gui_synclist_get_sel_pos(&lists
);
388 button
= rb
->get_action(CONTEXT_LIST
,TIMEOUT_BLOCK
);
389 if (rb
->gui_synclist_do_button(&lists
,&button
,LIST_WRAP_UNLESS_HELD
))
395 bool edit_text
= true;
396 #ifdef HAVE_LCD_COLOR
400 rb
->strcpy(temp_line
,&buffer
[do_action(ACTION_GET
,0,cur_sel
)]);
401 #ifdef HAVE_LCD_COLOR
402 if (edit_colors_file
)
404 char *name
= temp_line
, *value
= NULL
;
405 char extension
[MAX_LINE_LEN
];
406 rb
->settings_parseline(temp_line
, &name
, &value
);
409 MENUITEM_STRINGLIST(menu
, "Edit What?", NULL
,
410 "Extension", "Color",);
411 switch (rb
->do_menu(&menu
, NULL
, NULL
, false))
419 hex_to_rgb(value
, &color
);
421 rb
->strcpy(extension
, name
);
422 rb
->set_color(rb
->screens
[SCREEN_MAIN
], name
, &color
, -1);
423 rb
->snprintf(temp_line
, MAX_LINE_LEN
, "%s: %02X%02X%02X",
424 extension
, RGB_UNPACK_RED(color
),
425 RGB_UNPACK_GREEN(color
),
426 RGB_UNPACK_BLUE(color
));
429 do_action(ACTION_UPDATE
,temp_line
,cur_sel
);
431 else do_action(ACTION_INSERT
,temp_line
,cur_sel
);
438 if (edit_text
&&!rb
->kbd_input(temp_line
,MAX_LINE_LEN
))
442 do_action(ACTION_UPDATE
,temp_line
,cur_sel
);
444 else do_action(ACTION_INSERT
,temp_line
,cur_sel
);
449 case ACTION_STD_CONTEXT
:
450 if (!line_count
) break;
451 rb
->strcpy(copy_buffer
,&buffer
[do_action(ACTION_GET
,0,cur_sel
)]);
452 do_action(ACTION_REMOVE
,0,cur_sel
);
455 case ACTION_STD_MENU
:
456 { /* do the item menu */
457 switch (do_item_menu(cur_sel
, copy_buffer
))
463 case MENU_RET_UPDATE
:
466 case MENU_RET_NO_UPDATE
:
471 case ACTION_STD_CANCEL
:
474 MENUITEM_STRINGLIST(menu
, "Do What?", NULL
,
476 "Show Playback Menu", "Save Changes",
477 "Save As...", "Save and Exit",
478 "Ignore Changes and Exit");
479 switch (rb
->do_menu(&menu
, NULL
, NULL
, false))
484 playback_control(rb
, NULL
);
486 case 2: //save to disk
507 rb
->gui_synclist_set_nb_items(&lists
,line_count
);
509 rb
->global_settings
->statusbar
= prev_show_statusbar
;