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"
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
;
50 JNIEnv
*env_ptr
= getJavaEnvironment();
54 /* passing NULL to DeleteLocalRef() is OK */
55 e
->DeleteLocalRef(env_ptr
, title
);
56 e
->DeleteLocalRef(env_ptr
, artist
);
57 e
->DeleteLocalRef(env_ptr
, album
);
58 e
->DeleteLocalRef(env_ptr
, albumart
);
61 const char * ptitle
= id3
->title
;
62 if (!ptitle
&& *id3
->path
)
63 { /* pass the filename as title if id3 info isn't available */
64 ptitle
= strip_extension(buf
, sizeof(buf
), strrchr(id3
->path
,'/') + 1);
67 title
= e
->NewStringUTF(env_ptr
, ptitle
?: "");
68 artist
= e
->NewStringUTF(env_ptr
, id3
->artist
?: "");
69 album
= e
->NewStringUTF(env_ptr
, id3
->album
?: "");
72 if (id3
->embed_albumart
&& id3
->albumart
.type
== AA_TYPE_JPG
)
73 { /* extract albumart to a temporary file using mmap() */
74 snprintf(buf
, sizeof(buf
), "/sdcard/rockbox/.temp_albumart_%d.jpg",
76 int dst_fd
= creat(buf
, 0666);
79 int src_fd
= open(id3
->path
, O_RDONLY
);
80 off_t o_pos
= id3
->albumart
.pos
;
81 off_t pa_pos
= o_pos
& ~(sysconf(_SC_PAGE_SIZE
) - 1);
83 { /* align to page boundary */
84 int pos_diff
= o_pos
- pa_pos
;
85 unsigned char* p
= mmap(NULL
, id3
->albumart
.size
+ pos_diff
,
86 PROT_READ
, MAP_SHARED
, src_fd
, pa_pos
);
89 write(dst_fd
, p
+ pos_diff
, id3
->albumart
.size
);
90 munmap(p
, id3
->albumart
.size
+ pos_diff
);
91 albumart
= e
->NewStringUTF(env_ptr
, buf
);
98 else if (find_albumart(id3
, buf
, sizeof(buf
), &dim
))
100 albumart
= e
->NewStringUTF(env_ptr
, buf
);
103 e
->CallVoidMethod(env_ptr
, NotificationManager_instance
,
104 updateNotification
, title
, artist
, album
, albumart
);
109 * notify about track finishing */
110 static void track_finished_callback(void *param
)
113 JNIEnv
*env_ptr
= getJavaEnvironment();
115 e
->CallVoidMethod(env_ptr
, NotificationManager_instance
,
118 /* delete temporary albumart file */
120 snprintf(buf
, sizeof(buf
), "/sdcard/rockbox/.temp_albumart_%d.jpg",
125 void notification_init(void)
127 JNIEnv
*env_ptr
= getJavaEnvironment();
129 jfieldID nNM
= e
->GetFieldID(env_ptr
, RockboxService_class
,
130 "fg_runner", "Lorg/rockbox/Helper/RunForegroundManager;");
131 jobject nMN_instance
= e
->GetObjectField(env_ptr
,
132 RockboxService_instance
, nNM
);
133 if (nMN_instance
== NULL
)
135 DEBUGF("Failed to get RunForegroundManager instance. Performance will be bad");
138 NotificationManager_instance
= e
->NewGlobalRef(env_ptr
, nMN_instance
);
140 jclass
class = e
->GetObjectClass(env_ptr
, NotificationManager_instance
);
141 updateNotification
= e
->GetMethodID(env_ptr
, class, "updateNotification",
142 "(Ljava/lang/String;"
145 "Ljava/lang/String;)V");
146 finishNotification
= e
->GetMethodID(env_ptr
, class, "finishNotification",
149 add_event(PLAYBACK_EVENT_TRACK_CHANGE
, false, track_changed_callback
);
150 add_event(PLAYBACK_EVENT_TRACK_FINISH
, false, track_finished_callback
);