| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183 |
- /*****************************************************************************
- * libvlcjni.c
- *****************************************************************************
- * Copyright © 2010-2012 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.
- *****************************************************************************/
- #include <dirent.h>
- #include <errno.h>
- #include <string.h>
- #include <pthread.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include <vlc/vlc.h>
- #include <vlc_common.h>
- #include <vlc_url.h>
- #include <vlc_fourcc.h>
- #include <jni.h>
- #include <android/api-level.h>
- #include "libvlcjni.h"
- #include "aout.h"
- #include "utils.h"
- #define LOG_TAG "VLC/JNI/main"
- #include "log.h"
- #define AOUT_AUDIOTRACK_JAVA 0
- #define AOUT_AUDIOTRACK 1
- #define AOUT_OPENSLES 2
- static jint getInt(JNIEnv *env, jobject thiz, const char* field) {
- jclass clazz = (*env)->GetObjectClass(env, thiz);
- jfieldID fieldMP = (*env)->GetFieldID(env, clazz,
- field, "I");
- return (*env)->GetIntField(env, thiz, fieldMP);
- }
- static void setInt(JNIEnv *env, jobject item, const char* field, jint value) {
- jclass cls;
- jfieldID fieldId;
- /* Get a reference to item's class */
- cls = (*env)->GetObjectClass(env, item);
- /* Look for the instance field s in cls */
- fieldId = (*env)->GetFieldID(env, cls, field, "I");
- if (fieldId == NULL)
- return;
- (*env)->SetIntField(env, item, fieldId, value);
- }
- static jlong getLong(JNIEnv *env, jobject thiz, const char* field) {
- jclass clazz = (*env)->GetObjectClass(env, thiz);
- jfieldID fieldMP = (*env)->GetFieldID(env, clazz,
- field, "J");
- return (*env)->GetLongField(env, thiz, fieldMP);
- }
- static void setLong(JNIEnv *env, jobject item, const char* field, jlong value) {
- jclass cls;
- jfieldID fieldId;
- /* Get a reference to item's class */
- cls = (*env)->GetObjectClass(env, item);
- /* Look for the instance field s in cls */
- fieldId = (*env)->GetFieldID(env, cls, field, "J");
- if (fieldId == NULL)
- return;
- (*env)->SetLongField(env, item, fieldId, value);
- }
- static void setFloat(JNIEnv *env, jobject item, const char* field, jfloat value) {
- jclass cls;
- jfieldID fieldId;
- /* Get a reference to item's class */
- cls = (*env)->GetObjectClass(env, item);
- /* Look for the instance field s in cls */
- fieldId = (*env)->GetFieldID(env, cls, field, "F");
- if (fieldId == NULL)
- return;
- (*env)->SetFloatField(env, item, fieldId, value);
- }
- static void setString(JNIEnv *env, jobject item, const char* field, const char* text) {
- jclass cls;
- jfieldID fieldId;
- jstring jstr;
- /* Get a reference to item's class */
- cls = (*env)->GetObjectClass(env, item);
- /* Look for the instance field s in cls */
- fieldId = (*env)->GetFieldID(env, cls, field, "Ljava/lang/String;");
- if (fieldId == NULL)
- return;
- /* Create a new string and overwrite the instance field */
- jstr = (*env)->NewStringUTF(env, text);
- if (jstr == NULL)
- return;
- (*env)->SetObjectField(env, item, fieldId, jstr);
- }
- struct length_change_monitor {
- pthread_mutex_t doneMutex;
- pthread_cond_t doneCondVar;
- bool length_changed;
- };
- static void length_changed_callback(const libvlc_event_t *ev, void *data)
- {
- struct length_change_monitor *monitor = data;
- pthread_mutex_lock(&monitor->doneMutex);
- monitor->length_changed = true;
- pthread_cond_signal(&monitor->doneCondVar);
- pthread_mutex_unlock(&monitor->doneMutex);
- }
- libvlc_media_t *new_media(jlong instance, JNIEnv *env, jobject thiz, jstring fileLocation, bool noOmx, bool noVideo)
- {
- libvlc_instance_t *libvlc = (libvlc_instance_t*)(intptr_t)instance;
- jboolean isCopy;
- const char *psz_location = (*env)->GetStringUTFChars(env, fileLocation, &isCopy);
- libvlc_media_t *p_md = libvlc_media_new_location(libvlc, psz_location);
- (*env)->ReleaseStringUTFChars(env, fileLocation, psz_location);
- if (!p_md)
- return NULL;
- if (!noOmx) {
- jclass cls = (*env)->GetObjectClass(env, thiz);
- jmethodID methodId = (*env)->GetMethodID(env, cls, "useIOMX", "()Z");
- if ((*env)->CallBooleanMethod(env, thiz, methodId)) {
- /*
- * Set higher caching values if using iomx decoding, since some omx
- * decoders have a very high latency, and if the preroll data isn't
- * enough to make the decoder output a frame, the playback timing gets
- * started too soon, and every decoded frame appears to be too late.
- * On Nexus One, the decoder latency seems to be 25 input packets
- * for 320x170 H.264, a few packets less on higher resolutions.
- * On Nexus S, the decoder latency seems to be about 7 packets.
- */
- libvlc_media_add_option(p_md, ":file-caching=1500");
- libvlc_media_add_option(p_md, ":network-caching=1500");
- libvlc_media_add_option(p_md, ":codec=mediacodec,iomx,all");
- }
- if (noVideo)
- libvlc_media_add_option(p_md, ":no-video");
- }
- return p_md;
- }
- static libvlc_media_list_t *getMediaList(JNIEnv *env, jobject thiz)
- {
- return (libvlc_media_list_t*)(intptr_t)getLong(env, thiz, "mMediaListInstance");
- }
- static libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz)
- {
- return (libvlc_media_player_t*)(intptr_t)getLong(env, thiz, "mInternalMediaPlayerInstance");
- }
- static libvlc_media_list_player_t *getMediaListPlayer(JNIEnv *env, jobject thiz)
- {
- return (libvlc_media_list_player_t*)(intptr_t)getLong(env, thiz, "mMediaListPlayerInstance");
- }
- static void releaseMediaPlayer(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t* p_mlp = getMediaListPlayer(env, thiz);
- if (p_mlp)
- {
- libvlc_media_list_player_stop(p_mlp);
- libvlc_media_list_player_release(p_mlp);
- /* libvlc_media_list_player_release frees the media player, so
- * we don't free it ourselves. */
- setLong(env, thiz, "mInternalMediaPlayerInstance", 0);
- setLong(env, thiz, "mMediaListPlayerInstance", 0);
- }
- }
- /* Pointer to the Java virtual machine
- * Note: It's okay to use a static variable for the VM pointer since there
- * can only be one instance of this shared library in a single VM
- */
- JavaVM *myVm;
- static jobject eventManagerInstance = NULL;
- static pthread_mutex_t vout_android_lock;
- static void *vout_android_surf = NULL;
- static void *vout_android_gui = NULL;
- void *jni_LockAndGetAndroidSurface() {
- pthread_mutex_lock(&vout_android_lock);
- return vout_android_surf;
- }
- void jni_UnlockAndroidSurface() {
- pthread_mutex_unlock(&vout_android_lock);
- }
- void jni_SetAndroidSurfaceSize(int width, int height, int sar_num, int sar_den)
- {
- if (vout_android_gui == NULL)
- return;
- JNIEnv *p_env;
- (*myVm)->AttachCurrentThread (myVm, &p_env, NULL);
- jclass cls = (*p_env)->GetObjectClass (p_env, vout_android_gui);
- jmethodID methodId = (*p_env)->GetMethodID (p_env, cls, "setSurfaceSize", "(IIII)V");
- (*p_env)->CallVoidMethod (p_env, vout_android_gui, methodId, width, height, sar_num, sar_den);
- (*p_env)->DeleteLocalRef(p_env, cls);
- (*myVm)->DetachCurrentThread (myVm);
- }
- static void vlc_event_callback(const libvlc_event_t *ev, void *data)
- {
- JNIEnv *env;
- JavaVM *myVm = data;
- bool isAttached = false;
- if (eventManagerInstance == NULL)
- return;
- int status = (*myVm)->GetEnv(myVm, (void**) &env, JNI_VERSION_1_2);
- if (status < 0) {
- LOGD("vlc_event_callback: failed to get JNI environment, "
- "assuming native thread");
- status = (*myVm)->AttachCurrentThread(myVm, &env, NULL);
- if (status < 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 putString = (*env)->GetMethodID(env, clsBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V" );
- if(ev->type == libvlc_MediaPlayerVout) {
- /* For determining the vout/ES track change */
- jstring sData = (*env)->NewStringUTF(env, "data");
- (*env)->CallVoidMethod(env, bundle, putInt, sData, ev->u.media_player_vout.new_count);
- (*env)->DeleteLocalRef(env, sData);
- } else if(ev->type == libvlc_MediaListItemAdded ||
- ev->type == libvlc_MediaListItemDeleted ) {
- 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, eventManagerInstance);
- if (!cls) {
- LOGE("EventManager: 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, eventManagerInstance, methodID, ev->type, bundle);
- } else {
- LOGE("EventManager: failed to get the callback method");
- }
- end:
- if (isAttached)
- (*myVm)->DetachCurrentThread(myVm);
- }
- jint JNI_OnLoad(JavaVM *vm, void *reserved)
- {
- // Keep a reference on the Java VM.
- myVm = vm;
- pthread_mutex_init(&vout_android_lock, NULL);
- LOGD("JNI interface loaded.");
- return JNI_VERSION_1_2;
- }
- void JNI_OnUnload(JavaVM* vm, void* reserved) {
- pthread_mutex_destroy(&vout_android_lock);
- }
- void Java_org_videolan_vlc_LibVLC_attachSurface(JNIEnv *env, jobject thiz, jobject surf, jobject gui, jint width, jint height) {
- jclass clz;
- jfieldID fid;
- pthread_mutex_lock(&vout_android_lock);
- clz = (*env)->GetObjectClass(env, surf);
- fid = (*env)->GetFieldID(env, clz, "mSurface", "I");
- if (fid == NULL) {
- jthrowable exp = (*env)->ExceptionOccurred(env);
- if (exp) {
- (*env)->DeleteLocalRef(env, exp);
- (*env)->ExceptionClear(env);
- }
- fid = (*env)->GetFieldID(env, clz, "mNativeSurface", "I");
- }
- vout_android_surf = (void*)(*env)->GetIntField(env, surf, fid);
- (*env)->DeleteLocalRef(env, clz);
- vout_android_gui = (*env)->NewGlobalRef(env, gui);
- pthread_mutex_unlock(&vout_android_lock);
- }
- void Java_org_videolan_vlc_LibVLC_detachSurface(JNIEnv *env, jobject thiz) {
- pthread_mutex_lock(&vout_android_lock);
- vout_android_surf = NULL;
- if (vout_android_gui != NULL)
- (*env)->DeleteGlobalRef(env, vout_android_gui);
- vout_android_gui = NULL;
- pthread_mutex_unlock(&vout_android_lock);
- }
- static void debug_log(void *data, int level, const char *fmt, va_list ap)
- {
- bool *verbose = data;
- static const uint8_t priority[5] = {
- [LIBVLC_DEBUG] = ANDROID_LOG_DEBUG,
- [1 /* ??? */] = ANDROID_LOG_DEBUG,
- [LIBVLC_NOTICE] = ANDROID_LOG_INFO,
- [LIBVLC_WARNING] = ANDROID_LOG_WARN,
- [LIBVLC_ERROR] = ANDROID_LOG_ERROR,
- };
- int prio = ANDROID_LOG_DEBUG;
- if (level >= LIBVLC_DEBUG && level <= LIBVLC_ERROR)
- prio = priority[level];
- if (!*verbose && prio < ANDROID_LOG_ERROR)
- return;
- __android_log_vprint(prio, "VLC", fmt, ap);
- }
- static libvlc_log_subscriber_t debug_subscriber;
- static bool verbosity;
- void Java_org_videolan_vlc_LibVLC_changeVerbosity(JNIEnv *env, jobject thiz, jboolean verbose)
- {
- verbosity = verbose;
- libvlc_log_unsubscribe(&debug_subscriber);
- libvlc_log_subscribe(&debug_subscriber, debug_log, &verbosity);
- }
- void Java_org_videolan_vlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz, jboolean verbose)
- {
- //only use OpenSLES if java side says we can
- jclass cls = (*env)->GetObjectClass(env, thiz);
- jmethodID methodId = (*env)->GetMethodID(env, cls, "getAout", "()I");
- bool use_opensles = (*env)->CallIntMethod(env, thiz, methodId) == AOUT_OPENSLES;
- methodId = (*env)->GetMethodID(env, cls, "timeStretchingEnabled", "()Z");
- bool enable_time_stretch = (*env)->CallBooleanMethod(env, thiz, methodId);
- methodId = (*env)->GetMethodID(env, cls, "getSubtitlesEncoding", "()Ljava/lang/String;");
- jstring subsencoding = (*env)->CallObjectMethod(env, thiz, methodId);
- const char *subsencodingstr = (*env)->GetStringUTFChars(env, subsencoding, 0);
- LOGD("Subtitle encoding set to \"%s\"", subsencodingstr);
- verbosity = verbose;
- libvlc_log_subscribe(&debug_subscriber, debug_log, &verbosity);
- /* Don't add any invalid options, otherwise it causes LibVLC to crash */
- const char *argv[] = {
- "-I", "dummy",
- "--no-osd",
- "--no-video-title-show",
- "--no-stats",
- "--no-plugins-cache",
- "--no-drop-late-frames",
- "--avcodec-fast",
- "--avcodec-threads=0",
- "--subsdec-encoding", subsencodingstr,
- enable_time_stretch ? "--audio-time-stretch" : "--no-audio-time-stretch",
- use_opensles ? "--aout=opensles" : "--aout=android_audiotrack",
- };
- libvlc_instance_t *instance = libvlc_new(sizeof(argv) / sizeof(*argv), argv);
- setLong(env, thiz, "mLibVlcInstance", (jlong)(intptr_t) instance);
- (*env)->ReleaseStringUTFChars(env, subsencoding, subsencodingstr);
- if (!instance)
- {
- jclass exc = (*env)->FindClass(env, "org/videolan/vlc/LibVlcException");
- (*env)->ThrowNew(env, exc, "Unable to instantiate LibVLC");
- }
- LOGI("LibVLC initialized: %p", instance);
- /* Initialize media list (a.k.a. playlist/history) */
- libvlc_media_list_t* pointer = libvlc_media_list_new( instance );
- if(!pointer) {
- jclass exc = (*env)->FindClass(env, "org/videolan/vlc/LibVlcException");
- (*env)->ThrowNew(env, exc, "Unable to create LibVLC media list");
- return;
- }
- /* 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);
- setLong(env, thiz, "mMediaListInstance", (jlong)(intptr_t)pointer);
- }
- jstring Java_org_videolan_vlc_LibVLC_nativeToURI(JNIEnv *env, jobject thiz, jstring path)
- {
- jboolean isCopy;
- /* Get C string */
- const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);
- /* Convert the path to URI */
- char* psz_location;
- if(unlikely( strstr( psz_path, "://" ) ))
- psz_location = strdup(psz_path);
- else
- psz_location = vlc_path2uri(psz_path, "file");
- /* Box into jstring */
- jstring t = (*env)->NewStringUTF(env, psz_location);
- /* Clean up */
- (*env)->ReleaseStringUTFChars(env, path, psz_path);
- free(psz_location);
- return t;
- }
- void Java_org_videolan_vlc_LibVLC_nativeDestroy(JNIEnv *env, jobject thiz)
- {
- releaseMediaPlayer(env, thiz);
- jlong libVlcInstance = getLong(env, thiz, "mLibVlcInstance");
- if (!libVlcInstance)
- return; // Already destroyed
- libvlc_instance_t *instance = (libvlc_instance_t*)(intptr_t) libVlcInstance;
- libvlc_release(instance);
- libvlc_log_unsubscribe(&debug_subscriber);
- setLong(env, thiz, "mLibVlcInstance", 0);
- }
- void Java_org_videolan_vlc_LibVLC_detachEventManager(JNIEnv *env, jobject thiz)
- {
- if (eventManagerInstance != NULL) {
- (*env)->DeleteGlobalRef(env, eventManagerInstance);
- eventManagerInstance = NULL;
- }
- }
- void Java_org_videolan_vlc_LibVLC_setEventManager(JNIEnv *env, jobject thiz, jobject eventManager)
- {
- if (eventManagerInstance != NULL) {
- (*env)->DeleteGlobalRef(env, eventManagerInstance);
- eventManagerInstance = NULL;
- }
- jclass cls = (*env)->GetObjectClass(env, eventManager);
- if (!cls) {
- LOGE("setEventManager: failed to get class reference");
- return;
- }
- jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(ILandroid/os/Bundle;)V");
- if (!methodID) {
- LOGE("setEventManager: failed to get the callback method");
- return;
- }
- eventManagerInstance = (*env)->NewGlobalRef(env, eventManager);
- }
- jobjectArray Java_org_videolan_vlc_LibVLC_readMediaMeta(JNIEnv *env,
- jobject thiz, jlong instance, jstring mrl)
- {
- jobjectArray array = (*env)->NewObjectArray(env, 8,
- (*env)->FindClass(env, "java/lang/String"),
- (*env)->NewStringUTF(env, ""));
- libvlc_media_t *m = new_media(instance, env, thiz, mrl, false, false);
- if (!m)
- {
- LOGE("readMediaMeta: Could not create the media!");
- return array;
- }
- libvlc_media_parse(m);
- static const char str[][7] = {
- "artist", "album", "title", "genre",
- };
- static const libvlc_meta_t meta_id[] = {
- libvlc_meta_Artist,
- libvlc_meta_Album,
- libvlc_meta_Title,
- libvlc_meta_Genre,
- };
- for (int i=0; i < sizeof(str) / sizeof(*str); i++) {
- char *meta = libvlc_media_get_meta(m, meta_id[i]);
- if (!meta)
- meta = strdup("");
- jstring k = (*env)->NewStringUTF(env, str[i]);
- (*env)->SetObjectArrayElement(env, array, 2*i, k);
- jstring v = (*env)->NewStringUTF(env, meta);
- (*env)->SetObjectArrayElement(env, array, 2*i+1, v);
- free(meta);
- }
- libvlc_media_release(m);
- return array;
- }
- static void create_player_and_play(JNIEnv* env, jobject thiz,
- jlong instance, int position) {
- /* Release previous media player, if any */
- releaseMediaPlayer(env, thiz);
- libvlc_media_list_t* p_mlist = getMediaList(env, thiz);
- /* Create a media player playing environment */
- libvlc_media_list_player_t* p_mlp = libvlc_media_list_player_new((libvlc_instance_t*)(intptr_t)instance);
- libvlc_media_player_t *mp = libvlc_media_player_new((libvlc_instance_t*)(intptr_t)instance);
- jobject myJavaLibVLC = (*env)->NewGlobalRef(env, thiz);
- //if AOUT_AUDIOTRACK_JAVA, we use amem
- jclass cls = (*env)->GetObjectClass(env, thiz);
- jmethodID methodId = (*env)->GetMethodID(env, cls, "getAout", "()I");
- if ( (*env)->CallIntMethod(env, thiz, methodId) == AOUT_AUDIOTRACK_JAVA )
- {
- libvlc_audio_set_callbacks(mp, aout_play, aout_pause, NULL, NULL, NULL,
- (void*) myJavaLibVLC);
- libvlc_audio_set_format_callbacks(mp, aout_open, aout_close);
- }
- /* Connect the event manager */
- libvlc_event_manager_t *ev = libvlc_media_player_event_manager(mp);
- static const libvlc_event_type_t mp_events[] = {
- libvlc_MediaPlayerPlaying,
- libvlc_MediaPlayerPaused,
- libvlc_MediaPlayerEndReached,
- libvlc_MediaPlayerStopped,
- libvlc_MediaPlayerVout,
- };
- for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
- libvlc_event_attach(ev, mp_events[i], vlc_event_callback, myVm);
- libvlc_media_list_player_set_media_list(p_mlp, p_mlist);
- libvlc_media_list_player_set_media_player(p_mlp, mp);
- /* Keep a pointer to this media player */
- setLong(env, thiz, "mMediaListPlayerInstance", (jlong)(intptr_t)p_mlp);
- setLong(env, thiz, "mInternalMediaPlayerInstance", (jlong)(intptr_t)mp);
- libvlc_media_list_player_play_item_at_index(p_mlp, position);
- }
- jint Java_org_videolan_vlc_LibVLC_readMedia(JNIEnv *env, jobject thiz,
- jlong instance, jstring mrl, jboolean novideo)
- {
- /* Create a new item */
- libvlc_media_t *m = new_media(instance, env, thiz, mrl, false, novideo);
- if (!m)
- {
- LOGE("readMedia: Could not create the media!");
- return -1;
- }
- libvlc_media_list_t* p_mlist = getMediaList(env, thiz);
- libvlc_media_list_lock(p_mlist);
- if(libvlc_media_list_add_media(p_mlist, m) != 0) {
- LOGE("readMedia: Could not add to the media list!");
- libvlc_media_list_unlock(p_mlist);
- libvlc_media_release(m);
- return -1;
- }
- int position = libvlc_media_list_index_of_item(p_mlist, m);
- libvlc_media_list_unlock(p_mlist);
- /* No need to keep the media now */
- libvlc_media_release(m);
- create_player_and_play(env, thiz, instance, position);
- return position;
- }
- void Java_org_videolan_vlc_LibVLC_playIndex(JNIEnv *env, jobject thiz,
- jlong instance, int position) {
- create_player_and_play(env, thiz, instance, position);
- }
- void Java_org_videolan_vlc_LibVLC_getMediaListItems(
- JNIEnv *env, jobject thiz, jobject arrayList) {
- jclass arrayClass = (*env)->FindClass(env, "java/util/ArrayList");
- jmethodID methodID = (*env)->GetMethodID(env, arrayClass, "add", "(Ljava/lang/Object;)Z");
- jstring str;
- libvlc_media_list_t* p_mlist = getMediaList(env, thiz);
- libvlc_media_list_lock( p_mlist );
- for(int i = 0; i < libvlc_media_list_count( p_mlist ); i++) {
- char* mrl = libvlc_media_get_mrl( libvlc_media_list_item_at_index( p_mlist, i ) );
- str = (*env)->NewStringUTF(env, mrl);
- (*env)->CallBooleanMethod(env, arrayList, methodID, str);
- (*env)->DeleteLocalRef(env, str);
- free(mrl);
- }
- libvlc_media_list_unlock( p_mlist );
- }
- jfloat Java_org_videolan_vlc_LibVLC_getRate(JNIEnv *env, jobject thiz) {
- libvlc_media_player_t* mp = getMediaPlayer(env, thiz);
- if(mp)
- return libvlc_media_player_get_rate(mp);
- else
- return 1.00;
- }
- void Java_org_videolan_vlc_LibVLC_setRate(JNIEnv *env, jobject thiz, jfloat rate) {
- libvlc_media_player_t* mp = getMediaPlayer(env, thiz);
- if(mp)
- libvlc_media_player_set_rate(mp, rate);
- }
- jboolean Java_org_videolan_vlc_LibVLC_hasVideoTrack(JNIEnv *env, jobject thiz,
- jlong i_instance, jstring fileLocation)
- {
- /* Create a new item and assign it to the media player. */
- libvlc_media_t *p_m = new_media(i_instance, env, thiz, fileLocation, false, false);
- if (p_m == NULL)
- {
- LOGE("Could not create the media!");
- return JNI_FALSE;
- }
- /* Get the tracks information of the media. */
- libvlc_media_track_info_t *p_tracks;
- libvlc_media_parse(p_m);
- libvlc_media_player_t* p_mp = libvlc_media_player_new_from_media(p_m);
- struct length_change_monitor* monitor;
- monitor = malloc(sizeof(struct length_change_monitor));
- if (!monitor) return 0;
- /* Initialize pthread variables. */
- pthread_mutex_init(&monitor->doneMutex, NULL);
- pthread_cond_init(&monitor->doneCondVar, NULL);
- monitor->length_changed = false;
- libvlc_event_manager_t *ev = libvlc_media_player_event_manager(p_mp);
- libvlc_event_attach(ev, libvlc_MediaPlayerLengthChanged, length_changed_callback, monitor);
- libvlc_media_player_play( p_mp );
- pthread_mutex_lock(&monitor->doneMutex);
- struct timespec deadline;
- clock_gettime(CLOCK_REALTIME, &deadline);
- deadline.tv_sec += 2; /* If "VLC can't open the file", return */
- int mp_alive = 1;
- while( !monitor->length_changed && mp_alive ) {
- pthread_cond_timedwait(&monitor->doneCondVar, &monitor->doneMutex, &deadline);
- mp_alive = libvlc_media_player_will_play(p_mp);
- }
- pthread_mutex_unlock(&monitor->doneMutex);
- int i_nbTracks;
- if( mp_alive )
- i_nbTracks = libvlc_video_get_track_count(p_mp);
- else
- i_nbTracks = -1;
- LOGI("Number of video tracks: %d",i_nbTracks);
- libvlc_event_detach(ev, libvlc_MediaPlayerLengthChanged, length_changed_callback, monitor);
- libvlc_media_player_stop(p_mp);
- libvlc_media_player_release(p_mp);
- libvlc_media_release(p_m);
- pthread_mutex_destroy(&monitor->doneMutex);
- pthread_cond_destroy(&monitor->doneCondVar);
- free(monitor);
- if(i_nbTracks > 0)
- return JNI_TRUE;
- else if(i_nbTracks < 0)
- (*env)->ThrowNew(env, (*env)->FindClass(env, "java/io/IOException"), "VLC can't open the file");
- else
- return JNI_FALSE;
- }
- jobjectArray read_track_info_internal(JNIEnv *env, jobject thiz, libvlc_media_t* p_m)
- {
- /* get java class */
- jclass cls = (*env)->FindClass( env, "org/videolan/vlc/TrackInfo" );
- if ( !cls )
- {
- LOGE("Failed to load class (org/videolan/vlc/TrackInfo)" );
- return NULL;
- }
- /* get java class contructor */
- jmethodID clsCtor = (*env)->GetMethodID( env, cls, "<init>", "()V" );
- if ( !clsCtor )
- {
- LOGE("Failed to find class constructor (org/videolan/vlc/TrackInfo)" );
- return NULL;
- }
- /* Get the tracks information of the media. */
- libvlc_media_track_info_t *p_tracks;
- int i_nbTracks = libvlc_media_get_tracks_info(p_m, &p_tracks);
- jobjectArray array = (*env)->NewObjectArray(env, i_nbTracks + 1, cls, NULL);
- unsigned i;
- if (array != NULL)
- {
- for (i = 0; i <= i_nbTracks; ++i)
- {
- jobject item = (*env)->NewObject(env, cls, clsCtor);
- if (item == NULL)
- continue;
- (*env)->SetObjectArrayElement(env, array, i, item);
- // use last track for metadata
- if (i == i_nbTracks)
- {
- setInt(env, item, "Type", 3 /* TYPE_META */);
- setLong(env, item, "Length", libvlc_media_get_duration(p_m));
- setString(env, item, "Title", libvlc_media_get_meta(p_m, libvlc_meta_Title));
- setString(env, item, "Artist", libvlc_media_get_meta(p_m, libvlc_meta_Artist));
- setString(env, item, "Album", libvlc_media_get_meta(p_m, libvlc_meta_Album));
- setString(env, item, "Genre", libvlc_media_get_meta(p_m, libvlc_meta_Genre));
- setString(env, item, "ArtworkURL", libvlc_media_get_meta(p_m, libvlc_meta_ArtworkURL));
- continue;
- }
- setInt(env, item, "Id", p_tracks[i].i_id);
- setInt(env, item, "Type", p_tracks[i].i_type);
- setString(env, item, "Codec", (const char*)vlc_fourcc_GetDescription(0,p_tracks[i].i_codec));
- setString(env, item, "Language", p_tracks[i].psz_language);
- if (p_tracks[i].i_type == libvlc_track_video)
- {
- setInt(env, item, "Height", p_tracks[i].u.video.i_height);
- setInt(env, item, "Width", p_tracks[i].u.video.i_width);
- setFloat(env, item, "Framerate", p_tracks[i].u.video.f_frame_rate);
- }
- if (p_tracks[i].i_type == libvlc_track_audio)
- {
- setInt(env, item, "Channels", p_tracks[i].u.audio.i_channels);
- setInt(env, item, "Samplerate", p_tracks[i].u.audio.i_rate);
- }
- }
- }
- libvlc_media_tracks_info_release(p_tracks, i_nbTracks);
- return array;
- }
- jobjectArray Java_org_videolan_vlc_LibVLC_readTracksInfo(JNIEnv *env, jobject thiz,
- jlong instance, jstring mrl)
- {
- /* Create a new item and assign it to the media player. */
- libvlc_media_t *p_m = new_media(instance, env, thiz, mrl, false, false);
- if (p_m == NULL)
- {
- LOGE("Could not create the media!");
- return NULL;
- }
- libvlc_media_parse(p_m);
- jobjectArray jar = read_track_info_internal(env, thiz, p_m);
- libvlc_media_release(p_m);
- return jar;
- }
- jobjectArray Java_org_videolan_vlc_LibVLC_readTracksInfoPosition(JNIEnv *env, jobject thiz,
- jint position)
- {
- libvlc_media_list_t* p_mlist = getMediaList(env, thiz);
- libvlc_media_t *p_m = libvlc_media_list_item_at_index( p_mlist, position );
- if (p_m == NULL) {
- LOGE("Could not load get media @ position %d!", position);
- return NULL;
- } else
- return read_track_info_internal(env, thiz, p_m);
- }
- jlong Java_org_videolan_vlc_LibVLC_getLengthFromLocation(JNIEnv *env, jobject thiz,
- jlong i_instance, jstring fileLocation)
- {
- jlong length = 0;
- struct length_change_monitor *monitor;
- monitor = malloc(sizeof(*monitor));
- if (!monitor)
- return 0;
- /* Initialize pthread variables. */
- pthread_mutex_init(&monitor->doneMutex, NULL);
- pthread_cond_init(&monitor->doneCondVar, NULL);
- monitor->length_changed = false;
- /* Create a new item and assign it to the media player. */
- libvlc_media_t *m = new_media(i_instance, env, thiz, fileLocation, false, false);
- if (m == NULL)
- {
- LOGE("Could not create the media to play!");
- goto end;
- }
- /* Create a media player playing environment */
- libvlc_media_player_t *mp = libvlc_media_player_new_from_media (m);
- libvlc_event_manager_t *ev = libvlc_media_player_event_manager(mp);
- libvlc_event_attach(ev, libvlc_MediaPlayerLengthChanged, length_changed_callback, monitor);
- libvlc_media_release (m);
- libvlc_media_player_play( mp );
- pthread_mutex_lock(&monitor->doneMutex);
- while (!monitor->length_changed)
- pthread_cond_wait(&monitor->doneCondVar, &monitor->doneMutex);
- pthread_mutex_unlock(&monitor->doneMutex);
- length = libvlc_media_player_get_length( mp );
- libvlc_media_player_stop( mp );
- libvlc_media_player_release( mp );
- end:
- pthread_mutex_destroy(&monitor->doneMutex);
- pthread_cond_destroy(&monitor->doneCondVar);
- free(monitor);
- return length;
- }
- jboolean Java_org_videolan_vlc_LibVLC_hasMediaPlayer(JNIEnv *env, jobject thiz)
- {
- return !!getMediaListPlayer(env, thiz);
- }
- jboolean Java_org_videolan_vlc_LibVLC_isPlaying(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t *mp = getMediaListPlayer(env, thiz);
- if (mp)
- return !!libvlc_media_list_player_is_playing(mp);
- else
- return 0;
- }
- jboolean Java_org_videolan_vlc_LibVLC_isSeekable(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return !!libvlc_media_player_is_seekable(mp);
- return 0;
- }
- void Java_org_videolan_vlc_LibVLC_play(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t *mp = getMediaListPlayer(env, thiz);
- if (mp)
- libvlc_media_list_player_play(mp);
- }
- void Java_org_videolan_vlc_LibVLC_pause(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t *mp = getMediaListPlayer(env, thiz);
- if (mp)
- libvlc_media_list_player_pause(mp);
- }
- void Java_org_videolan_vlc_LibVLC_stop(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t *mp = getMediaListPlayer(env, thiz);
- if (mp)
- libvlc_media_list_player_stop(mp);
- }
- void Java_org_videolan_vlc_LibVLC_previous(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t *mp = getMediaListPlayer(env, thiz);
- if (mp)
- libvlc_media_list_player_previous(mp);
- }
- void Java_org_videolan_vlc_LibVLC_next(JNIEnv *env, jobject thiz)
- {
- libvlc_media_list_player_t *mp = getMediaListPlayer(env, thiz);
- if (mp)
- libvlc_media_list_player_next(mp);
- }
- jint Java_org_videolan_vlc_LibVLC_getVolume(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return (jint) libvlc_audio_get_volume(mp);
- return -1;
- }
- jint Java_org_videolan_vlc_LibVLC_setVolume(JNIEnv *env, jobject thiz, jint volume)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- //Returns 0 if the volume was set, -1 if it was out of range or error
- return (jint) libvlc_audio_set_volume(mp, (int) volume);
- return -1;
- }
- jlong Java_org_videolan_vlc_LibVLC_getTime(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return libvlc_media_player_get_time(mp);
- return -1;
- }
- void Java_org_videolan_vlc_LibVLC_setTime(JNIEnv *env, jobject thiz, jlong time)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- libvlc_media_player_set_time(mp, time);
- }
- jfloat Java_org_videolan_vlc_LibVLC_getPosition(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return (jfloat) libvlc_media_player_get_position(mp);
- return -1;
- }
- void Java_org_videolan_vlc_LibVLC_setPosition(JNIEnv *env, jobject thiz, jfloat pos)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- libvlc_media_player_set_position(mp, pos);
- }
- jlong Java_org_videolan_vlc_LibVLC_getLength(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return (jlong) libvlc_media_player_get_length(mp);
- return -1;
- }
- jstring Java_org_videolan_vlc_LibVLC_version(JNIEnv* env, jobject thiz)
- {
- return (*env)->NewStringUTF(env, libvlc_get_version());
- }
- jstring Java_org_videolan_vlc_LibVLC_compiler(JNIEnv* env, jobject thiz)
- {
- return (*env)->NewStringUTF(env, libvlc_get_compiler());
- }
- jstring Java_org_videolan_vlc_LibVLC_changeset(JNIEnv* env, jobject thiz)
- {
- return (*env)->NewStringUTF(env, libvlc_get_changeset());
- }
- jint Java_org_videolan_vlc_LibVLC_getAudioTracksCount(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return (jint) libvlc_audio_get_track_count(mp);
- return -1;
- }
- jobjectArray Java_org_videolan_vlc_LibVLC_getAudioTrackDescription(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (!mp)
- return NULL;
- int i_nbTracks = libvlc_audio_get_track_count(mp) - 1;
- if (i_nbTracks < 0)
- i_nbTracks = 0;
- jobjectArray array = (*env)->NewObjectArray(env, i_nbTracks,
- (*env)->FindClass(env, "java/lang/String"),
- NULL);
- libvlc_track_description_t *first = libvlc_audio_get_track_description(mp);
- libvlc_track_description_t *desc = first != NULL ? first->p_next : NULL;
- unsigned i;
- for (i = 0; i < i_nbTracks; ++i)
- {
- jstring name = (*env)->NewStringUTF(env, desc->psz_name);
- (*env)->SetObjectArrayElement(env, array, i, name);
- desc = desc->p_next;
- }
- libvlc_track_description_list_release(first);
- return array;
- }
- jint Java_org_videolan_vlc_LibVLC_getAudioTrack(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return libvlc_audio_get_track(mp);
- return -1;
- }
- jint Java_org_videolan_vlc_LibVLC_setAudioTrack(JNIEnv *env, jobject thiz, jint index)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return libvlc_audio_set_track(mp, index);
- return -1;
- }
- jint Java_org_videolan_vlc_LibVLC_getVideoTracksCount(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return (jint) libvlc_video_get_track_count(mp);
- return -1;
- }
- jobjectArray Java_org_videolan_vlc_LibVLC_getSpuTrackDescription(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (!mp)
- return NULL;
- int i_nbTracks = libvlc_video_get_spu_count(mp);
- jobjectArray array = (*env)->NewObjectArray(env, i_nbTracks,
- (*env)->FindClass(env, "java/lang/String"),
- NULL);
- libvlc_track_description_t *first = libvlc_video_get_spu_description(mp);
- libvlc_track_description_t *desc = first;
- unsigned i;
- for (i = 0; i < i_nbTracks; ++i)
- {
- jstring name = (*env)->NewStringUTF(env, desc->psz_name);
- (*env)->SetObjectArrayElement(env, array, i, name);
- desc = desc->p_next;
- }
- libvlc_track_description_list_release(first);
- return array;
- }
- jint Java_org_videolan_vlc_LibVLC_getSpuTracksCount(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return (jint) libvlc_video_get_spu_count(mp);
- return -1;
- }
- jint Java_org_videolan_vlc_LibVLC_getSpuTrack(JNIEnv *env, jobject thiz)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return libvlc_video_get_spu(mp);
- return -1;
- }
- jint Java_org_videolan_vlc_LibVLC_setSpuTrack(JNIEnv *env, jobject thiz, jint index)
- {
- libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
- if (mp)
- return libvlc_video_set_spu(mp, index);
- return -1;
- }
- void Java_org_videolan_vlc_LibVLC_nativeReadDirectory(JNIEnv *env, jobject thiz, jstring path, jobject arrayList)
- {
- jboolean isCopy;
- /* Get C string */
- const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);
- DIR* p_dir = opendir(psz_path);
- (*env)->ReleaseStringUTFChars(env, path, psz_path);
- if(!p_dir)
- return;
- jclass arrayClass = (*env)->FindClass(env, "java/util/ArrayList");
- jmethodID methodID = (*env)->GetMethodID(env, arrayClass, "add", "(Ljava/lang/Object;)Z");
- struct dirent* p_dirent;
- jstring str;
- while(1) {
- errno = 0;
- p_dirent = readdir(p_dir);
- if(p_dirent == NULL) {
- if(errno > 0) /* error reading this entry */
- continue;
- else if(errno == 0) /* end of stream */
- break;
- }
- str = (*env)->NewStringUTF(env, p_dirent->d_name);
- (*env)->CallBooleanMethod(env, arrayList, methodID, str);
- (*env)->DeleteLocalRef(env, str);
- }
- closedir(p_dir);
- }
- jboolean Java_org_videolan_vlc_LibVLC_nativeIsPathDirectory(JNIEnv *env, jobject thiz, jstring path)
- {
- jboolean isCopy;
- /* Get C string */
- const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);
- jboolean isDirectory;
- struct stat buf;
- if(stat(psz_path, &buf) != 0)
- /* couldn't stat */
- isDirectory = JNI_FALSE;
- else {
- if(S_ISDIR(buf.st_mode))
- isDirectory = JNI_TRUE;
- else
- isDirectory = JNI_FALSE;
- }
- (*env)->ReleaseStringUTFChars(env, path, psz_path);
- return isDirectory;
- }
|