]> git.sesse.net Git - vlc/blobdiff - lib/media_player.c
lib: allow media player volume to be set before playing media
[vlc] / lib / media_player.c
index cfd9f63b8e52384c74f098ddfa896ebd9a9ea8ff..868aefe627d816ba7e376f85c2cf78f287a22539 100644 (file)
 #include <vlc_demux.h>
 #include <vlc_input.h>
 #include <vlc_vout.h>
+#include <vlc_aout.h>
 #include <vlc_keys.h>
 
 #include "libvlc_internal.h"
 #include "media_internal.h" // libvlc_media_set_state()
 #include "media_player_internal.h"
 
-/*
- * mapping of libvlc_navigate_mode_t to vlc_action_t
- */
-static const vlc_action_t libvlc_navigate_to_action[] =
-{
-    ACTIONID_NAV_ACTIVATE,
-    ACTIONID_NAV_UP,
-    ACTIONID_NAV_DOWN,
-    ACTIONID_NAV_LEFT,
-    ACTIONID_NAV_RIGHT
-};
-
-static const uint32_t libvlc_navigate_to_action_size =                        \
-  sizeof( libvlc_navigate_to_action ) / sizeof( libvlc_navigate_to_action[0] );
-
-
 static int
 input_seekable_changed( vlc_object_t * p_this, char const * psz_cmd,
                         vlc_value_t oldval, vlc_value_t newval,
@@ -64,6 +49,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_scrambled_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 );
@@ -132,6 +121,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, "program-scrambled",
+                    input_scrambled_changed, p_mi );
     var_DelCallback( p_input_thread, "intf-event",
                      input_event_changed, p_mi );
 
@@ -226,6 +217,24 @@ input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,
     return VLC_SUCCESS;
 }
 
+static int
+input_scrambled_changed( vlc_object_t * p_this, char const * psz_cmd,
+                        vlc_value_t oldval, vlc_value_t newval,
+                        void * p_userdata )
+{
+    VLC_UNUSED(oldval);
+    VLC_UNUSED(p_this);
+    VLC_UNUSED(psz_cmd);
+    libvlc_media_player_t * p_mi = p_userdata;
+    libvlc_event_t event;
+
+    event.type = libvlc_MediaPlayerScrambledChanged;
+    event.u.media_player_scrambled_changed.new_scrambled = 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,
@@ -357,13 +366,6 @@ static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd,
     return VLC_SUCCESS;
 }
 
-static input_thread_t *find_input (vlc_object_t *obj)
-{
-    libvlc_media_player_t *mp = (libvlc_media_player_t *)obj;
-
-    return libvlc_get_input_thread (mp);
-}
-
 /* */
 static void libvlc_media_player_destroy( libvlc_media_player_t * );
 
