diff options
-rw-r--r-- | android/src/org/rockbox/Helper/MediaButtonReceiver.java | 17 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxActivity.java | 31 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxFramebuffer.java | 2 | ||||
-rw-r--r-- | android/src/org/rockbox/RockboxService.java | 113 | ||||
-rw-r--r-- | apps/main.c | 1 | ||||
-rw-r--r-- | firmware/target/hosted/android/button-android.c | 8 | ||||
-rw-r--r-- | firmware/target/hosted/android/lcd-android.c | 99 |
7 files changed, 123 insertions, 148 deletions
diff --git a/android/src/org/rockbox/Helper/MediaButtonReceiver.java b/android/src/org/rockbox/Helper/MediaButtonReceiver.java index 3749cec32a..a57bdd4831 100644 --- a/android/src/org/rockbox/Helper/MediaButtonReceiver.java +++ b/android/src/org/rockbox/Helper/MediaButtonReceiver.java | |||
@@ -22,9 +22,8 @@ | |||
22 | package org.rockbox.Helper; | 22 | package org.rockbox.Helper; |
23 | 23 | ||
24 | import java.lang.reflect.Method; | 24 | import java.lang.reflect.Method; |
25 | 25 | import org.rockbox.RockboxFramebuffer; | |
26 | import org.rockbox.RockboxService; | 26 | import org.rockbox.RockboxService; |
27 | |||
28 | import android.content.BroadcastReceiver; | 27 | import android.content.BroadcastReceiver; |
29 | import android.content.ComponentName; | 28 | import android.content.ComponentName; |
30 | import android.content.Context; | 29 | import android.content.Context; |
@@ -73,7 +72,12 @@ public class MediaButtonReceiver | |||
73 | 72 | ||
74 | /* helper class for the manifest */ | 73 | /* helper class for the manifest */ |
75 | public static class MediaReceiver extends BroadcastReceiver | 74 | public static class MediaReceiver extends BroadcastReceiver |
76 | { | 75 | { |
76 | private void startService(Context c, Intent baseIntent) | ||
77 | { | ||
78 | baseIntent.setClass(c, RockboxService.class); | ||
79 | c.startService(baseIntent); | ||
80 | } | ||
77 | @Override | 81 | @Override |
78 | public void onReceive(Context context, Intent intent) | 82 | public void onReceive(Context context, Intent intent) |
79 | { | 83 | { |
@@ -81,8 +85,11 @@ public class MediaButtonReceiver | |||
81 | { | 85 | { |
82 | KeyEvent key = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); | 86 | KeyEvent key = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); |
83 | if (key.getAction() == KeyEvent.ACTION_UP) | 87 | if (key.getAction() == KeyEvent.ACTION_UP) |
84 | { /* pass the pressed key to Rockbox */ | 88 | { /* pass the pressed key to Rockbox, starting it if needed */ |
85 | if (RockboxService.get_instance().get_fb().dispatchKeyEvent(key)) | 89 | RockboxService s = RockboxService.get_instance(); |
90 | if (s == null || !s.isRockboxRunning()) | ||
91 | startService(context, intent); | ||
92 | else if (RockboxFramebuffer.buttonHandler(key.getKeyCode(), false)) | ||
86 | abortBroadcast(); | 93 | abortBroadcast(); |
87 | } | 94 | } |
88 | } | 95 | } |
diff --git a/android/src/org/rockbox/RockboxActivity.java b/android/src/org/rockbox/RockboxActivity.java index 90c687f35a..65c7f92bbe 100644 --- a/android/src/org/rockbox/RockboxActivity.java +++ b/android/src/org/rockbox/RockboxActivity.java | |||
@@ -29,16 +29,12 @@ import android.os.Bundle; | |||
29 | import android.os.Handler; | 29 | import android.os.Handler; |
30 | import android.os.ResultReceiver; | 30 | import android.os.ResultReceiver; |
31 | import android.util.Log; | 31 | import android.util.Log; |
32 | import android.view.View; | ||
33 | import android.view.ViewGroup; | ||
34 | import android.view.Window; | 32 | import android.view.Window; |
35 | import android.view.WindowManager; | 33 | import android.view.WindowManager; |
36 | import android.widget.Toast; | 34 | import android.widget.Toast; |
37 | 35 | ||
38 | public class RockboxActivity extends Activity | 36 | public class RockboxActivity extends Activity |
39 | { | 37 | { |
40 | private RockboxService rbservice; | ||
41 | |||
42 | /** Called when the activity is first created. */ | 38 | /** Called when the activity is first created. */ |
43 | @Override | 39 | @Override |
44 | public void onCreate(Bundle savedInstanceState) | 40 | public void onCreate(Bundle savedInstanceState) |
@@ -79,9 +75,7 @@ public class RockboxActivity extends Activity | |||
79 | loadingdialog.setProgress(resultData.getInt("value", 0)); | 75 | loadingdialog.setProgress(resultData.getInt("value", 0)); |
80 | break; | 76 | break; |
81 | case RockboxService.RESULT_SERVICE_RUNNING: | 77 | case RockboxService.RESULT_SERVICE_RUNNING: |
82 | rbservice = RockboxService.get_instance(); | ||
83 | setServiceActivity(true); | 78 | setServiceActivity(true); |
84 | attachFramebuffer(); | ||
85 | break; | 79 | break; |
86 | case RockboxService.RESULT_ERROR_OCCURED: | 80 | case RockboxService.RESULT_ERROR_OCCURED: |
87 | Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG); | 81 | Toast.makeText(RockboxActivity.this, resultData.getString("error"), Toast.LENGTH_LONG); |
@@ -89,38 +83,21 @@ public class RockboxActivity extends Activity | |||
89 | } | 83 | } |
90 | } | 84 | } |
91 | }); | 85 | }); |
86 | setContentView(new RockboxFramebuffer(this)); | ||
92 | startService(intent); | 87 | startService(intent); |
93 | } | 88 | } |
94 | 89 | ||
95 | private void setServiceActivity(boolean set) | 90 | private void setServiceActivity(boolean set) |
96 | { | 91 | { |
97 | if (rbservice != null) | 92 | RockboxService s = RockboxService.get_instance(); |
98 | rbservice.set_activity(set ? this : null); | 93 | if (s != null) |
99 | } | 94 | s.set_activity(set ? this : null); |
100 | |||
101 | private void attachFramebuffer() | ||
102 | { | ||
103 | View rbFramebuffer = null; | ||
104 | try { | ||
105 | rbFramebuffer = rbservice.get_fb(); | ||
106 | setContentView(rbFramebuffer); | ||
107 | } catch (IllegalStateException e) { | ||
108 | /* we are already using the View, | ||
109 | * need to remove it and re-attach it */ | ||
110 | ViewGroup g = (ViewGroup) rbFramebuffer.getParent(); | ||
111 | g.removeView(rbFramebuffer); | ||
112 | setContentView(rbFramebuffer); | ||
113 | } catch (NullPointerException e) { | ||
114 | return; | ||
115 | } | ||
116 | rbFramebuffer.requestFocus(); | ||
117 | } | 95 | } |
118 | 96 | ||
119 | public void onResume() | 97 | public void onResume() |
120 | { | 98 | { |
121 | super.onResume(); | 99 | super.onResume(); |
122 | setVisible(true); | 100 | setVisible(true); |
123 | attachFramebuffer(); | ||
124 | } | 101 | } |
125 | 102 | ||
126 | /* this is also called when the backlight goes off, | 103 | /* this is also called when the backlight goes off, |
diff --git a/android/src/org/rockbox/RockboxFramebuffer.java b/android/src/org/rockbox/RockboxFramebuffer.java index 037fd2db85..a17bc90ab6 100644 --- a/android/src/org/rockbox/RockboxFramebuffer.java +++ b/android/src/org/rockbox/RockboxFramebuffer.java | |||
@@ -148,7 +148,7 @@ public class RockboxFramebuffer extends SurfaceView | |||
148 | } | 148 | } |
149 | 149 | ||
150 | private native void touchHandler(boolean down, int x, int y); | 150 | private native void touchHandler(boolean down, int x, int y); |
151 | private native static boolean buttonHandler(int keycode, boolean state); | 151 | public native static boolean buttonHandler(int keycode, boolean state); |
152 | 152 | ||
153 | public native void surfaceCreated(SurfaceHolder holder); | 153 | public native void surfaceCreated(SurfaceHolder holder); |
154 | public native void surfaceDestroyed(SurfaceHolder holder); | 154 | public native void surfaceDestroyed(SurfaceHolder holder); |
diff --git a/android/src/org/rockbox/RockboxService.java b/android/src/org/rockbox/RockboxService.java index 43d122a8cc..4f0caa7704 100644 --- a/android/src/org/rockbox/RockboxService.java +++ b/android/src/org/rockbox/RockboxService.java | |||
@@ -59,8 +59,7 @@ public class RockboxService extends Service | |||
59 | private static RockboxService instance = null; | 59 | private static RockboxService instance = null; |
60 | 60 | ||
61 | /* locals needed for the c code and rockbox state */ | 61 | /* locals needed for the c code and rockbox state */ |
62 | private RockboxFramebuffer fb = null; | 62 | private static volatile boolean rockbox_running; |
63 | private volatile boolean rockbox_running; | ||
64 | private Activity current_activity = null; | 63 | private Activity current_activity = null; |
65 | private IntentFilter itf; | 64 | private IntentFilter itf; |
66 | private BroadcastReceiver batt_monitor; | 65 | private BroadcastReceiver batt_monitor; |
@@ -69,11 +68,9 @@ public class RockboxService extends Service | |||
69 | @SuppressWarnings("unused") | 68 | @SuppressWarnings("unused") |
70 | private int battery_level; | 69 | private int battery_level; |
71 | private ResultReceiver resultReceiver; | 70 | private ResultReceiver resultReceiver; |
72 | final private Object lock = new Object(); | ||
73 | 71 | ||
74 | public static final int RESULT_INVOKING_MAIN = 0; | 72 | public static final int RESULT_INVOKING_MAIN = 0; |
75 | public static final int RESULT_LIB_LOAD_PROGRESS = 1; | 73 | public static final int RESULT_LIB_LOAD_PROGRESS = 1; |
76 | public static final int RESULT_FB_INITIALIZED = 2; | ||
77 | public static final int RESULT_SERVICE_RUNNING = 3; | 74 | public static final int RESULT_SERVICE_RUNNING = 3; |
78 | public static final int RESULT_ERROR_OCCURED = 4; | 75 | public static final int RESULT_ERROR_OCCURED = 4; |
79 | public static final int RESULT_LIB_LOADED = 5; | 76 | public static final int RESULT_LIB_LOADED = 5; |
@@ -88,14 +85,15 @@ public class RockboxService extends Service | |||
88 | 85 | ||
89 | public static RockboxService get_instance() | 86 | public static RockboxService get_instance() |
90 | { | 87 | { |
88 | /* don't call the construtor here, the instances are managed by | ||
89 | * android, so we can't just create a new one */ | ||
91 | return instance; | 90 | return instance; |
92 | } | 91 | } |
93 | 92 | ||
94 | public RockboxFramebuffer get_fb() | 93 | public boolean isRockboxRunning() |
95 | { | 94 | { |
96 | return fb; | 95 | return rockbox_running; |
97 | } | 96 | } |
98 | |||
99 | public Activity get_activity() | 97 | public Activity get_activity() |
100 | { | 98 | { |
101 | return current_activity; | 99 | return current_activity; |
@@ -108,71 +106,48 @@ public class RockboxService extends Service | |||
108 | private void do_start(Intent intent) | 106 | private void do_start(Intent intent) |
109 | { | 107 | { |
110 | LOG("Start Service"); | 108 | LOG("Start Service"); |
111 | |||
112 | if (intent != null && intent.hasExtra("callback")) | 109 | if (intent != null && intent.hasExtra("callback")) |
113 | resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback"); | 110 | resultReceiver = (ResultReceiver) intent.getParcelableExtra("callback"); |
114 | 111 | ||
115 | /* Display a notification about us starting. | ||
116 | * We put an icon in the status bar. */ | ||
117 | if (fg_runner == null) | ||
118 | { /* needs to be initialized before main() runs */ | ||
119 | try { | ||
120 | } catch (Exception e) { | ||
121 | e.printStackTrace(); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | if (!rockbox_running) | 112 | if (!rockbox_running) |
126 | { | 113 | startservice(); |
127 | synchronized(lock) | ||
128 | { | ||
129 | startservice(); | ||
130 | while(true) { | ||
131 | try { | ||
132 | lock.wait(); | ||
133 | } catch (InterruptedException e) { | ||
134 | continue; | ||
135 | } | ||
136 | break; | ||
137 | } | ||
138 | fb = new RockboxFramebuffer(this); | ||
139 | if (resultReceiver != null) | ||
140 | resultReceiver.send(RESULT_FB_INITIALIZED, null); | ||
141 | } | ||
142 | } | ||
143 | if (resultReceiver != null) | 114 | if (resultReceiver != null) |
144 | resultReceiver.send(RESULT_LIB_LOADED, null); | 115 | resultReceiver.send(RESULT_LIB_LOADED, null); |
145 | 116 | ||
117 | |||
146 | if (intent != null && intent.getAction() != null) | 118 | if (intent != null && intent.getAction() != null) |
147 | { | 119 | { |
148 | Log.d("RockboxService", intent.getAction()); | 120 | if (!rockbox_running) |
149 | if (intent.getAction().equals("org.rockbox.PlayPause")) | 121 | { /* give it a bit of time so we can register button presses |
150 | { | 122 | * sleeping longer doesn't work here, apparently Android |
151 | if (fb != null) | 123 | * surpresses long sleeps during intent handling */ |
152 | fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, null); | 124 | try { |
125 | Thread.sleep(50); | ||
126 | } | ||
127 | catch (InterruptedException e) { } | ||
153 | } | 128 | } |
154 | else if (intent.getAction().equals("org.rockbox.Prev")) | 129 | |
130 | if (intent.getAction().equals(Intent.ACTION_MEDIA_BUTTON)) | ||
155 | { | 131 | { |
156 | if (fb != null) | 132 | KeyEvent kev = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT); |
157 | fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_PREVIOUS, null); | 133 | RockboxFramebuffer.buttonHandler(kev.getKeyCode(), kev.getAction() == KeyEvent.ACTION_DOWN); |
158 | } | 134 | } |
135 | else if (intent.getAction().equals("org.rockbox.PlayPause")) | ||
136 | RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, false); | ||
137 | else if (intent.getAction().equals("org.rockbox.Prev")) | ||
138 | RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_PREVIOUS, false); | ||
159 | else if (intent.getAction().equals("org.rockbox.Next")) | 139 | else if (intent.getAction().equals("org.rockbox.Next")) |
160 | { | 140 | RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_NEXT, false); |
161 | if (fb != null) | ||
162 | fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_NEXT, null); | ||
163 | } | ||
164 | else if (intent.getAction().equals("org.rockbox.Stop")) | 141 | else if (intent.getAction().equals("org.rockbox.Stop")) |
165 | { | 142 | RockboxFramebuffer.buttonHandler(KeyEvent.KEYCODE_MEDIA_STOP, false); |
166 | if (fb != null) | ||
167 | fb.onKeyUp(KeyEvent.KEYCODE_MEDIA_STOP, null); | ||
168 | } | ||
169 | } | 143 | } |
170 | 144 | ||
171 | /* (Re-)attach the media button receiver, in case it has been lost */ | 145 | /* (Re-)attach the media button receiver, in case it has been lost */ |
172 | mMediaButtonReceiver.register(); | 146 | mMediaButtonReceiver.register(); |
173 | |||
174 | if (resultReceiver != null) | 147 | if (resultReceiver != null) |
175 | resultReceiver.send(RESULT_SERVICE_RUNNING, null); | 148 | resultReceiver.send(RESULT_SERVICE_RUNNING, null); |
149 | |||
150 | rockbox_running = true; | ||
176 | } | 151 | } |
177 | 152 | ||
178 | private void LOG(CharSequence text) | 153 | private void LOG(CharSequence text) |
@@ -195,16 +170,23 @@ public class RockboxService extends Service | |||
195 | return 1; /* old API compatibility: 1 == START_STICKY */ | 170 | return 1; /* old API compatibility: 1 == START_STICKY */ |
196 | } | 171 | } |
197 | 172 | ||
198 | private void startservice() | 173 | private void startservice() |
199 | { | 174 | { |
200 | final int BUFFER = 8*1024; | 175 | final Object lock = new Object(); |
201 | Thread rb = new Thread(new Runnable() | 176 | Thread rb = new Thread(new Runnable() |
202 | { | 177 | { |
203 | public void run() | 178 | public void run() |
204 | { | 179 | { |
180 | final int BUFFER = 8*1024; | ||
205 | String rockboxDirPath = "/data/data/org.rockbox/app_rockbox/rockbox"; | 181 | String rockboxDirPath = "/data/data/org.rockbox/app_rockbox/rockbox"; |
206 | File rockboxDir = new File(rockboxDirPath); | 182 | File rockboxDir = new File(rockboxDirPath); |
207 | 183 | ||
184 | /* load library before unzipping which may take a while */ | ||
185 | synchronized (lock) { | ||
186 | System.loadLibrary("rockbox"); | ||
187 | lock.notify(); | ||
188 | } | ||
189 | |||
208 | /* the following block unzips libmisc.so, which contains the files | 190 | /* the following block unzips libmisc.so, which contains the files |
209 | * we ship, such as themes. It's needed to put it into a .so file | 191 | * we ship, such as themes. It's needed to put it into a .so file |
210 | * because there's no other way to ship files and have access | 192 | * because there's no other way to ship files and have access |
@@ -268,13 +250,7 @@ public class RockboxService extends Service | |||
268 | } | 250 | } |
269 | } | 251 | } |
270 | } | 252 | } |
271 | |||
272 | synchronized (lock) { | ||
273 | System.loadLibrary("rockbox"); | ||
274 | lock.notify(); | ||
275 | } | ||
276 | 253 | ||
277 | rockbox_running = true; | ||
278 | if (resultReceiver != null) | 254 | if (resultReceiver != null) |
279 | resultReceiver.send(RESULT_INVOKING_MAIN, null); | 255 | resultReceiver.send(RESULT_INVOKING_MAIN, null); |
280 | 256 | ||
@@ -283,7 +259,20 @@ public class RockboxService extends Service | |||
283 | } | 259 | } |
284 | }, "Rockbox thread"); | 260 | }, "Rockbox thread"); |
285 | rb.setDaemon(false); | 261 | rb.setDaemon(false); |
286 | rb.start(); | 262 | /* wait at least until the library is loaded */ |
263 | synchronized (lock) | ||
264 | { | ||
265 | rb.start(); | ||
266 | while(true) | ||
267 | { | ||
268 | try { | ||
269 | lock.wait(); | ||
270 | } catch (InterruptedException e) { | ||
271 | continue; | ||
272 | } | ||
273 | break; | ||
274 | } | ||
275 | } | ||
287 | } | 276 | } |
288 | 277 | ||
289 | private native void main(); | 278 | private native void main(); |
@@ -352,5 +341,7 @@ public class RockboxService extends Service | |||
352 | mMediaButtonReceiver = null; | 341 | mMediaButtonReceiver = null; |
353 | /* Make sure our notification is gone. */ | 342 | /* Make sure our notification is gone. */ |
354 | stopForeground(); | 343 | stopForeground(); |
344 | instance = null; | ||
345 | rockbox_running = false; | ||
355 | } | 346 | } |
356 | } | 347 | } |
diff --git a/apps/main.c b/apps/main.c index 3fc48be183..bd04223f97 100644 --- a/apps/main.c +++ b/apps/main.c | |||
@@ -410,7 +410,6 @@ static void init(void) | |||
410 | #endif /* CONFIG_CODEC == SWCODEC */ | 410 | #endif /* CONFIG_CODEC == SWCODEC */ |
411 | 411 | ||
412 | audio_init(); | 412 | audio_init(); |
413 | button_clear_queue(); /* Empty the keyboard buffer */ | ||
414 | 413 | ||
415 | settings_apply_skins(); | 414 | settings_apply_skins(); |
416 | } | 415 | } |
diff --git a/firmware/target/hosted/android/button-android.c b/firmware/target/hosted/android/button-android.c index 832eef54f3..ed1e125223 100644 --- a/firmware/target/hosted/android/button-android.c +++ b/firmware/target/hosted/android/button-android.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "system.h" | 29 | #include "system.h" |
30 | #include "touchscreen.h" | 30 | #include "touchscreen.h" |
31 | 31 | ||
32 | extern JNIEnv *env_ptr; | ||
32 | static int last_y, last_x; | 33 | static int last_y, last_x; |
33 | static int last_btns; | 34 | static int last_btns; |
34 | 35 | ||
@@ -61,11 +62,11 @@ Java_org_rockbox_RockboxFramebuffer_touchHandler(JNIEnv*env, jobject this, | |||
61 | * this writes in an interrupt-like fashion the button events that the user | 62 | * this writes in an interrupt-like fashion the button events that the user |
62 | * generated by pressing/releasing them to a variable */ | 63 | * generated by pressing/releasing them to a variable */ |
63 | JNIEXPORT bool JNICALL | 64 | JNIEXPORT bool JNICALL |
64 | Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jclass this, | 65 | Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jclass class, |
65 | jint keycode, jboolean state) | 66 | jint keycode, jboolean state) |
66 | { | 67 | { |
67 | (void)env; | 68 | (void)env; |
68 | (void)this; | 69 | (void)class; |
69 | 70 | ||
70 | unsigned button = 0; | 71 | unsigned button = 0; |
71 | 72 | ||
@@ -75,7 +76,10 @@ Java_org_rockbox_RockboxFramebuffer_buttonHandler(JNIEnv*env, jclass this, | |||
75 | if (!button) | 76 | if (!button) |
76 | button = dpad_to_button((int)keycode); | 77 | button = dpad_to_button((int)keycode); |
77 | if (button) | 78 | if (button) |
79 | { | ||
78 | queue_post(&button_queue, button, 0); | 80 | queue_post(&button_queue, button, 0); |
81 | return true; | ||
82 | } | ||
79 | } | 83 | } |
80 | 84 | ||
81 | if (!button) | 85 | if (!button) |
diff --git a/firmware/target/hosted/android/lcd-android.c b/firmware/target/hosted/android/lcd-android.c index f719329819..c9bd0a1254 100644 --- a/firmware/target/hosted/android/lcd-android.c +++ b/firmware/target/hosted/android/lcd-android.c | |||
@@ -29,68 +29,63 @@ | |||
29 | #include "button.h" | 29 | #include "button.h" |
30 | 30 | ||
31 | extern JNIEnv *env_ptr; | 31 | extern JNIEnv *env_ptr; |
32 | extern jclass RockboxService_class; | ||
33 | extern jobject RockboxService_instance; | 32 | extern jobject RockboxService_instance; |
34 | 33 | ||
35 | static jclass RockboxFramebuffer_class; | ||
36 | static jobject RockboxFramebuffer_instance; | 34 | static jobject RockboxFramebuffer_instance; |
37 | static jmethodID java_lcd_update; | 35 | static jmethodID java_lcd_update; |
38 | static jmethodID java_lcd_update_rect; | 36 | static jmethodID java_lcd_update_rect; |
37 | static jmethodID java_lcd_init; | ||
38 | static jobject native_buffer; | ||
39 | 39 | ||
40 | static int dpi; | 40 | static int dpi; |
41 | static int scroll_threshold; | 41 | static int scroll_threshold; |
42 | static bool display_on; | 42 | static bool display_on; |
43 | 43 | ||
44 | void lcd_init_device(void) | 44 | /* this might actually be called before lcd_init_device() or even main(), so |
45 | * be sure to only access static storage initalized at library loading, | ||
46 | * and not more */ | ||
47 | void connect_with_java(JNIEnv* env, jobject fb_instance) | ||
45 | { | 48 | { |
46 | JNIEnv e = *env_ptr; | 49 | JNIEnv e = *env; |
47 | /* get existing instance from the Service */ | 50 | static bool have_class; |
48 | jmethodID get_fb = e->GetMethodID(env_ptr, RockboxService_class, "get_fb", | 51 | RockboxFramebuffer_instance = fb_instance; |
49 | "()Lorg/rockbox/RockboxFramebuffer;"); | 52 | if (!have_class) |
50 | RockboxFramebuffer_instance = e->CallObjectMethod(env_ptr, | 53 | { |
51 | RockboxService_instance, | 54 | jclass fb_class = e->GetObjectClass(env, fb_instance); |
52 | get_fb); | 55 | /* cache update functions */ |
53 | RockboxFramebuffer_class = (*env_ptr)->GetObjectClass(env_ptr, | 56 | java_lcd_update = e->GetMethodID(env, fb_class, |
54 | RockboxFramebuffer_instance); | 57 | "java_lcd_update", |
55 | 58 | "()V"); | |
56 | /* Get init function and set up what's left from the constructor */ | 59 | java_lcd_update_rect = e->GetMethodID(env, fb_class, |
57 | jmethodID java_lcd_init = (*env_ptr)->GetMethodID(env_ptr, | 60 | "java_lcd_update_rect", |
58 | RockboxFramebuffer_class, | 61 | "(IIII)V"); |
59 | "java_lcd_init", | 62 | jmethodID get_dpi = e->GetMethodID(env, fb_class, |
60 | "(IILjava/nio/ByteBuffer;)V"); | 63 | "getDpi", "()I"); |
61 | 64 | jmethodID thresh = e->GetMethodID(env, fb_class, | |
62 | jobject buf = e->NewDirectByteBuffer(env_ptr, | 65 | "getScrollThreshold", "()I"); |
66 | /* these don't change with new instances so call them now */ | ||
67 | dpi = e->CallIntMethod(env, fb_instance, get_dpi); | ||
68 | scroll_threshold = e->CallIntMethod(env, fb_instance, thresh); | ||
69 | |||
70 | java_lcd_init = e->GetMethodID(env, fb_class, | ||
71 | "java_lcd_init", | ||
72 | "(IILjava/nio/ByteBuffer;)V"); | ||
73 | |||
74 | native_buffer = e->NewDirectByteBuffer(env, | ||
63 | lcd_framebuffer, | 75 | lcd_framebuffer, |
64 | (jlong)sizeof(lcd_framebuffer)); | 76 | (jlong)sizeof(lcd_framebuffer)); |
77 | have_class = true; | ||
78 | } | ||
79 | /* we need to setup parts for the java object every time */ | ||
80 | (*env)->CallVoidMethod(env, fb_instance, java_lcd_init, | ||
81 | (jint)LCD_WIDTH, (jint)LCD_HEIGHT, native_buffer); | ||
82 | } | ||
65 | 83 | ||
66 | e->CallVoidMethod(env_ptr, RockboxFramebuffer_instance, java_lcd_init, | 84 | /* |
67 | (jint)LCD_WIDTH, | 85 | * Do nothing here and connect with the java object later (if it isn't already) |
68 | (jint)LCD_HEIGHT, | 86 | */ |
69 | buf); | 87 | void lcd_init_device(void) |
70 | 88 | { | |
71 | /* cache update functions */ | ||
72 | java_lcd_update = (*env_ptr)->GetMethodID(env_ptr, | ||
73 | RockboxFramebuffer_class, | ||
74 | "java_lcd_update", | ||
75 | "()V"); | ||
76 | java_lcd_update_rect = (*env_ptr)->GetMethodID(env_ptr, | ||
77 | RockboxFramebuffer_class, | ||
78 | "java_lcd_update_rect", | ||
79 | "(IIII)V"); | ||
80 | |||
81 | jmethodID get_dpi = e->GetMethodID(env_ptr, | ||
82 | RockboxFramebuffer_class, | ||
83 | "getDpi", "()I"); | ||
84 | |||
85 | jmethodID get_scroll_threshold | ||
86 | = e->GetMethodID(env_ptr, | ||
87 | RockboxFramebuffer_class, | ||
88 | "getScrollThreshold", "()I"); | ||
89 | |||
90 | dpi = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance, | ||
91 | get_dpi); | ||
92 | scroll_threshold = e->CallIntMethod(env_ptr, RockboxFramebuffer_instance, | ||
93 | get_scroll_threshold); | ||
94 | /* must not draw until surface is created */ | 89 | /* must not draw until surface is created */ |
95 | display_on = false; | 90 | display_on = false; |
96 | } | 91 | } |
@@ -116,12 +111,14 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
116 | * Note this is considered interrupt context | 111 | * Note this is considered interrupt context |
117 | */ | 112 | */ |
118 | JNIEXPORT void JNICALL | 113 | JNIEXPORT void JNICALL |
119 | Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv *e, jobject this, | 114 | Java_org_rockbox_RockboxFramebuffer_surfaceCreated(JNIEnv *env, jobject this, |
120 | jobject surfaceholder) | 115 | jobject surfaceholder) |
121 | { | 116 | { |
122 | (void)e; (void)this; (void)surfaceholder; | 117 | (void)surfaceholder; |
123 | 118 | /* possibly a new instance - reconnect */ | |
119 | connect_with_java(env, this); | ||
124 | display_on = true; | 120 | display_on = true; |
121 | |||
125 | send_event(LCD_EVENT_ACTIVATION, NULL); | 122 | send_event(LCD_EVENT_ACTIVATION, NULL); |
126 | /* Force an update, since the newly created surface is initially black | 123 | /* Force an update, since the newly created surface is initially black |
127 | * waiting for the next normal update results in a longish black screen */ | 124 | * waiting for the next normal update results in a longish black screen */ |