A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 250 lines 9.6 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2007 Copyright Kévin Ferrare based on Zakk Roberts's work 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 "fixedpoint.h" 23#include "clock_draw_analog.h" 24#include "lib/xlcd.h" 25#include "clock_bitmaps.h" 26#include "clock_bitmap_strings.h" 27 28#define ANALOG_SECOND_RADIUS(screen, round) \ 29 ANALOG_MINUTE_RADIUS(screen, round) 30#define ANALOG_MINUTE_RADIUS(screen, round) \ 31 (round?MIN(screen->getheight()/2 -10, screen->getwidth()/2 -10):screen->getheight()/2) 32#define ANALOG_HOUR_RADIUS(screen, round) \ 33 (2*ANALOG_MINUTE_RADIUS(screen, round)/3) 34 35#define HOUR_ANGLE(hour, minute, second) (30*(hour) +(minute)/2) 36#define MINUTE_ANGLE(minute, second) (6*(minute)+(second)/10) 37#define SECOND_ANGLE(second) (6 * (second)) 38 39/* Note that the given angle's origin is midday and not 3 o'clock */ 40static void polar_to_cartesian(int a, int r, int* x, int* y) 41{ 42#if CONFIG_LCD == LCD_SSD1815 43 /* Correct non-square pixel aspect of archos recorder LCD */ 44 *x = (fp14_sin(a) * 5 / 4 * r) >> 14; 45#else 46 *x = (fp14_sin(a) * r) >> 14; 47#endif 48 *y = (fp14_sin(a-90) * r) >> 14; 49} 50 51static void polar_to_cartesian_screen_centered(struct screen * display, 52 int a, int r, int* x, int* y) 53{ 54 polar_to_cartesian(a, r, x, y); 55 *x+=display->getwidth()/2; 56 *y+=display->getheight()/2; 57} 58 59static void angle_to_square(int square_width, int square_height, 60 int a, int* x, int* y) 61{ 62 a = (a+360-90)%360; 63 if(a>45 && a<=135){/* top line */ 64 a-=45; 65 *x=square_width-(square_width*2*a)/90; 66 *y=square_height; 67 }else if(a>135 && a<=225){/* left line */ 68 a-=135; 69 *x=-square_width; 70 *y=square_height-(square_height*2*a)/90; 71 }else if(a>225 && a<=315){/* bottom line */ 72 a-=225; 73 *x=(square_width*2*a)/90-square_width; 74 *y=-square_height; 75 }else if(a>315 || a<=45){/* right line */ 76 if(a>315) 77 a-=315; 78 else 79 a+=45; 80 *x=square_width; 81 *y=(square_height*2*a)/90-square_height; 82 } 83} 84 85static void angle_to_square_screen_centered(struct screen * display, 86 int square_width, int square_height, 87 int a, int* x, int* y) 88{ 89 angle_to_square(square_width, square_height, a, x, y); 90 *x+=display->getwidth()/2; 91 *y+=display->getheight()/2; 92} 93 94static void draw_hand(struct screen* display, int angle, 95 int radius, int thickness, bool round) 96{ 97 int x1, y1; /* the longest */ 98 int x2, y2, x3, y3; /* the base */ 99 if(round){/* round clock */ 100 polar_to_cartesian_screen_centered(display, angle, radius, &x1, &y1); 101 }else{/* fullscreen clock, hands describes square motions */ 102 int square_width, square_height; 103 /* radius is defined smallest between getwidth() and getheight() */ 104 square_height=radius; 105 square_width=(radius*display->getwidth())/display->getheight(); 106 angle_to_square_screen_centered( 107 display, square_width, square_height, angle, &x1, &y1); 108 } 109 polar_to_cartesian_screen_centered(display, (angle+120)%360, 110 radius/40+thickness, &x2, &y2); 111 polar_to_cartesian_screen_centered(display, (angle+240)%360, 112 radius/40+thickness, &x3, &y3); 113 xlcd_filltriangle_screen(display, x1, y1, x2, y2, x3, y3); 114 rb->lcd_drawline(x1, y1, x2, y2); 115 rb->lcd_drawline(x1, y1, x3, y3); 116} 117 118static void draw_hands(struct screen* display, int hour, int minute, int second, 119 int thickness, bool round, bool draw_seconds) 120{ 121 if(draw_seconds){ 122 draw_hand(display, SECOND_ANGLE(second), 123 ANALOG_SECOND_RADIUS(display, round), thickness, round); 124 } 125 draw_hand(display, MINUTE_ANGLE(minute, second), 126 ANALOG_MINUTE_RADIUS(display, round), thickness+2, round); 127 draw_hand(display, HOUR_ANGLE(hour, minute, second), 128 ANALOG_HOUR_RADIUS(display, round), thickness+2, round); 129} 130 131static void draw_counter(struct screen* display, struct counter* counter) 132{ 133 char buffer[10]; 134 int second_str_w, hour_str_w, str_h; 135 const struct picture* smalldigits_bitmaps = 136 &(smalldigits[display->screen_type]); 137 struct time counter_time; 138 counter_get_elapsed_time(counter, &counter_time); 139 rb->snprintf(buffer, 10, "%02d:%02d", 140 counter_time.hour, counter_time.minute); 141 getstringsize(smalldigits_bitmaps, buffer, &hour_str_w, &str_h); 142 draw_string(display, smalldigits_bitmaps, buffer, 143 display->getwidth()-hour_str_w, 144 display->getheight()-2*str_h); 145 146 rb->snprintf(buffer, 10, "%02d", counter_time.second); 147 getstringsize(smalldigits_bitmaps, buffer, &second_str_w, &str_h); 148 draw_string(display, smalldigits_bitmaps, buffer, 149 display->getwidth()-(hour_str_w+second_str_w)/2, 150 display->getheight()-str_h); 151} 152 153static void draw_date(struct screen* display, struct time* time, int date_format) 154{ 155 char buffer[10]; 156 int year_str_w, monthday_str_w, str_h; 157 int year_line=date_format==JAPANESE?1:2; 158 int monthday_line=date_format==JAPANESE?2:1; 159 const struct picture* smalldigits_bitmaps = 160 &(smalldigits[display->screen_type]); 161 if(date_format==ENGLISH || date_format==JAPANESE){ 162 rb->snprintf(buffer, 10, "%02d/%02d", time->month, time->day); 163 }else{ 164 rb->snprintf(buffer, 10, "%02d/%02d", time->day, time->month); 165 } 166 /* draws month and day */ 167 getstringsize(smalldigits_bitmaps, buffer, &monthday_str_w, &str_h); 168 draw_string(display, smalldigits_bitmaps, buffer, 169 0, display->getheight()-year_line*str_h); 170 rb->snprintf(buffer, 10, "%04d", time->year); 171 172 /* draws year */ 173 getstringsize(smalldigits_bitmaps, buffer, &year_str_w, &str_h); 174 draw_string(display, smalldigits_bitmaps, buffer, 175 (monthday_str_w-year_str_w)/2, 176 display->getheight()-monthday_line*str_h); 177} 178 179static void draw_border(struct screen* display, int skin) 180{ 181 /* Draws square dots every 5 minutes */ 182 int i; 183 int x, y; 184 int size=display->getheight()/50;/* size of the square dots */ 185 if(size%2)/* a pair number */ 186 size++; 187 for(i=0; i < 60; i+=5){ 188 if(skin){ 189 polar_to_cartesian_screen_centered(display, MINUTE_ANGLE(i, 0), 190 ANALOG_MINUTE_RADIUS(display, skin), &x, &y); 191 }else{ 192 angle_to_square_screen_centered( 193 display, display->getwidth()/2-size/2, display->getheight()/2-size/2, 194 MINUTE_ANGLE(i, 0), &x, &y); 195 } 196 display->fillrect(x-size/2, y-size/2, size, size); 197 } 198} 199 200static void draw_hour(struct screen* display, struct time* time, 201 bool show_seconds, int skin) 202{ 203 int hour=time->hour; 204 if(hour >= 12) 205 hour -= 12; 206 207 /* Crappy fake antialiasing (color LCDs only)! 208 * how this works is we draw a large mid-gray hr/min/sec hand, 209 * then the actual (slightly smaller) hand on top of those. 210 * End result: mid-gray edges to the black hands, smooths them out. */ 211#ifdef HAVE_LCD_COLOR 212 if(display->is_color){ 213 display->set_foreground(LCD_RGBPACK(100,110,125)); 214 draw_hands(display, hour, time->minute, time->second, 215 1, skin, show_seconds); 216 display->set_foreground(LCD_BLACK); 217 } 218#endif 219 draw_hands(display, hour, time->minute, time->second, 220 0, skin, show_seconds); 221} 222 223static void draw_center_cover(struct screen* display) 224{ 225 display->hline((display->getwidth()/2)-1, 226 (display->getwidth()/2)+1, (display->getheight()/2)+3); 227 display->hline((display->getwidth()/2)-3, 228 (display->getwidth()/2)+3, (display->getheight()/2)+2); 229 display->fillrect((display->getwidth()/2)-4, (display->getheight()/2)-1, 9, 3); 230 display->hline((display->getwidth()/2)-3, 231 (display->getwidth()/2)+3, (display->getheight()/2)-2); 232 display->hline((display->getwidth()/2)-1, 233 (display->getwidth()/2)+1, (display->getheight()/2)-3); 234} 235 236void analog_clock_draw(struct screen* display, struct time* time, 237 struct clock_settings* settings, 238 struct counter* counter, 239 int skin) 240{ 241 242 draw_hour(display, time, settings->analog.show_seconds, skin); 243 if(settings->analog.show_border) 244 draw_border(display, skin); 245 if(counter) 246 draw_counter(display, counter); 247 if(settings->analog.show_date && settings->general.date_format!=NONE) 248 draw_date(display, time, settings->general.date_format); 249 draw_center_cover(display); 250}