A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 205 lines 6.3 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2010 Clément Pit-Claudel 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 "plugin.h" 23#include "lib/pluginlib_actions.h" 24 25 26 27const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; 28 29static int current = 0; 30static bool tomorrow = false; 31static int alarms[2] = {0, 0}, maxval[2] = {24, 60}, prev_tick = 3600 * 24; 32static bool quit = false, usb = false, waiting = false, done = false; 33 34static inline int get_button(void) 35{ 36 return pluginlib_getaction(HZ/2, plugin_contexts, 37 ARRAYLEN(plugin_contexts)); 38} 39 40static int rem_seconds(void) 41{ 42 int seconds = (((alarms[0] - rb->get_time()->tm_hour) * 3600) 43 +((alarms[1] - rb->get_time()->tm_min) * 60) 44 -(rb->get_time()->tm_sec)); 45 46 /* The tomorrow flag means that the alarm should ring on the next day */ 47 if (seconds > prev_tick) tomorrow = false; 48 prev_tick = seconds; 49 50 return seconds + (tomorrow ? 24 * 3600 : 0); 51} 52 53static void draw_centered_string(struct screen * display, char * string) 54{ 55 int w, h; 56 display->getstringsize(string, &w, &h); 57 58 if (w > display->lcdwidth || h > display->lcdheight) { 59 rb->splash(0, string); 60 } else { 61 display->putsxy((display->lcdwidth - w) / 2, 62 (display->lcdheight - h) / 2, 63 string); 64 display->update(); 65 } 66} 67 68static void draw(struct screen * display) 69{ 70 char info[128]; 71 display->clear_display(); 72 73 int secs = rem_seconds(); 74 75 if (waiting) 76 rb->snprintf(info, sizeof(info), "Next alarm in %02dh," 77 " %02dmn, and %02ds.", 78 secs / 3600, (secs / 60) % 60, secs % 60); 79 else { 80 if (current == 0) 81 rb->snprintf(info, sizeof(info), "Set alarm at [%02d]:%02d.", 82 alarms[0], 83 alarms[1]); 84 else 85 rb->snprintf(info, sizeof(info), "Set alarm at %02d:[%02d].", 86 alarms[0], 87 alarms[1]); 88 } 89 draw_centered_string(display, info); 90} 91 92static bool can_play(void) 93{ 94 int audio_status = rb->audio_status(); 95 if ((!audio_status && rb->global_status->resume_index != -1) 96 && (rb->playlist_resume() != -1)) { 97 return true; 98 } 99 else if (audio_status & AUDIO_STATUS_PLAY) 100 return true; 101 102 return false; 103} 104 105static void resume_audio(void) 106{ 107 int audio_status = rb->audio_status(); 108 if (!audio_status && rb->global_status->resume_index != -1) { 109 if (rb->playlist_resume() != -1) { 110 rb->playlist_resume_track(rb->global_status->resume_index, 111 rb->global_status->resume_crc32, 112 rb->global_status->resume_elapsed, 113 rb->global_status->resume_offset); 114 } 115 } 116 else if (audio_status & AUDIO_STATUS_PLAY) 117 rb->audio_resume(); 118} 119 120static void pause_audio(void) 121{ 122 if (rb->audio_status() & AUDIO_STATUS_PLAY) 123 rb->audio_pause(); 124} 125 126enum plugin_status plugin_start(const void* parameter) 127{ 128 int button; 129 (void)parameter; 130 131 if (!can_play()) { 132 rb->splash(HZ*2, "No track to resume! " 133 "Play or pause one first."); 134 return PLUGIN_ERROR; 135 } 136 pause_audio(); 137 138 while(!quit) { 139 FOR_NB_SCREENS(i) { 140 draw(rb->screens[i]); 141 } 142 button = get_button(); 143 144#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ 145 || (CONFIG_KEYPAD == IPOD_3G_PAD) \ 146 || (CONFIG_KEYPAD == IPOD_4G_PAD) 147 if (button == PLA_EXIT || button == PLA_CANCEL || button == PLA_UP) 148#else 149 if (button == PLA_EXIT || button == PLA_CANCEL) 150#endif 151 quit = true; 152 153 if (waiting) { 154 if (rem_seconds() <= 0) { 155 quit = done = true; 156 resume_audio(); 157 } 158 } 159 else { 160 switch (button) { 161 case PLA_UP: 162 case PLA_UP_REPEAT: 163#ifdef HAVE_SCROLLWHEEL 164 case PLA_SCROLL_FWD: 165 case PLA_SCROLL_FWD_REPEAT: 166#endif 167 alarms[current] = (alarms[current] + 1) % maxval[current]; 168 break; 169 case PLA_DOWN: 170 case PLA_DOWN_REPEAT: 171#ifdef HAVE_SCROLLWHEEL 172 case PLA_SCROLL_BACK: 173 case PLA_SCROLL_BACK_REPEAT: 174#endif 175 alarms[current] = (alarms[current] + maxval[current] - 1) 176 % maxval[current]; 177 break; 178 179 case PLA_LEFT: 180 case PLA_LEFT_REPEAT: 181 case PLA_RIGHT: 182 case PLA_RIGHT_REPEAT: 183 current = (current + 1) % 2; 184 break; 185 186 case PLA_SELECT: 187 case PLA_SELECT_REPEAT: { 188 if (rem_seconds() < 0) 189 tomorrow = true; 190 191 waiting = true; 192 break; 193 } 194 195 default: 196 if (rb->default_event_handler(button) == SYS_USB_CONNECTED) 197 quit = usb = true; 198 break; 199 } 200 } 201 } 202 203 return (usb) ? PLUGIN_USB_CONNECTED 204 : (done ? PLUGIN_GOTO_WPS : PLUGIN_OK); 205}