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) 2006 - 2008 Alexander Papst
11 * Idea from http://www.tetris1d.org
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "plugin.h"
24#include "lib/pluginlib_actions.h"
25
26/* this set the context to use with PLA */
27static const struct button_mapping *plugin_contexts[] = { pla_main_ctx };
28#define ONEDROCKBLOX_DOWN PLA_DOWN
29#define ONEDROCKBLOX_DOWN_REPEAT PLA_DOWN_REPEAT
30#define ONEDROCKBLOX_QUIT PLA_EXIT
31
32#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
33 || (CONFIG_KEYPAD == IPOD_3G_PAD) \
34 || (CONFIG_KEYPAD == IPOD_4G_PAD)
35#define ONEDROCKBLOX_QUIT2 PLA_UP
36#else
37#define ONEDROCKBLOX_QUIT2 PLA_CANCEL
38#endif
39
40#define mrand(max) (short)(rb->rand()%max)
41
42#define TILES 11
43
44/**********
45** Lots of defines for the drawing stuff :-)
46** The most ugly way i could think of...
47*/
48
49#if (LCD_WIDTH > LCD_HEIGHT)
50 /* Any screens larger than the minis LCD */
51#if (LCD_WIDTH > 132)
52 /* Max size of one block */
53# define WIDTH (int)((LCD_HEIGHT * 0.85) / TILES)
54 /* Align the playing filed centered */
55# define CENTER_X (int)(LCD_WIDTH/2-(WIDTH/2))
56# define CENTER_Y (int)(LCD_HEIGHT/2-((WIDTH*TILES+TILES)/2))
57 /* Score box */
58# define SCORE_X (int)(((CENTER_X+WIDTH+4) + (LCD_WIDTH-(CENTER_X+WIDTH+4))/2)-(f_width/2))
59# define SCORE_Y (int)((LCD_HEIGHT/2)-(f_height/2))
60 /* Max. size of bricks is 4 blocks */
61# define NEXT_H (WIDTH*4+3)
62# define NEXT_X (int)(CENTER_X/2-WIDTH/2)
63# define NEXT_Y (int)(LCD_HEIGHT/2-NEXT_H/2)
64#else
65 /* Max size of one block */
66# define WIDTH (int)((LCD_HEIGHT * 0.85) / TILES)
67 /* Align the playing left centered */
68# define CENTER_X (int)(LCD_WIDTH*0.2)
69# define CENTER_Y (int)(LCD_HEIGHT/2-((WIDTH*TILES+TILES)/2))
70 /* Score box */
71# define SCORE_X (int)(((CENTER_X+WIDTH+4) + (LCD_WIDTH-(CENTER_X+WIDTH+4))/2)-(f_width/2))
72# define SCORE_Y 16
73 /* Max. size of bricks is 4 blocks */
74# define NEXT_H (WIDTH*4+3)
75# define NEXT_X (score_x+f_width+7)
76# define NEXT_Y (int)(LCD_HEIGHT-((4*WIDTH)+13))
77#endif
78#else
79 /* Max size of one block */
80# define WIDTH (int)((LCD_HEIGHT * 0.8) / TILES)
81 /* Align the playing filed centered */
82# define CENTER_X (int)(LCD_WIDTH/2-(WIDTH/2))
83# define CENTER_Y 2
84 /* Score box */
85# define SCORE_X (int)((LCD_WIDTH/2)-(f_width/2))
86# define SCORE_Y (LCD_HEIGHT-(f_height+2))
87 /* Max. size of bricks is 4 blocks */
88# define NEXT_H (WIDTH*4+3)
89# define NEXT_X (int)(CENTER_X/2-WIDTH/2)
90# define NEXT_Y (int)((LCD_HEIGHT * 0.8)/2-NEXT_H/2)
91#endif
92
93static void draw_brick(int pos, int length) {
94 int i = pos;
95 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
96 rb->lcd_fillrect(CENTER_X, CENTER_Y, WIDTH, WIDTH * TILES + TILES);
97 rb->lcd_set_drawmode(DRMODE_SOLID);
98
99 for (i = pos; i < length + pos; ++i) {
100 if (i >= 0) rb->lcd_fillrect(CENTER_X, CENTER_Y+i+(WIDTH*i), WIDTH, WIDTH);
101 }
102}
103
104enum plugin_status plugin_start(const void* parameter)
105{
106 int i;
107 int f_width, f_height;
108 int score_x;
109
110 bool quit = false;
111 int button;
112
113 int cycletime = 300;
114 int end;
115
116 int pos_cur_brick = 0;
117 int type_cur_brick = 0;
118 int type_next_brick = 0;
119
120 unsigned long int score = 34126;
121
122 (void)parameter;
123
124#if LCD_DEPTH > 1
125 rb->lcd_set_backdrop(NULL);
126 rb->lcd_set_background(LCD_BLACK);
127 rb->lcd_set_foreground(LCD_WHITE);
128#endif
129
130 rb->lcd_setfont(FONT_SYSFIXED);
131
132 rb->lcd_getstringsize("100000000", &f_width, &f_height);
133
134 rb->lcd_clear_display();
135
136 /***********
137 ** Draw EVERYTHING
138 */
139
140 /* Playing filed box */
141 rb->lcd_vline(CENTER_X-2, CENTER_Y, CENTER_Y + (WIDTH*TILES+TILES));
142 rb->lcd_vline(CENTER_X + WIDTH + 1, CENTER_Y,
143 CENTER_Y + (WIDTH*TILES+TILES));
144 rb->lcd_hline(CENTER_X-2, CENTER_X + WIDTH + 1,
145 CENTER_Y + (WIDTH*TILES+TILES));
146
147 /* Score box */
148#if (LCD_WIDTH > LCD_HEIGHT)
149 rb->lcd_drawrect(SCORE_X-4, SCORE_Y-5, f_width+8, f_height+9);
150 rb->lcd_putsxy(SCORE_X-4, SCORE_Y-6-f_height, "score");
151#else
152 rb->lcd_hline(0, LCD_WIDTH, SCORE_Y-5);
153 rb->lcd_putsxy(2, SCORE_Y-6-f_height, "score");
154#endif
155 score_x = SCORE_X;
156
157 /* Next box */
158 rb->lcd_getstringsize("next", &f_width, NULL);
159#if (LCD_WIDTH > LCD_HEIGHT) && !(LCD_WIDTH > 132)
160 rb->lcd_drawrect(NEXT_X-5, NEXT_Y-5, WIDTH+10, NEXT_H+10);
161 rb->lcd_putsxy(score_x-4, NEXT_Y-5, "next");
162#else
163 rb->lcd_drawrect(NEXT_X-5, NEXT_Y-5, WIDTH+10, NEXT_H+10);
164 rb->lcd_putsxy(NEXT_X-5, NEXT_Y-5-f_height-1, "next");
165#endif
166
167 /***********
168 ** GAMELOOP
169 */
170 rb->srand( *rb->current_tick );
171
172 type_cur_brick = 2 + mrand(3);
173 type_next_brick = 2 + mrand(3);
174
175 do {
176 end = *rb->current_tick + (cycletime * HZ) / 1000;
177
178 draw_brick(pos_cur_brick, type_cur_brick);
179
180 /* Draw next brick */
181 rb->lcd_set_drawmode(DRMODE_BG|DRMODE_INVERSEVID);
182 rb->lcd_fillrect(NEXT_X, NEXT_Y, WIDTH, WIDTH * 4 + 4);
183 rb->lcd_set_drawmode(DRMODE_SOLID);
184
185 for (i = 0; i < type_next_brick; ++i) {
186 rb->lcd_fillrect(NEXT_X,
187 NEXT_Y + ((type_next_brick % 2) ? (int)(WIDTH/2) : ((type_next_brick == 2) ? (WIDTH+1) : 0)) + (WIDTH*i) + i,
188 WIDTH, WIDTH);
189 }
190
191 /* Score box */
192 rb->lcd_putsxyf(score_x, SCORE_Y, "%8ld0", score);
193
194 rb->lcd_update();
195
196 /*We get button from PLA this way */
197 button = pluginlib_getaction(TIMEOUT_NOBLOCK, plugin_contexts,
198 ARRAYLEN(plugin_contexts));
199
200 switch(button) {
201 case ONEDROCKBLOX_DOWN:
202 case ONEDROCKBLOX_DOWN_REPEAT:
203 cycletime = 100;
204 break;
205 case ONEDROCKBLOX_QUIT:
206 case ONEDROCKBLOX_QUIT2:
207 quit = true;
208 break;
209 default:
210 cycletime = 300;
211 if(rb->default_event_handler(button) == SYS_USB_CONNECTED) {
212 quit = true;
213 }
214 }
215
216 if ((pos_cur_brick + type_cur_brick) > 10) {
217 type_cur_brick = type_next_brick;
218 type_next_brick = 2 + mrand(3);
219 score += (type_cur_brick - 1) * 2;
220 pos_cur_brick = 1 - type_cur_brick;
221 } else {
222 ++pos_cur_brick;
223 }
224
225 if (TIME_BEFORE(*rb->current_tick, end))
226 rb->sleep(end-*rb->current_tick);
227 else
228 rb->yield();
229
230 } while (!quit);
231
232 return PLUGIN_OK;
233}