[vlc-devel] [PATCH 1/2] qt: scan and select the Renderer via the menu

Steve Lhomme robux4 at videolabs.io
Thu Jun 23 13:34:04 CEST 2016


---
 modules/gui/qt/actions_manager.cpp | 172 +++++++++++++++++++++++++++++++++++++
 modules/gui/qt/actions_manager.hpp |   9 +-
 modules/gui/qt/menus.cpp           |  34 ++++++++
 modules/gui/qt/menus.hpp           |   3 +
 4 files changed, 217 insertions(+), 1 deletion(-)

diff --git a/modules/gui/qt/actions_manager.cpp b/modules/gui/qt/actions_manager.cpp
index 89f5d22..8296032 100644
--- a/modules/gui/qt/actions_manager.cpp
+++ b/modules/gui/qt/actions_manager.cpp
@@ -27,6 +27,7 @@
 
 #include <vlc_vout.h>
 #include <vlc_keys.h>
+#include <vlc_renderer_discovery.h>
 
 #include "actions_manager.hpp"
 
@@ -35,10 +36,29 @@
 #include "main_interface.hpp"        /* Show playlist */
 #include "components/controller.hpp" /* Toggle FSC controller width */
 #include "components/extended_panels.hpp"
+#include "menus.hpp"
 
 ActionsManager::ActionsManager( intf_thread_t * _p_i )
 {
     p_intf = _p_i;
+    p_rd   = NULL;
+    b_rd_started = false;
+}
+
+ActionsManager::~ActionsManager()
+{
+    if ( p_rd != NULL )
+    {
+        if (b_rd_started)
+        {
+            vlc_event_manager_t *em = vlc_rd_event_manager( p_rd );
+            vlc_event_detach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, p_intf);
+            vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, p_intf);
+
+            vlc_rd_stop( p_rd );
+        }
+        vlc_rd_release( p_rd );
+    }
 }
 
 void ActionsManager::doAction( int id_action )
@@ -213,3 +233,155 @@ void ActionsManager::PPaction( QAction *a )
 
     ExtVideo::setPostprocessing( p_intf, i_q );
 }
