libvlcjni.c 20.4 KB
Newer Older
Rafaël Carré's avatar
Rafaël Carré committed
1
2
3
/*****************************************************************************
 * libvlcjni.c
 *****************************************************************************
Edward Wang's avatar
Edward Wang committed
4
 * Copyright © 2010-2013 VLC authors and VideoLAN
Rafaël Carré's avatar
Rafaël Carré committed
5
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
6
7
8
 * 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
Rafaël Carré's avatar
Rafaël Carré committed
9
10
11
12
 * (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
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
13
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
Rafaël Carré's avatar
Rafaël Carré committed
15
 *
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
16
17
18
 * 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.
Rafaël Carré's avatar
Rafaël Carré committed
19
20
 *****************************************************************************/

21
22
#include <dirent.h>
#include <errno.h>
23
#include <string.h>
24
#include <pthread.h>
25
#include <sys/stat.h>
26
#include <sys/types.h>
27
#include <unistd.h>
28

29
#include <vlc/vlc.h>
30
31
#include <vlc_common.h>
#include <vlc_url.h>
32

33
#include <jni.h>
34

35
#include <android/api-level.h>
36

37
#include "libvlcjni.h"
ivoire's avatar
ivoire committed
38
#include "aout.h"
39
#include "utils.h"
40
41

#define LOG_TAG "VLC/JNI/main"
42
43
#include "log.h"

44
libvlc_media_t *new_media(jlong instance, JNIEnv *env, jobject thiz, jstring fileLocation, bool noOmx, bool noVideo)
45
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
46
    libvlc_instance_t *libvlc = (libvlc_instance_t*)(intptr_t)instance;
47
    jboolean isCopy;
48
49
50
    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);
51
52
53
    if (!p_md)
        return NULL;

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
    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");
69
            libvlc_media_add_option(p_md, ":codec=mediacodec,iomx,all");
70
        }
71
72
        if (noVideo)
            libvlc_media_add_option(p_md, ":no-video");
73
    }
74
    return p_md;
75
76
}

77
78
79
80
81
82
83
// Get the current media list being followed
libvlc_media_list_t* getMediaList(JNIEnv *env, jobject thiz) {
    jclass clazz = (*env)->GetObjectClass(env, thiz);
    jfieldID fieldMP = (*env)->GetFieldID(env, clazz,
                                          "mMediaList", "Lorg/videolan/libvlc/MediaList;");
    jobject javaML = (*env)->GetObjectField(env, thiz, fieldMP);
    return getMediaListFromJava(env, javaML);
84
85
}

86
libvlc_media_player_t *getMediaPlayer(JNIEnv *env, jobject thiz)
87
{
Ludovic Fauvet's avatar
Ludovic Fauvet committed
88
    return (libvlc_media_player_t*)(intptr_t)getLong(env, thiz, "mInternalMediaPlayerInstance");
89
90
}

Rafaël Carré's avatar
Rafaël Carré committed
91
92
static void releaseMediaPlayer(JNIEnv *env, jobject thiz)
{
93
94
    libvlc_media_player_t* p_mp = getMediaPlayer(env, thiz);
    if (p_mp)
95
    {
96
97
        libvlc_media_player_stop(p_mp);
        libvlc_media_player_release(p_mp);
98
        setLong(env, thiz, "mInternalMediaPlayerInstance", 0);
99
100
101
    }
}

102
103
104
105
106
/* 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;
107

108
static jobject eventHandlerInstance = NULL;
109

110
111
/** vout lock declared in vout.c */
extern pthread_mutex_t vout_android_lock;
112

