[Android] [PATCH 06/13] libvlc: add VLCObject
Thomas Guillem
thomas at gllm.fr
Thu Jan 15 19:22:23 CET 2015
Base class for all future VLC objects: Media, MediaList, MediaDiscoverer, and
MediaPlayer in the future.
---
libvlc/jni/Android.mk | 2 +
libvlc/jni/event_thread.c | 201 ++++++++++++++++++++++++++
libvlc/jni/event_thread.h | 36 +++++
libvlc/jni/libvlcjni-vlcobject.c | 161 +++++++++++++++++++++
libvlc/jni/libvlcjni-vlcobject.h | 73 ++++++++++
libvlc/jni/libvlcjni.c | 78 +++++++++-
libvlc/jni/utils.h | 19 +++
libvlc/src/org/videolan/libvlc/VLCObject.java | 173 ++++++++++++++++++++++
8 files changed, 742 insertions(+), 1 deletion(-)
create mode 100644 libvlc/jni/event_thread.c
create mode 100644 libvlc/jni/event_thread.h
create mode 100644 libvlc/jni/libvlcjni-vlcobject.c
create mode 100644 libvlc/jni/libvlcjni-vlcobject.h
create mode 100644 libvlc/src/org/videolan/libvlc/VLCObject.java
diff --git a/libvlc/jni/Android.mk b/libvlc/jni/Android.mk
index e6308d1..ff0fdd8 100644
--- a/libvlc/jni/Android.mk
+++ b/libvlc/jni/Android.mk
@@ -5,6 +5,8 @@ LOCAL_MODULE := libvlcjni
LOCAL_SRC_FILES := libvlcjni.c libvlcjni-util.c libvlcjni-track.c
LOCAL_SRC_FILES += libvlcjni-equalizer.c
+LOCAL_SRC_FILES += libvlcjni-vlcobject.c
+LOCAL_SRC_FILES += event_thread.c
LOCAL_SRC_FILES += aout.c vout.c native_crash_handler.c thumbnailer.c
ifneq ($(ANDROID_API),android-21)
# compat functions not needed after android-21
diff --git a/libvlc/jni/event_thread.c b/libvlc/jni/event_thread.c
new file mode 100644
index 0000000..9696906
--- /dev/null
+++ b/libvlc/jni/event_thread.c
@@ -0,0 +1,201 @@
+/*****************************************************************************
+ * event-thread.c
+ *****************************************************************************
+ * Copyright © 2015 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <sys/queue.h>
+#include <pthread.h>
+
+#include "event_thread.h"
+#include "utils.h"
+
+#define LOG_TAG "EventThread"
+#include "log.h"
+
+#define THREAD_NAME "EventThread"
+extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
+extern void jni_detach_thread();
+extern int jni_get_env(JNIEnv **env);
+
+typedef struct event_queue_elm event_queue_elm;
+struct event_queue_elm
+{
+ libvlc_event_t event;
+ jweak jobj;
+ TAILQ_ENTRY(event_queue_elm) next;
+};
+typedef TAILQ_HEAD(, event_queue_elm) EVENT_QUEUE;
+
+struct event_thread {
+ bool b_run;
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ pthread_t thread;
+ EVENT_QUEUE queue;
+ jweak jobj_calling;
+};
+
+static void *
+EventThread_thread(void *data)
+{
+ JNIEnv *env;
+ event_thread *p_event_thread = data;
+
+ if (jni_attach_thread(&env, THREAD_NAME) < 0)
+ return NULL;
+
+ pthread_mutex_lock(&p_event_thread->lock);
+ while (p_event_thread->b_run)
+ {
+ jlong arg1 = -1, arg2 = -1;
+ event_queue_elm *event_elm;
+ libvlc_event_t *ev;
+
+ while (p_event_thread->b_run &&
+ !(event_elm = TAILQ_FIRST(&p_event_thread->queue)))
+ pthread_cond_wait(&p_event_thread->cond, &p_event_thread->lock);
+
+ if (!p_event_thread->b_run || event_elm == NULL)
+ continue;
+
+ ev = &event_elm->event;
+ TAILQ_REMOVE(&p_event_thread->queue, event_elm, next);
+ p_event_thread->jobj_calling = event_elm->jobj;
+
+ pthread_mutex_unlock(&p_event_thread->lock);
+
+ switch (ev->type)
+ {
+ case libvlc_MediaListItemAdded:
+ arg1 = ev->u.media_list_item_added.index;
+ break;
+ case libvlc_MediaListItemDeleted:
+ arg1 = ev->u.media_list_item_deleted.index;
+ break;
+ case libvlc_MediaMetaChanged:
+ arg1 = ev->u.media_meta_changed.meta_type;
+ break;
+ case libvlc_MediaDurationChanged:
+ arg1 = ev->u.media_duration_changed.new_duration;
+ break;
+ case libvlc_MediaStateChanged:
+ arg1 = ev->u.media_state_changed.new_state;
+ }
+
+ (*env)->CallVoidMethod(env, event_elm->jobj,
+ fields.VLCObject.dispatchEventFromNativeID,
+ (jint)ev->type, arg1, arg2);
+
+ free(event_elm);
+
+ pthread_mutex_lock(&p_event_thread->lock);
+ p_event_thread->jobj_calling = NULL;
+ pthread_cond_signal(&p_event_thread->cond);
+ }
+ pthread_mutex_unlock(&p_event_thread->lock);
+
+ jni_detach_thread();
+
+ return NULL;
+}
+
+event_thread *
+EventThread_create()
+{
+ event_thread *p_event_thread = calloc(1, sizeof(event_thread));
+ if (!p_event_thread)
+ return NULL;
+
+ pthread_mutex_init(&p_event_thread->lock, NULL);
+ pthread_cond_init(&p_event_thread->cond, NULL);
+ TAILQ_INIT(&p_event_thread->queue);
+
+ p_event_thread->b_run = true;
+ pthread_create(&p_event_thread->thread, NULL,
+ EventThread_thread, p_event_thread);
+
+ return p_event_thread;
+}
+
+void
+EventThread_destroy(event_thread *p_event_thread)
+{
+ event_queue_elm *event_elm, *event_elm_next;
+
+ pthread_mutex_lock(&p_event_thread->lock);
+ p_event_thread->b_run = false;
+
+ for (event_elm = TAILQ_FIRST(&p_event_thread->queue);
+ event_elm != NULL; event_elm = event_elm_next)
+ {
+ event_elm_next = TAILQ_NEXT(event_elm, next);
+ TAILQ_REMOVE(&p_event_thread->queue, event_elm, next);
+ free(event_elm);
+ }
+ pthread_cond_signal(&p_event_thread->cond);
+ pthread_mutex_unlock(&p_event_thread->lock);
+
+ pthread_join(p_event_thread->thread, NULL);
+
+ pthread_mutex_destroy(&p_event_thread->lock);
+ pthread_cond_destroy(&p_event_thread->cond);
+
+ free(p_event_thread);
+}
+
+void
+EventThread_add(event_thread *p_event_thread, const libvlc_event_t *ev,
+ jweak jobj)
+{
+ event_queue_elm *event_elm = (event_queue_elm *) calloc(1, sizeof(event_queue_elm));
+ if (!event_elm)
+ return;
+ event_elm->event = *ev;
+ event_elm->jobj = jobj;
+
+ pthread_mutex_lock(&p_event_thread->lock);
+ TAILQ_INSERT_TAIL(&p_event_thread->queue, event_elm, next);
+ pthread_cond_signal(&p_event_thread->cond);
+ pthread_mutex_unlock(&p_event_thread->lock);
+}
+
+void
+EventThread_clean(event_thread *p_event_thread, jweak jobj)
+{
+ event_queue_elm *event_elm, *event_elm_next;
+
+ pthread_mutex_lock(&p_event_thread->lock);
+
+ /* remove all events that will be called by the specified obj */
+ for (event_elm = TAILQ_FIRST(&p_event_thread->queue);
+ event_elm != NULL; event_elm = event_elm_next)
+ {
+ event_elm_next = TAILQ_NEXT(event_elm, next);
+ if (event_elm->jobj == jobj) {
+ TAILQ_REMOVE(&p_event_thread->queue, event_elm, next);
+ free(event_elm);
+ }
+ }
+
+ /* wait for the obj to finish java call (if any) */
+ while (p_event_thread->jobj_calling == jobj)
+ pthread_cond_wait(&p_event_thread->cond, &p_event_thread->lock);
+
+ pthread_mutex_unlock(&p_event_thread->lock);
+}
diff --git a/libvlc/jni/event_thread.h b/libvlc/jni/event_thread.h
new file mode 100644
index 0000000..dc0b4ff
--- /dev/null
+++ b/libvlc/jni/event_thread.h
@@ -0,0 +1,36 @@
+/*****************************************************************************
+ * event_thread.h
+ *****************************************************************************
+ * Copyright © 2015 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef EVENT_THREAD_H
+#define EVENT_THREAD_H
+
+#include <jni.h>
+#include <vlc/vlc.h>
+#include <vlc/libvlc_events.h>
+
+typedef struct event_thread event_thread;
+
+event_thread *EventThread_create();
+void EventThread_destroy(event_thread *p_event_thread);
+void EventThread_add(event_thread *p_event_thread, const libvlc_event_t *ev,
+ jobject jobj);
+void EventThread_clean(event_thread *p_event_thread, jobject jobj);
+
+#endif // EVENT_THREAD_H
diff --git a/libvlc/jni/libvlcjni-vlcobject.c b/libvlc/jni/libvlcjni-vlcobject.c
new file mode 100644
index 0000000..44a1f50
--- /dev/null
+++ b/libvlc/jni/libvlcjni-vlcobject.c
@@ -0,0 +1,161 @@
+/*****************************************************************************
+ * libvlcjni-vlcobject.c
+ *****************************************************************************
+ * Copyright © 2015 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <sys/queue.h>
+#include <pthread.h>
+
+#include "event_thread.h"
+#include "libvlcjni-vlcobject.h"
+
+struct vlcjni_object_owner
+{
+ jweak thiz;
+
+ libvlc_event_manager_t *p_event_manager;
+ const int *p_events;
+ event_thread *p_event_thread;
+};
+
+// XXX attach it to libvlc
+extern event_thread *get_global_event_thread();
+
+vlcjni_object *
+VLCJniObject_getInstance(JNIEnv *env, jobject thiz)
+{
+ return (vlcjni_object*)(intptr_t) (*env)->GetLongField(env, thiz,
+ fields.VLCObject.mInstanceID);
+}
+
+static void
+VLCJniObject_setInstance(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
+{
+ (*env)->SetLongField(env, thiz,
+ fields.VLCObject.mInstanceID,
+ (jlong)(intptr_t)p_obj);
+}
+
+vlcjni_object *
+VLCJniObject_newFromLibVlc(JNIEnv *env, jobject thiz,
+ libvlc_instance_t *p_libvlc)
+{
+ vlcjni_object *p_obj;
+ libvlc_event_manager_t *ev;
+
+ p_obj = VLCJniObject_getInstance(env, thiz);
+ if (p_obj)
+ return NULL;
+
+ p_obj = calloc(1, sizeof(vlcjni_object));
+ if (!p_obj)
+ goto error;
+
+ p_obj->p_owner = calloc(1, sizeof(vlcjni_object_owner));
+ if (!p_obj->p_owner)
+ goto error;
+
+ p_obj->p_libvlc = p_libvlc;
+ libvlc_retain(p_libvlc);
+
+ p_obj->p_owner->thiz = (*env)->NewWeakGlobalRef(env, thiz);
+ if (!p_obj->p_owner->thiz)
+ goto error;
+
+ p_obj->p_owner->p_event_thread = get_global_event_thread();
+
+ VLCJniObject_setInstance(env, thiz, p_obj);
+
+ return p_obj;
+
+error:
+ VLCJniObject_release(env, thiz, p_obj);
+ return NULL;
+}
+
+vlcjni_object *
+VLCJniObject_newFromJavaLibVlc(JNIEnv *env, jobject thiz,
+ jobject libVlc)
+{
+ libvlc_instance_t *p_libvlc = getLibVlcInstance(env, libVlc);
+ if (!p_libvlc)
+ return NULL;
+ return VLCJniObject_newFromLibVlc(env, thiz, p_libvlc);
+}
+
+void
+VLCJniObject_release(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
+{
+ if (p_obj)
+ {
+ if (p_obj->p_libvlc)
+ libvlc_release(p_obj->p_libvlc);
+
+ if (p_obj->p_owner->thiz)
+ (*env)->DeleteWeakGlobalRef(env, p_obj->p_owner->thiz);
+
+ free(p_obj->p_owner);
+ free(p_obj);
+ VLCJniObject_setInstance(env, thiz, NULL);
+ }
+}
+
+static void
+VLCJniObject_eventCallback(const libvlc_event_t *ev, void *data)
+{
+ vlcjni_object *p_obj = data;
+
+ EventThread_add(p_obj->p_owner->p_event_thread, ev, p_obj->p_owner->thiz);
+}
+
+void
+VLCJniObject_attachEvents(vlcjni_object *p_obj, libvlc_event_manager_t *p_ev,
+ const int *p_events)
+{
+ if (!p_ev || !p_events || p_obj->p_owner->p_event_manager
+ || p_obj->p_owner->p_events)
+ return;
+
+ p_obj->p_owner->p_event_manager = p_ev;
+ p_obj->p_owner->p_events = p_events;
+
+ for(int i = 0; p_obj->p_owner->p_events[i] != -1; ++i)
+ libvlc_event_attach(p_obj->p_owner->p_event_manager,
+ p_obj->p_owner->p_events[i],
+ VLCJniObject_eventCallback, p_obj);
+}
+
+void
+Java_org_videolan_libvlc_VLCObject_nativeDetachEvents(JNIEnv *env, jobject thiz)
+{
+ vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
+
+ if (!p_obj || !p_obj->p_owner->p_event_manager
+ || !p_obj->p_owner->p_events)
+ return;
+
+ for(int i = 0; p_obj->p_owner->p_events[i] != -1; ++i)
+ libvlc_event_detach(p_obj->p_owner->p_event_manager,
+ p_obj->p_owner->p_events[i],
+ VLCJniObject_eventCallback, p_obj);
+ p_obj->p_owner->p_event_manager = NULL;
+ p_obj->p_owner->p_events = NULL;
+
+ EventThread_clean(p_obj->p_owner->p_event_thread, p_obj->p_owner->thiz);
+}
diff --git a/libvlc/jni/libvlcjni-vlcobject.h b/libvlc/jni/libvlcjni-vlcobject.h
new file mode 100644
index 0000000..f833f39
--- /dev/null
+++ b/libvlc/jni/libvlcjni-vlcobject.h
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * libvlcjni-vlcobject.h
+ *****************************************************************************
+ * Copyright © 2015 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef LIBVLCJNI_VLCOBJECT_H
+#define LIBVLCJNI_VLCOBJECT_H
+
+#include <stdbool.h>
+
+#include <jni.h>
+#include <vlc/vlc.h>
+#include <vlc/libvlc_media_list.h>
+#include <vlc/libvlc_media_discoverer.h>
+
+#include "utils.h"
+#define LOG_TAG "VLC/JNI/VLCObject"
+#include "log.h"
+
+typedef struct vlcjni_object_owner vlcjni_object_owner;
+
+typedef struct vlcjni_object vlcjni_object;
+struct vlcjni_object
+{
+ libvlc_instance_t *p_libvlc;
+ union {
+ libvlc_media_t *p_m;
+ libvlc_media_list_t *p_ml;
+ libvlc_media_discoverer_t *p_md;
+ } u;
+ vlcjni_object_owner *p_owner;
+};
+
+vlcjni_object *VLCJniObject_getInstance(JNIEnv *env, jobject thiz);
+
+vlcjni_object *VLCJniObject_newFromJavaLibVlc(JNIEnv *env, jobject thiz,
+ jobject libVlc);
+
+vlcjni_object *VLCJniObject_newFromLibVlc(JNIEnv *env, jobject thiz,
+ libvlc_instance_t *p_libvlc);
+
+void VLCJniObject_release(JNIEnv *env, jobject thiz, vlcjni_object *p_obj);
+
+void VLCJniObject_attachEvents(vlcjni_object *p_obj,
+ libvlc_event_manager_t *p_ev,
+ const int *p_events);
+
+static inline void throw_IllegalStateException(JNIEnv *env, const char *p_error)
+{
+ (*env)->ThrowNew(env, fields.IllegalStateException.clazz, p_error);
+}
+
+static inline void throw_IllegalArgumentException(JNIEnv *env, const char *p_error)
+{
+ (*env)->ThrowNew(env, fields.IllegalArgumentException.clazz, p_error);
+}
+
+#endif // LIBVLCJNI_VLCOBJECT_H
diff --git a/libvlc/jni/libvlcjni.c b/libvlc/jni/libvlcjni.c
index 664092a..393dc04 100644
--- a/libvlc/jni/libvlcjni.c
+++ b/libvlc/jni/libvlcjni.c
@@ -35,6 +35,7 @@
#include <android/api-level.h>
+#include "event_thread.h"
#include "libvlcjni.h"
#include "aout.h"
#include "vout.h"
@@ -48,6 +49,8 @@
#define LOG_TAG "VLC/JNI/main"
#include "log.h"
+struct fields fields;
+
#define VLC_JNI_VERSION JNI_VERSION_1_2
#define THREAD_NAME "libvlcjni"
@@ -209,21 +212,94 @@ end:
jni_detach_thread();
}
+// XXX: attach it to libvlc
+static event_thread *global_event_thread;
+event_thread *
+get_global_event_thread()
+{
+ return global_event_thread;
+}
+
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
+ JNIEnv* env = NULL;
// Keep a reference on the Java VM.
myVm = vm;
+ if ((*vm)->GetEnv(vm, (void**) &env, VLC_JNI_VERSION) != JNI_OK)
+ return -1;
pthread_mutex_init(&vout_android_lock, NULL);
pthread_cond_init(&vout_android_surf_attached, NULL);
+#define GET_CLASS(clazz, str) do { \
+ (clazz) = (*env)->FindClass(env, (str)); \
+ if (!(clazz)) { \
+ LOGE("FindClass(%s) failed", (str)); \
+ return -1; \
+ } \
+ (clazz) = (jclass) (*env)->NewGlobalRef(env, (clazz)); \
+ if (!(clazz)) { \
+ LOGE("NewGlobalRef(%s) failed", (str)); \
+ return -1; \
+ } \
+} while (0)
+
+#define GET_ID(get, id, clazz, str, args) do { \
+ (id) = (*env)->get(env, (clazz), (str), (args)); \
+ if (!(id)) { \
+ LOGE(#get"(%s) failed", (str)); \
+ return -1; \
+ } \
+} while (0)
+
+ GET_CLASS(fields.IllegalStateException.clazz,
+ "java/lang/IllegalStateException");
+ GET_CLASS(fields.IllegalArgumentException.clazz,
+ "java/lang/IllegalArgumentException");
+ GET_CLASS(fields.String.clazz,
+ "java/lang/String");
+ GET_CLASS(fields.VLCObject.clazz,
+ "org/videolan/libvlc/VLCObject");
+
+ GET_ID(GetFieldID,
+ fields.VLCObject.mInstanceID,
+ fields.VLCObject.clazz,
+ "mInstance", "J");
+
+ GET_ID(GetMethodID,
+ fields.VLCObject.dispatchEventFromNativeID,
+ fields.VLCObject.clazz,
+ "dispatchEventFromNative", "(IJJ)V");
+
+#undef GET_CLASS
+#undef GET_ID
+
+ global_event_thread = EventThread_create();
+ if (!global_event_thread) {
+ LOGE("EventThread_create failed");
+ return -1;
+ }
+
LOGD("JNI interface loaded.");
return VLC_JNI_VERSION;
}
-void JNI_OnUnload(JavaVM* vm, void* reserved) {
+void JNI_OnUnload(JavaVM* vm, void* reserved)
+{
+ JNIEnv* env = NULL;
+
pthread_mutex_destroy(&vout_android_lock);
pthread_cond_destroy(&vout_android_surf_attached);
+
+ if ((*vm)->GetEnv(vm, (void**) &env, VLC_JNI_VERSION) != JNI_OK)
+ return;
+
+ EventThread_destroy(global_event_thread);
+
+ (*env)->DeleteGlobalRef(env, fields.IllegalStateException.clazz);
+ (*env)->DeleteGlobalRef(env, fields.IllegalArgumentException.clazz);
+ (*env)->DeleteGlobalRef(env, fields.String.clazz);
+ (*env)->DeleteGlobalRef(env, fields.VLCObject.clazz);
}
int jni_attach_thread(JNIEnv **env, const char *thread_name)
diff --git a/libvlc/jni/utils.h b/libvlc/jni/utils.h
index 5da3514..14879bc 100644
--- a/libvlc/jni/utils.h
+++ b/libvlc/jni/utils.h
@@ -21,6 +21,25 @@
#ifndef LIBVLCJNI_UTILS_H
#define LIBVLCJNI_UTILS_H
+struct fields {
+ struct {
+ jclass clazz;
+ } IllegalStateException;
+ struct {
+ jclass clazz;
+ } IllegalArgumentException;
+ struct {
+ jclass clazz;
+ } String;
+ struct {
+ jclass clazz;
+ jfieldID mInstanceID;
+ jmethodID dispatchEventFromNativeID;
+ } VLCObject;
+};
+
+extern struct fields fields;
+
libvlc_media_t *new_media(JNIEnv *env, jobject thiz, jstring fileLocation, bool noOmx, bool noVideo);
libvlc_instance_t *getLibVlcInstance(JNIEnv *env, jobject thiz);
diff --git a/libvlc/src/org/videolan/libvlc/VLCObject.java b/libvlc/src/org/videolan/libvlc/VLCObject.java
new file mode 100644
index 0000000..374c607
--- /dev/null
+++ b/libvlc/src/org/videolan/libvlc/VLCObject.java
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ * VLCObject.java
+ *****************************************************************************
+ * Copyright © 2015 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+package org.videolan.libvlc;
+
+public abstract class VLCObject {
+ private final static String TAG = "LibVLC/VlcObject";
+
+ public static class Events {
+ public static final int MediaMetaChanged = 0;
+ public static final int MediaSubItemAdded = 1;
+ public static final int MediaDurationChanged = 2;
+ public static final int MediaParsedChanged = 3;
+ //public static final int MediaFreed = 4;
+ public static final int MediaStateChanged = 5;
+ public static final int MediaSubItemTreeAdded = 6;
+
+ //public static final int MediaPlayerMediaChanged = 0x100;
+ //public static final int MediaPlayerNothingSpecial = 0x101;
+ //public static final int MediaPlayerOpening = 0x102;
+ //public static final int MediaPlayerBuffering = 0x103;
+ //public static final int MediaPlayerPlaying = 0x104;
+ //public static final int MediaPlayerPaused = 0x105;
+ //public static final int MediaPlayerStopped = 0x106;
+ //public static final int MediaPlayerForward = 0x107;
+ //public static final int MediaPlayerBackward = 0x108;
+ //public static final int MediaPlayerEndReached = 0x109;
+ //public static final int MediaPlayerEncounteredError = 0x10a;
+ //public static final int MediaPlayerTimeChanged = 0x10b;
+ //public static final int MediaPlayerPositionChanged = 0x10c;
+ //public static final int MediaPlayerSeekableChanged = 0x10d;
+ //public static final int MediaPlayerPausableChanged = 0x10e;
+ //public static final int MediaPlayerTitleChanged = 0x10f;
+ //public static final int MediaPlayerSnapshotTaken = 0x110;
+ //public static final int MediaPlayerLengthChanged = 0x111;
+ //public static final int MediaPlayerVout = 0x112;
+
+ public static final int MediaListItemAdded = 0x200;
+ //public static final int MediaListWillAddItem = 0x201;
+ public static final int MediaListItemDeleted = 0x202;
+ //public static final int MediaListWillDeleteItem = 0x203;
+
+ //public static final int MediaListViewItemAdded = 0x300;
+ //public static final int MediaListViewWillAddItem = 0x301;
+ //public static final int MediaListViewItemDeleted = 0x302;
+ //public static final int MediaListViewWillDeleteItem = 0x303;
+
+ //public static final int MediaListPlayerPlayed = 0x400;
+ //public static final int MediaListPlayerNextItemSet = 0x401;
+ //public static final int MediaListPlayerStopped = 0x402;
+
+ public static final int MediaDiscovererStarted = 0x500;
+ public static final int MediaDiscovererEnded = 0x501;
+
+ //public static final int VlmMediaAdded = 0x600;
+ //public static final int VlmMediaRemoved = 0x601;
+ //public static final int VlmMediaChanged = 0x602;
+ //public static final int VlmMediaInstanceStarted = 0x603;
+ //public static final int VlmMediaInstanceStopped = 0x604;
+ //public static final int VlmMediaInstanceStatusInit = 0x605;
+ //public static final int VlmMediaInstanceStatusOpening = 0x606;
+ //public static final int VlmMediaInstanceStatusPlaying = 0x607;
+ //public static final int VlmMediaInstanceStatusPause = 0x608;
+ //public static final int VlmMediaInstanceStatusEnd = 0x609;
+ //public static final int VlmMediaInstanceStatusError = 0x60a;
+ }
+
+ /**
+ * Listener for libvlc events
+ *
+ * @see Events
+ */
+ public interface EventListener {
+ public void onEvent(int event, long arg1, long arg2);
+ }
+
+ private EventListener mEventListener = null;
+ private int mNativeRefCount = 1;
+
+ /**
+ * Returns true if native object is released
+ */
+ public synchronized boolean isReleased() {
+ return mNativeRefCount == 0;
+ }
+
+ /**
+ * Increment internal ref count of the native object.
+ */
+ public synchronized final void retain() {
+ if (mNativeRefCount > 0)
+ mNativeRefCount++;
+ }
+
+ /**
+ * Release the native object if ref count is 1.
+ *
+ * After this call, native calls are not possible anymore.
+ * You can still call others methods to retrieve cached values.
+ * For example: if you parse, then release a media, you'll still be able to retrieve all Metas or Tracks infos.
+ */
+ public final void release() {
+ int refCount = -1;
+ synchronized (this) {
+ if (mNativeRefCount == 0)
+ return;
+ if (mNativeRefCount > 0) {
+ refCount = --mNativeRefCount;
+ }
+ // clear event list
+ if (refCount == 0)
+ setEventListener(null);
+ }
+ if (refCount == 0) {
+ // detach events when not synchronized since onEvent is executed synchronized
+ nativeDetachEvents();
+ synchronized (this) {
+ onReleaseNative();
+ }
+ }
+ }
+
+ /**
+ * Set an event listener.
+ *
+ * @param listener see {@link EventListener}
+ */
+ public synchronized final void setEventListener(EventListener listener) {
+ mEventListener = listener;
+ }
+
+ /**
+ * Called when libvlc send events.
+ *
+ * @param event
+ * @param arg1
+ * @param arg2
+ * @return true if event should be spread to listeners
+ */
+ protected abstract boolean onEventNative(int event, long arg1, long arg2);
+
+ /**
+ * Called when native object is released (refcount is 0).
+ *
+ * This is where you must release native resources.
+ */
+ protected abstract void onReleaseNative();
+
+ /* JNI */
+ private long mInstance = 0; // Read-only, reserved for JNI
+ private synchronized void dispatchEventFromNative(int event, long arg1, long arg2) {
+ if (onEventNative(event, arg1, arg2) && mEventListener != null)
+ mEventListener.onEvent(event, arg1, arg2);;
+ }
+ private final native void nativeDetachEvents();
+}
--
2.1.3
More information about the Android
mailing list