1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-07-23 08:55:26 +02:00

settings: refactor for SettingsView - stage two

1. Remove redundant functions in AvAdapter
2. Add CurrentDevice for video device treatment
   Audio device treatment should be improved in the next
   stage
3. Add QSortFilterProxyModel to all video list models and
   manage them together to avoid redundant function calls
4. Video device call action should be responsive to device
   change as well

Gitlab: #508

Change-Id: I3df949a08bc19042b73f033139cd6ab06925c0b6
This commit is contained in:
Ming Rui Zhang 2021-08-31 10:37:11 -04:00
parent a196513d2e
commit e0737f4b70
30 changed files with 893 additions and 1101 deletions

View file

@ -67,10 +67,7 @@ set(COMMON_SOURCES
${SRC_DIR}/mediacodeclistmodel.cpp
${SRC_DIR}/accountstomigratelistmodel.cpp
${SRC_DIR}/audiodevicemodel.cpp
${SRC_DIR}/videoinputdevicemodel.cpp
${SRC_DIR}/pluginlistpreferencemodel.cpp
${SRC_DIR}/videoformatfpsmodel.cpp
${SRC_DIR}/videoformatresolutionmodel.cpp
${SRC_DIR}/audiomanagerlistmodel.cpp
${SRC_DIR}/qmlregister.cpp
${SRC_DIR}/utilsadapter.cpp
@ -88,7 +85,8 @@ set(COMMON_SOURCES
${SRC_DIR}/wizardviewstepmodel.cpp
${SRC_DIR}/avatarregistry.cpp
${SRC_DIR}/currentconversation.cpp
${SRC_DIR}/currentaccount.cpp)
${SRC_DIR}/currentaccount.cpp
${SRC_DIR}/videodevices.cpp)
set(COMMON_HEADERS
${SRC_DIR}/avatarimageprovider.h
@ -123,10 +121,7 @@ set(COMMON_HEADERS
${SRC_DIR}/mediacodeclistmodel.h
${SRC_DIR}/accountstomigratelistmodel.h
${SRC_DIR}/audiodevicemodel.h
${SRC_DIR}/videoinputdevicemodel.h
${SRC_DIR}/pluginlistpreferencemodel.h
${SRC_DIR}/videoformatfpsmodel.h
${SRC_DIR}/videoformatresolutionmodel.h
${SRC_DIR}/audiomanagerlistmodel.h
${SRC_DIR}/qmlregister.h
${SRC_DIR}/abstractlistmodelbase.h
@ -147,7 +142,8 @@ set(COMMON_HEADERS
${SRC_DIR}/wizardviewstepmodel.h
${SRC_DIR}/avatarregistry.h
${SRC_DIR}/currentconversation.h
${SRC_DIR}/currentaccount.h)
${SRC_DIR}/currentaccount.h
${SRC_DIR}/videodevices.h)
set(QML_LIBS
Qt5::Quick

View file

@ -263,32 +263,12 @@ AccountAdapter::savePassword(const QString& accountId,
return lrcInstance_->accountModel().changeAccountPassword(accountId, oldPassword, newPassword);
}
void
AccountAdapter::startPreviewing(bool force)
{
lrcInstance_->renderer()->startPreviewing(force);
}
void
AccountAdapter::stopPreviewing()
{
if (!lrcInstance_->hasActiveCall(true) && lrcInstance_->renderer()->isPreviewing()) {
lrcInstance_->renderer()->stopPreviewing();
}
}
bool
AccountAdapter::hasVideoCall()
{
return lrcInstance_->hasActiveCall(true);
}
bool
AccountAdapter::isPreviewing()
{
return lrcInstance_->renderer()->isPreviewing();
}
void
AccountAdapter::setCurrAccDisplayName(const QString& text)
{

View file

@ -77,11 +77,7 @@ public:
Q_INVOKABLE bool savePassword(const QString& accountId,
const QString& oldPassword,
const QString& newPassword);
Q_INVOKABLE void startPreviewing(bool force = false);
Q_INVOKABLE void stopPreviewing();
Q_INVOKABLE bool hasVideoCall();
Q_INVOKABLE bool isPreviewing();
Q_INVOKABLE void setCurrAccDisplayName(const QString& text);
Q_INVOKABLE void setCurrentAccountAvatarFile(const QString& source);
Q_INVOKABLE void setCurrentAccountAvatarBase64(const QString& source = {});

View file

@ -36,36 +36,18 @@
AvAdapter::AvAdapter(LRCInstance* instance, QObject* parent)
: QmlAdapterBase(instance, parent)
{
auto& avModel = lrcInstance_->avModel();
deviceListSize_ = avModel.getDevices().size();
connect(&avModel, &lrc::api::AVModel::audioDeviceEvent, this, &AvAdapter::onAudioDeviceEvent);
connect(&avModel, &lrc::api::AVModel::deviceEvent, this, &AvAdapter::onVideoDeviceEvent);
connect(lrcInstance_->renderer(), &RenderManager::previewFrameStarted, [this]() {
// TODO: listen to the correct signals that are needed to be added in daemon or lrc
auto callId = getCurrentCallId();
auto callId = lrcInstance_->getCurrentCallId();
if (!callId.isEmpty())
set_currentRenderingDeviceType(
lrcInstance_->avModel().getCurrentRenderedDevice(callId).type);
});
}
void
AvAdapter::selectVideoInputDeviceByName(const QString& deviceName)
{
auto deviceId = lrcInstance_->avModel().getDeviceIdFromName(deviceName);
if (deviceId.isEmpty()) {
qWarning() << "Couldn't find device: " << deviceName;
return;
}
selectVideoInputDeviceById(deviceId);
}
void
AvAdapter::selectVideoInputDeviceById(const QString& deviceId)
{
lrcInstance_->avModel().setCurrentVideoCaptureDevice(deviceId);
lrcInstance_->avModel().switchInputTo(deviceId, getCurrentCallId());
connect(&lrcInstance_->avModel(),
&lrc::api::AVModel::audioDeviceEvent,
this,
&AvAdapter::onAudioDeviceEvent);
}
// The top left corner of primary screen is (0, 0).
@ -114,7 +96,7 @@ AvAdapter::shareEntireScreen(int screenNumber)
rect.y(),
rect.width() * screen->devicePixelRatio(),
rect.height() * screen->devicePixelRatio(),
getCurrentCallId());
lrcInstance_->getCurrentCallId());
}
void
@ -127,7 +109,7 @@ AvAdapter::shareAllScreens()
arrangementRect.y(),
arrangementRect.width(),
arrangementRect.height(),
getCurrentCallId());
lrcInstance_->getCurrentCallId());
}
void
@ -187,7 +169,7 @@ AvAdapter::captureAllScreens()
void
AvAdapter::shareFile(const QString& filePath)
{
lrcInstance_->avModel().setInputFile(filePath, getCurrentCallId());
lrcInstance_->avModel().setInputFile(filePath, lrcInstance_->getCurrentCallId());
}
void
@ -206,7 +188,7 @@ AvAdapter::shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned heig
y,
width < 128 ? 128 : width,
height < 128 ? 128 : height,
getCurrentCallId());
lrcInstance_->getCurrentCallId());
});
#else
lrcInstance_->avModel().setDisplay(getScreenNumber(),
@ -214,14 +196,14 @@ AvAdapter::shareScreenArea(unsigned x, unsigned y, unsigned width, unsigned heig
y,
width < 128 ? 128 : width,
height < 128 ? 128 : height,
getCurrentCallId());
lrcInstance_->getCurrentCallId());
#endif
}
void
AvAdapter::stopSharing()
{
auto callId = getCurrentCallId();
auto callId = lrcInstance_->getCurrentCallId();
if (!callId.isEmpty())
lrcInstance_->avModel().switchInputTo(lrcInstance_->avModel().getCurrentVideoCaptureDevice(),
callId);
@ -248,82 +230,6 @@ AvAdapter::onAudioDeviceEvent()
Q_EMIT audioDeviceListChanged(inputs, outputs);
}
void
AvAdapter::onVideoDeviceEvent()
{
auto& avModel = lrcInstance_->avModel();
auto defaultDevice = avModel.getDefaultDevice();
auto currentCaptureDevice = avModel.getCurrentVideoCaptureDevice();
QString callId = getCurrentCallId();
/*
* Decide whether a device has plugged, unplugged, or nothing has changed.
*/
auto deviceList = avModel.getDevices();
auto currentDeviceListSize = deviceList.size();
DeviceEvent deviceEvent {DeviceEvent::None};
if (currentDeviceListSize > deviceListSize_) {
deviceEvent = DeviceEvent::Added;
} else if (currentDeviceListSize < deviceListSize_) {
/*
* Check if the currentCaptureDevice is still in the device list.
*/
if (std::find(std::begin(deviceList), std::end(deviceList), currentCaptureDevice)
== std::end(deviceList)) {
deviceEvent = DeviceEvent::RemovedCurrent;
}
}
auto cb = [this, currentDeviceListSize, deviceEvent, defaultDevice, callId] {
auto& avModel = lrcInstance_->avModel();
if (currentDeviceListSize == 0) {
avModel.clearCurrentVideoCaptureDevice();
avModel.switchInputTo({}, callId);
avModel.stopPreview();
} else if (deviceEvent == DeviceEvent::RemovedCurrent && currentDeviceListSize > 0) {
avModel.setDefaultDevice(defaultDevice);
avModel.setCurrentVideoCaptureDevice(defaultDevice);
avModel.switchInputTo(defaultDevice, callId);
}
};
if (lrcInstance_->renderer()->isPreviewing()) {
Utils::oneShotConnect(lrcInstance_->renderer(),
&RenderManager::previewRenderingStopped,
[cb] { QtConcurrent::run([cb]() { cb(); }); });
} else {
if (deviceEvent == DeviceEvent::Added && currentDeviceListSize == 1) {
avModel.setDefaultDevice(defaultDevice);
avModel.setCurrentVideoCaptureDevice(defaultDevice);
if (callId.isEmpty()) {
Q_EMIT videoDeviceAvailable();
} else {
avModel.switchInputTo(defaultDevice, callId);
}
} else {
cb();
}
}
Q_EMIT videoDeviceListChanged(currentDeviceListSize);
deviceListSize_ = currentDeviceListSize;
}
QString
AvAdapter::getCurrentCallId()
{
try {
const auto& convInfo = lrcInstance_->getConversationFromConvUid(
lrcInstance_->get_selectedConvUid());
auto call = lrcInstance_->getCallInfoForConversation(convInfo);
return call ? call->id : QString();
} catch (...) {
return QString();
}
}
int
AvAdapter::getScreenNumber() const
{
@ -349,30 +255,6 @@ AvAdapter::setDeviceName(const QString& deviceName)
lrcInstance_->getCurrentAccountInfo().deviceModel->setCurrentDeviceName(deviceName);
}
void
AvAdapter::setCurrentVideoDeviceRateAndResolution(qreal rate, const QString& resolution)
{
auto settings = lrcInstance_->avModel().getDeviceSettings(
lrcInstance_->avModel().getCurrentVideoCaptureDevice());
settings.rate = rate;
settings.size = resolution;
lrcInstance_->avModel().setDeviceSettings(settings);
}
QString
AvAdapter::getVideoSettingsSize(const QString& deviceId)
{
return lrcInstance_->avModel().getDeviceSettings(deviceId).size;
}
int
AvAdapter::getCurrentVideoDeviceCapabilitiesSize()
{
return lrcInstance_->avModel()
.getDeviceCapabilities(lrcInstance_->avModel().getCurrentVideoCaptureDevice())
.size();
}
void
AvAdapter::enableCodec(unsigned int id, bool isToEnable)
{
@ -390,3 +272,34 @@ AvAdapter::decreaseCodecPriority(unsigned int id, bool isVideo)
{
lrcInstance_->getCurrentAccountInfo().codecModel->decreasePriority(id, isVideo);
}
bool
AvAdapter::getHardwareAcceleration()
{
return lrcInstance_->avModel().getHardwareAcceleration();
}
void
AvAdapter::setHardwareAcceleration(bool accelerate)
{
lrcInstance_->avModel().setHardwareAcceleration(accelerate);
}
void
AvAdapter::startPreviewing(bool force)
{
lrcInstance_->renderer()->startPreviewing(force);
}
void
AvAdapter::stopPreviewing()
{
if (!lrcInstance_->hasActiveCall(true)) {
lrcInstance_->renderer()->stopPreviewing();
}
}
bool
AvAdapter::isPreviewing()
{
return lrcInstance_->renderer()->isPreviewing();
}

View file

@ -29,28 +29,20 @@
class AvAdapter final : public QmlAdapterBase
{
Q_OBJECT
QML_PROPERTY(lrc::api::video::DeviceType, currentRenderingDeviceType)
QML_RO_PROPERTY(lrc::api::video::DeviceType, currentRenderingDeviceType)
public:
explicit AvAdapter(LRCInstance* instance, QObject* parent = nullptr);
~AvAdapter() = default;
Q_SIGNALS:
void audioDeviceListChanged(int inputs, int outputs);
void videoDeviceListChanged(int inputs);
void screenCaptured(int screenNumber, QString source);
void videoDeviceAvailable();
// TODO: move to future audio device class
void audioDeviceListChanged(int inputs, int outputs);
protected:
void safeInit() override {};
// switch preview video input by device name
Q_INVOKABLE void selectVideoInputDeviceByName(const QString& deviceName);
// switch preview video input by device id
Q_INVOKABLE void selectVideoInputDeviceById(const QString& deviceId);
// Share the screen specificed by screen number.
Q_INVOKABLE void shareEntireScreen(int screenNumber);
@ -76,31 +68,25 @@ protected:
Q_INVOKABLE void stopAudioMeter();
Q_INVOKABLE void setDeviceName(const QString& deviceName);
Q_INVOKABLE void setCurrentVideoDeviceRateAndResolution(qreal rate, const QString& resolution);
Q_INVOKABLE QString getVideoSettingsSize(const QString& deviceId);
Q_INVOKABLE int getCurrentVideoDeviceCapabilitiesSize();
Q_INVOKABLE void enableCodec(unsigned int id, bool isToEnable);
Q_INVOKABLE void increaseCodecPriority(unsigned int id, bool isVideo);
Q_INVOKABLE void decreaseCodecPriority(unsigned int id, bool isVideo);
// TODO: to be removed
Q_INVOKABLE bool getHardwareAcceleration();
Q_INVOKABLE void setHardwareAcceleration(bool accelerate);
Q_INVOKABLE bool isPreviewing();
Q_INVOKABLE void startPreviewing(bool force = false);
Q_INVOKABLE void stopPreviewing();
private Q_SLOTS:
void onAudioDeviceEvent();
void onVideoDeviceEvent();
private:
// Get screens arrangement rect relative to primary screen.
const QRect getAllScreensBoundingRect();
// Get current callId from current selected conv id.
QString getCurrentCallId();
// Used to classify capture device events.
enum class DeviceEvent { Added, RemovedCurrent, None };
// Used to track the capture device count.
int deviceListSize_;
// Get the screen number
int getScreenNumber() const;
};

View file

@ -39,13 +39,13 @@ Item {
height: boothLayout.height
function startBooth() {
AccountAdapter.startPreviewing(false)
AvAdapter.startPreviewing(false)
isPreviewing = true
}
function stopBooth(){
if (!AccountAdapter.hasVideoCall()) {
AccountAdapter.stopPreviewing()
AvAdapter.stopPreviewing()
}
isPreviewing = false
}
@ -136,8 +136,6 @@ Item {
anchors.margins: 1
visible: isPreviewing
onRenderingStopped: stopBooth()
lrcInstance: LRCInstance
layer.enabled: true
@ -148,6 +146,11 @@ Item {
radius: avatarSize / 2
}
}
onRenderingStopped: {
if (root.visible)
stopBooth()
}
}
Rectangle {

View file

@ -24,19 +24,23 @@ import net.jami.Constants 1.1
ComboBox {
id: root
property string tooltipText
property string comboBoxBackgroundColor: JamiTheme.editBackgroundColor
property alias tooltipText: toolTip.text
property string placeholderText
property string currentSelectionText: currentText
property string comboBoxBackgroundColor: JamiTheme.editBackgroundColor
MaterialToolTip {
id: toolTip
parent: root
visible: hovered && (text.length > 0)
delay: Qt.styleHints.mousePressAndHoldInterval
}
displayText: currentIndex !== -1 ?
currentText :
(placeholderText !== "" ?
placeholderText :
JamiStrings.notAvailable)
ToolTip.delay: Qt.styleHints.mousePressAndHoldInterval
ToolTip.visible: hovered && (tooltipText.length > 0)
ToolTip.text: tooltipText
currentSelectionText : (placeholderText !== "" ?
placeholderText :
JamiStrings.notAvailable)
delegate: ItemDelegate {
width: root.width
@ -53,7 +57,6 @@ ComboBox {
elide: Text.ElideRight
verticalAlignment: Text.AlignVCenter
}
highlighted: root.highlightedIndex === index
background: Rectangle {
color: highlighted? JamiTheme.selectedColor : JamiTheme.editBackgroundColor
}
@ -61,8 +64,10 @@ ComboBox {
indicator: Canvas {
id: canvas
x: root.width - width - root.rightPadding
y: root.topPadding + (root.availableHeight - height) / 2
width: 12
height: 8
contextType: "2d"
@ -113,17 +118,17 @@ ComboBox {
contentItem: ListView {
id: listView
clip: true
implicitHeight: contentHeight
model: root.delegateModel
currentIndex: root.highlightedIndex
ScrollBar.vertical: ScrollBar { }
ScrollBar.vertical: ScrollBar {}
}
background: Rectangle {
color: JamiTheme.editBackgroundColor
border.color: "gray"
border.color: JamiTheme.greyBorderColor
radius: 2
}
}

View file

@ -417,3 +417,15 @@ LRCInstance::monitor(bool continuous)
{
lrc_->monitor(continuous);
}
QString
LRCInstance::getCurrentCallId()
{
try {
const auto& convInfo = getConversationFromConvUid(get_selectedConvUid());
auto call = getCallInfoForConversation(convInfo);
return call ? call->id : QString();
} catch (...) {
return QString();
}
}

View file

@ -89,6 +89,7 @@ public:
const account::Info& getAccountInfo(const QString& accountId);
const account::Info& getCurrentAccountInfo();
QString getCurrentCallId();
QString getCallIdForConversationUid(const QString& convUid, const QString& accountId);
const call::Info* getCallInfo(const QString& callId, const QString& accountId);
const call::Info* getCallInfoForConversation(const conversation::Info& convInfo,

View file

@ -57,7 +57,6 @@ Rectangle {
property string currentAccountId: LRCInstance.currentAccountId
onCurrentAccountIdChanged: {
if (inSettingsView) {
settingsView.accountListChanged()
settingsView.setSelected(settingsView.selectedMenu, true)
} else {
backToMainView(true)

View file

@ -70,11 +70,6 @@ Control {
audioOutputDeviceListModel.reset();
audioOutputMenuAction.enabled = outputs
}
function onVideoDeviceListChanged(inputs) {
videoInputDeviceListModel.reset();
videoInputMenuAction.enabled = inputs
}
}
property list<Action> menuActions: [
@ -144,34 +139,16 @@ Control {
},
Action {
id: videoInputMenuAction
enabled: VideoDevices.listSize !== 0
text: JamiStrings.selectVideoDevice
Component.onCompleted: enabled = videoInputDeviceListModel.rowCount()
property var listModel: VideoInputDeviceModel {
id: videoInputDeviceListModel
lrcInstance: LRCInstance
}
property var listModel: VideoDevices.devicesSourceModel()
function accept(index) {
if (listModel.deviceCount() < 1)
if (VideoDevices.listSize < 1)
return
try {
var deviceId = listModel.data(
listModel.index(index, 0),
VideoInputDeviceModel.DeviceId)
var deviceName = listModel.data(
listModel.index(index, 0),
VideoInputDeviceModel.DeviceName)
if (deviceId.length === 0) {
console.warn("Couldn't find device: " + deviceName)
return
}
if (AVModel.getCurrentVideoCaptureDevice() !== deviceId) {
AVModel.setCurrentVideoCaptureDevice(deviceId)
AVModel.setDefaultDevice(deviceId)
}
AvAdapter.selectVideoInputDeviceById(deviceId)
} catch (err) {
console.warn(err.message)
}
// TODO: change it when we can suppot showing default and
// current rendering device at the same time and
// start and stop preview logic in here should be in LRC
VideoDevices.setDefaultDevice(index, true)
}
}
]

View file

@ -190,10 +190,11 @@ Rectangle {
}
Connections {
target: AvAdapter
target: VideoDevices
function onVideoDeviceListChanged(inputs) {
previewRenderer.visible = (inputs !== 0)
// TODO: previewRenderer visible should be listening to a property
function onDeviceListChanged() {
previewRenderer.visible = VideoDevices.listSize !== 0
}
}

View file

@ -59,7 +59,7 @@ Rectangle {
updateState(RecordBox.States.INIT)
if (isVideo) {
AccountAdapter.startPreviewing(false)
AvAdapter.startPreviewing(false)
previewAvailable = true
}
}
@ -67,10 +67,9 @@ Rectangle {
function scaleHeight() {
height = preferredHeight
if (isVideo) {
var device = AVModel.getDefaultDevice()
var settings = AvAdapter.getVideoSettingsSize(device)
var res = settings.split("x")
var aspectRatio = res[1] / res[0]
var resolution = VideoDevices.defaultRes
var resVec = resolution.split("x")
var aspectRatio = resVec[1] / resVec[0]
if (aspectRatio) {
height = preferredWidth * aspectRatio
} else {
@ -80,8 +79,8 @@ Rectangle {
}
function closeRecorder() {
if (isVideo && AccountAdapter.isPreviewing()) {
AccountAdapter.stopPreviewing()
if (isVideo && AvAdapter.isPreviewing()) {
AvAdapter.stopPreviewing()
}
stopRecording()
visible = false

View file

@ -28,6 +28,7 @@
#include "conversationsadapter.h"
#include "currentconversation.h"
#include "currentaccount.h"
#include "videodevices.h"
#include "accountlistmodel.h"
#include "accountstomigratelistmodel.h"
@ -52,9 +53,6 @@
#include "pluginlistpreferencemodel.h"
#include "previewrenderer.h"
#include "version.h"
#include "videoformatfpsmodel.h"
#include "videoformatresolutionmodel.h"
#include "videoinputdevicemodel.h"
#include "wizardviewstepmodel.h"
#include "api/peerdiscoverymodel.h"
@ -116,6 +114,7 @@ registerTypes(QQmlEngine* engine,
auto pluginAdapter = new PluginAdapter(lrcInstance, parent);
auto currentConversation = new CurrentConversation(lrcInstance, parent);
auto currentAccount = new CurrentAccount(lrcInstance, appSettingsManager, parent);
auto videoDevices = new VideoDevices(lrcInstance, parent);
// qml adapter registration
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, callAdapter, "CallAdapter");
@ -128,6 +127,7 @@ registerTypes(QQmlEngine* engine,
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, pluginAdapter, "PluginAdapter");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentConversation, "CurrentConversation");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, currentAccount, "CurrentAccount");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_ADAPTERS, videoDevices, "VideoDevices");
// TODO: remove these
QML_REGISTERSINGLETONTYPE_CUSTOM(NS_MODELS, AVModel, &lrcInstance->avModel())
@ -152,9 +152,6 @@ registerTypes(QQmlEngine* engine,
QML_REGISTERTYPE(NS_MODELS, AccountsToMigrateListModel);
QML_REGISTERTYPE(NS_MODELS, AudioDeviceModel);
QML_REGISTERTYPE(NS_MODELS, AudioManagerListModel);
QML_REGISTERTYPE(NS_MODELS, VideoInputDeviceModel);
QML_REGISTERTYPE(NS_MODELS, VideoFormatResolutionModel);
QML_REGISTERTYPE(NS_MODELS, VideoFormatFpsModel);
QML_REGISTERTYPE(NS_MODELS, PluginListPreferenceModel);
QML_REGISTERTYPE(NS_MODELS, FilesToSendListModel);
QML_REGISTERTYPE(NS_MODELS, SmartListModel);
@ -216,6 +213,9 @@ registerTypes(QQmlEngine* engine,
QML_REGISTERUNCREATABLE(NS_ENUMS, NetWorkManager)
QML_REGISTERUNCREATABLE(NS_ENUMS, WizardViewStepModel)
QML_REGISTERUNCREATABLE(NS_ENUMS, DeviceItemListModel)
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoInputDeviceModel)
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatResolutionModel)
QML_REGISTERUNCREATABLE(NS_ENUMS, VideoFormatFpsModel)
engine->addImageProvider(QLatin1String("qrImage"), new QrImageProvider(lrcInstance));
engine->addImageProvider(QLatin1String("avatarImage"),

View file

@ -80,6 +80,29 @@ oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
});
}
template<typename Func1, typename Func2>
void
oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,
Func1 signal,
QObject* context,
Func2 slot,
Qt::ConnectionType connectionType = Qt::ConnectionType::AutoConnection)
{
QMetaObject::Connection* const connection = new QMetaObject::Connection;
*connection = QObject::connect(sender, signal, context, slot, connectionType);
QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection;
*disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] {
if (connection) {
QObject::disconnect(*connection);
delete connection;
}
if (disconnectConnection) {
QObject::disconnect(*disconnectConnection);
delete disconnectConnection;
}
});
}
template<typename Func1, typename Func2, typename Func3>
void
oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender,

View file

@ -234,10 +234,6 @@ RenderManager::isPreviewing()
void
RenderManager::stopPreviewing()
{
if (!previewFrameWrapper_->isRendering()) {
return;
}
previewFrameWrapper_->stopRendering();
avModel_.stopPreview();
}

View file

@ -42,7 +42,7 @@ Rectangle {
if(visible){
setSelected(selectedMenu,true)
} else {
AccountAdapter.stopPreviewing()
AvAdapter.stopPreviewing()
}
}
@ -50,12 +50,10 @@ Rectangle {
if(selectedMenu === sel && (!recovery)) { return }
switch(sel) {
case SettingsView.Account:
AccountAdapter.stopPreviewing()
selectedMenu = sel
pageIdCurrentAccountSettings.updateAccountInfoDisplayed()
break
case SettingsView.General:
AccountAdapter.stopPreviewing()
selectedMenu = sel
break
case SettingsView.Media:
@ -63,25 +61,15 @@ Rectangle {
avSettings.populateAVSettings()
break
case SettingsView.Plugin:
AccountAdapter.stopPreviewing()
selectedMenu = sel
pluginSettings.populatePluginSettings()
break
}
}
Connections {
id: accountListChangedConnection
target: LRCInstance
function onAccountListChanged() {
accountListChanged()
}
}
// slots
function leaveSettingsSlot(showMainView) {
AccountAdapter.stopPreviewing()
AvAdapter.stopPreviewing()
settingsViewRect.stopBooth()
if (showMainView)
settingsViewNeedToShowMainView()
@ -89,16 +77,6 @@ Rectangle {
settingsViewNeedToShowNewWizardWindow()
}
function accountListChanged() {
var accountList = AccountAdapter.model.getAccountList()
if(accountList.length === 0)
return
var device = AVModel.getDefaultDevice()
if(device.length === 0) {
AVModel.setCurrentVideoCaptureDevice(device)
}
}
property int selectedMenu: SettingsView.Account
// signal to redirect the page to main view
signal settingsViewNeedToShowMainView()

View file

@ -267,8 +267,8 @@ ColumnLayout {
modelIndex: CurrentAccount.method_TLS
onModelIndexChanged: CurrentAccount.method_TLS =
parseInt(comboModel.get(modelIndex).secondArg)
onActivated: CurrentAccount.method_TLS =
parseInt(comboModel.get(modelIndex).secondArg)
}
SettingsMaterialLineEdit {

View file

@ -75,7 +75,7 @@ ColumnLayout {
tipText: JamiStrings.selectAudioInputDevice
role: "DeviceName"
onModelIndexChanged: {
onActivated: {
AvAdapter.stopAudioMeter()
AVModel.setInputDevice(comboModel.data(
comboModel.index(modelIndex, 0),
@ -114,7 +114,7 @@ ColumnLayout {
tipText: JamiStrings.selectAudioOutputDevice
role: "DeviceName"
onModelIndexChanged: {
onActivated: {
AvAdapter.stopAudioMeter()
AVModel.setOutputDevice(comboModel.data(
comboModel.index(modelIndex, 0),
@ -140,7 +140,7 @@ ColumnLayout {
tipText: JamiStrings.selectRingtoneOutputDevice
role: "DeviceName"
onModelIndexChanged: {
onActivated: {
AvAdapter.stopAudioMeter()
AVModel.setRingtoneDevice(comboModel.data(
comboModel.index(modelIndex, 0),
@ -164,7 +164,7 @@ ColumnLayout {
widthOfComboBox: itemWidth
role: "ID_UTF8"
onModelIndexChanged: {
onActivated: {
AvAdapter.stopAudioMeter()
var selectedAudioManager = comboModel.data(
comboModel.index(modelIndex, 0), AudioManagerListModel.AudioManagerID)

View file

@ -34,20 +34,10 @@ Rectangle {
function populateAVSettings() {
audioSettings.populateAudioSettings()
videoSettings.populateVideoSettings()
}
color: JamiTheme.secondaryBackgroundColor
Connections {
target: AvAdapter
function onVideoDeviceAvailable() {
if (root.visible)
videoSettings.startPreviewing()
}
}
ColumnLayout {
id: avSettingsColumnLayout

View file

@ -31,6 +31,7 @@ RowLayout {
property alias tipText: comboBoxOfLayout.tooltipText
property alias role: comboBoxOfLayout.textRole
property alias placeholderText: comboBoxOfLayout.placeholderText
property alias currentSelectionText: comboBoxOfLayout.currentSelectionText
property alias enabled: comboBoxOfLayout.enabled
property alias fontPointSize: comboBoxOfLayout.font.pointSize
property alias modelIndex: comboBoxOfLayout.currentIndex
@ -38,6 +39,8 @@ RowLayout {
property int heightOfLayout: 30
property int widthOfComboBox: 50
signal activated
ElidedTextLabel {
id: label
@ -62,5 +65,7 @@ RowLayout {
textRole: role
tooltipText: tipText
onActivated: root.activated()
}
}

View file

@ -35,79 +35,72 @@ ColumnLayout {
property bool previewAvailable: false
property int itemWidth
Connections {
target: AvAdapter
function onVideoDeviceListChanged() {
populateVideoSettings()
}
}
function startPreviewing(force = false) {
if (root.visible) {
AccountAdapter.startPreviewing(force)
AvAdapter.startPreviewing(force)
previewAvailable = true
}
}
function populateVideoSettings() {
deviceComboBoxSetting.comboModel.reset()
var count = deviceComboBoxSetting.comboModel.deviceCount()
previewWidget.visible = count > 0
deviceComboBoxSetting.enabled = count > 0
resolutionComboBoxSetting.enabled = count > 0
fpsComboBoxSetting.enabled = count > 0
if (count === 0) {
resolutionComboBoxSetting.reset()
fpsComboBoxSetting.reset()
} else {
deviceComboBoxSetting.modelIndex =
deviceComboBoxSetting.comboModel.getCurrentIndex()
}
hardwareAccelControl.checked = AVModel.getHardwareAcceleration()
}
function slotDeviceBoxCurrentIndexChanged(index) {
if (deviceComboBoxSetting.comboModel.deviceCount() <= 0)
return
try {
var deviceId = deviceComboBoxSetting.comboModel.data(
deviceComboBoxSetting.comboModel.index(index, 0),
VideoInputDeviceModel.DeviceId)
var deviceName = deviceComboBoxSetting.comboModel.data(
deviceComboBoxSetting.comboModel.index(index, 0),
VideoInputDeviceModel.DeviceName)
if(deviceId.length === 0) {
console.warn("Couldn't find device: " + deviceName)
return
function updatePreviewRatio() {
var resolution = VideoDevices.defaultRes
if (resolution.length !== 0) {
var resVec = resolution.split("x")
var ratio = resVec[1] / resVec[0]
if (ratio) {
aspectRatio = ratio
} else {
console.error("Could not scale recording video preview")
}
if (AVModel.getCurrentVideoCaptureDevice() !== deviceId) {
AVModel.setCurrentVideoCaptureDevice(deviceId)
AVModel.setDefaultDevice(deviceId)
}
resolutionComboBoxSetting.reset()
} catch(err){ console.warn(err.message) }
}
function updatePreviewRatio(resolution) {
var res = resolution.split("x")
var ratio = res[1] / res[0]
if (ratio) {
aspectRatio = ratio
} else {
console.error("Could not scale recording video preview")
}
}
onVisibleChanged: {
if (visible)
startPreviewing(true)
if (visible) {
hardwareAccelControl.checked = AvAdapter.getHardwareAcceleration()
updatePreviewRatio()
if (previewWidget.visible)
startPreviewing(true)
} else {
AvAdapter.stopPreviewing()
}
}
Connections {
target: VideoDevices
function onDefaultResChanged() {
updatePreviewRatio()
}
function onDeviceAvailable() {
startPreviewing()
}
function onDeviceListChanged() {
var deviceModel = deviceComboBoxSetting.comboModel
var resModel = resolutionComboBoxSetting.comboModel
var fpsModel = fpsComboBoxSetting.comboModel
var resultList = deviceModel.match(deviceModel.index(0, 0),
VideoInputDeviceModel.DeviceId,
VideoDevices.defaultId)
deviceComboBoxSetting.modelIndex = resultList.length > 0 ?
resultList[0].row : deviceModel.rowCount() ? 0 : -1
resultList = resModel.match(resModel.index(0, 0),
VideoFormatResolutionModel.Resolution,
VideoDevices.defaultRes)
resolutionComboBoxSetting.modelIndex = resultList.length > 0 ?
resultList[0].row : deviceModel.rowCount() ? 0 : -1
resultList = fpsModel.match(fpsModel.index(0, 0),
VideoFormatFpsModel.FPS,
VideoDevices.defaultFps)
fpsComboBoxSetting.modelIndex = resultList.length > 0 ?
resultList[0].row : deviceModel.rowCount() ? 0 : -1
}
}
ElidedTextLabel {
@ -126,98 +119,66 @@ ColumnLayout {
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.leftMargin: JamiTheme.preferredMarginSize
labelText: JamiStrings.device
enabled: VideoDevices.listSize !== 0
fontPointSize: JamiTheme.settingsFontSize
comboModel: VideoInputDeviceModel {
lrcInstance: LRCInstance
}
widthOfComboBox: itemWidth
labelText: JamiStrings.device
tipText: JamiStrings.selectVideoDevice
role: "DeviceName_UTF8"
onModelIndexChanged: slotDeviceBoxCurrentIndexChanged(modelIndex)
placeholderText: JamiStrings.noVideoDevice
currentSelectionText: VideoDevices.defaultName
comboModel: VideoDevices.devicesFilterModel()
role: "DeviceName"
onActivated: {
// TODO: start and stop preview logic in here should be in LRC
AvAdapter.stopPreviewing()
VideoDevices.setDefaultDevice(modelIndex)
startPreviewing()
}
}
SettingsComboBox {
id: resolutionComboBoxSetting
function reset() {
modelIndex = -1
comboModel.reset()
modelIndex = 0
}
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.leftMargin: JamiTheme.preferredMarginSize
labelText: JamiStrings.resolution
fontPointSize: JamiTheme.settingsFontSize
comboModel: VideoFormatResolutionModel {
lrcInstance: LRCInstance
}
enabled: VideoDevices.listSize !== 0
widthOfComboBox: itemWidth
fontPointSize: JamiTheme.settingsFontSize
labelText: JamiStrings.resolution
currentSelectionText: VideoDevices.defaultRes
tipText: JamiStrings.selectVideoResolution
role: "Resolution_UTF8"
comboModel: VideoDevices.resFilterModel()
role: "Resolution"
modelIndex: -1
onModelIndexChanged: {
if (modelIndex === -1)
return
var resolution = comboModel.data(comboModel.index(modelIndex, 0),
VideoFormatResolutionModel.Resolution)
fpsComboBoxSetting.comboModel.currentResolution = resolution
fpsComboBoxSetting.modelIndex = 0
var rate = fpsComboBoxSetting.comboModel.data(
fpsComboBoxSetting.comboModel.index(0, 0),
VideoFormatFpsModel.FPS)
AvAdapter.setCurrentVideoDeviceRateAndResolution(rate, resolution)
updatePreviewRatio(resolution)
}
onActivated: VideoDevices.setDefaultDeviceRes(modelIndex)
}
SettingsComboBox {
id: fpsComboBoxSetting
function reset() {
modelIndex = -1
comboModel.reset()
modelIndex = 0
}
Layout.fillWidth: true
Layout.preferredHeight: JamiTheme.preferredFieldHeight
Layout.leftMargin: JamiTheme.preferredMarginSize
labelText: JamiStrings.fps
fontPointSize: JamiTheme.settingsFontSize
comboModel: VideoFormatFpsModel {
lrcInstance: LRCInstance
}
enabled: VideoDevices.listSize !== 0
widthOfComboBox: itemWidth
fontPointSize: JamiTheme.settingsFontSize
tipText: JamiStrings.selectFPS
role: "FPS_ToDisplay_UTF8"
labelText: JamiStrings.fps
currentSelectionText: VideoDevices.defaultFps.toString()
comboModel: VideoDevices.fpsFilterModel()
role: "FPS"
modelIndex: -1
onModelIndexChanged: {
if (modelIndex === -1)
return
var resolution = resolutionComboBoxSetting.comboModel.data(
resolutionComboBoxSetting.comboModel.index(
resolutionComboBoxSetting.modelIndex, 0),
VideoFormatResolutionModel.Resolution)
var rate = comboModel.data(comboModel.index(modelIndex, 0),
VideoFormatFpsModel.FPS)
AvAdapter.setCurrentVideoDeviceRateAndResolution(rate, resolution)
}
onActivated: VideoDevices.setDefaultDeviceFps(modelIndex)
}
ToggleSwitch {
@ -230,7 +191,7 @@ ColumnLayout {
fontPointSize: JamiTheme.settingsFontSize
onSwitchToggled: {
AVModel.setHardwareAcceleration(checked)
AvAdapter.setHardwareAcceleration(checked)
startPreviewing(true)
}
}
@ -247,8 +208,7 @@ ColumnLayout {
Layout.preferredWidth: itemWidth * 2
Layout.bottomMargin: JamiTheme.preferredMarginSize
color: "white"
radius: 5
color: JamiTheme.primaryForegroundColor
PreviewRenderer {
id: previewWidget
@ -257,6 +217,7 @@ ColumnLayout {
lrcInstance: LRCInstance
visible: VideoDevices.listSize !== 0
layer.enabled: true
layer.effect: OpacityMask {
maskSource: rectBox
@ -265,6 +226,7 @@ ColumnLayout {
}
Label {
// TODO: proper use of previewAvailable
visible: !previewAvailable
Layout.fillWidth: true

443
src/videodevices.cpp Normal file
View file

@ -0,0 +1,443 @@
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@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 "videodevices.h"
// VideoInputDeviceModel
VideoInputDeviceModel::VideoInputDeviceModel(LRCInstance* lrcInstance,
VideoDevices* videoDeviceInstance)
: QAbstractListModel(videoDeviceInstance)
, lrcInstance_(lrcInstance)
, videoDevices_(videoDeviceInstance)
{}
VideoInputDeviceModel::~VideoInputDeviceModel() {}
int
VideoInputDeviceModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid() && lrcInstance_) {
return videoDevices_->get_listSize();
}
return 0;
}
QVariant
VideoInputDeviceModel::data(const QModelIndex& index, int role) const
{
auto deviceList = lrcInstance_->avModel().getDevices();
if (!index.isValid() || deviceList.size() == 0 || index.row() >= deviceList.size()) {
return QVariant();
}
auto currentDeviceSetting = lrcInstance_->avModel().getDeviceSettings(deviceList[index.row()]);
switch (role) {
case Role::DeviceName:
return QVariant(currentDeviceSetting.name);
case Role::DeviceId:
return QVariant(currentDeviceSetting.id);
}
return QVariant();
}
QHash<int, QByteArray>
VideoInputDeviceModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[DeviceName] = "DeviceName";
roles[DeviceId] = "DeviceId";
return roles;
}
int
VideoInputDeviceModel::getCurrentIndex() const
{
QString currentId = videoDevices_->get_defaultId();
auto resultList = match(index(0, 0), DeviceId, QVariant(currentId));
return resultList.size() > 0 ? resultList[0].row() : 0;
}
// VideoFormatResolutionModel
VideoFormatResolutionModel::VideoFormatResolutionModel(LRCInstance* lrcInstance,
VideoDevices* videoDeviceInstance)
: QAbstractListModel(videoDeviceInstance)
, lrcInstance_(lrcInstance)
, videoDevices_(videoDeviceInstance)
{}
VideoFormatResolutionModel::~VideoFormatResolutionModel() {}
int
VideoFormatResolutionModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid() && lrcInstance_) {
return videoDevices_->get_defaultResRateList().size();
}
return 0;
}
QVariant
VideoFormatResolutionModel::data(const QModelIndex& index, int role) const
{
auto& channelCaps = videoDevices_->get_defaultResRateList();
if (!index.isValid() || channelCaps.size() <= index.row() || channelCaps.size() == 0) {
return QVariant();
}
switch (role) {
case Role::Resolution:
return QVariant(channelCaps.at(index.row()).first);
}
return QVariant();
}
QHash<int, QByteArray>
VideoFormatResolutionModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Resolution] = "Resolution";
return roles;
}
int
VideoFormatResolutionModel::getCurrentIndex() const
{
QString currentDeviceId = videoDevices_->get_defaultId();
QString currentResolution = videoDevices_->get_defaultRes();
auto resultList = match(index(0, 0), Resolution, QVariant(currentResolution));
return resultList.size() > 0 ? resultList[0].row() : 0;
}
// VideoFormatFpsModel
VideoFormatFpsModel::VideoFormatFpsModel(LRCInstance* lrcInstance, VideoDevices* videoDeviceInstance)
: QAbstractListModel(videoDeviceInstance)
, lrcInstance_(lrcInstance)
, videoDevices_(videoDeviceInstance)
{}
VideoFormatFpsModel::~VideoFormatFpsModel() {}
int
VideoFormatFpsModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid() && lrcInstance_) {
return videoDevices_->get_defaultFpsList().size();
}
return 0;
}
QVariant
VideoFormatFpsModel::data(const QModelIndex& index, int role) const
{
auto& fpsList = videoDevices_->get_defaultFpsList();
if (!index.isValid() || fpsList.size() == 0 || index.row() >= fpsList.size()) {
return QVariant();
}
switch (role) {
case Role::FPS:
return QVariant(static_cast<int>(fpsList[index.row()]));
case Role::FPS_Float:
return QVariant(fpsList[index.row()]);
}
return QVariant();
}
QHash<int, QByteArray>
VideoFormatFpsModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[FPS] = "FPS";
roles[FPS_Float] = "FPS_Float";
return roles;
}
int
VideoFormatFpsModel::getCurrentIndex() const
{
QString currentDeviceId = videoDevices_->get_defaultId();
float currentFps = videoDevices_->get_defaultFps();
auto resultList = match(index(0, 0), FPS, QVariant(currentFps));
return resultList.size() > 0 ? resultList[0].row() : 0;
}
// VideoDevices
VideoDevices::VideoDevices(LRCInstance* lrcInstance, QObject* parent)
: QObject(parent)
, lrcInstance_(lrcInstance)
, devicesFilterModel_(new CurrentItemFilterModel(this))
, resFilterModel_(new CurrentItemFilterModel(this))
, fpsFilterModel_(new CurrentItemFilterModel(this))
{
devicesSourceModel_ = new VideoInputDeviceModel(lrcInstance, this);
resSourceModel_ = new VideoFormatResolutionModel(lrcInstance, this);
fpsSourceModel_ = new VideoFormatFpsModel(lrcInstance, this);
devicesFilterModel_->setSourceModel(devicesSourceModel_);
resFilterModel_->setSourceModel(resSourceModel_);
fpsFilterModel_->setSourceModel(fpsSourceModel_);
devicesFilterModel_->setFilterRole(VideoInputDeviceModel::DeviceName);
resFilterModel_->setFilterRole(VideoFormatResolutionModel::Resolution);
fpsFilterModel_->setFilterRole(VideoFormatFpsModel::FPS);
connect(&lrcInstance_->avModel(),
&lrc::api::AVModel::deviceEvent,
this,
&VideoDevices::onVideoDeviceEvent);
updateData();
}
VideoDevices::~VideoDevices() {}
QVariant
VideoDevices::devicesFilterModel()
{
return QVariant::fromValue(devicesFilterModel_);
}
QVariant
VideoDevices::devicesSourceModel()
{
return QVariant::fromValue(devicesSourceModel_);
}
QVariant
VideoDevices::resFilterModel()
{
return QVariant::fromValue(resFilterModel_);
}
QVariant
VideoDevices::resSourceModel()
{
return QVariant::fromValue(resSourceModel_);
}
QVariant
VideoDevices::fpsFilterModel()
{
return QVariant::fromValue(fpsFilterModel_);
}
QVariant
VideoDevices::fpsSourceModel()
{
return QVariant::fromValue(fpsSourceModel_);
}
void
VideoDevices::setDefaultDevice(int index, bool useSourceModel)
{
QString deviceId {};
auto callId = lrcInstance_->getCurrentCallId();
if (useSourceModel)
deviceId = devicesSourceModel_
->data(devicesSourceModel_->index(index, 0), VideoInputDeviceModel::DeviceId)
.toString();
else
deviceId = devicesFilterModel_
->data(devicesFilterModel_->index(index, 0), VideoInputDeviceModel::DeviceId)
.toString();
lrcInstance_->avModel().setDefaultDevice(deviceId);
if (!callId.isEmpty())
lrcInstance_->avModel().switchInputTo(deviceId, callId);
updateData();
}
void
VideoDevices::setDefaultDeviceRes(int index)
{
auto& channelCaps = get_defaultResRateList();
auto settings = lrcInstance_->avModel().getDeviceSettings(get_defaultId());
settings.size = resFilterModel_
->data(resFilterModel_->index(index, 0),
VideoFormatResolutionModel::Resolution)
.toString();
for (int i = 0; i < channelCaps.size(); i++) {
if (channelCaps[i].first == settings.size) {
settings.rate = channelCaps[i].second.at(0);
lrcInstance_->avModel().setDeviceSettings(settings);
break;
}
}
updateData();
}
void
VideoDevices::setDefaultDeviceFps(int index)
{
auto settings = lrcInstance_->avModel().getDeviceSettings(get_defaultId());
settings.size = get_defaultRes();
settings.rate = fpsFilterModel_
->data(fpsFilterModel_->index(index, 0), VideoFormatFpsModel::FPS_Float)
.toFloat();
lrcInstance_->avModel().setDeviceSettings(settings);
updateData();
}
void
VideoDevices::updateData()
{
set_listSize(lrcInstance_->avModel().getDevices().size());
if (get_listSize() != 0) {
auto defaultDevice = lrcInstance_->avModel().getDefaultDevice();
auto defaultDeviceSettings = lrcInstance_->avModel().getDeviceSettings(defaultDevice);
auto defaultDeviceCap = lrcInstance_->avModel().getDeviceCapabilities(defaultDevice);
auto currentResRateList = defaultDeviceCap[defaultDeviceSettings.channel.isEmpty()
? "default"
: defaultDeviceSettings.channel];
lrc::api::video::FrameratesList fpsList;
for (int i = 0; i < currentResRateList.size(); i++) {
if (currentResRateList[i].first == defaultDeviceSettings.size) {
fpsList = currentResRateList[i].second;
}
}
set_defaultChannel(defaultDeviceSettings.channel);
set_defaultId(defaultDeviceSettings.id);
set_defaultName(defaultDeviceSettings.name);
set_defaultRes(defaultDeviceSettings.size);
set_defaultFps(defaultDeviceSettings.rate);
set_defaultResRateList(currentResRateList);
set_defaultFpsList(fpsList);
devicesFilterModel_->setCurrentItemFilter(defaultDeviceSettings.name);
resFilterModel_->setCurrentItemFilter(defaultDeviceSettings.size);
fpsFilterModel_->setCurrentItemFilter(static_cast<int>(defaultDeviceSettings.rate));
} else {
set_defaultChannel("");
set_defaultId("");
set_defaultName("");
set_defaultRes("");
set_defaultFps(0);
set_defaultResRateList({});
set_defaultFpsList({});
devicesFilterModel_->setCurrentItemFilter("");
resFilterModel_->setCurrentItemFilter("");
fpsFilterModel_->setCurrentItemFilter(0);
}
devicesSourceModel_->reset();
resSourceModel_->reset();
fpsSourceModel_->reset();
}
void
VideoDevices::onVideoDeviceEvent()
{
auto& avModel = lrcInstance_->avModel();
auto defaultDevice = avModel.getDefaultDevice();
QString callId = lrcInstance_->getCurrentCallId();
// Decide whether a device has plugged, unplugged, or nothing has changed.
auto deviceList = avModel.getDevices();
auto currentDeviceListSize = deviceList.size();
auto previousDeviceListSize = get_listSize();
DeviceEvent deviceEvent {DeviceEvent::None};
if (currentDeviceListSize > previousDeviceListSize) {
if (previousDeviceListSize == 0)
deviceEvent = DeviceEvent::FirstDevice;
else
deviceEvent = DeviceEvent::Added;
} else if (currentDeviceListSize < previousDeviceListSize) {
deviceEvent = DeviceEvent::Removed;
}
auto cb = [this, currentDeviceListSize, deviceEvent, defaultDevice, callId] {
auto& avModel = lrcInstance_->avModel();
if (currentDeviceListSize == 0) {
avModel.switchInputTo({}, callId);
avModel.stopPreview();
} else if (deviceEvent == DeviceEvent::Removed) {
avModel.switchInputTo(defaultDevice, callId);
}
updateData();
Q_EMIT deviceListChanged(currentDeviceListSize);
};
if (deviceEvent == DeviceEvent::Added) {
updateData();
Q_EMIT deviceListChanged(currentDeviceListSize);
} else if (deviceEvent == DeviceEvent::FirstDevice) {
updateData();
if (callId.isEmpty()) {
Q_EMIT deviceAvailable();
} else {
avModel.switchInputTo(defaultDevice, callId);
}
Q_EMIT deviceListChanged(currentDeviceListSize);
} else if (lrcInstance_->renderer()->isPreviewing()) {
updateData();
// Use QueuedConnection to make sure that it happens at the event loop of current device
Utils::oneShotConnect(
lrcInstance_->renderer(),
&RenderManager::previewRenderingStopped,
this,
[cb] { cb(); },
Qt::QueuedConnection);
} else {
cb();
}
}
const lrc::api::video::ResRateList&
VideoDevices::get_defaultResRateList()
{
return defaultResRateList_;
}
void
VideoDevices::set_defaultResRateList(lrc::api::video::ResRateList resRateList)
{
defaultResRateList_.swap(resRateList);
}
const lrc::api::video::FrameratesList&
VideoDevices::get_defaultFpsList()
{
return defaultFpsList_;
}
void
VideoDevices::set_defaultFpsList(lrc::api::video::FrameratesList rateList)
{
defaultFpsList_.swap(rateList);
}

205
src/videodevices.h Normal file
View file

@ -0,0 +1,205 @@
/*!
* Copyright (C) 2020 by Savoir-faire Linux
* Author: Mingrui Zhang <mingrui.zhang@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 "lrcinstance.h"
#include "qtutils.h"
#include "api/newdevicemodel.h"
#include <QSortFilterProxyModel>
#include <QObject>
class VideoDevices;
class CurrentItemFilterModel final : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit CurrentItemFilterModel(QObject* parent = nullptr)
: QSortFilterProxyModel(parent)
{}
void setCurrentItemFilter(const QVariant& filter)
{
currentItemFilter_ = filter;
}
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override
{
// Do not filter if there is only one item.
if (currentItemFilter_.isNull() || sourceModel()->rowCount() == 1)
return true;
// Exclude current item filter.
auto index = sourceModel()->index(sourceRow, 0, sourceParent);
return index.data(filterRole()) != currentItemFilter_ && !index.parent().isValid();
}
private:
QVariant currentItemFilter_ {};
};
class VideoInputDeviceModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Role { DeviceName = Qt::UserRole + 1, DeviceId };
Q_ENUM(Role)
explicit VideoInputDeviceModel(LRCInstance* lrcInstance, VideoDevices* videoDeviceInstance);
~VideoInputDeviceModel();
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void reset()
{
beginResetModel();
endResetModel();
}
// Get model index of the current device
Q_INVOKABLE int getCurrentIndex() const;
private:
LRCInstance* lrcInstance_ {nullptr};
VideoDevices* const videoDevices_;
};
class VideoFormatResolutionModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Role { Resolution = Qt::UserRole + 1 };
Q_ENUM(Role)
explicit VideoFormatResolutionModel(LRCInstance* lrcInstance, VideoDevices* videoDeviceInstance);
~VideoFormatResolutionModel();
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void reset()
{
beginResetModel();
endResetModel();
}
// Get model index of the current device
Q_INVOKABLE int getCurrentIndex() const;
private:
LRCInstance* lrcInstance_ {nullptr};
VideoDevices* const videoDevices_;
};
class VideoFormatFpsModel : public QAbstractListModel
{
Q_OBJECT
public:
enum Role { FPS = Qt::UserRole + 1, FPS_Float };
Q_ENUM(Role)
explicit VideoFormatFpsModel(LRCInstance* lrcInstance, VideoDevices* videoDeviceInstance);
~VideoFormatFpsModel();
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void reset()
{
beginResetModel();
endResetModel();
}
// Get model index of the current device
Q_INVOKABLE int getCurrentIndex() const;
private:
LRCInstance* lrcInstance_;
VideoDevices* const videoDevices_;
};
class VideoDevices : public QObject
{
Q_OBJECT
QML_RO_PROPERTY(int, listSize)
QML_RO_PROPERTY(QString, defaultChannel)
QML_RO_PROPERTY(QString, defaultId)
QML_RO_PROPERTY(QString, defaultName)
QML_RO_PROPERTY(QString, defaultRes)
QML_RO_PROPERTY(int, defaultFps)
public:
explicit VideoDevices(LRCInstance* lrcInstance, QObject* parent = nullptr);
~VideoDevices();
Q_INVOKABLE QVariant devicesFilterModel();
Q_INVOKABLE QVariant devicesSourceModel();
Q_INVOKABLE QVariant resFilterModel();
Q_INVOKABLE QVariant resSourceModel();
Q_INVOKABLE QVariant fpsFilterModel();
Q_INVOKABLE QVariant fpsSourceModel();
Q_INVOKABLE void setDefaultDevice(int index, bool useSourceModel = false);
Q_INVOKABLE void setDefaultDeviceRes(int index);
Q_INVOKABLE void setDefaultDeviceFps(int index);
const lrc::api::video::ResRateList& get_defaultResRateList();
void set_defaultResRateList(lrc::api::video::ResRateList resRateList);
const lrc::api::video::FrameratesList& get_defaultFpsList();
void set_defaultFpsList(lrc::api::video::FrameratesList rateList);
Q_SIGNALS:
void deviceAvailable();
void deviceListChanged(int inputs);
private Q_SLOTS:
void onVideoDeviceEvent();
private:
// Used to classify capture device events.
enum class DeviceEvent { FirstDevice, Added, Removed, None };
void updateData();
LRCInstance* lrcInstance_;
CurrentItemFilterModel* devicesFilterModel_;
CurrentItemFilterModel* resFilterModel_;
CurrentItemFilterModel* fpsFilterModel_;
VideoInputDeviceModel* devicesSourceModel_;
VideoFormatResolutionModel* resSourceModel_;
VideoFormatFpsModel* fpsSourceModel_;
lrc::api::video::ResRateList defaultResRateList_;
lrc::api::video::FrameratesList defaultFpsList_;
};

View file

@ -1,226 +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 "videoformatfpsmodel.h"
#include "lrcinstance.h"
#include "api/account.h"
#include "api/contact.h"
#include "api/conversation.h"
#include "api/newdevicemodel.h"
VideoFormatFpsModel::VideoFormatFpsModel(QObject* parent)
: AbstractListModelBase(parent)
{
connect(this, &AbstractListModelBase::lrcInstanceChanged, [this] {
if (lrcInstance_)
try {
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
currentResolution_ = currentSettings.size;
} catch (const std::exception& e) {
qWarning() << "Constructor of VideoFormatFpsModel, exception: " << e.what();
}
});
}
VideoFormatFpsModel::~VideoFormatFpsModel() {}
int
VideoFormatFpsModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid() && lrcInstance_) {
/*
* Count.
*/
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto deviceCapabilities = lrcInstance_->avModel().getDeviceCapabilities(currentDeviceId);
if (deviceCapabilities.size() == 0) {
return 0;
}
try {
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
auto currentChannel = currentSettings.channel;
currentChannel = currentChannel.isEmpty() ? "default" : currentChannel;
auto channelCaps = deviceCapabilities[currentChannel];
bool resolutionFound = false;
int indexOfCurrentResolutionInResRateList = 0;
for (int i = 0; i < channelCaps.size(); i++) {
if (channelCaps[i].first == currentResolution_) {
indexOfCurrentResolutionInResRateList = i;
resolutionFound = true;
break;
}
}
if (resolutionFound) {
auto fpsList = channelCaps[indexOfCurrentResolutionInResRateList].second;
return fpsList.size();
}
} catch (const std::exception& e) {
qWarning() << e.what();
}
return 0;
}
/*
* A valid QModelIndex returns 0 as no entry has sub-elements.
*/
return 0;
}
int
VideoFormatFpsModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
/*
* Only need one column.
*/
return 1;
}
QVariant
VideoFormatFpsModel::data(const QModelIndex& index, int role) const
{
try {
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto deviceCapabilities = lrcInstance_->avModel().getDeviceCapabilities(currentDeviceId);
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
auto currentChannel = currentSettings.channel;
currentChannel = currentChannel.isEmpty() ? "default" : currentChannel;
auto channelCaps = deviceCapabilities[currentChannel];
bool resolutionFound = false;
int indexOfCurrentResolutionInResRateList = 0;
for (int i = 0; i < channelCaps.size(); i++) {
if (channelCaps[i].first == currentResolution_) {
indexOfCurrentResolutionInResRateList = i;
resolutionFound = true;
break;
}
}
if (!index.isValid() || channelCaps.size() <= index.row() || deviceCapabilities.size() == 0
|| !resolutionFound) {
return QVariant();
}
auto fpsList = channelCaps[indexOfCurrentResolutionInResRateList].second;
switch (role) {
case Role::FPS:
return QVariant(fpsList[index.row()]);
case Role::FPS_ToDisplay_UTF8:
QString rateDisplayUtf8 = QString("%1 fps").arg((int) fpsList[index.row()]);
return QVariant(rateDisplayUtf8.toUtf8());
}
} catch (const std::exception& e) {
qWarning() << e.what();
}
return QVariant();
}
QHash<int, QByteArray>
VideoFormatFpsModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[FPS] = "FPS";
roles[FPS_ToDisplay_UTF8] = "FPS_ToDisplay_UTF8";
return roles;
}
QModelIndex
VideoFormatFpsModel::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
VideoFormatFpsModel::parent(const QModelIndex& child) const
{
Q_UNUSED(child);
return QModelIndex();
}
Qt::ItemFlags
VideoFormatFpsModel::flags(const QModelIndex& index) const
{
auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
if (!index.isValid()) {
return QAbstractItemModel::flags(index);
}
return flags;
}
void
VideoFormatFpsModel::reset()
{
beginResetModel();
endResetModel();
}
int
VideoFormatFpsModel::getCurrentSettingIndex()
{
int resultRowIndex = 0;
try {
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
float currentFps = currentSettings.rate;
auto resultList = match(index(0, 0), FPS, QVariant(currentFps));
if (resultList.size() > 0) {
resultRowIndex = resultList[0].row();
}
} catch (const std::exception& e) {
qWarning() << e.what();
}
return resultRowIndex;
}
QString
VideoFormatFpsModel::getCurrentResolution()
{
return currentResolution_;
}
void
VideoFormatFpsModel::setCurrentResolution(QString resNew)
{
if (currentResolution_ != resNew) {
currentResolution_ = resNew;
reset();
Q_EMIT currentResolutionChanged(resNew);
}
}

View file

@ -1,70 +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 "abstractlistmodelbase.h"
class VideoFormatFpsModel : public AbstractListModelBase
{
Q_OBJECT
Q_PROPERTY(QString currentResolution READ getCurrentResolution WRITE setCurrentResolution NOTIFY
currentResolutionChanged);
public:
enum Role { FPS = Qt::UserRole + 1, FPS_ToDisplay_UTF8 };
Q_ENUM(Role)
explicit VideoFormatFpsModel(QObject* parent = nullptr);
~VideoFormatFpsModel();
/*
* 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();
/*
* Getters and setters
*/
QString getCurrentResolution();
void setCurrentResolution(QString resNew);
Q_SIGNALS:
void currentResolutionChanged(QString resNew);
private:
QString currentResolution_;
};

View file

@ -1,171 +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 "videoformatresolutionmodel.h"
#include "lrcinstance.h"
#include "api/account.h"
#include "api/contact.h"
#include "api/conversation.h"
#include "api/newdevicemodel.h"
VideoFormatResolutionModel::VideoFormatResolutionModel(QObject* parent)
: AbstractListModelBase(parent)
{}
VideoFormatResolutionModel::~VideoFormatResolutionModel() {}
int
VideoFormatResolutionModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid() && lrcInstance_) {
/*
* Count.
*/
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto deviceCapabilities = lrcInstance_->avModel().getDeviceCapabilities(currentDeviceId);
if (deviceCapabilities.size() == 0) {
return 0;
}
try {
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
auto currentChannel = currentSettings.channel;
currentChannel = currentChannel.isEmpty() ? "default" : currentChannel;
auto channelCaps = deviceCapabilities[currentChannel];
return channelCaps.size();
} catch (const std::exception& e) {
qWarning() << e.what();
return 0;
}
}
/*
* A valid QModelIndex returns 0 as no entry has sub-elements.
*/
return 0;
}
int
VideoFormatResolutionModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
/*
* Only need one column.
*/
return 1;
}
QVariant
VideoFormatResolutionModel::data(const QModelIndex& index, int role) const
{
try {
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto deviceCapabilities = lrcInstance_->avModel().getDeviceCapabilities(currentDeviceId);
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
auto currentChannel = currentSettings.channel;
currentChannel = currentChannel.isEmpty() ? "default" : currentChannel;
auto channelCaps = deviceCapabilities[currentChannel];
if (!index.isValid() || channelCaps.size() <= index.row()
|| deviceCapabilities.size() == 0) {
return QVariant();
}
switch (role) {
case Role::Resolution:
return QVariant(channelCaps.at(index.row()).first);
case Role::Resolution_UTF8:
return QVariant(channelCaps.at(index.row()).first.toUtf8());
}
} catch (const std::exception& e) {
qWarning() << e.what();
}
return QVariant();
}
QHash<int, QByteArray>
VideoFormatResolutionModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[Resolution] = "Resolution";
roles[Resolution_UTF8] = "Resolution_UTF8";
return roles;
}
QModelIndex
VideoFormatResolutionModel::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
VideoFormatResolutionModel::parent(const QModelIndex& child) const
{
Q_UNUSED(child);
return QModelIndex();
}
Qt::ItemFlags
VideoFormatResolutionModel::flags(const QModelIndex& index) const
{
auto flags = QAbstractItemModel::flags(index) | Qt::ItemNeverHasChildren | Qt::ItemIsSelectable;
if (!index.isValid()) {
return QAbstractItemModel::flags(index);
}
return flags;
}
void
VideoFormatResolutionModel::reset()
{
beginResetModel();
endResetModel();
}
int
VideoFormatResolutionModel::getCurrentSettingIndex()
{
int resultRowIndex = 0;
try {
QString currentDeviceId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto currentSettings = lrcInstance_->avModel().getDeviceSettings(currentDeviceId);
QString currentResolution = currentSettings.size;
auto resultList = match(index(0, 0), Resolution, QVariant(currentResolution));
if (resultList.size() > 0) {
resultRowIndex = resultList[0].row();
}
} catch (const std::exception& e) {
qWarning() << e.what();
}
return resultRowIndex;
}

View file

@ -1,55 +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 "abstractlistmodelbase.h"
class VideoFormatResolutionModel : public AbstractListModelBase
{
Q_OBJECT
public:
enum Role { Resolution = Qt::UserRole + 1, Resolution_UTF8 };
Q_ENUM(Role)
explicit VideoFormatResolutionModel(QObject* parent = nullptr);
~VideoFormatResolutionModel();
/*
* 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();
};

View file

@ -1,106 +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 "videoinputdevicemodel.h"
#include "lrcinstance.h"
#include "api/newdevicemodel.h"
VideoInputDeviceModel::VideoInputDeviceModel(QObject* parent)
: AbstractListModelBase(parent)
{}
VideoInputDeviceModel::~VideoInputDeviceModel() {}
int
VideoInputDeviceModel::rowCount(const QModelIndex& parent) const
{
if (!parent.isValid() && lrcInstance_) {
return lrcInstance_->avModel().getDevices().size();
}
return 0;
}
QVariant
VideoInputDeviceModel::data(const QModelIndex& index, int role) const
{
auto deviceList = lrcInstance_->avModel().getDevices();
if (!index.isValid()) {
return QVariant();
}
if (deviceList.size() <= index.row()) {
return QVariant();
}
auto currentDeviceSetting = lrcInstance_->avModel().getDeviceSettings(deviceList[index.row()]);
switch (role) {
case Role::DeviceChannel:
return QVariant((QString) currentDeviceSetting.channel);
case Role::DeviceName:
return QVariant(currentDeviceSetting.name);
case Role::DeviceId:
return QVariant(currentDeviceSetting.id);
case Role::CurrentFrameRate:
return QVariant((float) currentDeviceSetting.rate);
case Role::CurrentResolution:
return QVariant((QString) currentDeviceSetting.size);
case Role::DeviceName_UTF8:
return QVariant(currentDeviceSetting.name.toUtf8());
case Role::isCurrent:
return QVariant(index.row() == getCurrentIndex());
}
return QVariant();
}
QHash<int, QByteArray>
VideoInputDeviceModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[DeviceChannel] = "DeviceChannel";
roles[DeviceName] = "DeviceName";
roles[DeviceId] = "DeviceId";
roles[CurrentFrameRate] = "CurrentFrameRate";
roles[CurrentResolution] = "CurrentResolution";
roles[DeviceName_UTF8] = "DeviceName_UTF8";
roles[isCurrent] = "isCurrent";
return roles;
}
void
VideoInputDeviceModel::reset()
{
beginResetModel();
endResetModel();
}
int
VideoInputDeviceModel::deviceCount()
{
return lrcInstance_->avModel().getDevices().size();
}
int
VideoInputDeviceModel::getCurrentIndex() const
{
QString currentId = lrcInstance_->avModel().getCurrentVideoCaptureDevice();
auto resultList = match(index(0, 0), DeviceId, QVariant(currentId));
return resultList.size() > 0 ? resultList[0].row() : 0;
}

View file

@ -1,50 +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 "abstractlistmodelbase.h"
class VideoInputDeviceModel : public AbstractListModelBase
{
Q_OBJECT
public:
enum Role {
DeviceName = Qt::UserRole + 1,
DeviceChannel,
DeviceId,
CurrentFrameRate,
CurrentResolution,
DeviceName_UTF8,
isCurrent
};
Q_ENUM(Role)
explicit VideoInputDeviceModel(QObject* parent = nullptr);
~VideoInputDeviceModel();
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void reset();
Q_INVOKABLE int deviceCount();
// get model index of the current device
Q_INVOKABLE int getCurrentIndex() const;
};