[vlc-devel] [PATCH 3/5] gui:qt: add a dialog to select the renderer to use
Steve Lhomme
robux4 at videolabs.io
Tue May 31 13:51:33 CEST 2016
limited to the first and only renderer discovery service we have for now
--
replaces https://patches.videolan.org/patch/13518/
---
modules/gui/qt/Makefile.am | 4 +
modules/gui/qt/dialogs/renderer.cpp | 257 ++++++++++++++++++++++++++++++++++++
modules/gui/qt/dialogs/renderer.hpp | 64 +++++++++
modules/gui/qt/dialogs_provider.cpp | 8 ++
modules/gui/qt/dialogs_provider.hpp | 3 +
modules/gui/qt/ui/renderer.ui | 54 ++++++++
6 files changed, 390 insertions(+)
create mode 100644 modules/gui/qt/dialogs/renderer.cpp
create mode 100644 modules/gui/qt/dialogs/renderer.hpp
create mode 100644 modules/gui/qt/ui/renderer.ui
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index b48e4ee..1911cb5 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -67,6 +67,7 @@ libqt_plugin_la_SOURCES = \
dialogs/podcast_configuration.cpp dialogs/podcast_configuration.hpp \
dialogs/extensions.cpp dialogs/extensions.hpp \
dialogs/fingerprintdialog.cpp dialogs/fingerprintdialog.hpp \
+ dialogs/renderer.cpp dialogs/renderer.hpp \
components/extended_panels.cpp components/extended_panels.hpp \
components/info_panels.cpp components/info_panels.hpp \
components/info_widgets.cpp components/info_widgets.hpp \
@@ -166,6 +167,7 @@ nodist_libqt_plugin_la_SOURCES = \
dialogs/firstrun.moc.cpp \
dialogs/extensions.moc.cpp \
dialogs/fingerprintdialog.moc.cpp \
+ dialogs/renderer.moc.cpp \
components/extended_panels.moc.cpp \
components/info_panels.moc.cpp \
components/info_widgets.moc.cpp \
@@ -223,6 +225,7 @@ nodist_libqt_plugin_la_SOURCES += \
ui/about.h \
ui/update.h \
ui/fingerprintdialog.h \
+ ui/renderer.h \
ui/sout.h
# User interface compilation
@@ -260,6 +263,7 @@ libqt_plugin_la_UI = \
ui/streampanel.ui \
ui/messages_panel.ui \
ui/about.ui \
+ ui/renderer.ui \
ui/update.ui \
ui/sout.ui \
ui/vlm.ui \
diff --git a/modules/gui/qt/dialogs/renderer.cpp b/modules/gui/qt/dialogs/renderer.cpp
new file mode 100644
index 0000000..37f5342
--- /dev/null
+++ b/modules/gui/qt/dialogs/renderer.cpp
@@ -0,0 +1,257 @@
+/*****************************************************************************
+ * renderer.cpp : Renderer output dialog
+ ****************************************************************************
+ * Copyright (C) 2015-2016 the VideoLAN team
+ *
+ * $Id$
+ *
+ * Authors: Steve Lhomme <robux4 at videolabs.io>
+ *
+ * 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 <QListWidget>
+#include <QListWidgetItem>
+#include <sstream>
+
+#include <vlc_common.h>
+#include <vlc_access.h>
+#include <vlc_renderer_discovery.h>
+#include <vlc_url.h>
+
+#include "dialogs/renderer.hpp"
+
+class RendererItem : public QListWidgetItem
+{
+public:
+ RendererItem(vlc_renderer_item *obj)
+ : QListWidgetItem( vlc_renderer_item_flags(obj) & VLC_RENDERER_CAN_VIDEO ? QIcon( ":/sidebar/movie" ) : QIcon( ":/sidebar/music" ),
+ qfu( vlc_renderer_item_name(obj) ))
+ {
+ m_obj = vlc_renderer_item_hold(obj);
+ }
+ ~RendererItem()
+ {
+ vlc_renderer_item_release(m_obj);
+ }
+
+ bool isItemSout( const char *psz_sout, bool as_output ) const;
+
+protected:
+ vlc_renderer_item* m_obj;
+
+ friend class RendererDialog;
+};
+
+void RendererDialog::renderer_event_received( const vlc_event_t * p_event, void * user_data )
+{
+ RendererDialog *p_this = reinterpret_cast<RendererDialog*>(user_data);
+ p_this->discoveryEventReceived( p_event );
+}
+
+RendererDialog::RendererDialog( intf_thread_t *_p_intf )
+ : QVLCDialog( (QWidget*)_p_intf->p_sys->p_mi, _p_intf )
+ , p_rd( NULL )
+ , b_rd_started( false )
+{
+ setWindowTitle( qtr( "Renderer Output" ) );
+ setWindowRole( "vlc-renderer" );
+
+ /* Build Ui */
+ ui.setupUi( this );
+
+ CONNECT( ui.buttonBox, accepted(), this, accept() );
+ CONNECT( ui.buttonBox, rejected(), this, onReject() );
+ CONNECT( ui.receiversListWidget, itemDoubleClicked(QListWidgetItem*), this, accept());
+
+ QVLCTools::restoreWidgetPosition( p_intf, "Renderer", this, QSize( 400 , 440 ) );
+}
+
+RendererDialog::~RendererDialog()
+{
+ if ( p_rd != NULL )
+ vlc_rd_release( p_rd );
+}
+
+void RendererDialog::onReject()
+{
+ setSout( NULL );
+
+ QVLCDialog::reject();
+}
+
+void RendererDialog::close()
+{
+ QVLCTools::saveWidgetPosition( p_intf, "Renderer", this );
+
+ QVLCDialog::close();
+}
+
+void RendererDialog::setVisible(bool visible)
+{
+ QVLCDialog::setVisible(visible);
+
+ if (visible)
+ {
+ /* 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 )
+ {
+ int row = -1;
+ char *psz_renderer = var_InheritString( THEPL, "sout" );
+ if ( psz_renderer != NULL )
+ {
+ for ( row = 0 ; row < ui.receiversListWidget->count(); row++ )
+ {
+ RendererItem *rowItem = reinterpret_cast<RendererItem*>( ui.receiversListWidget->item( row ) );
+ if ( rowItem->isItemSout( psz_renderer, false ) )
+ break;
+ }
+ if ( row == ui.receiversListWidget->count() )
+ row = -1;
+ free( psz_renderer );
+ }
+ ui.receiversListWidget->setCurrentRow( row );
+
+ if ( !b_rd_started )
+ {
+ vlc_event_manager_t *em = vlc_rd_event_manager( p_rd );
+ vlc_event_attach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, this );
+ vlc_event_attach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, this );
+
+ b_rd_started = vlc_rd_start( p_rd ) == VLC_SUCCESS;
+ if ( !b_rd_started )
+ {
+ vlc_event_detach( em, vlc_RendererDiscoveryItemAdded, renderer_event_received, this);
+ vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, this);
+ }
+ }
+ }
+ }
+ else
+ {
+ 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, this);
+ vlc_event_detach( em, vlc_RendererDiscoveryItemRemoved, renderer_event_received, this);
+
+ vlc_rd_stop( p_rd );
+ b_rd_started = false;
+ }
+ }
+ ui.receiversListWidget->clear();
+ }
+}
+
+void RendererDialog::accept()
+{
+ /* get the selected one in the listview if any */
+ QListWidgetItem *current = ui.receiversListWidget->currentItem();
+ if (current != NULL)
+ {
+ RendererItem *rowItem = reinterpret_cast<RendererItem*>(current);
+ msg_Dbg( p_intf, "selecting Renderer %s", vlc_renderer_item_name(rowItem->m_obj) );
+
+ setSout( rowItem->m_obj );
+ }
+
+ QVLCDialog::accept();
+}
+
+void RendererDialog::discoveryEventReceived( const vlc_event_t * p_event )
+{
+ if ( p_event->type == vlc_RendererDiscoveryItemAdded )
+ {
+ vlc_renderer_item *p_item = p_event->u.renderer_discovery_item_added.p_new_item;
+
+ int row = 0;
+ for ( ; row < ui.receiversListWidget->count(); row++ )
+ {
+ RendererItem *rowItem = reinterpret_cast<RendererItem*>( ui.receiversListWidget->item( row ) );
+ if ( rowItem->isItemSout( vlc_renderer_item_sout( p_item ), false ) )
+ return;
+ }
+
+ RendererItem *newItem = new RendererItem(p_item);
+ ui.receiversListWidget->addItem( newItem );
+
+ char *psz_renderer = var_InheritString( THEPL, "sout" );
+ if ( psz_renderer != NULL )
+ {
+ if ( newItem->isItemSout( psz_renderer, true ) )
+ ui.receiversListWidget->setCurrentItem( newItem );
+ free( psz_renderer );
+ }
+ }
+}
+
+void RendererDialog::setSout( const vlc_renderer_item *p_item )
+{
+ std::stringstream s_sout;
+ if ( p_item )
+ {
+ const char *psz_out = vlc_renderer_item_sout( p_item );
+ if ( psz_out )
+ s_sout << '#' << psz_out;
+ }
+
+ msg_Dbg( p_intf, "using sout: '%s'", s_sout.str().c_str() );
+ var_SetString( THEPL, "sout", s_sout.str().c_str() );
+}
+
+bool RendererItem::isItemSout( const char *psz_sout, bool as_output ) const
+{
+ std::stringstream s_sout;
+ if ( psz_sout == NULL )
+ psz_sout = "";
+ if ( m_obj )
+ {
+ const char *psz_out = vlc_renderer_item_sout( m_obj );
+ if ( likely( psz_out != NULL ) )
+ {
+ if ( as_output )
+ s_sout << '#';
+ s_sout << psz_out;
+ }
+ }
+ return s_sout.str() == psz_sout;
+}
diff --git a/modules/gui/qt/dialogs/renderer.hpp b/modules/gui/qt/dialogs/renderer.hpp
new file mode 100644
index 0000000..4090bfe
--- /dev/null
+++ b/modules/gui/qt/dialogs/renderer.hpp
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * renderer.hpp : Renderer output dialog
+ ****************************************************************************
+ * Copyright ( C ) 2015 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Steve Lhomme <robux4 at videolabs.io>
+ *
+ * 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 QVLC_RENDERER_DIALOG_H_
+#define QVLC_RENDERER_DIALOG_H_ 1
+
+#include "util/qvlcframe.hpp"
+#include "util/singleton.hpp"
+#include "ui/renderer.h"
+
+class MsgEvent;
+
+class RendererDialog : public QVLCDialog, public Singleton<RendererDialog>
+{
+ Q_OBJECT
+
+public:
+ void discoveryEventReceived( const vlc_event_t * p_event );
+ void setVisible(bool visible);
+
+private:
+ RendererDialog( intf_thread_t * );
+ virtual ~RendererDialog();
+
+ Ui::rendererWidget ui;
+ void sinkMessage( const MsgEvent * );
+
+private slots:
+ void accept();
+ void onReject();
+ void close();
+
+private:
+
+ friend class Singleton<RendererDialog>;
+ vlc_renderer_discovery *p_rd;
+ bool b_rd_started;
+ void setSout( const vlc_renderer_item *p_item );
+
+ static void renderer_event_received( const vlc_event_t * p_event, void * user_data );
+};
+
+
+#endif
diff --git a/modules/gui/qt/dialogs_provider.cpp b/modules/gui/qt/dialogs_provider.cpp
index 83d3487..1aabe1a 100644
--- a/modules/gui/qt/dialogs_provider.cpp
+++ b/modules/gui/qt/dialogs_provider.cpp
@@ -57,6 +57,7 @@
#include "dialogs/external.hpp"
#include "dialogs/epg.hpp"
#include "dialogs/errors.hpp"
+#include "dialogs/renderer.hpp"
#include <QEvent>
#include <QApplication>
@@ -153,6 +154,8 @@ void DialogsProvider::customEvent( QEvent *event )
bookmarksDialog(); break;
case INTF_DIALOG_EXTENDED:
extendedDialog(); break;
+ case INTF_DIALOG_RENDERER:
+ rendererDialog(); break;
case INTF_DIALOG_SENDKEY:
sendKey( de->i_arg ); break;
#ifdef ENABLE_VLM
@@ -234,6 +237,11 @@ void DialogsProvider::extendedDialog()
extDialog->hide();
}
+void DialogsProvider::rendererDialog()
+{
+ RendererDialog::getInstance( p_intf )->toggleVisible();
+}
+
void DialogsProvider::synchroDialog()
{
ExtendedDialog *extDialog = ExtendedDialog::getInstance(p_intf );
diff --git a/modules/gui/qt/dialogs_provider.hpp b/modules/gui/qt/dialogs_provider.hpp
index 01faa11..8de4fb5 100644
--- a/modules/gui/qt/dialogs_provider.hpp
+++ b/modules/gui/qt/dialogs_provider.hpp
@@ -124,6 +124,9 @@ public slots:
void mediaCodecDialog();
void prefsDialog();
void extendedDialog();
+#if defined(ENABLE_SOUT)
+ void rendererDialog();
+#endif
void synchroDialog();
void messagesDialog();
void sendKey( int key );
diff --git a/modules/gui/qt/ui/renderer.ui b/modules/gui/qt/ui/renderer.ui
new file mode 100644
index 0000000..67e7eda
--- /dev/null
+++ b/modules/gui/qt/ui/renderer.ui
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>rendererWidget</class>
+ <widget class="QWidget" name="rendererWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>570</width>
+ <height>440</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Renderer Output</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Available Renderers</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QListWidget" name="receiversListWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>1</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--
2.7.0.windows.1
More information about the vlc-devel
mailing list