1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Thomas Martitz
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
25 #include "notification.h"
26 #include "appevents.h"
33 extern JNIEnv
*env_ptr
;
34 extern jclass RockboxService_class
;
35 extern jobject RockboxService_instance
;
37 static jmethodID updateNotification
, finishNotification
;
38 static jobject NotificationManager_instance
;
39 static jstring title
, artist
, album
, albumart
;
41 /* completely arbitrary dimensions. neded for find_albumart() */
42 static const struct dim dim
= { .width
= 200, .height
= 200 };
43 #define NZV(a) (a && a[0])
46 * notify about track change, and show track info */
47 static void track_changed_callback(void *param
)
49 struct mp3entry
* id3
= (struct mp3entry
*)param
;
53 /* passing NULL to DeleteLocalRef() is OK */
54 e
->DeleteLocalRef(env_ptr
, title
);
55 e
->DeleteLocalRef(env_ptr
, artist
);
56 e
->DeleteLocalRef(env_ptr
, album
);
57 e
->DeleteLocalRef(env_ptr
, albumart
);
60 const char * ptitle
= id3
->title
;
61 if (!ptitle
&& *id3
->path
)
62 { /* pass the filename as title if id3 info isn't available */
63 ptitle
= strip_extension(buf
, sizeof(buf
), strrchr(id3
->path
,'/') + 1);
66 title
= e
->NewStringUTF(env_ptr
, ptitle
?: "");
67 artist
= e
->NewStringUTF(env_ptr
, id3
->artist
?: "");
68 album
= e
->NewStringUTF(env_ptr
, id3
->album
?: "");
71 if (id3
->has_embedded_albumart
&& id3
->albumart
.type
== AA_TYPE_JPG
)
72 { /* extract albumart to a temporary file using mmap() */
73 snprintf(buf
, sizeof(buf
), "/sdcard/rockbox/.temp_albumart_%d.jpg",
75 int dst_fd
= creat(buf
, 0666);
78 int src_fd
= open(id3
->path
, O_RDONLY
);
79 off_t o_pos
= id3
->albumart
.pos
;
80 off_t pa_pos
= o_pos
& ~(sysconf(_SC_PAGE_SIZE
) - 1);
82 { /* align to page boundary */
83 int pos_diff
= o_pos
- pa_pos
;
84 unsigned char* p
= mmap(NULL
, id3
->albumart
.size
+ pos_diff
,
85 PROT_READ
, MAP_SHARED
, src_fd
, pa_pos
);
88 write(dst_fd
, p
+ pos_diff
, id3
->albumart
.size
);
89 munmap(p
, id3
->albumart
.size
+ pos_diff
);
90 albumart
= e
->NewStringUTF(env_ptr
, buf
);
97 else if (find_albumart(id3
, buf
, sizeof(buf
), &dim
))
99 albumart
= e
->NewStringUTF(env_ptr
, buf
);
102 e
->CallVoidMethod(env_ptr
, NotificationManager_instance
,
103 updateNotification
, title
, artist
, album
, albumart
);
108 * notify about track finishing */
109 static void track_finished_callback(void *param
)
113 e
->CallVoidMethod(env_ptr
, NotificationManager_instance
,
116 /* delete temporary albumart file */
118 snprintf(buf
, sizeof(buf
), "/sdcard/rockbox/.temp_albumart_%d.jpg",
123 void notification_init(void)
126 jfieldID nNM
= e
->GetFieldID(env_ptr
, RockboxService_class
,
127 "mFgRunner", "Lorg/rockbox/Helper/RunForegroundManager;");
128 NotificationManager_instance
= e
->GetObjectField(env_ptr
,
129 RockboxService_instance
, nNM
);
130 if (NotificationManager_instance
== NULL
)
132 DEBUGF("Failed to get RunForegroundManager instance. Performance will be bad");
136 jclass
class = e
->GetObjectClass(env_ptr
, NotificationManager_instance
);
137 updateNotification
= e
->GetMethodID(env_ptr
, class, "updateNotification",
138 "(Ljava/lang/String;"
141 "Ljava/lang/String;)V");
142 finishNotification
= e
->GetMethodID(env_ptr
, class, "finishNotification",
145 add_event(PLAYBACK_EVENT_TRACK_CHANGE
, false, track_changed_callback
);
146 add_event(PLAYBACK_EVENT_TRACK_FINISH
, false, track_finished_callback
);