]> git.sesse.net Git - vlc/blobdiff - modules/gui/qt4/input_manager.cpp
Win32: add support for play and pause buttons in media keys (different from a plya...
[vlc] / modules / gui / qt4 / input_manager.cpp
index 82bdb04729e4d0b6f05979f5ee385b582b1cf51d..1650d4e90c33d15cec13bfe6e1e5fc4cf1c7cdca 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "input_manager.hpp"
 #include <vlc_keys.h>
+#include <vlc_url.h>
 
 #include <QApplication>
 
@@ -38,8 +39,22 @@ static int ItemChanged( vlc_object_t *, const char *,
                         vlc_value_t, vlc_value_t, void * );
 static int PLItemChanged( vlc_object_t *, const char *,
                         vlc_value_t, vlc_value_t, void * );
+static int PLItemAppended( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+static int PLItemRemoved( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
 static int VolumeChanged( vlc_object_t *, const char *,
                         vlc_value_t, vlc_value_t, void * );
+static int SoundMuteChanged( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+
+static int RandomChanged( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+static int LoopChanged( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+static int RepeatChanged( vlc_object_t *, const char *,
+                        vlc_value_t, vlc_value_t, void * );
+
 
 static int InputEvent( vlc_object_t *, const char *,
                        vlc_value_t, vlc_value_t, void * );
@@ -149,16 +164,12 @@ void InputManager::customEvent( QEvent *event )
     int i_type = event->type();
     IMEvent *ple = static_cast<IMEvent *>(event);
 
+    if( i_type == ItemChanged_Type )
+        UpdateMeta( ple->p_item );
+
     if( !hasInput() )
         return;
 
-#ifndef NDEBUG
-    if( i_type != PositionUpdate_Type &&
-        i_type != StatisticsUpdate_Type &&
-        i_type != ItemChanged_Type )
-        msg_Dbg( p_intf, "New Event: type %i", i_type );
-#endif
-
     /* Actions */
     switch( i_type )
     {
@@ -177,7 +188,6 @@ void InputManager::customEvent( QEvent *event )
             UpdateArt();
             /* Update duration of file */
         }
-        UpdateMeta( ple->p_item->i_id );
         break;
     case ItemStateChanged_Type:
         // TODO: Fusion with above state
@@ -407,7 +417,7 @@ void InputManager::UpdateStatus()
 void InputManager::UpdateRate()
 {
     /* Update Rate */
-    int i_new_rate = var_GetInteger( p_input, "rate");
+    int i_new_rate = INPUT_RATE_DEFAULT / var_GetFloat( p_input, "rate" );
     if( i_new_rate != i_rate )
     {
         i_rate = i_new_rate;
@@ -590,12 +600,20 @@ void InputManager::UpdateArt()
     if( hasInput() )
     {
         char *psz_art = input_item_GetArtURL( input_GetItem( p_input ) );
-        url = qfu( psz_art );
+        if( psz_art && !strncmp( psz_art, "file://", 7 ) &&
+                decode_URI( psz_art + 7 ) )
+#ifdef WIN32
+            url = qfu( psz_art + 8 ); // Remove extra / starting on Win32.
+#else
+            url = qfu( psz_art + 7 );
+#endif
         free( psz_art );
+
+        url = url.replace( "file://", "" );
+        /* Taglib seems to define a attachment://, It won't work yet */
+        url = url.replace( "attachment://", "" );
     }
-    url = url.replace( "file://", QString("" ) );
-    /* Taglib seems to define a attachment://, It won't work yet */
-    url = url.replace( "attachment://", QString("" ) );
+
     /* Update Art meta */
     emit artChanged( url );
 }
@@ -605,9 +623,9 @@ inline void InputManager::UpdateStats()
     emit statisticsUpdated( input_GetItem( p_input ) );
 }
 
-inline void InputManager::UpdateMeta( int id )
+inline void InputManager::UpdateMeta( input_item_t *p_item )
 {
-    emit metaChanged( id );
+    emit metaChanged( p_item );
 }
 
 inline void InputManager::UpdateMeta()
@@ -661,8 +679,8 @@ void InputManager::sectionPrev()
     if( hasInput() )
     {
         int i_type = var_Type( p_input, "next-chapter" );
-        var_SetVoid( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
-                            "prev-chapter":"prev-title" );
+        var_TriggerCallback( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
+                             "prev-chapter":"prev-title" );
     }
 }
 
@@ -671,8 +689,8 @@ void InputManager::sectionNext()
     if( hasInput() )
     {
         int i_type = var_Type( p_input, "next-chapter" );
-        var_SetVoid( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
-                            "next-chapter":"next-title" );
+        var_TriggerCallback( p_input, (i_type & VLC_VAR_TYPE) != 0 ?
+                             "next-chapter":"next-title" );
     }
 }
 
@@ -768,21 +786,21 @@ void InputManager::reverse()
 {
     if( hasInput() )
     {
-        int i_rate = var_GetInteger( p_input, "rate" );
-        var_SetInteger( p_input, "rate", -i_rate );
+        float f_rate = var_GetFloat( p_input, "rate" );
+        var_SetFloat( p_input, "rate", -f_rate );
     }
 }
 
 void InputManager::slower()
 {
     if( hasInput() )
-        var_SetVoid( p_input, "rate-slower" );
+        var_TriggerCallback( p_input, "rate-slower" );
 }
 
 void InputManager::faster()
 {
     if( hasInput() )
-        var_SetVoid( p_input, "rate-faster" );
+        var_TriggerCallback( p_input, "rate-faster" );
 }
 
 void InputManager::littlefaster()
@@ -798,13 +816,14 @@ void InputManager::littleslower()
 void InputManager::normalRate()
 {
     if( hasInput() )
-        var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT );
+        var_SetFloat( p_input, "rate", 1. );
 }
 
 void InputManager::setRate( int new_rate )
 {
     if( hasInput() )
-        var_SetInteger( p_input, "rate", new_rate );
+        var_SetFloat( p_input, "rate",
+                      (float)INPUT_RATE_DEFAULT / (float)new_rate );
 }
 
 void InputManager::jumpFwd()
@@ -877,8 +896,14 @@ MainInputManager::MainInputManager( intf_thread_t *_p_intf )
     var_AddCallback( THEPL, "item-change", ItemChanged, im );
     var_AddCallback( THEPL, "item-current", PLItemChanged, this );
     var_AddCallback( THEPL, "activity", PLItemChanged, this );
+    var_AddCallback( THEPL, "playlist-item-append", PLItemAppended, this );
+    var_AddCallback( THEPL, "playlist-item-deleted", PLItemRemoved, this );
+    var_AddCallback( THEPL, "random", RandomChanged, this );
+    var_AddCallback( THEPL, "repeat", RepeatChanged, this );
+    var_AddCallback( THEPL, "loop", LoopChanged, this );
 
     var_AddCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
+    var_AddCallback( p_intf->p_libvlc, "volume-muted", SoundMuteChanged, this );
 
     /* Warn our embedded IM about input changes */
     CONNECT( this, inputChanged( input_thread_t * ),
@@ -909,11 +934,18 @@ MainInputManager::~MainInputManager()
     }
 
     var_DelCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this );
+    var_DelCallback( p_intf->p_libvlc, "volume-muted", SoundMuteChanged, this );
 
     var_DelCallback( THEPL, "activity", PLItemChanged, this );
     var_DelCallback( THEPL, "item-change", ItemChanged, im );
 
     var_DelCallback( THEPL, "item-current", PLItemChanged, this );
+    var_DelCallback( THEPL, "playlist-item-append", PLItemAppended, this );
+    var_DelCallback( THEPL, "playlist-item-deleted", PLItemRemoved, this );
+    var_DelCallback( THEPL, "random", RandomChanged, this );
+    var_DelCallback( THEPL, "repeat", RepeatChanged, this );
+    var_DelCallback( THEPL, "loop", LoopChanged, this );
+
 }
 
 vout_thread_t* MainInputManager::getVout()
@@ -929,14 +961,35 @@ aout_instance_t * MainInputManager::getAout()
 void MainInputManager::customEvent( QEvent *event )
 {
     int type = event->type();
-    if ( type != ItemChanged_Type && type != VolumeChanged_Type )
-        return;
+
+    PLEvent *plEv;
 
     // msg_Dbg( p_intf, "New MainIM Event of type: %i", type );
-    if( type == VolumeChanged_Type )
+    switch( type )
     {
+    case VolumeChanged_Type:
         emit volumeChanged();
         return;
+    case SoundMuteChanged_Type:
+        emit soundMuteChanged();
+        return;
+    case PLItemAppended_Type:
+        plEv = static_cast<PLEvent*>( event );
+        emit playlistItemAppended( plEv->i_item, plEv->i_parent );
+        return;
+    case PLItemRemoved_Type:
+        plEv = static_cast<PLEvent*>( event );
+        emit playlistItemRemoved( plEv->i_item );
+        return;
+    case RandomChanged_Type:
+        emit randomChanged( var_GetBool( THEPL, "random" ) );
+        return;
+    case LoopChanged_Type:
+    case RepeatChanged_Type:
+        notifyRepeatLoop();
+        return;
+    default:
+        if( type != ItemChanged_Type ) return;
     }
 
     /* Should be PLItemChanged Event */
@@ -1005,12 +1058,64 @@ void MainInputManager::togglePlayPause()
         getIM()->togglePlayPause();
 }
 
+void MainInputManager::play()
+{
+    /* No input, play */
+    if( !p_input )
+        playlist_Play( THEPL );
+    else
+    {
+        if( PLAYING_S != var_GetInteger( p_input, "state" ) )
+        {
+            getIM()->togglePlayPause();
+        }
+    }
+}
+
+void MainInputManager::pause()
+{
+    if(p_input && PLAYING_S == var_GetInteger( p_input, "state" ) )
+    {
+        getIM()->togglePlayPause();
+    }
+}
+
+void MainInputManager::toggleRandom()
+{
+    var_ToggleBool( THEPL, "random" );
+}
+
+void MainInputManager::notifyRepeatLoop()
+{
+    int i_value = var_GetBool( THEPL, "loop" ) * REPEAT_ONE
+              + var_GetBool( THEPL, "repeat" ) * REPEAT_ALL;
+
+    emit repeatLoopChanged( i_value );
+}
+
+void MainInputManager::loopRepeatLoopStatus()
+{
+    /* Toggle Normal -> Loop -> Repeat -> Normal ... */
+    if( var_GetBool( THEPL, "repeat" ) )
+        var_SetBool( THEPL, "repeat", false );
+    else if( var_GetBool( THEPL, "loop" ) )
+    {
+        var_SetBool( THEPL, "loop", false );
+        var_SetBool( THEPL, "repeat", true );
+    }
+    else
+        var_SetBool( THEPL, "loop", true );
+}
+
 void MainInputManager::activatePlayQuit( bool b_exit )
 {
     var_SetBool( THEPL, "play-and-exit", b_exit );
 }
 
-/* Static callbacks for MIM */
+
+/****************************
+ * Static callbacks for MIM *
+ ****************************/
 static int PLItemChanged( vlc_object_t *p_this, const char *psz_var,
                         vlc_value_t oldval, vlc_value_t, void *param )
 {
@@ -1031,3 +1136,63 @@ static int VolumeChanged( vlc_object_t *p_this, const char *psz_var,
     return VLC_SUCCESS;
 }
 
+static int SoundMuteChanged( vlc_object_t *p_this, const char *psz_var,
+                        vlc_value_t oldval, vlc_value_t newval, void *param )
+{
+    MainInputManager *mim = (MainInputManager*)param;
+
+    IMEvent *event = new IMEvent( SoundMuteChanged_Type );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}
+
+static int PLItemAppended
+( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data )
+{
+    MainInputManager *mim = static_cast<MainInputManager*>(data);
+    playlist_add_t *p_add = static_cast<playlist_add_t*>( cur.p_address );
+
+    PLEvent *event = new PLEvent( PLItemAppended_Type, p_add->i_item, p_add->i_node  );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}
+static int PLItemRemoved
+( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data )
+{
+    MainInputManager *mim = static_cast<MainInputManager*>(data);
+
+    PLEvent *event = new PLEvent( PLItemRemoved_Type, cur.i_int, 0  );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}
+
+static int RandomChanged
+( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data )
+{
+    MainInputManager *mim = static_cast<MainInputManager*>(data);
+
+    IMEvent *event = new IMEvent( RandomChanged_Type );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}
+
+/* Probably could be merged with next callback */
+static int LoopChanged
+( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data )
+{
+    MainInputManager *mim = static_cast<MainInputManager*>(data);
+
+    IMEvent *event = new IMEvent( LoopChanged_Type );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}
+
+static int RepeatChanged
+( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data )
+{
+    MainInputManager *mim = static_cast<MainInputManager*>(data);
+
+    IMEvent *event = new IMEvent( RepeatChanged_Type );
+    QApplication::postEvent( mim, event );
+    return VLC_SUCCESS;
+}