<commit_before>/*
 * This file is part of libbluray
 * Copyright (C) 2010      <NAME>
 * Copyright (C) 2012-2014 <NAME> <<EMAIL>>
 *
 * This library 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 library 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.s
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include "libbluray/bdj/bdj.h"
#include "libbluray/bdj/bdj_private.h"
#include "libbluray/bdj/bdj_util.h"
#include "libbluray/bdj/bdjo_parser.h"
#include "libbluray/bdj/common.h"  // BDJ_BDJO_PATH
#include "libbluray/bluray.h"
#include "libbluray/bluray_internal.h"

#include "util/strutl.h"
#include "util/macro.h"
#include "util/logging.h"

#include <string.h>
#include <inttypes.h>

/* this automatically generated header is included to cross-check native function signatures */
#include "org_videolan_Libbluray.h"

/* Disable some warnings */
#if defined __GNUC__
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#ifdef __cplusplus
#define CPP_EXTERN extern
#else
#define CPP_EXTERN
#endif

static jobject _make_title_info(JNIEnv* env, int title, int objType, int playbackType, const char* bdjoName, int hdmvOID)
{
    jstring name = bdjoName ? (*env)->NewStringUTF(env, bdjoName) : NULL;
    jobject ti = bdj_make_object(env, "org/videolan/TitleInfo",
                                 "(IIILjava/lang/String;I)V",
                                 title, objType, playbackType, name, hdmvOID);
    if (name)
        (*env)->DeleteLocalRef(env, name);
    return ti;
}

static jobjectArray _make_stream_array(JNIEnv* env, int count, BLURAY_STREAM_INFO* streams)
{
    jobjectArray streamArr = bdj_make_array(env,
                    "org/videolan/StreamInfo", count);
    for (int i = 0; i < count; i++) {
        BLURAY_STREAM_INFO s = streams[i];
        jstring lang = (*env)->NewStringUTF(env, (char*)s.lang);
        jobject streamObj = bdj_make_object(env, "org/videolan/StreamInfo",
                "(BBBCLjava/lang/String;BB)V", s.coding_type, s.format,
                s.rate, s.char_code, lang, s.aspect, s.subpath_id);
        (*env)->SetObjectArrayElement(env, streamArr, i, streamObj);
    }

    return streamArr;
}

static jobject _make_playlist_info(JNIEnv* env, BLURAY_TITLE_INFO* ti)
{
    jobjectArray marks = bdj_make_array(env, "org/videolan/TIMark",
            ti->mark_count);

    for (uint32_t i = 0; i < ti->mark_count; i++) {
        BLURAY_TITLE_MARK m = ti->marks[i];
        jobject mark = bdj_make_object(env, "org/videolan/TIMark",
                "(IIJJJI)V", m.idx, m.type, m.start, m.duration, m.offset, m.clip_ref);
        (*env)->SetObjectArrayElement(env, marks, i, mark);
    }

    jobjectArray clips = bdj_make_array(env, "org/videolan/TIClip",
            ti->clip_count);

    for (uint32_t i = 0; i < ti->clip_count; i++) {
        BLURAY_CLIP_INFO info = ti->clips[i];

        jobjectArray videoStreams = _make_stream_array(env, info.video_stream_count,
                info.video_streams);

        jobjectArray audioStreams = _make_stream_array(env, info.audio_stream_count,
                info.audio_streams);

        jobjectArray pgStreams = _make_stream_array(env, info.pg_stream_count,
                info.pg_streams);

        jobjectArray igStreams = _make_stream_array(env, info.ig_stream_count,
                info.ig_streams);

        jobjectArray secVideoStreams = _make_stream_array(env, info.sec_video_stream_count,
                info.sec_video_streams);

        jobjectArray secAudioStreams = _make_stream_array(env, info.sec_audio_stream_count,
                info.sec_audio_streams);

        jobject clip = bdj_make_object(env, "org/videolan/TIClip",
                "(I[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;)V",
                i, videoStreams, audioStreams, pgStreams, igStreams, secVideoStreams, secAudioStreams);

        (*env)->SetObjectArrayElement(env, clips, i, clip);
    }

    return bdj_make_object(env, "org/videolan/PlaylistInfo",
            "(IJI[Lorg/videolan/TIMark;[Lorg/videolan/TIClip;)V",
            ti->playlist, ti->duration, ti->angle_count, marks, clips);
}

static int _read_index(BDJAVA *bdj)
{
    if (!bdj) {
        return 0;
    }

    if (!bdj->index) {
        bdj->index = indx_parse(bdj->path);
    }

    return !!bdj->index;
}

JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getTitleInfoN
  (JNIEnv * env, jclass cls, jlong np, jint title)
{
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "getTitleInfoN(%d)\n", (int)title);

    if (!_read_index(bdj)) {
        return NULL;
    }

    if (title == 65535) {
        if (bdj->index->first_play.object_type == indx_object_type_hdmv)
            return _make_title_info(env, 65535, indx_object_type_hdmv,
                                    bdj->index->first_play.hdmv.playback_type,
                                    NULL,
                                    bdj->index->first_play.hdmv.id_ref);
        else
            return _make_title_info(env, 65535, indx_object_type_bdj,
                                    bdj->index->first_play.bdj.playback_type,
                                    bdj->index->first_play.bdj.name,
                                    -1);
    } else if (title == 0) {
        if (bdj->index->top_menu.object_type == indx_object_type_hdmv)
            return _make_title_info(env, 0, indx_object_type_hdmv,
                                    bdj->index->top_menu.hdmv.playback_type,
                                    NULL,
                                    bdj->index->top_menu.hdmv.id_ref);
        else
            return _make_title_info(env, 0, indx_object_type_bdj,
                                    bdj->index->top_menu.bdj.playback_type,
                                    bdj->index->top_menu.bdj.name,
                                    -1);
    } else if ((title > 0) && (title <= bdj->index->num_titles)) {
        if (bdj->index->titles[title - 1].object_type == indx_object_type_hdmv)
            return _make_title_info(env, title, indx_object_type_hdmv,
                                    bdj->index->titles[title - 1].hdmv.playback_type,
                                    NULL,
                                    bdj->index->titles[title - 1].hdmv.id_ref);
        else
            return _make_title_info(env, title, indx_object_type_bdj,
                                    bdj->index->titles[title - 1].bdj.playback_type,
                                    bdj->index->titles[title - 1].bdj.name,
                                    -1);
    }
    return NULL;
}

JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getPlaylistInfoN
  (JNIEnv * env, jclass cls, jlong np, jint playlist)
{
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    BLURAY_TITLE_INFO* ti;

    BD_DEBUG(DBG_JNI, "getPlaylistInfoN(%d)\n", (int)playlist);

    ti = bd_get_playlist_info(bdj->bd, playlist, 0);
    if (!ti)
        return NULL;

    jobject titleInfo = _make_playlist_info(env, ti);

    bd_free_title_info(ti);

    return titleInfo;
}

JNIEXPORT jbyteArray JNICALL Java_org_videolan_Libbluray_getAacsDataN
  (JNIEnv * env, jclass cls, jlong np, jint type)
{
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    const uint8_t *data = bd_get_aacs_data(bdj->bd, type);

    if (!data) {
        return NULL;
    }
    jbyteArray array = (*env)->NewByteArray(env, 16);
    (*env)->SetByteArrayRegion(env, array, 0, 16, (const jbyte *)data);
    return array;
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_getUOMaskN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_uo_mask(bdj->bd);
}

JNIEXPORT void JNICALL Java_org_videolan_Libbluray_setUOMaskN(JNIEnv * env,
        jclass cls, jlong np, jboolean menuCallMask, jboolean titleSearchMask) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    bdj->uo_mask = ((!!menuCallMask) * BDJ_MENU_CALL_MASK) | ((!!titleSearchMask) * BDJ_TITLE_SEARCH_MASK);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getTitlesN(JNIEnv * env,
                                                              jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    if (!_read_index(bdj)) {
        return 0;
    }

    return bdj->index->num_titles;
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekN(JNIEnv * env,
        jclass cls, jlong np, jlong pos) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekN(%"PRId64")\n", (int64_t)pos);

    return bd_seek(bdj->bd, pos);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekTimeN(JNIEnv * env,
        jclass cls, jlong np, jlong tick) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekTimeN(%"PRId64")\n", (int64_t)tick);

    return bd_seek_time(bdj->bd, tick);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekChapterN(JNIEnv * env,
        jclass cls, jlong np, jint chapter) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekChapterN(%d)\n", (int)chapter);

    return bd_seek_chapter(bdj->bd, chapter);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_chapterPosN(JNIEnv * env,
        jclass cls, jlong np, jint chapter) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_chapter_pos(bdj->bd, chapter);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getCurrentChapterN(
        JNIEnv * env, jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_current_chapter(bdj->bd);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekMarkN(JNIEnv * env,
        jclass cls, jlong np, jint mark) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekMarkN(%d)\n", (int)mark);

    return bd_seek_mark(bdj->bd, mark);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekPlayItemN(JNIEnv * env,
        jclass cls, jlong np, jint clip) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekPlayItemN(%d)\n", (int)clip);

    return bd_seek_playitem(bdj->bd, clip);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectPlaylistN(
        JNIEnv * env, jclass cls, jlong np, jint playlist, jint playitem, jint playmark, jlong time) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    if (!bdj || !bdj->bd) {
        return 0;
    }

    BD_DEBUG(DBG_JNI, "selectPlaylistN(pl=%d, pi=%d, pm=%d, time=%ld)\n",
             (int)playlist, (int)playitem, (int)playmark, (long)time);

    return bd_play_playlist_at(bdj->bd, playlist, playitem, playmark, time);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectTitleN(JNIEnv * env,
        jclass cls, jlong np, jint title) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "selectTitleN(%d)\n", (int)title);

    return bd_play_title_internal(bdj->bd, title);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectAngleN(JNIEnv * env,
        jclass cls, jlong np, jint angle) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_select_angle(bdj->bd, angle);
}

