diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index 0eab90ff81..41a662fdfa 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -29,6 +29,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/android.make b/android/android.make
index 82a8dedf24..53d5d46bbf 100644
--- a/android/android.make
+++ b/android/android.make
@@ -40,6 +40,7 @@ R_OBJ := $(BUILDDIR)/bin/$(PACKAGE_PATH)/R.class
JAVA_SRC := $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/Helper/*.java)
JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/*.java)
+JAVA_SRC += $(wildcard $(ANDROID_DIR)/src/$(PACKAGE_PATH)/widgets/*.java)
JAVA_OBJ := $(call java2class,$(subst $(ANDROID)/src/$(PACKAGE_PATH),$(ANDROID)/bin/$(PACKAGE_PATH),$(JAVA_SRC)))
diff --git a/android/res/drawable/appwidget_background.xml b/android/res/drawable/appwidget_background.xml
new file mode 100644
index 0000000000..a9a23495a9
--- /dev/null
+++ b/android/res/drawable/appwidget_background.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_background_normal.9.png b/android/res/drawable/appwidget_background_normal.9.png
new file mode 100644
index 0000000000..c06f285be3
Binary files /dev/null and b/android/res/drawable/appwidget_background_normal.9.png differ
diff --git a/android/res/drawable/appwidget_ff_normal.png b/android/res/drawable/appwidget_ff_normal.png
new file mode 100644
index 0000000000..82a90dd6aa
Binary files /dev/null and b/android/res/drawable/appwidget_ff_normal.png differ
diff --git a/android/res/drawable/appwidget_infodisplay_background.xml b/android/res/drawable/appwidget_infodisplay_background.xml
new file mode 100644
index 0000000000..e6ed34c994
--- /dev/null
+++ b/android/res/drawable/appwidget_infodisplay_background.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_next.xml b/android/res/drawable/appwidget_next.xml
new file mode 100644
index 0000000000..34d6a6952b
--- /dev/null
+++ b/android/res/drawable/appwidget_next.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_pause.xml b/android/res/drawable/appwidget_pause.xml
new file mode 100644
index 0000000000..72df5a857a
--- /dev/null
+++ b/android/res/drawable/appwidget_pause.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_pause_normal.png b/android/res/drawable/appwidget_pause_normal.png
new file mode 100644
index 0000000000..835c5e7e5e
Binary files /dev/null and b/android/res/drawable/appwidget_pause_normal.png differ
diff --git a/android/res/drawable/appwidget_play.xml b/android/res/drawable/appwidget_play.xml
new file mode 100644
index 0000000000..5fa0f5beac
--- /dev/null
+++ b/android/res/drawable/appwidget_play.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_play_normal.png b/android/res/drawable/appwidget_play_normal.png
new file mode 100644
index 0000000000..73d48c94db
Binary files /dev/null and b/android/res/drawable/appwidget_play_normal.png differ
diff --git a/android/res/drawable/appwidget_prev.xml b/android/res/drawable/appwidget_prev.xml
new file mode 100644
index 0000000000..df56f77f05
--- /dev/null
+++ b/android/res/drawable/appwidget_prev.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_rew_normal.png b/android/res/drawable/appwidget_rew_normal.png
new file mode 100644
index 0000000000..b5e18a7362
Binary files /dev/null and b/android/res/drawable/appwidget_rew_normal.png differ
diff --git a/android/res/drawable/appwidget_selection_clicked.9.png b/android/res/drawable/appwidget_selection_clicked.9.png
new file mode 100644
index 0000000000..7d39e88396
Binary files /dev/null and b/android/res/drawable/appwidget_selection_clicked.9.png differ
diff --git a/android/res/drawable/appwidget_selection_over.9.png b/android/res/drawable/appwidget_selection_over.9.png
new file mode 100644
index 0000000000..da96c6a831
Binary files /dev/null and b/android/res/drawable/appwidget_selection_over.9.png differ
diff --git a/android/res/drawable/appwidget_selection_transparent.9.png b/android/res/drawable/appwidget_selection_transparent.9.png
new file mode 100644
index 0000000000..535eb0b561
Binary files /dev/null and b/android/res/drawable/appwidget_selection_transparent.9.png differ
diff --git a/android/res/drawable/appwidget_stop.xml b/android/res/drawable/appwidget_stop.xml
new file mode 100644
index 0000000000..895c8b622d
--- /dev/null
+++ b/android/res/drawable/appwidget_stop.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/res/drawable/appwidget_stop_normal.png b/android/res/drawable/appwidget_stop_normal.png
new file mode 100644
index 0000000000..56932254da
Binary files /dev/null and b/android/res/drawable/appwidget_stop_normal.png differ
diff --git a/android/res/drawable/rockbox.png b/android/res/drawable/rockbox.png
new file mode 100644
index 0000000000..84d940abe9
Binary files /dev/null and b/android/res/drawable/rockbox.png differ
diff --git a/android/res/drawable/source/appwidget_background.svg b/android/res/drawable/source/appwidget_background.svg
new file mode 100644
index 0000000000..1404bde947
Binary files /dev/null and b/android/res/drawable/source/appwidget_background.svg differ
diff --git a/android/res/layout/appwidget_2x2.xml b/android/res/layout/appwidget_2x2.xml
new file mode 100644
index 0000000000..a29f416b3d
--- /dev/null
+++ b/android/res/layout/appwidget_2x2.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/res/layout/appwidget_4x1.xml b/android/res/layout/appwidget_4x1.xml
new file mode 100644
index 0000000000..0d2d6df010
--- /dev/null
+++ b/android/res/layout/appwidget_4x1.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/res/layout/appwidget_configure.xml b/android/res/layout/appwidget_configure.xml
new file mode 100644
index 0000000000..8dd0ff2144
--- /dev/null
+++ b/android/res/layout/appwidget_configure.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
index 8034eab086..5ff2a6dc20 100644
--- a/android/res/values/strings.xml
+++ b/android/res/values/strings.xml
@@ -10,4 +10,18 @@
No
Error occured during extraction!
Rockbox is loading. Please wait...
-
\ No newline at end of file
+
+
+Rockbox (line)
+Rockbox (square)
+Touch to launch app
+
+
+Please chose elements to display in widget.
+Prev Button
+Stop Button
+Play/Pause Button
+Next Button
+Create Widget
+
+
diff --git a/android/res/values/style.xml b/android/res/values/style.xml
new file mode 100644
index 0000000000..201b478d19
--- /dev/null
+++ b/android/res/values/style.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/android/res/xml/appwidget_provider_2x2.xml b/android/res/xml/appwidget_provider_2x2.xml
new file mode 100644
index 0000000000..981b4f1b3d
--- /dev/null
+++ b/android/res/xml/appwidget_provider_2x2.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/android/res/xml/appwidget_provider_4x1.xml b/android/res/xml/appwidget_provider_4x1.xml
new file mode 100644
index 0000000000..9a29901f5e
--- /dev/null
+++ b/android/res/xml/appwidget_provider_4x1.xml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/android/src/org/rockbox/Helper/RunForegroundManager.java b/android/src/org/rockbox/Helper/RunForegroundManager.java
index 6c5f2deb14..99ac66b686 100644
--- a/android/src/org/rockbox/Helper/RunForegroundManager.java
+++ b/android/src/org/rockbox/Helper/RunForegroundManager.java
@@ -11,6 +11,7 @@ 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;
@@ -92,6 +93,19 @@ public class RunForegroundManager
else
mNotification.tickerText = title+" - "+artist;
mNM.notify(R.string.notification, mNotification);
+
+ Intent widgetUpdate = new Intent("org.rockbox.TrackUpdateInfo");
+ 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");
+ mCurrentService.sendBroadcast(widgetUpdate);
}
private interface IRunForeground
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
index 18415562f3..05d2b11184 100644
--- a/android/src/org/rockbox/RockboxFramebuffer.java
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -147,5 +147,5 @@ public class RockboxFramebuffer extends View
private native void post_update_done();
private native void set_lcd_active(int active);
private native void touchHandler(boolean down, int x, int y);
- private native boolean buttonHandler(int keycode, boolean state);
+ private native static boolean buttonHandler(int keycode, boolean state);
}
diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java
index 146e639a08..c1fecbcc15 100644
--- a/android/src/org/rockbox/RockboxPCM.java
+++ b/android/src/org/rockbox/RockboxPCM.java
@@ -23,9 +23,11 @@ package org.rockbox;
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 @@ public class RockboxPCM extends AudioTrack
private void play_pause(boolean pause) {
if (pause)
{
+ Intent widgetUpdate = new Intent("org.rockbox.UpdateState");
+ widgetUpdate.putExtra("state", "pause");
+ RockboxService.get_instance().sendBroadcast(widgetUpdate);
pause();
}
else
{
+ Intent widgetUpdate = new Intent("org.rockbox.UpdateState");
+ widgetUpdate.putExtra("state", "play");
+ RockboxService.get_instance().sendBroadcast(widgetUpdate);
if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
{
RockboxService.get_instance().startForeground();
@@ -114,6 +122,9 @@ public class RockboxPCM extends AudioTrack
throw new IllegalStateException(e);
}
RockboxService.get_instance().stopForeground();
+ Intent widgetUpdate = new Intent("org.rockbox.UpdateState");
+ widgetUpdate.putExtra("state", "stop");
+ RockboxService.get_instance().sendBroadcast(widgetUpdate);
}
@SuppressWarnings("unused")
diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java
index 23086eae29..de90999783 100644
--- a/android/src/org/rockbox/RockboxService.java
+++ b/android/src/org/rockbox/RockboxService.java
@@ -43,6 +43,7 @@ import android.os.Bundle;
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 @@ public class RockboxService extends Service
@Override
public void onCreate()
{
- instance = this;
+ instance = this;
}
public static RockboxService get_instance()
@@ -115,6 +116,31 @@ public class RockboxService extends Service
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.Prev"))
+ {
+ if (fb != null)
+ fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_PREVIOUS, null);
+ }
+ else if (intent.getAction().equals("org.rockbox.Next"))
+ {
+ if (fb != null)
+ fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_NEXT, null);
+ }
+ else if (intent.getAction().equals("org.rockbox.Stop"))
+ {
+ if (fb != null)
+ fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_STOP, null);
+ }
+ }
+
/* Display a notification about us starting.
* We put an icon in the status bar. */
if (fg_runner == null)
diff --git a/android/src/org/rockbox/widgets/RockboxWidgetConfigure.java b/android/src/org/rockbox/widgets/RockboxWidgetConfigure.java
new file mode 100644
index 0000000000..82adb97126
--- /dev/null
+++ b/android/src/org/rockbox/widgets/RockboxWidgetConfigure.java
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.widgets;
+
+import org.rockbox.R;
+
+import android.app.Activity;
+import android.appwidget.AppWidgetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+
+
+public class RockboxWidgetConfigure extends Activity
+{
+ int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
+
+ public RockboxWidgetConfigure()
+ {
+ super();
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ setResult(RESULT_CANCELED);
+ setContentView(R.layout.appwidget_configure);
+
+ ((CheckBox)findViewById(R.id.enable_prev)).setChecked(false);
+ ((CheckBox)findViewById(R.id.enable_stop)).setChecked(true);
+ ((CheckBox)findViewById(R.id.enable_playpause)).setChecked(true);
+ ((CheckBox)findViewById(R.id.enable_next)).setChecked(false);
+
+ findViewById(R.id.confirm).setOnClickListener(mCreateWidget);
+
+ Intent intent = getIntent();
+ Bundle extras = intent.getExtras();
+ if (extras != null)
+ mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
+
+ if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID)
+ finish();
+ }
+
+ View.OnClickListener mCreateWidget = new View.OnClickListener()
+ {
+ public void onClick(View v)
+ {
+ final Context context = RockboxWidgetConfigure.this;
+
+ WidgetPref state = new WidgetPref();
+ state.enablePrev = ((CheckBox)findViewById(R.id.enable_prev)).isChecked();
+ state.enableStop = ((CheckBox)findViewById(R.id.enable_stop)).isChecked();
+ state.enablePlayPause = ((CheckBox)findViewById(R.id.enable_playpause)).isChecked();
+ state.enableNext = ((CheckBox)findViewById(R.id.enable_next)).isChecked();
+ saveWidgetPref(context, mAppWidgetId, state);
+
+ AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
+ RockboxWidgetProvider.updateAppWidget(context, appWidgetManager, mAppWidgetId, null);
+
+ Intent result = new Intent();
+ result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
+ setResult(RESULT_OK, result);
+ finish();
+ }
+ };
+
+ static public class WidgetPref
+ {
+ public boolean enablePrev = true;
+ public boolean enableStop = true;
+ public boolean enablePlayPause = true;
+ public boolean enableNext = true;
+ }
+
+ static void saveWidgetPref(Context context, int appWidgetId, WidgetPref state)
+ {
+ SharedPreferences.Editor prefs = context.getSharedPreferences("org.rockbox.RockboxWidgetConfigure", 0).edit();
+ prefs.putBoolean("prev"+appWidgetId, state.enablePrev);
+ prefs.putBoolean("stop"+appWidgetId, state.enableStop);
+ prefs.putBoolean("playpause"+appWidgetId, state.enablePlayPause);
+ prefs.putBoolean("next"+appWidgetId, state.enableNext);
+ prefs.commit();
+ }
+
+ static WidgetPref loadWidgetPref(Context context, int appWidgetId)
+ {
+ SharedPreferences prefs = context.getSharedPreferences("org.rockbox.RockboxWidgetConfigure", 0);
+ WidgetPref state = new WidgetPref();
+ state.enablePrev = prefs.getBoolean("prev"+appWidgetId, true);
+ state.enableStop = prefs.getBoolean("stop"+appWidgetId, true);
+ state.enablePlayPause = prefs.getBoolean("playpause"+appWidgetId, true);
+ state.enableNext = prefs.getBoolean("next"+appWidgetId, true);
+ return state;
+ }
+}
diff --git a/android/src/org/rockbox/widgets/RockboxWidgetProvider.java b/android/src/org/rockbox/widgets/RockboxWidgetProvider.java
new file mode 100644
index 0000000000..756d9f9a13
--- /dev/null
+++ b/android/src/org/rockbox/widgets/RockboxWidgetProvider.java
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.widgets;
+
+import org.rockbox.R;
+import org.rockbox.RockboxActivity;
+import org.rockbox.RockboxService;
+
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.appwidget.AppWidgetProviderInfo;
+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, this.getClass()));
+ 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)
+ {
+ AppWidgetProviderInfo provider = appWidgetManager.getAppWidgetInfo(appWidgetId);
+ RemoteViews views = null;
+ views = new RemoteViews(context.getPackageName(), provider.initialLayout);
+
+ Intent intent = new Intent(context, RockboxActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
+ views.setOnClickPendingIntent(R.id.infoDisplay, pendingIntent);
+
+ RockboxWidgetConfigure.WidgetPref state = RockboxWidgetConfigure.loadWidgetPref(context, appWidgetId);
+
+ if (state.enablePrev)
+ {
+ intent = new Intent("org.rockbox.Prev", Uri.EMPTY, context, RockboxService.class);
+ pendingIntent = PendingIntent.getService(context, 0, intent, 0);
+ views.setOnClickPendingIntent(R.id.prev, pendingIntent);
+ }
+ else
+ views.setViewVisibility(R.id.prev, View.GONE);
+
+ if (state.enablePlayPause)
+ {
+ intent = new Intent("org.rockbox.PlayPause", Uri.EMPTY, context, RockboxService.class);
+ pendingIntent = PendingIntent.getService(context, 0, intent, 0);
+ views.setOnClickPendingIntent(R.id.playPause, pendingIntent);
+ }
+ else
+ views.setViewVisibility(R.id.playPause, View.GONE);
+
+ if (state.enableNext)
+ {
+ intent = new Intent("org.rockbox.Next", Uri.EMPTY, context, RockboxService.class);
+ pendingIntent = PendingIntent.getService(context, 0, intent, 0);
+ views.setOnClickPendingIntent(R.id.next, pendingIntent);
+ }
+ else
+ views.setViewVisibility(R.id.next, View.GONE);
+
+ if (state.enableStop)
+ {
+ intent = new Intent("org.rockbox.Stop", Uri.EMPTY, context, RockboxService.class);
+ pendingIntent = PendingIntent.getService(context, 0, intent, 0);
+ views.setOnClickPendingIntent(R.id.stop, pendingIntent);
+ }
+ else
+ views.setViewVisibility(R.id.stop, View.GONE);
+
+ 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 playstate = args.getCharSequenceExtra("state");
+ if (playstate.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);
+ }
+}
+
diff --git a/android/src/org/rockbox/widgets/RockboxWidgetProvider2x2.java b/android/src/org/rockbox/widgets/RockboxWidgetProvider2x2.java
new file mode 100644
index 0000000000..183c4273ec
--- /dev/null
+++ b/android/src/org/rockbox/widgets/RockboxWidgetProvider2x2.java
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.widgets;
+
+public class RockboxWidgetProvider2x2 extends RockboxWidgetProvider
+{
+}
+
diff --git a/android/src/org/rockbox/widgets/RockboxWidgetProvider4x1.java b/android/src/org/rockbox/widgets/RockboxWidgetProvider4x1.java
new file mode 100644
index 0000000000..303c54c92b
--- /dev/null
+++ b/android/src/org/rockbox/widgets/RockboxWidgetProvider4x1.java
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.widgets;
+
+public class RockboxWidgetProvider4x1 extends RockboxWidgetProvider
+{
+}
+
diff --git a/apps/hosted/notification.c b/apps/hosted/notification.c
index 3c623aad1d..fa8c286808 100644
--- a/apps/hosted/notification.c
+++ b/apps/hosted/notification.c
@@ -30,7 +30,7 @@ extern JNIEnv *env_ptr;
extern jclass RockboxService_class;
extern jobject RockboxService_instance;
-static jmethodID updateNotification;
+static jmethodID updateNotification, finishNotification;
static jobject NotificationManager_instance;
static jstring title, artist, album;
@@ -66,6 +66,16 @@ static void track_changed_callback(void *param)
}
}
+/*
+ * notify about track finishing */
+static void track_finished_callback(void *param)
+{
+ (void)param;
+ JNIEnv e = *env_ptr;
+ e->CallVoidMethod(env_ptr, NotificationManager_instance,
+ finishNotification);
+}
+
void notification_init(void)
{
JNIEnv e = *env_ptr;
@@ -79,6 +89,9 @@ void notification_init(void)
"(Ljava/lang/String;"
"Ljava/lang/String;"
"Ljava/lang/String;)V");
+ finishNotification = e->GetMethodID(env_ptr, class, "finishNotification",
+ "()V");
add_event(PLAYBACK_EVENT_TRACK_CHANGE, false, track_changed_callback);
+ add_event(PLAYBACK_EVENT_TRACK_FINISH, false, track_finished_callback);
}
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c
index 9bfc7a370a..832eef54f3 100644
--- a/firmware/target/hosted/android/button-android.c
+++ b/firmware/target/hosted/android/button-android.c
@@ -61,7 +61,7 @@ Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this,
* this writes in an interrupt-like fashion the button events that the user
* generated by pressing/releasing them to a variable */
JNIEXPORT bool JNICALL
-Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jobject this,
+Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jclass this,
jint keycode, jboolean state)
{
(void)env;