A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 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#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include "inttypes.h"
25#include "config.h"
26#include "core_alloc.h"
27#include "icon.h"
28#include "screen_access.h"
29#include "icons.h"
30#include "settings.h"
31#include "rbpaths.h"
32#include "bmp.h"
33#include "filetypes.h"
34#include "language.h"
35#include "misc.h"
36
37#include "bitmaps/default_icons.h"
38#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
39#include "bitmaps/remote_default_icons.h"
40#endif
41
42/* We dont actually do anything with these pointers,
43 but they need to be grouped like this to save code
44 so storing them as void* is ok. (stops compile warning) */
45static const struct bitmap *inbuilt_iconset[NB_SCREENS] =
46{
47 &bm_default_icons,
48#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
49 &bm_remote_default_icons,
50#endif
51};
52
53enum Iconset {
54 Iconset_user,
55 Iconset_viewers,
56 Iconset_Count
57};
58
59static struct iconset {
60 struct bitmap bmp;
61 bool loaded;
62 int handle;
63} iconsets[Iconset_Count][NB_SCREENS];
64
65#define ICON_HEIGHT(screen) (!iconsets[Iconset_user][screen].loaded ? \
66 (*(inbuilt_iconset[screen])) : iconsets[Iconset_user][screen].bmp).height \
67 / Icon_Last_Themeable
68
69#define ICON_WIDTH(screen) (!iconsets[Iconset_user][screen].loaded ? \
70 (*(inbuilt_iconset[screen])) : iconsets[Iconset_user][screen].bmp).width
71
72/* x,y in letters, not pixles */
73void screen_put_icon(struct screen * display,
74 int x, int y, enum themable_icons icon)
75{
76 screen_put_icon_with_offset(display, x, y, 0, 0, icon);
77}
78
79void screen_put_icon_with_offset(struct screen * display,
80 int x, int y, int off_x, int off_y,
81 enum themable_icons icon)
82{
83 const int screen = display->screen_type;
84 const int icon_width = ICON_WIDTH(screen);
85 const int icon_height = ICON_HEIGHT(screen);
86 int xpos, ypos;
87 int width, height;
88 display->getstringsize((unsigned char *)"M", &width, &height);
89 xpos = x*icon_width + off_x;
90 ypos = y*height + off_y;
91
92 if ( height > icon_height )/* center the cursor */
93 ypos += (height - icon_height) / 2;
94 screen_put_iconxy(display, xpos, ypos, icon);
95}
96
97/* x,y in pixels */
98void screen_put_iconxy(struct screen * display,
99 int xpos, int ypos, enum themable_icons icon)
100{
101 const int screen = display->screen_type;
102 const int width = ICON_WIDTH(screen);
103 const int height = ICON_HEIGHT(screen);
104 const int is_rtl = lang_is_rtl();
105 const struct bitmap *iconset;
106
107 if (icon <= Icon_NOICON)
108 {
109 if (is_rtl)
110 xpos = display->getwidth() - xpos - width;
111 screen_clear_area(display, xpos, ypos, width, height);
112 return;
113 }
114 else if (icon >= Icon_Last_Themeable)
115 {
116 iconset = &iconsets[Iconset_viewers][screen].bmp;
117 icon -= Icon_Last_Themeable;
118 if (!iconsets[Iconset_viewers][screen].loaded ||
119 (global_status.viewer_icon_count * height > iconset->height) ||
120 (icon * height + height > iconset->height))
121 {
122 screen_put_iconxy(display, xpos, ypos, Icon_Questionmark);
123 return;
124 }
125 }
126 else if (iconsets[Iconset_user][screen].loaded)
127 {
128 iconset = &iconsets[Iconset_user][screen].bmp;
129 }
130 else
131 {
132 iconset = inbuilt_iconset[screen];
133 }
134
135 if (is_rtl)
136 xpos = display->getwidth() - xpos - width;
137
138
139 display->bmp_part(iconset, 0, height * icon, xpos, ypos, width, height);
140}
141
142void screen_put_cursorxy(struct screen * display, int x, int y, bool on)
143{
144 screen_put_icon(display, x, y, on?Icon_Cursor:0);
145}
146
147static int buflib_move_callback(int handle, void* current, void* new)
148{
149 (void)handle;
150 (void)new;
151 int i;
152 FOR_NB_SCREENS(j)
153 {
154 for (i=0; i<Iconset_Count; i++)
155 {
156 struct iconset *set = &iconsets[i][j];
157 if (set->bmp.data == current)
158 {
159 set->bmp.data = new;
160 return BUFLIB_CB_OK;
161 }
162 }
163 }
164 return BUFLIB_CB_OK;
165}
166
167static void load_icons(const char* filename, enum Iconset iconset,
168 enum screen_type screen)
169{
170 static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL};
171 const int bmpformat = (FORMAT_ANY|FORMAT_DITHER|FORMAT_TRANSPARENT);
172 struct iconset *ic = &iconsets[iconset][screen];
173 ssize_t buf_reqd;
174
175 ic->loaded = false;
176 ic->handle = CLB_ALOC_ERR;
177 if (filename[0] && filename[0] != '-')
178 {
179 char fname[MAX_PATH];
180 snprintf(fname, sizeof(fname), ICON_DIR "/%s.bmp", filename);
181 ic->handle = core_load_bmp(fname, &ic->bmp, bmpformat, &buf_reqd, &buflib_ops);
182 if (ic->handle != CLB_ALOC_ERR)
183 {
184 ic->bmp.data = core_get_data(ic->handle);
185 ic->loaded = true;
186 }
187 }
188}
189
190void icons_init(void)
191{
192 int i;
193 FOR_NB_SCREENS(j)
194 {
195 for (i=0; i<Iconset_Count; i++)
196 {
197 struct iconset* set = &iconsets[i][j];
198 if (set->loaded && set->handle > 0)
199 {
200 set->handle = core_free(set->handle);
201 set->loaded = false;
202 }
203 }
204 }
205
206 if (global_settings.show_icons)
207 {
208 load_icons(global_settings.icon_file, Iconset_user, SCREEN_MAIN);
209
210 if (global_settings.viewers_icon_file[0] != '-' &&
211 global_settings.viewers_icon_file[0] != '\0')
212 {
213 load_icons(global_settings.viewers_icon_file,
214 Iconset_viewers, SCREEN_MAIN);
215 read_viewer_theme_file();
216 }
217#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
218 load_icons(global_settings.remote_icon_file,
219 Iconset_user, SCREEN_REMOTE);
220
221 if (global_settings.remote_viewers_icon_file[0] != '-' &&
222 global_settings.remote_viewers_icon_file[0] != '\0')
223 {
224 load_icons(global_settings.remote_viewers_icon_file,
225 Iconset_viewers, SCREEN_REMOTE);
226 }
227#endif
228 }
229}
230
231int get_icon_width(enum screen_type screen_type)
232{
233 return ICON_WIDTH(screen_type);
234}
235
236int get_icon_height(enum screen_type screen_type)
237{
238 return ICON_HEIGHT(screen_type);
239}
240
241#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
242int get_icon_format(enum screen_type screen)
243{
244 const struct bitmap *iconset;
245
246 if (iconsets[Iconset_user][screen].loaded)
247 iconset = &iconsets[Iconset_user][screen].bmp;
248 else
249 iconset = inbuilt_iconset[screen];
250
251 return iconset->format;
252}
253#endif