JNIEXPORT void JNICALL Java_org_videolan_Libbluray_seamlessAngleChangeN(
        JNIEnv * env, jclass cls, jlong np, jint angle) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    bd_seamless_angle_change(bdj->bd, angle);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_getTitleSizeN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_title_size(bdj->bd);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getCurrentAngleN(
        JNIEnv * env, jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_current_angle(bdj->bd);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_tell(bdj->bd);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellTimeN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_tell_time(bdj->bd);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectRateN(JNIEnv * env,
        jclass cls, jlong np, jfloat rate, jint reason) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    bd_select_rate(bdj->bd, (float)rate, reason);
    return 1;
}
<commit_msg>Log BD-J rate change requests<commit_after>/*
 * This file is part of libbluray
 * Copyright (C) 2010      <NAME>
 * Copyright (C) 2012-2014 <NAME> <<EMAIL>>
 *
 * This library 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 library 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.s
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see
 * <http://www.gnu.org/licenses/>.
 */

#include "libbluray/bdj/bdj.h"
#include "libbluray/bdj/bdj_private.h"
#include "libbluray/bdj/bdj_util.h"
#include "libbluray/bdj/bdjo_parser.h"
#include "libbluray/bdj/common.h"  // BDJ_BDJO_PATH
#include "libbluray/bluray.h"
#include "libbluray/bluray_internal.h"

#include "util/strutl.h"
#include "util/macro.h"
#include "util/logging.h"

#include <string.h>
#include <inttypes.h>

/* this automatically generated header is included to cross-check native function signatures */
#include "org_videolan_Libbluray.h"

/* Disable some warnings */
#if defined __GNUC__
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

#ifdef __cplusplus
#define CPP_EXTERN extern
#else
#define CPP_EXTERN
#endif

static jobject _make_title_info(JNIEnv* env, int title, int objType, int playbackType, const char* bdjoName, int hdmvOID)
{
    jstring name = bdjoName ? (*env)->NewStringUTF(env, bdjoName) : NULL;
    jobject ti = bdj_make_object(env, "org/videolan/TitleInfo",
                                 "(IIILjava/lang/String;I)V",
                                 title, objType, playbackType, name, hdmvOID);
    if (name)
        (*env)->DeleteLocalRef(env, name);
    return ti;
}

static jobjectArray _make_stream_array(JNIEnv* env, int count, BLURAY_STREAM_INFO* streams)
{
    jobjectArray streamArr = bdj_make_array(env,
                    "org/videolan/StreamInfo", count);
    for (int i = 0; i < count; i++) {
        BLURAY_STREAM_INFO s = streams[i];
        jstring lang = (*env)->NewStringUTF(env, (char*)s.lang);
        jobject streamObj = bdj_make_object(env, "org/videolan/StreamInfo",
                "(BBBCLjava/lang/String;BB)V", s.coding_type, s.format,
                s.rate, s.char_code, lang, s.aspect, s.subpath_id);
        (*env)->SetObjectArrayElement(env, streamArr, i, streamObj);
    }

    return streamArr;
}

