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) 2005 Kevin Ferrare
11*
12* Mystify demo plugin
13*
14* This program is free software; you can redistribute it and/or
15* modify it under the terms of the GNU General Public License
16* as published by the Free Software Foundation; either version 2
17* of the License, or (at your option) any later version.
18*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22****************************************************************************/
23
24#include "plugin.h"
25#include "lib/pluginlib_exit.h"
26
27#include "lib/pluginlib_actions.h"
28#include "lib/helper.h"
29
30
31#define DEFAULT_WAIT_TIME 3
32#define DEFAULT_NB_POLYGONS 7
33#define NB_POINTS 4
34#define MAX_STEP_RANGE 7
35#define MIN_STEP_RANGE 3
36#define MAX_POLYGONS 40
37#define MIN_POLYGONS 1
38
39/* Key assignement */
40
41#ifdef HAVE_SCROLLWHEEL
42
43#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
44 || (CONFIG_KEYPAD == IPOD_3G_PAD) \
45 || (CONFIG_KEYPAD == IPOD_4G_PAD)
46#define DEMYSTIFY_QUIT PLA_UP
47#else
48#define DEMYSTIFY_QUIT PLA_CANCEL
49#endif
50
51#define DEMYSTIFY_INCREASE_SPEED PLA_SCROLL_FWD
52#define DEMYSTIFY_DECREASE_SPEED PLA_SCROLL_BACK
53#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_SCROLL_FWD_REPEAT
54#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_SCROLL_BACK_REPEAT
55
56#define DEMYSTIFY_ADD_POLYGON PLA_RIGHT
57#define DEMYSTIFY_REMOVE_POLYGON PLA_LEFT
58#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_RIGHT_REPEAT
59#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_LEFT_REPEAT
60
61#else
62
63#define DEMYSTIFY_QUIT PLA_CANCEL
64
65#define DEMYSTIFY_INCREASE_SPEED PLA_RIGHT
66#define DEMYSTIFY_DECREASE_SPEED PLA_LEFT
67#define DEMYSTIFY_INCREASE_SPEED_REPEAT PLA_RIGHT_REPEAT
68#define DEMYSTIFY_DECREASE_SPEED_REPEAT PLA_LEFT_REPEAT
69
70#define DEMYSTIFY_ADD_POLYGON PLA_UP
71#define DEMYSTIFY_REMOVE_POLYGON PLA_DOWN
72#define DEMYSTIFY_ADD_POLYGON_REPEAT PLA_UP_REPEAT
73#define DEMYSTIFY_REMOVE_POLYGON_REPEAT PLA_DOWN_REPEAT
74
75#endif
76const struct button_mapping *plugin_contexts[]
77= {pla_main_ctx,
78#if defined(HAVE_REMOTE_LCD)
79 pla_remote_ctx,
80#endif
81};
82
83#ifdef HAVE_LCD_COLOR
84struct line_color
85{
86 int r,g,b;
87 int current_r,current_g,current_b;
88};
89#endif
90
91/******************************* Globals ***********************************/
92
93/*
94 * Compute a new random step to make the point bounce the borders of the screen
95 */
96
97static int get_new_step(int step)
98{
99 if(step>0)
100 return -(MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
101 else
102 return (MIN_STEP_RANGE + rb->rand() % (MAX_STEP_RANGE-MIN_STEP_RANGE));
103}
104
105/*
106 * Point Stuffs
107 */
108
109struct point
110{
111 int x;
112 int y;
113};
114
115/*
116 * Polygon Stuffs
117 */
118
119struct polygon
120{
121 struct point points[NB_POINTS];
122};
123
124/*
125 * Generates a random polygon (which fits the screen size though)
126 */
127static void polygon_init(struct polygon * polygon, struct screen * display)
128{
129 int i;
130 for(i=0;i<NB_POINTS;++i)
131 {
132 polygon->points[i].x=(rb->rand() % (display->getwidth()));
133 polygon->points[i].y=(rb->rand() % (display->getheight()));
134 }
135}
136
137/*
138 * Draw the given polygon onto the screen
139 */
140
141static void polygon_draw(struct polygon * polygon, struct screen * display)
142{
143 int i;
144 for(i=0;i<NB_POINTS-1;++i)
145 {
146 display->drawline(polygon->points[i].x, polygon->points[i].y,
147 polygon->points[i+1].x, polygon->points[i+1].y);
148 }
149 display->drawline(polygon->points[0].x, polygon->points[0].y,
150 polygon->points[NB_POINTS-1].x,
151 polygon->points[NB_POINTS-1].y);
152}
153
154/*
155 * Polygon moving data Stuffs
156 */
157
158struct polygon_move
159{
160 struct point move_steps[NB_POINTS];
161};
162
163static void polygon_move_init(struct polygon_move * polygon_move)
164{
165 int i;
166 for(i=0;i<NB_POINTS;++i)
167 {
168 polygon_move->move_steps[i].x=get_new_step(-1);
169 /* -1 because we want a positive random step */
170 polygon_move->move_steps[i].y=get_new_step(-1);
171 }
172}
173
174/*
175 * Update the given polygon's position according to the given informations in
176 * polygon_move (polygon_move may be updated)
177 */
178static void polygon_update(struct polygon *polygon, struct screen * display,
179 struct polygon_move *polygon_move)
180{
181 int i, x, y, step;
182 for(i=0;i<NB_POINTS;++i)
183 {
184 x=polygon->points[i].x;
185 step=polygon_move->move_steps[i].x;
186 x+=step;
187 if(x<=0)
188 {
189 x=1;
190 polygon_move->move_steps[i].x=get_new_step(step);
191 }
192 else if(x>=display->getwidth())
193 {
194 x=display->getwidth()-1;
195 polygon_move->move_steps[i].x=get_new_step(step);
196 }
197 polygon->points[i].x=x;
198
199 y=polygon->points[i].y;
200 step=polygon_move->move_steps[i].y;
201 y+=step;
202 if(y<=0)
203 {
204 y=1;
205 polygon_move->move_steps[i].y=get_new_step(step);
206 }
207 else if(y>=display->getheight())
208 {
209 y=display->getheight()-1;
210 polygon_move->move_steps[i].y=get_new_step(step);
211 }
212 polygon->points[i].y=y;
213 }
214}
215
216/*
217 * Polygon fifo Stuffs
218 */
219
220struct polygon_fifo
221{
222 int fifo_tail;
223 int fifo_head;
224 int nb_items;
225 struct polygon tab[MAX_POLYGONS];
226};
227
228static void fifo_init(struct polygon_fifo * fifo)
229{
230 fifo->fifo_tail=0;
231 fifo->fifo_head=0;
232 fifo->nb_items=0;
233}
234
235static void fifo_push(struct polygon_fifo * fifo, struct polygon * polygon)
236{
237 if(fifo->nb_items>=MAX_POLYGONS)
238 return;
239 ++(fifo->nb_items);
240
241 /*
242 * Workaround for gcc (which uses memcpy internally) to avoid link error
243 * fifo->tab[fifo->fifo_head]=polygon
244 */
245 rb->memcpy(&(fifo->tab[fifo->fifo_head]), polygon, sizeof(struct polygon));
246 ++(fifo->fifo_head);
247 if(fifo->fifo_head>=MAX_POLYGONS)
248 fifo->fifo_head=0;
249}
250
251static struct polygon * fifo_pop(struct polygon_fifo * fifo)
252{
253 int index;
254 if(fifo->nb_items==0)
255 return(NULL);
256 --(fifo->nb_items);
257 index=fifo->fifo_tail;
258 ++(fifo->fifo_tail);
259 if(fifo->fifo_tail>=MAX_POLYGONS)
260 fifo->fifo_tail=0;
261 return(&(fifo->tab[index]));
262}
263
264/*
265 * Drawing stuffs
266 */
267
268static void polygons_draw(struct polygon_fifo * polygons, struct screen * display)
269{
270 int i, j;
271 for(i=0, j=polygons->fifo_tail;i<polygons->nb_items;++i, ++j)
272 {
273 if(j>=MAX_POLYGONS)
274 j=0;
275 polygon_draw(&(polygons->tab[j]), display);
276 }
277}
278
279static void cleanup(void)
280{
281
282 backlight_use_settings();
283 remote_backlight_use_settings();
284
285}
286
287#ifdef HAVE_LCD_COLOR
288static void color_randomize(struct line_color * color)
289{
290 color->r = rb->rand()%255;
291 color->g = rb->rand()%255;
292 color->b = rb->rand()%255;
293}
294
295static void color_init(struct line_color * color)
296{
297 color_randomize(color);
298 color->current_r=color->r;
299 color->current_g=color->g;
300 color->current_b=color->b;
301}
302
303static void color_change(struct line_color * color)
304{
305 if(color->current_r<color->r)
306 ++color->current_r;
307 else if(color->current_r>color->r)
308 --color->current_r;
309 if(color->current_g<color->g)
310 ++color->current_g;
311 else if(color->current_g>color->g)
312 --color->current_g;
313 if(color->current_b<color->b)
314 ++color->current_b;
315 else if(color->current_b>color->b)
316 --color->current_b;
317
318 if(color->current_r==color->r &&
319 color->current_g==color->g &&
320 color->current_b==color->b)
321 color_randomize(color);
322}
323
324#define COLOR_RGBPACK(color) \
325 LCD_RGBPACK((color)->current_r, (color)->current_g, (color)->current_b)
326
327static void color_apply(struct line_color * color, struct screen * display)
328{
329 if (display->is_color){
330 unsigned foreground=
331 SCREEN_COLOR_TO_NATIVE(display,COLOR_RGBPACK(color));
332 display->set_foreground(foreground);
333 }
334}
335#endif
336
337/*
338 * Main function
339 */
340
341static int plugin_main(void)
342{
343 int action;
344 int sleep_time=DEFAULT_WAIT_TIME;
345 int nb_wanted_polygons=DEFAULT_NB_POLYGONS;
346 struct polygon_fifo polygons[NB_SCREENS];
347 struct polygon_move move[NB_SCREENS]; /* This describes the movement of the leading
348 polygon, the others just follow */
349 struct polygon leading_polygon[NB_SCREENS];
350 FOR_NB_SCREENS(i)
351 {
352#ifdef HAVE_LCD_COLOR
353 struct screen *display = rb->screens[i];
354 if (display->is_color)
355 display->set_background(LCD_BLACK);
356#endif
357 fifo_init(&polygons[i]);
358 polygon_move_init(&move[i]);
359 polygon_init(&leading_polygon[i], rb->screens[i]);
360 }
361
362#ifdef HAVE_LCD_COLOR
363 struct line_color color;
364 color_init(&color);
365#endif
366
367 while (true)
368 {
369 FOR_NB_SCREENS(i)
370 {
371 struct screen * display=rb->screens[i];
372 if(polygons[i].nb_items>nb_wanted_polygons)
373 { /* We have too many polygons, we must drop some of them */
374 fifo_pop(&polygons[i]);
375 }
376 if(nb_wanted_polygons==polygons[i].nb_items)
377 { /* We have the good number of polygons, we can safely drop
378 the last one to add the new one later */
379 fifo_pop(&polygons[i]);
380 }
381 fifo_push(&polygons[i], &leading_polygon[i]);
382
383 /*
384 * Then we update the leading polygon for the next round acording to
385 * current move (the move may be altered in case of sreen border
386 * collision)
387 */
388 polygon_update(&leading_polygon[i], display, &move[i]);
389
390 /* Now the drawing part */
391#ifdef HAVE_LCD_COLOR
392 color_apply(&color, display);
393#endif
394 display->clear_display();
395 polygons_draw(&polygons[i], display);
396 display->update();
397 }
398#ifdef HAVE_LCD_COLOR
399 color_change(&color);
400#endif
401 /* Speed handling*/
402 if (sleep_time<0)/* full speed */
403 rb->yield();
404 else
405 rb->sleep(sleep_time);
406 action = pluginlib_getaction(TIMEOUT_NOBLOCK,
407 plugin_contexts, ARRAYLEN(plugin_contexts));
408 switch(action)
409 {
410 case DEMYSTIFY_QUIT:
411 return PLUGIN_OK;
412
413 case DEMYSTIFY_ADD_POLYGON:
414 case DEMYSTIFY_ADD_POLYGON_REPEAT:
415 if(nb_wanted_polygons<MAX_POLYGONS)
416 ++nb_wanted_polygons;
417 break;
418
419 case DEMYSTIFY_REMOVE_POLYGON:
420 case DEMYSTIFY_REMOVE_POLYGON_REPEAT:
421 if(nb_wanted_polygons>MIN_POLYGONS)
422 --nb_wanted_polygons;
423 break;
424
425 case DEMYSTIFY_INCREASE_SPEED:
426 case DEMYSTIFY_INCREASE_SPEED_REPEAT:
427 if(sleep_time>=0)
428 --sleep_time;
429 break;
430
431 case DEMYSTIFY_DECREASE_SPEED:
432 case DEMYSTIFY_DECREASE_SPEED_REPEAT:
433 ++sleep_time;
434 break;
435
436 default:
437 exit_on_usb(action);
438 break;
439 }
440 }
441}
442
443/*************************** Plugin entry point ****************************/
444
445enum plugin_status plugin_start(const void* parameter)
446{
447 int ret;
448
449 (void)parameter;
450 atexit(cleanup);
451
452#if LCD_DEPTH > 1
453 rb->lcd_set_backdrop(NULL);
454#endif
455
456 backlight_ignore_timeout();
457 remote_backlight_ignore_timeout();
458
459 ret = plugin_main();
460
461 return ret;
462}