From 28aa5aab6deca5d1b65d9d4de075dce827f4f282 Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Thu, 18 Mar 2021 16:10:09 -0400
Subject: [PATCH] settings: use default audio devices

Refactors audio settings to avoid list model code duplication. This code
could be greatly simplified by using string lists, however the combo-box
component design is highly dependent on QAbstractItemModel based models.

Also translates the handlebarred strings upon presentation, which is
currently used to translate the "Default" prefix for the first device
item.

Gitlab: #346
Change-Id: I5ed282d29cc4ec6a090a9cdf47b0459f0db2a99b
---
 CMakeLists.txt                                |   6 +-
 jami-qt.pro                                   |   6 +-
 src/audiodevicemodel.cpp                      | 123 +++++++++++++++
 ...oinputdevicemodel.h => audiodevicemodel.h} |  49 +++---
 src/audioinputdevicemodel.cpp                 | 128 ----------------
 src/audiooutputdevicemodel.cpp                | 142 ------------------
 src/audiooutputdevicemodel.h                  |  66 --------
 src/commoncomponents/SettingParaCombobox.qml  |   5 +-
 src/qmlregister.cpp                           |   6 +-
 src/settingsview/components/AudioSettings.qml |  56 +++----
 10 files changed, 177 insertions(+), 410 deletions(-)
 create mode 100644 src/audiodevicemodel.cpp
 rename src/{audioinputdevicemodel.h => audiodevicemodel.h} (57%)
 delete mode 100644 src/audioinputdevicemodel.cpp
 delete mode 100644 src/audiooutputdevicemodel.cpp
 delete mode 100644 src/audiooutputdevicemodel.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d4b076432..5fb237d84 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,9 +58,8 @@ set(COMMON_SOURCES
     ${SRC_DIR}/preferenceitemlistmodel.cpp
     ${SRC_DIR}/mediacodeclistmodel.cpp
     ${SRC_DIR}/accountstomigratelistmodel.cpp
-    ${SRC_DIR}/audioinputdevicemodel.cpp
+    ${SRC_DIR}/audiodevicemodel.cpp
     ${SRC_DIR}/videoinputdevicemodel.cpp
-    ${SRC_DIR}/audiooutputdevicemodel.cpp
     ${SRC_DIR}/pluginlistpreferencemodel.cpp
     ${SRC_DIR}/videoformatfpsmodel.cpp
     ${SRC_DIR}/videoformatresolutionmodel.cpp
@@ -109,9 +108,8 @@ set(COMMON_HEADERS
     ${SRC_DIR}/preferenceitemlistmodel.h
     ${SRC_DIR}/mediacodeclistmodel.h
     ${SRC_DIR}/accountstomigratelistmodel.h
-    ${SRC_DIR}/audioinputdevicemodel.h
+    ${SRC_DIR}/audiodevicemodel.h
     ${SRC_DIR}/videoinputdevicemodel.h
-    ${SRC_DIR}/audiooutputdevicemodel.h
     ${SRC_DIR}/pluginlistpreferencemodel.h
     ${SRC_DIR}/videoformatfpsmodel.h
     ${SRC_DIR}/videoformatresolutionmodel.h
diff --git a/jami-qt.pro b/jami-qt.pro
index cd3e9ce3a..871f2ab54 100644
--- a/jami-qt.pro
+++ b/jami-qt.pro
@@ -200,9 +200,8 @@ HEADERS += \
         src/preferenceitemlistmodel.h \
         src/mediacodeclistmodel.h \
         src/accountstomigratelistmodel.h \
-        src/audioinputdevicemodel.h \
+        src/audiodevicemodel.h \
         src/videoinputdevicemodel.h \
-        src/audiooutputdevicemodel.h \
         src/pluginlistpreferencemodel.h \
         src/videoformatfpsmodel.h \
         src/videoformatresolutionmodel.h \
@@ -242,9 +241,8 @@ SOURCES += \
         src/preferenceitemlistmodel.cpp \
         src/mediacodeclistmodel.cpp \
         src/accountstomigratelistmodel.cpp \
-        src/audioinputdevicemodel.cpp \
+        src/audiodevicemodel.cpp \
         src/videoinputdevicemodel.cpp \
-        src/audiooutputdevicemodel.cpp \
         src/pluginlistpreferencemodel.cpp \
         src/videoformatfpsmodel.cpp \
         src/videoformatresolutionmodel.cpp \
diff --git a/src/audiodevicemodel.cpp b/src/audiodevicemodel.cpp
new file mode 100644
index 000000000..83c4168e5
--- /dev/null
+++ b/src/audiodevicemodel.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2021 by Savoir-faire Linux
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "audiodevicemodel.h"
+
+#include "lrcinstance.h"
+
+AudioDeviceModel::AudioDeviceModel(QObject* parent)
+    : QAbstractListModel(parent)
+{
+    connect(this, &AudioDeviceModel::typeChanged, this, &AudioDeviceModel::reset);
+}
+
+int
+AudioDeviceModel::rowCount(const QModelIndex& parent) const
+{
+    if (!parent.isValid()) {
+        return devices_.size();
+    }
+    return 0;
+}
+
+int
+AudioDeviceModel::columnCount(const QModelIndex& parent) const
+{
+    Q_UNUSED(parent);
+    return 1;
+}
+
+QVariant
+AudioDeviceModel::data(const QModelIndex& index, int role) const
+{
+    if (!index.isValid() || devices_.size() <= index.row()) {
+        return QVariant();
+    }
+
+    switch (role) {
+    case Qt::DisplayRole:
+    case Role::DeviceName: {
+        auto deviceName = devices_.at(index.row());
+        QRegularExpression re("{{(.*?)}}");
+        QRegularExpressionMatch match = re.match(deviceName);
+        if (match.hasMatch() && re.captureCount() > 0) {
+            deviceName.replace(match.captured(0), QObject::tr(match.captured(1).toUtf8()));
+        }
+        return QVariant(deviceName.toUtf8());
+    }
+    case Role::RawDeviceName:
+        return QVariant(devices_.at(index.row()));
+    default:
+        break;
+    }
+    return QVariant();
+}
+
+QHash<int, QByteArray>
+AudioDeviceModel::roleNames() const
+{
+    QHash<int, QByteArray> roles;
+    roles[DeviceName] = "DeviceName";
+    roles[RawDeviceName] = "RawDeviceName";
+    return roles;
+}
+
+QModelIndex
+AudioDeviceModel::index(int row, int column, const QModelIndex&) const
+{
+    if (column != 0) {
+        return QModelIndex();
+    }
+    if (row >= 0 && row < rowCount()) {
+        return createIndex(row, column);
+    }
+    return QModelIndex();
+}
+
+QModelIndex
+AudioDeviceModel::parent(const QModelIndex&) const
+{
+    return QModelIndex();
+}
+
+Qt::ItemFlags
+AudioDeviceModel::flags(const QModelIndex& index) const
+{
+    auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
+    if (!index.isValid()) {
+        return QAbstractItemModel::flags(index);
+    }
+    return flags;
+}
+
+void
+AudioDeviceModel::reset()
+{
+    beginResetModel();
+    devices_ = type_ == Type::Record ? LRCInstance::avModel().getAudioInputDevices()
+                                     : LRCInstance::avModel().getAudioOutputDevices();
+    endResetModel();
+}
+
+int
+AudioDeviceModel::getCurrentIndex()
+{
+    QString currentId = LRCInstance::avModel().getInputDevice();
+    auto resultList = match(index(0, 0), Qt::DisplayRole, QVariant(currentId));
+    return resultList.size() > 0 ? resultList[0].row() : 0;
+}
diff --git a/src/audioinputdevicemodel.h b/src/audiodevicemodel.h
similarity index 57%
rename from src/audioinputdevicemodel.h
rename to src/audiodevicemodel.h
index 5593beb2f..c4ec427e6 100644
--- a/src/audioinputdevicemodel.h
+++ b/src/audiodevicemodel.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
+ * Copyright (C) 2021 by Savoir-faire Linux
+ * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
  *
  * 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
@@ -20,22 +20,23 @@
 
 #include <QAbstractItemModel>
 
-#include "api/account.h"
-#include "api/contact.h"
-#include "api/conversation.h"
-#include "api/newdevicemodel.h"
-
-#include "lrcinstance.h"
-
-class AudioInputDeviceModel : public QAbstractListModel
+class AudioDeviceModel : public QAbstractListModel
 {
     Q_OBJECT
 public:
-    enum Role { Device_ID = Qt::UserRole + 1, ID_UTF8 };
+    enum class Type { Invalid, Record, Playback, Ringtone };
+    Q_ENUM(Type)
+    Q_PROPERTY(Type type MEMBER type_ NOTIFY typeChanged)
+
+    enum Role { DeviceName = Qt::UserRole + 1, RawDeviceName };
     Q_ENUM(Role)
 
-    explicit AudioInputDeviceModel(QObject* parent = 0);
-    ~AudioInputDeviceModel();
+signals:
+    void typeChanged();
+
+public:
+    explicit AudioDeviceModel(QObject* parent = 0);
+    ~AudioDeviceModel() = default;
 
     /*
      * QAbstractListModel override.
@@ -43,20 +44,22 @@ public:
     int rowCount(const QModelIndex& parent = QModelIndex()) const override;
     int columnCount(const QModelIndex& parent) const override;
     QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+
     /*
      * Override role name as access point in qml.
      */
     QHash<int, QByteArray> roleNames() const override;
-    QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const;
-    QModelIndex parent(const QModelIndex& child) const;
-    Qt::ItemFlags flags(const QModelIndex& index) const;
+    QModelIndex index(int row,
+                      int column = 0,
+                      const QModelIndex& parent = QModelIndex()) const override;
+    QModelIndex parent(const QModelIndex& child) const override;
+    Qt::ItemFlags flags(const QModelIndex& index) const override;
 
-    /*
-     * This function is to reset the model when there's new account added.
-     */
     Q_INVOKABLE void reset();
-    /*
-     * This function is to get the current device id in the demon.
-     */
-    Q_INVOKABLE int getCurrentSettingIndex();
+    Q_INVOKABLE int getCurrentIndex();
+
+private:
+    QVector<QString> devices_;
+
+    Type type_ {Type::Invalid};
 };
diff --git a/src/audioinputdevicemodel.cpp b/src/audioinputdevicemodel.cpp
deleted file mode 100644
index df491ad8b..000000000
--- a/src/audioinputdevicemodel.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "audioinputdevicemodel.h"
-
-AudioInputDeviceModel::AudioInputDeviceModel(QObject* parent)
-    : QAbstractListModel(parent)
-{}
-
-AudioInputDeviceModel::~AudioInputDeviceModel() {}
-
-int
-AudioInputDeviceModel::rowCount(const QModelIndex& parent) const
-{
-    if (!parent.isValid()) {
-        /*
-         * Count.
-         */
-        return LRCInstance::avModel().getAudioInputDevices().size();
-    }
-    /*
-     * A valid QModelIndex returns 0 as no entry has sub-elements.
-     */
-    return 0;
-}
-
-int
-AudioInputDeviceModel::columnCount(const QModelIndex& parent) const
-{
-    Q_UNUSED(parent);
-    /*
-     * Only need one column.
-     */
-    return 1;
-}
-
-QVariant
-AudioInputDeviceModel::data(const QModelIndex& index, int role) const
-{
-    auto deviceList = LRCInstance::avModel().getAudioInputDevices();
-    if (!index.isValid() || deviceList.size() <= index.row()) {
-        return QVariant();
-    }
-
-    switch (role) {
-    case Role::Device_ID:
-        return QVariant(deviceList.at(index.row()));
-    case Role::ID_UTF8:
-        return QVariant(deviceList.at(index.row()).toUtf8());
-    }
-    return QVariant();
-}
-
-QHash<int, QByteArray>
-AudioInputDeviceModel::roleNames() const
-{
-    QHash<int, QByteArray> roles;
-    roles[Device_ID] = "Device_ID";
-    roles[ID_UTF8] = "ID_UTF8";
-    return roles;
-}
-
-QModelIndex
-AudioInputDeviceModel::index(int row, int column, const QModelIndex& parent) const
-{
-    Q_UNUSED(parent);
-    if (column != 0) {
-        return QModelIndex();
-    }
-
-    if (row >= 0 && row < rowCount()) {
-        return createIndex(row, column);
-    }
-    return QModelIndex();
-}
-
-QModelIndex
-AudioInputDeviceModel::parent(const QModelIndex& child) const
-{
-    Q_UNUSED(child);
-    return QModelIndex();
-}
-
-Qt::ItemFlags
-AudioInputDeviceModel::flags(const QModelIndex& index) const
-{
-    auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
-    if (!index.isValid()) {
-        return QAbstractItemModel::flags(index);
-    }
-    return flags;
-}
-
-void
-AudioInputDeviceModel::reset()
-{
-    beginResetModel();
-    endResetModel();
-}
-
-int
-AudioInputDeviceModel::getCurrentSettingIndex()
-{
-    QString currentId = LRCInstance::avModel().getInputDevice();
-    auto resultList = match(index(0, 0), Device_ID, QVariant(currentId));
-
-    int resultRowIndex = 0;
-    if (resultList.size() > 0) {
-        resultRowIndex = resultList[0].row();
-    }
-
-    return resultRowIndex;
-}
diff --git a/src/audiooutputdevicemodel.cpp b/src/audiooutputdevicemodel.cpp
deleted file mode 100644
index fc3c92a24..000000000
--- a/src/audiooutputdevicemodel.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-
-#include "audiooutputdevicemodel.h"
-
-AudioOutputDeviceModel::AudioOutputDeviceModel(QObject* parent)
-    : QAbstractListModel(parent)
-{}
-
-AudioOutputDeviceModel::~AudioOutputDeviceModel() {}
-
-int
-AudioOutputDeviceModel::rowCount(const QModelIndex& parent) const
-{
-    if (!parent.isValid()) {
-        /*
-         * Count.
-         */
-        return LRCInstance::avModel().getAudioOutputDevices().size();
-    }
-    /*
-     * A valid QModelIndex returns 0 as no entry has sub-elements.
-     */
-    return 0;
-}
-
-int
-AudioOutputDeviceModel::columnCount(const QModelIndex& parent) const
-{
-    Q_UNUSED(parent);
-    /*
-     * Only need one column.
-     */
-    return 1;
-}
-
-QVariant
-AudioOutputDeviceModel::data(const QModelIndex& index, int role) const
-{
-    auto deviceList = LRCInstance::avModel().getAudioOutputDevices();
-    if (!index.isValid() || deviceList.size() <= index.row()) {
-        return QVariant();
-    }
-
-    switch (role) {
-    case Role::Device_ID:
-        return QVariant(deviceList.at(index.row()));
-    case Role::ID_UTF8:
-        return QVariant(deviceList.at(index.row()).toUtf8());
-    }
-    return QVariant();
-}
-
-QHash<int, QByteArray>
-AudioOutputDeviceModel::roleNames() const
-{
-    QHash<int, QByteArray> roles;
-    roles[Device_ID] = "Device_ID";
-    roles[ID_UTF8] = "ID_UTF8";
-    return roles;
-}
-
-QModelIndex
-AudioOutputDeviceModel::index(int row, int column, const QModelIndex& parent) const
-{
-    Q_UNUSED(parent);
-    if (column != 0) {
-        return QModelIndex();
-    }
-
-    if (row >= 0 && row < rowCount()) {
-        return createIndex(row, column);
-    }
-    return QModelIndex();
-}
-
-QModelIndex
-AudioOutputDeviceModel::parent(const QModelIndex& child) const
-{
-    Q_UNUSED(child);
-    return QModelIndex();
-}
-
-Qt::ItemFlags
-AudioOutputDeviceModel::flags(const QModelIndex& index) const
-{
-    auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
-    if (!index.isValid()) {
-        return QAbstractItemModel::flags(index);
-    }
-    return flags;
-}
-
-void
-AudioOutputDeviceModel::reset()
-{
-    beginResetModel();
-    endResetModel();
-}
-
-int
-AudioOutputDeviceModel::getCurrentSettingIndex()
-{
-    QString currentId = LRCInstance::avModel().getOutputDevice();
-    auto resultList = match(index(0, 0), Device_ID, QVariant(currentId));
-
-    int resultRowIndex = 0;
-    if (resultList.size() > 0) {
-        resultRowIndex = resultList[0].row();
-    }
-
-    return resultRowIndex;
-}
-
-int
-AudioOutputDeviceModel::getCurrentRingtoneDeviceIndex()
-{
-    QString currentId = LRCInstance::avModel().getRingtoneDevice();
-    auto resultList = match(index(0, 0), Device_ID, QVariant(currentId));
-
-    int resultRowIndex = 0;
-    if (resultList.size() > 0) {
-        resultRowIndex = resultList[0].row();
-    }
-
-    return resultRowIndex;
-}
diff --git a/src/audiooutputdevicemodel.h b/src/audiooutputdevicemodel.h
deleted file mode 100644
index a615869d4..000000000
--- a/src/audiooutputdevicemodel.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2019-2020 by Savoir-faire Linux
- * Author: Yang Wang   <yang.wang@savoirfairelinux.com>
- *
- * 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 3 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, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <QAbstractItemModel>
-
-#include "api/account.h"
-#include "api/contact.h"
-#include "api/conversation.h"
-#include "api/newdevicemodel.h"
-
-#include "lrcinstance.h"
-
-class AudioOutputDeviceModel : public QAbstractListModel
-{
-    Q_OBJECT
-public:
-    enum Role { Device_ID = Qt::UserRole + 1, ID_UTF8 };
-    Q_ENUM(Role)
-
-    explicit AudioOutputDeviceModel(QObject* parent = 0);
-    ~AudioOutputDeviceModel();
-
-    /*
-     * QAbstractListModel override.
-     */
-    int rowCount(const QModelIndex& parent = QModelIndex()) const override;
-    int columnCount(const QModelIndex& parent) const override;
-    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
-    /*
-     * Override role name as access point in qml.
-     */
-    QHash<int, QByteArray> roleNames() const override;
-    QModelIndex index(int row, int column = 0, const QModelIndex& parent = QModelIndex()) const;
-    QModelIndex parent(const QModelIndex& child) const;
-    Qt::ItemFlags flags(const QModelIndex& index) const;
-
-    /*
-     * This function is to reset the model when there's new account added.
-     */
-    Q_INVOKABLE void reset();
-    /*
-     * This function is to get the current device id in the demon.
-     */
-    Q_INVOKABLE int getCurrentSettingIndex();
-    /*
-     * This function is to get the current ringtone device id in the demon.
-     */
-    Q_INVOKABLE int getCurrentRingtoneDeviceIndex();
-};
diff --git a/src/commoncomponents/SettingParaCombobox.qml b/src/commoncomponents/SettingParaCombobox.qml
index 432f46fff..9e821e1d7 100644
--- a/src/commoncomponents/SettingParaCombobox.qml
+++ b/src/commoncomponents/SettingParaCombobox.qml
@@ -22,6 +22,7 @@ import QtQuick.Controls.Universal 2.14
 import QtQuick.Layouts 1.14
 import QtGraphicalEffects 1.14
 import QtQuick.Controls.Styles 1.4
+
 import net.jami.Constants 1.0
 
 ComboBox {
@@ -37,10 +38,8 @@ ComboBox {
         width: root.width
         contentItem: Text {
             text: {
-                if (index < 0)
-                    return qsTr("")
                 var currentItem = root.delegateModel.items.get(index)
-                return  currentItem.model[root.textRole].toString()
+                return currentItem.model[root.textRole].toString()
             }
             color: JamiTheme.textColor
             font: root.font
diff --git a/src/qmlregister.cpp b/src/qmlregister.cpp
index ef7b44ab4..292727609 100644
--- a/src/qmlregister.cpp
+++ b/src/qmlregister.cpp
@@ -21,9 +21,8 @@
 #include "accountadapter.h"
 #include "accountstomigratelistmodel.h"
 #include "mediacodeclistmodel.h"
-#include "audioinputdevicemodel.h"
+#include "audiodevicemodel.h"
 #include "audiomanagerlistmodel.h"
-#include "audiooutputdevicemodel.h"
 #include "avadapter.h"
 #include "bannedlistmodel.h"
 #include "moderatorlistmodel.h"
@@ -107,8 +106,7 @@ registerTypes()
     QML_REGISTERTYPE("net.jami.Models", ModeratorListModel, 1, 0);
     QML_REGISTERTYPE("net.jami.Models", MediaCodecListModel, 1, 0);
     QML_REGISTERTYPE("net.jami.Models", AccountsToMigrateListModel, 1, 0);
-    QML_REGISTERTYPE("net.jami.Models", AudioInputDeviceModel, 1, 0);
-    QML_REGISTERTYPE("net.jami.Models", AudioOutputDeviceModel, 1, 0);
+    QML_REGISTERTYPE("net.jami.Models", AudioDeviceModel, 1, 0);
     QML_REGISTERTYPE("net.jami.Models", AudioManagerListModel, 1, 0);
     QML_REGISTERTYPE("net.jami.Models", VideoInputDeviceModel, 1, 0);
     QML_REGISTERTYPE("net.jami.Models", VideoFormatResolutionModel, 1, 0);
diff --git a/src/settingsview/components/AudioSettings.qml b/src/settingsview/components/AudioSettings.qml
index df8a1b74b..8d29010c7 100644
--- a/src/settingsview/components/AudioSettings.qml
+++ b/src/settingsview/components/AudioSettings.qml
@@ -17,12 +17,8 @@
  */
 
 import QtQuick 2.14
-import QtQuick.Controls 2.14
-import QtQuick.Controls.Universal 2.14
 import QtQuick.Layouts 1.14
-import QtGraphicalEffects 1.14
-import QtQuick.Controls.Styles 1.4
-import Qt.labs.platform 1.1
+
 import net.jami.Models 1.0
 import net.jami.Adapters 1.0
 import net.jami.Enums 1.0
@@ -43,24 +39,15 @@ ColumnLayout {
     }
 
     function populateAudioSettings() {
-        inputComboBoxSetting.comboModel.reset()
-        audioOutputDeviceModel.reset()
-        audioManagerComboBoxSetting.comboModel.reset()
-
-        inputComboBoxSetting.setCurrentIndex(inputComboBoxSetting.comboModel.getCurrentSettingIndex())
-        outputComboBoxSetting.setCurrentIndex(audioOutputDeviceModel.getCurrentSettingIndex())
-        ringtoneDeviceComboBoxSetting.setCurrentIndex(audioOutputDeviceModel.getCurrentRingtoneDeviceIndex())
+        inputComboBoxSetting.setCurrentIndex(inputComboBoxSetting.comboModel.getCurrentIndex())
+        outputComboBoxSetting.setCurrentIndex(outputComboBoxSetting.comboModel.getCurrentIndex())
+        ringtoneComboBoxSetting.setCurrentIndex(outputComboBoxSetting.comboModel.getCurrentIndex())
         if(audioManagerComboBoxSetting.comboModel.rowCount() > 0) {
             audioManagerComboBoxSetting.setCurrentIndex(audioManagerComboBoxSetting.comboModel.getCurrentSettingIndex())
         }
-
         audioManagerComboBoxSetting.visible = (audioManagerComboBoxSetting.comboModel.rowCount() > 0)
     }
 
-    AudioOutputDeviceModel{
-        id: audioOutputDeviceModel
-    }
-
     ElidedTextLabel {
         Layout.fillWidth: true
         Layout.preferredHeight: JamiTheme.preferredFieldHeight
@@ -79,17 +66,16 @@ ColumnLayout {
 
         labelText: JamiStrings.microphone
         fontPointSize: JamiTheme.settingsFontSize
-        comboModel: AudioInputDeviceModel {}
+        comboModel: AudioDeviceModel { type: AudioDeviceModel.Type.Record }
         widthOfComboBox: itemWidth
         tipText: JamiStrings.selectAudioInputDevice
-        role: "ID_UTF8"
+        role: "DeviceName"
 
         onIndexChanged: {
             AvAdapter.stopAudioMeter(false)
-            var selectedInputDeviceName = comboModel.data(
-                        comboModel.index(modelIndex, 0),
-                        AudioInputDeviceModel.Device_ID)
-            AVModel.setInputDevice(selectedInputDeviceName)
+            AVModel.setInputDevice(comboModel.data(
+                                       comboModel.index(modelIndex, 0),
+                                       AudioDeviceModel.RawDeviceName))
             AvAdapter.startAudioMeter(false)
         }
     }
@@ -116,23 +102,22 @@ ColumnLayout {
 
         labelText: JamiStrings.outputDevice
         fontPointSize: JamiTheme.settingsFontSize
-        comboModel: audioOutputDeviceModel
+        comboModel: AudioDeviceModel { type: AudioDeviceModel.Type.Playback }
         widthOfComboBox: itemWidth
         tipText: JamiStrings.selectAudioOutputDevice
-        role: "ID_UTF8"
+        role: "DeviceName"
 
         onIndexChanged: {
             AvAdapter.stopAudioMeter(false)
-            var selectedOutputDeviceName = audioOutputDeviceModel.data(
-                        audioOutputDeviceModel.index(modelIndex, 0),
-                        AudioOutputDeviceModel.Device_ID)
-            AVModel.setOutputDevice(selectedOutputDeviceName)
+            AVModel.setOutputDevice(comboModel.data(
+                                        comboModel.index(modelIndex, 0),
+                                        AudioDeviceModel.RawDeviceName))
             AvAdapter.startAudioMeter(false)
         }
     }
 
     SettingsComboBox {
-        id: ringtoneDeviceComboBoxSetting
+        id: ringtoneComboBoxSetting
 
         Layout.fillWidth: true
         Layout.preferredHeight: JamiTheme.preferredFieldHeight
@@ -140,17 +125,16 @@ ColumnLayout {
 
         labelText: JamiStrings.ringtoneDevice
         fontPointSize: JamiTheme.settingsFontSize
-        comboModel: audioOutputDeviceModel
+        comboModel: AudioDeviceModel { type: AudioDeviceModel.Type.Ringtone }
         widthOfComboBox: itemWidth
         tipText: JamiStrings.selectRingtoneOutputDevice
-        role: "ID_UTF8"
+        role: "DeviceName"
 
         onIndexChanged: {
             AvAdapter.stopAudioMeter(false)
-            var selectedRingtoneDeviceName = audioOutputDeviceModel.data(
-                        audioOutputDeviceModel.index(modelIndex, 0),
-                        AudioOutputDeviceModel.Device_ID)
-            AVModel.setRingtoneDevice(selectedRingtoneDeviceName)
+            AVModel.setRingtoneDevice(comboModel.data(
+                                          comboModel.index(modelIndex, 0),
+                                          AudioDeviceModel.RawDeviceName))
             AvAdapter.startAudioMeter(false)
         }
     }
-- 
GitLab