Fix:core:Silence debug messages in win32 and android graphics.
[profile/ivi/navit.git] / navit / navit / graphics / android / graphics_android.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <unistd.h>
21 #include <glib.h>
22 #include <poll.h>
23 #include "config.h"
24 #include "window.h"
25 #include "point.h"
26 #include "graphics.h"
27 #include "color.h"
28 #include "plugin.h"
29 #include "event.h"
30 #include "debug.h"
31 #include "callback.h"
32 #include "android.h"
33
34 int dummy;
35
36 struct graphics_priv {
37         jclass NavitGraphicsClass;
38         jmethodID NavitGraphics_draw_polyline, NavitGraphics_draw_polygon, NavitGraphics_draw_rectangle, NavitGraphics_draw_circle, NavitGraphics_draw_text, NavitGraphics_draw_image, NavitGraphics_draw_mode, NavitGraphics_draw_drag, NavitGraphics_overlay_disable, NavitGraphics_overlay_resize, NavitGraphics_SetCamera;
39
40         jclass PaintClass;
41         jmethodID Paint_init,Paint_setStrokeWidth,Paint_setARGB;
42
43         jobject NavitGraphics;
44         jobject Paint;
45         
46         jclass BitmapFactoryClass;      
47         jmethodID BitmapFactory_decodeFile, BitmapFactory_decodeResource;
48
49         jclass BitmapClass;
50         jmethodID Bitmap_getHeight, Bitmap_getWidth;
51
52         jclass ContextClass;
53         jmethodID Context_getResources;
54
55         jclass ResourcesClass;
56         jobject Resources;
57         jmethodID Resources_getIdentifier;
58
59         jobject packageName;
60
61         struct callback_list *cbl;
62         struct window win;
63 };
64
65 struct graphics_font_priv {
66         int size;
67 };
68
69 struct graphics_gc_priv {
70         struct graphics_priv *gra;
71         int linewidth;
72         enum draw_mode_num mode;
73         int a,r,g,b;
74 };
75
76 struct graphics_image_priv {
77         jobject Bitmap;
78         int width;
79         int height;
80         struct point hot;
81 };
82
83 static GHashTable *image_cache_hash = NULL;
84
85 static int
86 find_class_global(char *name, jclass *ret)
87 {
88         *ret=(*jnienv)->FindClass(jnienv, name);
89         if (! *ret) {
90                 dbg(0,"Failed to get Class %s\n",name);
91                 return 0;
92         }
93         *ret = (*jnienv)->NewGlobalRef(jnienv, *ret);
94         return 1;
95 }
96
97 static int
98 find_method(jclass class, char *name, char *args, jmethodID *ret)
99 {
100         *ret = (*jnienv)->GetMethodID(jnienv, class, name, args);
101         if (*ret == NULL) {
102                 dbg(0,"Failed to get Method %s with signature %s\n",name,args);
103                 return 0;
104         }
105         return 1;
106 }
107
108 static int
109 find_static_method(jclass class, char *name, char *args, jmethodID *ret)
110 {
111         *ret = (*jnienv)->GetStaticMethodID(jnienv, class, name, args);
112         if (*ret == NULL) {
113                 dbg(0,"Failed to get static Method %s with signature %s\n",name,args);
114                 return 0;
115         }
116         return 1;
117 }
118
119 static void
120 graphics_destroy(struct graphics_priv *gr)
121 {
122 }
123
124 static void font_destroy(struct graphics_font_priv *font)
125 {
126         g_free(font);
127 }
128
129 static struct graphics_font_methods font_methods = {
130         font_destroy
131 };
132
133 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *font,  int size, int flags)
134 {
135         struct graphics_font_priv *ret=g_new0(struct graphics_font_priv, 1);
136         *meth=font_methods;
137
138         ret->size=size;
139         return ret;
140 }
141
142 static void
143 gc_destroy(struct graphics_gc_priv *gc)
144 {
145         g_free(gc);
146 }
147
148 static void
149 gc_set_linewidth(struct graphics_gc_priv *gc, int w)
150 {
151     gc->linewidth = w;
152 }
153
154 static void
155 gc_set_dashes(struct graphics_gc_priv *gc, int w, int offset, unsigned char *dash_list, int n)
156 {
157 }
158
159 static void
160 gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
161 {
162     gc->r = c->r >> 8;
163     gc->g = c->g >> 8;
164     gc->b = c->b >> 8;
165     gc->a = c->a >> 8;
166 }
167
168 static void
169 gc_set_background(struct graphics_gc_priv *gc, struct color *c)
170 {
171 }
172
173 static struct graphics_gc_methods gc_methods = {
174         gc_destroy,
175         gc_set_linewidth,
176         gc_set_dashes,  
177         gc_set_foreground,      
178         gc_set_background       
179 };
180
181 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
182 {
183         struct graphics_gc_priv *ret=g_new0(struct graphics_gc_priv, 1);
184         *meth=gc_methods;
185
186         ret->gra = gr;
187         ret->a = ret->r = ret->g = ret->b = 255;
188         ret->linewidth=1;
189         return ret;
190 }
191
192 static void image_destroy(struct graphics_image_priv *img)
193 {
194     // unused?
195 }
196
197 static struct graphics_image_methods image_methods = {
198         image_destroy
199 };
200
201
202 static struct graphics_image_priv *
203 image_new(struct graphics_priv *gra, struct graphics_image_methods *meth, char *path, int *w, int *h, struct point *hot, int rotation)
204 {
205         struct graphics_image_priv* ret = NULL;
206
207         if ( !g_hash_table_lookup_extended( image_cache_hash, path, NULL, (gpointer)&ret) )
208         {
209                 ret=g_new0(struct graphics_image_priv, 1);
210                 jstring string;
211                 jclass localBitmap = NULL;
212                 int id;
213
214                 dbg(1,"enter %s\n",path);
215                 if (!strncmp(path,"res/drawable/",13)) {
216                         jstring a=(*jnienv)->NewStringUTF(jnienv, "drawable");
217                         char *path_noext=g_strdup(path+13);
218                         char *pos=strrchr(path_noext, '.');
219                         if (pos)
220                                 *pos='\0';
221                         dbg(1,"path_noext=%s\n",path_noext);
222                         string = (*jnienv)->NewStringUTF(jnienv, path_noext);
223                         g_free(path_noext);
224                         id=(*jnienv)->CallIntMethod(jnienv, gra->Resources, gra->Resources_getIdentifier, string, a, gra->packageName);
225                         dbg(1,"id=%d\n",id);
226                         if (id)
227                                 localBitmap=(*jnienv)->CallStaticObjectMethod(jnienv, gra->BitmapFactoryClass, gra->BitmapFactory_decodeResource, gra->Resources, id);
228                         (*jnienv)->DeleteLocalRef(jnienv, a);
229                 } else {
230                         string = (*jnienv)->NewStringUTF(jnienv, path);
231                         localBitmap=(*jnienv)->CallStaticObjectMethod(jnienv, gra->BitmapFactoryClass, gra->BitmapFactory_decodeFile, string);
232                 }
233                 dbg(1,"result=%p\n",localBitmap);
234                 if (localBitmap) {
235                         ret->Bitmap = (*jnienv)->NewGlobalRef(jnienv, localBitmap);
236                         (*jnienv)->DeleteLocalRef(jnienv, localBitmap);
237                         ret->width=(*jnienv)->CallIntMethod(jnienv, ret->Bitmap, gra->Bitmap_getWidth);
238                         ret->height=(*jnienv)->CallIntMethod(jnienv, ret->Bitmap, gra->Bitmap_getHeight);
239                         dbg(1,"w=%d h=%d for %s\n",ret->width,ret->height,path);
240                         ret->hot.x=ret->width/2;
241                         ret->hot.y=ret->height/2;
242                 } else {
243                         g_free(ret);
244                         ret=NULL;
245                         dbg(1,"Failed to open %s\n",path);
246                 }
247                 (*jnienv)->DeleteLocalRef(jnienv, string);
248                 g_hash_table_insert(image_cache_hash, g_strdup( path ),  (gpointer)ret );
249         }
250         if (ret) {
251                 *w=ret->width;
252                 *h=ret->height;
253                 if (hot)
254                         *hot=ret->hot;
255         }
256
257         return ret;
258 }
259
260 static void initPaint(struct graphics_priv *gra, struct graphics_gc_priv *gc)
261 {
262     float wf = gc->linewidth;
263     (*jnienv)->CallVoidMethod(jnienv, gc->gra->Paint, gra->Paint_setStrokeWidth, wf);
264     (*jnienv)->CallVoidMethod(jnienv, gc->gra->Paint, gra->Paint_setARGB, gc->a, gc->r, gc->g, gc->b);
265 }
266
267 static void
268 draw_lines(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count)
269 {
270         jint pc[count*2];
271         int i;
272         jintArray points;
273         if (count <= 0)
274                 return;
275         points = (*jnienv)->NewIntArray(jnienv,count*2);
276         for (i = 0 ; i < count ; i++) {
277                 pc[i*2]=p[i].x;
278                 pc[i*2+1]=p[i].y;
279         }
280         initPaint(gra, gc);
281         (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count*2, pc);
282         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polyline, gc->gra->Paint, points);
283         (*jnienv)->DeleteLocalRef(jnienv, points);
284 }
285
286 static void
287 draw_polygon(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int count)
288 {
289         jint pc[count*2];
290         int i;
291         jintArray points;
292         if (count <= 0)
293                 return;
294         points = (*jnienv)->NewIntArray(jnienv,count*2);
295         for (i = 0 ; i < count ; i++) {
296                 pc[i*2]=p[i].x;
297                 pc[i*2+1]=p[i].y;
298         }
299         initPaint(gra, gc);
300         (*jnienv)->SetIntArrayRegion(jnienv, points, 0, count*2, pc);
301         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_polygon, gc->gra->Paint, points);
302         (*jnienv)->DeleteLocalRef(jnienv, points);
303 }
304
305 static void
306 draw_rectangle(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int w, int h)
307 {
308         initPaint(gra, gc);
309         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_rectangle, gc->gra->Paint, p->x, p->y, w, h);
310 }
311
312 static void
313 draw_circle(struct graphics_priv *gra, struct graphics_gc_priv *gc, struct point *p, int r)
314 {
315         initPaint(gra, gc);
316         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_circle, gc->gra->Paint, p->x, p->y, r);
317 }
318
319
320 static void
321 draw_text(struct graphics_priv *gra, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
322 {
323         dbg(1,"enter %s\n", text);
324         initPaint(gra, fg);
325         jstring string = (*jnienv)->NewStringUTF(jnienv, text);
326         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_text, fg->gra->Paint, p->x, p->y, string, font->size, dx, dy);
327         (*jnienv)->DeleteLocalRef(jnienv, string);
328 }
329
330 static void
331 draw_image(struct graphics_priv *gra, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
332 {
333         dbg(1,"enter %p\n",img);
334         initPaint(gra, fg);
335         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_image, fg->gra->Paint, p->x, p->y, img->Bitmap);
336         
337 }
338
339 static void
340 draw_image_warp(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, int count, char *data)
341 {
342 }
343
344 static void
345 draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
346 {
347 }
348
349 static void draw_drag(struct graphics_priv *gra, struct point *p)
350 {
351         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_drag, p ? p->x : 0, p ? p->y : 0);
352 }
353
354 static void
355 background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
356 {
357 }
358
359 static void
360 draw_mode(struct graphics_priv *gra, enum draw_mode_num mode)
361 {
362         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_draw_mode, (int)mode);
363 }
364
365 static struct graphics_priv * overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound);
366
367 static void *
368 get_data(struct graphics_priv *this, const char *type)
369 {
370         if (strcmp(type,"window"))
371                 return NULL;
372         return &this->win;
373 }
374
375 static void image_free(struct graphics_priv *gr, struct graphics_image_priv *priv)
376 {
377 }
378
379 static void get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
380 {
381         int len = g_utf8_strlen(text, -1);
382         int xMin = 0;
383         int yMin = 0;
384         int yMax = 13*font->size/256;
385         int xMax = 9*font->size*len/256;
386
387         ret[0].x = xMin;
388         ret[0].y = -yMin;
389         ret[1].x = xMin;
390         ret[1].y = -yMax;
391         ret[2].x = xMax;
392         ret[2].y = -yMax;
393         ret[3].x = xMax;
394         ret[3].y = -yMin;
395 }
396
397 static void overlay_disable(struct graphics_priv *gra, int disable)
398 {
399         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_overlay_disable, disable);
400 }
401
402 static void overlay_resize(struct graphics_priv *gra, struct point *pnt, int w, int h, int alpha, int wraparound)
403 {
404         (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_overlay_resize, pnt ? pnt->x:0 , pnt ? pnt->y:0, w, h, alpha, wraparound);
405 }
406
407 static int
408 set_attr(struct graphics_priv *gra, struct attr *attr)
409 {
410         switch (attr->type) {
411         case attr_use_camera:
412                 (*jnienv)->CallVoidMethod(jnienv, gra->NavitGraphics, gra->NavitGraphics_SetCamera, attr->u.num);
413                 return 1;
414         default:
415                 return 0;
416         }
417 }
418
419 static struct graphics_methods graphics_methods = {
420         graphics_destroy,
421         draw_mode,
422         draw_lines,
423         draw_polygon,
424         draw_rectangle,
425         draw_circle,
426         draw_text,
427         draw_image,
428         draw_image_warp,
429         draw_restore,
430         draw_drag,
431         font_new,
432         gc_new,
433         background_gc,
434         overlay_new,
435         image_new,
436         get_data,
437         image_free,
438         get_text_bbox,
439         overlay_disable,
440         overlay_resize,
441         set_attr,
442 };
443
444 static void
445 resize_callback(struct graphics_priv *gra, int w, int h)
446 {
447         dbg(0,"w=%d h=%d ok\n",w,h);
448          callback_list_call_attr_2(gra->cbl, attr_resize, (void *)w, (void *)h);
449 }
450
451 static void
452 motion_callback(struct graphics_priv *gra, int x, int y)
453 {
454         struct point p;
455         p.x=x;
456         p.y=y;
457         callback_list_call_attr_1(gra->cbl, attr_motion, (void *)&p);
458 }
459
460 static void
461 keypress_callback(struct graphics_priv *gra, char *s)
462 {
463         dbg(0,"enter %s\n",s);
464         callback_list_call_attr_1(gra->cbl, attr_keypress, s);
465 }
466
467 static void
468 button_callback(struct graphics_priv *gra, int pressed, int button, int x, int y)
469 {
470         struct point p;
471         p.x=x;
472         p.y=y;
473         callback_list_call_attr_3(gra->cbl, attr_button, (void *)pressed, (void *)button, (void *)&p);
474 }
475
476
477 static int
478 set_activity(jobject graphics)
479 {
480         jclass ActivityClass;
481         jmethodID cid;
482
483         ActivityClass = (*jnienv)->GetObjectClass(jnienv, android_activity);
484         dbg(0,"at 5\n");
485         if (ActivityClass == NULL) {
486                 dbg(0,"no activity class found\n");
487                 return 0;
488         }
489         dbg(0,"at 6\n");
490         cid = (*jnienv)->GetMethodID(jnienv, ActivityClass, "setContentView", "(Landroid/view/View;)V");
491         if (cid == NULL) {
492                 dbg(0,"no setContentView method found\n");
493                 return 0;
494         }
495         dbg(0,"at 7\n");
496         (*jnienv)->CallVoidMethod(jnienv, android_activity, cid, graphics);
497         dbg(0,"at 8\n");
498         return 1;
499 }
500
501 static int
502 graphics_android_init(struct graphics_priv *ret, struct graphics_priv *parent, struct point *pnt, int w, int h, int alpha, int wraparound, int use_camera)
503 {
504         struct callback *cb;
505         jmethodID cid, Context_getPackageName;
506
507         dbg(0,"at 2 jnienv=%p\n",jnienv);
508         if (!find_class_global("android/graphics/Paint", &ret->PaintClass))
509                 return 0;
510         if (!find_method(ret->PaintClass, "<init>", "(I)V", &ret->Paint_init))
511                 return 0;
512         if (!find_method(ret->PaintClass, "setARGB", "(IIII)V", &ret->Paint_setARGB))
513                 return 0;
514         if (!find_method(ret->PaintClass, "setStrokeWidth", "(F)V", &ret->Paint_setStrokeWidth))
515                 return 0;
516
517         if (!find_class_global("android/graphics/BitmapFactory", &ret->BitmapFactoryClass))
518                 return 0;
519         if (!find_static_method(ret->BitmapFactoryClass, "decodeFile", "(Ljava/lang/String;)Landroid/graphics/Bitmap;", &ret->BitmapFactory_decodeFile))
520                 return 0;
521         if (!find_static_method(ret->BitmapFactoryClass, "decodeResource", "(Landroid/content/res/Resources;I)Landroid/graphics/Bitmap;", &ret->BitmapFactory_decodeResource))
522                 return 0;
523
524         if (!find_class_global("android/graphics/Bitmap", &ret->BitmapClass))
525                 return 0;
526         if (!find_method(ret->BitmapClass, "getHeight", "()I", &ret->Bitmap_getHeight))
527                 return 0;
528         if (!find_method(ret->BitmapClass, "getWidth", "()I", &ret->Bitmap_getWidth))
529                 return 0;
530
531         if (!find_class_global("android/content/Context", &ret->ContextClass))
532                 return 0;
533         if (!find_method(ret->ContextClass, "getResources", "()Landroid/content/res/Resources;", &ret->Context_getResources))
534                 return 0;
535
536
537         ret->Resources=(*jnienv)->CallObjectMethod(jnienv, android_activity, ret->Context_getResources);
538         if (ret->Resources)
539                 ret->Resources = (*jnienv)->NewGlobalRef(jnienv, ret->Resources);
540         if (!find_class_global("android/content/res/Resources", &ret->ResourcesClass))
541                 return 0;
542         if (!find_method(ret->ResourcesClass, "getIdentifier", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", &ret->Resources_getIdentifier))
543                 return 0;
544
545         if (!find_method(ret->ContextClass, "getPackageName", "()Ljava/lang/String;", &Context_getPackageName))
546                 return 0;
547         ret->packageName=(*jnienv)->CallObjectMethod(jnienv, android_activity, Context_getPackageName);
548         ret->packageName=(*jnienv)->NewGlobalRef(jnienv, ret->packageName);
549
550         if (!find_class_global("org/navitproject/navit/NavitGraphics", &ret->NavitGraphicsClass))
551                 return 0;
552         dbg(0,"at 3\n");
553         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "<init>", "(Landroid/app/Activity;Lorg/navitproject/navit/NavitGraphics;IIIIIII)V");
554         if (cid == NULL) {
555                 dbg(0,"no method found\n");
556                 return 0; /* exception thrown */
557         }
558         dbg(0,"at 4 android_activity=%p\n",android_activity);
559         ret->NavitGraphics=(*jnienv)->NewObject(jnienv, ret->NavitGraphicsClass, cid, android_activity, parent ? parent->NavitGraphics : NULL, pnt ? pnt->x:0 , pnt ? pnt->y:0, w, h, alpha, wraparound, use_camera);
560         dbg(0,"result=%p\n",ret->NavitGraphics);
561         if (ret->NavitGraphics)
562                 ret->NavitGraphics = (*jnienv)->NewGlobalRef(jnienv, ret->NavitGraphics);
563
564         /* Create a single global Paint, otherwise android will quickly run out
565          * of global refs.*/
566         /* 0x101 = text kerning (default), antialiasing */
567         ret->Paint=(*jnienv)->NewObject(jnienv, ret->PaintClass, ret->Paint_init, 0x101);
568
569         dbg(0,"result=%p\n",ret->Paint);
570         if (ret->Paint)
571                 ret->Paint = (*jnienv)->NewGlobalRef(jnienv, ret->Paint);
572
573         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setSizeChangedCallback", "(I)V");
574         if (cid == NULL) {
575                 dbg(0,"no SetResizeCallback method found\n");
576                 return 0; /* exception thrown */
577         }
578         cb=callback_new_1(callback_cast(resize_callback), ret);
579         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
580
581         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setButtonCallback", "(I)V");
582         if (cid == NULL) {
583                 dbg(0,"no SetButtonCallback method found\n");
584                 return 0; /* exception thrown */
585         }
586         cb=callback_new_1(callback_cast(button_callback), ret);
587         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
588
589         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setMotionCallback", "(I)V");
590         if (cid == NULL) {
591                 dbg(0,"no SetMotionCallback method found\n");
592                 return 0; /* exception thrown */
593         }
594         cb=callback_new_1(callback_cast(motion_callback), ret);
595         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
596
597         cid = (*jnienv)->GetMethodID(jnienv, ret->NavitGraphicsClass, "setKeypressCallback", "(I)V");
598         if (cid == NULL) {
599                 dbg(0,"no SetKeypressCallback method found\n");
600                 return 0; /* exception thrown */
601         }
602         cb=callback_new_1(callback_cast(keypress_callback), ret);
603         (*jnienv)->CallVoidMethod(jnienv, ret->NavitGraphics, cid, (int)cb);
604
605         if (!find_method(ret->NavitGraphicsClass, "draw_polyline", "(Landroid/graphics/Paint;[I)V", &ret->NavitGraphics_draw_polyline))
606                 return 0;
607         if (!find_method(ret->NavitGraphicsClass, "draw_polygon", "(Landroid/graphics/Paint;[I)V", &ret->NavitGraphics_draw_polygon))
608                 return 0;
609         if (!find_method(ret->NavitGraphicsClass, "draw_rectangle", "(Landroid/graphics/Paint;IIII)V", &ret->NavitGraphics_draw_rectangle))
610                 return 0;
611         if (!find_method(ret->NavitGraphicsClass, "draw_circle", "(Landroid/graphics/Paint;III)V", &ret->NavitGraphics_draw_circle))
612                 return 0;
613         if (!find_method(ret->NavitGraphicsClass, "draw_text", "(Landroid/graphics/Paint;IILjava/lang/String;III)V", &ret->NavitGraphics_draw_text))
614                 return 0;
615         if (!find_method(ret->NavitGraphicsClass, "draw_image", "(Landroid/graphics/Paint;IILandroid/graphics/Bitmap;)V", &ret->NavitGraphics_draw_image))
616                 return 0;
617         if (!find_method(ret->NavitGraphicsClass, "draw_mode", "(I)V", &ret->NavitGraphics_draw_mode))
618                 return 0;
619         if (!find_method(ret->NavitGraphicsClass, "draw_drag", "(II)V", &ret->NavitGraphics_draw_drag))
620                 return 0;
621         if (!find_method(ret->NavitGraphicsClass, "overlay_disable", "(I)V", &ret->NavitGraphics_overlay_disable))
622                 return 0;
623         if (!find_method(ret->NavitGraphicsClass, "overlay_resize", "(IIIIII)V", &ret->NavitGraphics_overlay_resize))
624                 return 0;
625         if (!find_method(ret->NavitGraphicsClass, "SetCamera", "(I)V", &ret->NavitGraphics_SetCamera))
626                 return 0;
627 #if 0
628         set_activity(ret->NavitGraphics);
629 #endif
630         return 1;
631 }
632
633 static int
634 graphics_android_fullscreen(struct window *win, int on)
635 {
636         return 1;
637 }
638
639 static jclass NavitClass;
640 static jmethodID Navit_disableSuspend, Navit_exit;
641
642 static void
643 graphics_android_disable_suspend(struct window *win)
644 {
645         dbg(1,"enter\n");
646         (*jnienv)->CallVoidMethod(jnienv, android_activity, Navit_disableSuspend);
647 }
648
649
650 static struct graphics_priv *
651 graphics_android_new(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
652 {
653         struct graphics_priv *ret;
654         struct attr *attr;
655         int use_camera=0;
656         if (!event_request_system("android","graphics_android"))
657                 return NULL;
658         ret=g_new0(struct graphics_priv, 1);
659
660         ret->cbl=cbl;
661         *meth=graphics_methods;
662         ret->win.priv=ret;
663         ret->win.fullscreen=graphics_android_fullscreen;
664         ret->win.disable_suspend=graphics_android_disable_suspend;
665         if ((attr=attr_search(attrs, NULL, attr_use_camera))) {
666                 use_camera=attr->u.num;
667         }
668         image_cache_hash = g_hash_table_new(g_str_hash, g_str_equal);
669         if (graphics_android_init(ret, NULL, NULL, 0, 0, 0, 0, use_camera)) {
670                 dbg(0,"returning %p\n",ret);
671                 return ret;
672         } else {
673                 g_free(ret);
674                 return NULL;
675         }
676 }
677
678 static struct graphics_priv *
679 overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound)
680 {
681         struct graphics_priv *ret=g_new0(struct graphics_priv, 1);
682         *meth=graphics_methods;
683         if (graphics_android_init(ret, gr, p, w, h, alpha, wraparound, 0)) {
684                 dbg(0,"returning %p\n",ret);
685                 return ret;
686         } else {
687                 g_free(ret);
688                 return NULL;
689         }
690 }
691
692
693 static void
694 event_android_main_loop_run(void)
695 {
696         dbg(0,"enter\n");
697 }
698
699 static void event_android_main_loop_quit(void)
700 {
701         dbg(0,"enter\n");
702         (*jnienv)->CallVoidMethod(jnienv, android_activity, Navit_exit);
703 }
704
705
706 static jclass NavitTimeoutClass;
707 static jmethodID NavitTimeout_init;
708 static jmethodID NavitTimeout_remove;
709
710 static jclass NavitIdleClass;
711 static jmethodID NavitIdle_init;
712 static jmethodID NavitIdle_remove;
713
714 static jclass NavitWatchClass;
715 static jmethodID NavitWatch_init;
716 static jmethodID NavitWatch_remove;
717
718
719 static void do_poll(JNIEnv *env, int fd, int cond)
720 {
721         struct pollfd pfd;
722         pfd.fd=fd;
723         dbg(1,"%p poll called for %d %d\n", fd, cond);
724         switch ((enum event_watch_cond)cond) {
725         case event_watch_cond_read:
726                 pfd.events=POLLIN;
727                 break;
728         case event_watch_cond_write:
729                 pfd.events=POLLOUT;
730                 break;
731         case event_watch_cond_except:
732                 pfd.events=POLLERR;
733                 break;
734         default:
735                 pfd.events=0;
736         }
737         pfd.revents=0;
738         poll(&pfd, 1, -1);
739 }
740
741 static struct event_watch *
742 event_android_add_watch(void *h, enum event_watch_cond cond, struct callback *cb)
743 {
744         jobject ret;
745         ret=(*jnienv)->NewObject(jnienv, NavitWatchClass, NavitWatch_init, (int)do_poll, (int) h, (int) cond, (int)cb);
746         dbg(0,"result for %p,%d,%p=%p\n",h,cond,cb,ret);
747         if (ret)
748                 ret = (*jnienv)->NewGlobalRef(jnienv, ret);
749         return (struct event_watch *)ret;
750 }
751
752 static void
753 event_android_remove_watch(struct event_watch *ev)
754 {
755         dbg(0,"enter %p\n",ev);
756         if (ev) {
757                 jobject obj=(jobject )ev;
758                 (*jnienv)->CallVoidMethod(jnienv, obj, NavitWatch_remove);
759                 (*jnienv)->DeleteGlobalRef(jnienv, obj);
760         }
761 }
762
763 struct event_timeout
764 {
765         void (*handle_timeout)(struct event_timeout *priv);
766         jobject jni_timeout;
767         int multi;
768         struct callback *cb;
769 };
770
771 static void
772 event_android_remove_timeout(struct event_timeout *priv)
773 {
774         if (priv && priv->jni_timeout) {
775                 (*jnienv)->CallVoidMethod(jnienv, priv->jni_timeout, NavitTimeout_remove);
776                 (*jnienv)->DeleteGlobalRef(jnienv, priv->jni_timeout);
777                 priv->jni_timeout = NULL;
778         }
779 }
780
781 static void event_android_handle_timeout(struct event_timeout *priv)
782 {
783         callback_call_0(priv->cb);
784         if (!priv->multi)
785                 event_android_remove_timeout(priv);
786 }
787
788 static struct event_timeout *
789 event_android_add_timeout(int timeout, int multi, struct callback *cb)
790 {
791         struct event_timeout *ret = g_new0(struct event_timeout, 1);
792         ret->cb = cb;
793         ret->multi = multi;
794         ret->handle_timeout = event_android_handle_timeout;
795         ret->jni_timeout = (*jnienv)->NewObject(jnienv, NavitTimeoutClass, NavitTimeout_init, timeout, multi, (int)ret);
796         if (ret->jni_timeout)
797                 ret->jni_timeout = (*jnienv)->NewGlobalRef(jnienv, ret->jni_timeout);
798         return ret;
799 }
800
801
802 static struct event_idle *
803 event_android_add_idle(int priority, struct callback *cb)
804 {
805 #if 0
806         jobject ret;
807         dbg(1,"enter\n");
808         ret=(*jnienv)->NewObject(jnienv, NavitIdleClass, NavitIdle_init, (int)cb);
809         dbg(1,"result for %p=%p\n",cb,ret);
810         if (ret)
811                 ret = (*jnienv)->NewGlobalRef(jnienv, ret);
812         return (struct event_idle *)ret;
813 #endif
814         return (struct event_idle *)event_android_add_timeout(1, 1, cb);
815 }
816
817 static void
818 event_android_remove_idle(struct event_idle *ev)
819 {
820 #if 0
821         dbg(1,"enter %p\n",ev);
822         if (ev) {
823                 jobject obj=(jobject )ev;
824                 (*jnienv)->CallVoidMethod(jnienv, obj, NavitIdle_remove);
825                 (*jnienv)->DeleteGlobalRef(jnienv, obj);
826         }
827 #endif
828         event_android_remove_timeout((struct event_timeout *)ev);
829 }
830
831 static void
832 event_android_call_callback(struct callback_list *cb)
833 {
834         dbg(0,"enter\n");
835 }
836
837 static struct event_methods event_android_methods = {
838         event_android_main_loop_run,
839         event_android_main_loop_quit,
840         event_android_add_watch,
841         event_android_remove_watch,
842         event_android_add_timeout,
843         event_android_remove_timeout,
844         event_android_add_idle,
845         event_android_remove_idle,
846         event_android_call_callback,
847 };
848
849 static struct event_priv *
850 event_android_new(struct event_methods *meth)
851 {
852         dbg(0,"enter\n");
853         if (!find_class_global("org/navitproject/navit/NavitTimeout", &NavitTimeoutClass))
854                 return NULL;
855         NavitTimeout_init = (*jnienv)->GetMethodID(jnienv, NavitTimeoutClass, "<init>", "(IZI)V");
856         if (NavitTimeout_init == NULL) 
857                 return NULL;
858         NavitTimeout_remove = (*jnienv)->GetMethodID(jnienv, NavitTimeoutClass, "remove", "()V");
859         if (NavitTimeout_remove == NULL) 
860                 return NULL;
861 #if 0
862         if (!find_class_global("org/navitproject/navit/NavitIdle", &NavitIdleClass))
863                 return NULL;
864         NavitIdle_init = (*jnienv)->GetMethodID(jnienv, NavitIdleClass, "<init>", "(I)V");
865         if (NavitIdle_init == NULL) 
866                 return NULL;
867         NavitIdle_remove = (*jnienv)->GetMethodID(jnienv, NavitIdleClass, "remove", "()V");
868         if (NavitIdle_remove == NULL) 
869                 return NULL;
870 #endif
871
872         if (!find_class_global("org/navitproject/navit/NavitWatch", &NavitWatchClass))
873                 return NULL;
874         NavitWatch_init = (*jnienv)->GetMethodID(jnienv, NavitWatchClass, "<init>", "(IIII)V");
875         if (NavitWatch_init == NULL) 
876                 return NULL;
877         NavitWatch_remove = (*jnienv)->GetMethodID(jnienv, NavitWatchClass, "remove", "()V");
878         if (NavitWatch_remove == NULL) 
879                 return NULL;
880
881         if (!find_class_global("org/navitproject/navit/Navit", &NavitClass))
882                 return NULL;
883         Navit_disableSuspend = (*jnienv)->GetMethodID(jnienv, NavitClass, "disableSuspend", "()V");
884         if (Navit_disableSuspend == NULL) 
885                 return NULL;
886         Navit_exit = (*jnienv)->GetMethodID(jnienv, NavitClass, "exit", "()V");
887         if (Navit_exit == NULL) 
888                 return NULL;
889         dbg(0,"ok\n");
890         *meth=event_android_methods;
891         return NULL;
892 }
893
894
895 void
896 plugin_init(void)
897 {
898         dbg(0,"enter\n");
899         plugin_register_graphics_type("android", graphics_android_new);
900         plugin_register_event_type("android", event_android_new);
901 }