UI: Defer device properties to separate thread
Because devices can take significant time to enumerate, defer the properties creation to a separate thread. The author of this commit feels a great amount of displeasure over having to write this.
This commit is contained in:
parent
ab2f3edb2b
commit
fcf01304d2
@ -238,6 +238,7 @@ set(obs_SOURCES
|
||||
item-widget-helpers.cpp
|
||||
context-bar-controls.cpp
|
||||
horizontal-scroll-area.cpp
|
||||
context-bar-controls-devices.cpp
|
||||
vertical-scroll-area.cpp
|
||||
visibility-item-widget.cpp
|
||||
slider-absoluteset-style.cpp
|
||||
@ -305,6 +306,7 @@ set(obs_HEADERS
|
||||
item-widget-helpers.hpp
|
||||
visibility-checkbox.hpp
|
||||
context-bar-controls.hpp
|
||||
context-bar-controls-devices.hpp
|
||||
locked-checkbox.hpp
|
||||
horizontal-scroll-area.hpp
|
||||
expand-checkbox.hpp
|
||||
|
149
UI/context-bar-controls-devices.cpp
Normal file
149
UI/context-bar-controls-devices.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
#include "context-bar-controls.hpp"
|
||||
#include "context-bar-controls-devices.hpp"
|
||||
#include "window-basic-main.hpp"
|
||||
|
||||
#include "ui_device-select-toolbar.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define get_os_module(win, mac, linux) obs_get_module(win)
|
||||
#define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, win)
|
||||
#elif __APPLE__
|
||||
#define get_os_module(win, mac, linux) obs_get_module(mac)
|
||||
#define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, mac)
|
||||
#else
|
||||
#define get_os_module(win, mac, linux) obs_get_module(linux)
|
||||
#define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, linux)
|
||||
#endif
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
DeviceToolbarPropertiesThread::~DeviceToolbarPropertiesThread()
|
||||
{
|
||||
obs_properties_destroy(props);
|
||||
}
|
||||
|
||||
void DeviceToolbarPropertiesThread::run()
|
||||
{
|
||||
props = obs_source_properties(source);
|
||||
source = nullptr;
|
||||
QMetaObject::invokeMethod(this, "Ready");
|
||||
}
|
||||
|
||||
void DeviceToolbarPropertiesThread::Ready()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
QLayoutItem *la = main->ui->emptySpace->layout()->itemAt(0);
|
||||
if (la) {
|
||||
DeviceCaptureToolbar *dct =
|
||||
qobject_cast<DeviceCaptureToolbar *>(la->widget());
|
||||
if (dct) {
|
||||
dct->SetProperties(props);
|
||||
props = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
DeviceCaptureToolbar::DeviceCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: QWidget(parent),
|
||||
weakSource(OBSGetWeakRef(source)),
|
||||
ui(new Ui_DeviceSelectToolbar)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
#ifndef _WIN32
|
||||
delete ui->activateButton;
|
||||
ui->activateButton = nullptr;
|
||||
#endif
|
||||
|
||||
setEnabled(false);
|
||||
|
||||
obs_module_t *mod =
|
||||
get_os_module("win-dshow", "mac-avcapture", "linux-v4l2");
|
||||
const char *device_str = obs_module_get_locale_text(mod, "Device");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
if (!main->devicePropertiesThread ||
|
||||
!main->devicePropertiesThread->isRunning()) {
|
||||
main->devicePropertiesThread.reset(
|
||||
new DeviceToolbarPropertiesThread(source));
|
||||
main->devicePropertiesThread->start();
|
||||
}
|
||||
}
|
||||
|
||||
DeviceCaptureToolbar::~DeviceCaptureToolbar()
|
||||
{
|
||||
delete ui;
|
||||
obs_properties_destroy(props);
|
||||
}
|
||||
|
||||
void DeviceCaptureToolbar::UpdateActivateButtonName()
|
||||
{
|
||||
obs_property_t *p = obs_properties_get(props, "activate");
|
||||
ui->activateButton->setText(obs_property_description(p));
|
||||
}
|
||||
|
||||
extern void UpdateSourceComboToolbarProperties(QComboBox *combo,
|
||||
OBSSource source,
|
||||
obs_properties_t *props,
|
||||
const char *prop_name,
|
||||
bool is_int);
|
||||
extern void UpdateSourceComboToolbarValue(QComboBox *combo, OBSSource source,
|
||||
int idx, const char *prop_name,
|
||||
bool is_int);
|
||||
|
||||
void DeviceCaptureToolbar::SetProperties(obs_properties_t *props_)
|
||||
{
|
||||
OBSSource source = OBSGetStrongRef(weakSource);
|
||||
if (!source) {
|
||||
obs_properties_destroy(props_);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
prop_name = "video_device_id";
|
||||
#elif __APPLE__
|
||||
prop_name = "device";
|
||||
#else
|
||||
prop_name = "device_id";
|
||||
#endif
|
||||
|
||||
props = props_;
|
||||
UpdateSourceComboToolbarProperties(ui->device, source, props, prop_name,
|
||||
false);
|
||||
#ifdef _WIN32
|
||||
UpdateActivateButtonName();
|
||||
#endif
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
void DeviceCaptureToolbar::on_device_currentIndexChanged(int idx)
|
||||
{
|
||||
OBSSource source = OBSGetStrongRef(weakSource);
|
||||
if (idx == -1 || !source) {
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateSourceComboToolbarValue(ui->device, source, idx, prop_name,
|
||||
false);
|
||||
}
|
||||
|
||||
void DeviceCaptureToolbar::on_activateButton_clicked()
|
||||
{
|
||||
OBSSource source = OBSGetStrongRef(weakSource);
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_property_t *p = obs_properties_get(props, "activate");
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_property_button_clicked(p, source.Get());
|
||||
#ifdef _WIN32
|
||||
UpdateActivateButtonName();
|
||||
#endif
|
||||
}
|
25
UI/context-bar-controls-devices.hpp
Normal file
25
UI/context-bar-controls-devices.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <obs.hpp>
|
||||
#include <string>
|
||||
#include <QThread>
|
||||
|
||||
class DeviceToolbarPropertiesThread : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
OBSSource source;
|
||||
obs_properties_t *props;
|
||||
|
||||
void run() override;
|
||||
|
||||
public:
|
||||
inline DeviceToolbarPropertiesThread(OBSSource source_)
|
||||
: source(source_)
|
||||
{
|
||||
}
|
||||
|
||||
~DeviceToolbarPropertiesThread() override;
|
||||
|
||||
public slots:
|
||||
void Ready();
|
||||
};
|
@ -152,12 +152,6 @@ void ComboSelectToolbar::Init()
|
||||
prop_name, is_int);
|
||||
}
|
||||
|
||||
void ComboSelectToolbar::UpdateActivateButtonName()
|
||||
{
|
||||
obs_property_t *p = obs_properties_get(props.get(), "activate");
|
||||
ui->activateButton->setText(obs_property_description(p));
|
||||
}
|
||||
|
||||
void UpdateSourceComboToolbarValue(QComboBox *combo, OBSSource source, int idx,
|
||||
const char *prop_name, bool is_int)
|
||||
{
|
||||
@ -184,22 +178,6 @@ void ComboSelectToolbar::on_device_currentIndexChanged(int idx)
|
||||
is_int);
|
||||
}
|
||||
|
||||
void ComboSelectToolbar::on_activateButton_clicked()
|
||||
{
|
||||
OBSSource source = GetSource();
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_property_t *p = obs_properties_get(props.get(), "activate");
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_property_button_clicked(p, source.Get());
|
||||
UpdateActivateButtonName();
|
||||
}
|
||||
|
||||
AudioCaptureToolbar::AudioCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: ComboSelectToolbar(parent, source)
|
||||
{
|
||||
@ -278,38 +256,6 @@ void DisplayCaptureToolbar::Init()
|
||||
ComboSelectToolbar::Init();
|
||||
}
|
||||
|
||||
DeviceCaptureToolbar::DeviceCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: ComboSelectToolbar(parent, source)
|
||||
{
|
||||
}
|
||||
|
||||
void DeviceCaptureToolbar::Init()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
delete ui->activateButton;
|
||||
ui->activateButton = nullptr;
|
||||
#endif
|
||||
|
||||
obs_module_t *mod =
|
||||
get_os_module("win-dshow", "mac-avcapture", "linux-v4l2");
|
||||
const char *device_str = obs_module_get_locale_text(mod, "Device");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
#ifdef _WIN32
|
||||
prop_name = "video_device_id";
|
||||
#elif __APPLE__
|
||||
prop_name = "device";
|
||||
#else
|
||||
prop_name = "device_id";
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
UpdateActivateButtonName();
|
||||
#endif
|
||||
|
||||
ComboSelectToolbar::Init();
|
||||
}
|
||||
|
||||
/* ========================================================================= */
|
||||
|
||||
GameCaptureToolbar::GameCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
|
@ -53,8 +53,6 @@ protected:
|
||||
const char *prop_name;
|
||||
bool is_int = false;
|
||||
|
||||
void UpdateActivateButtonName();
|
||||
|
||||
public:
|
||||
ComboSelectToolbar(QWidget *parent, OBSSource source);
|
||||
~ComboSelectToolbar();
|
||||
@ -62,7 +60,6 @@ public:
|
||||
|
||||
public slots:
|
||||
void on_device_currentIndexChanged(int idx);
|
||||
void on_activateButton_clicked();
|
||||
};
|
||||
|
||||
class AudioCaptureToolbar : public ComboSelectToolbar {
|
||||
@ -89,12 +86,25 @@ public:
|
||||
void Init() override;
|
||||
};
|
||||
|
||||
class DeviceCaptureToolbar : public ComboSelectToolbar {
|
||||
class DeviceCaptureToolbar : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
OBSWeakSource weakSource;
|
||||
Ui_DeviceSelectToolbar *ui;
|
||||
obs_properties_t *props = nullptr;
|
||||
const char *prop_name;
|
||||
|
||||
void UpdateActivateButtonName();
|
||||
|
||||
public:
|
||||
DeviceCaptureToolbar(QWidget *parent, OBSSource source);
|
||||
void Init() override;
|
||||
~DeviceCaptureToolbar();
|
||||
|
||||
void SetProperties(obs_properties_t *prpos);
|
||||
|
||||
public slots:
|
||||
void on_device_currentIndexChanged(int idx);
|
||||
void on_activateButton_clicked();
|
||||
};
|
||||
|
||||
class GameCaptureToolbar : public SourceToolbar {
|
||||
|
@ -908,6 +908,13 @@ void OBSBasic::Load(const char *file)
|
||||
InitDefaultTransitions();
|
||||
ClearContextBar();
|
||||
|
||||
if (devicePropertiesThread && devicePropertiesThread->isRunning()) {
|
||||
devicePropertiesThread->wait();
|
||||
devicePropertiesThread.reset();
|
||||
}
|
||||
|
||||
QApplication::sendPostedEvents(this);
|
||||
|
||||
obs_data_t *modulesObj = obs_data_get_obj(data, "modules");
|
||||
if (api)
|
||||
api->on_preload(modulesObj);
|
||||
@ -2951,7 +2958,6 @@ void OBSBasic::UpdateContextBar()
|
||||
strcmp(id, "v4l2_input") == 0) {
|
||||
DeviceCaptureToolbar *c = new DeviceCaptureToolbar(
|
||||
ui->emptySpace, source);
|
||||
c->Init();
|
||||
ui->emptySpace->layout()->addWidget(c);
|
||||
|
||||
} else if (strcmp(id, "game_capture") == 0) {
|
||||
@ -4193,6 +4199,12 @@ void OBSBasic::closeEvent(QCloseEvent *event)
|
||||
updateCheckThread->wait();
|
||||
if (logUploadThread)
|
||||
logUploadThread->wait();
|
||||
if (devicePropertiesThread && devicePropertiesThread->isRunning()) {
|
||||
devicePropertiesThread->wait();
|
||||
devicePropertiesThread.reset();
|
||||
}
|
||||
|
||||
QApplication::sendPostedEvents(this);
|
||||
|
||||
signalHandlers.clear();
|
||||
|
||||
|
@ -163,6 +163,8 @@ class OBSBasic : public OBSMainWindow {
|
||||
friend class ReplayBufferButton;
|
||||
friend class ExtraBrowsersModel;
|
||||
friend class ExtraBrowsersDelegate;
|
||||
friend class DeviceCaptureToolbar;
|
||||
friend class DeviceToolbarPropertiesThread;
|
||||
friend struct BasicOutputHandler;
|
||||
friend struct OBSStudioAPI;
|
||||
|
||||
@ -198,6 +200,7 @@ private:
|
||||
bool copyVisible = true;
|
||||
|
||||
bool closing = false;
|
||||
QScopedPointer<QThread> devicePropertiesThread;
|
||||
QScopedPointer<QThread> whatsNewInitThread;
|
||||
QScopedPointer<QThread> updateCheckThread;
|
||||
QScopedPointer<QThread> introCheckThread;
|
||||
|
Loading…
x
Reference in New Issue
Block a user