A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 276 lines 8.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * 9 * Copyright (C) 2014 Jonathan Gordon 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * 16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 17 * KIND, either express or implied. 18 * 19 ****************************************************************************/ 20 21/* mandatory include for all plugins */ 22#include "plugin.h" 23 24static struct menu_table *menu_table; 25static int menu_item_count; 26 27#define MAX_ITEM_NAME 64 28#define MAX_ITEMS 16 29struct items 30{ 31 unsigned char *name; 32 char string[MAX_ITEM_NAME]; 33 bool enabled; 34}; 35 36static struct items menu_items[MAX_ITEMS]; 37 38 39static const char * menu_get_name(int selected_item, void * data, 40 char * buffer, size_t buffer_len) 41{ 42 (void)data; 43 unsigned char *p = menu_items[selected_item].name; 44 int id = P2ID(p); 45 46 rb->snprintf(buffer, buffer_len, "%s: %s", (id != -1) ? rb->str(id) : p, 47 menu_items[selected_item].enabled ? 48 rb->str(LANG_ON) : rb->str(LANG_OFF)); 49 50 return buffer; 51} 52 53static enum themable_icons menu_get_icon(int selected_item, void * data) 54{ 55 (void)data; 56 57 return menu_items[selected_item].enabled ? Icon_Config : Icon_NOICON; 58} 59 60static unsigned char *item_name(int n) 61{ 62 const struct menu_item_ex *item = menu_table[n].item; 63 return (item->flags & MENU_HAS_DESC) ? 64 item->callback_and_desc->desc : 65 (rb->strcmp("wps", menu_table[n].string) ? 66 (unsigned char *)menu_table[n].string : 67 ID2P(LANG_RESUME_PLAYBACK)); 68} 69 70void load_from_cfg(void) 71{ 72 char config_str[128]; 73 char *token, *save; 74 int done = 0; 75 int i = 0; 76 bool found = false; 77 78 config_str[0] = '\0'; 79 rb->root_menu_write_to_cfg(NULL, config_str, sizeof(config_str)); 80 81 token = rb->strtok_r(config_str, ", ", &save); 82 83 while (token) 84 { 85 for (i = 0, found = false; i < menu_item_count; i++) 86 { 87 found = rb->strcmp(token, menu_table[i].string) == 0; 88 if (found) break; 89 } 90 if (found) 91 { 92 menu_items[done].name = item_name(i); 93 rb->strcpy(menu_items[done].string, token); 94 menu_items[done].enabled = true; 95 done++; 96 } 97 token = rb->strtok_r(NULL, ", ", &save); 98 } 99 100 if (done < menu_item_count) 101 { 102 for (i = 0; i < menu_item_count; i++) 103 { 104 found = false; 105 for (int j = 0; !found && j < done; j++) 106 { 107 found = rb->strcmp(menu_table[i].string, menu_items[j].string) == 0; 108 } 109 110 if (!found) 111 { 112 menu_items[done].name = item_name(i); 113 rb->strcpy(menu_items[done].string, menu_table[i].string); 114 menu_items[done].enabled = false; 115 done++; 116 } 117 } 118 } 119} 120 121static void save_to_cfg(void) 122{ 123 char out[128]; 124 int i, j = 0; 125 126 out[0] = '\0'; 127 for (i = 0; i < menu_item_count; i++) 128 { 129 if (menu_items[i].enabled) 130 { 131 j += rb->snprintf(&out[j],sizeof(out) - j, "%s, ", menu_items[i].string); 132 } 133 } 134 135 rb->root_menu_load_from_cfg(&rb->global_settings->root_menu_customized, out); 136} 137 138static void swap_items(int a, int b) 139{ 140 unsigned char *name; 141 char temp[MAX_ITEM_NAME]; 142 bool enabled; 143 144 name = menu_items[a].name; 145 rb->strcpy(temp, menu_items[a].string); 146 enabled = menu_items[a].enabled; 147 menu_items[a].name = menu_items[b].name; 148 rb->strcpy(menu_items[a].string, 149 menu_items[b].string); 150 menu_items[a].enabled = menu_items[b].enabled; 151 menu_items[b].name = name; 152 rb->strcpy(menu_items[b].string, temp); 153 menu_items[b].enabled = enabled; 154} 155 156static int menu_speak_item(int selected_item, void *data) 157{ 158 (void) data; 159 int id = P2ID(menu_items[selected_item].name); 160 161 if (id != -1) 162 { 163 rb->talk_number(selected_item + 1, false); 164 rb->talk_id(id, true); 165 rb->talk_id(menu_items[selected_item].enabled ? LANG_ON : LANG_OFF, true); 166 } 167 168 return 0; 169} 170 171/* this is the plugin entry point */ 172enum plugin_status plugin_start(const void* parameter) 173{ 174 (void)parameter; 175 bool show_icons = rb->global_settings->show_icons; 176 rb->global_settings->show_icons = true; 177 struct gui_synclist list; 178 bool done = false; 179 bool changed = false; 180 int action, cur_sel; 181 int ret = PLUGIN_OK; 182 183 menu_table = rb->root_menu_get_options(&menu_item_count); 184 load_from_cfg(); 185 186 rb->gui_synclist_init(&list, menu_get_name, NULL, false, 1, NULL); 187 if (rb->global_settings->talk_menu) 188 rb->gui_synclist_set_voice_callback(&list, menu_speak_item); 189 rb->gui_synclist_set_icon_callback(&list, menu_get_icon); 190 rb->gui_synclist_set_nb_items(&list, menu_item_count); 191 rb->gui_synclist_set_title(&list, rb->str(LANG_MAIN_MENU), Icon_Rockbox); 192 rb->gui_synclist_draw(&list); 193 rb->gui_synclist_speak_item(&list); 194 195 while (!done) 196 { 197 cur_sel = rb->gui_synclist_get_sel_pos(&list); 198 action = rb->get_action(CONTEXT_LIST, HZ/10); 199 if (rb->gui_synclist_do_button(&list, &action)) 200 continue; 201 202 switch (action) 203 { 204 case ACTION_STD_OK: 205 menu_items[cur_sel].enabled = !menu_items[cur_sel].enabled; 206 rb->gui_synclist_speak_item(&list); 207 changed = true; 208 break; 209 case ACTION_STD_CONTEXT: 210 { 211 MENUITEM_STRINGLIST(menu, ID2P(LANG_MAIN_MENU), NULL, 212 ID2P(LANG_MOVE_ITEM_UP), 213 ID2P(LANG_MOVE_ITEM_DOWN), 214 ID2P(LANG_LOAD_DEFAULT_CONFIGURATION)); 215 switch (rb->do_menu(&menu, NULL, NULL, false)) 216 { 217 case 0: 218 if (cur_sel == 0) 219 { 220 rb->splash(HZ, ID2P(LANG_FAILED)); 221 break; 222 } 223 swap_items(cur_sel, cur_sel - 1); 224 rb->gui_synclist_select_item(&list, cur_sel - 1); /* speaks */ 225 changed = true; 226 break; 227 case 1: 228 if (cur_sel + 1 == menu_item_count) 229 { 230 rb->splash(HZ, ID2P(LANG_FAILED)); 231 break; 232 } 233 swap_items(cur_sel, cur_sel + 1); 234 rb->gui_synclist_select_item(&list, cur_sel + 1); /* speaks */ 235 changed = true; 236 break; 237 case 2: 238 if (rb->yesno_pop_confirm(ID2P(LANG_LOAD_DEFAULT_CONFIGURATION))) 239 { 240 rb->root_menu_set_default(&rb->global_settings->root_menu_customized, NULL); 241 load_from_cfg(); 242 } 243 /* fall-through */ 244 default: 245 rb->gui_synclist_speak_item(&list); 246 } 247 rb->gui_synclist_set_title(&list, rb->str(LANG_MAIN_MENU), Icon_Rockbox); 248 break; 249 } 250 case ACTION_STD_CANCEL: 251 case ACTION_STD_MENU: 252 done = true; 253 break; 254 default: 255 if (rb->default_event_handler(action) == SYS_USB_CONNECTED) 256 { 257 ret = PLUGIN_USB_CONNECTED; 258 done = true; 259 } 260 continue; 261 } 262 263 if (!done) 264 rb->gui_synclist_draw(&list); 265 } 266 267 if (changed) 268 { 269 save_to_cfg(); 270 rb->global_settings->root_menu_customized = true; 271 rb->settings_save(); 272 } 273 rb->global_settings->show_icons = show_icons; 274 275 return ret; 276}