A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 211 lines 8.1 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2011 Antoine Cellerier <dionoea at videolan dot org> 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.widgets; 23 24import java.io.File; 25import org.rockbox.R; 26import org.rockbox.RockboxActivity; 27import org.rockbox.RockboxService; 28import android.app.PendingIntent; 29import android.appwidget.AppWidgetManager; 30import android.appwidget.AppWidgetProvider; 31import android.appwidget.AppWidgetProviderInfo; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.net.Uri; 36import android.view.KeyEvent; 37import android.view.View; 38import android.widget.RemoteViews; 39 40public class RockboxWidgetProvider extends AppWidgetProvider 41{ 42 static RockboxWidgetProvider mInstance; 43 public RockboxWidgetProvider() 44 { 45 super(); 46 mInstance = this; 47 } 48 49 @Override 50 public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) 51 { 52 final int N = appWidgetIds.length; 53 for (int i = 0; i < N; i++) 54 { 55 int appWidgetId = appWidgetIds[i]; 56 updateAppWidget(context, appWidgetManager, appWidgetId, null); 57 58 } 59 } 60 61 public static RockboxWidgetProvider getInstance() 62 { 63 /* no new instance here, instanced by android */ 64 return mInstance; 65 } 66 67 @Override 68 public void onDeleted(Context context, int[] appWidgetIds) 69 { 70 } 71 72 @Override 73 public void onEnabled(Context context) 74 { 75 } 76 77 @Override 78 public void onDisabled(Context context) 79 { 80 } 81 82 @Override 83 public void onReceive(Context context, Intent intent) 84 { 85 String action = intent.getAction(); 86 if (action.equals("org.rockbox.TrackUpdateInfo") || 87 action.equals("org.rockbox.TrackFinish") || 88 action.equals("org.rockbox.UpdateState")) 89 { 90 AppWidgetManager gm = AppWidgetManager.getInstance(context); 91 int[] appWidgetIds = gm.getAppWidgetIds(new ComponentName(context, this.getClass())); 92 final int N = appWidgetIds.length; 93 for (int i = 0; i < N; i++) 94 { 95 updateAppWidget(context, gm, appWidgetIds[i], intent); 96 } 97 } 98 else 99 { 100 super.onReceive(context, intent); 101 } 102 } 103 104 public void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Intent args) 105 { 106 AppWidgetProviderInfo provider = appWidgetManager.getAppWidgetInfo(appWidgetId); 107 RemoteViews views = null; 108 views = new RemoteViews(context.getPackageName(), provider.initialLayout); 109 110 Intent intent = new Intent(context, RockboxActivity.class); 111 PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); 112 views.setOnClickPendingIntent(R.id.infoDisplay, pendingIntent); 113 views.setOnClickPendingIntent(R.id.logo, pendingIntent); 114 115 RockboxWidgetConfigure.WidgetPref state = RockboxWidgetConfigure.loadWidgetPref(context, appWidgetId); 116 117 /* enable/disable PREV */ 118 if (state.enablePrev) 119 { 120 views.setOnClickPendingIntent(R.id.prev, 121 newPendingIntent(context, 122 KeyEvent.KEYCODE_MEDIA_PREVIOUS)); 123 } 124 else 125 views.setViewVisibility(R.id.prev, View.GONE); 126 127 /* enable/disable PLAY/PAUSE */ 128 if (state.enablePlayPause) 129 { 130 views.setOnClickPendingIntent(R.id.playPause, 131 newPendingIntent(context, 132 KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)); 133 } 134 else 135 views.setViewVisibility(R.id.playPause, View.GONE); 136 137 /* enable/disable NEXT */ 138 if (state.enableNext) 139 { 140 views.setOnClickPendingIntent(R.id.next, 141 newPendingIntent(context, 142 KeyEvent.KEYCODE_MEDIA_NEXT)); 143 } 144 else 145 views.setViewVisibility(R.id.next, View.GONE); 146 147 /* enable/disable STOP */ 148 if (state.enableStop) 149 { 150 views.setOnClickPendingIntent(R.id.stop, 151 newPendingIntent(context, 152 KeyEvent.KEYCODE_MEDIA_STOP)); 153 } 154 else 155 views.setViewVisibility(R.id.stop, View.GONE); 156 157 if (!state.enableAA) 158 views.setViewVisibility(R.id.logo, View.GONE); 159 160 if (args != null) 161 { 162 if (args.getAction().equals("org.rockbox.TrackUpdateInfo")) 163 { 164 CharSequence title = args.getCharSequenceExtra("title"); 165 CharSequence artist = args.getCharSequenceExtra("artist"); 166 CharSequence album = args.getCharSequenceExtra("album"); 167 views.setTextViewText(R.id.infoDisplay, title+"\n"+artist+"\n"+album); 168 CharSequence albumart = args.getCharSequenceExtra("albumart"); 169 /* Uri.fromFile() is buggy in <2.2 170 * http://stackoverflow.com/questions/3004713/get-content-uri-from-file-path-in-android */ 171 if (albumart != null) 172 views.setImageViewUri(R.id.logo, Uri.parse( 173 new File(albumart.toString()).toString())); 174 else 175 views.setImageViewResource(R.id.logo, R.drawable.rockbox); 176 } 177 else if (args.getAction().equals("org.rockbox.TrackFinish")) 178 { 179 // FIXME: looks like this event is always fired earlier than 180 // the actual track change (a few seconds) 181 views.setTextViewText(R.id.infoDisplay, context.getString(R.string.appwidget_infoDisplay)); 182 views.setImageViewResource(R.id.logo, R.drawable.rockbox); 183 } 184 else if (args.getAction().equals("org.rockbox.UpdateState")) 185 { 186 CharSequence playstate = args.getCharSequenceExtra("state"); 187 if (playstate.equals("play")) 188 views.setImageViewResource(R.id.playPause, R.drawable.appwidget_pause); 189 else /* pause or stop */ 190 views.setImageViewResource(R.id.playPause, R.drawable.appwidget_play); 191 } 192 } 193 194 appWidgetManager.updateAppWidget(appWidgetId, views); 195 } 196 197 public static PendingIntent newPendingIntent(Context context, int keycode) 198 { 199 /* Use keycode as request to code to prevent successive 200 * PendingIntents from overwritting one another. 201 * This seems hackish but at least it works. 202 * see: http://code.google.com/p/android/issues/detail?id=863 203 */ 204 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, Uri.EMPTY, 205 context, RockboxService.class); 206 intent.putExtra(Intent.EXTRA_KEY_EVENT, 207 new KeyEvent(KeyEvent.ACTION_UP, keycode)); 208 return PendingIntent.getService(context, keycode, intent, 0); 209 } 210} 211