A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 230 lines 6.1 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 by Daniel Stenberg 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 "config.h" 22#include "system.h" 23#include "kernel.h" 24#include "button.h" 25#ifdef HAVE_SDL 26#include "SDL.h" 27#if SDL_MAJOR_VERSION > 1 28#include "window-sdl.h" 29#endif 30#endif 31 32static struct event_queue button_queue SHAREDBSS_ATTR; 33static intptr_t button_data; /* data value from last message dequeued */ 34 35#ifdef HAVE_ADJUSTABLE_CPU_FREQ 36static bool button_boosted = false; 37static long button_unboost_tick; 38#define BUTTON_UNBOOST_TMO HZ 39 40static void button_boost(bool state) 41{ 42 if (state) 43 { 44 /* update the unboost time each button_boost(true) call */ 45 button_unboost_tick = current_tick + BUTTON_UNBOOST_TMO; 46 47 if (!button_boosted) 48 { 49 button_boosted = true; 50 cpu_boost(true); 51 } 52 } 53 else if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick)) 54 { 55 button_boosted = false; 56 cpu_boost(false); 57 } 58} 59 60static void button_queue_wait(struct queue_event *evp, int timeout) 61{ 62 /* Loop once after wait time if boosted in order to unboost and wait the 63 full remaining time */ 64 do 65 { 66 int ticks = timeout; 67 68 if (ticks == TIMEOUT_NOBLOCK) 69 ; 70 else if (ticks > 0) 71 { 72 if (button_boosted && ticks > BUTTON_UNBOOST_TMO) 73 ticks = BUTTON_UNBOOST_TMO; 74 75 timeout -= ticks; 76 } 77 else if (button_boosted) /* TIMEOUT_BLOCK (ticks < 0) */ 78 { 79 ticks = BUTTON_UNBOOST_TMO; 80 } 81 82 queue_wait_w_tmo(&button_queue, evp, ticks); 83 if (evp->id != SYS_TIMEOUT) 84 { 85 /* GUI boost build gets immediate kick, otherwise at least 3 86 messages had to be there */ 87 #ifndef HAVE_GUI_BOOST 88 if (queue_count(&button_queue) >= 2) 89 #endif 90 button_boost(true); 91 92 break; 93 } 94 button_boost(false); 95 } 96 while (timeout); 97} 98#else /* ndef HAVE_ADJUSTABLE_CPU_FREQ */ 99static inline void button_queue_wait(struct queue_event *evp, int timeout) 100{ 101#if defined(__APPLE__) && (CONFIG_PLATFORM & PLATFORM_SDL) 102 unsigned long initial_tick = current_tick; 103 unsigned long curr_tick, remaining; 104 while(true) 105 { 106 SDL_PumpEvents(); 107 queue_wait_w_tmo(&button_queue, evp, TIMEOUT_NOBLOCK); 108 if (evp->id != SYS_TIMEOUT || timeout == TIMEOUT_NOBLOCK) 109 return; 110 else if (timeout == TIMEOUT_BLOCK) 111 sleep(HZ/60); 112 else 113 { 114 curr_tick = current_tick; 115 if (!TIME_AFTER(initial_tick + timeout, curr_tick)) 116 return; 117 remaining = ((initial_tick + timeout) - curr_tick); 118 sleep(remaining < HZ/60 ? remaining : HZ/60); 119 } 120 } 121#else 122 queue_wait_w_tmo(&button_queue, evp, timeout); 123#if defined(HAVE_SDL) && (SDL_MAJOR_VERSION > 1) 124 sdl_window_adjust(); /* Window may have been resized */ 125#endif 126#endif 127} 128#endif /* HAVE_ADJUSTABLE_CPU_FREQ */ 129 130void button_queue_post(long id, intptr_t data) 131{ 132 queue_post(&button_queue, id, data); 133} 134 135void button_queue_post_remove_head(long id, intptr_t data) 136{ 137 queue_remove_from_head(&button_queue, id); 138 queue_post(&button_queue, id, data); 139} 140 141bool button_queue_try_post(long button, int data) 142{ 143#ifdef HAVE_TOUCHSCREEN 144 /* one can swipe over the scren very quickly, 145 * for this to work we want to forget about old presses and 146 * only respect the very latest ones */ 147 const bool force_post = true; 148#else 149 /* Only post events if the queue is empty, 150 * to avoid afterscroll effects. 151 * i.e. don't post new buttons if previous ones haven't been 152 * processed yet - but always post releases */ 153 const bool force_post = button & BUTTON_REL; 154#endif 155 156 if (!queue_empty(&button_queue)) 157 { 158 if (force_post) 159 queue_remove_from_head(&button_queue, button); 160 else 161 return false; 162 } 163 164 queue_post(&button_queue, button, data); 165 166 /* on touchscreen we posted unconditionally */ 167 return true; 168} 169 170int button_queue_count(void) 171{ 172 return queue_count(&button_queue); 173} 174 175bool button_queue_empty(void) 176{ 177 return queue_empty(&button_queue); 178} 179 180bool button_queue_full(void) 181{ 182 return queue_full(&button_queue); 183} 184 185void button_clear_queue(void) 186{ 187 queue_clear(&button_queue); 188} 189 190/* clears anything but release and sysevents */ 191void button_clear_pressed(void) 192{ 193 long button; 194 for (int count = queue_count(&button_queue); count > 0; count--) 195 { 196 button = button_get(false); 197 if (button & (BUTTON_REL | SYS_EVENT)) 198 { 199 button_queue_post(button, button_data); 200 } 201 } 202} 203 204long button_get_w_tmo(int ticks) 205{ 206 struct queue_event ev; 207 button_queue_wait(&ev, ticks); 208 209 if (ev.id == SYS_TIMEOUT) 210 ev.id = BUTTON_NONE; 211 else 212 button_data = ev.data; 213 214 return ev.id; 215} 216 217long button_get(bool block) 218{ 219 return button_get_w_tmo(block ? TIMEOUT_BLOCK : TIMEOUT_NOBLOCK); 220} 221 222intptr_t button_get_data(void) 223{ 224 return button_data; 225} 226 227void INIT_ATTR button_queue_init(void) 228{ 229 queue_init(&button_queue, true); 230}