diff --git a/android/.classpath b/android/.classpath
new file mode 100644
index 0000000000..6efcbb739a
--- /dev/null
+++ b/android/.classpath
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/android/.project b/android/.project
new file mode 100644
index 0000000000..7e8d136317
--- /dev/null
+++ b/android/.project
@@ -0,0 +1,33 @@
+
+
+ Rockbox
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
new file mode 100644
index 0000000000..a22c393379
--- /dev/null
+++ b/android/AndroidManifest.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/android/README b/android/README
new file mode 100644
index 0000000000..e41bfa6c0c
--- /dev/null
+++ b/android/README
@@ -0,0 +1,34 @@
+This folder contains the java parts needed to build an Rockbox as an
+application for android.
+
+* Build instructions
+
+Until there's a script which does all the work the procedure is documented here.
+
+First, make sure you have the ANDROID_NDK_PATH environment variable set up,
+otherwise configure will fail to find the compiler.
+
+Use this as your build folder, using '../tools/configure' etc.
+ $ ../tools/configure
+ $ make
+
+After the build finished, you need to copy librockbox.so to libs/armeabi/.
+ $ cp librockbox.so libs/armeabi
+
+For the other files (codecs, themes), you execute 'make zip'. Then you copy the
+zip to libs/armeabi, using the name libmisc.so. This is needed, since there's no
+way to bundle stuff into apk's and have access to them from native code other
+than pretending it was a library.
+ $ make zip
+ $ cp rockbox.zip lib/armeabi/libmisc.so
+
+rockbox.zip..err, libmisc.so will be unpacked at runtime.
+
+To finish, you can follow this guide [1], or use eclipse. Simply install eclipse
+and the android plugins, then import this folder as a new Android project and run it.
+See [2] for a guide on how to set up eclipse for android development.
+
+
+
+[1]: http://asantoso.wordpress.com/2009/09/15/how-to-build-android-application-package-apk-from-the-command-line-using-the-sdk-tools-continuously-integrated-using-cruisecontrol/
+[2]: http://developer.android.com/sdk/installing.html
diff --git a/android/default.properties b/android/default.properties
new file mode 100644
index 0000000000..9d79b12c71
--- /dev/null
+++ b/android/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-4
diff --git a/android/gen/org/rockbox/R.java b/android/gen/org/rockbox/R.java
new file mode 100644
index 0000000000..38c177ef36
--- /dev/null
+++ b/android/gen/org/rockbox/R.java
@@ -0,0 +1,22 @@
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package org.rockbox;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int icon=0x7f020000;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040000;
+ }
+}
diff --git a/android/res/drawable-hdpi/icon.png b/android/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000000..8074c4c571
Binary files /dev/null and b/android/res/drawable-hdpi/icon.png differ
diff --git a/android/res/drawable-ldpi/icon.png b/android/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000000..1095584ec2
Binary files /dev/null and b/android/res/drawable-ldpi/icon.png differ
diff --git a/android/res/drawable-mdpi/icon.png b/android/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000000..a07c69fa5a
Binary files /dev/null and b/android/res/drawable-mdpi/icon.png differ
diff --git a/android/res/layout/main.xml b/android/res/layout/main.xml
new file mode 100644
index 0000000000..4361cfe8aa
--- /dev/null
+++ b/android/res/layout/main.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
new file mode 100644
index 0000000000..6c3c8464fd
--- /dev/null
+++ b/android/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+
+ Rockbox
+
diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java
new file mode 100644
index 0000000000..791cad90ff
--- /dev/null
+++ b/android/src/org/rockbox/RockboxActivity.java
@@ -0,0 +1,148 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * 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 java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import android.app.Activity;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Window;
+import android.view.WindowManager;
+
+public class RockboxActivity extends Activity {
+ /** Called when the activity is first created. */
+ public RockboxFramebuffer fb;
+ private Thread rb;
+ static final int BUFFER = 2048;
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LOG("start rb");
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
+ ,WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ fb = new RockboxFramebuffer(this);
+ if (true) {
+ try
+ {
+ BufferedOutputStream dest = null;
+ BufferedInputStream is = null;
+ ZipEntry entry;
+ File file = new File("/data/data/org.rockbox/lib/libmisc.so");
+ /* use arbitary file to determine whether extracting is needed */
+ File file2 = new File("/data/data/org.rockbox/app_rockbox/rockbox/codecs/mpa.codec");
+ if (!file2.exists() || (file.lastModified() > file2.lastModified()))
+ {
+ ZipFile zipfile = new ZipFile(file);
+ Enumeration extends ZipEntry> e = zipfile.entries();
+ File folder;
+ while(e.hasMoreElements()) {
+ entry = (ZipEntry) e.nextElement();
+ LOG("Extracting: " +entry);
+ if (entry.isDirectory())
+ {
+ folder = new File(entry.getName());
+ LOG("mkdir "+ entry);
+ try {
+ folder.mkdirs();
+ } catch (SecurityException ex){
+ LOG(ex.getMessage());
+ }
+ continue;
+ }
+ is = new BufferedInputStream(zipfile.getInputStream(entry));
+ int count;
+ byte data[] = new byte[BUFFER];
+ folder = new File(new File(entry.getName()).getParent());
+ LOG("" + folder.getAbsolutePath());
+ if (!folder.exists())
+ folder.mkdirs();
+ FileOutputStream fos = new FileOutputStream(entry.getName());
+ dest = new BufferedOutputStream(fos, BUFFER);
+ while ((count = is.read(data, 0, BUFFER)) != -1) {
+ dest.write(data, 0, count);
+ }
+ dest.flush();
+ dest.close();
+ is.close();
+ }
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }}
+ Rect r = new Rect();
+ fb.getDrawingRect(r);
+ LOG(r.left + " " + r.top + " " + r.right + " " + r.bottom);
+ rb = new Thread(new Runnable()
+ {
+ public void run()
+ {
+ main();
+ }
+ },"Rockbox thread");
+ System.loadLibrary("rockbox");
+ rb.setDaemon(false);
+ setContentView(fb);
+ }
+
+ private void LOG(CharSequence text)
+ {
+ Log.d("RockboxBootloader", (String) text);
+ }
+
+ public synchronized void onStart()
+ {
+ super.onStart();
+ if (!rb.isAlive())
+ rb.start();
+ }
+
+ public void onPause()
+ {
+ super.onPause();
+ }
+
+ public void onResume()
+ {
+ super.onResume();
+ switch (rb.getState()) {
+ case BLOCKED: LOG("BLOCKED"); break;
+ case RUNNABLE: LOG("RUNNABLE"); break;
+ case NEW: LOG("NEW"); break;
+ case TERMINATED: LOG("TERMINATED"); break;
+ case TIMED_WAITING: LOG("TIMED_WAITING"); break;
+ case WAITING: LOG("WAITING"); break;
+ }
+ }
+
+
+ private native void main();
+}
\ No newline at end of file
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java
new file mode 100644
index 0000000000..f947806bb4
--- /dev/null
+++ b/android/src/org/rockbox/RockboxFramebuffer.java
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * 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 java.nio.ByteBuffer;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.os.Handler;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+
+public class RockboxFramebuffer extends View
+{
+ private Bitmap btm;
+ private ByteBuffer native_buf;
+ private Handler update_handler;
+ private Runnable cb;
+
+
+ public RockboxFramebuffer(Context c)
+ {
+ super(c);
+ update_handler = new Handler();
+ cb = new Runnable() {
+ public void run()
+ {
+ btm.copyPixelsFromBuffer(native_buf);
+ invalidate();
+ }
+ };
+ btm = null;
+ }
+
+ public void onDraw(Canvas c)
+ {
+ if (btm != null)
+ c.drawBitmap(btm, 0.0f, 0.0f, null);
+ }
+
+ public void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
+ {
+ btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
+ native_buf = native_fb;
+ }
+
+ public void java_lcd_update()
+ {
+ update_handler.post(cb);
+ }
+
+ private void LOG(CharSequence text)
+ {
+ Log.d("RockboxBootloader", (String) text);
+ }
+
+ public boolean onTouchEvent(MotionEvent me)
+ {
+ LOG("onTouchEvent");
+ switch (me.getAction())
+ {
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ touchHandler(0);
+ break;
+ case MotionEvent.ACTION_MOVE:
+ case MotionEvent.ACTION_DOWN:
+ touchHandler(1);
+ break;
+
+ }
+ pixelHandler((int)me.getX(), (int)me.getY());
+ return true;
+ }
+
+ public native void pixelHandler(int x, int y);
+ public native void touchHandler(int down);
+}
diff --git a/android/src/org/rockbox/RockboxPCM.java b/android/src/org/rockbox/RockboxPCM.java
new file mode 100644
index 0000000000..f098df6991
--- /dev/null
+++ b/android/src/org/rockbox/RockboxPCM.java
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * 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.media.AudioFormat;
+import android.media.AudioManager;
+import android.media.AudioTrack;
+import android.util.Log;
+
+public class RockboxPCM extends AudioTrack
+{
+ byte[] raw_data;
+
+ private void LOG(CharSequence text)
+ {
+ Log.d("RockboxBootloader", (String) text);
+ }
+
+ public RockboxPCM()
+ {
+ super(AudioManager.STREAM_MUSIC,
+ 44100,
+ /* should be CHANNEL_OUT_STEREO in 2.0 and above */
+ AudioFormat.CHANNEL_CONFIGURATION_STEREO,
+ AudioFormat.ENCODING_PCM_16BIT,
+ 24<<10,
+ AudioTrack.MODE_STREAM);
+ int buf_len = 24<<10;
+
+ raw_data = new byte[buf_len*2];
+ for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00;
+ /* fill with silence */
+ write(raw_data, 0, raw_data.length);
+ if (getState() == AudioTrack.STATE_INITIALIZED)
+ {
+ if (setNotificationMarkerPosition(bytes2frames(buf_len*2)/4) != AudioTrack.SUCCESS)
+ LOG("setNotificationMarkerPosition Error");
+ setPlaybackPositionUpdateListener(new PCMListener(buf_len*2));
+ }
+ }
+
+
+
+ int bytes2frames(int bytes) {
+ /* 1 sample is 2 bytes, 2 samples are 1 frame */
+ return (bytes/4);
+ }
+
+ int frames2bytes(int frames) {
+ /* 1 frame is 2 samples, 1 sample is 2 bytes */
+ return (frames*4);
+ }
+
+ @SuppressWarnings("unused")
+ private void play_pause(boolean pause) {
+ LOG("play_pause()");
+ if (pause)
+ pause();
+ else
+ {
+ if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
+ {
+ for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00;
+ LOG("Writing silence");
+ /* fill with silence */
+ write(raw_data, 0, raw_data.length);
+ }
+ play();
+ }
+ LOG("play_pause() return");
+ }
+
+ @SuppressWarnings("unused")
+ private void set_volume(int volume)
+ {
+ /* volume comes from 0..-990 from Rockbox */
+ /* TODO volume is in dB, but this code acts as if it were in %, convert? */
+ float fvolume;
+ /* special case min and max volume to not suffer from floating point accuracy */
+ if (volume == 0)
+ fvolume = 1.0f;
+ else if (volume == -990)
+ fvolume = 0.0f;
+ else
+ fvolume = (volume + 990)/990.0f;
+ setStereoVolume(fvolume, fvolume);
+ }
+
+ public native void pcmSamplesToByteArray(byte[] dest);
+
+ private class PCMListener implements OnPlaybackPositionUpdateListener {
+ int max_len;
+ byte[] buf;
+ public PCMListener(int len) {
+ max_len = len;
+ buf = new byte[len/2];
+ }
+ @Override
+ public void onMarkerReached(AudioTrack track) {
+ // push new data to the hardware
+ int result = 1;
+ pcmSamplesToByteArray(buf);
+ //LOG("Trying to write " + buf.length + " bytes");
+ result = track.write(buf, 0, buf.length);
+ if (result > 0)
+ {
+ //LOG(result + " bytes written");
+ track.setPlaybackPositionUpdateListener(this);
+ track.setNotificationMarkerPosition(bytes2frames(max_len)/4);
+ switch(track.getPlayState())
+ {
+ case AudioTrack.PLAYSTATE_PLAYING:
+ //LOG("State PLAYING");
+ break;
+ case AudioTrack.PLAYSTATE_PAUSED:
+ LOG("State PAUSED");
+ break;
+ case AudioTrack.PLAYSTATE_STOPPED:
+ LOG("State STOPPED");
+ break;
+ }
+ }
+ else
+ {
+ LOG("Error in onMarkerReached");
+ track.stop();
+ }
+ }
+
+ @Override
+ public void onPeriodicNotification(AudioTrack track) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+}
diff --git a/android/src/org/rockbox/RockboxTimer.java b/android/src/org/rockbox/RockboxTimer.java
new file mode 100644
index 0000000000..c7239b4ee6
--- /dev/null
+++ b/android/src/org/rockbox/RockboxTimer.java
@@ -0,0 +1,93 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * 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 java.util.Timer;
+import java.util.TimerTask;
+
+import android.util.Log;
+
+public class RockboxTimer extends Timer
+{
+ RockboxTimerTask task;
+ long interval;
+
+ private class RockboxTimerTask extends TimerTask {
+ private RockboxTimer t;
+ public RockboxTimerTask(RockboxTimer parent) {
+ super();
+ t = parent;
+ }
+
+ @Override
+ public void run() {
+ timerTask();
+ synchronized(t) {
+ t.notify();
+ }
+ }
+ }
+
+ public void pause()
+ {
+ cancel();
+ }
+ public void resume()
+ {
+ try {
+ schedule(task, 0, interval);
+ } catch (IllegalStateException e) {
+ /* not an error */
+ } catch (Exception e) {
+ LOG(e.toString());
+ }
+ }
+
+ public RockboxTimer(long period_inverval_in_ms)
+ {
+ super("tick timer", false);
+ task = new RockboxTimerTask(this);
+ schedule(task, 0, period_inverval_in_ms);
+ interval = period_inverval_in_ms;
+ }
+
+ private void LOG(CharSequence text)
+ {
+ Log.d("RockboxBootloader", (String) text);
+ }
+
+
+ /* methods called from native, keep them simple */
+ public void java_wait_for_interrupt()
+ {
+ synchronized(this) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ /* wakeup and return */
+ } catch (Exception e) {
+ LOG(e.toString());
+ }
+ }
+ }
+ public native void timerTask();
+}
diff --git a/apps/codecs/codec_crt0.c b/apps/codecs/codec_crt0.c
index dd0f99ffd8..c680030fee 100644
--- a/apps/codecs/codec_crt0.c
+++ b/apps/codecs/codec_crt0.c
@@ -34,6 +34,10 @@ extern unsigned char plugin_end_addr[];
extern enum codec_status codec_main(void);
+/* stub, the entry point is called via its reference in __header to
+ * avoid warning with certain compilers */
+int _start(void) {return 0;}
+
enum codec_status codec_start(void)
{
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h
index 5b5385a521..ee7c969b4c 100644
--- a/apps/codecs/libwavpack/wavpack.h
+++ b/apps/codecs/libwavpack/wavpack.h
@@ -16,7 +16,9 @@
typedef unsigned char uchar;
typedef unsigned short ushort;
+#if 0 // unused and causing compiler errrors
typedef unsigned int uint;
+#endif
#include
diff --git a/backdrops/cabbiev2.320x480x16.bmp b/backdrops/cabbiev2.320x480x16.bmp
new file mode 100644
index 0000000000..6933fd0675
Binary files /dev/null and b/backdrops/cabbiev2.320x480x16.bmp differ
diff --git a/bootloader/common.c b/bootloader/common.c
index 362c3b4d11..1099b9f453 100644
--- a/bootloader/common.c
+++ b/bootloader/common.c
@@ -68,7 +68,7 @@ void reset_screen(void)
#endif
}
-void printf(const char *format, ...)
+int printf(const char *format, ...)
{
int len;
unsigned char *ptr;
@@ -91,6 +91,7 @@ void printf(const char *format, ...)
if(remote_line >= LCD_REMOTE_HEIGHT/SYSFONT_HEIGHT)
remote_line = 0;
#endif
+ return len;
}
char *strerror(int error)
diff --git a/bootloader/common.h b/bootloader/common.h
index 6713585ad8..7d5425c9c8 100644
--- a/bootloader/common.h
+++ b/bootloader/common.h
@@ -41,7 +41,7 @@ extern bool verbose;
/* Functions common to all bootloaders */
void reset_screen(void);
-void printf(const char *format, ...);
+int printf(const char *format, ...);
char *strerror(int error);
void error(int errortype, int error, bool shutdown);
int load_firmware(unsigned char* buf, char* firmware, int buffer_size);
diff --git a/firmware/SOURCES b/firmware/SOURCES
index d8cfadef11..4092f71e04 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1698,3 +1698,14 @@ target/coldfire/mpio/fmradio_i2c-mpio.c
#endif /* BOOTLOADER */
#endif /* SIMULATOR */
#endif
+
+
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+target/hosted/android/lcd-android.c
+target/hosted/android/button-android.c
+target/hosted/android/kernel-android.c
+target/hosted/android/pcm-android.c
+target/hosted/android/system-android.c
+drivers/audio/android.c
+thread.c
+#endif
diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c
index 69bc1387ef..b63586c9f4 100644
--- a/firmware/common/rbpaths.c
+++ b/firmware/common/rbpaths.c
@@ -33,9 +33,13 @@
void paths_init(void)
{
/* make sure $HOME/.config/rockbox.org exists, it's needed for config.cfg */
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+ mkdir("/sdcard/rockbox");
+#else
char home_path[MAX_PATH];
snprintf(home_path, sizeof(home_path), "%s/.config/rockbox.org", getenv("HOME"));
mkdir(home_path);
+#endif
}
const char* get_user_file_path(const char *path,
@@ -50,7 +54,11 @@ const char* get_user_file_path(const char *path,
pos += ROCKBOX_DIR_LEN;
if (*pos == '/') pos += 1;
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+ if (snprintf(buf, bufsize, "/sdcard/rockbox/%s", pos)
+#else
if (snprintf(buf, bufsize, "%s/.config/rockbox.org/%s", getenv("HOME"), pos)
+#endif
>= (int)bufsize)
return NULL;
diff --git a/firmware/drivers/audio/android.c b/firmware/drivers/audio/android.c
new file mode 100644
index 0000000000..300bb08482
--- /dev/null
+++ b/firmware/drivers/audio/android.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright © 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include "config.h"
+#include "audiohw.h"
+
+const struct sound_settings_info audiohw_settings[] = {
+ [SOUND_VOLUME] = {"dB", 0, 1, VOLUME_MIN / 10, VOLUME_MAX / 10, -25},
+/* Bass and treble tone controls */
+#ifdef AUDIOHW_HAVE_BASS
+ [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0},
+#endif
+#ifdef AUDIOHW_HAVE_TREBLE
+ [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0},
+#endif
+ [SOUND_BALANCE] = {"%", 0, 1,-100, 100, 0},
+ [SOUND_CHANNELS] = {"", 0, 1, 0, 5, 0},
+ [SOUND_STEREO_WIDTH] = {"%", 0, 5, 0, 250, 100},
+#if defined(HAVE_RECORDING)
+ [SOUND_LEFT_GAIN] = {"dB", 1, 1,-128, 96, 0},
+ [SOUND_RIGHT_GAIN] = {"dB", 1, 1,-128, 96, 0},
+ [SOUND_MIC_GAIN] = {"dB", 1, 1,-128, 108, 16},
+#endif
+#if defined(AUDIOHW_HAVE_BASS_CUTOFF)
+ [SOUND_BASS_CUTOFF] = {"", 0, 1, 1, 4, 1},
+#endif
+#if defined(AUDIOHW_HAVE_TREBLE_CUTOFF)
+ [SOUND_TREBLE_CUTOFF] = {"", 0, 1, 1, 4, 1},
+#endif
+};
+
+
+void audiohw_set_volume(int volume)
+{
+ extern void pcm_set_mixer_volume(int);
+ pcm_set_mixer_volume(volume);
+}
+
+void audiohw_set_balance(int balance)
+{
+ (void)balance;
+}
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index d4861aac5a..658dd1301c 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -66,7 +66,7 @@
#elif defined(HAVE_AK4537)
#include "ak4537.h"
#endif
-#if defined(HAVE_SDL_AUDIO)
+#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
/* #include gives errors in other code areas,
* we don't really need it here, so don't. but it should maybe be fixed */
#ifndef SIMULATOR /* simulator gets values from the target .h files */
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 1b8a782f39..3b59004549 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -78,8 +78,10 @@
* bit fields to allow PLATFORM_HOSTED to be OR'ed e.g. with a
* possible future PLATFORM_ANDROID (some OSes might need totally different
* handling to run on them than a stand-alone application) */
-#define PLATFORM_NATIVE (1<<0)
-#define PLATFORM_HOSTED (1<<1)
+#define PLATFORM_NATIVE (1<<0)
+#define PLATFORM_HOSTED (1<<1)
+#define PLATFORM_ANDROID (1<<2)
+#define PLATFORM_SDL (1<<3)
/* CONFIG_KEYPAD */
#define PLAYER_PAD 1
@@ -427,6 +429,8 @@ Lyre prototype 1 */
#elif defined(APPLICATION)
#include "config/application.h"
+#define CONFIG_CPU 0
+#define CONFIG_STORAGE 0
#else
/* no known platform */
#endif
@@ -689,11 +693,17 @@ Lyre prototype 1 */
#define HAVE_EXTENDED_MESSAGING_AND_NAME
#define HAVE_WAKEUP_EXT_CB
+
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+#define HAVE_PRIORITY_SCHEDULING
+#endif
+
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
#define HAVE_PRIORITY_SCHEDULING
#define HAVE_SCHEDULER_BOOSTCTRL
#endif /* PLATFORM_NATIVE */
+
#define HAVE_SEMAPHORE_OBJECTS
#if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC
diff --git a/firmware/export/config/application.h b/firmware/export/config/application.h
index a5583ded75..988f0d51ac 100644
--- a/firmware/export/config/application.h
+++ b/firmware/export/config/application.h
@@ -4,11 +4,13 @@
#define TARGET_TREE /* this target is using the target tree system */
/* We don't run on hardware directly */
-#define CONFIG_PLATFORM PLATFORM_HOSTED
+#ifdef ANDROID
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
+#else
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
+#endif
/* For Rolo and boot loader */
-/*
-#define MODEL_NUMBER 24
-*/
+#define MODEL_NUMBER 100
#define MODEL_NAME "Rockbox"
@@ -37,9 +39,17 @@
/* define this if you would like tagcache to build on this target */
#define HAVE_TAGCACHE
-/* LCD dimensions */
+/* LCD dimensions
+ *
+ * overriden by configure for application builds */
+#ifndef LCD_WIDTH
#define LCD_WIDTH 320
-#define LCD_HEIGHT 240
+#endif
+
+#ifndef LCD_HEIGHT
+#define LCD_HEIGHT 480
+#endif
+
#define LCD_DEPTH 16
#define LCD_PIXELFORMAT 565
@@ -62,10 +72,10 @@
#define CONFIG_CODEC SWCODEC
#define CONFIG_KEYPAD COWON_D2_PAD
+
+#if (CONFIG_PLATFORM & PLATFORM_SDL)
/* Use SDL audio/pcm in a SDL app build */
#define HAVE_SDL
-
-#ifdef HAVE_SDL
#define HAVE_SDL_AUDIO
#endif
@@ -92,3 +102,5 @@
/* Define this if a programmable hotkey is mapped */
//#define HAVE_HOTKEY
+
+#define BOOTDIR "/.rockbox"
diff --git a/firmware/export/config/sim.h b/firmware/export/config/sim.h
index 5dcb4f6f2d..066201ad08 100644
--- a/firmware/export/config/sim.h
+++ b/firmware/export/config/sim.h
@@ -99,7 +99,8 @@
#define DEFAULT_BRIGHTNESS_SETTING MAX_BRIGHTNESS_SETTING
#endif
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_SDL)
#define HAVE_SDL
#define HAVE_SDL_AUDIO
-#define CONFIG_PLATFORM PLATFORM_HOSTED
+
#define _ISOC99_SOURCE 1
diff --git a/firmware/export/debug.h b/firmware/export/debug.h
index f7f0f32426..f19a96c526 100644
--- a/firmware/export/debug.h
+++ b/firmware/export/debug.h
@@ -21,6 +21,7 @@
#ifndef DEBUG_H
#define DEBUG_H
+#include "config.h"
#include "gcc_extensions.h"
extern void debug_init(void);
@@ -34,7 +35,11 @@ extern void ldebugf(const char* file, int line, const char *fmt, ...)
/* */
#if defined(SIMULATOR) && !defined(__PCTOOL__)
#define DEBUGF debugf
-#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__)
+#define LDEBUGF(...) ldebugf(__FILE__, __LINE__, __VA_ARGS__) && defined(DEBUG)
+#elif (CONFIG_PLATFORM & PLATFORM_ANDROID)
+#include "system-target.h"
+#define DEBUGF LOG
+#define LDEBUGF(...)
#else
#if defined(DEBUG)
diff --git a/firmware/export/thread.h b/firmware/export/thread.h
index c4b7d1fa22..2853c0b121 100644
--- a/firmware/export/thread.h
+++ b/firmware/export/thread.h
@@ -79,9 +79,19 @@
#define MAXTHREADS (BASETHREADS+TARGET_EXTRA_THREADS)
+/*
+ * We need more stack when we run under a host
+ * maybe more expensive C lib functions?
+ *
+ * simulator doesn't simulate stack usage anyway but well ... */
+#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SIMULATOR))
#define DEFAULT_STACK_SIZE 0x400 /* Bytes */
+#else
+#define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
+#endif
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+
+#if (CONFIG_PLATFORM & (PLATFORM_NATIVE|PLATFORM_ANDROID))
/* Need to keep structures inside the header file because debug_menu
* needs them. */
#ifdef CPU_COLDFIRE
@@ -101,7 +111,7 @@ struct regs
uint32_t pr; /* 32 - Procedure register */
uint32_t start; /* 36 - Thread start address, or NULL when started */
};
-#elif defined(CPU_ARM)
+#elif defined(CPU_ARM) || (CONFIG_PLATFORM & PLATFORM_ANDROID)
struct regs
{
uint32_t r[8]; /* 0-28 - Registers r4-r11 */
diff --git a/firmware/sound.c b/firmware/sound.c
index 76f1dd0df6..4cc63f4583 100644
--- a/firmware/sound.c
+++ b/firmware/sound.c
@@ -273,7 +273,7 @@ static void set_prescaled_volume(void)
#elif defined(HAVE_TLV320) || defined(HAVE_WM8978) || defined(HAVE_WM8985)
audiohw_set_headphone_vol(tenthdb2master(l), tenthdb2master(r));
-#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO)
+#elif defined(HAVE_JZ4740_CODEC) || defined(HAVE_SDL_AUDIO) || defined(ANDROID)
audiohw_set_volume(current_volume);
#endif
#else /* HAVE_SDL_AUDIO */
diff --git a/firmware/target/hosted/android/app/adc-target.h b/firmware/target/hosted/android/app/adc-target.h
new file mode 100644
index 0000000000..f8069be6f5
--- /dev/null
+++ b/firmware/target/hosted/android/app/adc-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __ADC_TARGET_H__
+#define __ADC_TARGET_H__
+
+#endif /* __ADC_TARGET_H__ */
diff --git a/firmware/target/hosted/android/app/backlight-target.h b/firmware/target/hosted/android/app/backlight-target.h
new file mode 100644
index 0000000000..f753e7c1dd
--- /dev/null
+++ b/firmware/target/hosted/android/app/backlight-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BACKLIGHT_TARGET_H__
+#define __BACKLIGHT_TARGET_H__
+
+#endif /* __BACKLIGHT_TARGET_H__ */
diff --git a/firmware/target/hosted/android/app/button-application.c b/firmware/target/hosted/android/app/button-application.c
new file mode 100644
index 0000000000..a27f769718
--- /dev/null
+++ b/firmware/target/hosted/android/app/button-application.c
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ***************************************************9*************************/
+
+
+#include "button.h"
+
+int key_to_button(int keyboard_key)
+{
+ (void)keyboard_key;
+ return BUTTON_NONE;
+}
diff --git a/firmware/target/hosted/android/app/button-target.h b/firmware/target/hosted/android/app/button-target.h
new file mode 100644
index 0000000000..329ed651af
--- /dev/null
+++ b/firmware/target/hosted/android/app/button-target.h
@@ -0,0 +1,64 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Rob Purchase
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef _BUTTON_TARGET_H_
+#define _BUTTON_TARGET_H_
+
+#include
+#include "config.h"
+
+#undef button_init_device
+void button_init_device(void);
+int button_read_device(int *data);
+
+/* Main unit's buttons */
+#define BUTTON_POWER 0x00000001
+#define BUTTON_PLUS 0x00000002
+#define BUTTON_MINUS 0x00000004
+#define BUTTON_MENU 0x00000008
+
+/* Compatibility hacks for flipping. Needs a somewhat better fix. */
+#define BUTTON_LEFT BUTTON_MIDLEFT
+#define BUTTON_RIGHT BUTTON_MIDRIGHT
+#define BUTTON_UP BUTTON_TOPMIDDLE
+#define BUTTON_DOWN BUTTON_BOTTOMMIDDLE
+
+/* Touch Screen Area Buttons */
+#define BUTTON_TOPLEFT 0x00000010
+#define BUTTON_TOPMIDDLE 0x00000020
+#define BUTTON_TOPRIGHT 0x00000040
+#define BUTTON_MIDLEFT 0x00000080
+#define BUTTON_CENTER 0x00000100
+#define BUTTON_MIDRIGHT 0x00000200
+#define BUTTON_BOTTOMLEFT 0x00000400
+#define BUTTON_BOTTOMMIDDLE 0x00000800
+#define BUTTON_BOTTOMRIGHT 0x00001000
+
+#define BUTTON_MAIN 0x1FFF
+
+/* No remote */
+#define BUTTON_REMOTE 0
+
+/* Software power-off */
+#define POWEROFF_BUTTON BUTTON_POWER
+#define POWEROFF_COUNT 10
+
+#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/hosted/android/app/i2c-target.h b/firmware/target/hosted/android/app/i2c-target.h
new file mode 100644
index 0000000000..89f0436b9e
--- /dev/null
+++ b/firmware/target/hosted/android/app/i2c-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __I2C_TARGET_H__
+#define __I2C_TARGET_H__
+
+#endif /* __I2C_TARGET_H__ */
diff --git a/firmware/target/hosted/android/app/usb-target.h b/firmware/target/hosted/android/app/usb-target.h
new file mode 100644
index 0000000000..10e04677f9
--- /dev/null
+++ b/firmware/target/hosted/android/app/usb-target.h
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __USB_TARGET_H__
+#define __USB_TARGET_H__
+
+#endif /* __USB_TARGET_H__ */
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c
new file mode 100644
index 0000000000..67e8ca1f89
--- /dev/null
+++ b/firmware/target/hosted/android/button-android.c
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include
+#include
+#include "config.h"
+#include "kernel.h"
+#include "system.h"
+#include "touchscreen.h"
+
+static long last_touch;
+static int last_y, last_x;
+
+static enum {
+ STATE_UNKNOWN,
+ STATE_UP,
+ STATE_DOWN,
+} last_state = STATE_UNKNOWN;
+
+
+/*
+ * this writes in an interrupt-like fashion the last pixel coordinates
+ * that the user pressed on the screen */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_pixelHandler(JNIEnv*env, jobject this,
+ int x, int y)
+{
+ (void)env;
+ (void)this;
+ last_x = x;
+ last_y = y;
+ last_touch = current_tick;
+}
+
+/*
+ * this notifies us in an interrupt-like fashion whether the user just
+ * began or stopped the touch action */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this,
+ int down)
+{
+ (void)env;
+ (void)this;
+ if (down)
+ last_state = STATE_DOWN;
+ else
+ last_state = STATE_UP;
+}
+
+void button_init_device(void)
+{
+ last_touch = current_tick;
+}
+
+int button_read_device(int *data)
+{
+ /* get grid button/coordinates based on the current touchscreen mode */
+ int btn = touchscreen_to_pixels(last_x, last_y, data);
+ if (last_state == STATE_DOWN)
+ {
+ return btn;
+ }
+ else
+ {
+ *data = last_x = last_y = 0;
+ return 0;
+ }
+}
diff --git a/firmware/target/hosted/android/buttonmap.h b/firmware/target/hosted/android/buttonmap.h
new file mode 100644
index 0000000000..e90b8a40d4
--- /dev/null
+++ b/firmware/target/hosted/android/buttonmap.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Fred Bauer
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __BUTTONMAP_H__
+#define __BUTTONMAP_H__
+/* Button maps: simulated key, x, y, radius, name */
+/* Run sim with --mapping to get coordinates */
+/* or --debugbuttons to check */
+/* The First matching button is returned */
+struct button_map {
+ int button, x, y, radius;
+ char *description;
+};
+
+extern struct button_map bm[];
+
+int xy2button( int x, int y);
+
+/* for the sim, these function is implemented in uisimulator/buttonmap/ *.c */
+int key_to_button(int keyboard_button);
+#ifdef HAVE_TOUCHSCREEN
+int key_to_touch(int keyboard_button, unsigned int mouse_coords);
+#endif
+
+#endif /* __BUTTONMAP_H__ */
diff --git a/firmware/target/hosted/android/kernel-android.c b/firmware/target/hosted/android/kernel-android.c
new file mode 100644
index 0000000000..9594516460
--- /dev/null
+++ b/firmware/target/hosted/android/kernel-android.c
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include
+#include "config.h"
+#include "system.h"
+
+extern JNIEnv *env_ptr;
+extern jclass RockboxActivity_class;
+extern jobject RockboxActivity_instance;
+
+static jclass RockboxTimer_class;
+static jobject RockboxTimer_instance;
+static jmethodID java_wait_for_interrupt;
+static bool initialized = false;
+
+/*
+ * This is called from the separate Timer java thread. I have not added any
+ * interrupt simulation to it (like the sdl counterpart does),
+ * I think this is probably not needed, unless code calls disable_interrupt()
+ * in order to be protected from tick tasks, but I can't remember a place right
+ * now.
+ *
+ * No synchronisation mechanism either. This could possibly be problematic,
+ * but we'll see :)
+ */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxTimer_timerTask(JNIEnv *env, jobject this)
+{
+ (void)env;
+ (void)this;
+ call_tick_tasks();
+}
+
+void tick_start(unsigned int interval_in_ms)
+{
+ JNIEnv e = *env_ptr;
+ /* first, create a new Timer instance */
+ RockboxTimer_class = e->FindClass(env_ptr, "org/rockbox/RockboxTimer");
+ jmethodID constructor = e->GetMethodID(env_ptr,
+ RockboxTimer_class,
+ "",
+ "(J)V");
+ /* the constructor will do the tick_start */
+ RockboxTimer_instance = e->NewObject(env_ptr,
+ RockboxTimer_class,
+ constructor,
+ (jlong)interval_in_ms);
+
+ /* get our wfi func also */
+ java_wait_for_interrupt = e->GetMethodID(env_ptr,
+ RockboxTimer_class,
+ "java_wait_for_interrupt",
+ "()V");
+ /* it's now safe to call java_wait_for_interrupt */
+ initialized = true;
+}
+
+void wait_for_interrupt(void)
+{
+ if (LIKELY(initialized))
+ {
+ (*env_ptr)->CallVoidMethod(env_ptr,
+ RockboxTimer_instance,
+ java_wait_for_interrupt);
+ }
+}
+
+bool timer_register(int reg_prio, void (*unregister_callback)(void),
+ long cycles, void (*timer_callback)(void))
+{
+ (void)reg_prio;
+ (void)unregister_callback;
+ (void)cycles;
+ (void)timer_callback;
+ return false;
+}
+
+bool timer_set_period(long cycles)
+{
+ (void)cycles;
+ return false;
+}
+
+void timer_unregister(void)
+{
+}
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c
new file mode 100644
index 0000000000..ef4004ef2a
--- /dev/null
+++ b/firmware/target/hosted/android/lcd-android.c
@@ -0,0 +1,291 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include
+#include "config.h"
+#include "system.h"
+#include "lcd.h"
+
+extern JNIEnv *env_ptr;
+extern jclass RockboxActivity_class;
+extern jobject RockboxActivity_instance;
+
+static jobject Framebuffer_instance;
+static jmethodID java_lcd_update;
+
+void lcd_init_device(void)
+{
+ /* get the RockboxFramebuffer instance allocated by the activity */
+ jfieldID id = (*env_ptr)->GetFieldID(env_ptr,
+ RockboxActivity_class,
+ "fb",
+ "Lorg/rockbox/RockboxFramebuffer;");
+
+ Framebuffer_instance = (*env_ptr)->GetObjectField(env_ptr,
+ RockboxActivity_instance,
+ id);
+
+ jclass Framebuffer_class = (*env_ptr)->GetObjectClass(env_ptr,
+ Framebuffer_instance);
+
+ /* get the java init function and call it. it'll set up a bitmap
+ * based on LCD_WIDTH, LCD_HEIGHT and the ByteBuffer which directly maps
+ * our framebuffer */
+
+ jmethodID java_init_lcd = (*env_ptr)->GetMethodID(env_ptr,
+ Framebuffer_class,
+ "java_lcd_init",
+ "(IILjava/nio/ByteBuffer;)V");
+ java_lcd_update = (*env_ptr)->GetMethodID(env_ptr,
+ Framebuffer_class,
+ "java_lcd_update",
+ "()V");
+
+ /* map the framebuffer to a ByteBuffer, this way lcd updates will
+ * be directly feched from the framebuffer */
+ jobject buf = (*env_ptr)->NewDirectByteBuffer(env_ptr,
+ lcd_framebuffer,
+ sizeof(lcd_framebuffer));
+
+ (*env_ptr)->CallVoidMethod(env_ptr,
+ Framebuffer_instance,
+ java_init_lcd,
+ LCD_WIDTH, LCD_HEIGHT, buf);
+}
+
+void lcd_update()
+{
+ /* tell the system we're ready for drawing */
+ (*env_ptr)->CallVoidMethod(env_ptr, Framebuffer_instance, java_lcd_update);
+}
+
+void lcd_update_rect(int x, int y, int height, int width)
+{
+ /* can't do partial updates yet */
+ (void)x; (void)y; (void)height; (void)width;
+ lcd_update();
+}
+
+/* below is a plain copy from lcd-sdl.c */
+
+/**
+ * |R| |1.000000 -0.000001 1.402000| |Y'|
+ * |G| = |1.000000 -0.334136 -0.714136| |Pb|
+ * |B| |1.000000 1.772000 0.000000| |Pr|
+ * Scaled, normalized, rounded and tweaked to yield RGB 565:
+ * |R| |74 0 101| |Y' - 16| >> 9
+ * |G| = |74 -24 -51| |Cb - 128| >> 8
+ * |B| |74 128 0| |Cr - 128| >> 9
+ */
+#define YFAC (74)
+#define RVFAC (101)
+#define GUFAC (-24)
+#define GVFAC (-51)
+#define BUFAC (128)
+
+static inline int clamp(int val, int min, int max)
+{
+ if (val < min)
+ val = min;
+ else if (val > max)
+ val = max;
+ return val;
+}
+
+void lcd_yuv_set_options(unsigned options)
+{
+ (void)options;
+}
+
+/* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
+ in the core */
+void lcd_blit_yuv(unsigned char * const src[3],
+ int src_x, int src_y, int stride,
+ int x, int y, int width, int height)
+{
+ const unsigned char *ysrc, *usrc, *vsrc;
+ int linecounter;
+ fb_data *dst, *row_end;
+ long z;
+
+ /* width and height must be >= 2 and an even number */
+ width &= ~1;
+ linecounter = height >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst = &lcd_framebuffer[y][x];
+ row_end = dst + width;
+#else
+ dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
+ row_end = dst + LCD_WIDTH * width;
+#endif
+
+ z = stride * src_y;
+ ysrc = src[0] + z + src_x;
+ usrc = src[1] + (z >> 2) + (src_x >> 1);
+ vsrc = src[2] + (usrc - src[1]);
+
+ /* stride => amount to jump from end of last row to start of next */
+ stride -= width;
+
+ /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
+
+ do
+ {
+ do
+ {
+ int y, cb, cr, rv, guv, bu, r, g, b;
+
+ y = YFAC*(*ysrc++ - 16);
+ cb = *usrc++ - 128;
+ cr = *vsrc++ - 128;
+
+ rv = RVFAC*cr;
+ guv = GUFAC*cb + GVFAC*cr;
+ bu = BUFAC*cb;
+
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+
+ y = YFAC*(*ysrc++ - 16);
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+ }
+ while (dst < row_end);
+
+ ysrc += stride;
+ usrc -= width >> 1;
+ vsrc -= width >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ row_end += LCD_WIDTH;
+ dst += LCD_WIDTH - width;
+#else
+ row_end -= 1;
+ dst -= LCD_WIDTH*width + 1;
+#endif
+
+ do
+ {
+ int y, cb, cr, rv, guv, bu, r, g, b;
+
+ y = YFAC*(*ysrc++ - 16);
+ cb = *usrc++ - 128;
+ cr = *vsrc++ - 128;
+
+ rv = RVFAC*cr;
+ guv = GUFAC*cb + GVFAC*cr;
+ bu = BUFAC*cb;
+
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+
+ y = YFAC*(*ysrc++ - 16);
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+ }
+ while (dst < row_end);
+
+ ysrc += stride;
+ usrc += stride >> 1;
+ vsrc += stride >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ row_end += LCD_WIDTH;
+ dst += LCD_WIDTH - width;
+#else
+ row_end -= 1;
+ dst -= LCD_WIDTH*width + 1;
+#endif
+ }
+ while (--linecounter > 0);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ lcd_update_rect(x, y, width, height);
+#else
+ lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
+#endif
+}
diff --git a/firmware/target/hosted/android/pcm-android.c b/firmware/target/hosted/android/pcm-android.c
new file mode 100644
index 0000000000..91978f422b
--- /dev/null
+++ b/firmware/target/hosted/android/pcm-android.c
@@ -0,0 +1,174 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#include
+#include
+#include
+#include "pcm.h"
+
+extern JNIEnv *env_ptr;
+extern jclass RockboxActivity_class;
+extern jobject RockboxActivity_instance;
+
+/* infos about our pcm chunks */
+static size_t pcm_data_size;
+static char *pcm_data_start;
+
+/* cache frequently called methods */
+static jmethodID play_pause_method;
+static jmethodID stop_method;
+static jmethodID set_volume_method;
+static jclass RockboxPCM_class;
+static jobject RockboxPCM_instance;
+
+
+/*
+ * transfer our raw data into a java array
+ *
+ * a bit of a monster functions, but it should cover all cases to overcome
+ * the issue that the chunk size of the java layer and our pcm chunks are
+ * differently sized
+ *
+ * afterall, it only copies the raw pcm data from pcm_data_start to
+ * the passed byte[]-array
+ *
+ * it is called from the PositionMarker callback of AudioTrack
+ **/
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxPCM_pcmSamplesToByteArray(JNIEnv *env,
+ jobject this,
+ jbyteArray arr)
+{
+ (void)this;
+ size_t len;
+ size_t array_size = (*env)->GetArrayLength(env, arr);
+ if (array_size > pcm_data_size)
+ len = pcm_data_size;
+ else
+ len = array_size;
+
+ (*env)->SetByteArrayRegion(env, arr, 0, len, pcm_data_start);
+
+ if (array_size > pcm_data_size)
+ { /* didn't have enough data for the array ? */
+ size_t remaining = array_size - pcm_data_size;
+ size_t offset = len;
+ retry:
+ pcm_play_get_more_callback((void**)&pcm_data_start, &pcm_data_size);
+ if (pcm_data_size == 0)
+ return;
+ if (remaining > pcm_data_size)
+ { /* got too little data, get more ... */
+ (*env)->SetByteArrayRegion(env, arr, offset, pcm_data_size, pcm_data_start);
+ /* advance in the java array by the amount we copied */
+ offset += pcm_data_size;
+ /* we copied at least a bit */
+ remaining -= pcm_data_size;
+ /* let's get another buch of data and try again */
+ goto retry;
+ }
+ else
+ (*env)->SetByteArrayRegion(env, arr, offset, remaining, pcm_data_start);
+ len = remaining;
+ }
+ pcm_data_start += len;
+ pcm_data_size -= len;
+}
+
+void pcm_play_lock(void)
+{
+}
+
+void pcm_play_unlock(void)
+{
+}
+
+void pcm_dma_apply_settings(void)
+{
+}
+
+void pcm_play_dma_start(const void *addr, size_t size)
+{
+ pcm_data_start = (char*)addr;
+ pcm_data_size = size;
+
+ pcm_play_dma_pause(false);
+}
+
+void pcm_play_dma_stop(void)
+{
+ (*env_ptr)->CallVoidMethod(env_ptr,
+ RockboxPCM_instance,
+ stop_method);
+}
+
+void pcm_play_dma_pause(bool pause)
+{
+ (*env_ptr)->CallVoidMethod(env_ptr,
+ RockboxPCM_instance,
+ play_pause_method,
+ (int)pause);
+}
+
+size_t pcm_get_bytes_waiting(void)
+{
+ return pcm_data_size;
+}
+
+const void * pcm_play_dma_get_peak_buffer(int *count)
+{
+ uintptr_t addr = (uintptr_t)pcm_data_start;
+ *count = pcm_data_size / 4;
+ return (void *)((addr + 3) & ~3);
+}
+
+void pcm_play_dma_init(void)
+{
+ /* in order to have background music playing after leaving the activity,
+ * we need to allocate the PCM object from the Rockbox thread (the Activity
+ * runs in a separate thread because it would otherwise kill us when
+ * stopping it)
+ *
+ * Luckily we only reference the PCM object from here, so it's safe (and
+ * clean) to allocate it here
+ **/
+ JNIEnv e = *env_ptr;
+ /* get the class and its constructor */
+ RockboxPCM_class = e->FindClass(env_ptr, "org/rockbox/RockboxPCM");
+ jmethodID constructor = e->GetMethodID(env_ptr, RockboxPCM_class, "", "()V");
+ /* instance = new RockboxPCM() */
+ RockboxPCM_instance = e->NewObject(env_ptr, RockboxPCM_class, constructor);
+ /* cache needed methods */
+ play_pause_method = e->GetMethodID(env_ptr, RockboxPCM_class, "play_pause", "(Z)V");
+ set_volume_method = e->GetMethodID(env_ptr, RockboxPCM_class, "set_volume", "(I)V");
+ stop_method = e->GetMethodID(env_ptr, RockboxPCM_class, "stop", "()V");
+ /* get initial pcm data, if any */
+ pcm_play_get_more_callback((void*)&pcm_data_start, &pcm_data_size);
+}
+
+void pcm_postinit(void)
+{
+}
+
+void pcm_set_mixer_volume(int volume)
+{
+ (*env_ptr)->CallVoidMethod(env_ptr, RockboxPCM_instance, set_volume_method, volume);
+}
diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c
new file mode 100644
index 0000000000..07dff2ed56
--- /dev/null
+++ b/firmware/target/hosted/android/system-android.c
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include
+#include "config.h"
+#include "system.h"
+
+void system_exception_wait(void) { }
+void system_reboot(void) { }
+void power_off(void) { }
+void system_init(void) { }
+
+
+/* global fields for use with various JNI calls */
+JNIEnv *env_ptr;
+jobject RockboxActivity_instance;
+jclass RockboxActivity_class;
+
+uintptr_t *stackbegin;
+uintptr_t *stackend;
+
+extern int main(void);
+/* this is the entry point of the android app initially called by jni */
+JNIEXPORT void JNICALL
+Java_org_rockbox_RockboxActivity_main(JNIEnv *env, jobject this)
+{
+ /* hack!!! we can't have a valid stack pointer otherwise.
+ * but we don't really need it anyway, thread.c only needs it
+ * for overflow detection which doesn't apply for the main thread
+ * (it's managed by the OS) */
+
+ (void)env;
+ (void)this;
+ volatile uintptr_t stack = 0;
+ stackbegin = stackend = &stack;
+ env_ptr = env;
+ RockboxActivity_instance = this;
+ RockboxActivity_class = (*env)->GetObjectClass(env, this);
+ main();
+}
diff --git a/firmware/target/hosted/android/system-target.h b/firmware/target/hosted/android/system-target.h
new file mode 100644
index 0000000000..210d191d6c
--- /dev/null
+++ b/firmware/target/hosted/android/system-target.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#ifndef __SYSTEM_TARGET_H__
+#define __SYSTEM_TARGET_H__
+
+#define disable_irq()
+#define enable_irq()
+#define disable_irq_save() 0
+#define restore_irq(level) (void)level
+
+void power_off(void);
+
+#include
+#define LOG_TAG "Rockbox"
+#define LOG(args...) \
+ __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, ##args);
+
+#endif /* __SYSTEM_TARGET_H__ */
+
+#define NEED_GENERIC_BYTESWAPS
+
diff --git a/firmware/target/hosted/android/thread-android-arm.c b/firmware/target/hosted/android/thread-android-arm.c
new file mode 100644
index 0000000000..baf8b84b65
--- /dev/null
+++ b/firmware/target/hosted/android/thread-android-arm.c
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Thom Johansen
+ * Copyright (C) 2010 by Thomas Martitz (Android-suitable core_sleep())
+ *
+ * Generic ARM threading support
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#include
+/*---------------------------------------------------------------------------
+ * Start the thread running and terminate it if it returns
+ *---------------------------------------------------------------------------
+ */
+static void __attribute__((naked,used)) start_thread(void)
+{
+ /* r0 = context */
+ asm volatile (
+ "ldr sp, [r0, #32] \n" /* Load initial sp */
+ "ldr r4, [r0, #40] \n" /* start in r4 since it's non-volatile */
+ "mov r1, #0 \n" /* Mark thread as running */
+ "str r1, [r0, #40] \n"
+ "mov lr, pc \n" /* Call thread function */
+ "bx r4 \n"
+ ); /* No clobber list - new thread doesn't care */
+ thread_exit();
+}
+
+/* For startup, place context pointer in r4 slot, start_thread pointer in r5
+ * slot, and thread function pointer in context.start. See load_context for
+ * what happens when thread is initially going to run. */
+#define THREAD_STARTUP_INIT(core, thread, function) \
+ ({ (thread)->context.r[0] = (uint32_t)&(thread)->context, \
+ (thread)->context.r[1] = (uint32_t)start_thread, \
+ (thread)->context.start = (uint32_t)function; })
+
+
+/*---------------------------------------------------------------------------
+ * Store non-volatile context.
+ *---------------------------------------------------------------------------
+ */
+static inline void store_context(void* addr)
+{
+ asm volatile(
+ "stmia %0, { r4-r11, sp, lr } \n"
+ : : "r" (addr)
+ );
+}
+
+/*---------------------------------------------------------------------------
+ * Load non-volatile context.
+ *---------------------------------------------------------------------------
+ */
+static inline void load_context(const void* addr)
+{
+ asm volatile(
+ "ldr r0, [%0, #40] \n" /* Load start pointer */
+ "cmp r0, #0 \n" /* Check for NULL */
+
+ /* If not already running, jump to start */
+ "ldmneia %0, { r0, pc } \n"
+ "ldmia %0, { r4-r11, sp, lr } \n" /* Load regs r4 to r14 from context */
+ : : "r" (addr) : "r0" /* only! */
+ );
+}
+
+/*
+ * this core sleep suspends the OS thread rockbox runs under, which greatly
+ * reduces cpu usage (~100% to <10%)
+ *
+ * it returns when the RockboxTimer notified us, i.e. at each tick
+ * (after it called the tick tasks)
+ *
+ * wait_for_interrupt is implemented in kernel-android.c
+ **/
+
+extern void wait_for_interrupt(void);
+static inline void core_sleep(void)
+{
+ wait_for_interrupt();
+}
+
+
diff --git a/firmware/thread.c b/firmware/thread.c
index c00fc36e3f..b3d8ec3970 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -123,8 +123,13 @@ static struct core_entry cores[NUM_CORES] IBSS_ATTR;
struct thread_entry threads[MAXTHREADS] IBSS_ATTR;
static const char main_thread_name[] = "main";
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
extern uintptr_t stackbegin[];
extern uintptr_t stackend[];
+#else
+extern uintptr_t *stackbegin;
+extern uintptr_t *stackend;
+#endif
static inline void core_sleep(IF_COP_VOID(unsigned int core))
__attribute__((always_inline));
@@ -170,7 +175,9 @@ void switch_thread(void)
/****************************************************************************
* Processor-specific section - include necessary core support
*/
-#if defined(CPU_ARM)
+#if defined(ANDROID)
+#include "thread-android-arm.c"
+#elif defined(CPU_ARM)
#include "thread-arm.c"
#if defined (CPU_PP)
#include "thread-pp.c"
@@ -1150,7 +1157,7 @@ void switch_thread(void)
store_context(&thread->context);
/* Check if the current thread stack is overflown */
- if (UNLIKELY(thread->stack[0] != DEADBEEF))
+ if (UNLIKELY(thread->stack[0] != DEADBEEF) && thread->stack_size > 0)
thread_stkov(thread);
#if NUM_CORES > 1
@@ -2319,7 +2326,9 @@ static int stack_usage(uintptr_t *stackptr, size_t stack_size)
*/
int thread_stack_usage(const struct thread_entry *thread)
{
- return stack_usage(thread->stack, thread->stack_size);
+ if (LIKELY(thread->stack_size > 0))
+ return stack_usage(thread->stack, thread->stack_size);
+ return 0;
}
#if NUM_CORES > 1
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index 7a127dea20..094214de72 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -631,6 +631,8 @@ sub runone {
}
else {
unless (".rockbox" eq $rbdir) {
+ mkpath($rbdir);
+ rmtree($rbdir);
move(".rockbox", $rbdir);
print "mv .rockbox $rbdir\n" if $verbose;
}
diff --git a/tools/configure b/tools/configure
index ce23c2a965..7504d562c9 100755
--- a/tools/configure
+++ b/tools/configure
@@ -14,6 +14,7 @@ CCOPTS="-W -Wall -Wundef -O -nostdlib -ffreestanding -Wstrict-prototypes -pipe"
# global LD options for all platforms
GLOBAL_LDOPTS=""
+extradefines=""
use_logf="#undef ROCKBOX_HAS_LOGF"
use_bootchart="#undef DO_BOOTCHART"
@@ -25,7 +26,10 @@ bindir=
libdir=
bindir_full=
libdir_full=
-
+
+app_platform=
+app_lcd_width=
+app_lcd_height=
#
# Begin Function Definitions
#
@@ -47,6 +51,59 @@ prefixtools () {
OC=${prefix}objcopy
}
+app_get_platform() {
+ echo "Select your platform: (S)DL, (A)ndroid (default: Android)"
+ choice=`input`
+ case $choice in
+ s|S*) app_platform="sdl" ;;
+ *|a|A*) app_platform="android" ;;
+ esac
+
+ echo "Selected $app_platform platform"
+ echo "Select the LCD resolution seperated with enter: XxY (default: 320x480)"
+ app_lcd_width=`input`
+ if [ -z "$app_lcd_width" ]; then app_lcd_width="320"; fi
+ app_lcd_height=`input`
+ if [ -z "$app_lcd_height" ]; then app_lcd_height="480"; fi
+ echo "Selected $app_lcd_width x $app_lcd_height resolution"
+
+ app_lcd_width="#define LCD_WIDTH $app_lcd_width"
+ app_lcd_height="#define LCD_HEIGHT $app_lcd_height"
+ # setup files and paths depending on the platform
+ if [ "$app_platform" = "sdl" ]; then
+ if [ -z "$PREFIX" ]; then
+ rbdir="/usr/local/share/rockbox"
+ bindir="/usr/local/bin"
+ bindir_full=$bindir
+ libdir="/usr/local/lib"
+ libdir_full=$libdir
+ else
+ rbdir=`realpath $PREFIX/share/rockbox`
+ bindir="$PREFIX/bin"
+ libdir="$PREFIX/lib"
+ if [ -d bindir ]; then
+ bindir_full=`realpath $bindir`
+ fi
+ if [ -d libdir ]; then
+ libdir_full=`realpath $libdir`
+ fi
+ fi
+ output="rockbox"
+ bootoutput="rockbox"
+ elif [ "$app_platform" = "android" ]; then
+ if [ -n "$PREFIX" ]; then
+ echo "WARNING: PREFIX not supported on Android. You can however use --rbdir"
+ fi
+ rbdir="/data/data/org.rockbox/app_rockbox/rockbox"
+ bindir="/data/data/org.rockbox/lib"
+ bindir_full=$bindir
+ libdir="/data/data/org.rockbox/app_rockbox"
+ libdir_full=$libdir
+ output="librockbox.so"
+ bootoutput="librockbox.so"
+ fi
+}
+
findarmgcc() {
if [ "$ARG_ARM_EABI" != "0" ]; then
prefixtools arm-elf-eabi-
@@ -102,6 +159,15 @@ findsdl(){
done
}
+appcc () {
+ if [ "$1" = "sdl" ]; then
+ simcc "sdl-app"
+ elif [ "$1" = "android" ]; then
+ app_type=$1
+ androidcc
+ fi
+}
+
simcc () {
# default tool setup for native building
@@ -114,15 +180,17 @@ simcc () {
GCCOPTIMIZE=''
LDOPTS='-lm' # button-sdl.c uses sqrt()
- # default output binary name
- output="rockboxui"
+ # default output binary name, don't override app_get_platform()
+ if [ "$app_type" != "sdl-app" ]; then
+ output="rockboxui"
+ fi
# default share option, override below if needed
SHARED_FLAG="-shared"
if [ "$win32crosscompile" = "yes" ]; then
LDOPTS="$LDOPTS -mconsole"
- output="rockboxui.exe"
+ output="$output.exe"
winbuild="yes"
else
case $uname in
@@ -130,7 +198,7 @@ simcc () {
echo "Cygwin host detected"
LDOPTS="$LDOPTS -mconsole"
- output="rockboxui.exe"
+ output="$output.exe"
winbuild="yes"
;;
@@ -138,7 +206,7 @@ simcc () {
echo "MinGW host detected"
LDOPTS="$LDOPTS -mconsole"
- output="rockboxui.exe"
+ output="$output.exe"
winbuild="yes"
;;
@@ -188,6 +256,7 @@ simcc () {
LDOPTS="$LDOPTS `$sdl --libs`"
fi
fi
+
GCCOPTS="$GCCOPTS -I\$(SIMDIR)"
@@ -379,6 +448,18 @@ mipselcc () {
gccchoice="4.1.2"
}
+androidcc () {
+ gccchoice="4.4.0"
+ prefixtools $ANDROID_NDK_PATH/build/prebuilt/linux-x86/arm-eabi-$gccchoice/bin/arm-eabi-
+ GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib// -e s/-Wundef//`
+ GCCOPTS="$GCCOPTS -std=gnu99 -ffunction-sections -fno-short-enums -march=armv5te -mtune=xscale -msoft-float -fomit-frame-pointer"
+ GLOBAL_LDOPTS="$GLOBAL_LDOPTS -nostdlib -lc -Wl,--no-undefined -Wl,--gc-sections -Wl,-z,noexecstack -L$ANDROID_NDK_PATH/build/platforms/android-4/arch-arm/usr/lib/ -Wl,-rpath-link=$ANDROID_NKD_PATH/build/platforms/android-4/arch-arm/usr/lib"
+ LDOPTS="$LDOPTS -shared -nostdlib -lm -ldl -llog"
+ extradefines="$extradefines -DANDROID"
+ endian="little"
+ SHARED_FLAG="-shared"
+}
+
whichadvanced () {
atype=`echo "$1" | cut -c 2-`
##################################################################
@@ -975,7 +1056,7 @@ cat < autoconf.h \
-e "s<@have_backlight@<$have_backlight autoconf.h \
@config_rtc@
@have_rtc_alarm@
+/* lcd dimensions for application builds from configure */
+@lcd_width@
+@lcd_height@
+
/* root of Rockbox */
#define ROCKBOX_DIR "@RBDIR@"
#define ROCKBOX_BINARY_PATH "@binpath@"
@@ -3089,6 +3159,10 @@ if test -n "$t_cpu"; then
TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl/"
TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/"
fi
+ if [ -n "$app_platform" -a "$app_platform" = "android" ]; then
+ # android's gcc doesn't add this :/
+ TARGET_INC="$TARGET_INC -I$ANDROID_NDK_PATH/build/platforms/android-4/arch-arm/usr/include"
+ fi
TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer"
TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu"
GCCOPTS="$GCCOPTS"
diff --git a/uisimulator/common/io.c b/uisimulator/common/io.c
index 260e880b62..4c0fa33be5 100644
--- a/uisimulator/common/io.c
+++ b/uisimulator/common/io.c
@@ -25,7 +25,11 @@
#include
#include
#include
-#ifndef WIN32
+#include "config.h"
+
+#define HAVE_STATVFS (0 == (CONFIG_PLATFORM & PLATFORM_ANDROID) && !defined(WIN32))
+
+#if HAVE_STATVFS
#include
#endif
@@ -41,14 +45,18 @@
#endif
#include
+#if (CONFIG_PLATFORM & PLATFORM_SDL)
#include
#include
+#include "thread-sdl.h"
+#else
+#define sim_thread_unlock() NULL
+#define sim_thread_lock(a)
+#endif
#include "thread.h"
#include "kernel.h"
#include "debug.h"
-#include "config.h"
#include "ata.h" /* for IF_MV2 et al. */
-#include "thread-sdl.h"
#include "rbpaths.h"
/* keep this in sync with file.h! */
@@ -193,7 +201,7 @@ static unsigned int rockbox2sim(int opt)
/** Simulator I/O engine routines **/
#define IO_YIELD_THRESHOLD 512
-enum
+enum io_dir
{
IO_READ,
IO_WRITE,
@@ -225,7 +233,7 @@ int ata_spinup_time(void)
return HZ;
}
-static ssize_t io_trigger_and_wait(int cmd)
+static ssize_t io_trigger_and_wait(enum io_dir cmd)
{
void *mythread = NULL;
ssize_t result;
@@ -246,6 +254,9 @@ static ssize_t io_trigger_and_wait(int cmd)
case IO_WRITE:
result = write(io.fd, io.buf, io.count);
break;
+ /* shut up gcc */
+ default:
+ result = -1;
}
/* Regain our status as current */
@@ -480,7 +491,7 @@ void fat_size(IF_MV2(int volume,) unsigned long* size, unsigned long* free)
if (free)
*free = free_clusters * secperclus / 2 * (bytespersec / 512);
}
-#else
+#elif HAVE_STATVFS
struct statvfs vfs;
if (!statvfs(".", &vfs)) {
@@ -490,9 +501,9 @@ void fat_size(IF_MV2(int volume,) unsigned long* size, unsigned long* free)
*size = vfs.f_blocks / 2 * (vfs.f_frsize / 512);
if (free)
*free = vfs.f_bfree / 2 * (vfs.f_frsize / 512);
- }
+ } else
#endif
- else {
+ {
if (size)
*size = 0;
if (free)
@@ -537,9 +548,19 @@ void *sim_codec_load_ram(char* codecptr, int size, void **pd)
to find an unused filename */
for (codec_count = 0; codec_count < 10; codec_count++)
{
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+ /* we need that path fixed, since get_user_file_path()
+ * gives us the folder on the sdcard where we cannot load libraries
+ * from (no exec permissions)
+ */
+ snprintf(path, sizeof(path),
+ "/data/data/org.rockbox/app_rockbox/libtemp_codec_%d.so",
+ codec_count);
+#else
char name[MAX_PATH];
const char *_name = get_user_file_path(ROCKBOX_DIR, 0, name, sizeof(name));
snprintf(path, sizeof(path), "%s/_temp_codec%d.dll", get_sim_pathname(_name), codec_count);
+#endif
fd = OPEN(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRWXU);
if (fd >= 0)
break; /* Created a file ok */
diff --git a/uisimulator/common/stubs.c b/uisimulator/common/stubs.c
index 6d7d7de06b..a9011b9aa5 100644
--- a/uisimulator/common/stubs.c
+++ b/uisimulator/common/stubs.c
@@ -21,8 +21,6 @@
#include
#include
#include
-#include "thread-sdl.h"
-
#include "debug.h"
#include "screens.h"
@@ -35,7 +33,6 @@
#include "ata.h" /* for volume definitions */
-extern char having_new_lcd;
static bool storage_spinning = false;
#if CONFIG_CODEC != SWCODEC
@@ -211,10 +208,13 @@ bool spdif_powered(void)
}
#endif
+#ifdef ARCHOS_PLAYER
bool is_new_player(void)
{
+ extern char having_new_lcd;
return having_new_lcd;
}
+#endif
#ifdef HAVE_USB_POWER
bool usb_powered(void)
diff --git a/uisimulator/uisimulator.make b/uisimulator/uisimulator.make
index b06b48c0d2..dcbd79988f 100644
--- a/uisimulator/uisimulator.make
+++ b/uisimulator/uisimulator.make
@@ -30,7 +30,6 @@ $(SIMLIB): $$(SIMOBJ) $(UIBMP)
$(SILENT)$(shell rm -f $@)
$(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
-# SIMLIB needs to be linked twice for some reason
$(BUILDDIR)/$(BINARY): $$(OBJ) $(SIMLIB) $(VOICESPEEXLIB) $(FIRMLIB) $(SKINLIB)
$(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(SIMLIB) $(LDOPTS) $(GLOBAL_LDOPTS)
diff --git a/wps/WPSLIST b/wps/WPSLIST
index 3068f48513..938caa13fa 100644
--- a/wps/WPSLIST
+++ b/wps/WPSLIST
@@ -292,6 +292,7 @@ RSBS:
Author: Johannes Voggenthaler, Apoo Maha, Marc Guay, Alex Vanderpol, Jerry Lange, Keith Perri, Mark Fawcus, and Marianne Arnold with support from Rockbox developers and forums. Based on Cabbie by Yohann Misquitta.
# Preferred font (including .fnt extension - leave blank for player):
+Font.320x480x16: 16-Adobe-Helvetica.fnt
Font.320x240x16: 15-Adobe-Helvetica.fnt
Font.240x400x16: 16-Adobe-Helvetica.fnt
Font.240x320x16: 15-Adobe-Helvetica.fnt
@@ -320,6 +321,7 @@ line selector text color: 000000
filetype colours:
#backdrop - remember this is the source file name in your SVN folder, not dest name!
+backdrop.320x480x16: backdrops/cabbiev2.320x480x16.bmp
backdrop.320x240x16: backdrops/cabbiev2.320x240x16.bmp
backdrop.128x128x16: backdrops/cabbiev2.128x128x16.bmp
backdrop.132x80x16: backdrops/cabbiev2.132x80x16.bmp
@@ -333,6 +335,7 @@ backdrop.240x320x16: backdrops/cabbiev2.240x320x16.bmp
backdrop.240x400x16: backdrops/cabbiev2.240x400x16.bmp
#selection bar settings for color targets
+selector type.320x480x16: bar (gradient)
selector type.320x240x16: bar (gradient)
selector type.128x128x16: bar (gradient)
selector type.132x80x16: bar (gradient)
@@ -346,6 +349,7 @@ selector type.160x128x2: bar (inverse)
selector type.138x110x2: bar (inverse)
#icons
+iconset.320x480x16: icons/tango_small.bmp
iconset.320x240x16: icons/tango_small.bmp
iconset.128x128x16: icons/tango_small.bmp
iconset.132x80x16: icons/tango_small.bmp
@@ -359,6 +363,7 @@ iconset.240x320x16: icons/tango_small.bmp
iconset.240x400x16: icons/tango_small.bmp
#viewer icons
+viewers iconset.320x480x16: icons/tango_small_viewers.bmp
viewers iconset.320x240x16: icons/tango_small_viewers.bmp
viewers iconset.128x128x16: icons/tango_small_viewers.bmp
viewers iconset.132x80x16: icons/tango_small_viewers.bmp
diff --git a/wps/cabbiev2.320x480x16.wps b/wps/cabbiev2.320x480x16.wps
new file mode 100644
index 0000000000..a64fa6fcf7
--- /dev/null
+++ b/wps/cabbiev2.320x480x16.wps
@@ -0,0 +1,79 @@
+# cabbie 2.0
+# (C) 2007, Johannes Voggenthaler (Zinc Alloy)
+# (C) 2009, Maurus Cuelenaere (mcuelenaere) ported to Onda VX747
+# derived from "cabbie" (C) Yohann Misquitta
+
+%wd
+%X(wpsbackdrop-240x400x16.bmp)
+%Cl(55,50,130,130,c,c)
+%pb(22,284,199,13,pb-240x320x16.bmp)
+%T(22,284,199,13,progressbar)
+%T(90,238,60,20,playlist)
+%?Tl(2.5)<%Vd(t)|%Vd(u)>
+%V(0,0,240,330,1)
+
+
+%?C<|>
+%?C<|>
+%?C<|%s%ac%?it<%it|%fn>>
+%?C<|%s%ac%?ia<%ia|%?d(2)<%d(2)|%(root%)>>>
+%?C<|%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>>
+%?C<|%ac%?iy<%iy|>>
+%?C<|>
+%?C<|%ac%?ig<%ig|>>
+%?C<|%ac%?fv<%(vbr%) |>%fb kbit/s %fc>
+%?C<|>
+%?C<%s%ac%?it<%it|%fn>|>
+%?C<%s%ac%?ia<%ia|%?d(2)<%d(2)|%(root%)>>|%ac%Sx(Next Track:)>
+%?C<%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>|%ac%s%?It<%It|%Fn>>
+%?C<|%s%ac%?Ia<%Ia|%?D(2)<%D(2)|%(root%)>>>
+%?C<%s%ac%Sx(Next:) %?Ia<%Ia|%?D(2)<%D(2)|%(root%)>> - %?It<%It|%Fn>|%s%ac%?Id<%Id|%?D(1)<%D(1)|%(root%)>>>
+
+
+ %pc%ac%?Sr<%pe %Sx(of) %pp|%pp %Sx(of) %pe>%ar%pr
+
+%?C<%Cd>
+
+%xl(A,lock-240x320x16.bmp,11,0,2)
+%xl(B,battery-240x320x16.bmp,46,0,10)
+%xl(C,volume-240x320x16.bmp,98,0,10)
+%xl(D,shuffle-240x320x16.bmp,139,0)
+%xl(E,repeat-240x320x16.bmp,182,0,4)
+%xl(F,playmode-240x320x16.bmp,206,0,5)
+
+%V(0,372,240,-,1)
+%?mh<%xd(Aa)|%xd(Ab)>
+%?bp<%?bc<%xd(Ba)|%xd(Bb)>|%?bl<|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)>>
+%?pv<%xd(Ca)|%xd(Cb)|%xd(Cc)|%xd(Cd)|%xd(Ce)|%xd(Cf)|%xd(Cg)|%xd(Ch)|%xd(Ci)|%xd(Cj)>
+%?ps<%xd(D)>
+%?mm<|%xd(Ea)|%xd(Eb)|%xd(Ec)|%xd(Ed)>
+%?mp<%xd(Fa)|%xd(Fb)|%xd(Fc)|%xd(Fd)|%xd(Fe)>
+
+%T(206,0,24,24,play)
+%T(206,0,24,24,&stop)
+%T(182,0,18,92,repmode)
+%T(139,0,37,23,shuffle)
+%T(98,0,33,23,volume)
+
+#viewport for the touch icons
+%xl(G,browser-320x240x16.bmp,0,0)
+%xl(I,pitch-320x240x16.bmp,39,0)
+%xl(H,context-320x240x16.bmp,58,0)
+%xl(J,quick-320x240x16.bmp,86,0)
+%xl(K,rew-320x240x16.bmp,115,0)
+%xl(L,ff-320x240x16.bmp,144,0)
+
+%Vl(t,70,335,-,30,1)
+%xd(G) %xd(H) %xd(I) %xd(J) %xd(K) %xd(L)
+%T(0,0,37,24,browse)
+%T(39,5,24,24,pitch)
+%T(58,0,24,24,contextmenu)
+%T(86,0,24,24,quickscreen)
+%T(115,0,24,23,&rwd)
+%T(144,0,24,23,&ffwd)
+%T(115,0,24,23,prev)
+%T(144,0,24,23,next)
+
+%Vl(u,70,335,-,30,1)
+#purposely left blank
+
diff --git a/wps/cabbiev2/wpsbackdrop-320x480x16.bmp b/wps/cabbiev2/wpsbackdrop-320x480x16.bmp
new file mode 100644
index 0000000000..3278c0d965
Binary files /dev/null and b/wps/cabbiev2/wpsbackdrop-320x480x16.bmp differ