summaryrefslogtreecommitdiffstats
path: root/misc
diff options
context:
space:
mode:
Diffstat (limited to 'misc')
-rw-r--r--misc/bstr.c20
-rw-r--r--misc/bstr.h8
-rw-r--r--misc/charset_conv.c21
-rw-r--r--misc/dispatch.c95
-rw-r--r--misc/io_utils.c87
-rw-r--r--misc/io_utils.h25
-rw-r--r--misc/jni.c312
-rw-r--r--misc/jni.h16
-rw-r--r--misc/json.c7
-rw-r--r--misc/json.h2
-rw-r--r--misc/language.c362
-rw-r--r--misc/language.h31
-rw-r--r--misc/node.c17
-rw-r--r--misc/node.h3
-rw-r--r--misc/path_utils.c219
-rw-r--r--misc/path_utils.h64
-rw-r--r--misc/random.c75
-rw-r--r--misc/random.h41
-rw-r--r--misc/rendezvous.c17
-rw-r--r--misc/thread_pool.c78
-rw-r--r--misc/thread_pool.h1
-rw-r--r--misc/thread_tools.c83
-rw-r--r--misc/thread_tools.h11
-rw-r--r--misc/uuid.c141
-rw-r--r--misc/uuid.h146
25 files changed, 1543 insertions, 339 deletions
diff --git a/misc/bstr.c b/misc/bstr.c
index 4f1e8629b3..abe688bd14 100644
--- a/misc/bstr.c
+++ b/misc/bstr.c
@@ -467,3 +467,23 @@ bool bstr_decode_hex(void *talloc_ctx, struct bstr hex, struct bstr *out)
*out = (struct bstr){ .start = arr, .len = len };
return true;
}
+
+#ifdef _WIN32
+
+#include <windows.h>
+
+int bstr_to_wchar(void *talloc_ctx, struct bstr s, wchar_t **ret)
+{
+ int count = MultiByteToWideChar(CP_UTF8, 0, s.start, s.len, NULL, 0);
+ if (count <= 0)
+ abort();
+ wchar_t *wbuf = *ret;
+ if (!wbuf || ta_get_size(wbuf) < (count + 1) * sizeof(wchar_t))
+ wbuf = talloc_realloc(talloc_ctx, wbuf, wchar_t, count + 1);
+ MultiByteToWideChar(CP_UTF8, 0, s.start, s.len, wbuf, count);
+ wbuf[count] = L'\0';
+ *ret = wbuf;
+ return count;
+}
+
+#endif
diff --git a/misc/bstr.h b/misc/bstr.h
index dc8ad4030c..aaae7d695c 100644
--- a/misc/bstr.h
+++ b/misc/bstr.h
@@ -56,6 +56,8 @@ static inline struct bstr bstrdup(void *talloc_ctx, struct bstr str)
return r;
}
+#define bstr0_lit(s) {(unsigned char *)(s), sizeof("" s) - 1}
+
static inline struct bstr bstr0(const char *s)
{
return (struct bstr){(unsigned char *)s, s ? strlen(s) : 0};
@@ -223,6 +225,12 @@ static inline bool bstr_eatend0(struct bstr *s, const char *prefix)
return bstr_eatend(s, bstr0(prefix));
}
+#ifdef _WIN32
+
+int bstr_to_wchar(void *talloc_ctx, struct bstr s, wchar_t **ret);
+
+#endif
+
// create a pair (not single value!) for "%.*s" printf syntax
#define BSTR_P(bstr) (int)((bstr).len), ((bstr).start ? (char*)(bstr).start : "")
diff --git a/misc/charset_conv.c b/misc/charset_conv.c
index 51e55c6338..b54f6362b6 100644
--- a/misc/charset_conv.c
+++ b/misc/charset_conv.c
@@ -101,18 +101,6 @@ static const char *mp_uchardet(void *talloc_ctx, struct mp_log *log, bstr buf)
const char *mp_charset_guess(void *talloc_ctx, struct mp_log *log, bstr buf,
const char *user_cp, int flags)
{
- if (strcasecmp(user_cp, "enca") == 0 || strcasecmp(user_cp, "guess") == 0 ||
- strcasecmp(user_cp, "uchardet") == 0 || strchr(user_cp, ':'))
- {
- mp_err(log, "This syntax for the --sub-codepage option was deprecated "
- "and has been removed.\n");
- if (strncasecmp(user_cp, "utf8:", 5) == 0) {
- user_cp = user_cp + 5;
- } else {
- user_cp = "";
- }
- }
-
if (user_cp[0] == '+') {
mp_verbose(log, "Forcing charset '%s'.\n", user_cp + 1);
return user_cp + 1;
@@ -126,7 +114,8 @@ const char *mp_charset_guess(void *talloc_ctx, struct mp_log *log, bstr buf,
int r = bstr_validate_utf8(buf);
if (r >= 0 || (r > -8 && (flags & MP_ICONV_ALLOW_CUTOFF))) {
- mp_verbose(log, "Data looks like UTF-8, ignoring user-provided charset.\n");
+ if (strcmp(user_cp, "auto") != 0 && !mp_charset_is_utf8(user_cp))
+ mp_verbose(log, "Data looks like UTF-8, ignoring user-provided charset.\n");
return "utf-8";
}
@@ -161,6 +150,9 @@ const char *mp_charset_guess(void *talloc_ctx, struct mp_log *log, bstr buf,
bstr mp_iconv_to_utf8(struct mp_log *log, bstr buf, const char *cp, int flags)
{
#if HAVE_ICONV
+ if (!buf.len)
+ return buf;
+
if (!cp || !cp[0] || mp_charset_is_utf8(cp))
return buf;
@@ -231,9 +223,10 @@ bstr mp_iconv_to_utf8(struct mp_log *log, bstr buf, const char *cp, int flags)
outbuf[osize - oleft - 1] = 0;
return (bstr){outbuf, osize - oleft - 1};
-#endif
failure:
+#endif
+
if (flags & MP_NO_LATIN1_FALLBACK) {
return buf;
} else {
diff --git a/misc/dispatch.c b/misc/dispatch.c
index 0c3c574afa..6fd9fe1a43 100644
--- a/misc/dispatch.c
+++ b/misc/dispatch.c
@@ -26,8 +26,8 @@
struct mp_dispatch_queue {
struct mp_dispatch_item *head, *tail;
- pthread_mutex_t lock;
- pthread_cond_t cond;
+ mp_mutex lock;
+ mp_cond cond;
void (*wakeup_fn)(void *wakeup_ctx);
void *wakeup_ctx;
void (*onlock_fn)(void *onlock_ctx);
@@ -39,7 +39,7 @@ struct mp_dispatch_queue {
// The target thread is in mp_dispatch_queue_process() (and either idling,
// locked, or running a dispatch callback).
bool in_process;
- pthread_t in_process_thread;
+ mp_thread_id in_process_thread_id;
// The target thread is in mp_dispatch_queue_process(), and currently
// something has exclusive access to it (e.g. running a dispatch callback,
// or a different thread got it with mp_dispatch_lock()).
@@ -48,7 +48,7 @@ struct mp_dispatch_queue {
size_t lock_requests;
// locked==true is due to a mp_dispatch_lock() call (for debugging).
bool locked_explicit;
- pthread_t locked_explicit_thread;
+ mp_thread_id locked_explicit_thread_id;
};
struct mp_dispatch_item {
@@ -67,8 +67,8 @@ static void queue_dtor(void *p)
assert(!queue->in_process);
assert(!queue->lock_requests);
assert(!queue->locked);
- pthread_cond_destroy(&queue->cond);
- pthread_mutex_destroy(&queue->lock);
+ mp_cond_destroy(&queue->cond);
+ mp_mutex_destroy(&queue->lock);
}
// A dispatch queue lets other threads run callbacks in a target thread.
@@ -76,7 +76,7 @@ static void queue_dtor(void *p)
// Free the dispatch queue with talloc_free(). At the time of destruction,
// the queue must be empty. The easiest way to guarantee this is to
// terminate all potential senders, then call mp_dispatch_run() with a
-// function that e.g. makes the target thread exit, then pthread_join() the
+// function that e.g. makes the target thread exit, then mp_thread_join() the
// target thread, and finally destroy the queue. Another way is calling
// mp_dispatch_queue_process() after terminating all potential senders, and
// then destroying the queue.
@@ -85,8 +85,8 @@ struct mp_dispatch_queue *mp_dispatch_create(void *ta_parent)
struct mp_dispatch_queue *queue = talloc_ptrtype(ta_parent, queue);
*queue = (struct mp_dispatch_queue){0};
talloc_set_destructor(queue, queue_dtor);
- pthread_mutex_init(&queue->lock, NULL);
- pthread_cond_init(&queue->cond, NULL);
+ mp_mutex_init(&queue->lock);
+ mp_cond_init(&queue->cond);
return queue;
}
@@ -126,14 +126,14 @@ void mp_dispatch_set_onlock_fn(struct mp_dispatch_queue *queue,
static void mp_dispatch_append(struct mp_dispatch_queue *queue,
struct mp_dispatch_item *item)
{
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
if (item->mergeable) {
for (struct mp_dispatch_item *cur = queue->head; cur; cur = cur->next) {
if (cur->mergeable && cur->fn == item->fn &&
cur->fn_data == item->fn_data)
{
talloc_free(item);
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
return;
}
}
@@ -148,12 +148,12 @@ static void mp_dispatch_append(struct mp_dispatch_queue *queue,
// Wake up the main thread; note that other threads might wait on this
// condition for reasons, so broadcast the condition.
- pthread_cond_broadcast(&queue->cond);
+ mp_cond_broadcast(&queue->cond);
// No wakeup callback -> assume mp_dispatch_queue_process() needs to be
// interrupted instead.
if (!queue->wakeup_fn)
queue->interrupted = true;
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
if (queue->wakeup_fn)
queue->wakeup_fn(queue->wakeup_ctx);
@@ -218,7 +218,7 @@ void mp_dispatch_enqueue_notify(struct mp_dispatch_queue *queue,
void mp_dispatch_cancel_fn(struct mp_dispatch_queue *queue,
mp_dispatch_fn fn, void *fn_data)
{
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
struct mp_dispatch_item **pcur = &queue->head;
queue->tail = NULL;
while (*pcur) {
@@ -231,7 +231,7 @@ void mp_dispatch_cancel_fn(struct mp_dispatch_queue *queue,
pcur = &cur->next;
}
}
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
}
// Run fn(fn_data) on the target thread synchronously. This function enqueues
@@ -247,10 +247,10 @@ void mp_dispatch_run(struct mp_dispatch_queue *queue,
};
mp_dispatch_append(queue, &item);
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
while (!item.completed)
- pthread_cond_wait(&queue->cond, &queue->lock);
- pthread_mutex_unlock(&queue->lock);
+ mp_cond_wait(&queue->cond, &queue->lock);
+ mp_mutex_unlock(&queue->lock);
}
// Process any outstanding dispatch items in the queue. This also handles
@@ -271,18 +271,18 @@ void mp_dispatch_run(struct mp_dispatch_queue *queue,
// no enqueued callback can call the lock/unlock functions).
void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
{
- pthread_mutex_lock(&queue->lock);
- queue->wait = timeout > 0 ? mp_add_timeout(mp_time_us(), timeout) : 0;
+ mp_mutex_lock(&queue->lock);
+ queue->wait = timeout > 0 ? mp_time_ns_add(mp_time_ns(), timeout) : 0;
assert(!queue->in_process); // recursion not allowed
queue->in_process = true;
- queue->in_process_thread = pthread_self();
+ queue->in_process_thread_id = mp_thread_current_id();
// Wake up thread which called mp_dispatch_lock().
if (queue->lock_requests)
- pthread_cond_broadcast(&queue->cond);
+ mp_cond_broadcast(&queue->cond);
while (1) {
if (queue->lock_requests) {
// Block due to something having called mp_dispatch_lock().
- pthread_cond_wait(&queue->cond, &queue->lock);
+ mp_cond_wait(&queue->cond, &queue->lock);
} else if (queue->head) {
struct mp_dispatch_item *item = queue->head;
queue->head = item->next;
@@ -295,23 +295,22 @@ void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
// from mp_dispatch_lock(), which is done by locked=true.
assert(!queue->locked);
queue->locked = true;
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
item->fn(item->fn_data);
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
assert(queue->locked);
queue->locked = false;
// Wakeup mp_dispatch_run(), also mp_dispatch_lock().
- pthread_cond_broadcast(&queue->cond);
+ mp_cond_broadcast(&queue->cond);
if (item->asynchronous) {
talloc_free(item);
} else {
item->completed = true;
}
} else if (queue->wait > 0 && !queue->interrupted) {
- struct timespec ts = mp_time_us_to_timespec(queue->wait);
- if (pthread_cond_timedwait(&queue->cond, &queue->lock, &ts))
+ if (mp_cond_timedwait_until(&queue->cond, &queue->lock, queue->wait))
queue->wait = 0;
} else {
break;
@@ -320,7 +319,7 @@ void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
assert(!queue->locked);
queue->in_process = false;
queue->interrupted = false;
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
}
// If the queue is inside of mp_dispatch_queue_process(), make it return as
@@ -331,10 +330,10 @@ void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
// wakeup the main thread from another thread in a race free way).
void mp_dispatch_interrupt(struct mp_dispatch_queue *queue)
{
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
queue->interrupted = true;
- pthread_cond_broadcast(&queue->cond);
- pthread_mutex_unlock(&queue->lock);
+ mp_cond_broadcast(&queue->cond);
+ mp_mutex_unlock(&queue->lock);
}
// If a mp_dispatch_queue_process() call is in progress, then adjust the maximum
@@ -347,12 +346,12 @@ void mp_dispatch_interrupt(struct mp_dispatch_queue *queue)
// to wait in external APIs.
void mp_dispatch_adjust_timeout(struct mp_dispatch_queue *queue, int64_t until)
{
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
if (queue->in_process && queue->wait > until) {
queue->wait = until;
- pthread_cond_broadcast(&queue->cond);
+ mp_cond_broadcast(&queue->cond);
}
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
}
// Grant exclusive access to the target thread's state. While this is active,
@@ -364,13 +363,13 @@ void mp_dispatch_adjust_timeout(struct mp_dispatch_queue *queue, int64_t until)
// already holding the dispatch lock.
void mp_dispatch_lock(struct mp_dispatch_queue *queue)
{
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
// Must not be called recursively from dispatched callbacks.
if (queue->in_process)
- assert(!pthread_equal(queue->in_process_thread, pthread_self()));
+ assert(!mp_thread_id_equal(queue->in_process_thread_id, mp_thread_current_id()));
// Must not be called recursively at all.
if (queue->locked_explicit)
- assert(!pthread_equal(queue->locked_explicit_thread, pthread_self()));
+ assert(!mp_thread_id_equal(queue->locked_explicit_thread_id, mp_thread_current_id()));
queue->lock_requests += 1;
// And now wait until the target thread gets "trapped" within the
// mp_dispatch_queue_process() call, which will mean we get exclusive
@@ -378,41 +377,41 @@ void mp_dispatch_lock(struct mp_dispatch_queue *queue)
if (queue->onlock_fn)
queue->onlock_fn(queue->onlock_ctx);
while (!queue->in_process) {
- pthread_mutex_unlock(&queue->lock);
+ mp_mutex_unlock(&queue->lock);
if (queue->wakeup_fn)
queue->wakeup_fn(queue->wakeup_ctx);
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
if (queue->in_process)
break;
- pthread_cond_wait(&queue->cond, &queue->lock);
+ mp_cond_wait(&queue->cond, &queue->lock);
}
// Wait until we can get the lock.
while (!queue->in_process || queue->locked)
- pthread_cond_wait(&queue->cond, &queue->lock);
+ mp_cond_wait(&queue->cond, &queue->lock);
// "Lock".
assert(queue->lock_requests);
assert(!queue->locked);
assert(!queue->locked_explicit);
queue->locked = true;
queue->locked_explicit = true;
- queue->locked_explicit_thread = pthread_self();
- pthread_mutex_unlock(&queue->lock);
+ queue->locked_explicit_thread_id = mp_thread_current_id();
+ mp_mutex_unlock(&queue->lock);
}
// Undo mp_dispatch_lock().
void mp_dispatch_unlock(struct mp_dispatch_queue *queue)
{
- pthread_mutex_lock(&queue->lock);
+ mp_mutex_lock(&queue->lock);
assert(queue->locked);
// Must be called after a mp_dispatch_lock(), from the same thread.
assert(queue->locked_explicit);
- assert(pthread_equal(queue->locked_explicit_thread, pthread_self()));
+ assert(mp_thread_id_equal(queue->locked_explicit_thread_id, mp_thread_current_id()));
// "Unlock".
queue->locked = false;
queue->locked_explicit = false;
queue->lock_requests -= 1;
// Wakeup mp_dispatch_queue_process(), and maybe other mp_dispatch_lock()s.
// (Would be nice to wake up only 1 other locker if lock_requests>0.)
- pthread_cond_broadcast(&queue->cond);
- pthread_mutex_unlock(&queue->lock);
+ mp_cond_broadcast(&queue->cond);
+ mp_mutex_unlock(&queue->lock);
}
diff --git a/misc/io_utils.c b/misc/io_utils.c
new file mode 100644
index 0000000000..c973cee0e4
--- /dev/null
+++ b/misc/io_utils.c
@@ -0,0 +1,87 @@
+/*
+ * I/O utility functions
+ *
+ * This file is part of mpv.
+ *
+ * mpv 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.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "mpv_talloc.h"
+#include "config.h"
+#include "misc/random.h"
+#include "misc/io_utils.h"
+#include "osdep/io.h"
+
+int mp_mkostemps(char *template, int suffixlen, int flags)
+{
+ size_t len = strlen(template);
+ char *t = len >= 6 + suffixlen ? &template[len - (6 + suffixlen)] : NULL;
+ if (!t || strncmp(t, "XXXXXX", 6) != 0) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (size_t fuckshit = 0; fuckshit < UINT32_MAX; fuckshit++) {
+ // Using a random value may make it require fewer iterations (even if
+ // not truly random; just a counter would be sufficient).
+ size_t fuckmess = mp_rand_next();
+ char crap[7] = "";
+ snprintf(crap, sizeof(crap), "%06zx", fuckmess);
+ memcpy(t, crap, 6);
+
+ int res = open(template, O_RDWR | O_CREAT | O_EXCL | flags, 0600);
+ if (res >= 0 || errno != EEXIST)
+ return res;
+ }
+
+ errno = EEXIST;
+ return -1;
+}
+
+bool mp_save_to_file(const char *filepath, const void *data, size_t size)
+{
+ assert(filepath && data && size);
+
+ bool result = false;
+ char *tmp = talloc_asprintf(NULL, "%sXXXXXX", filepath);
+ int fd = mkstemp(tmp);
+ if (fd < 0)
+ goto done;
+ FILE *cache = fdopen(fd, "wb");
+ if (!cache) {
+ close(fd);
+ unlink(tmp);
+ goto done;
+ }
+ size_t written = fwrite(data, size, 1, cache);
+ int ret = fclose(cache);
+ if (written > 0 && !ret) {
+ ret = rename(tmp, filepath);
+ result = !ret;
+ } else {
+ unlink(tmp);
+ }
+
+done:
+ talloc_free(tmp);
+ return result;
+}
diff --git a/misc/io_utils.h b/misc/io_utils.h
new file mode 100644
index 0000000000..012f2425f6
--- /dev/null
+++ b/misc/io_utils.h
@@ -0,0 +1,25 @@
+/*
+ * I/O utility functions
+ *
+ * This file is part of mpv.
+ *
+ * mpv 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.
+ *
+ * mpv is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <stddef.h>
+
+int mp_mkostemps(char *template, int suffixlen, int flags);
+bool mp_save_to_file(const char *filepath, const void *data, size_t size);
diff --git a/misc/jni.c b/misc/jni.c
index 3f76f379cb..02440722ca 100644
--- a/misc/jni.c
+++ b/misc/jni.c
@@ -20,17 +20,16 @@
*/
#include <libavcodec/jni.h>
-#include <libavutil/mem.h>
-#include <libavutil/bprint.h>
-#include <pthread.h>
#include <stdlib.h>
#include "jni.h"
+#include "mpv_talloc.h"
+#include "osdep/threads.h"
static JavaVM *java_vm;
static pthread_key_t current_env;
-static pthread_once_t once = PTHREAD_ONCE_INIT;
-static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static mp_once once = MP_STATIC_ONCE_INITIALIZER;
+static mp_static_mutex lock = MP_STATIC_MUTEX_INITIALIZER;
static void jni_detach_env(void *data)
{
@@ -46,26 +45,23 @@ static void jni_create_pthread_key(void)
JNIEnv *mp_jni_get_env(struct mp_log *log)
{
- int ret = 0;
JNIEnv *env = NULL;
- pthread_mutex_lock(&lock);
- if (java_vm == NULL) {
+ mp_mutex_lock(&lock);
+ if (!java_vm)
java_vm = av_jni_get_java_vm(NULL);
- }
if (!java_vm) {
mp_err(log, "No Java virtual machine has been registered\n");
goto done;
}
- pthread_once(&once, jni_create_pthread_key);
+ mp_exec_once(&once, jni_create_pthread_key);
- if ((env = pthread_getspecific(current_env)) != NULL) {
+ if ((env = pthread_getspecific(current_env)) != NULL)
goto done;
- }
- ret = (*java_vm)->GetEnv(java_vm, (void **)&env, JNI_VERSION_1_6);
+ int ret = (*java_vm)->GetEnv(java_vm, (void **)&env, JNI_VERSION_1_6);
switch(ret) {
case JNI_EDETACHED:
if ((*java_vm)->AttachCurrentThread(java_vm, &env, NULL) != 0) {
@@ -86,45 +82,33 @@ JNIEnv *mp_jni_get_env(struct mp_log *log)
}
done:
- pthread_mutex_unlock(&lock);
+ mp_mutex_unlock(&lock);
return env;
}
char *mp_jni_jstring_to_utf_chars(JNIEnv *env, jstring string, struct mp_log *log)
{
- char *ret = NULL;
- const char *utf_chars = NULL;
-
- jboolean copy = 0;
-
- if (!string) {
+ if (!string)
return NULL;
- }
- utf_chars = (*env)->GetStringUTFChars(env, string, &copy);
+ const char *utf_chars = (*env)->GetStringUTFChars(env, string, NULL);
if ((*env)->ExceptionCheck(env)) {
(*env)->ExceptionClear(env);
- mp_err(log, "String.getStringUTFChars() threw an exception\n");
+ mp_err(log, "getStringUTFChars() threw an exception\n");
return NULL;
}
- ret = av_strdup(utf_chars);
+ char *ret = talloc_strdup(NULL, utf_chars);
(*env)->ReleaseStringUTFChars(env, string, utf_chars);
- if ((*env)->ExceptionCheck(env)) {
- (*env)->ExceptionClear(env);
- mp_err(log, "String.releaseStringUTFChars() threw an exception\n");
- return NULL;
- }
return ret;
}
-jstring mp_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, struct mp_log *log)
+jstring mp_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars,
+ struct mp_log *log)
{
- jstring ret;
-
- ret = (*env)->NewStringUTF(env, utf_chars);
+ jstring ret = (*env)->NewStringUTF(env, utf_chars);
if ((*env)->ExceptionCheck(env)) {
(*env)->ExceptionClear(env);
mp_err(log, "NewStringUTF() threw an exception\n");
@@ -134,24 +118,19 @@ jstring mp_jni_utf_chars_to_jstring(JNIEnv *env, const char *utf_chars, struct m
return ret;
}
-int mp_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error, struct mp_log *log)
+int mp_jni_exception_get_summary(JNIEnv *env, jthrowable exception,
+ char **error, struct mp_log *log)
{
int ret = 0;
- AVBPrint bp;
-
char *name = NULL;
char *message = NULL;
jclass class_class = NULL;
- jmethodID get_name_id = NULL;
-
jclass exception_class = NULL;
- jmethodID get_message_id = NULL;
-
jstring string = NULL;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ *error = NULL;
exception_class = (*env)->GetObjectClass(env, exception);
if ((*env)->ExceptionCheck(env)) {
@@ -169,7 +148,7 @@ int mp_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error
goto done;
}
- get_name_id = (*env)->GetMethodID(env, class_class, "getName", "()Ljava/lang/String;");
+ jmethodID get_name_id = (*env)->GetMethodID(env, class_class, "getName", "()Ljava/lang/String;");
if ((*env)->ExceptionCheck(env)) {
(*env)->ExceptionClear(env);
mp_err(log, "Could not find method Class.getName()\n");
@@ -187,14 +166,13 @@ int mp_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error
if (string) {
name = mp_jni_jstring_to_utf_chars(env, string, log);
- (*env)->DeleteLocalRef(env, string);
- string = NULL;
+ MP_JNI_LOCAL_FREEP(&string);
}
- get_message_id = (*env)->GetMethodID(env, exception_class, "getMessage", "()Ljava/lang/String;");
+ jmethodID get_message_id = (*env)->GetMethodID(env, exception_class, "getMessage", "()Ljava/lang/String;");
if ((*env)->ExceptionCheck(env)) {
(*env)->ExceptionClear(env);
- mp_err(log, "Could not find method java/lang/Throwable.getMessage()\n");
+ mp_err(log, "Could not find method Throwable.getMessage()\n");
ret = -1;
goto done;
}
@@ -209,164 +187,145 @@ int mp_jni_exception_get_summary(JNIEnv *env, jthrowable exception, char **error
if (string) {
message = mp_jni_jstring_to_utf_chars(env, string, log);
- (*env)->DeleteLocalRef(env, string);
- string = NULL;
+ MP_JNI_LOCAL_FREEP(&string);
}
if (name && message) {
- av_bprintf(&bp, "%s: %s", name, message);
+ *error = talloc_asprintf(NULL, "%s: %s", name, message);
} else if (name && !message) {
- av_bprintf(&bp, "%s occurred", name);
+ *error = talloc_asprintf(NULL, "%s occurred", name);
} else if (!name && message) {
- av_bprintf(&bp, "Exception: %s", message);
+ *error = talloc_asprintf(NULL, "Exception: %s", message);
} else {
mp_warn(log, "Could not retrieve exception name and message\n");
- av_bprintf(&bp, "Exception occurred");
+ *error = talloc_strdup(NULL, "Exception occurred");
}
- ret = av_bprint_finalize(&bp, error);
done:
- av_free(name);
- av_free(message);
-
- if (class_class) {
- (*env)->DeleteLocalRef(env, class_class);
- }
-
- if (exception_class) {
- (*env)->DeleteLocalRef(env, exception_class);
- }
+ talloc_free(name);
+ talloc_free(message);
- if (string) {
- (*env)->DeleteLocalRef(env, string);
- }
+ MP_JNI_LOCAL_FREEP(&class_class);
+ MP_JNI_LOCAL_FREEP(&exception_class);
+ MP_JNI_LOCAL_FREEP(&string);
return ret;
}
int mp_jni_exception_check(JNIEnv *env, int logging, struct mp_log *log)
{
- int ret;
-
- jthrowable exception;
-
- char *message = NULL;
-
- if (!(*(env))->ExceptionCheck((env))) {
+ if (!(*env)->ExceptionCheck(env))
return 0;
- }
if (!logging) {
- (*(env))->ExceptionClear((env));
+ (*env)->ExceptionClear(env);
return -1;
}
- exception = (*env)->ExceptionOccurred(env);
- (*(env))->ExceptionClear((env));
+ jthrowable exception = (*env)->ExceptionOccurred(env);
+ (*env)->ExceptionClear(env);
- if ((ret = mp_jni_exception_get_summary(env, exception, &message, log)) < 0) {
- (*env)->DeleteLocalRef(env, exception);
+ char *message = NULL;
+ int ret = mp_jni_exception_get_summary(env, exception, &message, log);
+ MP_JNI_LOCAL_FREEP(&exception);
+ if (ret < 0)
return ret;
- }
-
- (*env)->DeleteLocalRef(env, exception);
mp_err(log, "%s\n", message);
- av_free(message);
-
+ talloc_free(message);
return -1;
}
-int mp_jni_init_jfields(JNIEnv *env, void *jfields, const struct MPJniField *jfields_mapping, int global, struct mp_log *log)
+#define CHECK_EXC_MANDATORY() do { \
+ if ((ret = mp_jni_exception_check(env, mandatory, log)) < 0 && \
+ mandatory) { \
+ goto done; \
+ } \
+ } while (0)
+
+int mp_jni_init_jfields(JNIEnv *env, void *jfields,
+ const struct MPJniField *jfields_mapping,
+ int global, struct mp_log *log)
{
- int i, ret = 0;
+ int ret = 0;
jclass last_clazz = NULL;
- for (i = 0; jfields_mapping[i].name; i++) {
- int mandatory = jfields_mapping[i].mandatory;
+ for (int i = 0; jfields_mapping[i].name; i++) {
+ bool mandatory = !!jfields_mapping[i].mandatory;
enum MPJniFieldType type = jfields_mapping[i].type;
- if (type == MP_JNI_CLASS) {
- jclass clazz;
+ void *jfield = (uint8_t*)jfields + jfields_mapping[i].offset;
+ if (type == MP_JNI_CLASS) {
last_clazz = NULL;
- clazz = (*env)->FindClass(env, jfields_mapping[i].name);
- if ((ret = mp_jni_exception_check(env, mandatory, log)) < 0 && mandatory) {
- goto done;
- }
+ jclass clazz = (*env)->FindClass(env, jfields_mapping[i].name);
+ CHECK_EXC_MANDATORY();
- last_clazz = *(jclass*)((uint8_t*)jfields + jfields_mapping[i].offset) =
+ last_clazz = *(jclass*)jfield =
global ? (*env)->NewGlobalRef(env, clazz) : clazz;
- if (global) {
- (*env)->DeleteLocalRef(env, clazz);
- }
-
- } else {
+ if (global)
+ MP_JNI_LOCAL_FREEP(&clazz);
- if (!last_clazz) {
- ret = -1;
- break;
- }
+ continue;
+ }
- switch(type) {
- case MP_JNI_FIELD: {
- jfieldID field_id = (*env)->GetFieldID(env, last_clazz, jfields_m