[Android] libvlc: add std_logger.c

Thomas Guillem git at videolan.org
Tue Apr 21 15:19:19 CEST 2015


vlc-ports/android | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Apr 21 15:17:43 2015 +0200| [8472a726328829e0272a76bd29402993ecd2766c] | committer: Thomas Guillem

libvlc: add std_logger.c

By default, stdout/stderr are deactivated, i.e. they are opened on /dev/null.
std_logger_Open will duplicate stdout and stderr fd on a write end of a pipe. A
thread will be created and will print the read end of the pipe.

Standard output will be printed with "VLC-std" TAG with debug priority.
Standard error will be printed with "VLC-std" TAG with error priority.

It's not activated by default since we don't want to mess up with the
application file descriptors.

> http://git.videolan.org/gitweb.cgi/vlc-ports/android.git/?a=commit;h=8472a726328829e0272a76bd29402993ecd2766c
---

 libvlc/jni/Android.mk   |    1 +
 libvlc/jni/libvlcjni.c  |   12 +++
 libvlc/jni/std_logger.c |  187 +++++++++++++++++++++++++++++++++++++++++++++++
 libvlc/jni/std_logger.h |   34 +++++++++
 4 files changed, 234 insertions(+)

diff --git a/libvlc/jni/Android.mk b/libvlc/jni/Android.mk
index d59be7d..1782a3a 100644
--- a/libvlc/jni/Android.mk
+++ b/libvlc/jni/Android.mk
@@ -9,6 +9,7 @@ LOCAL_SRC_FILES += libvlcjni-equalizer.c
 LOCAL_SRC_FILES += libvlcjni-vlcobject.c
 LOCAL_SRC_FILES += libvlcjni-media.c libvlcjni-medialist.c libvlcjni-mediadiscoverer.c
 LOCAL_SRC_FILES += vout.c native_crash_handler.c thumbnailer.c
+LOCAL_SRC_FILES += std_logger.c
 ifneq ($(APP_PLATFORM),android-21)
 # compat functions not needed after android-21
 LOCAL_SRC_FILES += compat/pthread-condattr.c compat/pthread-rwlocks.c
diff --git a/libvlc/jni/libvlcjni.c b/libvlc/jni/libvlcjni.c
index 3b8fe8e..e79b7f1 100644
--- a/libvlc/jni/libvlcjni.c
+++ b/libvlc/jni/libvlcjni.c
@@ -39,6 +39,7 @@
 #include "vout.h"
 #include "utils.h"
 #include "native_crash_handler.h"
+#include "std_logger.h"
 
 #define VOUT_ANDROID_SURFACE 0
 #define VOUT_OPENGLES2       1
@@ -254,6 +255,10 @@ JNIEnv *jni_get_env(const char *name)
     return env;
 }
 
+#ifndef NDEBUG
+static std_logger *p_std_logger = NULL;
+#endif
+
 jint JNI_OnLoad(JavaVM *vm, void *reserved)
 {
     JNIEnv* env = NULL;
@@ -271,6 +276,9 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved)
     pthread_mutex_init(&vout_android_lock, NULL);
     pthread_cond_init(&vout_android_surf_attached, NULL);
 
+#ifndef NDEBUG
+    p_std_logger = std_logger_Open("VLC-std");
+#endif
 
 #define GET_CLASS(clazz, str, b_globlal) do { \
     (clazz) = (*env)->FindClass(env, (str)); \
@@ -399,6 +407,10 @@ void JNI_OnUnload(JavaVM* vm, void* reserved)
     (*env)->DeleteGlobalRef(env, fields.Media.clazz);
 
     pthread_key_delete(jni_env_key);
+
+#ifndef NDEBUG
+    std_logger_Close(p_std_logger);
+#endif
 }
 
 void Java_org_videolan_libvlc_LibVLC_nativeInit(JNIEnv *env, jobject thiz)