113
114
115
116
static void vlc_event_callback(const libvlc_event_t *ev, void *data)
{
    JNIEnv *env;

117
    bool isAttached = false;
118

119
    if (eventHandlerInstance == NULL)
Sébastien Toque's avatar
Sébastien Toque committed
120
        return;
121

Rafaël Carré's avatar
Rafaël Carré committed
122
123
    if ((*myVm)->GetEnv(myVm, (void**) &env, JNI_VERSION_1_2) < 0) {
        if ((*myVm)->AttachCurrentThread(myVm, &env, NULL) < 0)
124
            return;
125
        isAttached = true;
126
127
    }

128
129
130
131
132
133
134
135
136
137
    /* 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" );
138
    jmethodID putFloat = (*env)->GetMethodID(env, clsBundle, "putFloat", "(Ljava/lang/String;F)V" );
139
140
    jmethodID putString = (*env)->GetMethodID(env, clsBundle, "putString", "(Ljava/lang/String;Ljava/lang/String;)V" );

141
142
143
144
145
    if (ev->type == libvlc_MediaPlayerPositionChanged) {
            jstring sData = (*env)->NewStringUTF(env, "data");
            (*env)->CallVoidMethod(env, bundle, putFloat, sData, ev->u.media_player_position_changed.new_position);
            (*env)->DeleteLocalRef(env, sData);
    } else if(ev->type == libvlc_MediaPlayerVout) {
146
147
148
149
        /* 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);
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
    } 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);
173
174
    }

175
    /* Get the object class */
176
    jclass cls = (*env)->GetObjectClass(env, eventHandlerInstance);
177
    if (!cls) {
178
        LOGE("EventHandler: failed to get class reference");
179
        goto end;
180
181
182
    }

    /* Find the callback ID */
183
    jmethodID methodID = (*env)->GetMethodID(env, cls, "callback", "(ILandroid/os/Bundle;)V");
184
    if (methodID) {
185
        (*env)->CallVoidMethod(env, eventHandlerInstance, methodID, ev->type, bundle);
186
    } else {
187
        LOGE("EventHandler: failed to get the callback method");
188
189
    }

190
191
192
end:
    if (isAttached)
        (*myVm)->DetachCurrentThread(myVm);
193
194
}

195
jint JNI_OnLoad(JavaVM *vm, void *reserved)
196
{
197
198
199
    // Keep a reference on the Java VM.
    myVm = vm;

200
201
    pthread_mutex_init(&vout_android_lock, NULL);

202
    LOGD("JNI interface loaded.");
203
    return JNI_VERSION_1_2;
204
205
}

206
207
208
209
void JNI_OnUnload(JavaVM* vm, void* reserved) {
    pthread_mutex_destroy(&vout_android_lock);
}

Rafaël Carré's avatar
Rafaël Carré committed
210
211
// FIXME: use atomics
static bool verbosity;
212