+
+bool ActionsManager::isItemSout( QVariant & m_obj, const char *psz_sout, bool as_output )
+{
+    if ( psz_sout == NULL )
+        return false;
+    if (!m_obj.canConvert<QString>())
+        return false;
+
+    QString renderer(psz_sout);
+    if ( as_output && renderer.at(0) == '#' )
+        renderer = renderer.right( renderer.length() - 1 );
+    return QString::compare( m_obj.toString(), renderer, Qt::CaseInsensitive) == 0;
+}
+
+void ActionsManager::renderer_event_received( const vlc_event_t * p_event, void * user_data )
+{
+    intf_thread_t *p_intf = reinterpret_cast<intf_thread_t*>(user_data);
+
+    if ( p_event->type == vlc_RendererDiscoveryItemAdded )
+    {
+        vlc_renderer_item *p_item =  p_event->u.renderer_discovery_item_added.p_new_item;
+
+        QAction *firstSeparator = NULL;
+        foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
+        {
+            if (action->isSeparator())
+            {
+                firstSeparator = action;
+                break;
+            }
+            QVariant v = action->data();
+            if ( isItemSout( v, vlc_renderer_item_sout( p_item ), false ) )
+                return; /* we already have this item */
+        }
+
+        QVariant data(vlc_renderer_item_sout( p_item ));
+
+        QAction *action = new QAction( vlc_renderer_item_flags(p_item) & VLC_RENDERER_CAN_VIDEO ? QIcon( ":/sidebar/movie" ) : QIcon( ":/sidebar/music" ),
+                                       vlc_renderer_item_name(p_item), VLCMenuBar::rendererMenu );
+        action->setCheckable(true);
+        action->setData(data);
+        if (firstSeparator != NULL)
+        {
+            VLCMenuBar::rendererMenu->insertAction( firstSeparator, action );
+            VLCMenuBar::rendererGroup->addAction(action);
+        }
+
+        char *psz_renderer = var_InheritString( THEPL, "sout" );
+        if ( psz_renderer != NULL )
+        {
+            if ( isItemSout( data, psz_renderer, true ) )
+                action->setChecked( true );
+            free( psz_renderer );
+        }
+
+        CONNECT( VLCMenuBar::rendererGroup, triggered(QAction*), ActionsManager::getInstance( p_intf ), RendererSelected( QAction* ) );
+    }
+}
+
+void ActionsManager::ScanRendererAction(bool checked)
+{
+    if (checked == b_rd_started)
+        return; /* nothing changed */
+
+    if (checked)
+    {
+        /* reset the list of renderers */
+        foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
+        {
+            QVariant data = action->data();
+            if (!data.canConvert<QString>())
+                continue;
+            VLCMenuBar::rendererMenu->removeAction(action);
+            VLCMenuBar::rendererGroup->removeAction(action);
+        }
+        char *psz_renderer = var_InheritString( THEPL, "sout" );
+        if ( psz_renderer == NULL || *psz_renderer == '\0' )
+        {
+            foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
+            {
+                if (!action->data().canConvert<QString>())
+                    continue;
+                if (!action->isSeparator())
+                    action->setChecked(true);
+                break;
+            }
+        }
+        free( psz_renderer );
+
+        /* SD subnodes */
+        char **ppsz_longnames;
+        char **ppsz_names;
+        if( vlc_rd_get_names( THEPL, &ppsz_names, &ppsz_longnames ) != VLC_SUCCESS )
+            return;
+
+        char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
+        for( ; *ppsz_name; ppsz_name++, ppsz_longname++ )
+        {
+            /* TODO launch all discovery services for renderers */
+            msg_Dbg( p_intf, "starting renderer discovery service %s", *ppsz_longname );
+            if ( p_rd == NULL )
+            {
+                p_rd = vlc_rd_new( VLC_OBJECT(p_intf), *ppsz_name );
+                if( !p_rd )
+                    msg_Err( p_intf, "Could not start renderer discovery services" );
+            }
+            break;
+        }
+        free( ppsz_names );
+        free( ppsz_longnames );
+
+        if ( p_rd != NULL )
+        {
+            vlc_event_manager_t *em = vlc_rd_event_manager( p_rd );
+            vlc_event_attach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, p_intf);
+            vlc_event_attach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, p_intf);
+
+            b_rd_started = vlc_rd_start( p_rd ) == VLC_SUCCESS;
+            if ( !b_rd_started )
+            {
+                vlc_event_detach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, p_intf);
+                vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, p_intf);
+            }
+        }
+    }
+    else
+    {
+        if ( p_rd != NULL )
+        {
+            vlc_event_manager_t *em = vlc_rd_event_manager( p_rd );
+            vlc_event_detach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, p_intf);
+            vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, p_intf);
+
+            vlc_rd_stop( p_rd );
+        }
+        b_rd_started = false;
+    }
+}
+
+void ActionsManager::RendererSelected( QAction *selected )
+{
+    QString s_sout;
+    QVariant data = selected->data();
+    if (data.canConvert<QString>())
+    {
+        s_sout.append('#');
+        s_sout.append(data.toString());
+    }
+    msg_Dbg( p_intf, "using sout: '%s'", s_sout.toUtf8().constData() );
+    var_SetString( THEPL, "sout", s_sout.toUtf8().constData() );
+}
+
diff --git a/modules/gui/qt/actions_manager.hpp b/modules/gui/qt/actions_manager.hpp
index cb3943a..5b5b3e6 100644
--- a/modules/gui/qt/actions_manager.hpp
+++ b/modules/gui/qt/actions_manager.hpp
@@ -72,9 +72,14 @@ public:
 
 private:
     ActionsManager( intf_thread_t  *_p_i );
-    virtual ~ActionsManager() {}
+    virtual ~ActionsManager();
 
     intf_thread_t       *p_intf;
+    vlc_renderer_discovery *p_rd;
+
+    bool  b_rd_started;
+    static void renderer_event_received( const vlc_event_t * p_event, void * user_data );
+    static bool isItemSout( QVariant & m_obj, const char *psz_sout, bool as_output );
 
 public slots:
     void toggleMuteAudio();
@@ -85,6 +90,8 @@ public slots:
     void skipForward();
     void skipBackward();
     void PPaction( QAction * );
+    void ScanRendererAction( bool );
+    void RendererSelected( QAction * );
 
 protected slots:
     void fullscreen();
diff --git a/modules/gui/qt/menus.cpp b/modules/gui/qt/menus.cpp
index 2f70f57..c770995 100644
--- a/modules/gui/qt/menus.cpp
+++ b/modules/gui/qt/menus.cpp
@@ -82,6 +82,8 @@ static QActionGroup *currentGroup;
 QMenu *VLCMenuBar::recentsMenu = NULL;
 QMenu *VLCMenuBar::audioDeviceMenu = NULL;
 QMenu *VLCMenuBar::ppMenu = NULL;
+QMenu *VLCMenuBar::rendererMenu = NULL;
+QActionGroup *VLCMenuBar::rendererGroup = NULL;
 
 /**
  * @brief Add static entries to DP in menus
@@ -673,6 +675,10 @@ QMenu *VLCMenuBar::VideoMenu( intf_thread_t *p_intf, QMenu *current )
         addActionWithSubmenu( current, "video-es", qtr( "Video &Track" ) );
 
         current->addSeparator();
+        rendererMenu = RendererMenu( p_intf );
+        current->addMenu( rendererMenu );
+
+        current->addSeparator();
         /* Surface modifiers */
         addActionWithCheckbox( current, "fullscreen", qtr( "&Fullscreen" ) );
         addActionWithCheckbox( current, "autoscale", qtr( "Always Fit &Window" ) );
@@ -1621,6 +1627,34 @@ void VLCMenuBar::updateRecents( intf_thread_t *p_intf )
     }
 }
 
+QMenu *VLCMenuBar::RendererMenu( intf_thread_t *p_intf )
+{
+    QMenu *submenu = new QMenu( qtr("&Renderer") );
+
+    rendererGroup = new QActionGroup(submenu);
+
+    QAction *action = new QAction( qtr("<Local>"), submenu );
+    action->setCheckable(true);
+    submenu->addAction( action );
+    rendererGroup->addAction(action);
+
+    char *psz_renderer = var_InheritString( THEPL, "sout" );
+    if ( psz_renderer == NULL )
+        action->setChecked( true );
+    else
+        free( psz_renderer );
+
+    submenu->addSeparator();
+
+    action = new QAction( qtr("Scan"), submenu );
+    action->setCheckable(true);
+    submenu->addAction( action );
+
+    CONNECT( action, triggered(bool), ActionsManager::getInstance( p_intf ), ScanRendererAction( bool ) );
+
+    return submenu;
+}
+
 QMenu *VLCMenuBar::PPMenu( intf_thread_t *p_intf )
 {
     int i_q = ExtVideo::getPostprocessing( p_intf );
diff --git a/modules/gui/qt/menus.hpp b/modules/gui/qt/menus.hpp
index 3d69a6a..222c2ca 100644
--- a/modules/gui/qt/menus.hpp
+++ b/modules/gui/qt/menus.hpp
@@ -95,6 +95,8 @@ public:
     Q_DECLARE_FLAGS(actionflags, actionflag)
 
     static QMenu *ppMenu;
+    static QMenu *rendererMenu;
+    static QActionGroup *rendererGroup;
 
 private:
     /* All main Menus */
@@ -131,6 +133,7 @@ private:
 
     static QMenu *HelpMenu( QWidget * );
     static QMenu *PPMenu( intf_thread_t *p_intf );
+    static QMenu *RendererMenu( intf_thread_t *p_intf );
 
     /* Popups Menus */
     static void PopupMenuStaticEntries( QMenu *menu );
-- 
2.8.2



More information about the vlc-devel mailing list