@@ -413,7 +415,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     var_Create (mp, "vmem-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
     var_Create (mp, "vmem-pitch", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
     var_Create (mp, "drawable-xid", VLC_VAR_INTEGER);
-#if defined (WIN32) || defined (__OS2__)
+#if defined (_WIN32) || defined (__OS2__)
     var_Create (mp, "drawable-hwnd", VLC_VAR_INTEGER);
 #endif
 #ifdef __APPLE__
@@ -465,9 +467,8 @@ libvlc_media_player_new( libvlc_instance_t *instance )
      /* Audio */
     var_Create (mp, "aout", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
     var_Create (mp, "mute", VLC_VAR_BOOL);
-    var_Create (mp, "volume", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
-    var_Create (mp, "find-input-callback", VLC_VAR_ADDRESS);
-    var_SetAddress (mp, "find-input-callback", find_input);
+    var_Create (mp, "volume", VLC_VAR_FLOAT);
+    var_Create (mp, "corks", VLC_VAR_INTEGER);
     var_Create (mp, "amem-data", VLC_VAR_ADDRESS);
     var_Create (mp, "amem-setup", VLC_VAR_ADDRESS);
     var_Create (mp, "amem-cleanup", VLC_VAR_ADDRESS);
@@ -481,16 +482,35 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
     var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT);
 
+    /* Video Title */
+    var_Create (mp, "video-title-show", VLC_VAR_BOOL);
+    var_Create (mp, "video-title-position", VLC_VAR_INTEGER);
+    var_Create (mp, "video-title-timeout", VLC_VAR_INTEGER);
+
+    /* Equalizer */
+    var_Create (mp, "equalizer-preamp", VLC_VAR_FLOAT);
+    var_Create (mp, "equalizer-bands", VLC_VAR_STRING);
+
     mp->p_md = NULL;
     mp->state = libvlc_NothingSpecial;
     mp->p_libvlc_instance = instance;
     mp->input.p_thread = NULL;
-    mp->input.p_resource = NULL;
+    mp->input.p_resource = input_resource_New(VLC_OBJECT(mp));
+    if (unlikely(mp->input.p_resource == NULL))
+    {
+        vlc_object_release(mp);
+        return NULL;
+    }
+    audio_output_t *aout = input_resource_GetAout(mp->input.p_resource);
+    if( aout != NULL )
+        input_resource_PutAout(mp->input.p_resource, aout);
+
     vlc_mutex_init (&mp->input.lock);
     mp->i_refcount = 1;
     mp->p_event_manager = libvlc_event_manager_new(mp, instance);
     if (unlikely(mp->p_event_manager == NULL))
     {
+        input_resource_Release(mp->input.p_resource);
         vlc_object_release(mp);
         return NULL;
     }
@@ -515,6 +535,7 @@ libvlc_media_player_new( libvlc_instance_t *instance )
     register_event(mp, PausableChanged);
 
     register_event(mp, Vout);
+    register_event(mp, ScrambledChanged);
 
     /* Snapshot initialization */
     register_event(mp, SnapshotTaken);
@@ -568,12 +589,8 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *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);
-    if( p_mi->input.p_resource )
-    {
-        input_resource_Terminate( p_mi->input.p_resource );
-        input_resource_Release( p_mi->input.p_resource );
-        p_mi->input.p_resource = NULL;
-    }
+    input_resource_Terminate( p_mi->input.p_resource );
+    input_resource_Release( p_mi->input.p_resource );
     vlc_mutex_destroy( &p_mi->input.lock );
 
     libvlc_event_manager_release( p_mi->p_event_manager );
@@ -717,8 +734,6 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
         return -1;
     }
 
-    if( !p_mi->input.p_resource )
-        p_mi->input.p_resource = input_resource_New( VLC_OBJECT( p_mi ) );
     p_input_thread = input_Create( p_mi, p_mi->p_md->p_input_item, NULL,
                                    p_mi->input.p_resource );
     unlock(p_mi);
@@ -731,6 +746,7 @@ 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, "program-scrambled", input_scrambled_changed, p_mi );
     var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
 
     if( input_Start( p_input_thread ) )
@@ -738,6 +754,7 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )
         unlock_input(p_mi);
         var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );
         var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );
+        var_DelCallback( p_input_thread, "program-scrambled", input_scrambled_changed, p_mi );
         var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );
         vlc_object_release( p_input_thread );
         libvlc_printerr( "Input initialization failure" );
@@ -818,8 +835,7 @@ void libvlc_media_player_stop( libvlc_media_player_t *p_mi )
         libvlc_event_send( p_mi->p_event_manager, &event );
     }
 
-    if( p_mi->input.p_resource != NULL )
-        input_resource_Terminate( p_mi->input.p_resource );
+    input_resource_Terminate( p_mi->input.p_resource );
     unlock_input(p_mi);
 }
 
