Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

FS10820 - Shopper, a shopping list plugin by Daniel Rigby.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27842 a1c6a512-1295-4272-9138-f99709370657

+486
+1
apps/plugins/CATEGORIES
··· 84 84 search,viewers 85 85 searchengine,viewers 86 86 settings_dumper,apps 87 + shopper,viewers 87 88 shortcuts_append,viewers 88 89 shortcuts_view,viewers 89 90 sliding_puzzle,games
+1
apps/plugins/SOURCES
··· 144 144 calendar.c 145 145 maze.c 146 146 mazezam.c 147 + shopper.c 147 148 text_editor.c 148 149 wavview.c 149 150 robotfindskitten.c
+482
apps/plugins/shopper.c
··· 1 + /*************************************************************************** 2 + * __________ __ ___. 3 + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 + * \/ \/ \/ \/ \/ 8 + * $Id: 9 + * 10 + * Copyright (C) 2010 Daniel Rigby 11 + * 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. 16 + * 17 + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 + * KIND, either express or implied. 19 + * 20 + ****************************************************************************/ 21 + #include "plugin.h" 22 + #include "lib/playback_control.h" 23 + 24 + PLUGIN_HEADER 25 + 26 + #define MAX_LIST_SIZE 400 27 + #define DESC_SIZE 40 28 + #define MAX_LINE_LEN (DESC_SIZE + 1) 29 + 30 + enum flag_type { 31 + FL_CLEARED = 0, 32 + FL_SET, 33 + FL_CATEGORY 34 + }; 35 + 36 + enum view_type { 37 + EDIT_SHOPPING_LIST = 0, 38 + VIEW_SHOPPING_LIST 39 + }; 40 + 41 + #define VIEW_TYPE_SIZE VIEW_SHOPPING_LIST + 1 42 + 43 + struct items_list_s { 44 + unsigned int id; 45 + enum flag_type flag; 46 + char desc[DESC_SIZE]; 47 + }; 48 + 49 + static struct items_list_s items_list[MAX_LIST_SIZE]; 50 + static int total_item_count = 0; 51 + static int view_id_list[MAX_LIST_SIZE]; 52 + static int view_item_count; 53 + static enum view_type view = EDIT_SHOPPING_LIST; 54 + static char filename[MAX_PATH]; 55 + static bool changed = false; 56 + static bool show_categories = true; 57 + static char category_string[] = "Hide categories"; 58 + 59 + static const char *list_get_name_cb(int selected_item, void* data, 60 + char* buf, size_t buf_len) 61 + { 62 + (void)data; 63 + rb->strlcpy(buf, items_list[view_id_list[selected_item]].desc, buf_len); 64 + return buf; 65 + } 66 + 67 + static enum themable_icons list_get_icon_cb(int selected_item, void *data) 68 + { 69 + (void)data; 70 + if (items_list[view_id_list[selected_item]].flag == FL_CATEGORY) 71 + return Icon_Rockbox; 72 + else if (items_list[view_id_list[selected_item]].flag == FL_SET) 73 + return Icon_Cursor; 74 + else 75 + return Icon_NOICON; 76 + } 77 + 78 + bool save_changes(void) 79 + { 80 + int fd; 81 + int i; 82 + 83 + fd = rb->open(filename,O_WRONLY|O_CREAT|O_TRUNC); 84 + if (fd < 0) 85 + { 86 + rb->splash(HZ*2, "Changes NOT saved"); 87 + return false; 88 + } 89 + 90 + rb->lcd_clear_display(); 91 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 92 + rb->cpu_boost(1); 93 + #endif 94 + for (i = 0;i < total_item_count; i++) 95 + { 96 + switch (items_list[i].flag) 97 + { 98 + case FL_CATEGORY: 99 + { 100 + rb->fdprintf(fd,"#%s\n",items_list[i].desc); 101 + break; 102 + } 103 + case FL_SET: 104 + { 105 + rb->fdprintf(fd,"!%s\n",items_list[i].desc); 106 + break; 107 + } 108 + case FL_CLEARED: 109 + { 110 + rb->fdprintf(fd," %s\n",items_list[i].desc); 111 + break; 112 + } 113 + } 114 + } 115 + /* save current view */ 116 + rb->fdprintf(fd,"$%d%d\n",view, show_categories); 117 + 118 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 119 + rb->cpu_boost(0); 120 + #endif 121 + rb->close(fd); 122 + 123 + return true; 124 + } 125 + 126 + void create_view(struct gui_synclist *lists) 127 + { 128 + unsigned int cnt = 0; 129 + int i, j; 130 + 131 + switch (view) 132 + { 133 + case EDIT_SHOPPING_LIST: 134 + { 135 + for (i = 0; i < total_item_count; i++) 136 + { 137 + if (show_categories || (items_list[i].flag != FL_CATEGORY)) 138 + view_id_list[cnt++] = i; 139 + } 140 + view_item_count = cnt; 141 + rb->gui_synclist_set_title(lists,"Select items",Icon_Playlist); 142 + break; 143 + } 144 + case VIEW_SHOPPING_LIST: 145 + { 146 + for (i = 0; i < total_item_count; i++) 147 + { 148 + if ((items_list[i].flag == FL_CATEGORY) && show_categories) 149 + { 150 + for (j = i+1; j < total_item_count; j++) 151 + { 152 + if (items_list[j].flag == FL_SET) 153 + { 154 + view_id_list[cnt++] = i; 155 + break; 156 + } 157 + if (items_list[j].flag == FL_CATEGORY) 158 + break; 159 + } 160 + } 161 + else if (items_list[i].flag == FL_SET) 162 + view_id_list[cnt++] = i; 163 + } 164 + view_item_count = cnt; 165 + rb->gui_synclist_set_title(lists,"Shopping list",Icon_Playlist); 166 + break; 167 + } 168 + } 169 + } 170 + 171 + bool toggle(int selected_item) 172 + { 173 + if (items_list[view_id_list[selected_item]].flag == FL_CATEGORY) 174 + return false; 175 + else if (items_list[view_id_list[selected_item]].flag == FL_SET) 176 + items_list[view_id_list[selected_item]].flag = FL_CLEARED; 177 + else 178 + items_list[view_id_list[selected_item]].flag = FL_SET; 179 + return true; 180 + } 181 + 182 + void update_category_string(void) 183 + { 184 + if (show_categories) 185 + rb->strcpy(category_string,"Hide categories"); 186 + else 187 + rb->strcpy(category_string,"Show categories"); 188 + } 189 + 190 + enum plugin_status load_file(void) 191 + { 192 + int fd; 193 + static char temp_line[DESC_SIZE]; 194 + static struct items_list_s new_item; 195 + static int count = 0; 196 + int linelen; 197 + total_item_count = 0; 198 + 199 + fd = rb->open(filename,O_RDONLY); 200 + if (fd < 0) 201 + { 202 + rb->splashf(HZ*2,"Couldn't open file: %s",filename); 203 + return PLUGIN_ERROR; 204 + } 205 + 206 + /* read in the file */ 207 + while (rb->read_line(fd,temp_line,MAX_LINE_LEN)) 208 + { 209 + if (rb->strncmp(temp_line, "$", 1) == 0) 210 + { 211 + /* read view preferences */ 212 + linelen = rb->strlen(temp_line); 213 + if (linelen >= 2) 214 + { 215 + unsigned int val = temp_line[1] - '0'; 216 + if (val < VIEW_TYPE_SIZE) 217 + { 218 + view = val; 219 + } 220 + } 221 + if (linelen >= 3) 222 + { 223 + unsigned int val = temp_line[2] - '0'; 224 + if (val <= 2) 225 + { 226 + show_categories = val; 227 + update_category_string(); 228 + } 229 + } 230 + } 231 + else 232 + { 233 + new_item.id = count; 234 + if (rb->strncmp(temp_line, " ", 1) == 0) 235 + { 236 + /* read description, flag = cleared */ 237 + new_item.flag = FL_CLEARED; 238 + rb->memcpy(new_item.desc, &temp_line[1], DESC_SIZE); 239 + } 240 + else if (rb->strncmp(temp_line, "!", 1) == 0) 241 + { 242 + /* read description, flag = set */ 243 + new_item.flag = FL_SET; 244 + rb->memcpy(new_item.desc, &temp_line[1], DESC_SIZE); 245 + } 246 + else if (rb->strncmp(temp_line, "#", 1) == 0) 247 + { 248 + /* read description, flag = category */ 249 + new_item.flag = FL_CATEGORY; 250 + rb->memcpy(new_item.desc, &temp_line[1], DESC_SIZE); 251 + } 252 + else 253 + { 254 + /* read description, flag = cleared */ 255 + new_item.flag = FL_CLEARED; 256 + rb->memcpy(new_item.desc, temp_line, DESC_SIZE); 257 + } 258 + items_list[total_item_count] = new_item; 259 + total_item_count++; 260 + if (total_item_count == MAX_LIST_SIZE) 261 + { 262 + total_item_count = MAX_LIST_SIZE - 1; 263 + rb->splashf(HZ*2, "Truncating shopping list to %d items", 264 + MAX_LIST_SIZE - 1); 265 + changed = true; 266 + rb->close(fd); 267 + return PLUGIN_OK; 268 + } 269 + } 270 + } 271 + rb->close(fd); 272 + changed = false; 273 + return PLUGIN_OK; 274 + } 275 + 276 + /* this is the plugin entry point */ 277 + enum plugin_status plugin_start(const void* parameter) 278 + { 279 + struct gui_synclist lists; 280 + bool exit = false; 281 + int button; 282 + int cur_sel = 0; 283 + 284 + #if LCD_DEPTH > 1 285 + rb->lcd_set_backdrop(NULL); 286 + #endif 287 + 288 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 289 + rb->cpu_boost(1); 290 + #endif 291 + if (parameter) 292 + { 293 + rb->strcpy(filename,(char*)parameter); 294 + 295 + if (load_file() == PLUGIN_ERROR) 296 + return PLUGIN_ERROR; 297 + } 298 + else 299 + return PLUGIN_ERROR; 300 + 301 + #ifdef HAVE_ADJUSTABLE_CPU_FREQ 302 + rb->cpu_boost(0); 303 + #endif 304 + /* now dump it in the list */ 305 + rb->gui_synclist_init(&lists,list_get_name_cb,0, false, 1, NULL); 306 + rb->gui_synclist_set_icon_callback(&lists, list_get_icon_cb); 307 + rb->gui_synclist_limit_scroll(&lists,true); 308 + create_view(&lists); 309 + rb->gui_synclist_set_nb_items(&lists,view_item_count); 310 + rb->gui_synclist_select_item(&lists, 0); 311 + rb->gui_synclist_draw(&lists); 312 + rb->lcd_update(); 313 + 314 + while (!exit) 315 + { 316 + rb->gui_synclist_draw(&lists); 317 + cur_sel = rb->gui_synclist_get_sel_pos(&lists); 318 + button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); 319 + if (rb->gui_synclist_do_button(&lists,&button,LIST_WRAP_UNLESS_HELD)) 320 + continue; 321 + switch (button) 322 + { 323 + case ACTION_STD_CONTEXT: 324 + case ACTION_STD_OK: 325 + { 326 + changed |= toggle(cur_sel); 327 + break; 328 + } 329 + case ACTION_STD_MENU: 330 + { 331 + switch(view) 332 + { 333 + case EDIT_SHOPPING_LIST: 334 + { 335 + MENUITEM_STRINGLIST(menu, "Options", NULL, 336 + "View shopping list", 337 + "Clear all items", 338 + "Mark all items", 339 + category_string, 340 + "Revert to saved", 341 + "Show Playback Menu",); 342 + 343 + switch (rb->do_menu(&menu, NULL, NULL, false)) 344 + { 345 + case 0: 346 + { 347 + /* view shopping list */ 348 + view = VIEW_SHOPPING_LIST; 349 + changed = true; 350 + break; 351 + } 352 + case 1: 353 + { 354 + /* clear all items */ 355 + int i; 356 + for (i = 0; i < total_item_count; i++) 357 + { 358 + if (items_list[i].flag == FL_SET) 359 + items_list[i].flag = FL_CLEARED; 360 + } 361 + changed = true; 362 + break; 363 + } 364 + case 2: 365 + { 366 + /* mark all items */ 367 + int i; 368 + for (i = 0; i < total_item_count; i++) 369 + { 370 + if (items_list[i].flag == FL_CLEARED) 371 + items_list[i].flag = FL_SET; 372 + } 373 + changed = true; 374 + break; 375 + } 376 + case 3: 377 + { 378 + /* toggle categories */ 379 + show_categories ^= true; 380 + update_category_string(); 381 + changed = true; 382 + break; 383 + } 384 + case 4: 385 + { 386 + /* revert to saved */ 387 + if (load_file() == PLUGIN_ERROR) 388 + return PLUGIN_ERROR; 389 + break; 390 + } 391 + case 5: 392 + { 393 + /* playback menu */ 394 + playback_control(NULL); 395 + break; 396 + } 397 + default: 398 + { 399 + break; 400 + } 401 + } 402 + break; 403 + } 404 + 405 + case VIEW_SHOPPING_LIST: 406 + { 407 + MENUITEM_STRINGLIST(menu, "Options", NULL, 408 + "Edit list", 409 + "Reset list", 410 + category_string, 411 + "Revert to saved", 412 + "Show Playback Menu",); 413 + 414 + switch (rb->do_menu(&menu, NULL, NULL, false)) 415 + { 416 + case 0: 417 + { 418 + /* edit list */ 419 + view = EDIT_SHOPPING_LIST; 420 + changed = true; 421 + break; 422 + } 423 + case 1: 424 + { 425 + /* reset list */ 426 + int i; 427 + for (i = 0; i < total_item_count; i++) 428 + { 429 + if (items_list[i].flag == FL_SET) 430 + items_list[i].flag = FL_CLEARED; 431 + } 432 + view = EDIT_SHOPPING_LIST; 433 + changed = true; 434 + break; 435 + } 436 + case 2: 437 + { 438 + /* toggle categories */ 439 + show_categories ^= true; 440 + update_category_string(); 441 + changed = true; 442 + break; 443 + } 444 + case 3: 445 + { 446 + /* revert to saved */ 447 + if (load_file() == PLUGIN_ERROR) 448 + return PLUGIN_ERROR; 449 + break; 450 + } 451 + case 4: 452 + { 453 + /* playback menu */ 454 + playback_control(NULL); 455 + break; 456 + } 457 + default: 458 + { 459 + break; 460 + } 461 + } 462 + break; 463 + } 464 + } 465 + break; 466 + } 467 + case ACTION_STD_CANCEL: 468 + { 469 + if (changed) 470 + save_changes(); 471 + exit = 1; 472 + break; 473 + } 474 + } 475 + 476 + create_view(&lists); 477 + rb->gui_synclist_set_nb_items(&lists,view_item_count); 478 + if (view_item_count > 0 && view_item_count <= cur_sel) 479 + rb->gui_synclist_select_item(&lists,view_item_count-1); 480 + } 481 + return PLUGIN_OK; 482 + }
+1
apps/plugins/viewers.config
··· 73 73 z6,viewers/frotz,- 74 74 z7,viewers/frotz,- 75 75 z8,viewers/frotz,- 76 + list,viewers/shopper,1
+1
docs/CREDITS
··· 556 556 Pierre-Yves Roosens 557 557 Hayden Pearce 558 558 Rodrigo Barretto 559 + Daniel Rigby 559 560 560 561 The libmad team 561 562 The wavpack team