[vlc-commits] Qt: split logically renderer widget and improve
Francois Cartegnie
git at videolan.org
Wed Jun 13 15:30:29 CEST 2018
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Sun Jun 10 22:02:49 2018 +0200| [691c674bfff87d56618dda0b546f6a02feca78b0] | committer: Francois Cartegnie
Qt: split logically renderer widget and improve
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=691c674bfff87d56618dda0b546f6a02feca78b0
---
modules/gui/qt/Makefile.am | 5 +
modules/gui/qt/actions_manager.cpp | 169 -----------------------
modules/gui/qt/actions_manager.hpp | 23 ----
modules/gui/qt/components/custom_menus.cpp | 198 +++++++++++++++++++++++++++
modules/gui/qt/components/custom_menus.hpp | 67 +++++++++
modules/gui/qt/main_interface.cpp | 3 +
modules/gui/qt/managers/renderer_manager.cpp | 170 +++++++++++++++++++++++
modules/gui/qt/managers/renderer_manager.hpp | 87 ++++++++++++
modules/gui/qt/menus.cpp | 39 +-----
modules/gui/qt/menus.hpp | 6 +-
po/POTFILES.in | 2 +
11 files changed, 539 insertions(+), 230 deletions(-)
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 6da5f5bc96..a37baeb1a9 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -48,6 +48,7 @@ libqt_plugin_la_SOURCES = \
gui/qt/actions_manager.cpp gui/qt/actions_manager.hpp \
gui/qt/extensions_manager.cpp gui/qt/extensions_manager.hpp \
gui/qt/managers/addons_manager.cpp gui/qt/managers/addons_manager.hpp \
+ gui/qt/managers/renderer_manager.cpp gui/qt/managers/renderer_manager.hpp \
gui/qt/recents.cpp gui/qt/recents.hpp \
gui/qt/adapters/seekpoints.cpp gui/qt/adapters/seekpoints.hpp \
gui/qt/adapters/chromaprint.cpp gui/qt/adapters/chromaprint.hpp \
@@ -92,6 +93,8 @@ libqt_plugin_la_SOURCES = \
gui/qt/components/controller.cpp gui/qt/components/controller.hpp \
gui/qt/components/controller_widget.cpp \
gui/qt/components/controller_widget.hpp \
+ gui/qt/components/custom_menus.cpp \
+ gui/qt/components/custom_menus.hpp \
gui/qt/components/epg/EPGChannels.cpp \
gui/qt/components/epg/EPGChannels.hpp \
gui/qt/components/epg/EPGItem.cpp \
@@ -169,6 +172,7 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/actions_manager.moc.cpp \
gui/qt/extensions_manager.moc.cpp \
gui/qt/managers/addons_manager.moc.cpp \
+ gui/qt/managers/renderer_manager.moc.cpp \
gui/qt/recents.moc.cpp \
gui/qt/adapters/seekpoints.moc.cpp \
gui/qt/adapters/chromaprint.moc.cpp \
@@ -204,6 +208,7 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/components/interface_widgets.moc.cpp \
gui/qt/components/controller.moc.cpp \
gui/qt/components/controller_widget.moc.cpp \
+ gui/qt/components/custom_menus.moc.cpp \
gui/qt/components/epg/EPGChannels.moc.cpp \
gui/qt/components/epg/EPGProgram.moc.cpp \
gui/qt/components/epg/EPGRuler.moc.cpp \
diff --git a/modules/gui/qt/actions_manager.cpp b/modules/gui/qt/actions_manager.cpp
index e614e424d0..4b9d4e6ad5 100644
--- a/modules/gui/qt/actions_manager.cpp
+++ b/modules/gui/qt/actions_manager.cpp
@@ -27,7 +27,6 @@
#include <vlc_vout.h>
#include <vlc_actions.h>
-#include <vlc_renderer_discovery.h>
#include "actions_manager.hpp"
@@ -40,28 +39,11 @@
ActionsManager::ActionsManager( intf_thread_t * _p_i )
: p_intf( _p_i )
- , m_scanning( false )
{
- CONNECT( this, rendererItemAdded( vlc_renderer_item_t* ),
- this, onRendererItemAdded( vlc_renderer_item_t* ) );
- CONNECT( this, rendererItemRemoved( vlc_renderer_item_t* ),
- this, onRendererItemRemoved( vlc_renderer_item_t* ) );
- m_stop_scan_timer.setSingleShot( true );
- CONNECT( &m_stop_scan_timer, timeout(), this, StopRendererScan() );
}
ActionsManager::~ActionsManager()
{
- StopRendererScan();
- /* reset the list of renderers */
- foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
- {
- QVariant data = action->data();
- if (!data.canConvert<QVariantHash>())
- continue;
- VLCMenuBar::rendererMenu->removeAction(action);
- VLCMenuBar::rendererGroup->removeAction(action);
- }
}
void ActionsManager::doAction( int id_action )
@@ -224,154 +206,3 @@ void ActionsManager::skipBackward()
if( p_input )
THEMIM->getIM()->jumpBwd();
}
-
-vlc_renderer_item_t* ActionsManager::getMatchingRenderer( const QVariant &obj, vlc_renderer_item_t* p_item )
-{
- if (!obj.canConvert<QVariantHash>())
- return NULL;
- QVariantHash qvh = obj.value<QVariantHash>();
- if (!qvh.contains( "sout" ))
- return NULL;
- vlc_renderer_item_t* p_existing =
- reinterpret_cast<vlc_renderer_item_t*>( qvh["sout"].value<void*>() );
- if ( !strcasecmp(vlc_renderer_item_sout( p_existing ),
- vlc_renderer_item_sout( p_item ) ) )
- return p_existing;
- return NULL;
-}
-
-void ActionsManager::onRendererItemAdded(vlc_renderer_item_t* p_item)
-{
- QAction *firstSeparator = NULL;
-
- foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
- {
- if (action->isSeparator())
- {
- firstSeparator = action;
- break;
- }
- if (getMatchingRenderer( action->data(), p_item ))
- {
- vlc_renderer_item_release( p_item );
- return; /* we already have this item */
- }
- }
-
- QAction *action = new QAction( vlc_renderer_item_flags(p_item) & VLC_RENDERER_CAN_VIDEO ? QIcon( ":/sidebar/movie.svg" ) : QIcon( ":/sidebar/music.svg" ),
- vlc_renderer_item_name(p_item), VLCMenuBar::rendererMenu );
- action->setCheckable(true);
-
- QVariantHash data;
- data.insert( "sout", QVariant::fromValue( reinterpret_cast<void*>( p_item ) ) );
- action->setData( data );
- if (firstSeparator != NULL)
- {
- VLCMenuBar::rendererMenu->insertAction( firstSeparator, action );
- VLCMenuBar::rendererGroup->addAction(action);
- }
- else
- {
- vlc_renderer_item_release( p_item );
- delete action;
- }
-}
-
-void ActionsManager::onRendererItemRemoved( vlc_renderer_item_t* p_item )
-{
- foreach (QAction* action, VLCMenuBar::rendererMenu->actions())
- {
- if (action->isSeparator())
- continue;
- vlc_renderer_item_t *p_existing = getMatchingRenderer( action->data(), p_item );
- if (p_existing)
- {
- VLCMenuBar::rendererMenu->removeAction( action );
- VLCMenuBar::rendererGroup->removeAction( action );
- vlc_renderer_item_release( p_existing );
- break;
- }
- }
- // Always release the item as we acquired it before emiting the signal
- vlc_renderer_item_release( p_item );
-}
-
-void ActionsManager::renderer_event_item_added( vlc_renderer_discovery_t* p_rd,
- vlc_renderer_item_t *p_item )
-{
- ActionsManager *self = reinterpret_cast<ActionsManager*>( p_rd->owner.sys );
- vlc_renderer_item_hold( p_item );
- self->emit rendererItemAdded( p_item );
-}
-
-void ActionsManager::renderer_event_item_removed( vlc_renderer_discovery_t *p_rd,
- vlc_renderer_item_t *p_item )
-{
- ActionsManager *self = reinterpret_cast<ActionsManager*>( p_rd->owner.sys );
- vlc_renderer_item_hold( p_item );
- self->emit rendererItemRemoved( p_item );
-}
-
-void ActionsManager::StartRendererScan()
-{
- m_stop_scan_timer.stop();
- if( m_scanning )
- return;
-
- /* SD subnodes */
- char **ppsz_longnames;
- char **ppsz_names;
- if( vlc_rd_get_names( THEPL, &ppsz_names, &ppsz_longnames ) != VLC_SUCCESS )
- return;
-
- struct vlc_renderer_discovery_owner owner =
- {
- this,
- renderer_event_item_added,
- renderer_event_item_removed,
- };
-
- char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
- for( ; *ppsz_name; ppsz_name++, ppsz_longname++ )
- {
- msg_Dbg( p_intf, "starting renderer discovery service %s", *ppsz_longname );
- vlc_renderer_discovery_t* p_rd = vlc_rd_new( VLC_OBJECT(p_intf), *ppsz_name, &owner );
- if( p_rd != NULL )
- m_rds.push_back( p_rd );
- free( *ppsz_name );
- free( *ppsz_longname );
- }
- free( ppsz_names );
- free( ppsz_longnames );
- m_scanning = true;
-}
-
-void ActionsManager::RendererMenuCountdown()
-{
- m_stop_scan_timer.start( 20000 );
-}
-
-void ActionsManager::StopRendererScan()
-{
- foreach ( vlc_renderer_discovery_t* p_rd, m_rds )
- vlc_rd_release( p_rd );
- m_rds.clear();
- m_scanning = false;
-}
-
-void ActionsManager::RendererSelected( QAction *selected )
-{
- QVariant data = selected->data();
- vlc_renderer_item_t *p_item = NULL;
- if (data.canConvert<QVariantHash>())
- {
- QVariantHash hash = data.value<QVariantHash>();
- if ( hash.contains( "sout" ) )
- p_item = reinterpret_cast<vlc_renderer_item_t*>(
- hash["sout"].value<void*>() );
- }
- // If we failed to convert the action data to a vlc_renderer_item_t,
- // assume the selected item was invalid, or most likely that "Local" was selected
- playlist_SetRenderer( THEPL, p_item );
-}
-
diff --git a/modules/gui/qt/actions_manager.hpp b/modules/gui/qt/actions_manager.hpp
index f82f6ee0aa..c244699d02 100644
--- a/modules/gui/qt/actions_manager.hpp
+++ b/modules/gui/qt/actions_manager.hpp
@@ -30,11 +30,8 @@
#include "qt.hpp"
#include "util/singleton.hpp"
-#include <QVector>
#include <QObject>
-#include <QTimer>
-class QAction;
typedef enum actionType_e
{
@@ -76,16 +73,6 @@ private:
virtual ~ActionsManager();
intf_thread_t* const p_intf;
- QVector<vlc_renderer_discovery_t*> m_rds;
- QTimer m_stop_scan_timer;
- bool m_scanning;
-
- static void renderer_event_item_added( vlc_renderer_discovery_t *,
- vlc_renderer_item_t * );
- static void renderer_event_item_removed( vlc_renderer_discovery_t *,
- vlc_renderer_item_t * );
- static vlc_renderer_item_t* getMatchingRenderer( const QVariant &m_obj,
- vlc_renderer_item_t* p_item );
public slots:
void toggleMuteAudio();
@@ -95,24 +82,14 @@ public slots:
void record();
void skipForward();
void skipBackward();
- void StartRendererScan();
- void RendererMenuCountdown();
- void StopRendererScan();
- void RendererSelected( QAction * );
protected slots:
- void onRendererItemAdded( vlc_renderer_item_t* );
- void onRendererItemRemoved( vlc_renderer_item_t* );
void fullscreen();
void snapshot();
void playlist();
void frame();
virtual void doAction( int );
-
-signals:
- void rendererItemAdded( vlc_renderer_item_t* );
- void rendererItemRemoved( vlc_renderer_item_t* );
};
#endif
diff --git a/modules/gui/qt/components/custom_menus.cpp b/modules/gui/qt/components/custom_menus.cpp
new file mode 100644
index 0000000000..c791d3da97
--- /dev/null
+++ b/modules/gui/qt/components/custom_menus.cpp
@@ -0,0 +1,198 @@
+/*****************************************************************************
+ * custom_menus.cpp : Qt custom menus classes
+ *****************************************************************************
+ * Copyright © 2006-2018 VideoLAN authors
+ * 2018 VideoLabs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_renderer_discovery.h>
+
+#include "custom_menus.hpp"
+#include "../managers/renderer_manager.hpp"
+
+#include <QMenu>
+#include <QAction>
+#include <QActionGroup>
+#include <QWidgetAction>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QProgressBar>
+
+RendererAction::RendererAction( vlc_renderer_item_t *p_item_ )
+ : QAction()
+{
+ p_item = p_item_;
+ vlc_renderer_item_hold( p_item );
+ if( vlc_renderer_item_flags( p_item ) & VLC_RENDERER_CAN_VIDEO )
+ setIcon( QIcon( ":/sidebar/movie.svg" ) );
+ else
+ setIcon( QIcon( ":/sidebar/music.svg" ) );
+ setText( vlc_renderer_item_name( p_item ) );
+ setCheckable(true);
+}
+
+RendererAction::~RendererAction()
+{
+ vlc_renderer_item_release( p_item );
+}
+
+vlc_renderer_item_t * RendererAction::getItem()
+{
+ return p_item;
+}
+
+RendererMenu::RendererMenu( QMenu *parent, intf_thread_t *p_intf_ )
+ : QMenu( parent ), p_intf( p_intf_ )
+{
+ setTitle( qtr("&Renderer") );
+
+ group = new QActionGroup( this );
+
+ QAction *action = new QAction( qtr("<Local>") );
+ action->setCheckable(true);
+ addAction( action );
+ group->addAction(action);
+
+ char *psz_renderer = var_InheritString( THEPL, "sout" );
+ if ( psz_renderer == NULL )
+ action->setChecked( true );
+ else
+ free( psz_renderer );
+
+ addSeparator();
+
+ QWidget *statusWidget = new QWidget();
+ statusWidget->setLayout( new QVBoxLayout );
+ QLabel *label = new QLabel();
+ label->setObjectName( "statuslabel" );
+ statusWidget->layout()->addWidget( label );
+ QProgressBar *pb = new QProgressBar();
+ pb->setObjectName( "statusprogressbar" );
+ pb->setMaximumHeight( 10 );
+ pb->setStyleSheet( QString("\
+ QProgressBar:horizontal {\
+ border: none;\
+ background: transparent;\
+ padding: 1px;\
+ }\
+ QProgressBar::chunk:horizontal {\
+ background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, \
+ stop: 0 white, stop: 0.4 orange, stop: 0.6 orange, stop: 1 white);\
+ }") );
+ pb->setRange( 0, 0 );
+ pb->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Maximum );
+ statusWidget->layout()->addWidget( pb );
+ QWidgetAction *qwa = new QWidgetAction( this );
+ qwa->setDefaultWidget( statusWidget );
+ qwa->setDisabled( true );
+ addAction( qwa );
+ status = qwa;
+
+ RendererManager *manager = RendererManager::getInstance( p_intf );
+ CONNECT( this, aboutToShow(), manager, StartScan() );
+ CONNECT( group, triggered(QAction*), this, RendererSelected( QAction* ) );
+ DCONNECT( manager, rendererItemAdded( vlc_renderer_item_t * ),
+ this, addRendererItem( vlc_renderer_item_t * ) );
+ DCONNECT( manager, rendererItemRemoved( vlc_renderer_item_t * ),
+ this, removeRendererItem( vlc_renderer_item_t * ) );
+ CONNECT( manager, statusUpdated( int ),
+ this, updateStatus( int ) );
+}
+
+RendererMenu::~RendererMenu()
+{
+ reset();
+}
+
+void RendererMenu::updateStatus( int val )
+{
+ QProgressBar *pb = findChild<QProgressBar *>("statusprogressbar");
+ QLabel *label = findChild<QLabel *>("statuslabel");
+ if( val >= RendererManager::RendererStatus::RUNNING )
+ {
+ label->setText( qtr("Scanning...").
+ append( QString(" (%1s)").arg( val ) ) );
+ pb->setVisible( true );
+ status->setVisible( true );
+ }
+ else if( val == RendererManager::RendererStatus::FAILED )
+ {
+ label->setText( "Failed (no discovery module available)" );
+ pb->setVisible( false );
+ status->setVisible( true );
+ }
+ else status->setVisible( false );
+}
+
+void RendererMenu::addRendererItem( vlc_renderer_item_t *p_item )
+{
+ QAction *action = new RendererAction( p_item );
+ insertAction( status, action );
+ group->addAction( action );
+}
+
+void RendererMenu::removeRendererItem( vlc_renderer_item_t *p_item )
+{
+ foreach (QAction* action, group->actions())
+ {
+ RendererAction *ra = qobject_cast<RendererAction *>( action );
+ if( !ra || ra->getItem() != p_item )
+ continue;
+ removeRendererAction( ra );
+ delete ra;
+ break;
+ }
+}
+
+void RendererMenu::addRendererAction(QAction *action)
+{
+ insertAction( status, action );
+ group->addAction( action );
+}
+
+void RendererMenu::removeRendererAction(QAction *action)
+{
+ removeAction( action );
+ group->removeAction( action );
+}
+
+void RendererMenu::reset()
+{
+ /* reset the list of renderers */
+ foreach (QAction* action, group->actions())
+ {
+ RendererAction *ra = qobject_cast<RendererAction *>( action );
+ if( ra )
+ {
+ removeRendererAction( ra );
+ delete ra;
+ }
+ }
+}
+
+void RendererMenu::RendererSelected(QAction *action)
+{
+ RendererAction *ra = qobject_cast<RendererAction *>( action );
+ if( ra )
+ RendererManager::getInstance( p_intf )->SelectRenderer( ra->getItem() );
+ else
+ RendererManager::getInstance( p_intf )->SelectRenderer( NULL );
+}
diff --git a/modules/gui/qt/components/custom_menus.hpp b/modules/gui/qt/components/custom_menus.hpp
new file mode 100644
index 0000000000..45c8c9039c
--- /dev/null
+++ b/modules/gui/qt/components/custom_menus.hpp
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * custom_menus.hpp : Qt custom menus classes
+ *****************************************************************************
+ * Copyright © 2006-2018 VideoLAN authors
+ * 2018 VideoLabs
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef CUSTOM_MENUS_HPP
+#define CUSTOM_MENUS_HPP
+
+#include "qt.hpp"
+
+#include <QMenu>
+
+class RendererAction : public QAction
+{
+ Q_OBJECT
+
+ public:
+ RendererAction( vlc_renderer_item_t * );
+ ~RendererAction();
+ vlc_renderer_item_t *getItem();
+
+ private:
+ vlc_renderer_item_t *p_item;
+};
+
+class RendererMenu : public QMenu
+{
+ Q_OBJECT
+
+public:
+ RendererMenu( QMenu *, intf_thread_t * );
+ virtual ~RendererMenu();
+ void reset();
+
+private slots:
+ void addRendererItem( vlc_renderer_item_t * );
+ void removeRendererItem( vlc_renderer_item_t * );
+ void updateStatus( int );
+ void RendererSelected( QAction* );
+
+private:
+ void addRendererAction( QAction * );
+ void removeRendererAction( QAction * );
+ static vlc_renderer_item_t* getMatchingRenderer( const QVariant &,
+ vlc_renderer_item_t* );
+ QAction *status;
+ QActionGroup *group;
+ intf_thread_t *p_intf;
+};
+
+
+#endif // CUSTOM_MENUS_HPP
diff --git a/modules/gui/qt/main_interface.cpp b/modules/gui/qt/main_interface.cpp
index 8b87e29e8f..0cb322bbcf 100644
--- a/modules/gui/qt/main_interface.cpp
+++ b/modules/gui/qt/main_interface.cpp
@@ -32,6 +32,7 @@
#include "main_interface.hpp"
#include "input_manager.hpp" // Creation
#include "actions_manager.hpp" // killInstance
+#include "managers/renderer_manager.hpp"
#include "util/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
#include "util/qt_dirs.hpp" // toNativeSeparators
@@ -280,6 +281,8 @@ MainInterface::~MainInterface()
/* Delete the FSC controller */
delete fullscreenControls;
+ RendererManager::killInstance();
+
/* Save states */
settings->beginGroup("MainWindow");
diff --git a/modules/gui/qt/managers/renderer_manager.cpp b/modules/gui/qt/managers/renderer_manager.cpp
new file mode 100644
index 0000000000..6a46270ad2
--- /dev/null
+++ b/modules/gui/qt/managers/renderer_manager.cpp
@@ -0,0 +1,170 @@
+#include "renderer_manager.hpp"
+
+#include <QApplication>
+
+const QEvent::Type RendererManagerEvent::AddedEvent =
+ (QEvent::Type)QEvent::registerEventType();
+const QEvent::Type RendererManagerEvent::RemovedEvent =
+ (QEvent::Type)QEvent::registerEventType();
+
+RendererManager::RendererManager( intf_thread_t *p_intf_ ) :
+ p_intf( p_intf_ ), p_selected_item( NULL )
+{
+ CONNECT( &m_stop_scan_timer, timeout(), this, RendererMenuCountdown() );
+}
+
+RendererManager::~RendererManager()
+{
+ StopScan();
+ foreach( ItemEntry entry, m_items )
+ {
+ emit rendererItemRemoved( entry.second );
+ vlc_renderer_item_release( entry.second );
+ }
+}
+
+void RendererManager::customEvent( QEvent *event )
+{
+ if( event->type() == RendererManagerEvent::AddedEvent ||
+ event->type() == RendererManagerEvent::RemovedEvent )
+ {
+ RendererManagerEvent *ev = static_cast<RendererManagerEvent *>(event);
+ QString souturi( vlc_renderer_item_sout( ev->getItem() ) );
+ vlc_renderer_item_t *p_item = ev->getItem();
+
+ if( event->type() == RendererManagerEvent::AddedEvent )
+ {
+ if( !m_items.contains( souturi ) )
+ {
+ vlc_renderer_item_hold( p_item );
+ ItemEntry entry( true, p_item );
+ m_items.insert( souturi, entry );
+ emit rendererItemAdded( p_item );
+ }
+ else /* incref for now */
+ {
+ ItemEntry &entry = m_items[ souturi ];
+ entry.first = true; /* to be kept */
+ }
+ }
+ else /* remove event */
+ {
+ if( m_items.contains( souturi ) )
+ {
+ p_item = m_items[ souturi ].second;
+ if( p_selected_item != p_item )
+ {
+ m_items.remove( souturi );
+ emit rendererItemRemoved( p_item );
+ vlc_renderer_item_release( p_item );
+ }
+ else m_items[ souturi ].first = true; /* keep */
+ }
+ /* else ignore */
+ }
+ }
+}
+
+void RendererManager::StartScan()
+{
+ if( m_stop_scan_timer.isActive() )
+ return;
+
+ /* SD subnodes */
+ char **ppsz_longnames;
+ char **ppsz_names;
+ if( vlc_rd_get_names( THEPL, &ppsz_names, &ppsz_longnames ) != VLC_SUCCESS )
+ {
+ emit statusUpdated( RendererManager::RendererStatus::FAILED );
+ return;
+ }
+
+ struct vlc_renderer_discovery_owner owner =
+ {
+ this,
+ renderer_event_item_added,
+ renderer_event_item_removed,
+ };
+
+ char **ppsz_name = ppsz_names, **ppsz_longname = ppsz_longnames;
+ for( ; *ppsz_name; ppsz_name++, ppsz_longname++ )
+ {
+ msg_Dbg( p_intf, "starting renderer discovery service %s", *ppsz_longname );
+ vlc_renderer_discovery_t* p_rd = vlc_rd_new( VLC_OBJECT(p_intf), *ppsz_name, &owner );
+ if( p_rd != NULL )
+ m_rds.push_back( p_rd );
+ free( *ppsz_name );
+ free( *ppsz_longname );
+ }
+ free( ppsz_names );
+ free( ppsz_longnames );
+
+ emit statusUpdated( RendererManager::RendererStatus::RUNNING );
+ m_scan_remain = 20000;
+ m_stop_scan_timer.setInterval( 1000 );
+ m_stop_scan_timer.start();
+}
+
+void RendererManager::StopScan()
+{
+ m_stop_scan_timer.stop();
+ foreach ( vlc_renderer_discovery_t* p_rd, m_rds )
+ vlc_rd_release( p_rd );
+ /* Cleanup of outdated items, and notify removal */
+ QHash<QString, ItemEntry>::iterator it = m_items.begin();
+ while ( it != m_items.end() )
+ {
+ ItemEntry &entry = it.value();
+ if( !entry.first /* don't keep */ && entry.second != p_selected_item )
+ {
+ emit rendererItemRemoved( entry.second );
+ vlc_renderer_item_release( entry.second );
+ it = m_items.erase( it );
+ }
+ else
+ {
+ entry.first = false; /* don't keep if not updated by new detect */
+ assert( it.value().first == false );
+ ++it;
+ }
+ }
+ m_rds.clear();
+ emit statusUpdated( RendererManager::RendererStatus::IDLE );
+}
+
+void RendererManager::RendererMenuCountdown()
+{
+ if( m_stop_scan_timer.isActive() && m_scan_remain > 0 )
+ {
+ m_scan_remain -= 1000;
+ emit statusUpdated( RendererManager::RendererStatus::RUNNING + m_scan_remain / 1000 );
+ }
+ else
+ {
+ StopScan();
+ }
+}
+
+void RendererManager::SelectRenderer( vlc_renderer_item_t *p_item )
+{
+ p_selected_item = p_item;
+ playlist_SetRenderer( THEPL, p_item );
+}
+
+void RendererManager::renderer_event_item_added( vlc_renderer_discovery_t* p_rd,
+ vlc_renderer_item_t *p_item )
+{
+ RendererManager *self = reinterpret_cast<RendererManager*>( p_rd->owner.sys );
+ QEvent *ev = new RendererManagerEvent( RendererManagerEvent::AddedEvent,
+ p_item );
+ QApplication::postEvent( self, ev );
+}
+
+void RendererManager::renderer_event_item_removed( vlc_renderer_discovery_t *p_rd,
+ vlc_renderer_item_t *p_item )
+{
+ RendererManager *self = reinterpret_cast<RendererManager*>( p_rd->owner.sys );
+ QEvent *ev = new RendererManagerEvent( RendererManagerEvent::RemovedEvent,
+ p_item );
+ QApplication::postEvent( self, ev );
+}
diff --git a/modules/gui/qt/managers/renderer_manager.hpp b/modules/gui/qt/managers/renderer_manager.hpp
new file mode 100644
index 0000000000..c8126761b0
--- /dev/null
+++ b/modules/gui/qt/managers/renderer_manager.hpp
@@ -0,0 +1,87 @@
+#ifndef RENDERER_MANAGER_HPP
+#define RENDERER_MANAGER_HPP
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qt.hpp"
+#include "util/singleton.hpp"
+
+#include <vlc_common.h>
+#include <vlc_renderer_discovery.h>
+
+#include <QObject>
+#include <QEvent>
+#include <QTimer>
+#include <QVector>
+#include <QHash>
+#include <QPair>
+
+class RendererManagerEvent : public QEvent
+{
+public:
+ static const QEvent::Type AddedEvent;
+ static const QEvent::Type RemovedEvent;
+
+ RendererManagerEvent( QEvent::Type type, vlc_renderer_item_t *p_item_ )
+ : QEvent( type ), p_item( p_item_ )
+ {
+ vlc_renderer_item_hold( p_item );
+ }
+ virtual ~RendererManagerEvent()
+ {
+ vlc_renderer_item_release( p_item );
+ }
+
+ vlc_renderer_item_t * getItem() const { return p_item; }
+
+private:
+ vlc_renderer_item_t *p_item;
+};
+
+class RendererManager : public QObject, public Singleton<RendererManager>
+{
+ Q_OBJECT
+ friend class Singleton<RendererManager>;
+
+public:
+ enum RendererStatus
+ {
+ FAILED = -2,
+ IDLE = -1,
+ RUNNING,
+ };
+ RendererManager( intf_thread_t * );
+ virtual ~RendererManager();
+ void customEvent( QEvent * );
+
+public slots:
+ void SelectRenderer( vlc_renderer_item_t * );
+ void StartScan();
+ void StopScan();
+
+signals:
+ void rendererItemAdded( vlc_renderer_item_t * ); /* For non queued only */
+ void rendererItemRemoved( vlc_renderer_item_t * ); /* For non queued only */
+ void statusUpdated( int );
+
+private:
+ static void renderer_event_item_added( vlc_renderer_discovery_t *,
+ vlc_renderer_item_t * );
+ static void renderer_event_item_removed( vlc_renderer_discovery_t *,
+ vlc_renderer_item_t * );
+
+ typedef std::pair<bool, vlc_renderer_item_t *> ItemEntry;
+ intf_thread_t* const p_intf;
+ const vlc_renderer_item_t *p_selected_item;
+ QVector<vlc_renderer_discovery_t*> m_rds;
+ QHash<QString, ItemEntry> m_items;
+ QTimer m_stop_scan_timer;
+ unsigned m_scan_remain;
+
+private slots:
+ void RendererMenuCountdown();
+};
+
+#endif // RENDERER_MANAGER_HPP
diff --git a/modules/gui/qt/menus.cpp b/modules/gui/qt/menus.cpp
index 14e07e4cd2..1f877cba58 100644
--- a/modules/gui/qt/menus.cpp
+++ b/modules/gui/qt/menus.cpp
@@ -80,8 +80,7 @@ enum
static QActionGroup *currentGroup;
QMenu *VLCMenuBar::recentsMenu = NULL;
-QMenu *VLCMenuBar::rendererMenu = NULL;
-QActionGroup *VLCMenuBar::rendererGroup = NULL;
+RendererMenu *VLCMenuBar::rendererMenu = NULL;
/**
* @brief Add static entries to DP in menus
@@ -733,10 +732,10 @@ QMenu *VLCMenuBar::NavigMenu( intf_thread_t *p_intf, QMenu *menu )
menu->addSeparator();
- if ( !rendererMenu )
- rendererMenu = RendererMenu( p_intf );
+ if ( !VLCMenuBar::rendererMenu )
+ VLCMenuBar::rendererMenu = new RendererMenu( menu, p_intf );
- menu->addMenu( rendererMenu );
+ menu->addMenu( VLCMenuBar::rendererMenu );
menu->addSeparator();
@@ -1630,33 +1629,3 @@ void VLCMenuBar::updateRecents( intf_thread_t *p_intf )
}
}
}
-
-QMenu *VLCMenuBar::RendererMenu(intf_thread_t *p_intf, QMenu *menu )
-{
- QMenu *submenu = new QMenu( qtr("&Renderer"), menu );
-
- 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("Scanning..."), submenu );
- action->setEnabled( false );
- submenu->addAction( action );
-
- CONNECT( submenu, aboutToShow(), ActionsManager::getInstance( p_intf ), StartRendererScan() );
- CONNECT( submenu, aboutToHide(), ActionsManager::getInstance( p_intf ), RendererMenuCountdown() );
- CONNECT( rendererGroup, triggered(QAction*), ActionsManager::getInstance( p_intf ), RendererSelected( QAction* ) );
-
- return submenu;
-}
diff --git a/modules/gui/qt/menus.hpp b/modules/gui/qt/menus.hpp
index 1bc6519d61..bfa0c818cc 100644
--- a/modules/gui/qt/menus.hpp
+++ b/modules/gui/qt/menus.hpp
@@ -27,6 +27,8 @@
#include "qt.hpp"
+#include "components/custom_menus.hpp"
+
#include <QObject>
#include <QMenu>
#include <QVector>
@@ -94,8 +96,7 @@ public:
};
Q_DECLARE_FLAGS(actionflags, actionflag)
- static QMenu *rendererMenu;
- static QActionGroup *rendererGroup;
+ static RendererMenu *rendererMenu;
private:
/* All main Menus */
@@ -131,7 +132,6 @@ private:
}
static QMenu *HelpMenu( QWidget * );
- static QMenu *RendererMenu(intf_thread_t *p_intf , QMenu *menu = NULL );
/* Popups Menus */
static void PopupMenuStaticEntries( QMenu *menu );
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 7683c437eb..4428605a9c 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -595,6 +595,8 @@ modules/gui/qt/components/controller.cpp
modules/gui/qt/components/controller.hpp
modules/gui/qt/components/controller_widget.cpp
modules/gui/qt/components/controller_widget.hpp
+modules/gui/qt/components/custom_menus.cpp
+modules/gui/qt/components/custom_menus.hpp
modules/gui/qt/components/epg/EPGChannels.cpp
modules/gui/qt/components/epg/EPGChannels.hpp
modules/gui/qt/components/epg/EPGItem.cpp
More information about the vlc-commits
mailing list