213
void Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
214
{
215
216
217
218
219
    //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;

220
221
222
    methodId = (*env)->GetMethodID(env, cls, "timeStretchingEnabled", "()Z");
    bool enable_time_stretch = (*env)->CallBooleanMethod(env, thiz, methodId);

Edward Wang's avatar
Edward Wang committed
223
224
225
    methodId = (*env)->GetMethodID(env, cls, "frameSkipEnabled", "()Z");
    bool enable_frame_skip = (*env)->CallBooleanMethod(env, thiz, methodId);

Edward Wang's avatar
Edward Wang committed
226
227
228
229
230
    methodId = (*env)->GetMethodID(env, cls, "getDeblocking", "()I");
    int deblocking = (*env)->CallIntMethod(env, thiz, methodId);
    char deblockstr[2] = "3";
    snprintf(deblockstr, 2, "%d", deblocking);
    LOGD("Using deblocking level %d", deblocking);
231

Edward Wang's avatar
Edward Wang committed
232
233
234
235
236
237
238
239
    methodId = (*env)->GetMethodID(env, cls, "getNetworkCaching", "()I");
    int networkCaching = (*env)->CallIntMethod(env, thiz, methodId);
    char networkCachingstr[25] = "0";
    if(networkCaching > 0) {
        snprintf(networkCachingstr, 25, "--network-caching=%d", networkCaching);
        LOGD("Using network caching of %d ms", networkCaching);
    }

240
241
242
243
    methodId = (*env)->GetMethodID(env, cls, "getChroma", "()Ljava/lang/String;");
    jstring chroma = (*env)->CallObjectMethod(env, thiz, methodId);
    const char *chromastr = (*env)->GetStringUTFChars(env, chroma, 0);
    LOGD("Chroma set to \"%s\"", chromastr);
Edward Wang's avatar
Edward Wang committed
244

245
246
247
    methodId = (*env)->GetMethodID(env, cls, "getSubtitlesEncoding", "()Ljava/lang/String;");
    jstring subsencoding = (*env)->CallObjectMethod(env, thiz, methodId);
    const char *subsencodingstr = (*env)->GetStringUTFChars(env, subsencoding, 0);
Edward Wang's avatar
Edward Wang committed
248
    LOGD("Subtitle encoding set to \"%s\"", subsencodingstr);
249

250
251
252
    methodId = (*env)->GetMethodID(env, cls, "isVerboseMode", "()Z");
    verbosity = (*env)->CallBooleanMethod(env, thiz, methodId);

253
    /* Don't add any invalid options, otherwise it causes LibVLC to crash */
254
    const char *argv[] = {
255
        "-I", "dummy",
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
256
257
258
        "--no-osd",
        "--no-video-title-show",
        "--no-stats",
259
260
        "--no-plugins-cache",
        "--no-drop-late-frames",
261
262
263
264
        /* The VLC default is to pick the highest resolution possible
         * (i.e. 1080p). For mobile, pick a more sane default for slow
         * mobile data networks and slower hardware. */
        "--preferred-resolution", "360",
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
265
        "--avcodec-fast",
266
        "--avcodec-threads=0",
267
        "--subsdec-encoding", subsencodingstr,
268
        enable_time_stretch ? "--audio-time-stretch" : "--no-audio-time-stretch",
Edward Wang's avatar
Edward Wang committed
269
        "--avcodec-skiploopfilter", deblockstr,
Edward Wang's avatar
Edward Wang committed
270
271
        "--avcodec-skip-frame", enable_frame_skip ? "4" : "0",
        "--avcodec-skip-idct", enable_frame_skip ? "4" : "0",
Edward Wang's avatar
Edward Wang committed
272
        (networkCaching > 0) ? networkCachingstr : "",
273
        use_opensles ? "--aout=opensles" : "--aout=android_audiotrack",
274
        "--androidsurface-chroma", chromastr != NULL && chromastr[0] != 0 ? chromastr : "RV32",
275
    };
276
    libvlc_instance_t *instance = libvlc_new(sizeof(argv) / sizeof(*argv), argv);
277

Ludovic Fauvet's avatar
Ludovic Fauvet committed
278
    setLong(env, thiz, "mLibVlcInstance", (jlong)(intptr_t) instance);
279

280
    (*env)->ReleaseStringUTFChars(env, chroma, chromastr);
281
282
    (*env)->ReleaseStringUTFChars(env, subsencoding, subsencodingstr);

283
284
    if (!instance)
    {
285
        jclass exc = (*env)->FindClass(env, "org/videolan/libvlc/LibVlcException");
286
287
288
289
        (*env)->ThrowNew(env, exc, "Unable to instantiate LibVLC");
    }

    LOGI("LibVLC initialized: %p", instance);
290

Rafaël Carré's avatar
Rafaël Carré committed
291
    libvlc_log_set(instance, debug_log, &verbosity);
292
293
}

294
void Java_org_videolan_libvlc_LibVLC_nativeDestroy(JNIEnv *env, jobject thiz)
295
{
296
    releaseMediaPlayer(env, thiz);
Edward Wang's avatar
Edward Wang committed
297
    jlong libVlcInstance = getLong(env, thiz, "mLibVlcInstance");
298
299
300
    if (!libVlcInstance)
        return; // Already destroyed

Ludovic Fauvet's avatar
Ludovic Fauvet committed
301
    libvlc_instance_t *instance = (libvlc_instance_t*)(intptr_t) libVlcInstance;
Rafaël Carré's avatar
Rafaël Carré committed
302
    libvlc_log_unset(instance);
303
304
    libvlc_release(instance);

Edward Wang's avatar
Edward Wang committed
305
    setLong(env, thiz, "mLibVlcInstance", 0);
306
307
}

308
void Java_org_videolan_libvlc_LibVLC_detachEventHandler(JNIEnv *env, jobject thiz)
309
{
310
311
312
    if (eventHandlerInstance != NULL) {
        (*env)->DeleteGlobalRef(env, eventHandlerInstance);
        eventHandlerInstance = NULL;
313
314
315
    }
}

316
void Java_org_videolan_libvlc_LibVLC_setEventHandler(JNIEnv *env, jobject thiz, jobject eventHandler)
317
{
318
319
320
    if (eventHandlerInstance != NULL) {
        (*env)->DeleteGlobalRef(env, eventHandlerInstance);
        eventHandlerInstance = NULL;
321
322
    }

323
    eventHandlerInstance = getEventHandlerReference(env, thiz, eventHandler);
324
325
}

