[vlc-devel] [PATCH 1/3] qt: use shared pointers in menu items

RĂ©mi Denis-Courmont remi at remlab.net
Sun Mar 17 10:56:46 CET 2019


Use QSharedPointer shared pointers to reference VLC objects in
automatically generated menus. This enables using a custom callback
for releasing the reference to object of different types.
---
 modules/gui/qt/menus.cpp | 100 ++++++++++++++++++++++++++-------------
 modules/gui/qt/menus.hpp |  25 +++++-----
 2 files changed, 80 insertions(+), 45 deletions(-)

diff --git a/modules/gui/qt/menus.cpp b/modules/gui/qt/menus.cpp
index b102fa6902..1e7b34b386 100644
--- a/modules/gui/qt/menus.cpp
+++ b/modules/gui/qt/menus.cpp
@@ -80,6 +80,35 @@ static QActionGroup *currentGroup;
 QMenu *VLCMenuBar::recentsMenu = NULL;
 RendererMenu *VLCMenuBar::rendererMenu = NULL;
 
+static void releaseDummy(vlc_object_t *)
+{
+}
+
+static QVLCObject wrap(playlist_t *pl)
+{
+    return QVLCObject(VLC_OBJECT(pl), releaseDummy);
+}
+
+static QVLCObject wrap(intf_thread_t *intf)
+{
+    return QVLCObject(VLC_OBJECT(intf), releaseDummy);
+}
+
+static QVLCObject wrap(input_thread_t *input)
+{
+    return QVLCObject(VLC_OBJECT(input), releaseDummy);
+}
+
+static QVLCObject wrap(audio_output_t *aout)
+{
+    return QVLCObject(VLC_OBJECT(aout), releaseDummy);
+}
+
+static QVLCObject wrap(vout_thread_t *vout)
+{
+    return QVLCObject(VLC_OBJECT(vout), releaseDummy);
+}
+
 /**
  * @brief Add static entries to DP in menus
  **/
@@ -209,7 +238,7 @@ static QAction * FindActionWithVar( QMenu *menu, const char *psz_var )
 #define PUSH_OBJVAR(object,var) \
     do { \
         varnames.append(var); \
-        objects.append(VLC_OBJECT(object)); \
+        objects.append(wrap(object)); \
     } while (0)
 
 #define PUSH_VAR(var) PUSH_OBJVAR(p_object, var)