@@ -935,7 +951,7 @@ void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
                                    void *drawable )
 {
     assert (p_mi != NULL);
-#if defined (WIN32) || defined (__OS2__)
+#if defined (_WIN32) || defined (__OS2__)
     var_SetString (p_mi, "window",
                    (drawable != NULL) ? "embed-hwnd,any" : "");
     var_SetInteger (p_mi, "drawable-hwnd", (uintptr_t)drawable);
@@ -950,7 +966,7 @@ void libvlc_media_player_set_hwnd( libvlc_media_player_t *p_mi,
 void *libvlc_media_player_get_hwnd( libvlc_media_player_t *p_mi )
 {
     assert (p_mi != NULL);
-#if defined (WIN32) || defined (__OS2__)
+#if defined (_WIN32) || defined (__OS2__)
     return (void *)(uintptr_t)var_GetInteger (p_mi, "drawable-hwnd");
 #else
     return NULL;
@@ -1239,7 +1255,7 @@ int libvlc_media_player_will_play( libvlc_media_player_t *p_mi )
     if ( !p_input_thread )
         return false;
 
-    b_will_play = !p_input_thread->b_die && !p_input_thread->b_dead;
+    b_will_play = !p_input_thread->b_dead;
     vlc_object_release( p_input_thread );
 
     return b_will_play;
@@ -1247,12 +1263,6 @@ int libvlc_media_player_will_play( libvlc_media_player_t *p_mi )
 
 int libvlc_media_player_set_rate( libvlc_media_player_t *p_mi, float rate )
 {
-    if (rate < 0.)
-    {
-        libvlc_printerr ("Playing backward not supported");
-        return -1;
-    }
-
     var_SetFloat (p_mi, "rate", rate);
 
     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
@@ -1293,19 +1303,21 @@ int libvlc_media_player_is_seekable( libvlc_media_player_t *p_mi )
 void libvlc_media_player_navigate( libvlc_media_player_t* p_mi,
                                    unsigned navigate )
 {
-    input_thread_t *p_input_thread;
+    static const vlc_action_t map[] =
+    {
+        INPUT_NAV_ACTIVATE, INPUT_NAV_UP, INPUT_NAV_DOWN,
+        INPUT_NAV_LEFT, INPUT_NAV_RIGHT,
+    };
 
-    if ( navigate >= libvlc_navigate_to_action_size)
+    if( navigate >= sizeof(map) / sizeof(map[0]) )
       return;
 
-    p_input_thread = libvlc_get_input_thread ( p_mi );
-    if ( !p_input_thread )
+    input_thread_t *p_input = libvlc_get_input_thread ( p_mi );
+    if ( p_input == NULL )
       return;
 
-    var_SetInteger( p_mi->p_libvlc_instance->p_libvlc_int,
-                    "key-action", libvlc_navigate_to_action[navigate] );
-
-    vlc_object_release( p_input_thread );
+    input_Control( p_input, map[navigate], NULL );
+    vlc_object_release( p_input );
 }
 
 /* internal function, used by audio, video */
@@ -1399,6 +1411,20 @@ int libvlc_media_player_can_pause( libvlc_media_player_t *p_mi )
     return b_can_pause;
 }
 
+int libvlc_media_player_program_scrambled( libvlc_media_player_t *p_mi )
+{
+    input_thread_t *p_input_thread;
+    bool b_program_scrambled;
+
+    p_input_thread = libvlc_get_input_thread ( p_mi );
+    if ( !p_input_thread )
+        return false;
+    b_program_scrambled = var_GetBool( p_input_thread, "program-scrambled" );
+    vlc_object_release( p_input_thread );
+
+    return b_program_scrambled;
+}
+
 void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
 {
     input_thread_t *p_input_thread = libvlc_get_input_thread ( p_mi );
@@ -1408,3 +1434,77 @@ void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )
         vlc_object_release( p_input_thread );
     }
 }
+
+void libvlc_media_player_set_video_title_display( libvlc_media_player_t *p_mi, libvlc_position_t position, unsigned timeout )
+{
+    if ( position != libvlc_position_disable )
+    {
+        var_SetBool( p_mi, "video-title-show", true );
+        var_SetInteger( p_mi, "video-title-position", position );
+        var_SetInteger( p_mi, "video-title-timeout", timeout );
+    }
+    else
+    {
+        var_SetBool( p_mi, "video-title-show", false );
+    }
+}
+
+/**
+ * Maximum size of a formatted equalizer amplification band frequency value.
+ *
+ * The allowed value range is supposed to be constrained from -20.0 to 20.0.
+ *
+ * The format string " %.07f" with a minimum value of "-20" gives a maximum
+ * string length of e.g. " -19.1234567", i.e. 12 bytes (not including the null
+ * terminator).
+ */
+#define EQZ_BAND_VALUE_SIZE 12
+
+int libvlc_media_player_set_equalizer( libvlc_media_player_t *p_mi, libvlc_equalizer_t *p_equalizer )
+{
+    float f_preamp;
+    char *psz_bands;
+
+    if ( p_equalizer )
+    {
+        f_preamp = p_equalizer->f_preamp;
+
+        psz_bands = malloc( EQZ_BANDS_MAX * EQZ_BAND_VALUE_SIZE + 1 );
+        if ( unlikely( psz_bands == NULL ) )
+            return -1;
+
+        char *p = psz_bands;
+        int c;
+        for ( int i = 0; i < EQZ_BANDS_MAX; i++ )
+        {
+            c = snprintf( p, EQZ_BAND_VALUE_SIZE + 1, " %.07f", p_equalizer->f_amp[i] );
+            if ( unlikely( c >= EQZ_BAND_VALUE_SIZE + 1 ) )
+            {
+                free( psz_bands );
+                return -1;
+            }
+
+            p += c;
+        }
+    }
+    else
+    {
+        f_preamp = 0.f;
+        psz_bands = NULL;
+    }
+
+    var_SetFloat( p_mi, "equalizer-preamp", f_preamp );
+    var_SetString( p_mi, "equalizer-bands", psz_bands );
+
+    audio_output_t *p_aout = input_resource_HoldAout( p_mi->input.p_resource );
+    if ( p_aout )
+    {
+        var_SetFloat( p_aout, "equalizer-preamp", f_preamp );
+        var_SetString( p_aout, "equalizer-bands", psz_bands );
+
+        vlc_object_release( p_aout );
+    }
+
+    free( psz_bands );
+    return 0;
+}