326
327
static void create_player_and_play(JNIEnv* env, jobject thiz,
                                   jlong instance, int position) {
328
329
330
    /* Release previous media player, if any */
    releaseMediaPlayer(env, thiz);

331
332
    libvlc_media_list_t* p_mlist = getMediaList(env, thiz);

333
    /* Create a media player playing environment */
Ludovic Fauvet's avatar
Ludovic Fauvet committed
334
    libvlc_media_player_t *mp = libvlc_media_player_new((libvlc_instance_t*)(intptr_t)instance);
335

336
337
    jobject myJavaLibVLC = (*env)->NewGlobalRef(env, thiz);

338
339
340
341
    //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 )
342
    {
343
        libvlc_audio_set_callbacks(mp, aout_play, aout_pause, NULL, NULL, NULL,
Sébastien Toque's avatar
Sébastien Toque committed
344
345
                                   (void*) myJavaLibVLC);
        libvlc_audio_set_format_callbacks(mp, aout_open, aout_close);
346
347
    }

348
349
    /* Connect the event manager */
    libvlc_event_manager_t *ev = libvlc_media_player_event_manager(mp);
350
351
352
353
354
    static const libvlc_event_type_t mp_events[] = {
        libvlc_MediaPlayerPlaying,
        libvlc_MediaPlayerPaused,
        libvlc_MediaPlayerEndReached,
        libvlc_MediaPlayerStopped,
355
        libvlc_MediaPlayerVout,
356
357
        libvlc_MediaPlayerPositionChanged,
        libvlc_MediaPlayerEncounteredError
358
    };
359
    for(int i = 0; i < (sizeof(mp_events) / sizeof(*mp_events)); i++)
360
361
        libvlc_event_attach(ev, mp_events[i], vlc_event_callback, myVm);

362

363
    /* Keep a pointer to this media player */
Ludovic Fauvet's avatar
Ludovic Fauvet committed
364
    setLong(env, thiz, "mInternalMediaPlayerInstance", (jlong)(intptr_t)mp);
365

366
367
368
369
370
371
    setInt(env, thiz, "mInternalMediaPlayerIndex", (jint)position);
    libvlc_media_list_lock(p_mlist);
    libvlc_media_t* p_md = libvlc_media_list_item_at_index(p_mlist, position);
    libvlc_media_list_unlock(p_mlist);
    libvlc_media_player_set_media(mp, p_md);
    libvlc_media_player_play(mp);
372
373
}

374
jint Java_org_videolan_libvlc_LibVLC_readMedia(JNIEnv *env, jobject thiz,
375
376
377
378
379
380
381
                                            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!");
382
        return -1;
383
384
385
386
387
    }

    libvlc_media_list_t* p_mlist = getMediaList(env, thiz);

    libvlc_media_list_lock(p_mlist);
388
389
390
391
    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);
392
        return -1;
393
    }
394
395
396
397
398
399
400
    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);
401
402

    return position;
403
404
}

405
void Java_org_videolan_libvlc_LibVLC_playIndex(JNIEnv *env, jobject thiz,
406
407
408
409
                                            jlong instance, int position) {
    create_player_and_play(env, thiz, instance, position);
}

410
void Java_org_videolan_libvlc_LibVLC_getMediaListItems(
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
                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 );
}

428
jfloat Java_org_videolan_libvlc_LibVLC_getRate(JNIEnv *env, jobject thiz) {
Edward Wang's avatar
Edward Wang committed
429
430
431
432
433
434
435
    libvlc_media_player_t* mp = getMediaPlayer(env, thiz);
    if(mp)
        return libvlc_media_player_get_rate(mp);
    else
        return 1.00;
}

436
void Java_org_videolan_libvlc_LibVLC_setRate(JNIEnv *env, jobject thiz, jfloat rate) {
Edward Wang's avatar
Edward Wang committed
437
438
439
440
441
    libvlc_media_player_t* mp = getMediaPlayer(env, thiz);
    if(mp)
        libvlc_media_player_set_rate(mp, rate);
}

442
jboolean Java_org_videolan_libvlc_LibVLC_isPlaying(JNIEnv *env, jobject thiz)
443
{
444
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
445
    if (mp)
446
        return !!libvlc_media_player_is_playing(mp);
447
448
    else
        return 0;
449
450
}

451
jboolean Java_org_videolan_libvlc_LibVLC_isSeekable(JNIEnv *env, jobject thiz)
452
{
453
454
455
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        return !!libvlc_media_player_is_seekable(mp);
456
    return 0;
457
458
}