@@ -217,7 +246,7 @@ static QAction * FindActionWithVar( QMenu *menu, const char *psz_var )
 #define PUSH_PLVAR(var) PUSH_OBJVAR(pl, var)
 
 static int InputAutoMenuBuilder( input_thread_t *p_input,
-        QVector<vlc_object_t *> &objects, QVector<const char *> &varnames )
+        QVector<QVLCObject> &objects, QVector<const char *> &varnames )
 {
     PUSH_INPUTVAR( "bookmark" );
     PUSH_INPUTVAR( "title" );
@@ -228,7 +257,7 @@ static int InputAutoMenuBuilder( input_thread_t *p_input,
 }
 
 static int VideoAutoMenuBuilder( playlist_t *pl, input_thread_t *p_input,
-        QVector<vlc_object_t *> &objects, QVector<const char *> &varnames )
+        QVector<QVLCObject> &objects, QVector<const char *> &varnames )
 {
     vout_thread_t *p_object = p_input ? input_GetVout( p_input ) : NULL;
 
@@ -249,7 +278,7 @@ static int VideoAutoMenuBuilder( playlist_t *pl, input_thread_t *p_input,
 }
 
 static int SubsAutoMenuBuilder( input_thread_t *p_input,
-        QVector<vlc_object_t *> &objects, QVector<const char *> &varnames )
+        QVector<QVLCObject> &objects, QVector<const char *> &varnames )
 {
     PUSH_INPUTVAR( "spu-es" );
 
@@ -257,7 +286,7 @@ static int SubsAutoMenuBuilder( input_thread_t *p_input,
 }
 
 static int AudioAutoMenuBuilder( input_thread_t *p_input,
-        QVector<vlc_object_t *> &objects, QVector<const char *> &varnames )
+        QVector<QVLCObject> &objects, QVector<const char *> &varnames )
 {
     audio_output_t *p_object = p_input ? input_GetAout( p_input ) : NULL;
 
@@ -553,10 +582,10 @@ QMenu *VLCMenuBar::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterfac
  **/
 QMenu *VLCMenuBar::InterfacesMenu( intf_thread_t *p_intf, QMenu *current )
 {
-    QVector<vlc_object_t *> objects;
+    QVector<QVLCObject> objects;
     QVector<const char *> varnames;
     varnames.append( "intf-add" );
-    objects.append( VLC_OBJECT(p_intf) );
+    objects.append( wrap(p_intf) );
 
     return Populate( current, varnames, objects );
 }
@@ -605,7 +634,7 @@ static inline void VolumeEntries( intf_thread_t *p_intf, QMenu *current )
  **/
 QMenu *VLCMenuBar::AudioMenu( intf_thread_t *p_intf, QMenu * current )
 {
-    QVector<vlc_object_t *> objects;
+    QVector<QVLCObject> objects;
     QVector<const char *> varnames;
     QMenu *audioDeviceMenu;
     audio_output_t *p_aout;
@@ -646,7 +675,7 @@ QMenu *VLCMenuBar::AudioMenu( intf_thread_t *p_intf, QMenu * current )
 QMenu *VLCMenuBar::SubtitleMenu( intf_thread_t *p_intf, QMenu *current, bool b_popup )
 {
     input_thread_t *p_input;
-    QVector<vlc_object_t *> objects;
+    QVector<QVLCObject> objects;
     QVector<const char *> varnames;
 
     if( current->isEmpty() || b_popup )
@@ -670,7 +699,7 @@ QMenu *VLCMenuBar::SubtitleMenu( intf_thread_t *p_intf, QMenu *current, bool b_p
 QMenu *VLCMenuBar::VideoMenu( intf_thread_t *p_intf, QMenu *current )
 {
     input_thread_t *p_input;
-    QVector<vlc_object_t *> objects;
+    QVector<QVLCObject> objects;
     QVector<const char *> varnames;
 
     if( current->isEmpty() )
@@ -747,7 +776,7 @@ QMenu *VLCMenuBar::RebuildNavigMenu( intf_thread_t *p_intf, QMenu *menu, bool b_
 {
     /* */
     input_thread_t *p_object;
-    QVector<vlc_object_t *> objects;
+    QVector<QVLCObject> objects;
     QVector<const char *> varnames;
 
     /* Get the input and hold it */
@@ -802,7 +831,7 @@ QMenu *VLCMenuBar::HelpMenu( QWidget *parent )
  *****************************************************************************/
 #define POPUP_BOILERPLATE \
     QMenu* menu;  \
-    QVector<vlc_object_t *> objects; \
+    QVector<QVLCObject> objects; \
     QVector<const char *> varnames; \
     input_thread_t *p_input = THEMIM->getInput();
 
@@ -1020,6 +1049,7 @@ QMenu* VLCMenuBar::PopupMenu( intf_thread_t *p_intf, bool show )
 
     if( p_input )
     {
+        QVLCObject input = wrap(p_input);
         QMenu *submenu;
         vout_thread_t *p_vout = THEMIM->getVout();
 
@@ -1031,10 +1061,11 @@ QMenu* VLCMenuBar::PopupMenu( intf_thread_t *p_intf, bool show )
             b_isFullscreen = !( !val.b_bool );
             if( b_isFullscreen )
             {
+                QVLCObject playlist = wrap(THEPL);
                 val.b_bool = false;
                 CreateAndConnect( menu, "fullscreen",
                         qtr( "Leave Fullscreen" ),"" , ITEM_NORMAL,
-                        VLC_OBJECT(THEPL), val, VLC_VAR_BOOL, b_isFullscreen );
+                        playlist, val, VLC_VAR_BOOL, b_isFullscreen );
             }
             vout_Release(p_vout);
 
@@ -1062,7 +1093,7 @@ QMenu* VLCMenuBar::PopupMenu( intf_thread_t *p_intf, bool show )
         submenu = new QMenu( menu );
         action = menu->addMenu( SubtitleMenu( p_intf, submenu, true ) );
         action->setText( qtr( "Subti&tle") );
-        UpdateItem( submenu, "spu-es", VLC_OBJECT(p_input), true );
+        UpdateItem( submenu, "spu-es", input, true );
 
         /* Playback menu for chapters */
         submenu = new QMenu( menu );
@@ -1090,12 +1121,13 @@ QMenu* VLCMenuBar::PopupMenu( intf_thread_t *p_intf, bool show )
         /* In skins interface, append some items */
         if( p_intf->p_sys->b_isDialogProvider )
         {
-            vlc_object_t* p_object = vlc_object_parent(p_intf);
+            intf_thread_t *p_object =
+                (intf_thread_t *)vlc_object_parent(p_intf);
             submenu->setTitle( qtr( "Interface" ) );
 
             /* Open skin dialog box */
             objects.clear(); varnames.clear();
-            objects.append( p_object );
+            objects.append( wrap(p_object) );
             varnames.append( "intf-skins-interactive" );
             Populate( submenu, varnames, objects );
             QAction* action = submenu->actions().back();
@@ -1103,7 +1135,7 @@ QMenu* VLCMenuBar::PopupMenu( intf_thread_t *p_intf, bool show )
 
             /* list of skins available */
             objects.clear(); varnames.clear();
-            objects.append( p_object );
+            objects.append( wrap(p_object) );
             varnames.append( "intf-skins" );
             Populate( submenu, varnames, objects );
 
@@ -1206,7 +1238,7 @@ void VLCMenuBar::updateSystrayMenu( MainInterface *mi,
  *************************************************************************/
 QMenu * VLCMenuBar::Populate( QMenu *current,
                               QVector< const char *> & varnames,
-                              QVector<vlc_object_t *> & objects )
+                              QVector<QVLCObject> & objects )
 {
     QMenu *menu = current;
     assert( menu );
@@ -1244,7 +1276,7 @@ static bool IsMenuEmpty( const char *psz_var, vlc_object_t *p_object )
 #define TEXT_OR_VAR qfue ( text ? text : psz_var )
 
 void VLCMenuBar::UpdateItem( QMenu *menu,
-        const char *psz_var, vlc_object_t *p_object, bool b_submenu )
+        const char *psz_var, QVLCObject& p_object, bool b_submenu )
 {
     vlc_value_t val;
     char *text;
@@ -1271,7 +1303,7 @@ void VLCMenuBar::UpdateItem( QMenu *menu,
      || !strcmp( psz_var, "bookmark" ) )
         i_type = VLC_VAR_INTEGER | VLC_VAR_HASCHOICE;
     else
-        i_type = var_Type( p_object, psz_var );
+        i_type = var_Type( &*p_object, psz_var );
 
     switch( i_type & VLC_VAR_TYPE )
     {
@@ -1289,7 +1321,7 @@ void VLCMenuBar::UpdateItem( QMenu *menu,
     }
 
     /* Make sure we want to display the variable */
-    if( menu->isEmpty() && IsMenuEmpty( psz_var, p_object ) )
+    if( menu->isEmpty() && IsMenuEmpty( psz_var, &*p_object ) )
     {
         if( action )
             action->setEnabled( false );
@@ -1297,7 +1329,7 @@ void VLCMenuBar::UpdateItem( QMenu *menu,
     }
 
     /* Get the descriptive name of the variable */
-    if( var_Change( p_object, psz_var, VLC_VAR_GETTEXT, &text ) )
+    if( var_Change( &*p_object, psz_var, VLC_VAR_GETTEXT, &text ) )
         text = NULL;
 
     if( !action )
@@ -1339,11 +1371,11 @@ void VLCMenuBar::UpdateItem( QMenu *menu,
         case VLC_VAR_VOID:
             val.i_int = 0;  // Prevent the copy of an uninitialized value
             CreateAndConnect( menu, psz_var, TEXT_OR_VAR, "", ITEM_NORMAL,
-                    p_object, val, i_type );
+                              p_object, val, i_type );
             break;
 
         case VLC_VAR_BOOL:
-            var_Get( p_object, psz_var, &val );
+            var_Get( &*p_object, psz_var, &val );
             val.b_bool = !val.b_bool;
             CreateAndConnect( menu, psz_var, TEXT_OR_VAR, "", ITEM_CHECK,
                     p_object, val, i_type, !val.b_bool );
@@ -1369,7 +1401,7 @@ static bool CheckTitle( vlc_object_t *p_object, const char *psz_var )
 
 
 int VLCMenuBar::CreateChoicesMenu( QMenu *submenu, const char *psz_var,
-                                   vlc_object_t *p_object )
+                                   QVLCObject& p_object )
 {
     vlc_value_t val;
     vlc_value_t *val_list;
@@ -1378,10 +1410,10 @@ int VLCMenuBar::CreateChoicesMenu( QMenu *submenu, const char *psz_var,
     int i_type;
 
     /* Check the type of the object variable */
-    i_type = var_Type( p_object, psz_var );
+    i_type = var_Type( &*p_object, psz_var );
 
     /* Make sure we want to display the variable */
-    if( submenu->isEmpty() && IsMenuEmpty( psz_var, p_object ) )
+    if( submenu->isEmpty() && IsMenuEmpty( psz_var, &*p_object ) )
         return VLC_EGENERIC;
 
     switch( i_type & VLC_VAR_TYPE )
@@ -1397,7 +1429,7 @@ int VLCMenuBar::CreateChoicesMenu( QMenu *submenu, const char *psz_var,
             return VLC_EGENERIC;
     }
 
-    if( var_Change( p_object, psz_var, VLC_VAR_GETCHOICES,
+    if( var_Change( &*p_object, psz_var, VLC_VAR_GETCHOICES,
                     &count, &val_list, &text_list ) < 0 )
     {
         return VLC_EGENERIC;
@@ -1415,7 +1447,7 @@ int VLCMenuBar::CreateChoicesMenu( QMenu *submenu, const char *psz_var,
         switch( i_type & VLC_VAR_TYPE )
         {
             case VLC_VAR_STRING:
-                var_Get( p_object, psz_var, &val );
+                var_Get( &*p_object, psz_var, &val );
                 another_val.psz_string = strdup( CURVAL.psz_string );
                 menutext = qfue( CURTEXT ? CURTEXT : another_val.psz_string );
                 CreateAndConnect( submenu, psz_var, menutext, "", RADIO_OR_COMMAND,
@@ -1427,17 +1459,17 @@ int VLCMenuBar::CreateChoicesMenu( QMenu *submenu, const char *psz_var,
                 break;
 
             case VLC_VAR_INTEGER:
-                var_Get( p_object, psz_var, &val );
+                var_Get( &*p_object, psz_var, &val );
                 if( CURTEXT ) menutext = qfue( CURTEXT );
                 else menutext = QString::number( CURVAL.i_int );
                 CreateAndConnect( submenu, psz_var, menutext, "", RADIO_OR_COMMAND,
                         p_object, CURVAL, i_type,
                         ( CURVAL.i_int == val.i_int )
-                        && CheckTitle( p_object, psz_var ) );
+                        && CheckTitle( &*p_object, psz_var ) );
                 break;
 
             case VLC_VAR_FLOAT:
-                var_Get( p_object, psz_var, &val );
+                var_Get( &*p_object, psz_var, &val );
                 if( CURTEXT ) menutext = qfue( CURTEXT );
                 else menutext.sprintf( "%.2f", CURVAL.f_float );
                 CreateAndConnect( submenu, psz_var, menutext, "", RADIO_OR_COMMAND,
@@ -1465,7 +1497,7 @@ int VLCMenuBar::CreateChoicesMenu( QMenu *submenu, const char *psz_var,
 
 void VLCMenuBar::CreateAndConnect( QMenu *menu, const char *psz_var,
         const QString& text, const QString& help,
-        int i_item_type, vlc_object_t *p_obj,
+        int i_item_type, QVLCObject& p_obj,
         vlc_value_t val, int i_val_type,
         bool checked )
 {
@@ -1513,7 +1545,7 @@ void VLCMenuBar::CreateAndConnect( QMenu *menu, const char *psz_var,
 void VLCMenuBar::DoAction( QObject *data )
 {
     MenuItemData *itemData = qobject_cast<MenuItemData *>( data );
-    vlc_object_t *p_object = itemData->p_obj;
+    vlc_object_t *p_object =&*itemData->obj;
     if( p_object == NULL ) return;
     const char *var = itemData->psz_var;
     vlc_value_t val = itemData->val;
diff --git a/modules/gui/qt/menus.hpp b/modules/gui/qt/menus.hpp
index 536e178c79..ca24c5f8e3 100644
--- a/modules/gui/qt/menus.hpp
+++ b/modules/gui/qt/menus.hpp
@@ -31,18 +31,21 @@
 #include <QObject>
 #include <QMenu>
 #include <QVector>
+#include <QSharedPointer>
+
+typedef QSharedPointer<vlc_object_t> QVLCObject;
 
 class MenuItemData : public QObject
 {
     Q_OBJECT
 
 public:
-    MenuItemData( QObject* parent, vlc_object_t *_p_obj, int _i_type,
+    MenuItemData( QObject* parent, QVLCObject& obj, int _i_type,
                   vlc_value_t _val, const char *_var ) : QObject( parent )
     {
-        p_obj = _p_obj;
-        if( p_obj )
-            vlc_object_hold( p_obj );
+        this->obj = obj;
+        if( obj )
+            vlc_object_hold( &*obj );
         i_val_type = _i_type;
         val = _val;
         psz_var = strdup( _var );
@@ -52,11 +55,11 @@ public:
         free( psz_var );
         if( ( i_val_type & VLC_VAR_TYPE) == VLC_VAR_STRING )
             free( val.psz_string );
-        if( p_obj )
-            vlc_object_release( p_obj );
+        if( obj )
+            vlc_object_release( &*obj );
     }
 
-    vlc_object_t *p_obj;
+    QVLCObject obj;
     vlc_value_t val;
     char *psz_var;
 
@@ -143,13 +146,13 @@ private:
 
     /* Generic automenu methods */
     static QMenu * Populate( QMenu *current,
-                             QVector<const char*>&, QVector<vlc_object_t *>& );
+                             QVector<const char*>&, QVector<QVLCObject>& );
 
     static void CreateAndConnect( QMenu *, const char *, const QString&,
-                                  const QString&, int, vlc_object_t *,
+                                  const QString&, int, QVLCObject& ,
                                   vlc_value_t, int, bool c = false );
-    static void UpdateItem( QMenu *, const char *, vlc_object_t *, bool );
-    static int CreateChoicesMenu( QMenu *,const char *, vlc_object_t * );
+    static void UpdateItem( QMenu *, const char *, QVLCObject&, bool );
+    static int CreateChoicesMenu( QMenu *,const char *, QVLCObject& );
     static void EnableStaticEntries( QMenu *, bool );
 
     /* recentMRL menu */
-- 
2.20.1



More information about the vlc-devel mailing list