[Android] [WIP PATCH 08/11] libvlc: add VlcObject
Thomas Guillem
thomas at gllm.fr
Tue Dec 23 18:38:29 CET 2014
base class for all future Vlc objects (Media, MediaList, MediaDiscoverer...)
---
libvlc/jni/Android.mk | 1 +
libvlc/jni/libvlcjni-vlcobject.c | 199 ++++++++++++++++++++++++++
libvlc/jni/libvlcjni-vlcobject.h | 63 ++++++++
libvlc/src/org/videolan/libvlc/VlcObject.java | 166 +++++++++++++++++++++
4 files changed, 429 insertions(+)
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..e2f1166 100644
--- a/libvlc/jni/Android.mk
+++ b/libvlc/jni/Android.mk
@@ -5,6 +5,7 @@ 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 += 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/libvlcjni-vlcobject.c b/libvlc/jni/libvlcjni-vlcobject.c
new file mode 100644
index 0000000..d62d05a
--- /dev/null
+++ b/libvlc/jni/libvlcjni-vlcobject.c
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * libvlcjni-vlcobject.c
+ *****************************************************************************
+ * Copyright © 2014 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 "libvlcjni-vlcobject.h"
+
+#define THREAD_NAME "VlcObject"
+extern int jni_attach_thread(JNIEnv **env, const char *thread_name);
+extern void jni_detach_thread();
+extern int jni_get_env(JNIEnv **env);
+
+struct vlcjni_object_owner
+{
+ bool b_dispatch_events;
+ libvlc_event_manager_t *p_ev;
+ const int *p_events;
+ jobject thiz;
+ jmethodID dispatchEventID;
+};
+
+// XXX DBG
+#include <pthread.h>
+static int DBG_allocCount = 0;
+static pthread_mutex_t DBG_allocMtx = PTHREAD_MUTEX_INITIALIZER;
+
+vlcjni_object *
+VlcJniObject_getInstance(JNIEnv *env, jobject thiz)
+{
+ return (vlcjni_object*)(intptr_t)getLong(env, thiz, "mInstance");
+}
+
+static void
+VlcJniObject_setInstance(JNIEnv *env, jobject thiz, vlcjni_object *p_obj)
+{
+ setLong(env, thiz, "mInstance", (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;
+ jclass cls;
+
+ 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)->NewGlobalRef(env, thiz);
+ if (!p_obj->p_owner->thiz)
+ goto error;
+
+ cls = (*env)->FindClass(env, "org/videolan/libvlc/VlcObject");
+ if (!cls)
+ goto error;
+
+ p_obj->p_owner->dispatchEventID = (*env)->GetMethodID(env, cls,
+ "dispatchEventFromNative",
+ "(IJJ)V");
+ if (!p_obj->p_owner->dispatchEventID)
+ goto error;
+
+ VlcJniObject_setInstance(env, thiz, p_obj);
+
+pthread_mutex_lock(&DBG_allocMtx);
+DBG_allocCount++;
+LOGE("DBG_allocCount: %d", DBG_allocCount);
+pthread_mutex_unlock(&DBG_allocMtx);
+ 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)->DeleteGlobalRef(env, p_obj->p_owner->thiz);
+
+ free(p_obj->p_owner);
+ free(p_obj);
+ VlcJniObject_setInstance(env, thiz, NULL);
+
+pthread_mutex_lock(&DBG_allocMtx);
+DBG_allocCount--;
+LOGE("DBG_allocCount: %d", DBG_allocCount);
+pthread_mutex_unlock(&DBG_allocMtx);
+ }
+}
+
+static void
+VlcJniObject_eventCallback(const libvlc_event_t *ev, void *data)
+{
+ JNIEnv *env;
+ vlcjni_object *p_obj = data;
+ int64_t arg1 = -1, arg2 = -1;
+ bool isAttached = false;
+
+ if (ev->type == libvlc_MediaListWillAddItem
+ || ev->type == libvlc_MediaListWillDeleteItem
+ || ev->type == libvlc_MediaListViewWillAddItem
+ || ev->type == libvlc_MediaListViewWillDeleteItem)
+ return;
+
+ 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;
+ }
+
+ if (jni_get_env(&env) < 0) {
+ if (jni_attach_thread(&env, THREAD_NAME) < 0)
+ return;
+ isAttached = true;
+ }
+
+ (*env)->CallVoidMethod(env, p_obj->p_owner->thiz,
+ p_obj->p_owner->dispatchEventID,
+ ev->type, arg1, arg2);
+
+ if (isAttached)
+ jni_detach_thread();
+}
+
+void
+VlcJniObject_attachEvents(vlcjni_object *p_obj, libvlc_event_manager_t *p_ev,
+ const int *p_events)
+{
+ if (!p_ev || !p_events)
+ return;
+ p_obj->p_owner->p_ev = 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_ev, 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_ev || !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_ev, p_obj->p_owner->p_events[i],
+ VlcJniObject_eventCallback, p_obj);
+ p_obj->p_owner->p_ev = NULL;
+ p_obj->p_owner->p_events = NULL;
+}
diff --git a/libvlc/jni/libvlcjni-vlcobject.h b/libvlc/jni/libvlcjni-vlcobject.h
new file mode 100644
index 0000000..6d2d84f
--- /dev/null
+++ b/libvlc/jni/libvlcjni-vlcobject.h
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * libvlcjni-vlcobject.h
+ *****************************************************************************
+ * Copyright © 2014 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);
+
+#endif // LIBVLCJNI_VLCOBJECT_H
diff --git a/libvlc/src/org/videolan/libvlc/VlcObject.java b/libvlc/src/org/videolan/libvlc/VlcObject.java
new file mode 100644
index 0000000..91e4cd8
--- /dev/null
+++ b/libvlc/src/org/videolan/libvlc/VlcObject.java
@@ -0,0 +1,166 @@
+/*****************************************************************************
+ * LibVLC.java
+ *****************************************************************************
+ * Copyright © 2010-2014 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;
+
+import android.os.Handler;
+import android.os.Looper;
+
+public abstract class VlcObject {
+ private final static String TAG = "LibVLC/VlcObject";
+
+ 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 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;
+
+ public interface Listener {
+ public void onEvent(int event, long arg1, long arg2);
+ }
+
+ private class EventRunnable implements Runnable {
+ public final Listener listener;
+ public final int event;
+ public final long arg1;
+ public final long arg2;
+
+ public EventRunnable(Listener listener, int event, long arg1, long arg2) {
+ this.listener = listener;
+ this.event = event;
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ }
+ @Override
+ public void run() {
+ listener.onEvent(event, arg1, arg2);
+ }
+ }
+
+ private Listener mListener = null;
+ private Handler mHandler = null;
+ private int mRefCount = 1;
+
+ /**
+ * increment internal ref count
+ */
+ public synchronized final void retain() {
+ if (mRefCount > 0)
+ mRefCount++;
+ }
+
+ /**
+ * release the object if ref count is 1
+ */
+ public final void release() {
+ int refCount = -1;
+ synchronized (this) {
+ if (mRefCount > 0) {
+ refCount = --mRefCount;
+ }
+ // clear event list
+ if (refCount == 0)
+ setListener(null);
+ }
+ if (refCount == 0) {
+ // detach events when not synchronized since onEvent is executed synchronized
+ nativeDetachEvents();
+ synchronized (this) {
+ onRelease();
+ }
+ }
+ }
+
+ /**
+ * Set a listener
+ *
+ * @param listener
+ * @throws LibVlcException
+ */
+ public synchronized final void setListener(Listener listener) {
+ if (mHandler != null)
+ mHandler.removeCallbacksAndMessages(null);
+ mListener = listener;
+ if (mListener != null && mHandler == null)
+ mHandler = new Handler(Looper.getMainLooper());
+ }
+
+ protected abstract void onEvent(int event, long arg1, long arg2);
+ protected abstract void onRelease();
+
+ /* JNI */
+ private long mInstance = 0; // Read-only, reserved for JNI
+ private synchronized void dispatchEventFromNative(int event, long arg1, long arg2) {
+ onEvent(event, arg1, arg2);
+ if (mListener != null)
+ mHandler.post(new EventRunnable(mListener, event, arg1, arg2));
+ }
+ private final native void nativeDetachEvents();
+}
--
2.1.3
More information about the Android
mailing list