459
void Java_org_videolan_libvlc_LibVLC_play(JNIEnv *env, jobject thiz)
460
{
461
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
462
    if (mp)
463
        libvlc_media_player_play(mp);
464
465
}

466
void Java_org_videolan_libvlc_LibVLC_pause(JNIEnv *env, jobject thiz)
467
{
468
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
469
    if (mp)
470
        libvlc_media_player_pause(mp);
471
472
}

473
void Java_org_videolan_libvlc_LibVLC_stop(JNIEnv *env, jobject thiz)
474
{
475
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
476
    if (mp)
477
        libvlc_media_player_stop(mp);
478
479
}

480
void Java_org_videolan_libvlc_LibVLC_previous(JNIEnv *env, jobject thiz)
Edward Wang's avatar
Edward Wang committed
481
{
482
483
484
485
486
487
488
    int current_position = getInt(env, thiz, "mInternalMediaPlayerIndex");

    if(current_position-1 >= 0) {
        setInt(env, thiz, "mInternalMediaPlayerIndex", (jint)(current_position-1));
        create_player_and_play(env, thiz,
             getLong(env, thiz, "mLibVlcInstance"), current_position-1);
    }
Edward Wang's avatar
Edward Wang committed
489
490
}

491
void Java_org_videolan_libvlc_LibVLC_next(JNIEnv *env, jobject thiz)
Edward Wang's avatar
Edward Wang committed
492
{
493
494
495
496
497
498
499
500
    libvlc_media_list_t* p_mlist = getMediaList(env, thiz);
    int current_position = getInt(env, thiz, "mInternalMediaPlayerIndex");

    if(current_position+1 < libvlc_media_list_count(p_mlist)) {
        setInt(env, thiz, "mInternalMediaPlayerIndex", (jint)(current_position+1));
        create_player_and_play(env, thiz,
             getLong(env, thiz, "mLibVlcInstance"), current_position+1);
    }
Edward Wang's avatar
Edward Wang committed
501
502
}

503
jint Java_org_videolan_libvlc_LibVLC_getVolume(JNIEnv *env, jobject thiz)
504
{
505
506
507
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        return (jint) libvlc_audio_get_volume(mp);
508
509
510
    return -1;
}

511
jint Java_org_videolan_libvlc_LibVLC_setVolume(JNIEnv *env, jobject thiz, jint volume)
512
{
513
514
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
515
        //Returns 0 if the volume was set, -1 if it was out of range or error
516
        return (jint) libvlc_audio_set_volume(mp, (int) volume);
517
518
519
    return -1;
}

520
jlong Java_org_videolan_libvlc_LibVLC_getTime(JNIEnv *env, jobject thiz)
521
{
522
523
524
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        return libvlc_media_player_get_time(mp);
525
526
527
    return -1;
}

528
void Java_org_videolan_libvlc_LibVLC_setTime(JNIEnv *env, jobject thiz, jlong time)
529
{
530
531
532
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        libvlc_media_player_set_time(mp, time);
533
534
}

535
jfloat Java_org_videolan_libvlc_LibVLC_getPosition(JNIEnv *env, jobject thiz)
536
{
537
538
539
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        return (jfloat) libvlc_media_player_get_position(mp);
540
541
542
    return -1;
}

543
void Java_org_videolan_libvlc_LibVLC_setPosition(JNIEnv *env, jobject thiz, jfloat pos)
544
{
545
546
547
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        libvlc_media_player_set_position(mp, pos);
548
549
}

550
jlong Java_org_videolan_libvlc_LibVLC_getLength(JNIEnv *env, jobject thiz)
551
{
552
553
554
    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);
    if (mp)
        return (jlong) libvlc_media_player_get_length(mp);
555
556
557
    return -1;
}

558
jstring Java_org_videolan_libvlc_LibVLC_version(JNIEnv* env, jobject thiz)
559
{
560
561
    return (*env)->NewStringUTF(env, libvlc_get_version());
}
562

563
jstring Java_org_videolan_libvlc_LibVLC_compiler(JNIEnv* env, jobject thiz)
564
565
566
567
{
    return (*env)->NewStringUTF(env, libvlc_get_compiler());
}

568
jstring Java_org_videolan_libvlc_LibVLC_changeset(JNIEnv* env, jobject thiz)
569
570
571
{
    return (*env)->NewStringUTF(env, libvlc_get_changeset());
}