[Android] [PATCH 4/4] libvlc: Add MediaDiscoverer

Thomas Guillem thomas at gllm.fr
Fri Dec 5 14:43:43 CET 2014


---
 libvlc/jni/Android.mk                              |   1 +
 libvlc/jni/libvlcjni-mediadiscoverer.c             | 141 +++++++++++++++++++++
 libvlc/jni/libvlcjni.c                             |  21 ++-
 libvlc/src/org/videolan/libvlc/EventHandler.java   |   7 +-
 libvlc/src/org/videolan/libvlc/LibVLC.java         |   6 +
 .../src/org/videolan/libvlc/MediaDiscoverer.java   |  87 +++++++++++++
 6 files changed, 258 insertions(+), 5 deletions(-)
 create mode 100644 libvlc/jni/libvlcjni-mediadiscoverer.c
 create mode 100644 libvlc/src/org/videolan/libvlc/MediaDiscoverer.java

diff --git a/libvlc/jni/Android.mk b/libvlc/jni/Android.mk
index 1e2ce54..58aee81 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-medialist.c libvlcjni-equalizer.c
+LOCAL_SRC_FILES += libvlcjni-mediadiscoverer.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-mediadiscoverer.c b/libvlc/jni/libvlcjni-mediadiscoverer.c
new file mode 100644
index 0000000..caff0c5
--- /dev/null
+++ b/libvlc/jni/libvlcjni-mediadiscoverer.c
@@ -0,0 +1,141 @@
+/*****************************************************************************
+ * libvlcjni-mediadiscoverer.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 <jni.h>
+#include <vlc/vlc.h>
+#include <vlc/libvlc_media_discoverer.h>
+
+#include "utils.h"
+#define LOG_TAG "VLC/JNI/MediaDiscoverer"
+#include "log.h"
+
+void vlc_event_callback(const libvlc_event_t *ev, void *data);
+
+static libvlc_media_discoverer_t *
+getMediaDiscoverer(JNIEnv *env, jobject thiz)
+{
+    return (libvlc_media_discoverer_t*)(intptr_t)getLong(env, thiz, "mInternalMediaDiscovererInstance");
+}
+
+static libvlc_media_discoverer_t *
+setMediaDiscoverer(JNIEnv *env, jobject thiz, libvlc_media_discoverer_t *p_md)
+{
+    setLong(env, thiz, "mInternalMediaDiscovererInstance", (jlong)(intptr_t)p_md);
+}
+
+static void throw(JNIEnv *env, const char *p_error)
+{
+    jclass exc = (*env)->FindClass(env, "org/videolan/libvlc/LibVlcException");
+    (*env)->ThrowNew(env, exc, p_error);
+}
+
+void
+Java_org_videolan_libvlc_LibVLC_mediaDiscoverCreate(JNIEnv *env, jobject thiz,
+                                                    jstring jname)
+{
+    libvlc_instance_t *p_instance = getLibVlcInstance(env, thiz);
+    libvlc_media_discoverer_t *p_discoverer = getMediaDiscoverer(env, thiz);
+    libvlc_event_manager_t *ev;
+
+    const char* p_name;
+    if (p_discoverer)
+    {
+        throw(env, "media discoverer instance already exist");
+        return;
+    }
+
+    if (!jname || !(p_name = (*env)->GetStringUTFChars(env, jname, 0)))
+    {
+        throw(env, "arguments invalid");
+        return;
+    }
+
+    p_discoverer = libvlc_media_discoverer_new(p_instance, p_name);
+
+    (*env)->ReleaseStringUTFChars(env, jname, p_name);
+
+    if (!p_discoverer)
+    {
+        throw(env, "can't create media discoverer instance");
+        return;
+    }
+
+    ev = libvlc_media_discoverer_event_manager(p_discoverer);
+    static const libvlc_event_type_t mp_events[] = {
+        libvlc_MediaDiscovererStarted,
+        libvlc_MediaDiscovererEnded,
+        libvlc_MediaDiscovererItemAdded,
+        libvlc_MediaDiscovererItemRemoved,
+        libvlc_MediaDiscovererItemRemoveAll
+    };
+    for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
+        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, NULL);
+
+    if (libvlc_media_discoverer_start(p_discoverer) == -1)
+    {
+        libvlc_media_discoverer_release(p_discoverer);
+        throw(env, "can't start media discoverer");
+        return;
+    }
+    setMediaDiscoverer(env, thiz, p_discoverer);
+}
+
+void
+Java_org_videolan_libvlc_LibVLC_mediaDiscoverRelease(JNIEnv *env, jobject thiz)
+{
+    libvlc_media_discoverer_t *p_discoverer = getMediaDiscoverer(env, thiz);
+    if (p_discoverer)
+    {
+        libvlc_media_discoverer_release(p_discoverer);
+        setMediaDiscoverer(env, thiz, NULL);
+    }
+}
+
+bool
+Java_org_videolan_libvlc_LibVLC_mediaDiscoverBrowse(JNIEnv *env, jobject thiz,
+                                                    jstring jpath)
+{
+    libvlc_media_discoverer_t *p_discoverer = getMediaDiscoverer(env, thiz);
+    const char* p_path;
+    int i_ret;
+
+    if (!p_discoverer)
+    {
+        throw(env, "discoverer instance does not exist");
+        return false;
+    }
+
+    if (jpath)
+    {
+        p_path = (*env)->GetStringUTFChars(env, jpath, 0);
+        if (!p_path)
+        {
+            throw(env, "can't get path");
+            return false;
+        }
+    } else
+        p_path = NULL;
+
+    i_ret = libvlc_media_discoverer_browse(p_discoverer, p_path);
+
+    if (jpath)
+        (*env)->ReleaseStringUTFChars(env, jpath, p_path);
+
+    return i_ret == 0 ? true : false;
+}
diff --git a/libvlc/jni/libvlcjni.c b/libvlc/jni/libvlcjni.c
index 94b216c..7c3ceab 100644
--- a/libvlc/jni/libvlcjni.c
+++ b/libvlc/jni/libvlcjni.c
@@ -126,7 +126,7 @@ static JavaVM *myVm;
 
 static jobject eventHandlerInstance = NULL;
 
-static void vlc_event_callback(const libvlc_event_t *ev, void *data)
+void vlc_event_callback(const libvlc_event_t *ev, void *data)
 {
     JNIEnv *env;
 
@@ -191,6 +191,21 @@ static void vlc_event_callback(const libvlc_event_t *ev, void *data)
         (*env)->DeleteLocalRef(env, item_uri_value);
         (*env)->DeleteLocalRef(env, item_index);
         free(mrl);
+    } else if(ev->type == libvlc_MediaDiscovererItemAdded ||
+              ev->type == libvlc_MediaDiscovererItemRemoved ) {
+        jstring item_uri = (*env)->NewStringUTF(env, "item_uri");
+        char* mrl = libvlc_media_get_mrl(
+            ev->type == libvlc_MediaListItemAdded ?
+            ev->u.media_discoverer_item_added.item :
+            ev->u.media_discoverer_item_removed.item
+            );
+        jstring item_uri_value = (*env)->NewStringUTF(env, mrl);
+
+        (*env)->CallVoidMethod(env, bundle, putString, item_uri, item_uri_value);
+
+        (*env)->DeleteLocalRef(env, item_uri);
+        (*env)->DeleteLocalRef(env, item_uri_value);
+        free(mrl);
     }
 
     /* Get the object class */
