Index: android/AndroidManifest.xml =================================================================== --- android/AndroidManifest.xml (revision 29051) +++ android/AndroidManifest.xml (working copy) @@ -29,6 +29,16 @@ + + + + + + + + + Index: android/src/org/rockbox/Helper/RunForegroundManager.java =================================================================== --- android/src/org/rockbox/Helper/RunForegroundManager.java (revision 29051) +++ android/src/org/rockbox/Helper/RunForegroundManager.java (working copy) @@ -5,12 +5,14 @@ import org.rockbox.R; import org.rockbox.RockboxActivity; +import org.rockbox.RockboxWidgetProvider; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; +import android.net.Uri; import android.util.Log; import android.widget.RemoteViews; @@ -82,15 +84,31 @@ api.stopForeground(); } - public void updateNotification(String title, String content, String ticker) + public void updateNotification(String title, String artist, String album) { RemoteViews views = mNotification.contentView; views.setTextViewText(R.id.title, title); - views.setTextViewText(R.id.content, content); - mNotification.tickerText = ticker; + views.setTextViewText(R.id.content, artist+"\n"+album); + if (artist.equals("")) + mNotification.tickerText = title; + else + mNotification.tickerText = title+" - "+artist; mNM.notify(R.string.notification, mNotification); + + Intent widgetUpdate = new Intent("org.rockbox.TrackUpdateInfo", Uri.EMPTY, mCurrentService, RockboxWidgetProvider.class); + widgetUpdate.putExtra("title", title); + widgetUpdate.putExtra("artist", artist); + widgetUpdate.putExtra("album", album); + mCurrentService.sendBroadcast(widgetUpdate); } + public void finishNotification() + { + Log.d("Rockbox", "TrackFinish"); + Intent widgetUpdate = new Intent("org.rockbox.TrackFinish", Uri.EMPTY, mCurrentService, RockboxWidgetProvider.class); + mCurrentService.sendBroadcast(widgetUpdate); + } + private interface IRunForeground { void startForeground(); Index: android/src/org/rockbox/RockboxWidgetProvider.java =================================================================== --- android/src/org/rockbox/RockboxWidgetProvider.java (revision 0) +++ android/src/org/rockbox/RockboxWidgetProvider.java (revision 0) @@ -0,0 +1,134 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Antoine Cellerier + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +package org.rockbox; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.util.Log; +import android.view.View; +import android.view.KeyEvent; +import android.widget.RemoteViews; + +import java.util.ArrayList; + +public class RockboxWidgetProvider extends AppWidgetProvider +{ + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) + { + final int N = appWidgetIds.length; + for (int i = 0; i < N; i++) + { + int appWidgetId = appWidgetIds[i]; + updateAppWidget(context, appWidgetManager, appWidgetId, null); + + } + } + + @Override + public void onDeleted(Context context, int[] appWidgetIds) + { + } + + @Override + public void onEnabled(Context context) + { + } + + @Override + public void onDisabled(Context context) + { + } + + @Override + public void onReceive(Context context, Intent intent) + { + String action = intent.getAction(); + if (intent.getAction().equals("org.rockbox.TrackUpdateInfo") || + intent.getAction().equals("org.rockbox.TrackFinish") || + intent.getAction().equals("org.rockbox.UpdateState")) + { + AppWidgetManager gm = AppWidgetManager.getInstance(context); + int[] appWidgetIds = gm.getAppWidgetIds(new ComponentName(context, RockboxWidgetProvider.class)); + final int N = appWidgetIds.length; + for (int i = 0; i < N; i++) + { + updateAppWidget(context, gm, appWidgetIds[i], intent); + } + } + else + { + super.onReceive(context, intent); + } + } + + public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Intent args) + { + RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget); + + Intent intent = new Intent(context, RockboxActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.infoDisplay, pendingIntent); + + intent = new Intent("org.rockbox.PlayPause", Uri.EMPTY, context, RockboxService.class); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.playPause, pendingIntent); + + intent = new Intent("org.rockbox.Next", Uri.EMPTY, context, RockboxService.class); + pendingIntent = PendingIntent.getService(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.next, pendingIntent); + + if (args != null) + { + if (args.getAction().equals("org.rockbox.TrackUpdateInfo")) + { + CharSequence title = args.getCharSequenceExtra("title"); + CharSequence artist = args.getCharSequenceExtra("artist"); + CharSequence album = args.getCharSequenceExtra("album"); + views.setTextViewText(R.id.infoDisplay, title+"\n"+artist+"\n"+album); + } + else if (args.getAction().equals("org.rockbox.TrackFinish")) + { + // FIXME: looks like this event is always fired earlier than + // the actual track change (a few seconds) + views.setTextViewText(R.id.infoDisplay, context.getString(R.string.appwidget_infoDisplay)); + } + else if (args.getAction().equals("org.rockbox.UpdateState")) + { + CharSequence state = args.getCharSequenceExtra("state"); + if (state.equals("play")) + views.setImageViewResource(R.id.playPause, R.drawable.appwidget_pause); + else /* pause or stop */ + views.setImageViewResource(R.id.playPause, R.drawable.appwidget_play); + } + } + + appWidgetManager.updateAppWidget(appWidgetId, views); + } +} + Index: android/src/org/rockbox/RockboxPCM.java =================================================================== --- android/src/org/rockbox/RockboxPCM.java (revision 29051) +++ android/src/org/rockbox/RockboxPCM.java (working copy) @@ -23,9 +23,11 @@ import java.util.Arrays; +import android.content.Intent; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; +import android.net.Uri; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; @@ -80,10 +82,16 @@ private void play_pause(boolean pause) { if (pause) { + Intent widgetUpdate = new Intent("org.rockbox.UpdateState", Uri.EMPTY, RockboxService.get_instance(), RockboxWidgetProvider.class); + widgetUpdate.putExtra("state", "pause"); + RockboxService.get_instance().sendBroadcast(widgetUpdate); pause(); } else { + Intent widgetUpdate = new Intent("org.rockbox.UpdateState", Uri.EMPTY, RockboxService.get_instance(), RockboxWidgetProvider.class); + widgetUpdate.putExtra("state", "play"); + RockboxService.get_instance().sendBroadcast(widgetUpdate); if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED) { RockboxService.get_instance().startForeground(); @@ -114,6 +122,9 @@ throw new IllegalStateException(e); } RockboxService.get_instance().stopForeground(); + Intent widgetUpdate = new Intent("org.rockbox.UpdateState", Uri.EMPTY, RockboxService.get_instance(), RockboxWidgetProvider.class); + widgetUpdate.putExtra("state", "stop"); + RockboxService.get_instance().sendBroadcast(widgetUpdate); } @SuppressWarnings("unused") Index: android/src/org/rockbox/RockboxService.java =================================================================== --- android/src/org/rockbox/RockboxService.java (revision 29051) +++ android/src/org/rockbox/RockboxService.java (working copy) @@ -43,6 +43,7 @@ import android.os.IBinder; import android.os.ResultReceiver; import android.util.Log; +import android.view.KeyEvent; /* This class is used as the main glue between java and c. * All access should be done through RockboxService.get_instance() for safety. @@ -76,7 +77,7 @@ @Override public void onCreate() { - instance = this; + instance = this; } public static RockboxService get_instance() @@ -115,6 +116,21 @@ if (!rbLibLoaded) startservice(); + if (intent != null && intent.getAction() != null) + { + Log.d("RockboxService", intent.getAction()); + if (intent.getAction().equals("org.rockbox.PlayPause")) + { + if (fb != null) + fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null); + } + else if (intent.getAction().equals("org.rockbox.Next")) + { + if (fb != null) + fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_NEXT, null); + } + } + /* Display a notification about us starting. * We put an icon in the status bar. */ if (fg_runner == null) Index: android/res/values/style.xml =================================================================== --- android/res/values/style.xml (revision 0) +++ android/res/values/style.xml (revision 0) @@ -0,0 +1,16 @@ + + + + + + + Index: android/res/values/strings.xml =================================================================== --- android/res/values/strings.xml (revision 29051) +++ android/res/values/strings.xml (working copy) @@ -10,4 +10,5 @@ No Error occured during extraction! Rockbox is loading. Please wait... - \ No newline at end of file +Rockbox\nTouch to launch app + Index: android/res/xml/appwidget_provider.xml =================================================================== --- android/res/xml/appwidget_provider.xml (revision 0) +++ android/res/xml/appwidget_provider.xml (revision 0) @@ -0,0 +1,7 @@ + + + Index: android/res/drawable/appwidget_pause.xml =================================================================== --- android/res/drawable/appwidget_pause.xml (revision 0) +++ android/res/drawable/appwidget_pause.xml (revision 0) @@ -0,0 +1,6 @@ + + + + + + Index: android/res/drawable/appwidget_next.xml =================================================================== --- android/res/drawable/appwidget_next.xml (revision 0) +++ android/res/drawable/appwidget_next.xml (revision 0) @@ -0,0 +1,6 @@ + + + + + + Index: android/res/drawable/appwidget_background.xml =================================================================== --- android/res/drawable/appwidget_background.xml (revision 0) +++ android/res/drawable/appwidget_background.xml (revision 0) @@ -0,0 +1,6 @@ + + + + + + Index: android/res/drawable/appwidget_infodisplay_background.xml =================================================================== --- android/res/drawable/appwidget_infodisplay_background.xml (revision 0) +++ android/res/drawable/appwidget_infodisplay_background.xml (revision 0) @@ -0,0 +1,8 @@ + + + + + + + + Index: android/res/drawable/appwidget_stop_normal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_stop_normal.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_background_normal.9.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_background_normal.9.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_ff_normal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_ff_normal.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_rew_normal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_rew_normal.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/source/appwidget_background.svg =================================================================== --- android/res/drawable/source/appwidget_background.svg (revision 0) +++ android/res/drawable/source/appwidget_background.svg (revision 0) @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + Index: android/res/drawable/appwidget_selection_clicked.9.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_selection_clicked.9.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_play_normal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_play_normal.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_selection_transparent.9.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_selection_transparent.9.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_play.xml =================================================================== --- android/res/drawable/appwidget_play.xml (revision 0) +++ android/res/drawable/appwidget_play.xml (revision 0) @@ -0,0 +1,6 @@ + + + + + + Index: android/res/drawable/appwidget_pause_normal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_pause_normal.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/drawable/appwidget_selection_over.9.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: android/res/drawable/appwidget_selection_over.9.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: android/res/layout/appwidget.xml =================================================================== --- android/res/layout/appwidget.xml (revision 0) +++ android/res/layout/appwidget.xml (revision 0) @@ -0,0 +1,23 @@ + + + + + +