A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 181 lines 6.1 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2010 Thomas Martitz 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 22package org.rockbox.Helper; 23 24import org.rockbox.RockboxFramebuffer; 25import org.rockbox.RockboxService; 26import android.content.BroadcastReceiver; 27import android.content.ComponentName; 28import android.content.Context; 29import android.content.Intent; 30import android.content.IntentFilter; 31import android.media.AudioManager; 32import android.view.KeyEvent; 33 34public class MediaButtonReceiver 35{ 36 /* A note on the API being used. 2.2 introduces a new and sane API 37 * for handling multimedia button presses 38 * http://android-developers.blogspot.com/2010/06/allowing-applications-to-play-nicer.html 39 * 40 * the old API is flawed. It doesn't have management for 41 * concurrent media apps 42 * 43 * if multiple media apps are running 44 * probably all of them want to respond to media keys 45 * 46 * it's not clear which app wins, it depends on the 47 * priority set for the IntentFilter (see below) 48 * 49 * so this all might or might not work on < 2.2 */ 50 51 IMultiMediaReceiver api; 52 53 public MediaButtonReceiver(Context c) 54 { 55 try { 56 api = new NewApi(c); 57 } catch (Throwable t) { 58 /* Throwable includes Exception and the expected 59 * NoClassDefFoundError */ 60 api = new OldApi(c); 61 Logger.i("MediaButtonReceiver: Falling back to compatibility API"); 62 } 63 } 64 65 public void register() 66 { 67 api.register(); 68 } 69 70 public void unregister() 71 { 72 api.unregister(); 73 } 74 75 /* helper class for the manifest */ 76 public static class MediaReceiver extends BroadcastReceiver 77 { 78 private void startService(Context c, Intent baseIntent) 79 { 80 baseIntent.setClass(c, RockboxService.class); 81 c.startService(baseIntent); 82 } 83 @Override 84 public void onReceive(Context context, Intent intent) 85 { 86 if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) 87 { 88 KeyEvent key = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); 89 if (key.getAction() == KeyEvent.ACTION_UP) 90 { /* pass the pressed key to Rockbox, starting it if needed */ 91 RockboxService s = RockboxService.getInstance(); 92 if (s == null || !s.isRockboxRunning()) 93 startService(context, intent); 94 else if (RockboxFramebuffer.buttonHandler(key.getKeyCode(), false)) 95 abortBroadcast(); 96 } 97 } 98 } 99 } 100 101 private interface IMultiMediaReceiver 102 { 103 void register(); 104 void unregister(); 105 } 106 107 private static class NewApi 108 implements IMultiMediaReceiver, AudioManager.OnAudioFocusChangeListener 109 { 110 private AudioManager audio_manager; 111 private ComponentName receiver_name; 112 private boolean running = false; 113 114 NewApi(Context c) 115 { 116 audio_manager = (AudioManager)c.getSystemService(Context.AUDIO_SERVICE); 117 receiver_name = new ComponentName(c, MediaReceiver.class); 118 } 119 120 public void register() 121 { 122 try { 123 audio_manager.registerMediaButtonEventReceiver(receiver_name); 124 audio_manager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); 125 running = true; 126 } catch (Exception e) { 127 // Nothing 128 e.printStackTrace(); 129 } 130 } 131 132 public void unregister() 133 { 134 try 135 { 136 audio_manager.unregisterMediaButtonEventReceiver(receiver_name); 137 audio_manager.abandonAudioFocus(this); 138 running = false; 139 } catch (Exception e) { 140 // Nothing 141 e.printStackTrace(); 142 } 143 } 144 145 public void onAudioFocusChange(int focusChange) 146 { 147 Logger.d("Audio focus" + ((focusChange>0)?"gained":"lost")+ 148 ": "+ focusChange); 149 if (running) 150 { /* Play nice and stop for the the other app */ 151 if (focusChange == AudioManager.AUDIOFOCUS_LOSS) 152 RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_STOP, false); 153 } 154 } 155 156 } 157 158 private static class OldApi implements IMultiMediaReceiver 159 { 160 private static final IntentFilter filter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON); 161 private MediaReceiver receiver; 162 private Context context; 163 OldApi(Context c) 164 { 165 filter.setPriority(1); /* 1 higher than the built-in media player */ 166 receiver = new MediaReceiver(); 167 context = c; 168 } 169 170 public void register() 171 { 172 context.registerReceiver(receiver, filter); 173 } 174 175 public void unregister() 176 { 177 context.unregisterReceiver(receiver); 178 } 179 180 } 181}