A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 288 lines 9.7 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2011 by Jonathan Gordon 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 22#include "config.h" 23#include "system.h" 24#include "lcd.h" 25#include "font.h" 26#include "button.h" 27#include "string.h" 28#include "settings.h" 29#include "kernel.h" 30#include "file.h" 31 32#include "action.h" 33#include "screen_access.h" 34#include "list.h" 35#include "scrollbar.h" 36#include "lang.h" 37#include "sound.h" 38#include "misc.h" 39#include "viewport.h" 40#include "statusbar-skinned.h" 41#include "skin_engine/skin_engine.h" 42#include "skin_engine/skin_display.h" 43#include "appevents.h" 44 45static struct listitem_viewport_cfg *listcfg[NB_SCREENS] = {NULL}; 46static struct gui_synclist *current_list; 47 48static int current_row; 49static int current_column; 50 51void skinlist_set_cfg(enum screen_type screen, 52 struct listitem_viewport_cfg *cfg) 53{ 54 if (listcfg[screen] != cfg) 55 { 56 if (listcfg[screen]) 57 screens[screen].scroll_stop_viewport(&listcfg[screen]->selected_item_vp.vp); 58 listcfg[screen] = cfg; 59 current_list = NULL; 60 current_column = -1; 61 current_row = -1; 62 } 63} 64 65static bool skinlist_is_configured(enum screen_type screen, 66 struct gui_synclist *list) 67{ 68 return (listcfg[screen] != NULL) && 69 (!list || (list && list->selected_size == 1)); 70} 71static int current_drawing_line; 72static int offset_to_item(int offset, bool wrap) 73{ 74 int item = current_drawing_line + offset; 75 if (!current_list || current_list->nb_items == 0) 76 return -1; 77 if (item < 0) 78 { 79 if (!wrap) 80 return -1; 81 else 82 item = (item + current_list->nb_items) % current_list->nb_items; 83 } 84 else if (item >= current_list->nb_items && !wrap) 85 return -1; 86 else 87 item = item % current_list->nb_items; 88 return item; 89} 90 91int skinlist_get_item_number() 92{ 93 return current_drawing_line; 94} 95 96int skinlist_get_item_row() 97{ 98 return current_row; 99} 100 101int skinlist_get_item_column() 102{ 103 return current_column; 104} 105 106 107const char* skinlist_get_item_text(int offset, bool wrap, char* buf, size_t buf_size) 108{ 109 int item = offset_to_item(offset, wrap); 110 if (item < 0 || !current_list) 111 return NULL; 112 const char* ret = current_list->callback_get_item_name( 113 item, current_list->data, buf, buf_size); 114 return P2STR((unsigned char*)ret); 115} 116 117enum themable_icons skinlist_get_item_icon(int offset, bool wrap) 118{ 119 int item = offset_to_item(offset, wrap); 120 if (item < 0 || !current_list || current_list->callback_get_item_icon == NULL) 121 return Icon_NOICON; 122 return current_list->callback_get_item_icon(item, current_list->data); 123} 124 125static bool is_selected = false; 126bool skinlist_is_selected_item(void) 127{ 128 return is_selected; 129} 130 131int skinlist_get_line_count(enum screen_type screen, struct gui_synclist *list) 132{ 133 struct viewport *parent = (list->parent[screen]); 134 if (!skinlist_is_configured(screen, list)) 135 return -1; 136 if (listcfg[screen]->tile == true) 137 { 138 int rows = (parent->height / listcfg[screen]->height); 139 int cols = (parent->width / listcfg[screen]->width); 140 return rows*cols; 141 } 142 else 143 return (parent->height / listcfg[screen]->height); 144} 145 146static int current_item; 147static int current_nbitems; 148static bool needs_scrollbar[NB_SCREENS]; 149bool skinlist_needs_scrollbar(enum screen_type screen) 150{ 151 return needs_scrollbar[screen]; 152} 153 154void skinlist_get_scrollbar(int* nb_item, int* first_shown, int* last_shown) 155{ 156 if (!skinlist_is_configured(0, NULL)) 157 { 158 *nb_item = 0; 159 *first_shown = 0; 160 *last_shown = 0; 161 } 162 else 163 { 164 *nb_item = current_item; 165 *first_shown = 0; 166 *last_shown = current_nbitems; 167 } 168} 169 170bool skinlist_get_item(struct screen *display, struct gui_synclist *list, int x, int y, int *item) 171{ 172 const int screen = display->screen_type; 173 if (!skinlist_is_configured(screen, list)) 174 return false; 175 176 int row = y / listcfg[screen]->height; 177 int column = x / listcfg[screen]->width; 178 struct viewport *parent = (list->parent[screen]); 179 int cols = (parent->width / listcfg[screen]->width); 180 *item = row * cols+ column; 181 return true; 182} 183 184bool skinlist_draw(struct screen *display, struct gui_synclist *list) 185{ 186 int cur_line, display_lines; 187 const int screen = display->screen_type; 188 struct viewport *parent = (list->parent[screen]); 189 char* label = NULL; 190 const int list_start_item = list->start_item[screen]; 191 struct gui_wps wps; 192 if (!skinlist_is_configured(screen, list)) 193 return false; 194 195 current_list = list; 196 wps.display = display; 197 wps.data = listcfg[screen]->data; 198 display_lines = skinlist_get_line_count(screen, list); 199 label = (char *)SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->label); 200 if (!label) 201 return false; 202 203 display->set_viewport(parent); 204 display->clear_viewport(); 205 current_item = list->selected_item; 206 current_nbitems = list->nb_items; 207 needs_scrollbar[screen] = list->nb_items > display_lines; 208 209 for (cur_line = 0; cur_line < display_lines; cur_line++) 210 { 211 struct skin_element* viewport; 212 struct skin_viewport* skin_viewport = NULL; 213 if (list_start_item+cur_line+1 > list->nb_items) 214 break; 215 current_drawing_line = list_start_item+cur_line; 216 is_selected = list_start_item+cur_line == list->selected_item; 217 218 for (viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), listcfg[screen]->data->tree); 219 viewport; 220 viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->next)) 221 { 222 int original_x, original_y; 223 skin_viewport = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->data); 224 char *viewport_label = NULL; 225 if (skin_viewport) 226 viewport_label = SKINOFFSETTOPTR(get_skin_buffer(wps.data), skin_viewport->label); 227 if (viewport->children == 0 || !viewport_label || 228 (skin_viewport->label && strcmp(label, viewport_label)) 229 ) 230 continue; 231 if (is_selected) 232 { 233 memcpy(&listcfg[screen]->selected_item_vp, skin_viewport, sizeof(struct skin_viewport)); 234 skin_viewport = &listcfg[screen]->selected_item_vp; 235 } 236 original_x = skin_viewport->vp.x; 237 original_y = skin_viewport->vp.y; 238 if (listcfg[screen]->tile) 239 { 240 int cols = (parent->width / listcfg[screen]->width); 241 current_column = (cur_line)%cols; 242 current_row = (cur_line)/cols; 243 244 skin_viewport->vp.x = parent->x + listcfg[screen]->width*current_column + original_x; 245 skin_viewport->vp.y = parent->y + listcfg[screen]->height*current_row + original_y; 246 } 247 else 248 { 249 current_column = 1; 250 current_row = cur_line; 251 skin_viewport->vp.x = parent->x + original_x; 252 skin_viewport->vp.y = parent->y + original_y + 253 (listcfg[screen]->height*cur_line); 254 } 255 display->set_viewport(&skin_viewport->vp); 256 /* Set images to not to be displayed */ 257 struct skin_token_list *imglist = SKINOFFSETTOPTR(get_skin_buffer(wps.data), wps.data->images); 258 while (imglist) 259 { 260 struct wps_token *token = SKINOFFSETTOPTR(get_skin_buffer(wps.data), imglist->token); 261 struct gui_img *img = NULL; 262 if (token) 263 img = SKINOFFSETTOPTR(get_skin_buffer(wps.data), token->value.data); 264 if (img) 265 img->display = -1; 266 imglist = SKINOFFSETTOPTR(get_skin_buffer(wps.data), imglist->next); 267 } 268 struct skin_element** children = SKINOFFSETTOPTR(get_skin_buffer(wps.data), viewport->children); 269 if (children && *children) 270 skin_render_viewport(SKINOFFSETTOPTR(get_skin_buffer(wps.data), (intptr_t)children[0]), 271 &wps, skin_viewport, SKIN_REFRESH_ALL); 272 wps_display_images(&wps, &skin_viewport->vp); 273 /* force disableing scroll because it breaks later */ 274 if (!is_selected) 275 { 276 display->scroll_stop_viewport(&skin_viewport->vp); 277 skin_viewport->vp.x = original_x; 278 skin_viewport->vp.y = original_y; 279 } 280 } 281 } 282 current_column = -1; 283 current_row = -1; 284 display->set_viewport(parent); 285 display->update_viewport(); 286 current_drawing_line = list->selected_item; 287 return true; 288}