static jobject _make_playlist_info(JNIEnv* env, BLURAY_TITLE_INFO* ti)
{
    jobjectArray marks = bdj_make_array(env, "org/videolan/TIMark",
            ti->mark_count);

    for (uint32_t i = 0; i < ti->mark_count; i++) {
        BLURAY_TITLE_MARK m = ti->marks[i];
        jobject mark = bdj_make_object(env, "org/videolan/TIMark",
                "(IIJJJI)V", m.idx, m.type, m.start, m.duration, m.offset, m.clip_ref);
        (*env)->SetObjectArrayElement(env, marks, i, mark);
    }

    jobjectArray clips = bdj_make_array(env, "org/videolan/TIClip",
            ti->clip_count);

    for (uint32_t i = 0; i < ti->clip_count; i++) {
        BLURAY_CLIP_INFO info = ti->clips[i];

        jobjectArray videoStreams = _make_stream_array(env, info.video_stream_count,
                info.video_streams);

        jobjectArray audioStreams = _make_stream_array(env, info.audio_stream_count,
                info.audio_streams);

        jobjectArray pgStreams = _make_stream_array(env, info.pg_stream_count,
                info.pg_streams);

        jobjectArray igStreams = _make_stream_array(env, info.ig_stream_count,
                info.ig_streams);

        jobjectArray secVideoStreams = _make_stream_array(env, info.sec_video_stream_count,
                info.sec_video_streams);

        jobjectArray secAudioStreams = _make_stream_array(env, info.sec_audio_stream_count,
                info.sec_audio_streams);

        jobject clip = bdj_make_object(env, "org/videolan/TIClip",
                "(I[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;[Lorg/videolan/StreamInfo;)V",
                i, videoStreams, audioStreams, pgStreams, igStreams, secVideoStreams, secAudioStreams);

        (*env)->SetObjectArrayElement(env, clips, i, clip);
    }

    return bdj_make_object(env, "org/videolan/PlaylistInfo",
            "(IJI[Lorg/videolan/TIMark;[Lorg/videolan/TIClip;)V",
            ti->playlist, ti->duration, ti->angle_count, marks, clips);
}

static int _read_index(BDJAVA *bdj)
{
    if (!bdj) {
        return 0;
    }

    if (!bdj->index) {
        bdj->index = indx_parse(bdj->path);
    }

    return !!bdj->index;
}

JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getTitleInfoN
  (JNIEnv * env, jclass cls, jlong np, jint title)
{
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "getTitleInfoN(%d)\n", (int)title);

    if (!_read_index(bdj)) {
        return NULL;
    }

    if (title == 65535) {
        if (bdj->index->first_play.object_type == indx_object_type_hdmv)
            return _make_title_info(env, 65535, indx_object_type_hdmv,
                                    bdj->index->first_play.hdmv.playback_type,
                                    NULL,
                                    bdj->index->first_play.hdmv.id_ref);
        else
            return _make_title_info(env, 65535, indx_object_type_bdj,
                                    bdj->index->first_play.bdj.playback_type,
                                    bdj->index->first_play.bdj.name,
                                    -1);
    } else if (title == 0) {
        if (bdj->index->top_menu.object_type == indx_object_type_hdmv)
            return _make_title_info(env, 0, indx_object_type_hdmv,
                                    bdj->index->top_menu.hdmv.playback_type,
                                    NULL,
                                    bdj->index->top_menu.hdmv.id_ref);
        else
            return _make_title_info(env, 0, indx_object_type_bdj,
                                    bdj->index->top_menu.bdj.playback_type,
                                    bdj->index->top_menu.bdj.name,
                                    -1);
    } else if ((title > 0) && (title <= bdj->index->num_titles)) {
        if (bdj->index->titles[title - 1].object_type == indx_object_type_hdmv)
            return _make_title_info(env, title, indx_object_type_hdmv,
                                    bdj->index->titles[title - 1].hdmv.playback_type,
                                    NULL,
                                    bdj->index->titles[title - 1].hdmv.id_ref);
        else
            return _make_title_info(env, title, indx_object_type_bdj,
                                    bdj->index->titles[title - 1].bdj.playback_type,
                                    bdj->index->titles[title - 1].bdj.name,
                                    -1);
    }
    return NULL;
}

JNIEXPORT jobject JNICALL Java_org_videolan_Libbluray_getPlaylistInfoN
  (JNIEnv * env, jclass cls, jlong np, jint playlist)
{
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    BLURAY_TITLE_INFO* ti;

    BD_DEBUG(DBG_JNI, "getPlaylistInfoN(%d)\n", (int)playlist);

    ti = bd_get_playlist_info(bdj->bd, playlist, 0);
    if (!ti)
        return NULL;

    jobject titleInfo = _make_playlist_info(env, ti);

    bd_free_title_info(ti);

    return titleInfo;
}

