Advertisement
Guest User

Untitled

a guest
Jan 26th, 2021
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.17 KB | None | 0 0
  1. /*
  2. * This file is part of libbluray
  3. * Copyright (C) 2010 William Hahne
  4. * Copyright (C) 2012-2019 Petri Hintukainen <phintuka@users.sourceforge.net>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.s
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20.  
  21. #if HAVE_CONFIG_H
  22. #include "config.h"
  23. #endif
  24.  
  25. #include "bdj.h"
  26.  
  27. #include "native/register_native.h"
  28.  
  29. #include "file/file.h"
  30. #include "file/dirs.h"
  31. #include "file/dl.h"
  32. #include "util/strutl.h"
  33. #include "util/macro.h"
  34. #include "util/logging.h"
  35.  
  36.  
  37. #include <jni.h>
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. #ifdef __APPLE__
  43. #include <sys/types.h>
  44. #include <sys/wait.h>
  45. #include <limits.h>
  46. #include <unistd.h>
  47. #endif
  48.  
  49. #ifdef _WIN32
  50. #include <windows.h>
  51. #include <winreg.h>
  52. #endif
  53.  
  54.  
  55. #define BDJ_JARFILE "libbluray-j2se-" VERSION ".jar"
  56.  
  57.  
  58. struct bdjava_s {
  59. void *h_libjvm;
  60. JavaVM *jvm;
  61. };
  62.  
  63. typedef jint (JNICALL * fptr_JNI_CreateJavaVM) (JavaVM **pvm, void **penv,void *args);
  64. typedef jint (JNICALL * fptr_JNI_GetCreatedJavaVMs) (JavaVM **vmBuf, jsize bufLen, jsize *nVMs);
  65.  
  66.  
  67. static void *_jvm_dlopen(const char *java_home, const char *jvm_dir, const char *jvm_lib)
  68. {
  69. char *path = str_printf("%s" DIR_SEP "%s" DIR_SEP "%s", java_home, jvm_dir, jvm_lib);
  70. if (!path) {
  71. BD_DEBUG(DBG_CRIT, "out of memory\n");
  72. return NULL;
  73. }
  74. BD_DEBUG(DBG_BDJ, "Opening %s ...\n", path);
  75. void *h = dl_dlopen(path, NULL);
  76.  
  77. X_FREE(path);
  78. return h;
  79. }
  80.  
  81. static void *_jvm_dlopen_a(const char *java_home,
  82. const char * const *jvm_dir, unsigned num_jvm_dir,
  83. const char *jvm_lib)
  84. {
  85. unsigned ii;
  86. void *dll = NULL;
  87.  
  88. if (!java_home) {
  89. BD_DEBUG(DBG_BDJ, "Opening %s ...\n", jvm_lib);
  90. return dl_dlopen(jvm_lib, NULL);
  91. }
  92.  
  93. for (ii = 0; !dll && ii < num_jvm_dir; ii++) {
  94. dll = _jvm_dlopen(java_home, jvm_dir[ii], jvm_lib);
  95. }
  96.  
  97. return dll;
  98. }
  99.  
  100.  
  101. static void *_load_jvm(const char **p_java_home)
  102. {
  103. static const char * const jvm_path[] = {NULL, JDK_HOME,};
  104.  
  105. static const char jvm_lib[] = "libjvm";
  106.  
  107. static const char * const jvm_dir[] = {"jre/lib/" JAVA_ARCH "/server",
  108. "lib/" JAVA_ARCH "/server",
  109. "lib/server",
  110. "jre/lib/" JAVA_ARCH "/client",
  111. "lib/" JAVA_ARCH "/client",
  112. "lib/client",
  113. };
  114.  
  115. const unsigned num_jvm_dir = sizeof(jvm_dir) / sizeof(jvm_dir[0]);
  116. const unsigned num_jvm_path = sizeof(jvm_path) / sizeof(jvm_path[0]);
  117.  
  118. const char *java_home = NULL;
  119. unsigned path_ind;
  120. void *handle = NULL;
  121.  
  122. BD_DEBUG(DBG_BDJ, "JAVA_HOME not set, trying default locations\n");
  123.  
  124. /* try our pre-defined locations */
  125. for (path_ind = 0; !handle && path_ind < num_jvm_path; path_ind++) {
  126. if (jvm_path[path_ind] && !jvm_path[path_ind][0]) {
  127. /* skip empty JVM_HOME */
  128. } else if (jvm_path[path_ind] && file_path_exists(jvm_path[path_ind]) < 0) {
  129. BD_DEBUG(DBG_BDJ, "Skipping %s (not found)\n", jvm_path[path_ind]);
  130. } else {
  131. *p_java_home = jvm_path[path_ind];
  132. handle = _jvm_dlopen_a(jvm_path[path_ind], jvm_dir, num_jvm_dir, jvm_lib);
  133. }
  134. }
  135.  
  136. if (!*p_java_home) {
  137. *p_java_home = dl_get_path();
  138. }
  139.  
  140. return handle;
  141. }
  142.  
  143. static int _can_read_file(const char *fn)
  144. {
  145. BD_FILE_H *fp;
  146.  
  147. if (!fn) {
  148. return 0;
  149. }
  150.  
  151. fp = file_open(fn, "rb");
  152. if (fp) {
  153. uint8_t b;
  154. int result = (int)file_read(fp, &b, 1);
  155. file_close(fp);
  156. if (result == 1) {
  157. return 1;
  158. }
  159. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Error reading %s\n", fn);
  160. }
  161. return 0;
  162. }
  163.  
  164. void bdj_config_cleanup(BDJ_CONFIG *p)
  165. {
  166. X_FREE(p->cache_root);
  167. X_FREE(p->persistent_root);
  168. X_FREE(p->classpath[0]);
  169. X_FREE(p->classpath[1]);
  170. }
  171.  
  172. static char *_find_libbluray_jar0()
  173. {
  174. // pre-defined search paths for libbluray.jar
  175. static const char * const jar_paths[] = {
  176. BDJ_JARFILE,
  177. };
  178.  
  179. unsigned i;
  180.  
  181. // check if overriding the classpath
  182. const char *classpath = getenv("LIBBLURAY_CP");
  183. if (classpath) {
  184. size_t cp_len = strlen(classpath);
  185. char *jar;
  186.  
  187. // directory or file ?
  188. if (cp_len > 0 && (classpath[cp_len - 1] == '/' || classpath[cp_len - 1] == '\\')) {
  189. jar = str_printf("%s%s", classpath, BDJ_JARFILE);
  190. } else {
  191. jar = str_dup(classpath);
  192. }
  193.  
  194. if (!jar) {
  195. BD_DEBUG(DBG_CRIT, "out of memory\n");
  196. return NULL;
  197. }
  198.  
  199. if (_can_read_file(jar)) {
  200. return jar;
  201. }
  202.  
  203. X_FREE(jar);
  204. BD_DEBUG(DBG_BDJ | DBG_CRIT, "invalid LIBBLURAY_CP %s\n", classpath);
  205. return NULL;
  206. }
  207.  
  208. BD_DEBUG(DBG_BDJ, "LIBBLURAY_CP not set, searching for "BDJ_JARFILE" ...\n");
  209.  
  210. // check directory where libbluray.so was loaded from
  211. const char *lib_path = dl_get_path();
  212. if (lib_path) {
  213. char *cp = str_printf("%s" BDJ_JARFILE, lib_path);
  214. if (!cp) {
  215. BD_DEBUG(DBG_CRIT, "out of memory\n");
  216. return NULL;
  217. }
  218.  
  219. BD_DEBUG(DBG_BDJ, "Checking %s ...\n", cp);
  220. if (_can_read_file(cp)) {
  221. BD_DEBUG(DBG_BDJ, "using %s\n", cp);
  222. return cp;
  223. }
  224. X_FREE(cp);
  225. }
  226.  
  227. // check pre-defined directories
  228. for (i = 0; i < sizeof(jar_paths) / sizeof(jar_paths[0]); i++) {
  229. BD_DEBUG(DBG_BDJ, "Checking %s ...\n", jar_paths[i]);
  230. if (_can_read_file(jar_paths[i])) {
  231. BD_DEBUG(DBG_BDJ, "using %s\n", jar_paths[i]);
  232. return str_dup(jar_paths[i]);
  233. }
  234. }
  235.  
  236. BD_DEBUG(DBG_BDJ | DBG_CRIT, BDJ_JARFILE" not found.\n");
  237. return NULL;
  238. }
  239.  
  240. static char *_find_libbluray_jar1(const char *jar0)
  241. {
  242. char *jar1;
  243. int cut;
  244.  
  245. cut = (int)strlen(jar0) - (int)strlen(VERSION) - 9;
  246. if (cut <= 0)
  247. return NULL;
  248.  
  249. jar1 = str_printf("%.*sawt-%s", cut, jar0, jar0 + cut);
  250. if (!jar1)
  251. return NULL;
  252.  
  253. if (!_can_read_file(jar1)) {
  254. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Cant access AWT jar file %s\n", jar1);
  255. X_FREE(jar1);
  256. }
  257.  
  258. return jar1;
  259. }
  260.  
  261. static int _find_libbluray_jar(BDJ_CONFIG *storage)
  262. {
  263. if (!storage->classpath[0]) {
  264. storage->classpath[0] = _find_libbluray_jar0();
  265. X_FREE(storage->classpath[1]);
  266. if (!storage->classpath[0])
  267. return 0;
  268. }
  269.  
  270. if (!storage->classpath[1]) {
  271. storage->classpath[1] = _find_libbluray_jar1(storage->classpath[0]);
  272. if (!storage->classpath[1]) {
  273. X_FREE(storage->classpath[0]);
  274. X_FREE(storage->classpath[1]);
  275. }
  276. }
  277.  
  278. return !!storage->classpath[0];
  279. }
  280.  
  281. static const char *_bdj_persistent_root(BDJ_CONFIG *storage)
  282. {
  283. const char *root;
  284. char *data_home;
  285.  
  286. if (storage->no_persistent_storage) {
  287. return NULL;
  288. }
  289.  
  290. if (!storage->persistent_root) {
  291.  
  292. root = getenv("LIBBLURAY_PERSISTENT_ROOT");
  293. if (root) {
  294. return root;
  295. }
  296.  
  297. data_home = file_get_data_home();
  298. if (data_home) {
  299. storage->persistent_root = str_printf("%s" DIR_SEP "bluray" DIR_SEP "dvb.persistent.root" DIR_SEP, data_home);
  300. X_FREE(data_home);
  301. BD_DEBUG(DBG_BDJ, "LIBBLURAY_PERSISTENT_ROOT not set, using %s\n", storage->persistent_root);
  302. }
  303.  
  304. if (!storage->persistent_root) {
  305. BD_DEBUG(DBG_BDJ | DBG_CRIT, "WARNING: BD-J persistent root not set\n");
  306. }
  307. }
  308.  
  309. return storage->persistent_root;
  310. }
  311.  
  312. static const char *_bdj_buda_root(BDJ_CONFIG *storage)
  313. {
  314. const char *root;
  315. char *cache_home;
  316.  
  317. if (storage->no_persistent_storage) {
  318. return NULL;
  319. }
  320.  
  321. if (!storage->cache_root) {
  322.  
  323. root = getenv("LIBBLURAY_CACHE_ROOT");
  324. if (root) {
  325. return root;
  326. }
  327.  
  328. cache_home = file_get_cache_home();
  329. if (cache_home) {
  330. storage->cache_root = str_printf("%s" DIR_SEP "bluray" DIR_SEP "bluray.bindingunit.root" DIR_SEP, cache_home);
  331. X_FREE(cache_home);
  332. BD_DEBUG(DBG_BDJ, "LIBBLURAY_CACHE_ROOT not set, using %s\n", storage->cache_root);
  333. }
  334.  
  335. if (!storage->cache_root) {
  336. BD_DEBUG(DBG_BDJ | DBG_CRIT, "WARNING: BD-J cache root not set\n");
  337. }
  338. }
  339.  
  340. return storage->cache_root;
  341. }
  342.  
  343. static int _get_method(JNIEnv *env, jclass *cls, jmethodID *method_id,
  344. const char *class_name, const char *method_name, const char *method_sig)
  345. {
  346. *method_id = NULL;
  347. *cls = (*env)->FindClass(env, class_name);
  348. if (!*cls) {
  349. (*env)->ExceptionDescribe(env);
  350. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to locate class %s\n", class_name);
  351. (*env)->ExceptionClear(env);
  352. return 0;
  353. }
  354.  
  355. *method_id = (*env)->GetStaticMethodID(env, *cls, method_name, method_sig);
  356. if (!*method_id) {
  357. (*env)->ExceptionDescribe(env);
  358. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to locate class %s method %s %s\n",
  359. class_name, method_name, method_sig);
  360. (*env)->DeleteLocalRef(env, *cls);
  361. *cls = NULL;
  362. (*env)->ExceptionClear(env);
  363. return 0;
  364. }
  365.  
  366. return 1;
  367. }
  368.  
  369. static int _bdj_init(JNIEnv *env, struct bluray *bd, const char *disc_root, const char *bdj_disc_id,
  370. BDJ_CONFIG *storage)
  371. {
  372. if (!bdj_register_native_methods(env)) {
  373. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't register native methods.\n");
  374. }
  375.  
  376. // initialize class org.videolan.Libbluray
  377. jclass init_class;
  378. jmethodID init_id;
  379. if (!_get_method(env, &init_class, &init_id,
  380. "org/videolan/Libbluray", "init",
  381. "(JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V")) {
  382. return 0;
  383. }
  384.  
  385. const char *disc_id = (bdj_disc_id && bdj_disc_id[0]) ? bdj_disc_id : "00000000000000000000000000000000";
  386. jlong param_bdjava_ptr = (jlong)(intptr_t) bd;
  387. jstring param_disc_id = (*env)->NewStringUTF(env, disc_id);
  388. jstring param_disc_root = (*env)->NewStringUTF(env, disc_root);
  389. jstring param_persistent_root = (*env)->NewStringUTF(env, _bdj_persistent_root(storage));
  390. jstring param_buda_root = (*env)->NewStringUTF(env, _bdj_buda_root(storage));
  391.  
  392. (*env)->CallStaticVoidMethod(env, init_class, init_id,
  393. param_bdjava_ptr, param_disc_id, param_disc_root,
  394. param_persistent_root, param_buda_root);
  395.  
  396. (*env)->DeleteLocalRef(env, init_class);
  397. (*env)->DeleteLocalRef(env, param_disc_id);
  398. (*env)->DeleteLocalRef(env, param_disc_root);
  399. (*env)->DeleteLocalRef(env, param_persistent_root);
  400. (*env)->DeleteLocalRef(env, param_buda_root);
  401.  
  402. if ((*env)->ExceptionOccurred(env)) {
  403. (*env)->ExceptionDescribe(env);
  404. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to initialize BD-J (uncaught exception)\n");
  405. (*env)->ExceptionClear(env);
  406. return 0;
  407. }
  408.  
  409. return 1;
  410. }
  411.  
  412. int bdj_jvm_available(BDJ_CONFIG *storage)
  413. {
  414. const char *java_home;
  415. void* jvm_lib = _load_jvm(&java_home);
  416. if (!jvm_lib) {
  417. BD_DEBUG(DBG_BDJ | DBG_CRIT, "BD-J check: Failed to load JVM library\n");
  418. return BDJ_CHECK_NO_JVM;
  419. }
  420. dl_dlclose(jvm_lib);
  421.  
  422. if (!_find_libbluray_jar(storage)) {
  423. BD_DEBUG(DBG_BDJ | DBG_CRIT, "BD-J check: Failed to load libbluray.jar\n");
  424. return BDJ_CHECK_NO_JAR;
  425. }
  426.  
  427. BD_DEBUG(DBG_BDJ, "BD-J check: OK\n");
  428.  
  429. return BDJ_CHECK_OK;
  430. }
  431.  
  432. static int _find_jvm(void *jvm_lib, JNIEnv **env, JavaVM **jvm)
  433. {
  434. fptr_JNI_GetCreatedJavaVMs JNI_GetCreatedJavaVMs_fp;
  435.  
  436. *(void **)(&JNI_GetCreatedJavaVMs_fp) = dl_dlsym(jvm_lib, "JNI_GetCreatedJavaVMs");
  437. if (JNI_GetCreatedJavaVMs_fp == NULL) {
  438. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_GetCreatedJavaVMs.\n");
  439. return 0;
  440. }
  441.  
  442. jsize nVMs = 0;
  443. JavaVM* javavm = NULL;
  444.  
  445. int result = JNI_GetCreatedJavaVMs_fp(&javavm, 1, &nVMs);
  446. if (result == JNI_OK && nVMs > 0) {
  447. *jvm = javavm;
  448. (**jvm)->AttachCurrentThread(*jvm, (void**)env, NULL);
  449. return 1;
  450. }
  451.  
  452. return 0;
  453. }
  454.  
  455. /* Export packages for Xlets */
  456. static const char * const java_base_exports[] = {
  457. "javax.media" ,
  458. "javax.media.protocol",
  459. "javax.tv.graphics",
  460. "javax.tv.service",
  461. "javax.tv.service.guide",
  462. "javax.tv.service.selection",
  463. "javax.tv.service.transport",
  464. "javax.tv.service.navigation",
  465. "javax.tv.net",
  466. "javax.tv.locator",
  467. "javax.tv.util",
  468. "javax.tv.media",
  469. "javax.tv.xlet",
  470. "javax.microedition.xlet",
  471. "org.davic.resources",
  472. "org.davic.net",
  473. "org.davic.media",
  474. "org.davic.mpeg",
  475. "org.dvb.user",
  476. "org.dvb.dsmcc",
  477. "org.dvb.application",
  478. "org.dvb.ui",
  479. "org.dvb.test",
  480. "org.dvb.lang",
  481. "org.dvb.event",
  482. "org.dvb.io.ixc",
  483. "org.dvb.io.persistent",
  484. "org.dvb.media",
  485. "org.havi.ui",
  486. "org.havi.ui.event",
  487. "org.bluray.application",
  488. "org.bluray.ui",
  489. "org.bluray.ui.event",
  490. "org.bluray.net",
  491. "org.bluray.storage",
  492. "org.bluray.vfs",
  493. "org.bluray.bdplus",
  494. "org.bluray.system",
  495. "org.bluray.media",
  496. "org.bluray.ti",
  497. "org.bluray.ti.selection",
  498. "org.blurayx.s3d.ui",
  499. "org.blurayx.s3d.system",
  500. "org.blurayx.s3d.media",
  501. "org.blurayx.s3d.ti",
  502. "org.blurayx.uhd.ui",
  503. "org.blurayx.uhd.system",
  504. "org.blurayx.uhd.ti",
  505. "com.aacsla.bluray.online",
  506. "com.aacsla.bluray.mc",
  507. "com.aacsla.bluray.mt",
  508. "org.videolan.backdoor", /* entry for injected Xlet / runtime fixes */
  509. };
  510. static const size_t num_java_base_exports = sizeof(java_base_exports) / sizeof(java_base_exports[0]);
  511.  
  512. static int _create_jvm(void *jvm_lib, const char *java_home, const char *jar_file[2],
  513. JNIEnv **env, JavaVM **jvm)
  514. {
  515. (void)java_home; /* used only with J2ME */
  516.  
  517. fptr_JNI_CreateJavaVM JNI_CreateJavaVM_fp;
  518. JavaVMOption option[96];
  519. int n = 0, result, java_9;
  520. JavaVMInitArgs args;
  521.  
  522. *(void **)(&JNI_CreateJavaVM_fp) = dl_dlsym(jvm_lib, "JNI_CreateJavaVM");
  523. if (JNI_CreateJavaVM_fp == NULL) {
  524. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Couldn't find symbol JNI_CreateJavaVM.\n");
  525. return 0;
  526. }
  527.  
  528.  
  529. memset(option, 0, sizeof(option));
  530.  
  531. option[n++].optionString = str_dup ("-Dawt.toolkit=java.awt.BDToolkit");
  532. option[n++].optionString = str_dup ("-Djava.awt.graphicsenv=java.awt.BDGraphicsEnvironment");
  533. option[n++].optionString = str_dup ("-Xms256M");
  534. option[n++].optionString = str_dup ("-Xmx256M");
  535. option[n++].optionString = str_dup ("-Xss2048k");
  536.  
  537.  
  538. # define CLASSPATH_FORMAT_P "%s:%s"
  539.  
  540.  
  541. if (!java_9) {
  542. option[n++].optionString = str_dup ("-Djavax.accessibility.assistive_technologies= ");
  543. option[n++].optionString = str_printf("-Xbootclasspath/p:" CLASSPATH_FORMAT_P, jar_file[0], jar_file[1]);
  544. } else {
  545. option[n++].optionString = str_printf("--patch-module=java.base=%s", jar_file[0]);
  546. option[n++].optionString = str_printf("--patch-module=java.desktop=%s", jar_file[1]);
  547.  
  548. /* Fix module graph */
  549.  
  550. option[n++].optionString = str_dup("--add-reads=java.base=java.desktop");
  551. /* org.videolan.IxcRegistryImpl -> java.rmi.Remote */
  552. option[n++].optionString = str_dup("--add-reads=java.base=java.rmi");
  553. /* org.videolan.FontIndex -> java.xml. */
  554. option[n++].optionString = str_dup("--add-reads=java.base=java.xml");
  555. /* AWT needs to access logger and Xlet context */
  556. option[n++].optionString = str_dup("--add-opens=java.base/org.videolan=java.desktop");
  557. /* AWT needs to acess DVBGraphics */
  558. option[n++].optionString = str_dup("--add-exports=java.base/org.dvb.ui=java.desktop");
  559. /* org.havi.ui.HBackgroundImage needs to access sun.awt.image.FileImageSource */
  560. option[n++].optionString = str_dup("--add-exports=java.desktop/sun.awt.image=java.base");
  561.  
  562. /* Export BluRay packages to Xlets */
  563. for (size_t idx = 0; idx < num_java_base_exports; idx++) {
  564. option[n++].optionString = str_printf("--add-exports=java.base/%s=ALL-UNNAMED", java_base_exports[idx]);
  565. }
  566. }
  567.  
  568. /* JVM debug options */
  569.  
  570. if (getenv("BDJ_JVM_DISABLE_JIT")) {
  571. BD_DEBUG(DBG_CRIT | DBG_BDJ, "Disabling BD-J JIT\n");
  572. option[n++].optionString = str_dup("-Xint");
  573. }
  574. if (getenv("BDJ_JVM_DEBUG")) {
  575. BD_DEBUG(DBG_CRIT | DBG_BDJ, "Enabling BD-J debug mode\n");
  576. option[n++].optionString = str_dup("-ea");
  577. //option[n++].optionString = str_dup("-verbose");
  578. //option[n++].optionString = str_dup("-verbose:class,gc,jni");
  579. option[n++].optionString = str_dup("-Xdebug");
  580. option[n++].optionString = str_dup("-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n");
  581. }
  582.  
  583.  
  584. args.version = JNI_VERSION_1_4;
  585. args.nOptions = n;
  586. args.options = option;
  587. args.ignoreUnrecognized = JNI_FALSE; // don't ignore unrecognized options
  588.  
  589.  
  590. result = JNI_CreateJavaVM_fp(jvm, (void**) env, &args);
  591.  
  592. while (--n >= 0) {
  593. X_FREE(option[n].optionString);
  594. }
  595.  
  596. if (result != JNI_OK || !*env) {
  597. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to create new Java VM. JNI_CreateJavaVM result: %d\n", result);
  598. return 0;
  599. }
  600.  
  601. return 1;
  602. }
  603.  
  604. BDJAVA* bdj_open(const char *path, struct bluray *bd,
  605. const char *bdj_disc_id, BDJ_CONFIG *cfg)
  606. {
  607. BD_DEBUG(DBG_BDJ, "bdj_open()\n");
  608.  
  609. if (!_find_libbluray_jar(cfg)) {
  610. BD_DEBUG(DBG_BDJ | DBG_CRIT, "BD-J start failed: " BDJ_JARFILE " not found.\n");
  611. return NULL;
  612. }
  613.  
  614.  
  615. // first load the jvm using dlopen
  616. const char *java_home = NULL;
  617. void* jvm_lib = _load_jvm(&java_home);
  618.  
  619. if (!jvm_lib) {
  620. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Wasn't able to load JVM\n");
  621. return 0;
  622. }
  623.  
  624. BDJAVA* bdjava = calloc(1, sizeof(BDJAVA));
  625. if (!bdjava) {
  626. dl_dlclose(jvm_lib);
  627. return NULL;
  628. }
  629.  
  630. JNIEnv* env = NULL;
  631. JavaVM *jvm = NULL;
  632. const char *jar[2] = { cfg->classpath[0], cfg->classpath[1] };
  633. if (!_find_jvm(jvm_lib, &env, &jvm) &&
  634. !_create_jvm(jvm_lib, java_home, jar, &env, &jvm)) {
  635.  
  636. X_FREE(bdjava);
  637. dl_dlclose(jvm_lib);
  638. return NULL;
  639. }
  640.  
  641. bdjava->h_libjvm = jvm_lib;
  642. bdjava->jvm = jvm;
  643.  
  644. if (debug_mask & DBG_JNI) {
  645. int version = (int)(*env)->GetVersion(env);
  646. BD_DEBUG(DBG_BDJ, "Java version: %d.%d\n", version >> 16, version & 0xffff);
  647. }
  648.  
  649. if (!_bdj_init(env, bd, path, bdj_disc_id, cfg)) {
  650. bdj_close(bdjava);
  651. return NULL;
  652. }
  653.  
  654. /* detach java main thread (CreateJavaVM attachs calling thread to JVM) */
  655. (*bdjava->jvm)->DetachCurrentThread(bdjava->jvm);
  656.  
  657. return bdjava;
  658. }
  659.  
  660. void bdj_close(BDJAVA *bdjava)
  661. {
  662. JNIEnv *env;
  663. int attach = 0;
  664. jclass shutdown_class;
  665. jmethodID shutdown_id;
  666.  
  667. if (!bdjava) {
  668. return;
  669. }
  670.  
  671. BD_DEBUG(DBG_BDJ, "bdj_close()\n");
  672.  
  673. if (bdjava->jvm) {
  674. if ((*bdjava->jvm)->GetEnv(bdjava->jvm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
  675. (*bdjava->jvm)->AttachCurrentThread(bdjava->jvm, (void**)&env, NULL);
  676. attach = 1;
  677. }
  678.  
  679. if (_get_method(env, &shutdown_class, &shutdown_id,
  680. "org/videolan/Libbluray", "shutdown", "()V")) {
  681. (*env)->CallStaticVoidMethod(env, shutdown_class, shutdown_id);
  682.  
  683. if ((*env)->ExceptionOccurred(env)) {
  684. (*env)->ExceptionDescribe(env);
  685. BD_DEBUG(DBG_BDJ | DBG_CRIT, "Failed to shutdown BD-J (uncaught exception)\n");
  686. (*env)->ExceptionClear(env);
  687. }
  688.  
  689. (*env)->DeleteLocalRef(env, shutdown_class);
  690. }
  691.  
  692. bdj_unregister_native_methods(env);
  693.  
  694. if (attach) {
  695. (*bdjava->jvm)->DetachCurrentThread(bdjava->jvm);
  696. }
  697. }
  698.  
  699. if (bdjava->h_libjvm) {
  700. dl_dlclose(bdjava->h_libjvm);
  701. }
  702.  
  703.  
  704. X_FREE(bdjava);
  705. }
  706.  
  707. int bdj_process_event(BDJAVA *bdjava, unsigned ev, unsigned param)
  708. {
  709. static const char * const ev_name[] = {
  710. /* 0 */ "NONE",
  711.  
  712. /* 1 */ "START",
  713. /* 2 */ "STOP",
  714. /* 3 */ "PSR102",
  715.  
  716. /* 4 */ "PLAYLIST",
  717. /* 5 */ "PLAYITEM",
  718. /* 6 */ "CHAPTER",
  719. /* 7 */ "MARK",
  720. /* 8 */ "PTS",
  721. /* 9 */ "END_OF_PLAYLIST",
  722.  
  723. /* 10 */ "SEEK",
  724. /* 11 */ "RATE",
  725.  
  726. /* 12 */ "ANGLE",
  727. /* 13 */ "AUDIO_STREAM",
  728. /* 14 */ "SUBTITLE",
  729. /* 15 */ "SECONDARY_STREAM",
  730.  
  731. /* 16 */ "VK_KEY",
  732. /* 17 */ "UO_MASKED",
  733. /* 18 */ "MOUSE",
  734. };
  735.  
  736. JNIEnv* env;
  737. int attach = 0;
  738. jclass event_class;
  739. jmethodID event_id;
  740. int result = -1;
  741.  
  742. if (!bdjava) {
  743. return -1;
  744. }
  745.  
  746. if (ev > BDJ_EVENT_LAST) {
  747. BD_DEBUG(DBG_BDJ | DBG_CRIT, "bdj_process_event(%d,%d): unknown event\n", ev, param);
  748. }
  749. // Disable too verbose logging (PTS)
  750. else if (ev != BDJ_EVENT_PTS) {
  751. BD_DEBUG(DBG_BDJ, "bdj_process_event(%s,%d)\n", ev_name[ev], param);
  752. }
  753.  
  754. if ((*bdjava->jvm)->GetEnv(bdjava->jvm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) {
  755. (*bdjava->jvm)->AttachCurrentThread(bdjava->jvm, (void**)&env, NULL);
  756. attach = 1;
  757. }
  758.  
  759. if (_get_method(env, &event_class, &event_id,
  760. "org/videolan/Libbluray", "processEvent", "(II)Z")) {
  761. if ((*env)->CallStaticBooleanMethod(env, event_class, event_id, (jint)ev, (jint)param)) {
  762. result = 0;
  763. }
  764.  
  765. if ((*env)->ExceptionOccurred(env)) {
  766. (*env)->ExceptionDescribe(env);
  767. BD_DEBUG(DBG_BDJ | DBG_CRIT, "bdj_process_event(%u,%u) failed (uncaught exception)\n", ev, param);
  768. (*env)->ExceptionClear(env);
  769. }
  770.  
  771. (*env)->DeleteLocalRef(env, event_class);
  772. }
  773.  
  774. if (attach) {
  775. (*bdjava->jvm)->DetachCurrentThread(bdjava->jvm);
  776. }
  777.  
  778. return result;
  779. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement