[vlc-devel] [PATCH 1/3] qt: add audio devices model

Hugo Beauzée-Luyssen hugo at beauzee.fr
Thu Jul 4 13:47:58 CEST 2019


Hi,

On Wed, Jun 26, 2019, at 8:43 PM, Sagar Kohli wrote:
> ---
>  modules/gui/qt/Makefile.am                    |   3 +
>  .../gui/qt/components/audio_device_model.cpp  | 149 ++++++++++++++++++
>  .../gui/qt/components/audio_device_model.hpp  |  68 ++++++++
>  3 files changed, 220 insertions(+)
>  create mode 100644 modules/gui/qt/components/audio_device_model.cpp
>  create mode 100644 modules/gui/qt/components/audio_device_model.hpp
> 
> diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
> index 1503a93000..2c2d4feba2 100644
> --- a/modules/gui/qt/Makefile.am
> +++ b/modules/gui/qt/Makefile.am
> @@ -106,6 +106,8 @@ libqt_plugin_la_SOURCES = \
>  	gui/qt/components/controller_widget.hpp \
>  	gui/qt/components/recent_media_model.cpp  \
>  	gui/qt/components/recent_media_model.hpp \
> +	gui/qt/components/audio_device_model.cpp  \
> +	gui/qt/components/audio_device_model.hpp \
>  	gui/qt/components/voutwindow/videosurface.cpp \
>  	gui/qt/components/voutwindow/videosurface.hpp \
>  	gui/qt/components/voutwindow/qvoutwindow.cpp \
> @@ -258,6 +260,7 @@ nodist_libqt_plugin_la_SOURCES = \
>  	gui/qt/components/controller_widget.moc.cpp \
>  	gui/qt/components/custom_menus.moc.cpp \
>  	gui/qt/components/recent_media_model.moc.cpp \
> +	gui/qt/components/audio_device_model.moc.cpp \
>  	gui/qt/components/voutwindow/videosurface.moc.cpp \
>  	gui/qt/components/voutwindow/qvoutwindow.moc.cpp \
>  	gui/qt/components/voutwindow/qvoutwindowdummy.moc.cpp \
> diff --git a/modules/gui/qt/components/audio_device_model.cpp 
> b/modules/gui/qt/components/audio_device_model.cpp
> new file mode 100644
> index 0000000000..ba6501962f
> --- /dev/null
> +++ b/modules/gui/qt/components/audio_device_model.cpp
> @@ -0,0 +1,149 @@
> +/*****************************************************************************
> + * Copyright (C) 2019 VLC authors and VideoLAN
> + *
> + * 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.
> + 
> *****************************************************************************/
> +
> +#include "audio_device_model.hpp"
> +
> +extern "C" {
> +
> +static void on_player_aout_device_changed(vlc_player_t *,const char 
> *device, void *data)
> +{
> +    AudioDeviceModel* that = static_cast<AudioDeviceModel*>(data);
> +    QMetaObject::invokeMethod(that, [that, 
> device=QString::fromUtf8(device)](){
> +        that->updateCurrent(device);
> +    }, Qt::QueuedConnection, nullptr);
> +}
> +
> +}
> +
> +static const struct vlc_player_aout_cbs player_aout_cbs = {
> +    nullptr,
> +    nullptr,
> +    on_player_aout_device_changed
> +};
> +
> +AudioDeviceModel::AudioDeviceModel(vlc_player_t *player, QObject 
> *parent)
> +    : QAbstractListModel(parent)
> +    , m_player(player)
> +{
> +    {
> +        vlc_player_locker locker{m_player};
> +        m_player_aout_listener = vlc_player_aout_AddListener(m_player, 
> &player_aout_cbs, this);
> +    }
> +
> +    m_aout = vlc_player_aout_Hold(m_player);
> +
> +    m_inputs = aout_DevicesList(m_aout, &m_ids, &m_names); 

If this fails, m_ids & m_names values are undefined, also m_inputs will be negative, and I'm not sure how Qt will handle rowCount returning a negative value (hopefully it shouldn't be an issue)

> +
> +}
> +
> +AudioDeviceModel::~AudioDeviceModel()
> +{
> +    for(int i=0; i<m_inputs; i++){
> +        free(m_ids[i]);
> +        free(m_names[i]);
> +    }
> +
> +    free(m_ids);
> +    free(m_names);
> +
> +    vlc_player_locker locker{m_player};
> +    vlc_player_aout_RemoveListener(m_player, m_player_aout_listener);
> +
> +    aout_Release(m_aout);
> +
> +}
> +
> +Qt::ItemFlags AudioDeviceModel::flags(const QModelIndex &) const
> +{
> +    return Qt::ItemIsUserCheckable;
> +}
> +
> +int AudioDeviceModel::rowCount(const QModelIndex &parent) const
> +{
> +    if (parent.isValid())
> +        return 0;
> +
> +    return m_inputs;
> +}
> +
> +QVariant AudioDeviceModel::data(const QModelIndex &index, int role) 
> const
> +{
> +    int row = index.row();
> +    if (!index.isValid())
> +        return QVariant();
> +    if(row < 0 || row >= m_inputs)
> +        return QVariant();
> +
> +    const char *name = m_names[row];
> +    if (role == Qt::DisplayRole)
> +        return qfu(name);
> +    else if (role == Qt::CheckStateRole)
> +        return QVariant::fromValue<bool>((!m_current.isEmpty() && 
> (QString::fromUtf8(m_ids[row]) == m_current)) ||
> +            (m_current.isEmpty() && m_ids[row] && m_ids[row][0] == 
> '\0' )) ;

Can't this simply be "m_current == m_ids[row]" ?

> +
> +    return QVariant();
> +}
> +
> +bool AudioDeviceModel::setData(const QModelIndex &index, const 
> QVariant &value, int role)
> +{
> +    int row = index.row();

You need to check for index validity here as well I think

> +    if (role != Qt::CheckStateRole)
> +        return false;
> +    if (!value.canConvert<bool>())
> +        return false;
> +    bool select = value.toBool();
> +    if (select)
> +    {
> +        aout_DeviceSet(m_aout, m_ids[row]);
> +    }
> +    return true;
> +}
> +
> +void AudioDeviceModel::updateCurrent(QString current)
> +{
> +    if (current == m_current)
> +        return;
> +    QString oldCurrent = m_current;
> +    m_current = current;
> +

Nitpick, you could swap the 2 strings instead of copying

> +    int oldIndex = -1;
> +    int currentIndex = -1;
> +
> +    for(int i=0; i<m_inputs; i++)
> +    {
> +        if(QString::fromUtf8(m_ids[i]) == m_current){
> +            currentIndex = i;
> +        }
> +        if(QString::fromUtf8(m_ids[i]) == oldCurrent){
> +            oldIndex = i;
> +        }
> +    }
> +
> +    if(oldIndex >= 0)
> +        emit dataChanged(index(oldIndex), index(oldIndex), { 
> Qt::DisplayRole, Qt::CheckStateRole });
> +    if(currentIndex >= 0)
> +        emit dataChanged(index(currentIndex), index(currentIndex), { 
> Qt::DisplayRole, Qt::CheckStateRole });
> +}
> +
> +QHash<int, QByteArray> AudioDeviceModel::roleNames() const
> +{
> +    return QHash<int, QByteArray>{
> +        {Qt::DisplayRole, "display"},
> +        {Qt::CheckStateRole, "checked"}
> +    };
> +}
> diff --git a/modules/gui/qt/components/audio_device_model.hpp 
> b/modules/gui/qt/components/audio_device_model.hpp
> new file mode 100644
> index 0000000000..7305dcd641
> --- /dev/null
> +++ b/modules/gui/qt/components/audio_device_model.hpp
> @@ -0,0 +1,68 @@
> +/*****************************************************************************
> + * Copyright (C) 2019 VLC authors and VideoLAN
> + *
> + * 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 AUDIO_DEVICE_MODEL_HPP
> +#define AUDIO_DEVICE_MODEL_HPP
> +
> +#include <QAbstractListModel>
> +
> +#ifdef HAVE_CONFIG_H
> +

Nitpick, extra blank lines

> +# include "config.h"
> +
> +#endif
> +
> +
> +#include "qt.hpp"
> +#include <QObject>
> +#include <QStringList>
> +#include <vlc_aout.h>
> +
> +class AudioDeviceModel : public QAbstractListModel
> +{
> +    Q_OBJECT
> +
> +public:
> +    AudioDeviceModel(vlc_player_t *player, QObject *parent = nullptr);
> +
> +    ~AudioDeviceModel();
> +
> +    virtual Qt::ItemFlags flags(const QModelIndex &) const  override;
> +
> +    virtual int rowCount(const QModelIndex &parent = QModelIndex()) 
> const override;
> +
> +    virtual QVariant data(const QModelIndex &index, int role = 
> Qt::DisplayRole) const override;
> +
> +    virtual bool setData(const QModelIndex &index, const QVariant 
> &value, int role = Qt::EditRole) override;
> +        
> +    void updateCurrent(QString current);
> +        
> +    QHash<int, QByteArray> roleNames() const override;
> +
> +
> +private:
> +    int m_inputs;
> +    char **m_names;
> +    char **m_ids;
> +    QString m_current;
> +    vlc_player_aout_listener_id* m_player_aout_listener = nullptr;
> +    audio_output_t* m_aout = nullptr;
> +    vlc_player_t *m_player;
> +};
> +
> +#endif // AUDIO_DEVICE_MODEL_HPP
> -- 
> 2.17.1

Regards,

-- 
  Hugo Beauzée-Luyssen
  hugo at beauzee.fr


More information about the vlc-devel mailing list