diff options
Diffstat (limited to 'android')
-rw-r--r-- | android/.classpath | 7 | ||||
-rw-r--r-- | android/.project | 33 | ||||
-rw-r--r-- | android/AndroidManifest.xml | 18 | ||||
-rw-r--r-- | android/README | 34 | ||||
-rw-r--r-- | android/default.properties | 11 | ||||
-rw-r--r-- | android/gen/org/rockbox/R.java | 22 | ||||
-rw-r--r-- | android/res/drawable-hdpi/icon.png | bin | 0 -> 4147 bytes | |||
-rw-r--r-- | android/res/drawable-ldpi/icon.png | bin | 0 -> 1723 bytes | |||
-rw-r--r-- | android/res/drawable-mdpi/icon.png | bin | 0 -> 2574 bytes | |||
-rw-r--r-- | android/res/layout/main.xml | 7 | ||||
-rw-r--r-- | android/res/values/strings.xml | 5 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxActivity.java | 148 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxFramebuffer.java | 98 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxPCM.java | 155 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxTimer.java | 93 |
15 files changed, 631 insertions, 0 deletions
diff --git a/android/.classpath b/android/.classpath new file mode 100644 index 0000000000..6efcbb739a --- /dev/null +++ b/android/.classpath | |||
@@ -0,0 +1,7 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <classpath> | ||
3 | <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> | ||
4 | <classpathentry kind="src" path="src"/> | ||
5 | <classpathentry kind="src" path="gen"/> | ||
6 | <classpathentry kind="output" path="bin"/> | ||
7 | </classpath> | ||
diff --git a/android/.project b/android/.project new file mode 100644 index 0000000000..7e8d136317 --- /dev/null +++ b/android/.project | |||
@@ -0,0 +1,33 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <projectDescription> | ||
3 | <name>Rockbox</name> | ||
4 | <comment></comment> | ||
5 | <projects> | ||
6 | </projects> | ||
7 | <buildSpec> | ||
8 | <buildCommand> | ||
9 | <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> | ||
10 | <arguments> | ||
11 | </arguments> | ||
12 | </buildCommand> | ||
13 | <buildCommand> | ||
14 | <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> | ||
15 | <arguments> | ||
16 | </arguments> | ||
17 | </buildCommand> | ||
18 | <buildCommand> | ||
19 | <name>org.eclipse.jdt.core.javabuilder</name> | ||
20 | <arguments> | ||
21 | </arguments> | ||
22 | </buildCommand> | ||
23 | <buildCommand> | ||
24 | <name>com.android.ide.eclipse.adt.ApkBuilder</name> | ||
25 | <arguments> | ||
26 | </arguments> | ||
27 | </buildCommand> | ||
28 | </buildSpec> | ||
29 | <natures> | ||
30 | <nature>com.android.ide.eclipse.adt.AndroidNature</nature> | ||
31 | <nature>org.eclipse.jdt.core.javanature</nature> | ||
32 | </natures> | ||
33 | </projectDescription> | ||
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 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | package="org.rockbox" | ||
4 | android:versionCode="1" | ||
5 | android:versionName="1.0"> | ||
6 | <application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true"> | ||
7 | <activity android:name=".RockboxActivity" | ||
8 | android:label="@string/app_name"> | ||
9 | <intent-filter> | ||
10 | <action android:name="android.intent.action.MAIN" /> | ||
11 | <category android:name="android.intent.category.LAUNCHER" /> | ||
12 | </intent-filter> | ||
13 | </activity> | ||
14 | |||
15 | </application> | ||
16 | <uses-sdk android:minSdkVersion="4" /> | ||
17 | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> | ||
18 | </manifest> \ 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 @@ | |||
1 | This folder contains the java parts needed to build an Rockbox as an | ||
2 | application for android. | ||
3 | |||
4 | * Build instructions | ||
5 | |||
6 | Until there's a script which does all the work the procedure is documented here. | ||
7 | |||
8 | First, make sure you have the ANDROID_NDK_PATH environment variable set up, | ||
9 | otherwise configure will fail to find the compiler. | ||
10 | |||
11 | Use this as your build folder, using '../tools/configure' etc. | ||
12 | $ ../tools/configure | ||
13 | $ make | ||
14 | |||
15 | After the build finished, you need to copy librockbox.so to libs/armeabi/. | ||
16 | $ cp librockbox.so libs/armeabi | ||
17 | |||
18 | For the other files (codecs, themes), you execute 'make zip'. Then you copy the | ||
19 | zip to libs/armeabi, using the name libmisc.so. This is needed, since there's no | ||
20 | way to bundle stuff into apk's and have access to them from native code other | ||
21 | than pretending it was a library. | ||
22 | $ make zip | ||
23 | $ cp rockbox.zip lib/armeabi/libmisc.so | ||
24 | |||
25 | rockbox.zip..err, libmisc.so will be unpacked at runtime. | ||
26 | |||
27 | To finish, you can follow this guide [1], or use eclipse. Simply install eclipse | ||
28 | and the android plugins, then import this folder as a new Android project and run it. | ||
29 | See [2] for a guide on how to set up eclipse for android development. | ||
30 | |||
31 | |||
32 | |||
33 | [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/ | ||
34 | [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 @@ | |||
1 | # This file is automatically generated by Android Tools. | ||
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! | ||
3 | # | ||
4 | # This file must be checked in Version Control Systems. | ||
5 | # | ||
6 | # To customize properties used by the Ant build system use, | ||
7 | # "build.properties", and override values to adapt the script to your | ||
8 | # project structure. | ||
9 | |||
10 | # Project target. | ||
11 | 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 @@ | |||
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY. | ||
2 | * | ||
3 | * This class was automatically generated by the | ||
4 | * aapt tool from the resource data it found. It | ||
5 | * should not be modified by hand. | ||
6 | */ | ||
7 | |||
8 | package org.rockbox; | ||
9 | |||
10 | public final class R { | ||
11 | public static final class attr { | ||
12 | } | ||
13 | public static final class drawable { | ||
14 | public static final int icon=0x7f020000; | ||
15 | } | ||
16 | public static final class layout { | ||
17 | public static final int main=0x7f030000; | ||
18 | } | ||
19 | public static final class string { | ||
20 | public static final int app_name=0x7f040000; | ||
21 | } | ||
22 | } | ||
diff --git a/android/res/drawable-hdpi/icon.png b/android/res/drawable-hdpi/icon.png new file mode 100644 index 0000000000..8074c4c571 --- /dev/null +++ b/android/res/drawable-hdpi/icon.png | |||
Binary files differ | |||
diff --git a/android/res/drawable-ldpi/icon.png b/android/res/drawable-ldpi/icon.png new file mode 100644 index 0000000000..1095584ec2 --- /dev/null +++ b/android/res/drawable-ldpi/icon.png | |||
Binary files differ | |||
diff --git a/android/res/drawable-mdpi/icon.png b/android/res/drawable-mdpi/icon.png new file mode 100644 index 0000000000..a07c69fa5a --- /dev/null +++ b/android/res/drawable-mdpi/icon.png | |||
Binary files 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 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
3 | android:orientation="vertical" | ||
4 | android:layout_width="fill_parent" | ||
5 | android:layout_height="fill_parent" | ||
6 | > | ||
7 | </LinearLayout> | ||
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 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <resources> | ||
3 | |||
4 | <string name="app_name">Rockbox</string> | ||
5 | </resources> | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | package org.rockbox; | ||
23 | |||
24 | import java.io.BufferedInputStream; | ||
25 | import java.io.BufferedOutputStream; | ||
26 | import java.io.File; | ||
27 | import java.io.FileOutputStream; | ||
28 | import java.util.Enumeration; | ||
29 | import java.util.zip.ZipEntry; | ||
30 | import java.util.zip.ZipFile; | ||
31 | |||
32 | import android.app.Activity; | ||
33 | import android.graphics.Rect; | ||
34 | import android.os.Bundle; | ||
35 | import android.util.Log; | ||
36 | import android.view.Window; | ||
37 | import android.view.WindowManager; | ||
38 | |||
39 | public class RockboxActivity extends Activity { | ||
40 | /** Called when the activity is first created. */ | ||
41 | public RockboxFramebuffer fb; | ||
42 | private Thread rb; | ||
43 | static final int BUFFER = 2048; | ||
44 | /** Called when the activity is first created. */ | ||
45 | @Override | ||
46 | public void onCreate(Bundle savedInstanceState) { | ||
47 | super.onCreate(savedInstanceState); | ||
48 | LOG("start rb"); | ||
49 | requestWindowFeature(Window.FEATURE_NO_TITLE); | ||
50 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN | ||
51 | ,WindowManager.LayoutParams.FLAG_FULLSCREEN); | ||
52 | fb = new RockboxFramebuffer(this); | ||
53 | if (true) { | ||
54 | try | ||
55 | { | ||
56 | BufferedOutputStream dest = null; | ||
57 | BufferedInputStream is = null; | ||
58 | ZipEntry entry; | ||
59 | File file = new File("/data/data/org.rockbox/lib/libmisc.so"); | ||
60 | /* use arbitary file to determine whether extracting is needed */ | ||
61 | File file2 = new File("/data/data/org.rockbox/app_rockbox/rockbox/codecs/mpa.codec"); | ||
62 | if (!file2.exists() || (file.lastModified() > file2.lastModified())) | ||
63 | { | ||
64 | ZipFile zipfile = new ZipFile(file); | ||
65 | Enumeration<? extends ZipEntry> e = zipfile.entries(); | ||
66 | File folder; | ||
67 | while(e.hasMoreElements()) { | ||
68 | entry = (ZipEntry) e.nextElement(); | ||
69 | LOG("Extracting: " +entry); | ||
70 | if (entry.isDirectory()) | ||
71 | { | ||
72 | folder = new File(entry.getName()); | ||
73 | LOG("mkdir "+ entry); | ||
74 | try { | ||
75 | folder.mkdirs(); | ||
76 | } catch (SecurityException ex){ | ||
77 | LOG(ex.getMessage()); | ||
78 | } | ||
79 | continue; | ||
80 | } | ||
81 | is = new BufferedInputStream(zipfile.getInputStream(entry)); | ||
82 | int count; | ||
83 | byte data[] = new byte[BUFFER]; | ||
84 | folder = new File(new File(entry.getName()).getParent()); | ||
85 | LOG("" + folder.getAbsolutePath()); | ||
86 | if (!folder.exists()) | ||
87 | folder.mkdirs(); | ||
88 | FileOutputStream fos = new FileOutputStream(entry.getName()); | ||
89 | dest = new BufferedOutputStream(fos, BUFFER); | ||
90 | while ((count = is.read(data, 0, BUFFER)) != -1) { | ||
91 | dest.write(data, 0, count); | ||
92 | } | ||
93 | dest.flush(); | ||
94 | dest.close(); | ||
95 | is.close(); | ||
96 | } | ||
97 | } | ||
98 | } catch(Exception e) { | ||
99 | e.printStackTrace(); | ||
100 | }} | ||
101 | Rect r = new Rect(); | ||
102 | fb.getDrawingRect(r); | ||
103 | LOG(r.left + " " + r.top + " " + r.right + " " + r.bottom); | ||
104 | rb = new Thread(new Runnable() | ||
105 | { | ||
106 | public void run() | ||
107 | { | ||
108 | main(); | ||
109 | } | ||
110 | },"Rockbox thread"); | ||
111 | System.loadLibrary("rockbox"); | ||
112 | rb.setDaemon(false); | ||
113 | setContentView(fb); | ||
114 | } | ||
115 | |||
116 | private void LOG(CharSequence text) | ||
117 | { | ||
118 | Log.d("RockboxBootloader", (String) text); | ||
119 | } | ||
120 | |||
121 | public synchronized void onStart() | ||
122 | { | ||
123 | super.onStart(); | ||
124 | if (!rb.isAlive()) | ||
125 | rb.start(); | ||
126 | } | ||
127 | |||
128 | public void onPause() | ||
129 | { | ||
130 | super.onPause(); | ||
131 | } | ||
132 | |||
133 | public void onResume() | ||
134 | { | ||
135 | super.onResume(); | ||
136 | switch (rb.getState()) { | ||
137 | case BLOCKED: LOG("BLOCKED"); break; | ||
138 | case RUNNABLE: LOG("RUNNABLE"); break; | ||
139 | case NEW: LOG("NEW"); break; | ||
140 | case TERMINATED: LOG("TERMINATED"); break; | ||
141 | case TIMED_WAITING: LOG("TIMED_WAITING"); break; | ||
142 | case WAITING: LOG("WAITING"); break; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | |||
147 | private native void main(); | ||
148 | } \ 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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | package org.rockbox; | ||
23 | |||
24 | import java.nio.ByteBuffer; | ||
25 | import android.content.Context; | ||
26 | import android.graphics.Bitmap; | ||
27 | import android.graphics.Canvas; | ||
28 | import android.os.Handler; | ||
29 | import android.util.Log; | ||
30 | import android.view.MotionEvent; | ||
31 | import android.view.View; | ||
32 | |||
33 | public class RockboxFramebuffer extends View | ||
34 | { | ||
35 | private Bitmap btm; | ||
36 | private ByteBuffer native_buf; | ||
37 | private Handler update_handler; | ||
38 | private Runnable cb; | ||
39 | |||
40 | |||
41 | public RockboxFramebuffer(Context c) | ||
42 | { | ||
43 | super(c); | ||
44 | update_handler = new Handler(); | ||
45 | cb = new Runnable() { | ||
46 | public void run() | ||
47 | { | ||
48 | btm.copyPixelsFromBuffer(native_buf); | ||
49 | invalidate(); | ||
50 | } | ||
51 | }; | ||
52 | btm = null; | ||
53 | } | ||
54 | |||
55 | public void onDraw(Canvas c) | ||
56 | { | ||
57 | if (btm != null) | ||
58 | c.drawBitmap(btm, 0.0f, 0.0f, null); | ||
59 | } | ||
60 | |||
61 | public void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb) | ||
62 | { | ||
63 | btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565); | ||
64 | native_buf = native_fb; | ||
65 | } | ||
66 | |||
67 | public void java_lcd_update() | ||
68 | { | ||
69 | update_handler.post(cb); | ||
70 | } | ||
71 | |||
72 | private void LOG(CharSequence text) | ||
73 | { | ||
74 | Log.d("RockboxBootloader", (String) text); | ||
75 | } | ||
76 | |||
77 | public boolean onTouchEvent(MotionEvent me) | ||
78 | { | ||
79 | LOG("onTouchEvent"); | ||
80 | switch (me.getAction()) | ||
81 | { | ||
82 | case MotionEvent.ACTION_CANCEL: | ||
83 | case MotionEvent.ACTION_UP: | ||
84 | touchHandler(0); | ||
85 | break; | ||
86 | case MotionEvent.ACTION_MOVE: | ||
87 | case MotionEvent.ACTION_DOWN: | ||
88 | touchHandler(1); | ||
89 | break; | ||
90 | |||
91 | } | ||
92 | pixelHandler((int)me.getX(), (int)me.getY()); | ||
93 | return true; | ||
94 | } | ||
95 | |||
96 | public native void pixelHandler(int x, int y); | ||
97 | public native void touchHandler(int down); | ||
98 | } | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | package org.rockbox; | ||
23 | |||
24 | import android.media.AudioFormat; | ||
25 | import android.media.AudioManager; | ||
26 | import android.media.AudioTrack; | ||
27 | import android.util.Log; | ||
28 | |||
29 | public class RockboxPCM extends AudioTrack | ||
30 | { | ||
31 | byte[] raw_data; | ||
32 | |||
33 | private void LOG(CharSequence text) | ||
34 | { | ||
35 | Log.d("RockboxBootloader", (String) text); | ||
36 | } | ||
37 | |||
38 | public RockboxPCM() | ||
39 | { | ||
40 | super(AudioManager.STREAM_MUSIC, | ||
41 | 44100, | ||
42 | /* should be CHANNEL_OUT_STEREO in 2.0 and above */ | ||
43 | AudioFormat.CHANNEL_CONFIGURATION_STEREO, | ||
44 | AudioFormat.ENCODING_PCM_16BIT, | ||
45 | 24<<10, | ||
46 | AudioTrack.MODE_STREAM); | ||
47 | int buf_len = 24<<10; | ||
48 | |||
49 | raw_data = new byte[buf_len*2]; | ||
50 | for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00; | ||
51 | /* fill with silence */ | ||
52 | write(raw_data, 0, raw_data.length); | ||
53 | if (getState() == AudioTrack.STATE_INITIALIZED) | ||
54 | { | ||
55 | if (setNotificationMarkerPosition(bytes2frames(buf_len*2)/4) != AudioTrack.SUCCESS) | ||
56 | LOG("setNotificationMarkerPosition Error"); | ||
57 | setPlaybackPositionUpdateListener(new PCMListener(buf_len*2)); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | |||
62 | |||
63 | int bytes2frames(int bytes) { | ||
64 | /* 1 sample is 2 bytes, 2 samples are 1 frame */ | ||
65 | return (bytes/4); | ||
66 | } | ||
67 | |||
68 | int frames2bytes(int frames) { | ||
69 | /* 1 frame is 2 samples, 1 sample is 2 bytes */ | ||
70 | return (frames*4); | ||
71 | } | ||
72 | |||
73 | @SuppressWarnings("unused") | ||
74 | private void play_pause(boolean pause) { | ||
75 | LOG("play_pause()"); | ||
76 | if (pause) | ||
77 | pause(); | ||
78 | else | ||
79 | { | ||
80 | if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED) | ||
81 | { | ||
82 | for(int i = 0; i < raw_data.length; i++) raw_data[i] = (byte) 0x00; | ||
83 | LOG("Writing silence"); | ||
84 | /* fill with silence */ | ||
85 | write(raw_data, 0, raw_data.length); | ||
86 | } | ||
87 | play(); | ||
88 | } | ||
89 | LOG("play_pause() return"); | ||
90 | } | ||
91 | |||
92 | @SuppressWarnings("unused") | ||
93 | private void set_volume(int volume) | ||
94 | { | ||
95 | /* volume comes from 0..-990 from Rockbox */ | ||
96 | /* TODO volume is in dB, but this code acts as if it were in %, convert? */ | ||
97 | float fvolume; | ||
98 | /* special case min and max volume to not suffer from floating point accuracy */ | ||
99 | if (volume == 0) | ||
100 | fvolume = 1.0f; | ||
101 | else if (volume == -990) | ||
102 | fvolume = 0.0f; | ||
103 | else | ||
104 | fvolume = (volume + 990)/990.0f; | ||
105 | setStereoVolume(fvolume, fvolume); | ||
106 | } | ||
107 | |||
108 | public native void pcmSamplesToByteArray(byte[] dest); | ||
109 | |||
110 | private class PCMListener implements OnPlaybackPositionUpdateListener { | ||
111 | int max_len; | ||
112 | byte[] buf; | ||
113 | public PCMListener(int len) { | ||
114 | max_len = len; | ||
115 | buf = new byte[len/2]; | ||
116 | } | ||
117 | @Override | ||
118 | public void onMarkerReached(AudioTrack track) { | ||
119 | // push new data to the hardware | ||
120 | int result = 1; | ||
121 | pcmSamplesToByteArray(buf); | ||
122 | //LOG("Trying to write " + buf.length + " bytes"); | ||
123 | result = track.write(buf, 0, buf.length); | ||
124 | if (result > 0) | ||
125 | { | ||
126 | //LOG(result + " bytes written"); | ||
127 | track.setPlaybackPositionUpdateListener(this); | ||
128 | track.setNotificationMarkerPosition(bytes2frames(max_len)/4); | ||
129 | switch(track.getPlayState()) | ||
130 | { | ||
131 | case AudioTrack.PLAYSTATE_PLAYING: | ||
132 | //LOG("State PLAYING"); | ||
133 | break; | ||
134 | case AudioTrack.PLAYSTATE_PAUSED: | ||
135 | LOG("State PAUSED"); | ||
136 | break; | ||
137 | case AudioTrack.PLAYSTATE_STOPPED: | ||
138 | LOG("State STOPPED"); | ||
139 | break; | ||
140 | } | ||
141 | } | ||
142 | else | ||
143 | { | ||
144 | LOG("Error in onMarkerReached"); | ||
145 | track.stop(); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | @Override | ||
150 | public void onPeriodicNotification(AudioTrack track) { | ||
151 | // TODO Auto-generated method stub | ||
152 | |||
153 | } | ||
154 | } | ||
155 | } | ||
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 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2010 Thomas Martitz | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | package org.rockbox; | ||
23 | |||
24 | import java.util.Timer; | ||
25 | import java.util.TimerTask; | ||
26 | |||
27 | import android.util.Log; | ||
28 | |||
29 | public class RockboxTimer extends Timer | ||
30 | { | ||
31 | RockboxTimerTask task; | ||
32 | long interval; | ||
33 | |||
34 | private class RockboxTimerTask extends TimerTask { | ||
35 | private RockboxTimer t; | ||
36 | public RockboxTimerTask(RockboxTimer parent) { | ||
37 | super(); | ||
38 | t = parent; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public void run() { | ||
43 | timerTask(); | ||
44 | synchronized(t) { | ||
45 | t.notify(); | ||
46 | } | ||
47 | } | ||
48 | } | ||
49 | |||
50 | public void pause() | ||
51 | { | ||
52 | cancel(); | ||
53 | } | ||
54 | public void resume() | ||
55 | { | ||
56 | try { | ||
57 | schedule(task, 0, interval); | ||
58 | } catch (IllegalStateException e) { | ||
59 | /* not an error */ | ||
60 | } catch (Exception e) { | ||
61 | LOG(e.toString()); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | public RockboxTimer(long period_inverval_in_ms) | ||
66 | { | ||
67 | super("tick timer", false); | ||
68 | task = new RockboxTimerTask(this); | ||
69 | schedule(task, 0, period_inverval_in_ms); | ||
70 | interval = period_inverval_in_ms; | ||
71 | } | ||
72 | |||
73 | private void LOG(CharSequence text) | ||
74 | { | ||
75 | Log.d("RockboxBootloader", (String) text); | ||
76 | } | ||
77 | |||
78 | |||
79 | /* methods called from native, keep them simple */ | ||
80 | public void java_wait_for_interrupt() | ||
81 | { | ||
82 | synchronized(this) { | ||
83 | try { | ||
84 | this.wait(); | ||
85 | } catch (InterruptedException e) { | ||
86 | /* wakeup and return */ | ||
87 | } catch (Exception e) { | ||
88 | LOG(e.toString()); | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | public native void timerTask(); | ||
93 | } | ||