[Android] MediaList: add support for events
Edward Wang
git at videolan.org
Wed Aug 28 16:34:19 CEST 2013
vlc-ports/android | branch: master | Edward Wang <edward.c.wang at compdigitec.com> | Tue Aug 27 21:25:50 2013 +0200| [569e6ff59f508cd48c23f83445792dc414d341b6] | committer: Edward Wang
MediaList: add support for events
> http://git.videolan.org/gitweb.cgi/vlc-ports/android.git/?a=commit;h=569e6ff59f508cd48c23f83445792dc414d341b6
---
vlc-android/jni/libvlcjni-medialist.c | 94 ++++++++++++++++++++
vlc-android/jni/libvlcjni.c | 9 --
.../src/org/videolan/libvlc/EventHandler.java | 2 +-
vlc-android/src/org/videolan/libvlc/MediaList.java | 8 ++
4 files changed, 103 insertions(+), 10 deletions(-)
diff --git a/vlc-android/jni/libvlcjni-medialist.c b/vlc-android/jni/libvlcjni-medialist.c
index 6a99b60..4c33356 100644
--- a/vlc-android/jni/libvlcjni-medialist.c
+++ b/vlc-android/jni/libvlcjni-medialist.c
@@ -21,15 +21,91 @@
#include <jni.h>
#include <vlc/vlc.h>
#include <vlc/libvlc_media_list.h>
+#include <stdlib.h>
#include "utils.h"
#define LOG_TAG "VLC/JNI/MediaList"
#include "log.h"
+/** Unique Java VM instance, as defined in libvlcjni.c */
+extern JavaVM *myVm;
+
libvlc_media_list_t* getMediaList(JNIEnv *env, jobject thiz) {
return (libvlc_media_list_t*)(intptr_t)getLong(env, thiz, "mMediaListInstance");
}
+// data is the MediaList Java object of the media list
+static void vlc_media_list_event_callback(const libvlc_event_t *ev, void *data)
+{
+ jobject eventHandlerInstance = (jobject)(intptr_t)data;
+ JNIEnv *env;
+
+ bool isAttached = false;
+
+ if (eventHandlerInstance == NULL)
+ return;
+
+ if ((*myVm)->GetEnv(myVm, (void**) &env, JNI_VERSION_1_2) < 0) {
+ if ((*myVm)->AttachCurrentThread(myVm, &env, NULL) < 0)
+ return;
+ isAttached = true;
+ }
+
+ /* Creating the bundle in C allows us to subscribe to more events
+ * and get better flexibility for each event. For example, we can
+ * have totally different types of data for each event, instead of,
+ * for example, only an integer and/or string.
+ */
+ jclass clsBundle = (*env)->FindClass(env, "android/os/Bundle");
+ jmethodID clsCtor = (*env)->GetMethodID(env, clsBundle, "<init>", "()V" );
+ jobject bundle = (*env)->NewObject(env, clsBundle, clsCtor);
+
+ jmethodID putInt = (*env)->GetMethodID(env, clsBundle, "putInt", "(Ljava/lang/String;I)V" );
+ jmethodID putFloat = (*env)->GetMethodID(env, clsBundle, "putFloat", "(Ljava/lang/String;F)V" );
+ jmethodID putString = (*env)->GetMethodID(env, clsBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V" );
+
+ jstring item_uri = (*env)->NewStringUTF(env, "item_uri");
+ jstring item_index = (*env)->NewStringUTF(env, "item_index");
+ char* mrl = libvlc_media_get_mrl(
+ ev->type == libvlc_MediaListItemAdded ?
+ ev->u.media_list_item_added.item :
+ ev->u.media_list_item_deleted.item
+ );
+ jstring item_uri_value = (*env)->NewStringUTF(env, mrl);
+ jint item_index_value;
+ if(ev->type == libvlc_MediaListItemAdded)
+ item_index_value = ev->u.media_list_item_added.index;
+ else
+ item_index_value = ev->u.media_list_item_deleted.index;
+
+ (*env)->CallVoidMethod(env, bundle, putString, item_uri, item_uri_value);
+ (*env)->CallVoidMethod(env, bundle, putInt, item_index, item_index_value);
+
+ (*env)->DeleteLocalRef(env, item_uri);
+ (*env)->DeleteLocalRef(env, item_uri_value);
+ (*env)->DeleteLocalRef(env, item_index);
+ free(mrl);
+
+ /* Get the object class */
+ jclass cls = (*env)->GetObjectClass(env, eventHandlerInstance);
+ if (!cls) {
+ LOGE("EventHandler: failed to get class reference");
+ goto end;
+ }
+
+ /* Find the callback ID */
+ jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(ILandroid/os/Bundle;)V");
+ if (methodID) {
+ (*env)->CallVoidMethod(env, eventHandlerInstance, methodID, ev->type, bundle);
+ } else {
+ LOGE("EventHandler: failed to get the callback method");
+ }
+
+end:
+ if (isAttached)
+ (*myVm)->DetachCurrentThread(myVm);
+}
+
jlong Java_org_videolan_libvlc_MediaList_init(JNIEnv *env, jobject thiz, jobject libvlcJava) {
libvlc_media_list_t* p_ml = libvlc_media_list_new((libvlc_instance_t*)(intptr_t)getLong(env, libvlcJava, "mLibVlcInstance"));
if(!p_ml) {
@@ -37,12 +113,30 @@ jlong Java_org_videolan_libvlc_MediaList_init(JNIEnv *env, jobject thiz, jobject
(*env)->ThrowNew(env, exc, "Unable to create LibVLC media list");
return (jlong)(intptr_t)NULL;
}
+
+ jclass cls = (*env)->GetObjectClass(env, thiz);
+ jfieldID fieldID = (*env)->GetFieldID(env, cls, "mEventHandler", "Lorg/videolan/libvlc/EventHandler;");
+ jobject eventHandler = (*env)->GetObjectField(env, thiz, fieldID);
+ jobject globalRef = getEventHandlerReference(env, thiz, eventHandler);
+
+ setLong(env, thiz, "mEventHanderGlobalRef", (jlong)(intptr_t)globalRef);
+
+ /* Connect the event manager */
+ libvlc_event_manager_t *ev = libvlc_media_list_event_manager(p_ml);
+ static const libvlc_event_type_t mp_events[] = {
+ libvlc_MediaListItemAdded,
+ libvlc_MediaListItemDeleted,
+ };
+ for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
+ libvlc_event_attach(ev, mp_events[i], vlc_media_list_event_callback, globalRef);
+
return (jlong)(intptr_t)p_ml;
}
void Java_org_videolan_libvlc_MediaList_nativeDestroy(JNIEnv *env, jobject thiz) {
libvlc_media_list_t* p_ml = getMediaList(env, thiz);
libvlc_media_list_release(p_ml);
+ (*env)->DeleteGlobalRef(env, (jobject)(intptr_t)getLong(env, thiz, "mEventHanderGlobalRef"));
}
void Java_org_videolan_libvlc_MediaList_remove(JNIEnv *env, jobject thiz, jint position) {
diff --git a/vlc-android/jni/libvlcjni.c b/vlc-android/jni/libvlcjni.c
index 6bc4dfe..6d37579 100644
--- a/vlc-android/jni/libvlcjni.c
+++ b/vlc-android/jni/libvlcjni.c
@@ -276,15 +276,6 @@ void Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
LOGI("LibVLC initialized: %p", instance);
libvlc_log_set(instance, debug_log, &verbosity);
-
- /* Connect the event manager */
- libvlc_event_manager_t *ev = libvlc_media_list_event_manager(pointer);
- static const libvlc_event_type_t mp_events[] = {
- libvlc_MediaListItemAdded,
- libvlc_MediaListItemDeleted,
- };
- for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
- libvlc_event_attach(ev, mp_events[i], vlc_event_callback, myVm);
}
void Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject thiz)
diff --git a/vlc-android/src/org/videolan/libvlc/EventHandler.java b/vlc-android/src/org/videolan/libvlc/EventHandler.java
index e2a250c..a1b8cd3 100644
--- a/vlc-android/src/org/videolan/libvlc/EventHandler.java
+++ b/vlc-android/src/org/videolan/libvlc/EventHandler.java
@@ -91,7 +91,7 @@ public class EventHandler {
private ArrayList<Handler> mEventHandler;
private static EventHandler mInstance;
- private EventHandler() {
+ EventHandler() {
mEventHandler = new ArrayList<Handler>();
}
diff --git a/vlc-android/src/org/videolan/libvlc/MediaList.java b/vlc-android/src/org/videolan/libvlc/MediaList.java
index 67da641..80ad13c 100644
--- a/vlc-android/src/org/videolan/libvlc/MediaList.java
+++ b/vlc-android/src/org/videolan/libvlc/MediaList.java
@@ -27,10 +27,13 @@ public class MediaList {
private static final String TAG = "VLC/LibVLC/MediaList";
private long mMediaListInstance = 0; // Read-only, reserved for JNI
+ private long mEventHanderGlobalRef = 0; // Read-only, reserved for JNI
private LibVLC mLibVLC; // Used to create new objects that require a libvlc instance
private boolean destroyed = false;
+ private EventHandler mEventHandler;
public MediaList(LibVLC libVLC) {
+ mEventHandler = new EventHandler(); // used in init() below to fire events at the correct targets
mMediaListInstance = init(libVLC);
mLibVLC = libVLC;
}
@@ -49,6 +52,7 @@ public class MediaList {
public void destroy() {
nativeDestroy();
mMediaListInstance = 0;
+ mEventHanderGlobalRef = 0;
mLibVLC = null;
destroyed = true;
}
@@ -74,6 +78,10 @@ public class MediaList {
*/
public native String getMRL(int position);
+ public EventHandler getEventHandler() {
+ return mEventHandler;
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
More information about the Android
mailing list