[Android] LibVLC: MediaPlayer: add record() method
Thomas Guillem
git at videolan.org
Tue Apr 2 17:00:00 CEST 2019
vlc-android | branch: master | Thomas Guillem <thomas at gllm.fr> | Thu Mar 28 11:50:55 2019 +0100| [17d0f8d697147ec72dd61ac0d9758dd4e982f0ca] | committer: Geoffrey Métais
LibVLC: MediaPlayer: add record() method
> https://code.videolan.org/videolan/vlc-android/commit/17d0f8d697147ec72dd61ac0d9758dd4e982f0ca
---
libvlc/jni/libvlcjni-mediaplayer.c | 36 +++++++++++
...03-libvlc-events-Add-callbacks-for-record.patch | 74 ++++++++++++++++++++++
...tput-file-Add-error-dialog-for-write-open.patch | 40 ++++++++++++
...005-libvlc-media_player-Add-record-method.patch | 69 ++++++++++++++++++++
libvlc/src/org/videolan/libvlc/MediaPlayer.java | 12 ++++
5 files changed, 231 insertions(+)
diff --git a/libvlc/jni/libvlcjni-mediaplayer.c b/libvlc/jni/libvlcjni-mediaplayer.c
index 59a48a080..4f7438c76 100644
--- a/libvlc/jni/libvlcjni-mediaplayer.c
+++ b/libvlc/jni/libvlcjni-mediaplayer.c
@@ -22,6 +22,7 @@
#include <pthread.h>
#include <stdlib.h>
+#include <dlfcn.h>
#include "libvlcjni-vlcobject.h"
@@ -1072,6 +1073,41 @@ Java_org_videolan_libvlc_MediaPlayer_nativeSetEqualizer(JNIEnv *env,
return libvlc_media_player_set_equalizer(p_obj->u.p_mp, p_eq) == 0 ? true: false;
}
+jboolean
+Java_org_videolan_libvlc_MediaPlayer_nativeRecord(JNIEnv *env, jobject thiz,
+ jstring jdirectory)
+{
+ vlcjni_object *p_obj = VLCJniObject_getInstance(env, thiz);
+ const char *psz_directory;
+
+ if (!p_obj)
+ return false;
+
+ int (*record_func)(libvlc_media_player_t *, const char *) =
+ dlsym(RTLD_DEFAULT, "libvlc_media_player_record");
+
+ if (!record_func)
+ return false;
+
+ if (jdirectory)
+ {
+ psz_directory = (*env)->GetStringUTFChars(env, jdirectory, 0);
+ if (!psz_directory)
+ {
+ throw_Exception(env, VLCJNI_EX_ILLEGAL_ARGUMENT, "directory invalid");
+ return false;
+ }
+ }
+ else
+ psz_directory = NULL;
+
+ jboolean ret = record_func(p_obj->u.p_mp, psz_directory) == 0;
+
+ (*env)->ReleaseStringUTFChars(env, jdirectory, psz_directory);
+
+ return ret;
+}
+
jint
Java_org_videolan_libvlc_MediaPlayer_00024Equalizer_nativeGetPresetCount(JNIEnv *env,
jobject thiz)
diff --git a/libvlc/patches/0003-libvlc-events-Add-callbacks-for-record.patch b/libvlc/patches/0003-libvlc-events-Add-callbacks-for-record.patch
new file mode 100644
index 000000000..c7eeb0a71
--- /dev/null
+++ b/libvlc/patches/0003-libvlc-events-Add-callbacks-for-record.patch
@@ -0,0 +1,74 @@
+From c4b67a2d0823729d0057155f828a7624d36059c9 Mon Sep 17 00:00:00 2001
+From: Soomin Lee <bubu at mikan.io>
+Date: Thu, 27 Sep 2018 18:40:39 +0200
+Subject: [PATCH 3/4] libvlc: events: Add callbacks for record
+
+---
+ include/vlc/libvlc_events.h | 9 +++++++++
+ lib/media_player.c | 16 ++++++++++++++++
+ 2 files changed, 25 insertions(+)
+
+diff --git a/include/vlc/libvlc_events.h b/include/vlc/libvlc_events.h
+index f8b0e9b5b2..bbc6bc0eec 100644
+--- a/include/vlc/libvlc_events.h
++++ b/include/vlc/libvlc_events.h
+@@ -32,6 +32,8 @@
+
+ # ifdef __cplusplus
+ extern "C" {
++# else
++# include <stdbool.h>
+ # endif
+
+ typedef struct libvlc_renderer_item_t libvlc_renderer_item_t;
+@@ -86,6 +88,7 @@ enum libvlc_event_e {
+ libvlc_MediaPlayerAudioVolume,
+ libvlc_MediaPlayerAudioDevice,
+ libvlc_MediaPlayerChapterChanged,
++ libvlc_MediaPlayerRecordChanged,
+
+ libvlc_MediaListItemAdded=0x200,
+ libvlc_MediaListWillAddItem,
+@@ -275,6 +278,12 @@ typedef struct libvlc_event_t
+ const char *device;
+ } media_player_audio_device;
+
++ struct
++ {
++ const char *file_path;
++ bool recording;
++ } media_player_record_changed;
++
+ struct
+ {
+ libvlc_renderer_item_t *item;
+diff --git a/lib/media_player.c b/lib/media_player.c
+index 354272b32d..e337cf7197 100644
+--- a/lib/media_player.c
++++ b/lib/media_player.c
+@@ -446,6 +446,22 @@ input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
+ }
+ }
+ }
++ else if ( newval.i_int == INPUT_EVENT_RECORD )
++ {
++ bool recording = var_GetBool( p_input, "record" );
++ char *file_path = NULL;
++
++ if ( !recording )
++ file_path = var_GetString( p_mi->obj.libvlc, "record-file" );
++
++ event.type = libvlc_MediaPlayerRecordChanged;
++ event.u.media_player_record_changed.file_path = file_path;
++ event.u.media_player_record_changed.recording = recording;
++
++ libvlc_event_send( &p_mi->event_manager, &event );
++
++ free( file_path );
++ }
+
+ return VLC_SUCCESS;
+ }
+--
+2.20.1
+
diff --git a/libvlc/patches/0004-access_output-file-Add-error-dialog-for-write-open.patch b/libvlc/patches/0004-access_output-file-Add-error-dialog-for-write-open.patch
new file mode 100644
index 000000000..8d5c5b921
--- /dev/null
+++ b/libvlc/patches/0004-access_output-file-Add-error-dialog-for-write-open.patch
@@ -0,0 +1,40 @@
+From 88ddce79a49dc6b88033844d36666848ce1a8365 Mon Sep 17 00:00:00 2001
+From: Soomin Lee <bubu at mikan.io>
+Date: Mon, 1 Oct 2018 15:37:57 +0200
+Subject: [PATCH 4/4] access_output: file: Add error dialog for write/open
+
+---
+ modules/access_output/file.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/modules/access_output/file.c b/modules/access_output/file.c
+index fbefce0be8..45de0fc75e 100644
+--- a/modules/access_output/file.c
++++ b/modules/access_output/file.c
+@@ -88,6 +88,9 @@ static ssize_t Write( sout_access_out_t *p_access, block_t *p_buffer )
+ {
+ if (errno == EINTR)
+ continue;
++ if (errno == ENOSPC)
++ vlc_dialog_display_error(p_access, "record",
++ "An error occurred during recording. Error: %s", vlc_strerror_c(errno));
+ block_ChainRelease (p_buffer);
+ msg_Err( p_access, "cannot write: %s", vlc_strerror_c(errno) );
+ return -1;
+@@ -305,8 +308,13 @@ static int Open( vlc_object_t *p_this )
+ if (fd != -1)
+ break;
+ if (fd == -1)
++ {
+ msg_Err (p_access, "cannot create %s: %s", path,
+ vlc_strerror_c(errno));
++
++ vlc_dialog_display_error(p_access, "record",
++ "An error occurred during recording. Error: %s", vlc_strerror_c(errno));
++ }
+ if (overwrite || errno != EEXIST)
+ break;
+ flags &= ~O_EXCL;
+--
+2.20.1
+
diff --git a/libvlc/patches/0005-libvlc-media_player-Add-record-method.patch b/libvlc/patches/0005-libvlc-media_player-Add-record-method.patch
new file mode 100644
index 000000000..74a85f8b6
--- /dev/null
+++ b/libvlc/patches/0005-libvlc-media_player-Add-record-method.patch
@@ -0,0 +1,69 @@
+From a16ca81ddc53c2275f6946ceb979f28b50bfb069 Mon Sep 17 00:00:00 2001
+From: Soomin Lee <bubu at mikan.io>
+Date: Wed, 31 Oct 2018 10:08:55 +0100
+Subject: [PATCH 2/4] libvlc: media_player: Add record method
+
+---
+ include/vlc/libvlc_media_player.h | 11 +++++++++++
+ lib/media_player.c | 19 +++++++++++++++++++
+ 2 files changed, 30 insertions(+)
+
+diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h
+index c431c235e9..8629fbc1a1 100644
+--- a/include/vlc/libvlc_media_player.h
++++ b/include/vlc/libvlc_media_player.h
+@@ -2079,6 +2079,17 @@ LIBVLC_API int libvlc_media_player_get_role(libvlc_media_player_t *p_mi);
+ */
+ LIBVLC_API int libvlc_media_player_set_role(libvlc_media_player_t *p_mi,
+ unsigned role);
++/**
++ * Start/stop recording
++ *
++ * \version LibVLC 4.0.0 and later.
++ *
++ * \param p_mi media player
++ * \param directory path of the recording directory or NULL to stop recording
++ * \return 0 on success, -1 on error
++ */
++LIBVLC_API int libvlc_media_player_record(libvlc_media_player_t *p_mi,
++ const char *directory);
+
+ /** @} audio */
+
+diff --git a/lib/media_player.c b/lib/media_player.c
+index a9a22fee15..354272b32d 100644
+--- a/lib/media_player.c
++++ b/lib/media_player.c
+@@ -621,6 +621,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
+ var_Create (mp, "rate", VLC_VAR_FLOAT|VLC_VAR_DOINHERIT);
+ var_Create (mp, "sout", VLC_VAR_STRING);
+ var_Create (mp, "demux-filter", VLC_VAR_STRING);
++ var_Create (mp, "input-record-path", VLC_VAR_STRING);
+
+ /* Video */
+ var_Create (mp, "vout", VLC_VAR_STRING|VLC_VAR_DOINHERIT);
+@@ -2078,3 +2079,21 @@ int libvlc_media_player_get_role(libvlc_media_player_t *mp)
+ free(str);
+ return ret;
+ }
++
++int libvlc_media_player_record( libvlc_media_player_t *p_mi,
++ const char *directory )
++{
++ vlc_value_t val = { .psz_string = (char *)directory };
++ const bool enable = directory != NULL;
++ input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
++ if( !p_input_thread )
++ return VLC_EGENERIC;
++
++ if( enable )
++ var_Set( p_mi, "input-record-path", val );
++
++ var_SetBool( p_input_thread, "record", enable);
++
++ vlc_object_release( p_input_thread );
++ return VLC_SUCCESS;
++}
+--
+2.20.1
+
diff --git a/libvlc/src/org/videolan/libvlc/MediaPlayer.java b/libvlc/src/org/videolan/libvlc/MediaPlayer.java
index 8827a8f11..57f28134e 100644
--- a/libvlc/src/org/videolan/libvlc/MediaPlayer.java
+++ b/libvlc/src/org/videolan/libvlc/MediaPlayer.java
@@ -1195,6 +1195,17 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
return nativeAddSlave(type, VLCUtil.encodeVLCUri(uri), select);
}
+ /**
+ * Start/stop recording
+ *
+ * @param directory path of the recording directory or null to stop
+ * recording
+ * @return true on success.
+ */
+ public boolean record(String directory) {
+ return nativeRecord(directory);
+ }
+
/**
* Add a slave (or subtitle) to the current media player.
*
@@ -1381,5 +1392,6 @@ public class MediaPlayer extends VLCObject<MediaPlayer.Event> {
private native long nativeGetSpuDelay();
private native boolean nativeSetSpuDelay(long delay);
private native boolean nativeAddSlave(int type, String location, boolean select);
+ private native boolean nativeRecord(String directory);
private native boolean nativeSetEqualizer(Equalizer equalizer);
}
More information about the Android
mailing list