[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