Commit d29241e3 authored by Geoffrey Métais's avatar Geoffrey Métais

LibVLC: Chromecast API implementation

parent 7e169db5
......@@ -103,4 +103,5 @@ clean {
dependencies {
api "com.android.support:support-annotations:$rootProject.ext.appCompatVersion"
api "com.android.support:support-v4:$rootProject.ext.appCompatVersion"
}
......@@ -7,7 +7,7 @@ LOCAL_MODULE := vlcjni_static
LOCAL_SRC_FILES := libvlcjni.c
LOCAL_SRC_FILES += libvlcjni-mediaplayer.c
LOCAL_SRC_FILES += libvlcjni-vlcobject.c
LOCAL_SRC_FILES += libvlcjni-media.c libvlcjni-medialist.c libvlcjni-mediadiscoverer.c
LOCAL_SRC_FILES += libvlcjni-media.c libvlcjni-medialist.c libvlcjni-mediadiscoverer.c libvlcjni-rendererdiscoverer.c
LOCAL_SRC_FILES += libvlcjni-dialog.c
LOCAL_SRC_FILES += thumbnailer.c
LOCAL_SRC_FILES += std_logger.c
......
......@@ -210,6 +210,26 @@ Java_org_videolan_libvlc_MediaPlayer_nativeSetMedia(JNIEnv *env,
libvlc_media_player_set_media(p_obj->u.p_mp, p_m);
}
jint
Java_org_videolan_libvlc_MediaPlayer_nativeSetRenderer(JNIEnv *env,
jobject thiz,
jobject jrenderer)
{
libvlc_renderer_item_t *p_m = NULL;
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
if (!p_obj)
return -1;
if (jrenderer)
{
vlcjni_object *p_m_obj = VLCJniObject_getInstance(env, jrenderer);
if (!p_m_obj)
return -1;
p_m = p_m_obj->u.p_r;
}
return libvlc_media_player_set_renderer(p_obj->u.p_mp, p_m);
}
void
Java_org_videolan_libvlc_MediaPlayer_nativeSetVideoTitleDisplay(JNIEnv *env,
jobject thiz,
......
/*****************************************************************************
* libvlcjni-rendererdiscoverer.c
*****************************************************************************
* Copyright © 2017 VLC authors, VideoLAN and VideoLabs
*
* 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 "libvlcjni-vlcobject.h"
static const libvlc_event_type_t rd_events[] = {
libvlc_RendererDiscovererItemAdded,
libvlc_RendererDiscovererItemDeleted,
-1,
};
static bool
RendererDiscoverer_event_cb(vlcjni_object *p_obj, const libvlc_event_t *p_ev,
java_event *p_java_event)
{
switch (p_ev->type)
{
case libvlc_RendererDiscovererItemAdded:
p_java_event->arg1 = p_ev->u.renderer_discoverer_item_added.item;
break;
case libvlc_RendererDiscovererItemDeleted:
p_java_event->arg1 = p_ev->u.renderer_discoverer_item_deleted.item;
break;
}
p_java_event->type = p_ev->type;
return true;
}
void
Java_org_videolan_libvlc_RendererDiscoverer_nativeNew(JNIEnv *env,
jobject thiz,
jobject libVlc,
jstring jname)
{
vlcjni_object *p_obj;
const char* p_name;
if (!jname || !(p_name = (*env)->GetStringUTFChars(env, jname, 0)))
{
throw_IllegalArgumentException(env, "jname invalid");
return;
}
p_obj = VLCJniObject_newFromJavaLibVlc(env, thiz, libVlc);
if (!p_obj)
{
(*env)->ReleaseStringUTFChars(env, jname, p_name);
return;
}
p_obj->u.p_rd = libvlc_renderer_discoverer_new(p_obj->p_libvlc, p_name);
(*env)->ReleaseStringUTFChars(env, jname, p_name);
if (!p_obj->u.p_rd)
{
VLCJniObject_release(env, thiz, p_obj);
throw_IllegalStateException(env, "can't create RendererDiscoverer instance");
return;
}
VLCJniObject_attachEvents(p_obj, RendererDiscoverer_event_cb,
libvlc_renderer_discoverer_event_manager(p_obj->u.p_rd),
rd_events);
}
void
Java_org_videolan_libvlc_RendererDiscoverer_nativeRelease(JNIEnv *env,
jobject thiz)
{
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
if (!p_obj)
return;
libvlc_renderer_discoverer_release(p_obj->u.p_rd);
VLCJniObject_release(env, thiz, p_obj);
}
jboolean
Java_org_videolan_libvlc_RendererDiscoverer_nativeStart(JNIEnv *env, jobject thiz)
{
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
if (!p_obj)
return false;
return libvlc_renderer_discoverer_start(p_obj->u.p_rd) == 0;
}
void
Java_org_videolan_libvlc_RendererDiscoverer_nativeStop(JNIEnv *env, jobject thiz)
{
vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
if (!p_obj)
return;
libvlc_renderer_discoverer_stop(p_obj->u.p_rd);
}
static jobject
service_to_object(JNIEnv *env, libvlc_rd_description_t *p_service)
{
jstring jname = NULL;
jstring jlongName = NULL;
jname = (*env)->NewStringUTF(env, p_service->psz_name);
jlongName = (*env)->NewStringUTF(env, p_service->psz_longname);
jobject jobj = (*env)->CallStaticObjectMethod(env, fields.RendererDiscoverer.clazz,
fields.RendererDiscoverer.createDescriptionFromNativeID,
jname, jlongName);
(*env)->DeleteLocalRef(env, jname);
(*env)->DeleteLocalRef(env, jlongName);
return jobj;
}
static jobject
item_to_object(JNIEnv *env, libvlc_renderer_item_t *p_item)
{
jstring jname = NULL;
jstring jType = NULL;
jstring jIconUri = NULL;
jint jFlags = 0;
jname = (*env)->NewStringUTF(env, libvlc_renderer_item_name(p_item));
jType = (*env)->NewStringUTF(env, libvlc_renderer_item_type(p_item));
jIconUri = (*env)->NewStringUTF(env, libvlc_renderer_item_icon_uri(p_item));
jFlags = libvlc_renderer_item_flags(p_item);
jobject jobj = (*env)->CallStaticObjectMethod(env, fields.RendererDiscoverer.clazz,
fields.RendererDiscoverer.createItemFromNativeID,
jname, jType, jIconUri, jFlags, (jlong) p_item);
(*env)->DeleteLocalRef(env, jname);
(*env)->DeleteLocalRef(env, jType);
(*env)->DeleteLocalRef(env, jIconUri);
return jobj;
}
jobject
Java_org_videolan_libvlc_RendererDiscoverer_nativeList(JNIEnv *env, jobject thiz,
jobject libVlc)
{
vlcjni_object *p_lib_obj = VLCJniObject_getInstance(env, libVlc);
libvlc_instance_t *p_libvlc = p_lib_obj->u.p_libvlc;
libvlc_rd_description_t **pp_services = NULL;
size_t i_nb_services = 0;
jobjectArray array;
if (!p_lib_obj)
return NULL;
i_nb_services =
libvlc_renderer_discoverer_list_get( p_libvlc, &pp_services);
if (i_nb_services == 0)
return NULL;
array = (*env)->NewObjectArray(env, i_nb_services,
fields.RendererDiscoverer.Description.clazz,
NULL);
if (!array)
goto error;
for (size_t i = 0; i < i_nb_services; ++i)
{
jobject jservice = service_to_object(env, pp_services[i]);
(*env)->SetObjectArrayElement(env, array, i, jservice);
}
error:
if (pp_services)
libvlc_renderer_discoverer_list_release(pp_services, i_nb_services);
return array;
}
jobject
Java_org_videolan_libvlc_RendererItem_nativeNewItem(JNIEnv *env, jobject thiz, jobject rd,
jlong ref)
{
vlcjni_object *p_rd_obj = VLCJniObject_getInstance(env, rd);
vlcjni_object *p_obj;
if (!p_rd_obj)
return NULL;
p_obj = VLCJniObject_newFromLibVlc(env, thiz, p_rd_obj->p_libvlc);
if (!p_obj)
return NULL;
p_obj->u.p_r = libvlc_renderer_item_hold((libvlc_renderer_item_t *)ref);
return item_to_object(env, p_obj->u.p_r);
}
void
Java_org_videolan_libvlc_RendererItem_nativeReleaseItem(JNIEnv *env, jobject thiz)
{
libvlc_renderer_item_t *p_renderer = NULL;
if (thiz)
{
vlcjni_object *p_r_obj = VLCJniObject_getInstance(env, thiz);
if (p_r_obj)
p_renderer = p_r_obj->u.p_r;
}
if (p_renderer)
libvlc_renderer_item_release(p_renderer);
}
......@@ -27,6 +27,7 @@
#include <vlc/vlc.h>
#include <vlc/libvlc_media_list.h>
#include <vlc/libvlc_media_discoverer.h>
#include <vlc/libvlc_renderer_discoverer.h>
#include "utils.h"
#define LOG_TAG "VLC/JNI/VLCObject"
......@@ -49,6 +50,8 @@ struct vlcjni_object
libvlc_media_list_t *p_ml;
libvlc_media_discoverer_t *p_md;
libvlc_media_player_t *p_mp;
libvlc_renderer_discoverer_t *p_rd;
libvlc_renderer_item_t *p_r;
} u;
/* Used by vlcobject */
vlcjni_object_owner *p_owner;
......
......@@ -175,6 +175,10 @@ int VLCJNI_OnLoad(JavaVM *vm, JNIEnv* env)
"org/videolan/libvlc/MediaDiscoverer", true);
GET_CLASS(fields.MediaDiscoverer.Description.clazz,
"org/videolan/libvlc/MediaDiscoverer$Description", true);
GET_CLASS(fields.RendererDiscoverer.clazz,
"org/videolan/libvlc/RendererDiscoverer", true);
GET_CLASS(fields.RendererDiscoverer.Description.clazz,
"org/videolan/libvlc/RendererDiscoverer$Description", true);
GET_CLASS(fields.Dialog.clazz,
"org/videolan/libvlc/Dialog", true);
......@@ -277,6 +281,20 @@ int VLCJNI_OnLoad(JavaVM *vm, JNIEnv* env)
"(Ljava/lang/String;Ljava/lang/String;I)"
"Lorg/videolan/libvlc/MediaDiscoverer$Description;");
GET_ID(GetStaticMethodID,
fields.RendererDiscoverer.createDescriptionFromNativeID,
fields.RendererDiscoverer.clazz,
"createDescriptionFromNative",
"(Ljava/lang/String;Ljava/lang/String;)"
"Lorg/videolan/libvlc/RendererDiscoverer$Description;");
GET_ID(GetStaticMethodID,
fields.RendererDiscoverer.createItemFromNativeID,
fields.RendererDiscoverer.clazz,
"createItemFromNative",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IJ)"
"Lorg/videolan/libvlc/RendererItem;");
GET_ID(GetStaticMethodID,
fields.Dialog.displayErrorFromNativeID,
fields.Dialog.clazz,
......
......@@ -91,6 +91,14 @@ struct fields {
jclass clazz;
jmethodID createDescriptionFromNativeID;
} MediaDiscoverer;
struct {
struct {
jclass clazz;
} Description;
jclass clazz;
jmethodID createDescriptionFromNativeID;
jmethodID createItemFromNativeID;
} RendererDiscoverer;
struct {
jclass clazz;
jmethodID displayErrorFromNativeID;
......
......@@ -578,6 +578,11 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
}
}
public int setRenderer(RendererItem item) {
return nativeSetRenderer(item);
}
/**
* Get the Media used by this MediaPlayer. This Media should be released with {@link #release()}.
*/
......@@ -1130,6 +1135,7 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
private native void nativeSetMedia(Media media);
private native void nativePlay();
private native void nativeStop();
private native int nativeSetRenderer(RendererItem item);
private native void nativeSetVideoTitleDisplay(int position, int timeout);
private native float nativeGetScale();
private native void nativeSetScale(float scale);
......
/*****************************************************************************
* RendererDiscoverer.java
*****************************************************************************
* Copyright © 2017 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.support.v4.util.LongSparseArray;
public class RendererDiscoverer extends VLCObject<RendererDiscoverer.Event> {
private final static String TAG = "LibVLC/RendererDiscoverer";
public static class Event extends VLCEvent {
public static final int ItemAdded = 0x502;
public static final int ItemDeleted = 0x503;
private RendererItem item;
protected Event(int type, long nativeHolder, RendererItem item) {
super(type, nativeHolder);
this.item = item;
}
public RendererItem getItem() {
return item;
}
}
@SuppressWarnings("unused") /* Used from JNI */
private static RendererItem createItemFromNative(String name, String type, String iconUrl, int flags, long ref) {
return new RendererItem(name, type, iconUrl, flags, ref);
}
public interface EventListener extends VLCEvent.Listener<RendererDiscoverer.Event> {}
/**
* Create a MediaDiscover.
*
* @param libVLC a valid LibVLC
* @param name Name of the vlc service discovery.
*/
public RendererDiscoverer(LibVLC libVLC, String name) {
super(libVLC);
nativeNew(libVLC, name);
}
/**
* Starts the discovery. This RendererDiscoverer should be alive (not released).
*
* @return true the service is started
*/
public boolean start() {
if (isReleased()) throw new IllegalStateException("MediaDiscoverer is released");
return nativeStart();
}
/**
* Stops the discovery. This RendererDiscoverer should be alive (not released).
* (You can also call {@link #release() to stop the discovery directly}.
*/
public void stop() {
if (isReleased()) throw new IllegalStateException("MediaDiscoverer is released");
setEventListener(null);
nativeStop();
}
public void setEventListener(EventListener listener) {
super.setEventListener(listener);
}
public static Description[] list(LibVLC libVlc) {
return nativeList(libVlc);
}
public static class Description {
public final String name;
final String longName;
private Description(String name, String longName) {
this.name = name;
this.longName = longName;
}
}
@Override
protected Event onEventNative(int eventType, long arg1, long arg2, float argf1) {
switch (eventType) {
case Event.ItemAdded:
return new Event(eventType, arg1, insertItemFromEvent(arg1));
case Event.ItemDeleted:
return new Event(eventType, arg1, removeItemFromEvent(arg1));
default:
return null;
}
}
private final LongSparseArray<RendererItem> index = new LongSparseArray<>();
private synchronized RendererItem insertItemFromEvent(long arg1) {
final RendererItem item = new RendererItem(this, arg1);
index.put(arg1, item);
return item;
}
private synchronized RendererItem removeItemFromEvent(long arg1) {
final RendererItem item = index.get(arg1);
if (item != null) index.remove(arg1);
return item;
}
@Override
protected void onReleaseNative() {
nativeRelease();
}
@SuppressWarnings("unused") /* Used from JNI */
private static Description createDescriptionFromNative(String name, String longName) {
return new Description(name, longName);
}
/* JNI */
private native void nativeNew(LibVLC libVLC, String name);
private native void nativeRelease();
private native boolean nativeStart();
private native void nativeStop();
private static native Description[] nativeList(LibVLC libVLC);
}
package org.videolan.libvlc;
@SuppressWarnings("unused, JniMissingFunction")
public class RendererItem extends VLCObject<RendererItem.Event> {
/** The renderer can render audio */
public static final int LIBVLC_RENDERER_CAN_AUDIO = 0x0001;
/** The renderer can render video */
public static final int LIBVLC_RENDERER_CAN_VIDEO = 0x0002;
final public String name;
final public String displayName;
final String type;
final String iconUrl;
final int flags;
private final long ref;
RendererItem (RendererDiscoverer rd, long ref) {
super(rd);
final RendererItem item = nativeNewItem(rd, ref);
name = item == null ? null : item.name;
displayName = item == null ? null : item.displayName;
this.type = item == null ? null : item.type;
this.iconUrl = item == null ? null : item.iconUrl;
this.flags = item == null ? 0 : item.flags;
this.ref = item == null ? ref : item.ref;
}
RendererItem(String name, String type, String iconUrl, int flags, long ref) {
final int index = name.lastIndexOf('-');
this.name = name;
this.displayName = index == -1 ? name : name.substring(0, index).replace('-', ' ');
this.type = type;
this.iconUrl = iconUrl;
this.flags = flags;
this.ref = ref;
}
@Override
public boolean equals(Object obj) {
return obj instanceof RendererItem && ref == ((RendererItem)obj).ref;
}
@Override
protected Event onEventNative(int eventType, long arg1, long arg2, float argf1) {
return new Event(eventType);
}
@Override
protected void onReleaseNative() {
nativeReleaseItem();
}
public static class Event extends VLCEvent {
protected Event(int type) {
super(type);
}
}
private native RendererItem nativeNewItem(RendererDiscoverer rd, long ref);
private native void nativeReleaseItem();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment