[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