@@ -442,7 +457,7 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv *env, jobject thiz,
         libvlc_MediaPlayerEncounteredError
     };
     for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
-        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, myVm);
+        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, NULL);
 
     /* Keep a pointer to this media player */
     setLong(env, thiz, "mInternalMediaPlayerInstance", (jlong)(intptr_t)mp);
@@ -467,7 +482,7 @@ void Java_org_videolan_libvlc_LibVLC_playMRL(JNIEnv *env, jobject thiz,
         libvlc_MediaMetaChanged,
     };
     for(int i = 0; i < (sizeof(mp_media_events) / sizeof(*mp_media_events)); i++)
-        libvlc_event_attach(ev_media, mp_media_events[i], vlc_event_callback, myVm);
+        libvlc_event_attach(ev_media, mp_media_events[i], vlc_event_callback, NULL);
 
     libvlc_media_player_set_media(mp, p_md);
     libvlc_media_player_play(mp);
diff --git a/libvlc/src/org/videolan/libvlc/EventHandler.java b/libvlc/src/org/videolan/libvlc/EventHandler.java
index 4ec0861..3f441b4 100644
--- a/libvlc/src/org/videolan/libvlc/EventHandler.java
+++ b/libvlc/src/org/videolan/libvlc/EventHandler.java
@@ -73,8 +73,11 @@ public class EventHandler {
     //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 MediaDiscovererStarted          = 0x500;
+    public static final int MediaDiscovererEnded            = 0x501;
+    public static final int MediaDiscovererItemAdded        = 0x502;
+    public static final int MediaDiscovererItemRemoved      = 0x503;
+    public static final int MediaDiscovererItemRemoveAll    = 0x504;
 
     //public static final int VlmMediaAdded                   = 0x600;
     //public static final int VlmMediaRemoved                 = 0x601;
diff --git a/libvlc/src/org/videolan/libvlc/LibVLC.java b/libvlc/src/org/videolan/libvlc/LibVLC.java
index 8bac400..e9d632e 100644
--- a/libvlc/src/org/videolan/libvlc/LibVLC.java
+++ b/libvlc/src/org/videolan/libvlc/LibVLC.java
@@ -66,6 +66,7 @@ public class LibVLC {
     /** libvlc_media_player pointer and index */
     private int mInternalMediaPlayerIndex = 0; // Read-only, reserved for JNI
     private long mInternalMediaPlayerInstance = 0; // Read-only, reserved for JNI
+    private long mInternalMediaDiscovererInstance = 0; // Read-only, reserved for JNI
 
     private MediaList mMediaList; // Pointer to media list being followed
     private MediaList mPrimaryList; // Primary/default media list; see getPrimaryMediaList()
@@ -872,4 +873,9 @@ public class LibVLC {
     /* MediaList */
     protected native void loadPlaylist(String mrl, ArrayList<String> items);
     protected native int expandMedia(int position, ArrayList<String> children);
+
+    /* MediaDiscoverer */
+    protected native void mediaDiscoverCreate(String name) throws LibVlcException;
+    protected native void mediaDiscoverRelease();
+    protected native void mediaDiscoverBrowse(String path) throws LibVlcException;
 }
diff --git a/libvlc/src/org/videolan/libvlc/MediaDiscoverer.java b/libvlc/src/org/videolan/libvlc/MediaDiscoverer.java
new file mode 100644
index 0000000..7eb194b
--- /dev/null
+++ b/libvlc/src/org/videolan/libvlc/MediaDiscoverer.java
@@ -0,0 +1,87 @@
+package org.videolan.libvlc;
+
+
+import org.videolan.libvlc.util.WeakHandler;
+
+import android.os.Handler;
+import android.os.Message;
+
+public class MediaDiscoverer {
+
+    public static class Item {
+        public final String uri;
+
+        public Item(String uri) {
+            this.uri = uri;
+        }
+    }
+
+    public interface Listener {
+        public void onStarted();
+        public void onEnded();
+        public void onItemAdded(Item item);
+        public void onItemRemoved(Item item);
+        public void onRemoveAll();
+    }
+
+    private final LibVLC mLibVLC;
+    private final Handler mWeakHandler = new MediaDiscovererEventHandler(this);
+    private final Listener mListener;
+
+    private static class MediaDiscovererEventHandler extends WeakHandler<MediaDiscoverer> {
+        public MediaDiscovererEventHandler(MediaDiscoverer owner) {
+            super(owner);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            final MediaDiscoverer discover = getOwner();
+            if(discover != null)
+                discover.dispatchMessage(msg);
+        }
+    };
+
+    private void dispatchMessage(Message msg) {
+        if (mListener == null)
+            return;
+        final int event = msg.getData().getInt("event");
+        switch (event) {
+            case EventHandler.MediaDiscovererStarted:
+                mListener.onStarted();
+                break;
+            case EventHandler.MediaDiscovererEnded:
+                mListener.onEnded();
+                break;
+            case EventHandler.MediaDiscovererItemAdded:
+            case EventHandler.MediaDiscovererItemRemoved: {
+                final Item item = new Item(msg.getData().getString("item_uri"));
+                if (event == EventHandler.MediaDiscovererItemAdded)
+                    mListener.onItemAdded(item);
+                else
+                    mListener.onItemRemoved(item);
+                break;
+            }
+            case EventHandler.MediaDiscovererItemRemoveAll:
+                mListener.onRemoveAll();
+                break;
+        }
+    }
+
+    public MediaDiscoverer(LibVLC libVLC, Listener listener) {
+        mLibVLC = libVLC;
+        mListener = listener;
+        EventHandler.getInstance().addHandler(mWeakHandler);
+    }
+
+    public void create(String name) throws LibVlcException {
+        mLibVLC.mediaDiscoverCreate(name);
+    }
+
+    public void release() {
+        mLibVLC.mediaDiscoverRelease();
+    }
+
+    public void browse(String path) throws LibVlcException {
+        mLibVLC.mediaDiscoverBrowse(path);
+    }
+}
-- 
2.1.3



More information about the Android mailing list