diff options
author | Antoine Cellerier <dionoea@videolan.org> | 2011-01-29 20:47:32 +0000 |
---|---|---|
committer | Antoine Cellerier <dionoea@videolan.org> | 2011-01-29 20:47:32 +0000 |
commit | c0c769c5a86c56c2ab2c9e88515a64da98575182 (patch) | |
tree | 24e84b2d146bf3da39d93983d5656061e3c88ecb /android | |
parent | e9749d1b93f23b3bc36305ad1d39ca5e5c0cb3a8 (diff) |
Add widgets to android port.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29170 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'android')
35 files changed, 756 insertions, 3 deletions
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 @@ </intent-filter> </receiver> + <!-- Widgets --> + <receiver android:name=".widgets.RockboxWidgetProvider4x1" + android:label="@string/appwidget_label_4x1"> + <intent-filter> + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> + <action android:name="org.rockbox.TrackUpdateInfo" /> + <action android:name="org.rockbox.TrackFinish" /> + <action android:name="org.rockbox.UpdateState" /> + </intent-filter> + <meta-data android:name="android.appwidget.provider" + android:resource="@xml/appwidget_provider_4x1" /> + </receiver> + + <receiver android:name=".widgets.RockboxWidgetProvider2x2" + android:label="@string/appwidget_label_2x2"> + <intent-filter> + <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> + <action android:name="org.rockbox.TrackUpdateInfo" /> + <action android:name="org.rockbox.TrackFinish" /> + <action android:name="org.rockbox.UpdateState" /> + </intent-filter> + <meta-data android:name="android.appwidget.provider" + android:resource="@xml/appwidget_provider_2x2" /> + </receiver> + + <!-- Widget configuration --> + <activity android:name=".widgets.RockboxWidgetConfigure"> + <intent-filter> + <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" /> + </intent-filter> + </activity> </application> 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/appwidget_background_normal" /> +</selector> + diff --git a/android/res/drawable/appwidget_background_normal.9.png b/android/res/drawable/appwidget_background_normal.9.png Binary files differnew file mode 100644 index 0000000000..c06f285be3 --- /dev/null +++ b/android/res/drawable/appwidget_background_normal.9.png diff --git a/android/res/drawable/appwidget_ff_normal.png b/android/res/drawable/appwidget_ff_normal.png Binary files differnew file mode 100644 index 0000000000..82a90dd6aa --- /dev/null +++ b/android/res/drawable/appwidget_ff_normal.png 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_pressed="true" android:drawable="@drawable/appwidget_selection_clicked" /> + <item android:state_focused="true" android:drawable="@drawable/appwidget_selection_over" /> + <item android:drawable="@drawable/appwidget_selection_transparent" /> +</selector> + 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/appwidget_ff_normal" /> +</selector> + 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/appwidget_pause_normal" /> +</selector> + diff --git a/android/res/drawable/appwidget_pause_normal.png b/android/res/drawable/appwidget_pause_normal.png Binary files differnew file mode 100644 index 0000000000..835c5e7e5e --- /dev/null +++ b/android/res/drawable/appwidget_pause_normal.png 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/appwidget_play_normal" /> +</selector> + diff --git a/android/res/drawable/appwidget_play_normal.png b/android/res/drawable/appwidget_play_normal.png Binary files differnew file mode 100644 index 0000000000..73d48c94db --- /dev/null +++ b/android/res/drawable/appwidget_play_normal.png 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/appwidget_rew_normal" /> +</selector> + diff --git a/android/res/drawable/appwidget_rew_normal.png b/android/res/drawable/appwidget_rew_normal.png Binary files differnew file mode 100644 index 0000000000..b5e18a7362 --- /dev/null +++ b/android/res/drawable/appwidget_rew_normal.png diff --git a/android/res/drawable/appwidget_selection_clicked.9.png b/android/res/drawable/appwidget_selection_clicked.9.png Binary files differnew file mode 100644 index 0000000000..7d39e88396 --- /dev/null +++ b/android/res/drawable/appwidget_selection_clicked.9.png diff --git a/android/res/drawable/appwidget_selection_over.9.png b/android/res/drawable/appwidget_selection_over.9.png Binary files differnew file mode 100644 index 0000000000..da96c6a831 --- /dev/null +++ b/android/res/drawable/appwidget_selection_over.9.png diff --git a/android/res/drawable/appwidget_selection_transparent.9.png b/android/res/drawable/appwidget_selection_transparent.9.png Binary files differnew file mode 100644 index 0000000000..535eb0b561 --- /dev/null +++ b/android/res/drawable/appwidget_selection_transparent.9.png 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:drawable="@drawable/appwidget_stop_normal" /> +</selector> + diff --git a/android/res/drawable/appwidget_stop_normal.png b/android/res/drawable/appwidget_stop_normal.png Binary files differnew file mode 100644 index 0000000000..56932254da --- /dev/null +++ b/android/res/drawable/appwidget_stop_normal.png diff --git a/android/res/drawable/rockbox.png b/android/res/drawable/rockbox.png Binary files differnew file mode 100644 index 0000000000..84d940abe9 --- /dev/null +++ b/android/res/drawable/rockbox.png 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 --- /dev/null +++ b/android/res/drawable/source/appwidget_background.svg @@ -0,0 +1,119 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="46" + height="116" + id="svg2" + version="1.1" + inkscape:version="0.47 r22583" + sodipodi:docname="appwidget_background.svg" + inkscape:export-filename="/home/antoine/rockbox/rockbox-svn/android/res/drawable/appwidget_background_normal.9.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs4"> + <linearGradient + id="linearGradient3594"> + <stop + style="stop-color:#000000;stop-opacity:1;" + offset="0" + id="stop3596" /> + <stop + style="stop-color:#545454;stop-opacity:1;" + offset="1" + id="stop3598" /> + </linearGradient> + <inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 526.18109 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="744.09448 : 526.18109 : 1" + inkscape:persp3d-origin="372.04724 : 350.78739 : 1" + id="perspective10" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3594" + id="linearGradient3600" + x1="149.28572" + y1="442.29074" + x2="149.28572" + y2="345.29074" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(-1.940295e-8,-15)" /> + <inkscape:perspective + id="perspective3612" + inkscape:persp3d-origin="0.5 : 0.33333333 : 1" + inkscape:vp_z="1 : 0.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 0.5 : 1" + sodipodi:type="inkscape:persp3d" /> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#bd0000" + borderopacity="0.75686275" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="14.651253" + inkscape:cx="0.54030499" + inkscape:cy="14.631532" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1280" + inkscape:window-height="725" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:window-maximized="1" + inkscape:snap-page="false" + inkscape:snap-grids="true" + inkscape:snap-to-guides="false" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-133.78572,-328.29074)"> + <rect + style="fill:url(#linearGradient3600);fill-opacity:1;fill-rule:evenodd;stroke:#8d8d8d;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="rect2816" + width="25" + height="99" + x="144.28572" + y="334.79074" + ry="4.8042979" + rx="4.3476572" /> + <path + style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 150.28573,328.79074 13.00097,0" + id="path3602" + clip-path="none" /> + <path + style="fill:none;stroke:#000000;stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + d="m 134.28572,340.75091 0,87.06367" + id="path3602-1" /> + </g> +</svg> 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:gravity="center" + android:background="@drawable/appwidget_background"> + <!-- style="@style/appwidget_background"--> + + <ImageView android:id="@+id/logo" + android:layout_width="fill_parent" + android:layout_height="40dp" + android:scaleType="centerInside" + android:src="@drawable/rockbox" /> + <Button android:id="@+id/infoDisplay" + style="@style/appwidget_infodisplay" + android:layout_width="fill_parent" + android:text="@string/appwidget_infoDisplay" /> + <LinearLayout android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_weight="0" + android:gravity="center" + android:orientation="horizontal"> + <ImageButton android:id="@+id/prev" + style="@style/appwidget_button" + android:layout_weight="1" + android:src="@drawable/appwidget_prev" /> + <ImageButton android:id="@+id/stop" + style="@style/appwidget_button" + android:layout_weight="1" + android:src="@drawable/appwidget_stop" /> + <ImageButton android:id="@+id/playPause" + style="@style/appwidget_button" + android:layout_weight="1" + android:src="@drawable/appwidget_play" /> + <ImageButton android:id="@+id/next" + style="@style/appwidget_button" + android:layout_weight="1" + android:src="@drawable/appwidget_next" /> + </LinearLayout> +</LinearLayout> 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="horizontal" + android:gravity="center" + android:background="@drawable/appwidget_background"> + <!-- style="@style/appwidget_background"--> + + <Button android:id="@+id/infoDisplay" + style="@style/appwidget_infodisplay" + android:layout_height="fill_parent" + android:text="@string/appwidget_infoDisplay" /> + <ImageButton android:id="@+id/prev" + style="@style/appwidget_button" + android:layout_height="fill_parent" + android:src="@drawable/appwidget_prev" /> + <ImageButton android:id="@+id/stop" + style="@style/appwidget_button" + android:layout_height="fill_parent" + android:src="@drawable/appwidget_stop" /> + <ImageButton android:id="@+id/playPause" + style="@style/appwidget_button" + android:layout_height="fill_parent" + android:src="@drawable/appwidget_play" /> + <ImageButton android:id="@+id/next" + style="@style/appwidget_button" + android:layout_height="fill_parent" + android:src="@drawable/appwidget_next" /> +</LinearLayout> 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <ImageView android:id="@+id/logo" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:scaleType="centerInside" + android:src="@drawable/rockbox" /> + + <TextView android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/appwidget_configure_instructions"/> + + <CheckBox android:id="@+id/enable_prev" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/appwidget_configure_prev"/> + <CheckBox android:id="@+id/enable_stop" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/appwidget_configure_stop"/> + <CheckBox android:id="@+id/enable_playpause" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/appwidget_configure_playpause"/> + <CheckBox android:id="@+id/enable_next" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/appwidget_configure_next"/> + + <Button android:id="@+id/confirm" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:text="@string/appwidget_configure_confirm"/> +</LinearLayout> + 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 @@ <string name="No">No</string> <string name="error_extraction">Error occured during extraction!</string> <string name="rockbox_extracting">Rockbox is loading. Please wait...</string> -</resources>
\ No newline at end of file + +<!-- Widget --> +<string name="appwidget_label_4x1">Rockbox (line)</string> +<string name="appwidget_label_2x2">Rockbox (square)</string> +<string name="appwidget_infoDisplay">Touch to launch app</string> + +<!-- Widget configuration --> +<string name="appwidget_configure_instructions">Please chose elements to display in widget.</string> +<string name="appwidget_configure_prev">Prev Button</string> +<string name="appwidget_configure_stop">Stop Button</string> +<string name="appwidget_configure_playpause">Play/Pause Button</string> +<string name="appwidget_configure_next">Next Button</string> +<string name="appwidget_configure_confirm">Create Widget</string> + +</resources> 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 @@ +<?xml version="1.0" encoding="utf-8"?> + +<resources> + <style name="appwidget_infodisplay"> + <item name="android:layout_width">1dp</item> + <item name="android:layout_height">1dp</item> + <item name="android:layout_weight">1</item> + <item name="android:textColor">#cecfce</item> + <item name="android:background">@drawable/appwidget_infodisplay_background</item> + </style> + <style name="appwidget_button"> + <item name="android:layout_width">40dp</item> + <item name="android:layout_height">40dp</item> + <item name="android:scaleType">fitCenter</item> + <item name="android:background">@drawable/appwidget_infodisplay_background</item> + </style> +</resources> + 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 @@ +<!-- cell size is (number of cells * 74) - 2 dp according to http://developer.android.com/guide/topics/appwidgets/index.html#MetaData --> +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" + android:minWidth="146dp" + android:minHeight="146dp" + android:updatePeriodMillis="86400000" + android:initialLayout="@layout/appwidget_2x2" + android:configure="org.rockbox.widgets.RockboxWidgetConfigure"> +</appwidget-provider> 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 @@ +<!-- cell size is (number of cells * 74) - 2 dp according to http://developer.android.com/guide/topics/appwidgets/index.html#MetaData --> +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" + android:minWidth="294dp" + android:minHeight="72dp" + android:updatePeriodMillis="86400000" + android:initialLayout="@layout/appwidget_4x1" + android:configure="org.rockbox.widgets.RockboxWidgetConfigure"> +</appwidget-provider> 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 <dionoea at videolan dot org> + * + * 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 <dionoea at videolan dot org> + * + * 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 <dionoea at videolan dot org> + * + * 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 <dionoea at videolan dot org> + * + * 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 +{ +} + |