[vlc-devel] [PATCH] Add new methods to libvlc to record the current media to either an application-specified file or a file automatically created by vlc:
Rémi Denis-Courmont
remi at remlab.net
Mon Aug 6 10:02:05 CEST 2012
Hello,
Inline...
On Sat, 4 Aug 2012 16:53:44 +0100, Mark Lee
<mark.lee at capricasoftware.co.uk> wrote:
> libvlc_media_player_is_recordable
> libvlc_media_player_is_recording
> libvlc_media_player_record_start
> libvlc_media_player_record_stop
>
> Add new events to support these methods:
>
> libvlc_MediaPlayerRecordableChanged
> libvlc_MediaPlayerRecordingFinished
> ---
> include/vlc/libvlc_events.h | 10 ++++
> include/vlc/libvlc_media_player.h | 115
> +++++++++++++++++++++++++++++++++++++
> lib/event.c | 2 +
> lib/libvlc.sym | 4 ++
> lib/media_player.c | 115
> +++++++++++++++++++++++++++++++++++++
> modules/stream_out/record.c | 12 ++++
> src/input/var.c | 3 +
> src/libvlc.c | 1 +
> 8 files changed, 262 insertions(+)
>
> diff --git a/include/vlc/libvlc_events.h b/include/vlc/libvlc_events.h
> index 2cfedbf..25a16ea 100644
> --- a/include/vlc/libvlc_events.h
> +++ b/include/vlc/libvlc_events.h
> @@ -72,6 +72,8 @@ enum libvlc_event_e {
> libvlc_MediaPlayerSnapshotTaken,
> libvlc_MediaPlayerLengthChanged,
> libvlc_MediaPlayerVout,
> + libvlc_MediaPlayerRecordableChanged,
> + libvlc_MediaPlayerRecordingFinished,
>
> libvlc_MediaListItemAdded=0x200,
> libvlc_MediaListWillAddItem,
> @@ -165,6 +167,14 @@ typedef struct libvlc_event_t
> } media_player_pausable_changed;
> struct
> {
> + int new_recordable;
> + } media_player_recordable_changed;
Hmm, should this be int or bool?
> + struct
> + {
> + char *psz_filename;
> + } media_player_recording_finished;
Maybe const char * ? Or is the callee expected to free that?
> + struct
> + {
> int new_count;
> } media_player_vout;
>
> # ifdef __cplusplus
(...)
> diff --git a/lib/media_player.c b/lib/media_player.c
> index f30f184..f71bfa3 100644
> --- a/lib/media_player.c
> +++ b/lib/media_player.c
> @@ -64,6 +64,10 @@ input_pausable_changed( vlc_object_t * p_this, char
> const * psz_cmd,
> vlc_value_t oldval, vlc_value_t newval,
> void * p_userdata );
> static int
> +input_recordable_changed( vlc_object_t *p_this, char const *psz_cmd,
> + vlc_value_t oldval, vlc_value_t newval,
> + void *p_userdata );
> +static int
> input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
> vlc_value_t oldval, vlc_value_t newval,
> void * p_userdata );
> @@ -72,6 +76,10 @@ static int
> snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,
> vlc_value_t oldval, vlc_value_t newval, void
*p_data
> );
>
> +static int
> +file_recording_finished( vlc_object_t *p_this, char const *psz_cmd,
> + vlc_value_t oldval, vlc_value_t newval, void
> *p_data );
> +
> static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );
>
> /*
> @@ -132,6 +140,8 @@ static void release_input_thread(
> libvlc_media_player_t *p_mi, bool b_input_abor
> input_seekable_changed, p_mi );
> var_DelCallback( p_input_thread, "can-pause",
> input_pausable_changed, p_mi );
> + var_DelCallback( p_input_thread, "can-record",
> + input_recordable_changed, p_mi );
> var_DelCallback( p_input_thread, "intf-event",
> input_event_changed, p_mi );
>
> @@ -227,6 +237,25 @@ input_pausable_changed( vlc_object_t * p_this, char
> const * psz_cmd,
> }
>
> static int
> +input_recordable_changed( vlc_object_t *p_this, char const *psz_cmd,
> + vlc_value_t oldval, vlc_value_t newval,
> + void *p_userdata )
> +{
> + VLC_UNUSED(p_this);
> + VLC_UNUSED(psz_cmd);
> + VLC_UNUSED(oldval);
> +
> + libvlc_media_player_t *p_mi = p_userdata;
> + libvlc_event_t event;
> +
> + event.type = libvlc_MediaPlayerRecordableChanged;
> + event.u.media_player_recordable_changed.new_recordable =
> newval.b_bool;
> +
> + libvlc_event_send( p_mi->p_event_manager, &event );
> + return VLC_SUCCESS;
> +}
> +
> +static int
> input_event_changed( vlc_object_t * p_this, char const * psz_cmd,
> vlc_value_t oldval, vlc_value_t newval,
> void * p_userdata )
> @@ -357,6 +386,23 @@ static int snapshot_was_taken(vlc_object_t *p_this,
> char const *psz_cmd,
> return VLC_SUCCESS;
> }
>
> +static int file_recording_finished(vlc_object_t *p_this, char const
> *psz_cmd,
> + vlc_value_t oldval, vlc_value_t
> newval, void *p_data )
> +{
> + VLC_UNUSED(p_this);
> + VLC_UNUSED(psz_cmd);
> + VLC_UNUSED(oldval);
> +
> + libvlc_media_player_t *p_mi = p_data;
> + libvlc_event_t event;
> +
> + event.type = libvlc_MediaPlayerRecordingFinished;
> + event.u.media_player_recording_finished.psz_filename =
> newval.psz_string;
> +
> + libvlc_event_send(p_mi->p_event_manager, &event);
> + return VLC_SUCCESS;
> +}
> +
> static input_thread_t *find_input (vlc_object_t *obj)
> {
> libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
> @@ -514,6 +560,9 @@ libvlc_media_player_new( libvlc_instance_t *instance
)
> register_event(mp, TitleChanged);
> register_event(mp, PausableChanged);
>
> + register_event(mp, RecordableChanged);
> + register_event(mp, RecordingFinished);
> +
> register_event(mp, Vout);
>
> /* Snapshot initialization */
> @@ -530,6 +579,8 @@ libvlc_media_player_new( libvlc_instance_t *instance
)
> */
> var_AddCallback(mp->p_libvlc, "snapshot-file", snapshot_was_taken,
> mp);
>
> + var_AddCallback(mp->p_libvlc, "recording-finished",
> file_recording_finished, mp);
This reproduces the bug in snapshot. Using the libvlc instance is
inappropriate. Things will break very badly if there are more than one
media player instance at a time.
That implementation shortcut in the record module was tolerable for the
VLC playlist, as the playlist is unique and exclusive. This is not true of
libvlc media players.
> +
> libvlc_retain(instance);
> return mp;
> }
> @@ -565,6 +616,9 @@ static void libvlc_media_player_destroy(
> libvlc_media_player_t *p_mi )
> var_DelCallback( p_mi->p_libvlc,
> "snapshot-file", snapshot_was_taken, p_mi );
>
> + var_DelCallback( p_mi->p_libvlc,
> + "recording-finished", file_recording_finished,
p_mi
> );
> +
> /* No need for lock_input() because no other threads knows us
anymore
> */
> if( p_mi->input.p_thread )
> release_input_thread(p_mi, true);
> @@ -731,12 +785,14 @@ int libvlc_media_player_play(
libvlc_media_player_t
> *p_mi )
>
> var_AddCallback( p_input_thread, "can-seek",
input_seekable_changed,
> p_mi );
> var_AddCallback( p_input_thread, "can-pause",
input_pausable_changed,
> p_mi );
> + var_AddCallback( p_input_thread, "can-record",
> input_recordable_changed, p_mi );
> var_AddCallback( p_input_thread, "intf-event", input_event_changed,
> p_mi );
>
> if( input_Start( p_input_thread ) )
> {
> unlock_input(p_mi);
> var_DelCallback( p_input_thread, "intf-event",
> input_event_changed, p_mi );
> + var_DelCallback( p_input_thread, "can-record",
> input_recordable_changed, p_mi );
> var_DelCallback( p_input_thread, "can-pause",
> input_pausable_changed, p_mi );
> var_DelCallback( p_input_thread, "can-seek",
> input_seekable_changed, p_mi );
> vlc_object_release( p_input_thread );
> @@ -1408,3 +1464,62 @@ void libvlc_media_player_next_frame(
> libvlc_media_player_t *p_mi )
> vlc_object_release( p_input_thread );
> }
> }
> +
> +bool libvlc_media_player_is_recordable( libvlc_media_player_t *p_mi )
> +{
> + input_thread_t *p_input_thread;
> + bool b_can_record;
> +
> + p_input_thread = libvlc_get_input_thread( p_mi );
> + if( !p_input_thread )
> + return 0;
> +
> + b_can_record = var_GetBool( p_input_thread, "can-record" );
> +
> + vlc_object_release( p_input_thread );
> + return b_can_record;
> +}
> +
> +bool libvlc_media_player_is_recording( libvlc_media_player_t *p_mi )
> +{
> + input_thread_t *p_input_thread;
> + bool b_record;
> +
> + p_input_thread = libvlc_get_input_thread( p_mi );
> + if( !p_input_thread )
> + return 0;
> +
> + b_record = var_GetBool( p_input_thread, "record" );
> +
> + vlc_object_release( p_input_thread );
> + return b_record;
> +}
> +
> +int libvlc_media_player_record_start( libvlc_media_player_t *p_mi,
const
> char* psz_filename )
> +{
> + input_thread_t *p_input_thread;
> +
> + p_input_thread = libvlc_get_input_thread( p_mi );
> + if( !p_input_thread )
> + return -1;
> +
> + var_SetString( p_input_thread, "input-record-path", psz_filename );
> + var_SetBool( p_input_thread, "record", true );
> +
> + vlc_object_release( p_input_thread );
> + return 0;
> +}
> +
> +int libvlc_media_player_record_stop( libvlc_media_player_t *p_mi )
> +{
> + input_thread_t *p_input_thread;
> +
> + p_input_thread = libvlc_get_input_thread( p_mi );
> + if( !p_input_thread )
> + return -1;
> +
> + var_SetBool( p_input_thread, "record", false );
> +
> + vlc_object_release( p_input_thread );
> + return 0;
> +}
> diff --git a/modules/stream_out/record.c b/modules/stream_out/record.c
> index de6d32e..41e2928 100644
> --- a/modules/stream_out/record.c
> +++ b/modules/stream_out/record.c
> @@ -110,6 +110,8 @@ struct sout_stream_sys_t
> int i_id;
> sout_stream_id_t **id;
> mtime_t i_dts_start;
> +
> + char *psz_record_file;
> };
>
> static void OutputStart( sout_stream_t *p_stream );
> @@ -158,6 +160,8 @@ static int Open( vlc_object_t *p_this )
> p_sys->i_dts_start = 0;
> TAB_INIT( p_sys->i_id, p_sys->id );
>
> + p_sys->psz_record_file = NULL;
> +
> return VLC_SUCCESS;
> }
>
> @@ -172,6 +176,11 @@ static void Close( vlc_object_t * p_this )
> if( p_sys->p_out )
> sout_StreamChainDelete( p_sys->p_out, p_sys->p_out );
>
> + if( p_sys->psz_record_file ) {
> + var_SetString( p_stream->p_libvlc, "recording-finished",
> p_sys->psz_record_file );
> + free( p_sys->psz_record_file );
> + }
> +
> TAB_CLEAN( p_sys->i_id, p_sys->id );
> free( p_sys->psz_prefix );
> free( p_sys );
> @@ -352,7 +361,10 @@ static int OutputNew( sout_stream_t *p_stream,
> }
>
> if( psz_file && psz_extension )
> + {
> + p_sys->psz_record_file = strdup( psz_file );
> var_SetString( p_stream->p_libvlc, "record-file", psz_file );
> + }
>
> free( psz_file );
> free( psz_output );
> diff --git a/src/input/var.c b/src/input/var.c
> index 9613fe2..04f33b9 100644
> --- a/src/input/var.c
> +++ b/src/input/var.c
> @@ -210,6 +210,9 @@ void input_ControlVarInit ( input_thread_t *p_input
)
> text.psz_string = _("Subtitles Track");
> var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );
>
> + /* ES Out */
> + var_Create( p_input, "input-record-path", VLC_VAR_STRING |
> VLC_VAR_DOINHERIT );
> +
> /* Special read only objects variables for intf */
> var_Create( p_input, "bookmarks", VLC_VAR_STRING |
VLC_VAR_DOINHERIT
> );
>
> diff --git a/src/libvlc.c b/src/libvlc.c
> index 0aac070..f318143 100644
> --- a/src/libvlc.c
> +++ b/src/libvlc.c
> @@ -476,6 +476,7 @@ int libvlc_InternalInit( libvlc_int_t *p_libvlc, int
> i_argc,
> /* variables for signalling creation of new files */
> var_Create( p_libvlc, "snapshot-file", VLC_VAR_STRING );
> var_Create( p_libvlc, "record-file", VLC_VAR_STRING );
> + var_Create( p_libvlc, "recording-finished", VLC_VAR_STRING );
>
> /* some default internal settings */
> var_Create( p_libvlc, "window", VLC_VAR_STRING );
--
Rémi Denis-Courmont
Sent from my collocated server
More information about the vlc-devel
mailing list