diff --git a/libvlc/jni/std_logger.c b/libvlc/jni/std_logger.c
new file mode 100644
index 0000000..c6bf3b8
--- /dev/null
+++ b/libvlc/jni/std_logger.c
@@ -0,0 +1,187 @@
+/*****************************************************************************
+ * std_logger.c
+ *****************************************************************************
+ * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#include <android/log.h>
+
+#include "std_logger.h"
+
+struct std_logger
+{
+    const char *TAG;
+    int stop_pipe[2];
+    int stdout_pipe[2];
+    int stderr_pipe[2];
+    int old_stdout, old_stderr;
+
+    pthread_t thread;
+};
+
+static ssize_t
+std_logger_Print(std_logger *sys, int fd, int prio)
+{
+    char buf[1024 + 1];
+    ssize_t ret;
+
+    ret = read(fd, buf, 1024);
+    if (ret <= 0)
+        return ret;
+
+    buf[ret] = '\0';
+    __android_log_print(prio, sys->TAG, "%s", buf);
+
+    return ret;
+}
+
+static void *
+std_logger_Thread(void *arg)
+{
+    std_logger *sys = arg;
+
+    while (true)
+    {
+        fd_set rfds;
+        int ret, nfds;
+
+        FD_ZERO(&rfds);
+
+        FD_SET(sys->stop_pipe[0], &rfds);
+        nfds = sys->stop_pipe[0];
+
+        FD_SET(sys->stdout_pipe[0], &rfds);
+        if (sys->stdout_pipe[0] > nfds)
+            nfds = sys->stdout_pipe[0];
+
+        FD_SET(sys->stderr_pipe[0], &rfds);
+        if (sys->stderr_pipe[0] > nfds)
+            nfds = sys->stderr_pipe[0];
+
+        ret = select(nfds + 1, &rfds, NULL, NULL, NULL);
+
+        if (ret == -1)
+            break;
+        else if (ret == 0)
+            continue;
+
+        if (FD_ISSET(sys->stop_pipe[0], &rfds))
+            break;
+
+        if (FD_ISSET(sys->stdout_pipe[0], &rfds)
+         && std_logger_Print(sys, sys->stdout_pipe[0], ANDROID_LOG_DEBUG) <= 0)
+            break;
+
+        if (FD_ISSET(sys->stderr_pipe[0], &rfds)
+         && std_logger_Print(sys, sys->stderr_pipe[0], ANDROID_LOG_ERROR) <= 0)
+            break;
+    }
+    return NULL;
+}
+
+static void
+ClosePipe(int *pipe)
+{
+    if (pipe[0] != -1)
+    {
+        close(pipe[0]);
+        pipe[0] = -1;
+    }
+    if (pipe[1] != -1)
+    {
+        close(pipe[1]);
+        pipe[1] = -1;
+    }
+}
+
+std_logger *
+std_logger_Open(const char *TAG)
+{
+    std_logger *sys = NULL;
+
+    sys = calloc(1, sizeof (std_logger));
+    if (!sys)
+        return NULL;
+
+    sys->TAG = TAG;
+    sys->stop_pipe[0] = sys->stop_pipe[1] =
+    sys->stdout_pipe[0] = sys->stdout_pipe[1] =
+    sys->old_stdout = sys->old_stderr = -1;
+
+    /* save the old stdout/stderr fd to restore it when logged is closed */
+    sys->old_stdout = dup(STDOUT_FILENO);
+    sys->old_stderr = dup(STDERR_FILENO);
+    if (sys->old_stdout == -1 || sys->old_stderr == -1)
+        goto bailout;
+
+    /* duplicate stdout */
+    if (pipe(sys->stdout_pipe) == -1)
+        goto bailout;
+    if (dup2(sys->stdout_pipe[1], STDOUT_FILENO) == -1)
+        goto bailout;
+
+    /* duplicate stderr */
+    if (pipe(sys->stderr_pipe) == -1)
+        goto bailout;
+    if (dup2(sys->stderr_pipe[1], STDERR_FILENO) == -1)
+        goto bailout;
+
+    /* pipe to signal the thread to stop */
+    if (pipe(sys->stop_pipe) == -1)
+        goto bailout;
+
+    if (pthread_create(&sys->thread, NULL, std_logger_Thread, sys))
+    {
+        ClosePipe(sys->stop_pipe);
+        goto bailout;
+    }
+
+    return sys;
+bailout:
+    std_logger_Close(sys);
+    return NULL;
+}
+
+void
+std_logger_Close(std_logger *sys)
+{
+    if (sys->stop_pipe[1] != -1)
+    {
+        write(sys->stop_pipe[1], '\0', 1);
+        close(sys->stop_pipe[1]);
+        sys->stop_pipe[1] = -1;
+        pthread_join(sys->thread, NULL);
+    }
+    ClosePipe(sys->stop_pipe);
+    ClosePipe(sys->stdout_pipe);
+    ClosePipe(sys->stderr_pipe);
+
+    if (sys->old_stdout != -1 && sys->old_stderr != -1) {
+        dup2(sys->old_stdout, STDOUT_FILENO);
+        dup2(sys->old_stderr, STDERR_FILENO);
+        close(sys->old_stdout);
+        close(sys->old_stderr);
+        sys->old_stdout = sys->old_stderr = -1;
+    }
+    free(sys);
+}
diff --git a/libvlc/jni/std_logger.h b/libvlc/jni/std_logger.h
new file mode 100644
index 0000000..ae9f47d
--- /dev/null
+++ b/libvlc/jni/std_logger.h
@@ -0,0 +1,34 @@
+/*****************************************************************************
+ * std_logger.h
+ *****************************************************************************
+ * Copyright © 2015 VLC authors, VideoLAN and VideoLabs
+ *
+ * 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
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+#ifndef STD_LOGGER_H
+#define STD_LOGGER_H
+
+/* By default, stdout/stderr are deactivated, i.e. they are opened on
+ * /dev/null. std_logger_Open will duplicate stdout and stderr fd on a write
+ * end of a pipe. A thread will be created and will print the read end of the
+ * pipe. */
+
+typedef struct std_logger std_logger;
+
+std_logger *std_logger_Open(const char *TAG);
+void        std_logger_Close(std_logger *sys);
+
+#endif // STD_LOGGER_H



More information about the Android mailing list