JNIEXPORT jbyteArray JNICALL Java_org_videolan_Libbluray_getAacsDataN
  (JNIEnv * env, jclass cls, jlong np, jint type)
{
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    const uint8_t *data = bd_get_aacs_data(bdj->bd, type);

    if (!data) {
        return NULL;
    }
    jbyteArray array = (*env)->NewByteArray(env, 16);
    (*env)->SetByteArrayRegion(env, array, 0, 16, (const jbyte *)data);
    return array;
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_getUOMaskN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_uo_mask(bdj->bd);
}

JNIEXPORT void JNICALL Java_org_videolan_Libbluray_setUOMaskN(JNIEnv * env,
        jclass cls, jlong np, jboolean menuCallMask, jboolean titleSearchMask) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    bdj->uo_mask = ((!!menuCallMask) * BDJ_MENU_CALL_MASK) | ((!!titleSearchMask) * BDJ_TITLE_SEARCH_MASK);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getTitlesN(JNIEnv * env,
                                                              jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    if (!_read_index(bdj)) {
        return 0;
    }

    return bdj->index->num_titles;
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekN(JNIEnv * env,
        jclass cls, jlong np, jlong pos) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekN(%"PRId64")\n", (int64_t)pos);

    return bd_seek(bdj->bd, pos);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekTimeN(JNIEnv * env,
        jclass cls, jlong np, jlong tick) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekTimeN(%"PRId64")\n", (int64_t)tick);

    return bd_seek_time(bdj->bd, tick);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekChapterN(JNIEnv * env,
        jclass cls, jlong np, jint chapter) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekChapterN(%d)\n", (int)chapter);

    return bd_seek_chapter(bdj->bd, chapter);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_chapterPosN(JNIEnv * env,
        jclass cls, jlong np, jint chapter) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_chapter_pos(bdj->bd, chapter);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getCurrentChapterN(
        JNIEnv * env, jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_current_chapter(bdj->bd);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekMarkN(JNIEnv * env,
        jclass cls, jlong np, jint mark) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekMarkN(%d)\n", (int)mark);

    return bd_seek_mark(bdj->bd, mark);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_seekPlayItemN(JNIEnv * env,
        jclass cls, jlong np, jint clip) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "seekPlayItemN(%d)\n", (int)clip);

    return bd_seek_playitem(bdj->bd, clip);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectPlaylistN(
        JNIEnv * env, jclass cls, jlong np, jint playlist, jint playitem, jint playmark, jlong time) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    if (!bdj || !bdj->bd) {
        return 0;
    }

    BD_DEBUG(DBG_JNI, "selectPlaylistN(pl=%d, pi=%d, pm=%d, time=%ld)\n",
             (int)playlist, (int)playitem, (int)playmark, (long)time);

    return bd_play_playlist_at(bdj->bd, playlist, playitem, playmark, time);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectTitleN(JNIEnv * env,
        jclass cls, jlong np, jint title) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "selectTitleN(%d)\n", (int)title);

    return bd_play_title_internal(bdj->bd, title);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectAngleN(JNIEnv * env,
        jclass cls, jlong np, jint angle) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_select_angle(bdj->bd, angle);
}

JNIEXPORT void JNICALL Java_org_videolan_Libbluray_seamlessAngleChangeN(
        JNIEnv * env, jclass cls, jlong np, jint angle) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    bd_seamless_angle_change(bdj->bd, angle);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_getTitleSizeN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_title_size(bdj->bd);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_getCurrentAngleN(
        JNIEnv * env, jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_get_current_angle(bdj->bd);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_tell(bdj->bd);
}

JNIEXPORT jlong JNICALL Java_org_videolan_Libbluray_tellTimeN(JNIEnv * env,
        jclass cls, jlong np) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;
    return bd_tell_time(bdj->bd);
}

JNIEXPORT jint JNICALL Java_org_videolan_Libbluray_selectRateN(JNIEnv * env,
        jclass cls, jlong np, jfloat rate, jint reason) {
    BDJAVA* bdj = (BDJAVA*)(intptr_t)np;

    BD_DEBUG(DBG_JNI, "selectRateN(%1.1f, %d)\n", (float)rate, (int)reason);

    bd_select_rate(bdj->bd, (float)rate, reason);
    return 1;
}

{'fraction_non_alphanumeric': 0.11529916195673358, 'fraction_numerical': 0.0053011108945624635, 'mean_word_length': 2.8761142166490408, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 171, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7583185', 'n_tokens_mistral': 10109, 'n_tokens_neox': 9484, 'n_words': 1819}