mirror of
https://github.com/obsproject/obs-studio
synced 2024-10-22 23:51:37 +00:00
clang-format: Increase column limit from 80 to 120
This commit is contained in:
parent
109f64c446
commit
a1fbf1015f
|
@ -44,7 +44,7 @@ BreakBeforeBraces: Custom
|
|||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakStringLiterals: false # apparently unpredictable
|
||||
ColumnLimit: 80
|
||||
ColumnLimit: 120
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
|
|
|
@ -6,8 +6,7 @@ AbsoluteSlider::AbsoluteSlider(QWidget *parent) : SliderIgnoreScroll(parent)
|
|||
setMouseTracking(true);
|
||||
}
|
||||
|
||||
AbsoluteSlider::AbsoluteSlider(Qt::Orientation orientation, QWidget *parent)
|
||||
: SliderIgnoreScroll(orientation, parent)
|
||||
AbsoluteSlider::AbsoluteSlider(Qt::Orientation orientation, QWidget *parent) : SliderIgnoreScroll(orientation, parent)
|
||||
{
|
||||
installEventFilter(this);
|
||||
setMouseTracking(true);
|
||||
|
@ -15,8 +14,7 @@ AbsoluteSlider::AbsoluteSlider(Qt::Orientation orientation, QWidget *parent)
|
|||
|
||||
void AbsoluteSlider::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
dragging = (event->buttons() & Qt::LeftButton ||
|
||||
event->buttons() & Qt::MiddleButton);
|
||||
dragging = (event->buttons() & Qt::LeftButton || event->buttons() & Qt::MiddleButton);
|
||||
|
||||
if (dragging) {
|
||||
setSliderDown(true);
|
||||
|
@ -59,8 +57,7 @@ bool AbsoluteSlider::eventFilter(QObject *obj, QEvent *event)
|
|||
if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
|
||||
if (keyEvent->key() == Qt::Key_Up ||
|
||||
keyEvent->key() == Qt::Key_Down) {
|
||||
if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -78,10 +75,8 @@ int AbsoluteSlider::posToRangeValue(QMouseEvent *event)
|
|||
int sliderMax;
|
||||
int handleLength;
|
||||
|
||||
const QRect groove = style()->subControlRect(
|
||||
QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
const QRect handle = style()->subControlRect(
|
||||
QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||
const QRect groove = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
|
||||
const QRect handle = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||
|
||||
if (orientation() == Qt::Horizontal) {
|
||||
pos = event->pos().x();
|
||||
|
@ -95,9 +90,8 @@ int AbsoluteSlider::posToRangeValue(QMouseEvent *event)
|
|||
sliderMax = groove.bottom() - (handleLength / 2) + 1;
|
||||
}
|
||||
|
||||
int sliderValue = style()->sliderValueFromPosition(
|
||||
minimum(), maximum(), pos - sliderMin, sliderMax - sliderMin,
|
||||
opt.upsideDown);
|
||||
int sliderValue = style()->sliderValueFromPosition(minimum(), maximum(), pos - sliderMin, sliderMax - sliderMin,
|
||||
opt.upsideDown);
|
||||
|
||||
return sliderValue;
|
||||
}
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
|
||||
#define MIN_DB -96.0
|
||||
#define MAX_DB 26.0
|
||||
static inline void setMixer(obs_source_t *source, const int mixerIdx,
|
||||
const bool checked);
|
||||
static inline void setMixer(obs_source_t *source, const int mixerIdx, const bool checked);
|
||||
|
||||
OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
||||
: source(source_)
|
||||
OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_) : source(source_)
|
||||
{
|
||||
QHBoxLayout *hlayout;
|
||||
signal_handler_t *handler = obs_source_get_signal_handler(source);
|
||||
|
@ -54,18 +52,14 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
sigs.emplace_back(handler, "activate", OBSSourceActivated, this);
|
||||
sigs.emplace_back(handler, "deactivate", OBSSourceDeactivated, this);
|
||||
sigs.emplace_back(handler, "audio_activate", OBSSourceActivated, this);
|
||||
sigs.emplace_back(handler, "audio_deactivate", OBSSourceDeactivated,
|
||||
this);
|
||||
sigs.emplace_back(handler, "audio_deactivate", OBSSourceDeactivated, this);
|
||||
sigs.emplace_back(handler, "volume", OBSSourceVolumeChanged, this);
|
||||
sigs.emplace_back(handler, "audio_sync", OBSSourceSyncChanged, this);
|
||||
sigs.emplace_back(handler, "update_flags", OBSSourceFlagsChanged, this);
|
||||
if (obs_audio_monitoring_available())
|
||||
sigs.emplace_back(handler, "audio_monitoring",
|
||||
OBSSourceMonitoringTypeChanged, this);
|
||||
sigs.emplace_back(handler, "audio_mixers", OBSSourceMixersChanged,
|
||||
this);
|
||||
sigs.emplace_back(handler, "audio_balance", OBSSourceBalanceChanged,
|
||||
this);
|
||||
sigs.emplace_back(handler, "audio_monitoring", OBSSourceMonitoringTypeChanged, this);
|
||||
sigs.emplace_back(handler, "audio_mixers", OBSSourceMixersChanged, this);
|
||||
sigs.emplace_back(handler, "audio_balance", OBSSourceBalanceChanged, this);
|
||||
sigs.emplace_back(handler, "rename", OBSSourceRenamed, this);
|
||||
|
||||
hlayout = new QHBoxLayout();
|
||||
|
@ -90,10 +84,8 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
SetSourceName(sourceName);
|
||||
nameLabel->setAlignment(Qt::AlignVCenter);
|
||||
|
||||
bool isActive = obs_source_active(source) &&
|
||||
obs_source_audio_active(source);
|
||||
active->setText(isActive ? QTStr("Basic.Stats.Status.Active")
|
||||
: QTStr("Basic.Stats.Status.Inactive"));
|
||||
bool isActive = obs_source_active(source) && obs_source_audio_active(source);
|
||||
active->setText(isActive ? QTStr("Basic.Stats.Status.Active") : QTStr("Basic.Stats.Status.Inactive"));
|
||||
if (isActive)
|
||||
setClasses(active, "text-danger");
|
||||
active->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
|
@ -104,8 +96,7 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
volume->setDecimals(1);
|
||||
volume->setSuffix(" dB");
|
||||
volume->setValue(obs_mul_to_db(vol));
|
||||
volume->setAccessibleName(
|
||||
QTStr("Basic.AdvAudio.VolumeSource").arg(sourceName));
|
||||
volume->setAccessibleName(QTStr("Basic.AdvAudio.VolumeSource").arg(sourceName));
|
||||
|
||||
if (volume->value() < MIN_DB) {
|
||||
volume->setSpecialValueText("-inf dB");
|
||||
|
@ -116,34 +107,29 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
percent->setMaximum(2000);
|
||||
percent->setSuffix("%");
|
||||
percent->setValue((int)(obs_source_get_volume(source) * 100.0f));
|
||||
percent->setAccessibleName(
|
||||
QTStr("Basic.AdvAudio.VolumeSource").arg(sourceName));
|
||||
percent->setAccessibleName(QTStr("Basic.AdvAudio.VolumeSource").arg(sourceName));
|
||||
|
||||
stackedWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
||||
stackedWidget->setFixedWidth(100);
|
||||
stackedWidget->addWidget(volume);
|
||||
stackedWidget->addWidget(percent);
|
||||
|
||||
VolumeType volType = (VolumeType)config_get_int(
|
||||
App()->GetUserConfig(), "BasicWindow", "AdvAudioVolumeType");
|
||||
VolumeType volType = (VolumeType)config_get_int(App()->GetUserConfig(), "BasicWindow", "AdvAudioVolumeType");
|
||||
|
||||
SetVolumeWidget(volType);
|
||||
|
||||
forceMono->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
forceMono->setChecked((flags & OBS_SOURCE_FLAG_FORCE_MONO) != 0);
|
||||
forceMono->setAccessibleName(
|
||||
QTStr("Basic.AdvAudio.MonoSource").arg(sourceName));
|
||||
forceMono->setAccessibleName(QTStr("Basic.AdvAudio.MonoSource").arg(sourceName));
|
||||
|
||||
balance->setOrientation(Qt::Horizontal);
|
||||
balance->setMinimum(0);
|
||||
balance->setMaximum(100);
|
||||
balance->setTickPosition(QSlider::TicksAbove);
|
||||
balance->setTickInterval(50);
|
||||
balance->setAccessibleName(
|
||||
QTStr("Basic.AdvAudio.BalanceSource").arg(sourceName));
|
||||
balance->setAccessibleName(QTStr("Basic.AdvAudio.BalanceSource").arg(sourceName));
|
||||
|
||||
const char *speakers =
|
||||
config_get_string(main->Config(), "Audio", "ChannelSetup");
|
||||
const char *speakers = config_get_string(main->Config(), "Audio", "ChannelSetup");
|
||||
|
||||
if (strcmp(speakers, "Mono") == 0)
|
||||
balance->setEnabled(false);
|
||||
|
@ -159,53 +145,40 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
syncOffset->setSuffix(" ms");
|
||||
syncOffset->setValue(int(cur_sync / NSEC_PER_MSEC));
|
||||
syncOffset->setFixedWidth(100);
|
||||
syncOffset->setAccessibleName(
|
||||
QTStr("Basic.AdvAudio.SyncOffsetSource").arg(sourceName));
|
||||
syncOffset->setAccessibleName(QTStr("Basic.AdvAudio.SyncOffsetSource").arg(sourceName));
|
||||
|
||||
int idx;
|
||||
if (obs_audio_monitoring_available()) {
|
||||
monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.None"),
|
||||
(int)OBS_MONITORING_TYPE_NONE);
|
||||
monitoringType->addItem(
|
||||
QTStr("Basic.AdvAudio.Monitoring.MonitorOnly"),
|
||||
(int)OBS_MONITORING_TYPE_MONITOR_ONLY);
|
||||
monitoringType->addItem(
|
||||
QTStr("Basic.AdvAudio.Monitoring.Both"),
|
||||
(int)OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT);
|
||||
monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.None"), (int)OBS_MONITORING_TYPE_NONE);
|
||||
monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.MonitorOnly"),
|
||||
(int)OBS_MONITORING_TYPE_MONITOR_ONLY);
|
||||
monitoringType->addItem(QTStr("Basic.AdvAudio.Monitoring.Both"),
|
||||
(int)OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT);
|
||||
int mt = (int)obs_source_get_monitoring_type(source);
|
||||
idx = monitoringType->findData(mt);
|
||||
monitoringType->setCurrentIndex(idx);
|
||||
monitoringType->setAccessibleName(
|
||||
QTStr("Basic.AdvAudio.MonitoringSource")
|
||||
.arg(sourceName));
|
||||
monitoringType->setSizePolicy(QSizePolicy::Maximum,
|
||||
QSizePolicy::Fixed);
|
||||
monitoringType->setAccessibleName(QTStr("Basic.AdvAudio.MonitoringSource").arg(sourceName));
|
||||
monitoringType->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
}
|
||||
|
||||
mixer1->setText("1");
|
||||
mixer1->setChecked(mixers & (1 << 0));
|
||||
mixer1->setAccessibleName(
|
||||
QTStr("Basic.Settings.Output.Adv.Audio.Track1"));
|
||||
mixer1->setAccessibleName(QTStr("Basic.Settings.Output.Adv.Audio.Track1"));
|
||||
mixer2->setText("2");
|
||||
mixer2->setChecked(mixers & (1 << 1));
|
||||
mixer2->setAccessibleName(
|
||||
QTStr("Basic.Settings.Output.Adv.Audio.Track2"));
|
||||
mixer2->setAccessibleName(QTStr("Basic.Settings.Output.Adv.Audio.Track2"));
|
||||
mixer3->setText("3");
|
||||
mixer3->setChecked(mixers & (1 << 2));
|
||||
mixer3->setAccessibleName(
|
||||
QTStr("Basic.Settings.Output.Adv.Audio.Track3"));
|
||||
mixer3->setAccessibleName(QTStr("Basic.Settings.Output.Adv.Audio.Track3"));
|
||||
mixer4->setText("4");
|
||||
mixer4->setChecked(mixers & (1 << 3));
|
||||
mixer4->setAccessibleName(
|
||||
QTStr("Basic.Settings.Output.Adv.Audio.Track4"));
|
||||
mixer4->setAccessibleName(QTStr("Basic.Settings.Output.Adv.Audio.Track4"));
|
||||
mixer5->setText("5");
|
||||
mixer5->setChecked(mixers & (1 << 4));
|
||||
mixer5->setAccessibleName(
|
||||
QTStr("Basic.Settings.Output.Adv.Audio.Track5"));
|
||||
mixer5->setAccessibleName(QTStr("Basic.Settings.Output.Adv.Audio.Track5"));
|
||||
mixer6->setText("6");
|
||||
mixer6->setChecked(mixers & (1 << 5));
|
||||
mixer6->setAccessibleName(
|
||||
QTStr("Basic.Settings.Output.Adv.Audio.Track6"));
|
||||
mixer6->setAccessibleName(QTStr("Basic.Settings.Output.Adv.Audio.Track6"));
|
||||
|
||||
balanceContainer->layout()->addWidget(labelL);
|
||||
balanceContainer->layout()->addWidget(balance);
|
||||
|
@ -224,26 +197,17 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
mixerContainer->layout()->addWidget(mixer6);
|
||||
mixerContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
|
||||
connect(volume, &QDoubleSpinBox::valueChanged, this,
|
||||
&OBSAdvAudioCtrl::volumeChanged);
|
||||
connect(percent, &QSpinBox::valueChanged, this,
|
||||
&OBSAdvAudioCtrl::percentChanged);
|
||||
connect(forceMono, &QCheckBox::clicked, this,
|
||||
&OBSAdvAudioCtrl::downmixMonoChanged);
|
||||
connect(balance, &BalanceSlider::valueChanged, this,
|
||||
&OBSAdvAudioCtrl::balanceChanged);
|
||||
connect(balance, &BalanceSlider::doubleClicked, this,
|
||||
&OBSAdvAudioCtrl::ResetBalance);
|
||||
connect(syncOffset, &QSpinBox::valueChanged, this,
|
||||
&OBSAdvAudioCtrl::syncOffsetChanged);
|
||||
connect(volume, &QDoubleSpinBox::valueChanged, this, &OBSAdvAudioCtrl::volumeChanged);
|
||||
connect(percent, &QSpinBox::valueChanged, this, &OBSAdvAudioCtrl::percentChanged);
|
||||
connect(forceMono, &QCheckBox::clicked, this, &OBSAdvAudioCtrl::downmixMonoChanged);
|
||||
connect(balance, &BalanceSlider::valueChanged, this, &OBSAdvAudioCtrl::balanceChanged);
|
||||
connect(balance, &BalanceSlider::doubleClicked, this, &OBSAdvAudioCtrl::ResetBalance);
|
||||
connect(syncOffset, &QSpinBox::valueChanged, this, &OBSAdvAudioCtrl::syncOffsetChanged);
|
||||
if (obs_audio_monitoring_available())
|
||||
connect(monitoringType, &QComboBox::currentIndexChanged, this,
|
||||
&OBSAdvAudioCtrl::monitoringTypeChanged);
|
||||
connect(monitoringType, &QComboBox::currentIndexChanged, this, &OBSAdvAudioCtrl::monitoringTypeChanged);
|
||||
|
||||
auto connectMixer = [this](QCheckBox *mixer, int num) {
|
||||
connect(mixer, &QCheckBox::clicked, [this, num](bool checked) {
|
||||
setMixer(source, num, checked);
|
||||
});
|
||||
connect(mixer, &QCheckBox::clicked, [this, num](bool checked) { setMixer(source, num, checked); });
|
||||
};
|
||||
connectMixer(mixer1, 0);
|
||||
connectMixer(mixer2, 1);
|
||||
|
@ -293,67 +257,62 @@ void OBSAdvAudioCtrl::ShowAudioControl(QGridLayout *layout)
|
|||
|
||||
void OBSAdvAudioCtrl::OBSSourceActivated(void *param, calldata_t *)
|
||||
{
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceActiveChanged", Q_ARG(bool, true));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceActiveChanged", Q_ARG(bool, true));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceDeactivated(void *param, calldata_t *)
|
||||
{
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceActiveChanged", Q_ARG(bool, false));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceActiveChanged",
|
||||
Q_ARG(bool, false));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceFlagsChanged(void *param, calldata_t *calldata)
|
||||
{
|
||||
uint32_t flags = (uint32_t)calldata_int(calldata, "flags");
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceFlagsChanged", Q_ARG(uint32_t, flags));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceFlagsChanged",
|
||||
Q_ARG(uint32_t, flags));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceVolumeChanged(void *param, calldata_t *calldata)
|
||||
{
|
||||
float volume = (float)calldata_float(calldata, "volume");
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceVolumeChanged", Q_ARG(float, volume));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceVolumeChanged",
|
||||
Q_ARG(float, volume));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceSyncChanged(void *param, calldata_t *calldata)
|
||||
{
|
||||
int64_t offset = calldata_int(calldata, "offset");
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceSyncChanged", Q_ARG(int64_t, offset));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceSyncChanged",
|
||||
Q_ARG(int64_t, offset));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceMonitoringTypeChanged(void *param,
|
||||
calldata_t *calldata)
|
||||
void OBSAdvAudioCtrl::OBSSourceMonitoringTypeChanged(void *param, calldata_t *calldata)
|
||||
{
|
||||
int type = calldata_int(calldata, "type");
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceMonitoringTypeChanged",
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceMonitoringTypeChanged",
|
||||
Q_ARG(int, type));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceMixersChanged(void *param, calldata_t *calldata)
|
||||
{
|
||||
uint32_t mixers = (uint32_t)calldata_int(calldata, "mixers");
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceMixersChanged",
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceMixersChanged",
|
||||
Q_ARG(uint32_t, mixers));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceBalanceChanged(void *param, calldata_t *calldata)
|
||||
{
|
||||
int balance = (float)calldata_float(calldata, "balance") * 100.0f;
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceBalanceChanged", Q_ARG(int, balance));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SourceBalanceChanged",
|
||||
Q_ARG(int, balance));
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceRenamed(void *param, calldata_t *calldata)
|
||||
{
|
||||
QString newName = QT_UTF8(calldata_string(calldata, "new_name"));
|
||||
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SetSourceName", Q_ARG(QString, newName));
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param), "SetSourceName", Q_ARG(QString, newName));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -441,19 +400,16 @@ void OBSAdvAudioCtrl::volumeChanged(double db)
|
|||
obs_source_set_volume(source, val);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, float val) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_source_set_volume(source, val);
|
||||
};
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
main->undo_s.add_action(
|
||||
QTStr("Undo.Volume.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid,
|
||||
true);
|
||||
main->undo_s.add_action(QTStr("Undo.Volume.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid, true);
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::percentChanged(int percent)
|
||||
|
@ -464,18 +420,15 @@ void OBSAdvAudioCtrl::percentChanged(int percent)
|
|||
obs_source_set_volume(source, val);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, float val) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_source_set_volume(source, val);
|
||||
};
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic::Get()->undo_s.add_action(
|
||||
QTStr("Undo.Volume.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid,
|
||||
true);
|
||||
OBSBasic::Get()->undo_s.add_action(QTStr("Undo.Volume.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid, true);
|
||||
}
|
||||
|
||||
static inline void set_mono(obs_source_t *source, bool mono)
|
||||
|
@ -504,8 +457,7 @@ void OBSAdvAudioCtrl::downmixMonoChanged(bool val)
|
|||
obs_source_set_flags(source, flags);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, bool val) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
set_mono(source, val);
|
||||
};
|
||||
|
||||
|
@ -513,10 +465,8 @@ void OBSAdvAudioCtrl::downmixMonoChanged(bool val)
|
|||
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic::Get()->undo_s.add_action(
|
||||
text.arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, !val),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid);
|
||||
OBSBasic::Get()->undo_s.add_action(text.arg(name), std::bind(undo_redo, std::placeholders::_1, !val),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid);
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::balanceChanged(int val)
|
||||
|
@ -534,18 +484,15 @@ void OBSAdvAudioCtrl::balanceChanged(int val)
|
|||
obs_source_set_balance_value(source, bal);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, float val) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_source_set_balance_value(source, val);
|
||||
};
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic::Get()->undo_s.add_action(
|
||||
QTStr("Undo.Balance.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, bal), uuid, uuid,
|
||||
true);
|
||||
OBSBasic::Get()->undo_s.add_action(QTStr("Undo.Balance.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, bal), uuid, uuid, true);
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::ResetBalance()
|
||||
|
@ -564,26 +511,22 @@ void OBSAdvAudioCtrl::syncOffsetChanged(int milliseconds)
|
|||
obs_source_set_sync_offset(source, val);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, int64_t val) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_source_set_sync_offset(source, val);
|
||||
};
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic::Get()->undo_s.add_action(
|
||||
QTStr("Undo.SyncOffset.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid,
|
||||
true);
|
||||
OBSBasic::Get()->undo_s.add_action(QTStr("Undo.SyncOffset.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, val), uuid, uuid, true);
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::monitoringTypeChanged(int index)
|
||||
{
|
||||
obs_monitoring_type prev = obs_source_get_monitoring_type(source);
|
||||
|
||||
obs_monitoring_type mt =
|
||||
(obs_monitoring_type)monitoringType->itemData(index).toInt();
|
||||
obs_monitoring_type mt = (obs_monitoring_type)monitoringType->itemData(index).toInt();
|
||||
obs_source_set_monitoring_type(source, mt);
|
||||
|
||||
const char *type = nullptr;
|
||||
|
@ -601,24 +544,20 @@ void OBSAdvAudioCtrl::monitoringTypeChanged(int index)
|
|||
}
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
blog(LOG_INFO, "User changed audio monitoring for source '%s' to: %s",
|
||||
name ? name : "(null)", type);
|
||||
blog(LOG_INFO, "User changed audio monitoring for source '%s' to: %s", name ? name : "(null)", type);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, obs_monitoring_type val) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_source_set_monitoring_type(source, val);
|
||||
};
|
||||
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic::Get()->undo_s.add_action(
|
||||
QTStr("Undo.MonitoringType.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, mt), uuid, uuid);
|
||||
OBSBasic::Get()->undo_s.add_action(QTStr("Undo.MonitoringType.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, prev),
|
||||
std::bind(undo_redo, std::placeholders::_1, mt), uuid, uuid);
|
||||
}
|
||||
|
||||
static inline void setMixer(obs_source_t *source, const int mixerIdx,
|
||||
const bool checked)
|
||||
static inline void setMixer(obs_source_t *source, const int mixerIdx, const bool checked)
|
||||
{
|
||||
uint32_t mixers = obs_source_get_audio_mixers(source);
|
||||
uint32_t new_mixers = mixers;
|
||||
|
@ -631,18 +570,15 @@ static inline void setMixer(obs_source_t *source, const int mixerIdx,
|
|||
obs_source_set_audio_mixers(source, new_mixers);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, uint32_t mixers) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_source_set_audio_mixers(source, mixers);
|
||||
};
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
OBSBasic::Get()->undo_s.add_action(
|
||||
QTStr("Undo.Mixers.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, mixers),
|
||||
std::bind(undo_redo, std::placeholders::_1, new_mixers), uuid,
|
||||
uuid);
|
||||
OBSBasic::Get()->undo_s.add_action(QTStr("Undo.Mixers.Change").arg(name),
|
||||
std::bind(undo_redo, std::placeholders::_1, mixers),
|
||||
std::bind(undo_redo, std::placeholders::_1, new_mixers), uuid, uuid);
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::SetVolumeWidget(VolumeType type)
|
||||
|
|
|
@ -53,8 +53,7 @@ private:
|
|||
static void OBSSourceFlagsChanged(void *param, calldata_t *calldata);
|
||||
static void OBSSourceVolumeChanged(void *param, calldata_t *calldata);
|
||||
static void OBSSourceSyncChanged(void *param, calldata_t *calldata);
|
||||
static void OBSSourceMonitoringTypeChanged(void *param,
|
||||
calldata_t *calldata);
|
||||
static void OBSSourceMonitoringTypeChanged(void *param, calldata_t *calldata);
|
||||
static void OBSSourceMixersChanged(void *param, calldata_t *calldata);
|
||||
static void OBSSourceBalanceChanged(void *param, calldata_t *calldata);
|
||||
static void OBSSourceRenamed(void *param, calldata_t *calldata);
|
||||
|
|
|
@ -28,19 +28,15 @@ template<typename T> struct OBSStudioCallback {
|
|||
T callback;
|
||||
void *private_data;
|
||||
|
||||
inline OBSStudioCallback(T cb, void *p) : callback(cb), private_data(p)
|
||||
{
|
||||
}
|
||||
inline OBSStudioCallback(T cb, void *p) : callback(cb), private_data(p) {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline size_t GetCallbackIdx(vector<OBSStudioCallback<T>> &callbacks,
|
||||
T callback, void *private_data)
|
||||
inline size_t GetCallbackIdx(vector<OBSStudioCallback<T>> &callbacks, T callback, void *private_data)
|
||||
{
|
||||
for (size_t i = 0; i < callbacks.size(); i++) {
|
||||
OBSStudioCallback<T> curCB = callbacks[i];
|
||||
if (curCB.callback == callback &&
|
||||
curCB.private_data == private_data)
|
||||
if (curCB.callback == callback && curCB.private_data == private_data)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -55,23 +51,13 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
inline OBSStudioAPI(OBSBasic *main_) : main(main_) {}
|
||||
|
||||
void *obs_frontend_get_main_window(void) override
|
||||
{
|
||||
return (void *)main;
|
||||
}
|
||||
void *obs_frontend_get_main_window(void) override { return (void *)main; }
|
||||
|
||||
void *obs_frontend_get_main_window_handle(void) override
|
||||
{
|
||||
return (void *)main->winId();
|
||||
}
|
||||
void *obs_frontend_get_main_window_handle(void) override { return (void *)main->winId(); }
|
||||
|
||||
void *obs_frontend_get_system_tray(void) override
|
||||
{
|
||||
return (void *)main->trayIcon.data();
|
||||
}
|
||||
void *obs_frontend_get_system_tray(void) override { return (void *)main->trayIcon.data(); }
|
||||
|
||||
void obs_frontend_get_scenes(
|
||||
struct obs_frontend_source_list *sources) override
|
||||
void obs_frontend_get_scenes(struct obs_frontend_source_list *sources) override
|
||||
{
|
||||
for (int i = 0; i < main->ui->scenes->count(); i++) {
|
||||
QListWidgetItem *item = main->ui->scenes->item(i);
|
||||
|
@ -96,23 +82,18 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
void obs_frontend_set_current_scene(obs_source_t *scene) override
|
||||
{
|
||||
if (main->IsPreviewProgramMode()) {
|
||||
QMetaObject::invokeMethod(
|
||||
main, "TransitionToScene", WaitConnection(),
|
||||
Q_ARG(OBSSource, OBSSource(scene)));
|
||||
QMetaObject::invokeMethod(main, "TransitionToScene", WaitConnection(),
|
||||
Q_ARG(OBSSource, OBSSource(scene)));
|
||||
} else {
|
||||
QMetaObject::invokeMethod(
|
||||
main, "SetCurrentScene", WaitConnection(),
|
||||
Q_ARG(OBSSource, OBSSource(scene)),
|
||||
Q_ARG(bool, false));
|
||||
QMetaObject::invokeMethod(main, "SetCurrentScene", WaitConnection(),
|
||||
Q_ARG(OBSSource, OBSSource(scene)), Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_get_transitions(
|
||||
struct obs_frontend_source_list *sources) override
|
||||
void obs_frontend_get_transitions(struct obs_frontend_source_list *sources) override
|
||||
{
|
||||
for (int i = 0; i < main->ui->transitions->count(); i++) {
|
||||
OBSSource tr = main->ui->transitions->itemData(i)
|
||||
.value<OBSSource>();
|
||||
OBSSource tr = main->ui->transitions->itemData(i).value<OBSSource>();
|
||||
|
||||
if (!tr)
|
||||
continue;
|
||||
|
@ -128,62 +109,43 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return obs_source_get_ref(tr);
|
||||
}
|
||||
|
||||
void
|
||||
obs_frontend_set_current_transition(obs_source_t *transition) override
|
||||
void obs_frontend_set_current_transition(obs_source_t *transition) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "SetTransition",
|
||||
Q_ARG(OBSSource,
|
||||
OBSSource(transition)));
|
||||
QMetaObject::invokeMethod(main, "SetTransition", Q_ARG(OBSSource, OBSSource(transition)));
|
||||
}
|
||||
|
||||
int obs_frontend_get_transition_duration(void) override
|
||||
{
|
||||
return main->ui->transitionDuration->value();
|
||||
}
|
||||
int obs_frontend_get_transition_duration(void) override { return main->ui->transitionDuration->value(); }
|
||||
|
||||
void obs_frontend_set_transition_duration(int duration) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main->ui->transitionDuration,
|
||||
"setValue", Q_ARG(int, duration));
|
||||
QMetaObject::invokeMethod(main->ui->transitionDuration, "setValue", Q_ARG(int, duration));
|
||||
}
|
||||
|
||||
void obs_frontend_release_tbar(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "TBarReleased");
|
||||
}
|
||||
void obs_frontend_release_tbar(void) override { QMetaObject::invokeMethod(main, "TBarReleased"); }
|
||||
|
||||
void obs_frontend_set_tbar_position(int position) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "TBarChanged",
|
||||
Q_ARG(int, position));
|
||||
QMetaObject::invokeMethod(main, "TBarChanged", Q_ARG(int, position));
|
||||
}
|
||||
|
||||
int obs_frontend_get_tbar_position(void) override
|
||||
{
|
||||
return main->tBar->value();
|
||||
}
|
||||
int obs_frontend_get_tbar_position(void) override { return main->tBar->value(); }
|
||||
|
||||
void obs_frontend_get_scene_collections(
|
||||
std::vector<std::string> &strings) override
|
||||
void obs_frontend_get_scene_collections(std::vector<std::string> &strings) override
|
||||
{
|
||||
for (auto &[collectionName, collection] :
|
||||
main->GetSceneCollectionCache()) {
|
||||
for (auto &[collectionName, collection] : main->GetSceneCollectionCache()) {
|
||||
strings.emplace_back(collectionName);
|
||||
}
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_scene_collection(void) override
|
||||
{
|
||||
const OBSSceneCollection ¤tCollection =
|
||||
main->GetCurrentSceneCollection();
|
||||
const OBSSceneCollection ¤tCollection = main->GetCurrentSceneCollection();
|
||||
return bstrdup(currentCollection.name.c_str());
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene_collection(
|
||||
const char *collection) override
|
||||
void obs_frontend_set_current_scene_collection(const char *collection) override
|
||||
{
|
||||
QList<QAction *> menuActions =
|
||||
main->ui->sceneCollectionMenu->actions();
|
||||
QList<QAction *> menuActions = main->ui->sceneCollectionMenu->actions();
|
||||
QString qstrCollection = QT_UTF8(collection);
|
||||
|
||||
for (int i = 0; i < menuActions.count(); i++) {
|
||||
|
@ -202,15 +164,12 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
bool obs_frontend_add_scene_collection(const char *name) override
|
||||
{
|
||||
bool success = false;
|
||||
QMetaObject::invokeMethod(main, "CreateNewSceneCollection",
|
||||
WaitConnection(),
|
||||
Q_RETURN_ARG(bool, success),
|
||||
Q_ARG(QString, QT_UTF8(name)));
|
||||
QMetaObject::invokeMethod(main, "CreateNewSceneCollection", WaitConnection(),
|
||||
Q_RETURN_ARG(bool, success), Q_ARG(QString, QT_UTF8(name)));
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
obs_frontend_get_profiles(std::vector<std::string> &strings) override
|
||||
void obs_frontend_get_profiles(std::vector<std::string> &strings) override
|
||||
{
|
||||
const OBSProfileCache &profiles = main->GetProfileCache();
|
||||
|
||||
|
@ -252,69 +211,42 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
void obs_frontend_create_profile(const char *name) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "CreateNewProfile",
|
||||
Q_ARG(QString, name));
|
||||
QMetaObject::invokeMethod(main, "CreateNewProfile", Q_ARG(QString, name));
|
||||
}
|
||||
|
||||
void obs_frontend_duplicate_profile(const char *name) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "CreateDuplicateProfile",
|
||||
Q_ARG(QString, name));
|
||||
QMetaObject::invokeMethod(main, "CreateDuplicateProfile", Q_ARG(QString, name));
|
||||
}
|
||||
|
||||
void obs_frontend_delete_profile(const char *profile) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "DeleteProfile",
|
||||
Q_ARG(QString, profile));
|
||||
QMetaObject::invokeMethod(main, "DeleteProfile", Q_ARG(QString, profile));
|
||||
}
|
||||
|
||||
void obs_frontend_streaming_start(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StartStreaming");
|
||||
}
|
||||
void obs_frontend_streaming_start(void) override { QMetaObject::invokeMethod(main, "StartStreaming"); }
|
||||
|
||||
void obs_frontend_streaming_stop(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StopStreaming");
|
||||
}
|
||||
void obs_frontend_streaming_stop(void) override { QMetaObject::invokeMethod(main, "StopStreaming"); }
|
||||
|
||||
bool obs_frontend_streaming_active(void) override
|
||||
{
|
||||
return os_atomic_load_bool(&streaming_active);
|
||||
}
|
||||
bool obs_frontend_streaming_active(void) override { return os_atomic_load_bool(&streaming_active); }
|
||||
|
||||
void obs_frontend_recording_start(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StartRecording");
|
||||
}
|
||||
void obs_frontend_recording_start(void) override { QMetaObject::invokeMethod(main, "StartRecording"); }
|
||||
|
||||
void obs_frontend_recording_stop(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StopRecording");
|
||||
}
|
||||
void obs_frontend_recording_stop(void) override { QMetaObject::invokeMethod(main, "StopRecording"); }
|
||||
|
||||
bool obs_frontend_recording_active(void) override
|
||||
{
|
||||
return os_atomic_load_bool(&recording_active);
|
||||
}
|
||||
bool obs_frontend_recording_active(void) override { return os_atomic_load_bool(&recording_active); }
|
||||
|
||||
void obs_frontend_recording_pause(bool pause) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, pause ? "PauseRecording"
|
||||
: "UnpauseRecording");
|
||||
QMetaObject::invokeMethod(main, pause ? "PauseRecording" : "UnpauseRecording");
|
||||
}
|
||||
|
||||
bool obs_frontend_recording_paused(void) override
|
||||
{
|
||||
return os_atomic_load_bool(&recording_paused);
|
||||
}
|
||||
bool obs_frontend_recording_paused(void) override { return os_atomic_load_bool(&recording_paused); }
|
||||
|
||||
bool obs_frontend_recording_split_file(void) override
|
||||
{
|
||||
if (os_atomic_load_bool(&recording_active) &&
|
||||
!os_atomic_load_bool(&recording_paused)) {
|
||||
proc_handler_t *ph = obs_output_get_proc_handler(
|
||||
main->outputHandler->fileOutput);
|
||||
if (os_atomic_load_bool(&recording_active) && !os_atomic_load_bool(&recording_paused)) {
|
||||
proc_handler_t *ph = obs_output_get_proc_handler(main->outputHandler->fileOutput);
|
||||
uint8_t stack[128];
|
||||
calldata cd;
|
||||
calldata_init_fixed(&cd, stack, sizeof(stack));
|
||||
|
@ -328,12 +260,10 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
bool obs_frontend_recording_add_chapter(const char *name) override
|
||||
{
|
||||
if (!os_atomic_load_bool(&recording_active) ||
|
||||
os_atomic_load_bool(&recording_paused))
|
||||
if (!os_atomic_load_bool(&recording_active) || os_atomic_load_bool(&recording_paused))
|
||||
return false;
|
||||
|
||||
proc_handler_t *ph = obs_output_get_proc_handler(
|
||||
main->outputHandler->fileOutput);
|
||||
proc_handler_t *ph = obs_output_get_proc_handler(main->outputHandler->fileOutput);
|
||||
|
||||
calldata cd;
|
||||
calldata_init(&cd);
|
||||
|
@ -343,25 +273,13 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return result;
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_start(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StartReplayBuffer");
|
||||
}
|
||||
void obs_frontend_replay_buffer_start(void) override { QMetaObject::invokeMethod(main, "StartReplayBuffer"); }
|
||||
|
||||
void obs_frontend_replay_buffer_save(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "ReplayBufferSave");
|
||||
}
|
||||
void obs_frontend_replay_buffer_save(void) override { QMetaObject::invokeMethod(main, "ReplayBufferSave"); }
|
||||
|
||||
void obs_frontend_replay_buffer_stop(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StopReplayBuffer");
|
||||
}
|
||||
void obs_frontend_replay_buffer_stop(void) override { QMetaObject::invokeMethod(main, "StopReplayBuffer"); }
|
||||
|
||||
bool obs_frontend_replay_buffer_active(void) override
|
||||
{
|
||||
return os_atomic_load_bool(&replaybuf_active);
|
||||
}
|
||||
bool obs_frontend_replay_buffer_active(void) override { return os_atomic_load_bool(&replaybuf_active); }
|
||||
|
||||
void *obs_frontend_add_tools_menu_qaction(const char *name) override
|
||||
{
|
||||
|
@ -369,9 +287,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return (void *)main->ui->menuTools->addAction(QT_UTF8(name));
|
||||
}
|
||||
|
||||
void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback, void *private_data) override
|
||||
{
|
||||
main->ui->menuTools->setEnabled(true);
|
||||
|
||||
|
@ -389,9 +305,8 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
QString name = d->objectName();
|
||||
if (name.isEmpty() || main->IsDockObjectNameUsed(name)) {
|
||||
blog(LOG_WARNING,
|
||||
"The object name of the added dock is empty or already used,"
|
||||
" a temporary one will be set to avoid conflicts");
|
||||
blog(LOG_WARNING, "The object name of the added dock is empty or already used,"
|
||||
" a temporary one will be set to avoid conflicts");
|
||||
|
||||
char *uuid = os_generate_uuid();
|
||||
name = QT_UTF8(uuid);
|
||||
|
@ -404,8 +319,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return (void *)main->AddDockWidget(d);
|
||||
}
|
||||
|
||||
bool obs_frontend_add_dock_by_id(const char *id, const char *title,
|
||||
void *widget) override
|
||||
bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget) override
|
||||
{
|
||||
if (main->IsDockObjectNameUsed(QT_UTF8(id))) {
|
||||
blog(LOG_WARNING,
|
||||
|
@ -428,10 +342,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return true;
|
||||
}
|
||||
|
||||
void obs_frontend_remove_dock(const char *id) override
|
||||
{
|
||||
main->RemoveDockWidget(QT_UTF8(id));
|
||||
}
|
||||
void obs_frontend_remove_dock(const char *id) override { main->RemoveDockWidget(QT_UTF8(id)); }
|
||||
|
||||
bool obs_frontend_add_custom_qdock(const char *id, void *dock) override
|
||||
{
|
||||
|
@ -451,16 +362,14 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return true;
|
||||
}
|
||||
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data) override
|
||||
{
|
||||
size_t idx = GetCallbackIdx(callbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
callbacks.emplace_back(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data) override
|
||||
{
|
||||
size_t idx = GetCallbackIdx(callbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
|
@ -471,13 +380,8 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
obs_output_t *obs_frontend_get_streaming_output(void) override
|
||||
{
|
||||
auto multitrackVideo =
|
||||
main->outputHandler->multitrackVideo.get();
|
||||
auto mtvOutput =
|
||||
multitrackVideo
|
||||
? obs_output_get_ref(
|
||||
multitrackVideo->StreamingOutput())
|
||||
: nullptr;
|
||||
auto multitrackVideo = main->outputHandler->multitrackVideo.get();
|
||||
auto mtvOutput = multitrackVideo ? obs_output_get_ref(multitrackVideo->StreamingOutput()) : nullptr;
|
||||
if (mtvOutput)
|
||||
return mtvOutput;
|
||||
|
||||
|
@ -497,10 +401,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return obs_output_get_ref(out);
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_profile_config(void) override
|
||||
{
|
||||
return main->activeConfiguration;
|
||||
}
|
||||
config_t *obs_frontend_get_profile_config(void) override { return main->activeConfiguration; }
|
||||
|
||||
config_t *obs_frontend_get_global_config(void) override
|
||||
{
|
||||
|
@ -509,19 +410,11 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return App()->GetAppConfig();
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_app_config(void) override
|
||||
{
|
||||
return App()->GetAppConfig();
|
||||
}
|
||||
config_t *obs_frontend_get_app_config(void) override { return App()->GetAppConfig(); }
|
||||
|
||||
config_t *obs_frontend_get_user_config(void) override
|
||||
{
|
||||
return App()->GetUserConfig();
|
||||
}
|
||||
config_t *obs_frontend_get_user_config(void) override { return App()->GetUserConfig(); }
|
||||
|
||||
void obs_frontend_open_projector(const char *type, int monitor,
|
||||
const char *geometry,
|
||||
const char *name) override
|
||||
void obs_frontend_open_projector(const char *type, int monitor, const char *geometry, const char *name) override
|
||||
{
|
||||
SavedProjectorInfo proj = {
|
||||
ProjectorType::Preview,
|
||||
|
@ -539,108 +432,71 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
else if (astrcmpi(type, "Multiview") == 0)
|
||||
proj.type = ProjectorType::Multiview;
|
||||
}
|
||||
QMetaObject::invokeMethod(main, "OpenSavedProjector",
|
||||
WaitConnection(),
|
||||
QMetaObject::invokeMethod(main, "OpenSavedProjector", WaitConnection(),
|
||||
Q_ARG(SavedProjectorInfo *, &proj));
|
||||
}
|
||||
|
||||
void obs_frontend_save(void) override { main->SaveProject(); }
|
||||
|
||||
void obs_frontend_defer_save_begin(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "DeferSaveBegin");
|
||||
}
|
||||
void obs_frontend_defer_save_begin(void) override { QMetaObject::invokeMethod(main, "DeferSaveBegin"); }
|
||||
|
||||
void obs_frontend_defer_save_end(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "DeferSaveEnd");
|
||||
}
|
||||
void obs_frontend_defer_save_end(void) override { QMetaObject::invokeMethod(main, "DeferSaveEnd"); }
|
||||
|
||||
void obs_frontend_add_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data) override
|
||||
{
|
||||
size_t idx =
|
||||
GetCallbackIdx(saveCallbacks, callback, private_data);
|
||||
size_t idx = GetCallbackIdx(saveCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
saveCallbacks.emplace_back(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data) override
|
||||
{
|
||||
size_t idx =
|
||||
GetCallbackIdx(saveCallbacks, callback, private_data);
|
||||
size_t idx = GetCallbackIdx(saveCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
return;
|
||||
|
||||
saveCallbacks.erase(saveCallbacks.begin() + idx);
|
||||
}
|
||||
|
||||
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data) override
|
||||
{
|
||||
size_t idx = GetCallbackIdx(preloadCallbacks, callback,
|
||||
private_data);
|
||||
size_t idx = GetCallbackIdx(preloadCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
preloadCallbacks.emplace_back(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) override
|
||||
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data) override
|
||||
{
|
||||
size_t idx = GetCallbackIdx(preloadCallbacks, callback,
|
||||
private_data);
|
||||
size_t idx = GetCallbackIdx(preloadCallbacks, callback, private_data);
|
||||
if (idx == (size_t)-1)
|
||||
return;
|
||||
|
||||
preloadCallbacks.erase(preloadCallbacks.begin() + idx);
|
||||
}
|
||||
|
||||
void obs_frontend_push_ui_translation(
|
||||
obs_frontend_translate_ui_cb translate) override
|
||||
void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate) override
|
||||
{
|
||||
App()->PushUITranslation(translate);
|
||||
}
|
||||
|
||||
void obs_frontend_pop_ui_translation(void) override
|
||||
{
|
||||
App()->PopUITranslation();
|
||||
}
|
||||
void obs_frontend_pop_ui_translation(void) override { App()->PopUITranslation(); }
|
||||
|
||||
void obs_frontend_set_streaming_service(obs_service_t *service) override
|
||||
{
|
||||
main->SetService(service);
|
||||
}
|
||||
void obs_frontend_set_streaming_service(obs_service_t *service) override { main->SetService(service); }
|
||||
|
||||
obs_service_t *obs_frontend_get_streaming_service(void) override
|
||||
{
|
||||
return main->GetService();
|
||||
}
|
||||
obs_service_t *obs_frontend_get_streaming_service(void) override { return main->GetService(); }
|
||||
|
||||
void obs_frontend_save_streaming_service(void) override
|
||||
{
|
||||
main->SaveService();
|
||||
}
|
||||
void obs_frontend_save_streaming_service(void) override { main->SaveService(); }
|
||||
|
||||
bool obs_frontend_preview_program_mode_active(void) override
|
||||
{
|
||||
return main->IsPreviewProgramMode();
|
||||
}
|
||||
bool obs_frontend_preview_program_mode_active(void) override { return main->IsPreviewProgramMode(); }
|
||||
|
||||
void obs_frontend_set_preview_program_mode(bool enable) override
|
||||
{
|
||||
main->SetPreviewProgramMode(enable);
|
||||
}
|
||||
void obs_frontend_set_preview_program_mode(bool enable) override { main->SetPreviewProgramMode(enable); }
|
||||
|
||||
void obs_frontend_preview_program_trigger_transition(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "TransitionClicked");
|
||||
}
|
||||
|
||||
bool obs_frontend_preview_enabled(void) override
|
||||
{
|
||||
return main->previewEnabled;
|
||||
}
|
||||
bool obs_frontend_preview_enabled(void) override { return main->previewEnabled; }
|
||||
|
||||
void obs_frontend_set_preview_enabled(bool enable) override
|
||||
{
|
||||
|
@ -658,26 +514,19 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
obs_frontend_set_current_preview_scene(obs_source_t *scene) override
|
||||
void obs_frontend_set_current_preview_scene(obs_source_t *scene) override
|
||||
{
|
||||
if (main->IsPreviewProgramMode()) {
|
||||
QMetaObject::invokeMethod(main, "SetCurrentScene",
|
||||
Q_ARG(OBSSource,
|
||||
OBSSource(scene)),
|
||||
QMetaObject::invokeMethod(main, "SetCurrentScene", Q_ARG(OBSSource, OBSSource(scene)),
|
||||
Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
|
||||
void obs_frontend_take_screenshot(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "Screenshot");
|
||||
}
|
||||
void obs_frontend_take_screenshot(void) override { QMetaObject::invokeMethod(main, "Screenshot"); }
|
||||
|
||||
void obs_frontend_take_source_screenshot(obs_source_t *source) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "Screenshot",
|
||||
Q_ARG(OBSSource, OBSSource(source)));
|
||||
QMetaObject::invokeMethod(main, "Screenshot", Q_ARG(OBSSource, OBSSource(source)));
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_virtualcam_output(void) override
|
||||
|
@ -686,47 +535,32 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return obs_output_get_ref(output);
|
||||
}
|
||||
|
||||
void obs_frontend_start_virtualcam(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StartVirtualCam");
|
||||
}
|
||||
void obs_frontend_start_virtualcam(void) override { QMetaObject::invokeMethod(main, "StartVirtualCam"); }
|
||||
|
||||
void obs_frontend_stop_virtualcam(void) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "StopVirtualCam");
|
||||
}
|
||||
void obs_frontend_stop_virtualcam(void) override { QMetaObject::invokeMethod(main, "StopVirtualCam"); }
|
||||
|
||||
bool obs_frontend_virtualcam_active(void) override
|
||||
{
|
||||
return os_atomic_load_bool(&virtualcam_active);
|
||||
}
|
||||
bool obs_frontend_virtualcam_active(void) override { return os_atomic_load_bool(&virtualcam_active); }
|
||||
|
||||
void obs_frontend_reset_video(void) override { main->ResetVideo(); }
|
||||
|
||||
void obs_frontend_open_source_properties(obs_source_t *source) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "OpenProperties",
|
||||
Q_ARG(OBSSource, OBSSource(source)));
|
||||
QMetaObject::invokeMethod(main, "OpenProperties", Q_ARG(OBSSource, OBSSource(source)));
|
||||
}
|
||||
|
||||
void obs_frontend_open_source_filters(obs_source_t *source) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "OpenFilters",
|
||||
Q_ARG(OBSSource, OBSSource(source)));
|
||||
QMetaObject::invokeMethod(main, "OpenFilters", Q_ARG(OBSSource, OBSSource(source)));
|
||||
}
|
||||
|
||||
void obs_frontend_open_source_interaction(obs_source_t *source) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "OpenInteraction",
|
||||
Q_ARG(OBSSource, OBSSource(source)));
|
||||
QMetaObject::invokeMethod(main, "OpenInteraction", Q_ARG(OBSSource, OBSSource(source)));
|
||||
}
|
||||
|
||||
void obs_frontend_open_sceneitem_edit_transform(
|
||||
obs_sceneitem_t *item) override
|
||||
void obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item) override
|
||||
{
|
||||
QMetaObject::invokeMethod(main, "OpenEditTransform",
|
||||
Q_ARG(OBSSceneItem,
|
||||
OBSSceneItem(item)));
|
||||
QMetaObject::invokeMethod(main, "OpenEditTransform", Q_ARG(OBSSceneItem, OBSSceneItem(item)));
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_record_output_path(void) override
|
||||
|
@ -736,43 +570,25 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return bstrdup(recordOutputPath);
|
||||
}
|
||||
|
||||
const char *obs_frontend_get_locale_string(const char *string) override
|
||||
{
|
||||
return Str(string);
|
||||
}
|
||||
const char *obs_frontend_get_locale_string(const char *string) override { return Str(string); }
|
||||
|
||||
bool obs_frontend_is_theme_dark(void) override
|
||||
{
|
||||
return App()->IsThemeDark();
|
||||
}
|
||||
bool obs_frontend_is_theme_dark(void) override { return App()->IsThemeDark(); }
|
||||
|
||||
char *obs_frontend_get_last_recording(void) override
|
||||
{
|
||||
return bstrdup(main->outputHandler->lastRecordingPath.c_str());
|
||||
}
|
||||
|
||||
char *obs_frontend_get_last_screenshot(void) override
|
||||
{
|
||||
return bstrdup(main->lastScreenshot.c_str());
|
||||
}
|
||||
char *obs_frontend_get_last_screenshot(void) override { return bstrdup(main->lastScreenshot.c_str()); }
|
||||
|
||||
char *obs_frontend_get_last_replay(void) override
|
||||
{
|
||||
return bstrdup(main->lastReplay.c_str());
|
||||
}
|
||||
char *obs_frontend_get_last_replay(void) override { return bstrdup(main->lastReplay.c_str()); }
|
||||
|
||||
void obs_frontend_add_undo_redo_action(const char *name,
|
||||
const undo_redo_cb undo,
|
||||
const undo_redo_cb redo,
|
||||
const char *undo_data,
|
||||
const char *redo_data,
|
||||
bool repeatable) override
|
||||
void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
|
||||
const char *undo_data, const char *redo_data, bool repeatable) override
|
||||
{
|
||||
main->undo_s.add_action(
|
||||
name,
|
||||
[undo](const std::string &data) { undo(data.c_str()); },
|
||||
[redo](const std::string &data) { redo(data.c_str()); },
|
||||
undo_data, redo_data, repeatable);
|
||||
name, [undo](const std::string &data) { undo(data.c_str()); },
|
||||
[redo](const std::string &data) { redo(data.c_str()); }, undo_data, redo_data, repeatable);
|
||||
}
|
||||
|
||||
void on_load(obs_data_t *settings) override
|
||||
|
@ -801,8 +617,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
void on_event(enum obs_frontend_event event) override
|
||||
{
|
||||
if (main->disableSaving &&
|
||||
event != OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP &&
|
||||
if (main->disableSaving && event != OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP &&
|
||||
event != OBS_FRONTEND_EVENT_EXIT)
|
||||
return;
|
||||
|
||||
|
|
|
@ -32,8 +32,7 @@ static void HandleIntProperty(obs_property_t *prop, std::vector<int> &bitrates)
|
|||
bitrates.push_back(i);
|
||||
}
|
||||
|
||||
static void HandleListProperty(obs_property_t *prop, const char *id,
|
||||
std::vector<int> &bitrates)
|
||||
static void HandleListProperty(obs_property_t *prop, const char *id, std::vector<int> &bitrates)
|
||||
{
|
||||
obs_combo_format format = obs_property_list_format(prop);
|
||||
if (format != OBS_COMBO_FORMAT_INT) {
|
||||
|
@ -50,8 +49,7 @@ static void HandleListProperty(obs_property_t *prop, const char *id,
|
|||
if (obs_property_list_item_disabled(prop, i))
|
||||
continue;
|
||||
|
||||
int bitrate =
|
||||
static_cast<int>(obs_property_list_item_int(prop, i));
|
||||
int bitrate = static_cast<int>(obs_property_list_item_int(prop, i));
|
||||
bitrates.push_back(bitrate);
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +59,7 @@ static void HandleSampleRate(obs_property_t *prop, const char *id)
|
|||
auto ReleaseData = [](obs_data_t *data) {
|
||||
obs_data_release(data);
|
||||
};
|
||||
std::unique_ptr<obs_data_t, decltype(ReleaseData)> data{
|
||||
obs_encoder_defaults(id), ReleaseData};
|
||||
std::unique_ptr<obs_data_t, decltype(ReleaseData)> data{obs_encoder_defaults(id), ReleaseData};
|
||||
|
||||
if (!data) {
|
||||
blog(LOG_ERROR,
|
||||
|
@ -79,8 +76,7 @@ static void HandleSampleRate(obs_property_t *prop, const char *id)
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t sampleRate =
|
||||
config_get_uint(main->Config(), "Audio", "SampleRate");
|
||||
uint32_t sampleRate = config_get_uint(main->Config(), "Audio", "SampleRate");
|
||||
|
||||
obs_data_set_int(data.get(), "samplerate", sampleRate);
|
||||
|
||||
|
@ -92,8 +88,8 @@ static void HandleEncoderProperties(const char *id, std::vector<int> &bitrates)
|
|||
auto DestroyProperties = [](obs_properties_t *props) {
|
||||
obs_properties_destroy(props);
|
||||
};
|
||||
std::unique_ptr<obs_properties_t, decltype(DestroyProperties)> props{
|
||||
obs_get_encoder_properties(id), DestroyProperties};
|
||||
std::unique_ptr<obs_properties_t, decltype(DestroyProperties)> props{obs_get_encoder_properties(id),
|
||||
DestroyProperties};
|
||||
|
||||
if (!props) {
|
||||
blog(LOG_ERROR,
|
||||
|
@ -103,8 +99,7 @@ static void HandleEncoderProperties(const char *id, std::vector<int> &bitrates)
|
|||
return;
|
||||
}
|
||||
|
||||
obs_property_t *samplerate =
|
||||
obs_properties_get(props.get(), "samplerate");
|
||||
obs_property_t *samplerate = obs_properties_get(props.get(), "samplerate");
|
||||
if (samplerate)
|
||||
HandleSampleRate(samplerate, id);
|
||||
|
||||
|
@ -156,16 +151,14 @@ static void PopulateBitrateLists()
|
|||
for (auto &bitrate : fallbackBitrates)
|
||||
ss << "\n " << setw(3) << bitrate << " kbit/s:";
|
||||
|
||||
blog(LOG_DEBUG, "Fallback encoder bitrates:%s",
|
||||
ss.str().c_str());
|
||||
blog(LOG_DEBUG, "Fallback encoder bitrates:%s", ss.str().c_str());
|
||||
|
||||
const char *id = nullptr;
|
||||
for (size_t i = 0; obs_enum_encoder_types(i, &id); i++) {
|
||||
if (obs_get_encoder_type(id) != OBS_ENCODER_AUDIO)
|
||||
continue;
|
||||
|
||||
if (strcmp(id, "ffmpeg_aac") == 0 ||
|
||||
strcmp(id, "ffmpeg_opus") == 0)
|
||||
if (strcmp(id, "ffmpeg_aac") == 0 || strcmp(id, "ffmpeg_opus") == 0)
|
||||
continue;
|
||||
|
||||
std::string encoder = id;
|
||||
|
@ -180,11 +173,9 @@ static void PopulateBitrateLists()
|
|||
|
||||
ostringstream ss;
|
||||
for (auto &bitrate : encoderBitrates[encoder])
|
||||
ss << "\n " << setw(3) << bitrate
|
||||
<< " kbit/s";
|
||||
ss << "\n " << setw(3) << bitrate << " kbit/s";
|
||||
|
||||
blog(LOG_DEBUG, "%s (%s) encoder bitrates:%s",
|
||||
EncoderName(id), id, ss.str().c_str());
|
||||
blog(LOG_DEBUG, "%s (%s) encoder bitrates:%s", EncoderName(id), id, ss.str().c_str());
|
||||
}
|
||||
|
||||
if (encoderBitrates.empty() && fallbackBitrates.empty())
|
||||
|
@ -222,8 +213,7 @@ static void PopulateSimpleAACBitrateMap()
|
|||
return val == NullToEmpty(id);
|
||||
};
|
||||
|
||||
if (find_if(begin(encoders), end(encoders), Compare) !=
|
||||
end(encoders))
|
||||
if (find_if(begin(encoders), end(encoders), Compare) != end(encoders))
|
||||
continue;
|
||||
|
||||
if (strcmp(GetCodec(id), "aac") != 0)
|
||||
|
@ -256,12 +246,10 @@ static void PopulateSimpleAACBitrateMap()
|
|||
|
||||
ostringstream ss;
|
||||
for (auto &entry : simpleAACBitrateMap)
|
||||
ss << "\n " << setw(3) << entry.first
|
||||
<< " kbit/s: '" << EncoderName(entry.second) << "' ("
|
||||
<< entry.second << ')';
|
||||
ss << "\n " << setw(3) << entry.first << " kbit/s: '" << EncoderName(entry.second)
|
||||
<< "' (" << entry.second << ')';
|
||||
|
||||
blog(LOG_DEBUG, "AAC simple encoder bitrate mapping:%s",
|
||||
ss.str().c_str());
|
||||
blog(LOG_DEBUG, "AAC simple encoder bitrate mapping:%s", ss.str().c_str());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -301,12 +289,10 @@ static void PopulateSimpleOpusBitrateMap()
|
|||
|
||||
ostringstream ss;
|
||||
for (auto &entry : simpleOpusBitrateMap)
|
||||
ss << "\n " << setw(3) << entry.first
|
||||
<< " kbit/s: '" << EncoderName(entry.second) << "' ("
|
||||
<< entry.second << ')';
|
||||
ss << "\n " << setw(3) << entry.first << " kbit/s: '" << EncoderName(entry.second)
|
||||
<< "' (" << entry.second << ')';
|
||||
|
||||
blog(LOG_DEBUG, "Opus simple encoder bitrate mapping:%s",
|
||||
ss.str().c_str());
|
||||
blog(LOG_DEBUG, "Opus simple encoder bitrate mapping:%s", ss.str().c_str());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -342,8 +328,7 @@ const char *GetSimpleOpusEncoderForBitrate(int bitrate)
|
|||
|
||||
#define INVALID_BITRATE 10000
|
||||
|
||||
static int FindClosestAvailableSimpleBitrate(int bitrate,
|
||||
const map<int, std::string> &map)
|
||||
static int FindClosestAvailableSimpleBitrate(int bitrate, const map<int, std::string> &map)
|
||||
{
|
||||
int prev = 0;
|
||||
int next = INVALID_BITRATE;
|
||||
|
@ -369,14 +354,12 @@ static int FindClosestAvailableSimpleBitrate(int bitrate,
|
|||
|
||||
int FindClosestAvailableSimpleAACBitrate(int bitrate)
|
||||
{
|
||||
return FindClosestAvailableSimpleBitrate(
|
||||
bitrate, GetSimpleAACEncoderBitrateMap());
|
||||
return FindClosestAvailableSimpleBitrate(bitrate, GetSimpleAACEncoderBitrateMap());
|
||||
}
|
||||
|
||||
int FindClosestAvailableSimpleOpusBitrate(int bitrate)
|
||||
{
|
||||
return FindClosestAvailableSimpleBitrate(
|
||||
bitrate, GetSimpleOpusEncoderBitrateMap());
|
||||
return FindClosestAvailableSimpleBitrate(bitrate, GetSimpleOpusEncoderBitrateMap());
|
||||
}
|
||||
|
||||
const std::vector<int> &GetAudioEncoderBitrates(const char *id)
|
||||
|
@ -396,9 +379,7 @@ int FindClosestAvailableAudioBitrate(const char *id, int bitrate)
|
|||
int next = INVALID_BITRATE;
|
||||
std::string encoder = id;
|
||||
|
||||
for (auto val : encoderBitrates[encoder].empty()
|
||||
? fallbackBitrates
|
||||
: encoderBitrates[encoder]) {
|
||||
for (auto val : encoderBitrates[encoder].empty() ? fallbackBitrates : encoderBitrates[encoder]) {
|
||||
if (next > val) {
|
||||
if (val == bitrate)
|
||||
return bitrate;
|
||||
|
|
|
@ -61,8 +61,7 @@ void Auth::Load()
|
|||
if (main->auth) {
|
||||
if (main->auth->LoadInternal()) {
|
||||
main->auth->LoadUI();
|
||||
main->SetBroadcastFlowEnabled(
|
||||
main->auth->broadcastFlow());
|
||||
main->SetBroadcastFlowEnabled(main->auth->broadcastFlow());
|
||||
}
|
||||
} else {
|
||||
main->SetBroadcastFlowEnabled(false);
|
||||
|
|
|
@ -17,11 +17,7 @@ protected:
|
|||
std::string message;
|
||||
std::string error;
|
||||
|
||||
ErrorInfo(std::string message_, std::string error_)
|
||||
: message(message_),
|
||||
error(error_)
|
||||
{
|
||||
}
|
||||
ErrorInfo(std::string message_, std::string error_) : message(message_), error(error_) {}
|
||||
};
|
||||
|
||||
public:
|
||||
|
|
|
@ -10,33 +10,29 @@
|
|||
|
||||
#define LOGO_URL "https://obsproject.com/assets/images/new_icon_small-r.png"
|
||||
|
||||
static const QString serverResponseHeader =
|
||||
QStringLiteral("HTTP/1.0 200 OK\n"
|
||||
"Connection: close\n"
|
||||
"Content-Type: text/html; charset=UTF-8\n"
|
||||
"Server: OBS Studio\n"
|
||||
"\n"
|
||||
"<html><head><title>OBS Studio"
|
||||
"</title></head>");
|
||||
static const QString serverResponseHeader = QStringLiteral("HTTP/1.0 200 OK\n"
|
||||
"Connection: close\n"
|
||||
"Content-Type: text/html; charset=UTF-8\n"
|
||||
"Server: OBS Studio\n"
|
||||
"\n"
|
||||
"<html><head><title>OBS Studio"
|
||||
"</title></head>");
|
||||
|
||||
static const QString responseTemplate =
|
||||
"<center>"
|
||||
"<img src=\"" LOGO_URL
|
||||
"\" alt=\"OBS\" class=\"center\" height=\"60\" width=\"60\">"
|
||||
"</center>"
|
||||
"<center><p style=\"font-family:verdana; font-size:13pt\">%1</p></center>";
|
||||
static const QString responseTemplate = "<center>"
|
||||
"<img src=\"" LOGO_URL
|
||||
"\" alt=\"OBS\" class=\"center\" height=\"60\" width=\"60\">"
|
||||
"</center>"
|
||||
"<center><p style=\"font-family:verdana; font-size:13pt\">%1</p></center>";
|
||||
|
||||
AuthListener::AuthListener(QObject *parent) : QObject(parent)
|
||||
{
|
||||
server = new QTcpServer(this);
|
||||
connect(server, &QTcpServer::newConnection, this,
|
||||
&AuthListener::NewConnection);
|
||||
connect(server, &QTcpServer::newConnection, this, &AuthListener::NewConnection);
|
||||
if (!server->listen(QHostAddress::LocalHost, 0)) {
|
||||
blog(LOG_DEBUG, "Server could not start");
|
||||
emit fail();
|
||||
} else {
|
||||
blog(LOG_DEBUG, "Server started at port %d",
|
||||
server->serverPort());
|
||||
blog(LOG_DEBUG, "Server started at port %d", server->serverPort());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,8 +50,7 @@ void AuthListener::NewConnection()
|
|||
{
|
||||
QTcpSocket *socket = server->nextPendingConnection();
|
||||
if (socket) {
|
||||
connect(socket, &QTcpSocket::disconnected, socket,
|
||||
&QTcpSocket::deleteLater);
|
||||
connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater);
|
||||
connect(socket, &QTcpSocket::readyRead, socket, [&, socket]() {
|
||||
QByteArray buffer;
|
||||
while (socket->bytesAvailable() > 0) {
|
||||
|
@ -65,13 +60,10 @@ void AuthListener::NewConnection()
|
|||
QString redirect = QString::fromLatin1(buffer);
|
||||
blog(LOG_DEBUG, "redirect: %s", QT_TO_UTF8(redirect));
|
||||
|
||||
QRegularExpression re_state(
|
||||
"(&|\\?)state=(?<state>[^&]+)");
|
||||
QRegularExpression re_code(
|
||||
"(&|\\?)code=(?<code>[^&]+)");
|
||||
QRegularExpression re_state("(&|\\?)state=(?<state>[^&]+)");
|
||||
QRegularExpression re_code("(&|\\?)code=(?<code>[^&]+)");
|
||||
|
||||
QRegularExpressionMatch match =
|
||||
re_state.match(redirect);
|
||||
QRegularExpressionMatch match = re_state.match(redirect);
|
||||
|
||||
QString code;
|
||||
|
||||
|
@ -95,13 +87,11 @@ void AuthListener::NewConnection()
|
|||
}
|
||||
|
||||
if (code.isEmpty()) {
|
||||
auto data = responseTemplate.arg(
|
||||
QTStr("YouTube.Auth.NoCode"));
|
||||
auto data = responseTemplate.arg(QTStr("YouTube.Auth.NoCode"));
|
||||
socket->write(QT_TO_UTF8(data));
|
||||
emit fail();
|
||||
} else {
|
||||
auto data = responseTemplate.arg(
|
||||
QTStr("YouTube.Auth.Ok"));
|
||||
auto data = responseTemplate.arg(QTStr("YouTube.Auth.Ok"));
|
||||
socket->write(QT_TO_UTF8(data));
|
||||
emit ok(code);
|
||||
}
|
||||
|
|
|
@ -26,9 +26,7 @@ extern QCefCookieManager *panel_cookies;
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
OAuthLogin::OAuthLogin(QWidget *parent, const std::string &url, bool token)
|
||||
: QDialog(parent),
|
||||
get_token(token)
|
||||
OAuthLogin::OAuthLogin(QWidget *parent, const std::string &url, bool token) : QDialog(parent), get_token(token)
|
||||
{
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
if (!cef) {
|
||||
|
@ -51,10 +49,8 @@ OAuthLogin::OAuthLogin(QWidget *parent, const std::string &url, bool token)
|
|||
return;
|
||||
}
|
||||
|
||||
connect(cefWidget, &QCefWidget::titleChanged, this,
|
||||
&OAuthLogin::setWindowTitle);
|
||||
connect(cefWidget, &QCefWidget::urlChanged, this,
|
||||
&OAuthLogin::urlChanged);
|
||||
connect(cefWidget, &QCefWidget::titleChanged, this, &OAuthLogin::setWindowTitle);
|
||||
connect(cefWidget, &QCefWidget::urlChanged, this, &OAuthLogin::urlChanged);
|
||||
|
||||
QPushButton *close = new QPushButton(QTStr("Cancel"));
|
||||
connect(close, &QAbstractButton::clicked, this, &QDialog::reject);
|
||||
|
@ -131,8 +127,7 @@ struct OAuthInfo {
|
|||
|
||||
static std::vector<OAuthInfo> loginCBs;
|
||||
|
||||
void OAuth::RegisterOAuth(const Def &d, create_cb create, login_cb login,
|
||||
delete_cookies_cb delete_cookies)
|
||||
void OAuth::RegisterOAuth(const Def &d, create_cb create, login_cb login, delete_cookies_cb delete_cookies)
|
||||
{
|
||||
OAuthInfo info = {d, login, delete_cookies};
|
||||
loginCBs.push_back(info);
|
||||
|
@ -162,15 +157,13 @@ void OAuth::DeleteCookies(const std::string &service)
|
|||
void OAuth::SaveInternal()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
config_set_string(main->Config(), service(), "RefreshToken",
|
||||
refresh_token.c_str());
|
||||
config_set_string(main->Config(), service(), "RefreshToken", refresh_token.c_str());
|
||||
config_set_string(main->Config(), service(), "Token", token.c_str());
|
||||
config_set_uint(main->Config(), service(), "ExpireTime", expire_time);
|
||||
config_set_int(main->Config(), service(), "ScopeVer", currentScopeVer);
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section,
|
||||
const char *name)
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section, const char *name)
|
||||
{
|
||||
const char *val = config_get_string(main->Config(), section, name);
|
||||
return val ? val : "";
|
||||
|
@ -182,8 +175,7 @@ bool OAuth::LoadInternal()
|
|||
refresh_token = get_config_str(main, service(), "RefreshToken");
|
||||
token = get_config_str(main, service(), "Token");
|
||||
expire_time = config_get_uint(main->Config(), service(), "ExpireTime");
|
||||
currentScopeVer =
|
||||
(int)config_get_int(main->Config(), service(), "ScopeVer");
|
||||
currentScopeVer = (int)config_get_int(main->Config(), service(), "ScopeVer");
|
||||
return implicit ? !token.empty() : !refresh_token.empty();
|
||||
}
|
||||
|
||||
|
@ -196,25 +188,20 @@ bool OAuth::TokenExpired()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool OAuth::GetToken(const char *url, const std::string &client_id,
|
||||
const std::string &secret, const std::string &redirect_uri,
|
||||
int scope_ver, const std::string &auth_code, bool retry)
|
||||
bool OAuth::GetToken(const char *url, const std::string &client_id, const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver, const std::string &auth_code, bool retry)
|
||||
{
|
||||
return GetTokenInternal(url, client_id, secret, redirect_uri, scope_ver,
|
||||
auth_code, retry);
|
||||
return GetTokenInternal(url, client_id, secret, redirect_uri, scope_ver, auth_code, retry);
|
||||
}
|
||||
|
||||
bool OAuth::GetToken(const char *url, const std::string &client_id,
|
||||
int scope_ver, const std::string &auth_code, bool retry)
|
||||
bool OAuth::GetToken(const char *url, const std::string &client_id, int scope_ver, const std::string &auth_code,
|
||||
bool retry)
|
||||
{
|
||||
return GetTokenInternal(url, client_id, {}, {}, scope_ver, auth_code,
|
||||
retry);
|
||||
return GetTokenInternal(url, client_id, {}, {}, scope_ver, auth_code, retry);
|
||||
}
|
||||
|
||||
bool OAuth::GetTokenInternal(const char *url, const std::string &client_id,
|
||||
const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver,
|
||||
const std::string &auth_code, bool retry)
|
||||
bool OAuth::GetTokenInternal(const char *url, const std::string &client_id, const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver, const std::string &auth_code, bool retry)
|
||||
try {
|
||||
std::string output;
|
||||
std::string error;
|
||||
|
@ -225,8 +212,7 @@ try {
|
|||
return true;
|
||||
} else {
|
||||
QString title = QTStr("Auth.InvalidScope.Title");
|
||||
QString text =
|
||||
QTStr("Auth.InvalidScope.Text").arg(service());
|
||||
QString text = QTStr("Auth.InvalidScope.Text").arg(service());
|
||||
|
||||
QMessageBox::warning(OBSBasic::Get(), title, text);
|
||||
}
|
||||
|
@ -259,14 +245,11 @@ try {
|
|||
bool success = false;
|
||||
|
||||
auto func = [&]() {
|
||||
success = GetRemoteFile(url, output, error, nullptr,
|
||||
"application/x-www-form-urlencoded", "",
|
||||
post_data.c_str(),
|
||||
std::vector<std::string>(), nullptr, 5);
|
||||
success = GetRemoteFile(url, output, error, nullptr, "application/x-www-form-urlencoded", "",
|
||||
post_data.c_str(), std::vector<std::string>(), nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(func, QTStr("Auth.Authing.Title"),
|
||||
QTStr("Auth.Authing.Text").arg(service()));
|
||||
ExecThreadedWithoutBlocking(func, QTStr("Auth.Authing.Title"), QTStr("Auth.Authing.Text").arg(service()));
|
||||
if (!success || output.empty())
|
||||
throw ErrorInfo("Failed to get token from remote", error);
|
||||
|
||||
|
@ -284,8 +267,7 @@ try {
|
|||
}
|
||||
}
|
||||
if (!error.empty())
|
||||
throw ErrorInfo(error,
|
||||
json["error_description"].string_value());
|
||||
throw ErrorInfo(error, json["error_description"].string_value());
|
||||
|
||||
/* -------------------------- */
|
||||
/* success! */
|
||||
|
@ -310,15 +292,12 @@ try {
|
|||
} catch (ErrorInfo &info) {
|
||||
if (!retry) {
|
||||
QString title = QTStr("Auth.AuthFailure.Title");
|
||||
QString text = QTStr("Auth.AuthFailure.Text")
|
||||
.arg(service(), info.message.c_str(),
|
||||
info.error.c_str());
|
||||
QString text = QTStr("Auth.AuthFailure.Text").arg(service(), info.message.c_str(), info.error.c_str());
|
||||
|
||||
QMessageBox::warning(OBSBasic::Get(), title, text);
|
||||
}
|
||||
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(), info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -335,8 +314,7 @@ void OAuthStreamKey::OnStreamConfig()
|
|||
bool bwtest = obs_data_get_bool(settings, "bwtest");
|
||||
|
||||
if (bwtest && strcmp(this->service(), "Twitch") == 0)
|
||||
obs_data_set_string(settings, "key",
|
||||
(key_ + "?bandwidthtest=true").c_str());
|
||||
obs_data_set_string(settings, "key", (key_ + "?bandwidthtest=true").c_str());
|
||||
else
|
||||
obs_data_set_string(settings, "key", key_.c_str());
|
||||
|
||||
|
|
|
@ -37,18 +37,13 @@ class OAuth : public Auth {
|
|||
public:
|
||||
inline OAuth(const Def &d) : Auth(d) {}
|
||||
|
||||
typedef std::function<std::shared_ptr<Auth>(
|
||||
QWidget *, const std::string &service_name)>
|
||||
login_cb;
|
||||
typedef std::function<std::shared_ptr<Auth>(QWidget *, const std::string &service_name)> login_cb;
|
||||
typedef std::function<void()> delete_cookies_cb;
|
||||
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent,
|
||||
const std::string &service);
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent, const std::string &service);
|
||||
static void DeleteCookies(const std::string &service);
|
||||
|
||||
static void RegisterOAuth(const Def &d, create_cb create,
|
||||
login_cb login,
|
||||
delete_cookies_cb delete_cookies);
|
||||
static void RegisterOAuth(const Def &d, create_cb create, login_cb login, delete_cookies_cb delete_cookies);
|
||||
|
||||
protected:
|
||||
std::string refresh_token;
|
||||
|
@ -62,20 +57,14 @@ protected:
|
|||
|
||||
virtual bool RetryLogin() = 0;
|
||||
bool TokenExpired();
|
||||
bool GetToken(const char *url, const std::string &client_id,
|
||||
int scope_ver,
|
||||
const std::string &auth_code = std::string(),
|
||||
bool retry = false);
|
||||
bool GetToken(const char *url, const std::string &client_id,
|
||||
const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver,
|
||||
const std::string &auth_code, bool retry);
|
||||
bool GetToken(const char *url, const std::string &client_id, int scope_ver,
|
||||
const std::string &auth_code = std::string(), bool retry = false);
|
||||
bool GetToken(const char *url, const std::string &client_id, const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver, const std::string &auth_code, bool retry);
|
||||
|
||||
private:
|
||||
bool GetTokenInternal(const char *url, const std::string &client_id,
|
||||
const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver,
|
||||
const std::string &auth_code, bool retry);
|
||||
bool GetTokenInternal(const char *url, const std::string &client_id, const std::string &secret,
|
||||
const std::string &redirect_uri, int scope_ver, const std::string &auth_code, bool retry);
|
||||
};
|
||||
|
||||
class OAuthStreamKey : public OAuth {
|
||||
|
|
|
@ -72,14 +72,12 @@ try {
|
|||
bool success;
|
||||
|
||||
auto func = [&]() {
|
||||
success = GetRemoteFile(RESTREAM_STREAMKEY_URL, output, error,
|
||||
nullptr, "application/json", "",
|
||||
nullptr, headers, nullptr, 5);
|
||||
success = GetRemoteFile(RESTREAM_STREAMKEY_URL, output, error, nullptr, "application/json", "", nullptr,
|
||||
headers, nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
func, QTStr("Auth.LoadingChannel.Title"),
|
||||
QTStr("Auth.LoadingChannel.Text").arg(service()));
|
||||
ExecThreadedWithoutBlocking(func, QTStr("Auth.LoadingChannel.Title"),
|
||||
QTStr("Auth.LoadingChannel.Text").arg(service()));
|
||||
if (!success || output.empty())
|
||||
throw ErrorInfo("Failed to get stream key from remote", error);
|
||||
|
||||
|
@ -89,35 +87,29 @@ try {
|
|||
|
||||
error = json["error"].string_value();
|
||||
if (!error.empty())
|
||||
throw ErrorInfo(error,
|
||||
json["error_description"].string_value());
|
||||
throw ErrorInfo(error, json["error_description"].string_value());
|
||||
|
||||
key_ = json["streamKey"].string_value();
|
||||
|
||||
return true;
|
||||
} catch (ErrorInfo info) {
|
||||
QString title = QTStr("Auth.ChannelFailure.Title");
|
||||
QString text = QTStr("Auth.ChannelFailure.Text")
|
||||
.arg(service(), info.message.c_str(),
|
||||
info.error.c_str());
|
||||
QString text = QTStr("Auth.ChannelFailure.Text").arg(service(), info.message.c_str(), info.error.c_str());
|
||||
|
||||
QMessageBox::warning(OBSBasic::Get(), title, text);
|
||||
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(), info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
void RestreamAuth::SaveInternal()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
config_set_string(main->Config(), service(), "DockState",
|
||||
main->saveState().toBase64().constData());
|
||||
config_set_string(main->Config(), service(), "DockState", main->saveState().toBase64().constData());
|
||||
OAuthStreamKey::SaveInternal();
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section,
|
||||
const char *name)
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section, const char *name)
|
||||
{
|
||||
const char *val = config_get_string(main->Config(), section, name);
|
||||
return val ? val : "";
|
||||
|
@ -209,10 +201,8 @@ void RestreamAuth::LoadUI()
|
|||
info->setVisible(true);
|
||||
channels->setVisible(true);
|
||||
} else {
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
const char *dockStateStr = config_get_string(main->Config(), service(), "DockState");
|
||||
QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
|
||||
if (main->isVisible() || !main->isMaximized())
|
||||
main->restoreState(dockState);
|
||||
|
@ -229,14 +219,12 @@ bool RestreamAuth::RetryLogin()
|
|||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<RestreamAuth> auth =
|
||||
std::make_shared<RestreamAuth>(restreamDef);
|
||||
std::shared_ptr<RestreamAuth> auth = std::make_shared<RestreamAuth>(restreamDef);
|
||||
|
||||
std::string client_id = RESTREAM_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], RESTREAM_HASH);
|
||||
|
||||
return GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION,
|
||||
QT_TO_UTF8(login.GetCode()), true);
|
||||
return GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION, QT_TO_UTF8(login.GetCode()), true);
|
||||
}
|
||||
|
||||
std::shared_ptr<Auth> RestreamAuth::Login(QWidget *parent, const std::string &)
|
||||
|
@ -248,15 +236,12 @@ std::shared_ptr<Auth> RestreamAuth::Login(QWidget *parent, const std::string &)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<RestreamAuth> auth =
|
||||
std::make_shared<RestreamAuth>(restreamDef);
|
||||
std::shared_ptr<RestreamAuth> auth = std::make_shared<RestreamAuth>(restreamDef);
|
||||
|
||||
std::string client_id = RESTREAM_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], RESTREAM_HASH);
|
||||
|
||||
if (!auth->GetToken(RESTREAM_TOKEN_URL, client_id,
|
||||
RESTREAM_SCOPE_VERSION,
|
||||
QT_TO_UTF8(login.GetCode()))) {
|
||||
if (!auth->GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION, QT_TO_UTF8(login.GetCode()))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -287,6 +272,5 @@ void RegisterRestreamAuth()
|
|||
return;
|
||||
#endif
|
||||
|
||||
OAuth::RegisterOAuth(restreamDef, CreateRestreamAuth,
|
||||
RestreamAuth::Login, DeleteCookies);
|
||||
OAuth::RegisterOAuth(restreamDef, CreateRestreamAuth, RestreamAuth::Login, DeleteCookies);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,5 @@ public:
|
|||
RestreamAuth(const Def &d);
|
||||
~RestreamAuth();
|
||||
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent,
|
||||
const std::string &service_name);
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent, const std::string &service_name);
|
||||
};
|
||||
|
|
|
@ -41,17 +41,14 @@ TwitchAuth::TwitchAuth(const Def &d) : OAuthStreamKey(d)
|
|||
if (!cef)
|
||||
return;
|
||||
|
||||
cef->add_popup_whitelist_url(
|
||||
"https://twitch.tv/popout/frankerfacez/chat?ffz-settings",
|
||||
this);
|
||||
cef->add_popup_whitelist_url("https://twitch.tv/popout/frankerfacez/chat?ffz-settings", this);
|
||||
|
||||
/* enables javascript-based popups. basically bttv popups */
|
||||
cef->add_popup_whitelist_url("about:blank#blocked", this);
|
||||
|
||||
uiLoadTimer.setSingleShot(true);
|
||||
uiLoadTimer.setInterval(500);
|
||||
connect(&uiLoadTimer, &QTimer::timeout, this,
|
||||
&TwitchAuth::TryLoadSecondaryUIPanes);
|
||||
connect(&uiLoadTimer, &QTimer::timeout, this, &TwitchAuth::TryLoadSecondaryUIPanes);
|
||||
}
|
||||
|
||||
TwitchAuth::~TwitchAuth()
|
||||
|
@ -86,19 +83,15 @@ bool TwitchAuth::MakeApiRequest(const char *path, Json &json_out)
|
|||
bool success = false;
|
||||
|
||||
auto func = [&]() {
|
||||
success = GetRemoteFile(url.c_str(), output, error, &error_code,
|
||||
"application/json", "", nullptr,
|
||||
success = GetRemoteFile(url.c_str(), output, error, &error_code, "application/json", "", nullptr,
|
||||
headers, nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
func, QTStr("Auth.LoadingChannel.Title"),
|
||||
QTStr("Auth.LoadingChannel.Text").arg(service()));
|
||||
ExecThreadedWithoutBlocking(func, QTStr("Auth.LoadingChannel.Title"),
|
||||
QTStr("Auth.LoadingChannel.Text").arg(service()));
|
||||
if (error_code == 403) {
|
||||
OBSMessageBox::warning(OBSBasic::Get(),
|
||||
Str("TwitchAuth.TwoFactorFail.Title"),
|
||||
Str("TwitchAuth.TwoFactorFail.Text"),
|
||||
true);
|
||||
OBSMessageBox::warning(OBSBasic::Get(), Str("TwitchAuth.TwoFactorFail.Title"),
|
||||
Str("TwitchAuth.TwoFactorFail.Text"), true);
|
||||
blog(LOG_WARNING, "%s: %s", __FUNCTION__,
|
||||
"Got 403 from Twitch, user probably does not "
|
||||
"have two-factor authentication enabled on "
|
||||
|
@ -140,8 +133,7 @@ try {
|
|||
|
||||
name = json["data"][0]["login"].string_value();
|
||||
|
||||
std::string path = "streams/key?broadcaster_id=" +
|
||||
json["data"][0]["id"].string_value();
|
||||
std::string path = "streams/key?broadcaster_id=" + json["data"][0]["id"].string_value();
|
||||
success = MakeApiRequest(path.c_str(), json);
|
||||
if (!success)
|
||||
return false;
|
||||
|
@ -151,14 +143,11 @@ try {
|
|||
return true;
|
||||
} catch (ErrorInfo info) {
|
||||
QString title = QTStr("Auth.ChannelFailure.Title");
|
||||
QString text = QTStr("Auth.ChannelFailure.Text")
|
||||
.arg(service(), info.message.c_str(),
|
||||
info.error.c_str());
|
||||
QString text = QTStr("Auth.ChannelFailure.Text").arg(service(), info.message.c_str(), info.error.c_str());
|
||||
|
||||
QMessageBox::warning(OBSBasic::Get(), title, text);
|
||||
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(), info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -169,14 +158,12 @@ void TwitchAuth::SaveInternal()
|
|||
config_set_string(main->Config(), service(), "UUID", uuid.c_str());
|
||||
|
||||
if (uiLoaded) {
|
||||
config_set_string(main->Config(), service(), "DockState",
|
||||
main->saveState().toBase64().constData());
|
||||
config_set_string(main->Config(), service(), "DockState", main->saveState().toBase64().constData());
|
||||
}
|
||||
OAuthStreamKey::SaveInternal();
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section,
|
||||
const char *name)
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section, const char *name)
|
||||
{
|
||||
const char *val = config_get_string(main->Config(), section, name);
|
||||
return val ? val : "";
|
||||
|
@ -268,8 +255,7 @@ void TwitchAuth::LoadUI()
|
|||
script = "localStorage.setItem('twilight.theme', 0);";
|
||||
}
|
||||
|
||||
const int twAddonChoice =
|
||||
config_get_int(main->Config(), service(), "AddonChoice");
|
||||
const int twAddonChoice = config_get_int(main->Config(), service(), "AddonChoice");
|
||||
if (twAddonChoice) {
|
||||
if (twAddonChoice & 0x1)
|
||||
script += bttv_script;
|
||||
|
@ -289,10 +275,8 @@ void TwitchAuth::LoadUI()
|
|||
if (firstLoad) {
|
||||
chat->setVisible(true);
|
||||
} else {
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
const char *dockStateStr = config_get_string(main->Config(), service(), "DockState");
|
||||
QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
|
||||
if (main->isVisible() || !main->isMaximized())
|
||||
main->restoreState(dockState);
|
||||
|
@ -325,8 +309,7 @@ void TwitchAuth::LoadSecondaryUIPanes()
|
|||
script += "/dashboard/live";
|
||||
script += referrer_script2;
|
||||
|
||||
const int twAddonChoice =
|
||||
config_get_int(main->Config(), service(), "AddonChoice");
|
||||
const int twAddonChoice = config_get_int(main->Config(), service(), "AddonChoice");
|
||||
if (twAddonChoice) {
|
||||
if (twAddonChoice & 0x1)
|
||||
script += bttv_script;
|
||||
|
@ -410,17 +393,14 @@ void TwitchAuth::LoadSecondaryUIPanes()
|
|||
stats->setVisible(false);
|
||||
feed->setVisible(false);
|
||||
} else {
|
||||
uint32_t lastVersion = config_get_int(App()->GetAppConfig(),
|
||||
"General", "LastVersion");
|
||||
uint32_t lastVersion = config_get_int(App()->GetAppConfig(), "General", "LastVersion");
|
||||
|
||||
if (lastVersion <= MAKE_SEMANTIC_VERSION(23, 0, 2)) {
|
||||
feed->setVisible(false);
|
||||
}
|
||||
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
const char *dockStateStr = config_get_string(main->Config(), service(), "DockState");
|
||||
QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
|
||||
if (main->isVisible() || !main->isMaximized())
|
||||
main->restoreState(dockState);
|
||||
|
@ -449,13 +429,11 @@ void TwitchAuth::TryLoadSecondaryUIPanes()
|
|||
if (!found) {
|
||||
QMetaObject::invokeMethod(&this_->uiLoadTimer, "start");
|
||||
} else {
|
||||
QMetaObject::invokeMethod(this_,
|
||||
"LoadSecondaryUIPanes");
|
||||
QMetaObject::invokeMethod(this_, "LoadSecondaryUIPanes");
|
||||
}
|
||||
};
|
||||
|
||||
panel_cookies->CheckForCookie("https://www.twitch.tv", "auth-token",
|
||||
cb);
|
||||
panel_cookies->CheckForCookie("https://www.twitch.tv", "auth-token", cb);
|
||||
}
|
||||
|
||||
bool TwitchAuth::RetryLogin()
|
||||
|
@ -465,13 +443,11 @@ bool TwitchAuth::RetryLogin()
|
|||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<TwitchAuth> auth =
|
||||
std::make_shared<TwitchAuth>(twitchDef);
|
||||
std::shared_ptr<TwitchAuth> auth = std::make_shared<TwitchAuth>(twitchDef);
|
||||
std::string client_id = TWITCH_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], TWITCH_HASH);
|
||||
|
||||
return GetToken(TWITCH_TOKEN_URL, client_id, TWITCH_SCOPE_VERSION,
|
||||
QT_TO_UTF8(login.GetCode()), true);
|
||||
return GetToken(TWITCH_TOKEN_URL, client_id, TWITCH_SCOPE_VERSION, QT_TO_UTF8(login.GetCode()), true);
|
||||
}
|
||||
|
||||
std::shared_ptr<Auth> TwitchAuth::Login(QWidget *parent, const std::string &)
|
||||
|
@ -481,14 +457,12 @@ std::shared_ptr<Auth> TwitchAuth::Login(QWidget *parent, const std::string &)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<TwitchAuth> auth =
|
||||
std::make_shared<TwitchAuth>(twitchDef);
|
||||
std::shared_ptr<TwitchAuth> auth = std::make_shared<TwitchAuth>(twitchDef);
|
||||
|
||||
std::string client_id = TWITCH_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], TWITCH_HASH);
|
||||
|
||||
if (!auth->GetToken(TWITCH_TOKEN_URL, client_id, TWITCH_SCOPE_VERSION,
|
||||
QT_TO_UTF8(login.GetCode()))) {
|
||||
if (!auth->GetToken(TWITCH_TOKEN_URL, client_id, TWITCH_SCOPE_VERSION, QT_TO_UTF8(login.GetCode()))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -517,6 +491,5 @@ void RegisterTwitchAuth()
|
|||
return;
|
||||
#endif
|
||||
|
||||
OAuth::RegisterOAuth(twitchDef, CreateTwitchAuth, TwitchAuth::Login,
|
||||
DeleteCookies);
|
||||
OAuth::RegisterOAuth(twitchDef, CreateTwitchAuth, TwitchAuth::Login, DeleteCookies);
|
||||
}
|
||||
|
|
|
@ -32,8 +32,7 @@ public:
|
|||
TwitchAuth(const Def &d);
|
||||
~TwitchAuth();
|
||||
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent,
|
||||
const std::string &service_name);
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent, const std::string &service_name);
|
||||
|
||||
QTimer uiLoadTimer;
|
||||
|
||||
|
|
|
@ -37,15 +37,12 @@ using namespace json11;
|
|||
#define YOUTUBE_API_STATE_LENGTH 32
|
||||
#define SECTION_NAME "YouTube"
|
||||
|
||||
#define YOUTUBE_CHAT_PLACEHOLDER_URL \
|
||||
"https://obsproject.com/placeholders/youtube-chat"
|
||||
#define YOUTUBE_CHAT_POPOUT_URL \
|
||||
"https://www.youtube.com/live_chat?is_popout=1&dark_theme=1&v=%1"
|
||||
#define YOUTUBE_CHAT_PLACEHOLDER_URL "https://obsproject.com/placeholders/youtube-chat"
|
||||
#define YOUTUBE_CHAT_POPOUT_URL "https://www.youtube.com/live_chat?is_popout=1&dark_theme=1&v=%1"
|
||||
|
||||
#define YOUTUBE_CHAT_DOCK_NAME "ytChat"
|
||||
|
||||
static const char allowedChars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static const char allowedChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
static const int allowedCount = static_cast<int>(sizeof(allowedChars) - 1);
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -67,20 +64,12 @@ void RegisterYoutubeAuth()
|
|||
{
|
||||
for (auto &service : youtubeServices) {
|
||||
OAuth::RegisterOAuth(
|
||||
service,
|
||||
[service]() {
|
||||
return std::make_shared<YoutubeApiWrappers>(
|
||||
service);
|
||||
},
|
||||
service, [service]() { return std::make_shared<YoutubeApiWrappers>(service); },
|
||||
YoutubeAuth::Login, DeleteCookies);
|
||||
}
|
||||
}
|
||||
|
||||
YoutubeAuth::YoutubeAuth(const Def &d)
|
||||
: OAuthStreamKey(d),
|
||||
section(SECTION_NAME)
|
||||
{
|
||||
}
|
||||
YoutubeAuth::YoutubeAuth(const Def &d) : OAuthStreamKey(d), section(SECTION_NAME) {}
|
||||
|
||||
YoutubeAuth::~YoutubeAuth()
|
||||
{
|
||||
|
@ -103,21 +92,16 @@ bool YoutubeAuth::RetryLogin()
|
|||
void YoutubeAuth::SaveInternal()
|
||||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
config_set_string(main->Config(), service(), "DockState",
|
||||
main->saveState().toBase64().constData());
|
||||
config_set_string(main->Config(), service(), "DockState", main->saveState().toBase64().constData());
|
||||
|
||||
const char *section_name = section.c_str();
|
||||
config_set_string(main->Config(), section_name, "RefreshToken",
|
||||
refresh_token.c_str());
|
||||
config_set_string(main->Config(), section_name, "RefreshToken", refresh_token.c_str());
|
||||
config_set_string(main->Config(), section_name, "Token", token.c_str());
|
||||
config_set_uint(main->Config(), section_name, "ExpireTime",
|
||||
expire_time);
|
||||
config_set_int(main->Config(), section_name, "ScopeVer",
|
||||
currentScopeVer);
|
||||
config_set_uint(main->Config(), section_name, "ExpireTime", expire_time);
|
||||
config_set_int(main->Config(), section_name, "ScopeVer", currentScopeVer);
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section,
|
||||
const char *name)
|
||||
static inline std::string get_config_str(OBSBasic *main, const char *section, const char *name)
|
||||
{
|
||||
const char *val = config_get_string(main->Config(), section, name);
|
||||
return val ? val : "";
|
||||
|
@ -130,10 +114,8 @@ bool YoutubeAuth::LoadInternal()
|
|||
const char *section_name = section.c_str();
|
||||
refresh_token = get_config_str(main, section_name, "RefreshToken");
|
||||
token = get_config_str(main, section_name, "Token");
|
||||
expire_time =
|
||||
config_get_uint(main->Config(), section_name, "ExpireTime");
|
||||
currentScopeVer =
|
||||
(int)config_get_int(main->Config(), section_name, "ScopeVer");
|
||||
expire_time = config_get_uint(main->Config(), section_name, "ExpireTime");
|
||||
currentScopeVer = (int)config_get_int(main->Config(), section_name, "ScopeVer");
|
||||
firstLoad = false;
|
||||
return implicit ? !token.empty() : !refresh_token.empty();
|
||||
}
|
||||
|
@ -161,8 +143,7 @@ void YoutubeAuth::LoadUI()
|
|||
chat->setMinimumSize(200, 300);
|
||||
chat->setAllowedAreas(Qt::AllDockWidgetAreas);
|
||||
|
||||
browser = cef->create_widget(chat, YOUTUBE_CHAT_PLACEHOLDER_URL,
|
||||
panel_cookies);
|
||||
browser = cef->create_widget(chat, YOUTUBE_CHAT_PLACEHOLDER_URL, panel_cookies);
|
||||
|
||||
chat->SetWidget(browser);
|
||||
main->AddDockWidget(chat, Qt::RightDockWidgetArea);
|
||||
|
@ -178,10 +159,8 @@ void YoutubeAuth::LoadUI()
|
|||
main->NewYouTubeAppDock();
|
||||
|
||||
if (!firstLoad) {
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
const char *dockStateStr = config_get_string(main->Config(), service(), "DockState");
|
||||
QByteArray dockState = QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
|
||||
if (main->isVisible() || !main->isMaximized())
|
||||
main->restoreState(dockState);
|
||||
|
@ -190,8 +169,7 @@ void YoutubeAuth::LoadUI()
|
|||
uiLoaded = true;
|
||||
}
|
||||
|
||||
void YoutubeAuth::SetChatId(const QString &chat_id,
|
||||
const std::string &api_chat_id)
|
||||
void YoutubeAuth::SetChatId(const QString &chat_id, const std::string &api_chat_id)
|
||||
{
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
QString chat_url = QString(YOUTUBE_CHAT_POPOUT_URL).arg(chat_id);
|
||||
|
@ -239,23 +217,19 @@ QString YoutubeAuth::GenerateState()
|
|||
}
|
||||
|
||||
// Static.
|
||||
std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
|
||||
const std::string &service)
|
||||
std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner, const std::string &service)
|
||||
{
|
||||
QString auth_code;
|
||||
AuthListener server;
|
||||
|
||||
auto it = std::find_if(youtubeServices.begin(), youtubeServices.end(),
|
||||
[service](auto &item) {
|
||||
return service == item.service;
|
||||
});
|
||||
[service](auto &item) { return service == item.service; });
|
||||
if (it == youtubeServices.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto auth = std::make_shared<YoutubeApiWrappers>(*it);
|
||||
|
||||
QString redirect_uri =
|
||||
QString("http://127.0.0.1:%1").arg(server.GetPort());
|
||||
QString redirect_uri = QString("http://127.0.0.1:%1").arg(server.GetPort());
|
||||
|
||||
QMessageBox dlg(owner);
|
||||
dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowCloseButtonHint);
|
||||
|
@ -277,12 +251,10 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
|
|||
url_template += "&redirect_uri=%3";
|
||||
url_template += "&state=%4";
|
||||
url_template += "&scope=https://www.googleapis.com/auth/youtube";
|
||||
QString url = url_template.arg(YOUTUBE_AUTH_URL, clientid.c_str(),
|
||||
redirect_uri, state);
|
||||
QString url = url_template.arg(YOUTUBE_AUTH_URL, clientid.c_str(), redirect_uri, state);
|
||||
|
||||
QString text = QTStr("YouTube.Auth.WaitingAuth.Text");
|
||||
text = text.arg(
|
||||
QString("<a href='%1'>Google OAuth Service</a>").arg(url));
|
||||
text = text.arg(QString("<a href='%1'>Google OAuth Service</a>").arg(url));
|
||||
|
||||
dlg.setText(text);
|
||||
dlg.setTextFormat(Qt::RichText);
|
||||
|
@ -293,25 +265,22 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
|
|||
dlg.setOption(QMessageBox::Option::DontUseNativeDialog);
|
||||
#endif
|
||||
|
||||
connect(&dlg, &QMessageBox::buttonClicked, &dlg,
|
||||
[&](QAbstractButton *) {
|
||||
connect(&dlg, &QMessageBox::buttonClicked, &dlg, [&](QAbstractButton *) {
|
||||
#ifdef _DEBUG
|
||||
blog(LOG_DEBUG, "Action Cancelled.");
|
||||
blog(LOG_DEBUG, "Action Cancelled.");
|
||||
#endif
|
||||
// TODO: Stop server.
|
||||
dlg.reject();
|
||||
});
|
||||
// TODO: Stop server.
|
||||
dlg.reject();
|
||||
});
|
||||
|
||||
// Async Login.
|
||||
connect(&server, &AuthListener::ok, &dlg,
|
||||
[&dlg, &auth_code](QString code) {
|
||||
connect(&server, &AuthListener::ok, &dlg, [&dlg, &auth_code](QString code) {
|
||||
#ifdef _DEBUG
|
||||
blog(LOG_DEBUG, "Got youtube redirected answer: %s",
|
||||
QT_TO_UTF8(code));
|
||||
blog(LOG_DEBUG, "Got youtube redirected answer: %s", QT_TO_UTF8(code));
|
||||
#endif
|
||||
auth_code = code;
|
||||
dlg.accept();
|
||||
});
|
||||
auth_code = code;
|
||||
dlg.accept();
|
||||
});
|
||||
connect(&server, &AuthListener::fail, &dlg, [&dlg]() {
|
||||
#ifdef _DEBUG
|
||||
blog(LOG_DEBUG, "No access granted");
|
||||
|
@ -325,10 +294,8 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
|
|||
QScopedPointer<QThread> thread(CreateQThread(open_external_browser));
|
||||
thread->start();
|
||||
|
||||
#if defined(__APPLE__) && QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) && \
|
||||
QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
|
||||
const bool nativeDialogs =
|
||||
qApp->testAttribute(Qt::AA_DontUseNativeDialogs);
|
||||
#if defined(__APPLE__) && QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) && QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
|
||||
const bool nativeDialogs = qApp->testAttribute(Qt::AA_DontUseNativeDialogs);
|
||||
App()->setAttribute(Qt::AA_DontUseNativeDialogs, true);
|
||||
dlg.exec();
|
||||
App()->setAttribute(Qt::AA_DontUseNativeDialogs, nativeDialogs);
|
||||
|
@ -336,12 +303,10 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
|
|||
dlg.exec();
|
||||
#endif
|
||||
|
||||
if (dlg.result() == QMessageBox::Cancel ||
|
||||
dlg.result() == QDialog::Rejected)
|
||||
if (dlg.result() == QMessageBox::Cancel || dlg.result() == QDialog::Rejected)
|
||||
return nullptr;
|
||||
|
||||
if (!auth->GetToken(YOUTUBE_TOKEN_URL, clientid, secret,
|
||||
QT_TO_UTF8(redirect_uri), YOUTUBE_SCOPE_VERSION,
|
||||
if (!auth->GetToken(YOUTUBE_TOKEN_URL, clientid, secret, QT_TO_UTF8(redirect_uri), YOUTUBE_SCOPE_VERSION,
|
||||
QT_TO_UTF8(auth_code), true)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -351,8 +316,7 @@ std::shared_ptr<Auth> YoutubeAuth::Login(QWidget *owner,
|
|||
|
||||
ChannelDescription cd;
|
||||
if (auth->GetChannelDescription(cd))
|
||||
config_set_string(config, "YouTube", "ChannelName",
|
||||
QT_TO_UTF8(cd.title));
|
||||
config_set_string(config, "YouTube", "ChannelName", QT_TO_UTF8(cd.title));
|
||||
|
||||
config_save_safe(config, "tmp", nullptr);
|
||||
return auth;
|
||||
|
@ -373,10 +337,8 @@ YoutubeChatDock::YoutubeChatDock(const QString &title) : BrowserDock(title)
|
|||
chatLayout->addWidget(lineEdit, 1);
|
||||
chatLayout->addWidget(sendButton);
|
||||
|
||||
QWidget::connect(lineEdit, &LineEditAutoResize::returnPressed, this,
|
||||
&YoutubeChatDock::SendChatMessage);
|
||||
QWidget::connect(sendButton, &QPushButton::pressed, this,
|
||||
&YoutubeChatDock::SendChatMessage);
|
||||
QWidget::connect(lineEdit, &LineEditAutoResize::returnPressed, this, &YoutubeChatDock::SendChatMessage);
|
||||
QWidget::connect(sendButton, &QPushButton::pressed, this, &YoutubeChatDock::SendChatMessage);
|
||||
}
|
||||
|
||||
void YoutubeChatDock::SetWidget(QCefWidget *widget_)
|
||||
|
@ -392,15 +354,13 @@ void YoutubeChatDock::SetWidget(QCefWidget *widget_)
|
|||
|
||||
cefWidget.reset(widget_);
|
||||
|
||||
QWidget::connect(cefWidget.get(), &QCefWidget::urlChanged, this,
|
||||
&YoutubeChatDock::YoutubeCookieCheck);
|
||||
QWidget::connect(cefWidget.get(), &QCefWidget::urlChanged, this, &YoutubeChatDock::YoutubeCookieCheck);
|
||||
}
|
||||
|
||||
void YoutubeChatDock::SetApiChatId(const std::string &id)
|
||||
{
|
||||
this->apiChatId = id;
|
||||
QMetaObject::invokeMethod(this, "EnableChatInput", Qt::QueuedConnection,
|
||||
Q_ARG(bool, !id.empty()));
|
||||
QMetaObject::invokeMethod(this, "EnableChatInput", Qt::QueuedConnection, Q_ARG(bool, !id.empty()));
|
||||
}
|
||||
|
||||
void YoutubeChatDock::YoutubeCookieCheck()
|
||||
|
@ -409,25 +369,20 @@ void YoutubeChatDock::YoutubeCookieCheck()
|
|||
auto cb = [this_](bool currentlyLoggedIn) {
|
||||
bool previouslyLoggedIn = this_->isLoggedIn;
|
||||
this_->isLoggedIn = currentlyLoggedIn;
|
||||
bool loginStateChanged =
|
||||
(currentlyLoggedIn && !previouslyLoggedIn) ||
|
||||
(!currentlyLoggedIn && previouslyLoggedIn);
|
||||
bool loginStateChanged = (currentlyLoggedIn && !previouslyLoggedIn) ||
|
||||
(!currentlyLoggedIn && previouslyLoggedIn);
|
||||
if (loginStateChanged) {
|
||||
QMetaObject::invokeMethod(
|
||||
this_, "EnableChatInput", Qt::QueuedConnection,
|
||||
Q_ARG(bool, !currentlyLoggedIn));
|
||||
QMetaObject::invokeMethod(this_, "EnableChatInput", Qt::QueuedConnection,
|
||||
Q_ARG(bool, !currentlyLoggedIn));
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
if (main->GetYouTubeAppDock() != nullptr) {
|
||||
QMetaObject::invokeMethod(
|
||||
main->GetYouTubeAppDock(),
|
||||
"SettingsUpdated", Qt::QueuedConnection,
|
||||
Q_ARG(bool, !currentlyLoggedIn));
|
||||
QMetaObject::invokeMethod(main->GetYouTubeAppDock(), "SettingsUpdated",
|
||||
Qt::QueuedConnection, Q_ARG(bool, !currentlyLoggedIn));
|
||||
}
|
||||
}
|
||||
};
|
||||
if (panel_cookies) {
|
||||
panel_cookies->CheckForCookie("https://www.youtube.com", "SID",
|
||||
cb);
|
||||
panel_cookies->CheckForCookie("https://www.youtube.com", "SID", cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -438,31 +393,26 @@ void YoutubeChatDock::SendChatMessage()
|
|||
return;
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
YoutubeApiWrappers *apiYouTube(
|
||||
dynamic_cast<YoutubeApiWrappers *>(main->GetAuth()));
|
||||
YoutubeApiWrappers *apiYouTube(dynamic_cast<YoutubeApiWrappers *>(main->GetAuth()));
|
||||
|
||||
ExecuteFuncSafeBlock([&]() {
|
||||
lineEdit->setText("");
|
||||
lineEdit->setPlaceholderText(
|
||||
QTStr("YouTube.Chat.Input.Sending"));
|
||||
lineEdit->setPlaceholderText(QTStr("YouTube.Chat.Input.Sending"));
|
||||
if (apiYouTube->SendChatMessage(apiChatId, message)) {
|
||||
os_sleep_ms(3000);
|
||||
} else {
|
||||
QString error = apiYouTube->GetLastError();
|
||||
apiYouTube->GetTranslatedError(error);
|
||||
QMetaObject::invokeMethod(
|
||||
this, "ShowErrorMessage", Qt::QueuedConnection,
|
||||
Q_ARG(const QString &, error));
|
||||
QMetaObject::invokeMethod(this, "ShowErrorMessage", Qt::QueuedConnection,
|
||||
Q_ARG(const QString &, error));
|
||||
}
|
||||
lineEdit->setPlaceholderText(
|
||||
QTStr("YouTube.Chat.Input.Placeholder"));
|
||||
lineEdit->setPlaceholderText(QTStr("YouTube.Chat.Input.Placeholder"));
|
||||
});
|
||||
}
|
||||
|
||||
void YoutubeChatDock::ShowErrorMessage(const QString &error)
|
||||
{
|
||||
QMessageBox::warning(this, QTStr("YouTube.Chat.Error.Title"),
|
||||
QTStr("YouTube.Chat.Error.Text").arg(error));
|
||||
QMessageBox::warning(this, QTStr("YouTube.Chat.Error.Title"), QTStr("YouTube.Chat.Error.Text").arg(error));
|
||||
}
|
||||
|
||||
void YoutubeChatDock::EnableChatInput(bool visible)
|
||||
|
|
|
@ -34,10 +34,9 @@ private slots:
|
|||
};
|
||||
#endif
|
||||
|
||||
inline const std::vector<Auth::Def> youtubeServices = {
|
||||
{"YouTube - RTMP", Auth::Type::OAuth_LinkedAccount, true, true},
|
||||
{"YouTube - RTMPS", Auth::Type::OAuth_LinkedAccount, true, true},
|
||||
{"YouTube - HLS", Auth::Type::OAuth_LinkedAccount, true, true}};
|
||||
inline const std::vector<Auth::Def> youtubeServices = {{"YouTube - RTMP", Auth::Type::OAuth_LinkedAccount, true, true},
|
||||
{"YouTube - RTMPS", Auth::Type::OAuth_LinkedAccount, true, true},
|
||||
{"YouTube - HLS", Auth::Type::OAuth_LinkedAccount, true, true}};
|
||||
|
||||
class YoutubeAuth : public OAuthStreamKey {
|
||||
Q_OBJECT
|
||||
|
@ -64,6 +63,5 @@ public:
|
|||
void ResetChat();
|
||||
void ReloadChat();
|
||||
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent,
|
||||
const std::string &service);
|
||||
static std::shared_ptr<Auth> Login(QWidget *parent, const std::string &service);
|
||||
};
|
||||
|
|
|
@ -2,80 +2,61 @@
|
|||
|
||||
#include "window-basic-main.hpp"
|
||||
|
||||
OBSBasicControls::OBSBasicControls(OBSBasic *main)
|
||||
: QFrame(nullptr),
|
||||
ui(new Ui::OBSBasicControls)
|
||||
OBSBasicControls::OBSBasicControls(OBSBasic *main) : QFrame(nullptr), ui(new Ui::OBSBasicControls)
|
||||
{
|
||||
/* Create UI elements */
|
||||
ui->setupUi(this);
|
||||
|
||||
streamButtonMenu.reset(new QMenu());
|
||||
startStreamAction =
|
||||
streamButtonMenu->addAction(QTStr("Basic.Main.StartStreaming"));
|
||||
stopStreamAction =
|
||||
streamButtonMenu->addAction(QTStr("Basic.Main.StopStreaming"));
|
||||
QAction *forceStopStreamAction = streamButtonMenu->addAction(
|
||||
QTStr("Basic.Main.ForceStopStreaming"));
|
||||
startStreamAction = streamButtonMenu->addAction(QTStr("Basic.Main.StartStreaming"));
|
||||
stopStreamAction = streamButtonMenu->addAction(QTStr("Basic.Main.StopStreaming"));
|
||||
QAction *forceStopStreamAction = streamButtonMenu->addAction(QTStr("Basic.Main.ForceStopStreaming"));
|
||||
|
||||
/* Transfer buttons signals as OBSBasicControls signals */
|
||||
connect(
|
||||
ui->streamButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->StreamButtonClicked(); },
|
||||
ui->streamButton, &QPushButton::clicked, this, [this]() { emit this->StreamButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->broadcastButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->BroadcastButtonClicked(); },
|
||||
ui->broadcastButton, &QPushButton::clicked, this, [this]() { emit this->BroadcastButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->recordButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->RecordButtonClicked(); },
|
||||
ui->recordButton, &QPushButton::clicked, this, [this]() { emit this->RecordButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->pauseRecordButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->PauseRecordButtonClicked(); },
|
||||
ui->pauseRecordButton, &QPushButton::clicked, this, [this]() { emit this->PauseRecordButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->replayBufferButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->ReplayBufferButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
[this]() { emit this->ReplayBufferButtonClicked(); }, Qt::DirectConnection);
|
||||
connect(
|
||||
ui->saveReplayButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->SaveReplayBufferButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
[this]() { emit this->SaveReplayBufferButtonClicked(); }, Qt::DirectConnection);
|
||||
connect(
|
||||
ui->virtualCamButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->VirtualCamButtonClicked(); },
|
||||
ui->virtualCamButton, &QPushButton::clicked, this, [this]() { emit this->VirtualCamButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->virtualCamConfigButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->VirtualCamConfigButtonClicked(); },
|
||||
[this]() { emit this->VirtualCamConfigButtonClicked(); }, Qt::DirectConnection);
|
||||
connect(
|
||||
ui->modeSwitch, &QPushButton::clicked, this, [this]() { emit this->StudioModeButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->modeSwitch, &QPushButton::clicked, this,
|
||||
[this]() { emit this->StudioModeButtonClicked(); },
|
||||
ui->settingsButton, &QPushButton::clicked, this, [this]() { emit this->SettingsButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->settingsButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->SettingsButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
connect(
|
||||
ui->exitButton, &QPushButton::clicked, this,
|
||||
[this]() { emit this->ExitButtonClicked(); },
|
||||
ui->exitButton, &QPushButton::clicked, this, [this]() { emit this->ExitButtonClicked(); },
|
||||
Qt::DirectConnection);
|
||||
|
||||
/* Transfer menu actions signals as OBSBasicControls signals */
|
||||
connect(
|
||||
startStreamAction.get(), &QAction::triggered, this,
|
||||
[this]() { emit this->StartStreamMenuActionClicked(); },
|
||||
Qt::DirectConnection);
|
||||
[this]() { emit this->StartStreamMenuActionClicked(); }, Qt::DirectConnection);
|
||||
connect(
|
||||
stopStreamAction.get(), &QAction::triggered, this,
|
||||
[this]() { emit this->StopStreamMenuActionClicked(); },
|
||||
Qt::DirectConnection);
|
||||
[this]() { emit this->StopStreamMenuActionClicked(); }, Qt::DirectConnection);
|
||||
connect(
|
||||
forceStopStreamAction, &QAction::triggered, this,
|
||||
[this]() { emit this->ForceStopStreamMenuActionClicked(); },
|
||||
Qt::DirectConnection);
|
||||
[this]() { emit this->ForceStopStreamMenuActionClicked(); }, Qt::DirectConnection);
|
||||
|
||||
/* Set up default visibilty */
|
||||
ui->broadcastButton->setVisible(false);
|
||||
|
@ -86,57 +67,35 @@ OBSBasicControls::OBSBasicControls(OBSBasic *main)
|
|||
ui->virtualCamConfigButton->setVisible(false);
|
||||
|
||||
/* Set up state update connections */
|
||||
connect(main, &OBSBasic::StreamingPreparing, this,
|
||||
&OBSBasicControls::StreamingPreparing);
|
||||
connect(main, &OBSBasic::StreamingStarting, this,
|
||||
&OBSBasicControls::StreamingStarting);
|
||||
connect(main, &OBSBasic::StreamingStarted, this,
|
||||
&OBSBasicControls::StreamingStarted);
|
||||
connect(main, &OBSBasic::StreamingStopping, this,
|
||||
&OBSBasicControls::StreamingStopping);
|
||||
connect(main, &OBSBasic::StreamingStopped, this,
|
||||
&OBSBasicControls::StreamingStopped);
|
||||
connect(main, &OBSBasic::StreamingPreparing, this, &OBSBasicControls::StreamingPreparing);
|
||||
connect(main, &OBSBasic::StreamingStarting, this, &OBSBasicControls::StreamingStarting);
|
||||
connect(main, &OBSBasic::StreamingStarted, this, &OBSBasicControls::StreamingStarted);
|
||||
connect(main, &OBSBasic::StreamingStopping, this, &OBSBasicControls::StreamingStopping);
|
||||
connect(main, &OBSBasic::StreamingStopped, this, &OBSBasicControls::StreamingStopped);
|
||||
|
||||
connect(main, &OBSBasic::BroadcastStreamReady, this,
|
||||
&OBSBasicControls::BroadcastStreamReady);
|
||||
connect(main, &OBSBasic::BroadcastStreamActive, this,
|
||||
&OBSBasicControls::BroadcastStreamActive);
|
||||
connect(main, &OBSBasic::BroadcastStreamStarted, this,
|
||||
&OBSBasicControls::BroadcastStreamStarted);
|
||||
connect(main, &OBSBasic::BroadcastStreamReady, this, &OBSBasicControls::BroadcastStreamReady);
|
||||
connect(main, &OBSBasic::BroadcastStreamActive, this, &OBSBasicControls::BroadcastStreamActive);
|
||||
connect(main, &OBSBasic::BroadcastStreamStarted, this, &OBSBasicControls::BroadcastStreamStarted);
|
||||
|
||||
connect(main, &OBSBasic::RecordingStarted, this,
|
||||
&OBSBasicControls::RecordingStarted);
|
||||
connect(main, &OBSBasic::RecordingPaused, this,
|
||||
&OBSBasicControls::RecordingPaused);
|
||||
connect(main, &OBSBasic::RecordingUnpaused, this,
|
||||
&OBSBasicControls::RecordingUnpaused);
|
||||
connect(main, &OBSBasic::RecordingStopping, this,
|
||||
&OBSBasicControls::RecordingStopping);
|
||||
connect(main, &OBSBasic::RecordingStopped, this,
|
||||
&OBSBasicControls::RecordingStopped);
|
||||
connect(main, &OBSBasic::RecordingStarted, this, &OBSBasicControls::RecordingStarted);
|
||||
connect(main, &OBSBasic::RecordingPaused, this, &OBSBasicControls::RecordingPaused);
|
||||
connect(main, &OBSBasic::RecordingUnpaused, this, &OBSBasicControls::RecordingUnpaused);
|
||||
connect(main, &OBSBasic::RecordingStopping, this, &OBSBasicControls::RecordingStopping);
|
||||
connect(main, &OBSBasic::RecordingStopped, this, &OBSBasicControls::RecordingStopped);
|
||||
|
||||
connect(main, &OBSBasic::ReplayBufStarted, this,
|
||||
&OBSBasicControls::ReplayBufferStarted);
|
||||
connect(main, &OBSBasic::ReplayBufStopping, this,
|
||||
&OBSBasicControls::ReplayBufferStopping);
|
||||
connect(main, &OBSBasic::ReplayBufStopped, this,
|
||||
&OBSBasicControls::ReplayBufferStopped);
|
||||
connect(main, &OBSBasic::ReplayBufStarted, this, &OBSBasicControls::ReplayBufferStarted);
|
||||
connect(main, &OBSBasic::ReplayBufStopping, this, &OBSBasicControls::ReplayBufferStopping);
|
||||
connect(main, &OBSBasic::ReplayBufStopped, this, &OBSBasicControls::ReplayBufferStopped);
|
||||
|
||||
connect(main, &OBSBasic::VirtualCamStarted, this,
|
||||
&OBSBasicControls::VirtualCamStarted);
|
||||
connect(main, &OBSBasic::VirtualCamStopped, this,
|
||||
&OBSBasicControls::VirtualCamStopped);
|
||||
connect(main, &OBSBasic::VirtualCamStarted, this, &OBSBasicControls::VirtualCamStarted);
|
||||
connect(main, &OBSBasic::VirtualCamStopped, this, &OBSBasicControls::VirtualCamStopped);
|
||||
|
||||
connect(main, &OBSBasic::PreviewProgramModeChanged, this,
|
||||
&OBSBasicControls::UpdateStudioModeState);
|
||||
connect(main, &OBSBasic::PreviewProgramModeChanged, this, &OBSBasicControls::UpdateStudioModeState);
|
||||
|
||||
/* Set up enablement connection */
|
||||
connect(main, &OBSBasic::BroadcastFlowEnabled, this,
|
||||
&OBSBasicControls::EnableBroadcastFlow);
|
||||
connect(main, &OBSBasic::ReplayBufEnabled, this,
|
||||
&OBSBasicControls::EnableReplayBufferButtons);
|
||||
connect(main, &OBSBasic::VirtualCamEnabled, this,
|
||||
&OBSBasicControls::EnableVirtualCamButtons);
|
||||
connect(main, &OBSBasic::BroadcastFlowEnabled, this, &OBSBasicControls::EnableBroadcastFlow);
|
||||
connect(main, &OBSBasic::ReplayBufEnabled, this, &OBSBasicControls::EnableReplayBufferButtons);
|
||||
connect(main, &OBSBasic::VirtualCamEnabled, this, &OBSBasicControls::EnableVirtualCamButtons);
|
||||
}
|
||||
|
||||
void OBSBasicControls::StreamingPreparing()
|
||||
|
@ -153,8 +112,7 @@ void OBSBasicControls::StreamingStarting(bool broadcastAutoStart)
|
|||
// well, we need to disable button while stream is not active
|
||||
ui->broadcastButton->setEnabled(false);
|
||||
|
||||
ui->broadcastButton->setText(
|
||||
QTStr("Basic.Main.StartBroadcast"));
|
||||
ui->broadcastButton->setText(QTStr("Basic.Main.StartBroadcast"));
|
||||
|
||||
ui->broadcastButton->setProperty("broadcastState", "ready");
|
||||
ui->broadcastButton->style()->unpolish(ui->broadcastButton);
|
||||
|
@ -209,9 +167,7 @@ void OBSBasicControls::BroadcastStreamActive()
|
|||
|
||||
void OBSBasicControls::BroadcastStreamStarted(bool autoStop)
|
||||
{
|
||||
ui->broadcastButton->setText(
|
||||
QTStr(autoStop ? "Basic.Main.AutoStopEnabled"
|
||||
: "Basic.Main.StopBroadcast"));
|
||||
ui->broadcastButton->setText(QTStr(autoStop ? "Basic.Main.AutoStopEnabled" : "Basic.Main.StopBroadcast"));
|
||||
if (autoStop)
|
||||
ui->broadcastButton->setEnabled(false);
|
||||
|
||||
|
@ -276,8 +232,7 @@ void OBSBasicControls::ReplayBufferStarted()
|
|||
|
||||
void OBSBasicControls::ReplayBufferStopping()
|
||||
{
|
||||
ui->replayBufferButton->setText(
|
||||
QTStr("Basic.Main.StoppingReplayBuffer"));
|
||||
ui->replayBufferButton->setText(QTStr("Basic.Main.StoppingReplayBuffer"));
|
||||
}
|
||||
|
||||
void OBSBasicControls::ReplayBufferStopped()
|
||||
|
|
|
@ -56,16 +56,12 @@ void SourceToolbar::SetUndoProperties(obs_source_t *source, bool repeatable)
|
|||
if (!currentSceneSource)
|
||||
return;
|
||||
std::string scene_uuid = obs_source_get_uuid(currentSceneSource);
|
||||
auto undo_redo = [scene_uuid = std::move(scene_uuid),
|
||||
main](const std::string &data) {
|
||||
OBSDataAutoRelease settings =
|
||||
obs_data_create_from_json(data.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(
|
||||
obs_data_get_string(settings, "undo_suuid"));
|
||||
auto undo_redo = [scene_uuid = std::move(scene_uuid), main](const std::string &data) {
|
||||
OBSDataAutoRelease settings = obs_data_create_from_json(data.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(obs_data_get_string(settings, "undo_suuid"));
|
||||
obs_source_reset_settings(source, settings);
|
||||
|
||||
OBSSourceAutoRelease scene_source =
|
||||
obs_get_source_by_uuid(scene_uuid.c_str());
|
||||
OBSSourceAutoRelease scene_source = obs_get_source_by_uuid(scene_uuid.c_str());
|
||||
main->SetCurrentScene(scene_source.Get(), true);
|
||||
|
||||
main->UpdateContextBar();
|
||||
|
@ -74,17 +70,14 @@ void SourceToolbar::SetUndoProperties(obs_source_t *source, bool repeatable)
|
|||
OBSDataAutoRelease new_settings = obs_data_create();
|
||||
OBSDataAutoRelease curr_settings = obs_source_get_settings(source);
|
||||
obs_data_apply(new_settings, curr_settings);
|
||||
obs_data_set_string(new_settings, "undo_suuid",
|
||||
obs_source_get_uuid(source));
|
||||
obs_data_set_string(new_settings, "undo_suuid", obs_source_get_uuid(source));
|
||||
|
||||
std::string undo_data(obs_data_get_json(oldData));
|
||||
std::string redo_data(obs_data_get_json(new_settings));
|
||||
|
||||
if (undo_data.compare(redo_data) != 0)
|
||||
main->undo_s.add_action(
|
||||
QTStr("Undo.Properties")
|
||||
.arg(obs_source_get_name(source)),
|
||||
undo_redo, undo_redo, undo_data, redo_data, repeatable);
|
||||
main->undo_s.add_action(QTStr("Undo.Properties").arg(obs_source_get_name(source)), undo_redo, undo_redo,
|
||||
undo_data, redo_data, repeatable);
|
||||
|
||||
oldData = nullptr;
|
||||
}
|
||||
|
@ -122,8 +115,7 @@ ComboSelectToolbar::ComboSelectToolbar(QWidget *parent, OBSSource source)
|
|||
|
||||
ComboSelectToolbar::~ComboSelectToolbar() {}
|
||||
|
||||
static int FillPropertyCombo(QComboBox *c, obs_property_t *p,
|
||||
const std::string &cur_id, bool is_int = false)
|
||||
static int FillPropertyCombo(QComboBox *c, obs_property_t *p, const std::string &cur_id, bool is_int = false)
|
||||
{
|
||||
size_t count = obs_property_list_item_count(p);
|
||||
int cur_idx = -1;
|
||||
|
@ -148,8 +140,7 @@ static int FillPropertyCombo(QComboBox *c, obs_property_t *p,
|
|||
return cur_idx;
|
||||
}
|
||||
|
||||
void UpdateSourceComboToolbarProperties(QComboBox *combo, OBSSource source,
|
||||
obs_properties_t *props,
|
||||
void UpdateSourceComboToolbarProperties(QComboBox *combo, OBSSource source, obs_properties_t *props,
|
||||
const char *prop_name, bool is_int)
|
||||
{
|
||||
std::string cur_id;
|
||||
|
@ -168,9 +159,7 @@ void UpdateSourceComboToolbarProperties(QComboBox *combo, OBSSource source,
|
|||
|
||||
if (cur_idx == -1 || obs_property_list_item_disabled(p, cur_idx)) {
|
||||
if (cur_idx == -1) {
|
||||
combo->insertItem(
|
||||
0,
|
||||
QTStr("Basic.Settings.Audio.UnknownAudioDevice"));
|
||||
combo->insertItem(0, QTStr("Basic.Settings.Audio.UnknownAudioDevice"));
|
||||
cur_idx = 0;
|
||||
}
|
||||
|
||||
|
@ -188,12 +177,10 @@ void ComboSelectToolbar::Init()
|
|||
return;
|
||||
}
|
||||
|
||||
UpdateSourceComboToolbarProperties(ui->device, source, props.get(),
|
||||
prop_name, is_int);
|
||||
UpdateSourceComboToolbarProperties(ui->device, source, props.get(), prop_name, is_int);
|
||||
}
|
||||
|
||||
void UpdateSourceComboToolbarValue(QComboBox *combo, OBSSource source, int idx,
|
||||
const char *prop_name, bool is_int)
|
||||
void UpdateSourceComboToolbarValue(QComboBox *combo, OBSSource source, int idx, const char *prop_name, bool is_int)
|
||||
{
|
||||
QString id = combo->itemData(idx).toString();
|
||||
|
||||
|
@ -214,28 +201,22 @@ void ComboSelectToolbar::on_device_currentIndexChanged(int idx)
|
|||
}
|
||||
|
||||
SaveOldProperties(source);
|
||||
UpdateSourceComboToolbarValue(ui->device, source, idx, prop_name,
|
||||
is_int);
|
||||
UpdateSourceComboToolbarValue(ui->device, source, idx, prop_name, is_int);
|
||||
SetUndoProperties(source);
|
||||
}
|
||||
|
||||
AudioCaptureToolbar::AudioCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: ComboSelectToolbar(parent, source)
|
||||
{
|
||||
}
|
||||
AudioCaptureToolbar::AudioCaptureToolbar(QWidget *parent, OBSSource source) : ComboSelectToolbar(parent, source) {}
|
||||
|
||||
void AudioCaptureToolbar::Init()
|
||||
{
|
||||
delete ui->activateButton;
|
||||
ui->activateButton = nullptr;
|
||||
|
||||
obs_module_t *mod =
|
||||
get_os_module("win-wasapi", "mac-capture", "linux-pulseaudio");
|
||||
obs_module_t *mod = get_os_module("win-wasapi", "mac-capture", "linux-pulseaudio");
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
const char *device_str =
|
||||
get_os_text(mod, "Device", "CoreAudio.Device", "Device");
|
||||
const char *device_str = get_os_text(mod, "Device", "CoreAudio.Device", "Device");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
prop_name = "device_id";
|
||||
|
@ -243,23 +224,18 @@ void AudioCaptureToolbar::Init()
|
|||
ComboSelectToolbar::Init();
|
||||
}
|
||||
|
||||
WindowCaptureToolbar::WindowCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: ComboSelectToolbar(parent, source)
|
||||
{
|
||||
}
|
||||
WindowCaptureToolbar::WindowCaptureToolbar(QWidget *parent, OBSSource source) : ComboSelectToolbar(parent, source) {}
|
||||
|
||||
void WindowCaptureToolbar::Init()
|
||||
{
|
||||
delete ui->activateButton;
|
||||
ui->activateButton = nullptr;
|
||||
|
||||
obs_module_t *mod =
|
||||
get_os_module("win-capture", "mac-capture", "linux-capture");
|
||||
obs_module_t *mod = get_os_module("win-capture", "mac-capture", "linux-capture");
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
const char *device_str = get_os_text(mod, "WindowCapture.Window",
|
||||
"WindowUtils.Window", "Window");
|
||||
const char *device_str = get_os_text(mod, "WindowCapture.Window", "WindowUtils.Window", "Window");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__) //linux
|
||||
|
@ -275,8 +251,7 @@ void WindowCaptureToolbar::Init()
|
|||
ComboSelectToolbar::Init();
|
||||
}
|
||||
|
||||
ApplicationAudioCaptureToolbar::ApplicationAudioCaptureToolbar(QWidget *parent,
|
||||
OBSSource source)
|
||||
ApplicationAudioCaptureToolbar::ApplicationAudioCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: ComboSelectToolbar(parent, source)
|
||||
{
|
||||
}
|
||||
|
@ -295,23 +270,18 @@ void ApplicationAudioCaptureToolbar::Init()
|
|||
ComboSelectToolbar::Init();
|
||||
}
|
||||
|
||||
DisplayCaptureToolbar::DisplayCaptureToolbar(QWidget *parent, OBSSource source)
|
||||
: ComboSelectToolbar(parent, source)
|
||||
{
|
||||
}
|
||||
DisplayCaptureToolbar::DisplayCaptureToolbar(QWidget *parent, OBSSource source) : ComboSelectToolbar(parent, source) {}
|
||||
|
||||
void DisplayCaptureToolbar::Init()
|
||||
{
|
||||
delete ui->activateButton;
|
||||
ui->activateButton = nullptr;
|
||||
|
||||
obs_module_t *mod =
|
||||
get_os_module("win-capture", "mac-capture", "linux-capture");
|
||||
obs_module_t *mod = get_os_module("win-capture", "mac-capture", "linux-capture");
|
||||
if (!mod)
|
||||
return;
|
||||
|
||||
const char *device_str =
|
||||
get_os_text(mod, "Monitor", "DisplayCapture.Display", "Screen");
|
||||
const char *device_str = get_os_text(mod, "Monitor", "DisplayCapture.Display", "Screen");
|
||||
ui->deviceLabel->setText(device_str);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -399,8 +369,7 @@ GameCaptureToolbar::GameCaptureToolbar(QWidget *parent, OBSSource source)
|
|||
return;
|
||||
|
||||
ui->modeLabel->setText(obs_module_get_locale_text(mod, "Mode"));
|
||||
ui->windowLabel->setText(
|
||||
obs_module_get_locale_text(mod, "WindowCapture.Window"));
|
||||
ui->windowLabel->setText(obs_module_get_locale_text(mod, "WindowCapture.Window"));
|
||||
|
||||
OBSDataAutoRelease settings = obs_source_get_settings(source);
|
||||
std::string cur_mode = obs_data_get_string(settings, "capture_mode");
|
||||
|
@ -522,8 +491,7 @@ void ImageSourceToolbar::on_browse_clicked()
|
|||
|
||||
static inline QColor color_from_int(long long val)
|
||||
{
|
||||
return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff,
|
||||
(val >> 24) & 0xff);
|
||||
return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff, (val >> 24) & 0xff);
|
||||
}
|
||||
|
||||
static inline long long color_to_int(QColor color)
|
||||
|
@ -532,8 +500,7 @@ static inline long long color_to_int(QColor color)
|
|||
return ((val & 0xff) << shift);
|
||||
};
|
||||
|
||||
return shift(color.red(), 0) | shift(color.green(), 8) |
|
||||
shift(color.blue(), 16) | shift(color.alpha(), 24);
|
||||
return shift(color.red(), 0) | shift(color.green(), 8) | shift(color.blue(), 16) | shift(color.alpha(), 24);
|
||||
}
|
||||
|
||||
ColorSourceToolbar::ColorSourceToolbar(QWidget *parent, OBSSource source)
|
||||
|
@ -557,12 +524,9 @@ void ColorSourceToolbar::UpdateColor()
|
|||
ui->color->setFrameStyle(QFrame::Sunken | QFrame::Panel);
|
||||
ui->color->setText(color.name(QColor::HexRgb));
|
||||
ui->color->setPalette(palette);
|
||||
ui->color->setStyleSheet(
|
||||
QString("background-color :%1; color: %2;")
|
||||
.arg(palette.color(QPalette::Window)
|
||||
.name(QColor::HexRgb))
|
||||
.arg(palette.color(QPalette::WindowText)
|
||||
.name(QColor::HexRgb)));
|
||||
ui->color->setStyleSheet(QString("background-color :%1; color: %2;")
|
||||
.arg(palette.color(QPalette::Window).name(QColor::HexRgb))
|
||||
.arg(palette.color(QPalette::WindowText).name(QColor::HexRgb)));
|
||||
ui->color->setAutoFillBackground(true);
|
||||
ui->color->setAlignment(Qt::AlignCenter);
|
||||
}
|
||||
|
@ -616,25 +580,20 @@ TextSourceToolbar::TextSourceToolbar(QWidget *parent, OBSSource source)
|
|||
|
||||
const char *id = obs_source_get_unversioned_id(source);
|
||||
bool ft2 = strcmp(id, "text_ft2_source") == 0;
|
||||
bool read_from_file = obs_data_get_bool(
|
||||
settings, ft2 ? "from_file" : "read_from_file");
|
||||
bool read_from_file = obs_data_get_bool(settings, ft2 ? "from_file" : "read_from_file");
|
||||
|
||||
OBSDataAutoRelease font_obj = obs_data_get_obj(settings, "font");
|
||||
MakeQFont(font_obj, font);
|
||||
|
||||
// Use "color1" if it's a freetype source and "color" elsewise
|
||||
unsigned int val = (unsigned int)obs_data_get_int(
|
||||
settings,
|
||||
(strncmp(obs_source_get_id(source), "text_ft2_source", 15) == 0)
|
||||
? "color1"
|
||||
: "color");
|
||||
settings, (strncmp(obs_source_get_id(source), "text_ft2_source", 15) == 0) ? "color1" : "color");
|
||||
|
||||
color = color_from_int(val);
|
||||
|
||||
const char *text = obs_data_get_string(settings, "text");
|
||||
|
||||
bool single_line = !read_from_file &&
|
||||
(!text || (strchr(text, '\n') == nullptr));
|
||||
bool single_line = !read_from_file && (!text || (strchr(text, '\n') == nullptr));
|
||||
ui->emptySpace->setVisible(!single_line);
|
||||
ui->text->setVisible(single_line);
|
||||
if (single_line)
|
||||
|
@ -658,10 +617,8 @@ void TextSourceToolbar::on_selectFont_clicked()
|
|||
options = QFontDialog::DontUseNativeDialog;
|
||||
#endif
|
||||
|
||||
font = QFontDialog::getFont(
|
||||
&success, font, this,
|
||||
QTStr("Basic.PropertiesWindow.SelectFont.WindowTitle"),
|
||||
options);
|
||||
font = QFontDialog::getFont(&success, font, this, QTStr("Basic.PropertiesWindow.SelectFont.WindowTitle"),
|
||||
options);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
@ -695,11 +652,9 @@ void TextSourceToolbar::on_selectColor_clicked()
|
|||
return;
|
||||
}
|
||||
|
||||
bool freetype =
|
||||
strncmp(obs_source_get_id(source), "text_ft2_source", 15) == 0;
|
||||
bool freetype = strncmp(obs_source_get_id(source), "text_ft2_source", 15) == 0;
|
||||
|
||||
obs_property_t *p =
|
||||
obs_properties_get(props.get(), freetype ? "color1" : "color");
|
||||
obs_property_t *p = obs_properties_get(props.get(), freetype ? "color1" : "color");
|
||||
|
||||
const char *desc = obs_property_description(p);
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ class SourceToolbar : public QWidget {
|
|||
|
||||
protected:
|
||||
using properties_delete_t = decltype(&obs_properties_destroy);
|
||||
using properties_t =
|
||||
std::unique_ptr<obs_properties_t, properties_delete_t>;
|
||||
using properties_t = std::unique_ptr<obs_properties_t, properties_delete_t>;
|
||||
|
||||
properties_t props;
|
||||
OBSDataAutoRelease oldData;
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
#include <graphics/vec4.h>
|
||||
#include <graphics/matrix4.h>
|
||||
|
||||
static inline void GetScaleAndCenterPos(int baseCX, int baseCY, int windowCX,
|
||||
int windowCY, int &x, int &y,
|
||||
static inline void GetScaleAndCenterPos(int baseCX, int baseCY, int windowCX, int windowCY, int &x, int &y,
|
||||
float &scale)
|
||||
{
|
||||
double windowAspect, baseAspect;
|
||||
|
@ -44,9 +43,8 @@ static inline void GetScaleAndCenterPos(int baseCX, int baseCY, int windowCX,
|
|||
y = windowCY / 2 - newCY / 2;
|
||||
}
|
||||
|
||||
static inline void GetCenterPosFromFixedScale(int baseCX, int baseCY,
|
||||
int windowCX, int windowCY,
|
||||
int &x, int &y, float scale)
|
||||
static inline void GetCenterPosFromFixedScale(int baseCX, int baseCY, int windowCX, int windowCY, int &x, int &y,
|
||||
float scale)
|
||||
{
|
||||
x = (float(windowCX) - float(baseCX) * scale) / 2.0f;
|
||||
y = (float(windowCY) - float(baseCY) * scale) / 2.0f;
|
||||
|
@ -65,12 +63,9 @@ static inline QSize GetPixelSize(QWidget *widget)
|
|||
#define GRAPHICS_SAFE_PERCENT 0.05f // 5.0%
|
||||
#define FOURBYTHREE_SAFE_PERCENT 0.1625f // 16.25%
|
||||
|
||||
static inline void InitSafeAreas(gs_vertbuffer_t **actionSafeMargin,
|
||||
gs_vertbuffer_t **graphicsSafeMargin,
|
||||
gs_vertbuffer_t **fourByThreeSafeMargin,
|
||||
gs_vertbuffer_t **leftLine,
|
||||
gs_vertbuffer_t **topLine,
|
||||
gs_vertbuffer_t **rightLine)
|
||||
static inline void InitSafeAreas(gs_vertbuffer_t **actionSafeMargin, gs_vertbuffer_t **graphicsSafeMargin,
|
||||
gs_vertbuffer_t **fourByThreeSafeMargin, gs_vertbuffer_t **leftLine,
|
||||
gs_vertbuffer_t **topLine, gs_vertbuffer_t **rightLine)
|
||||
{
|
||||
obs_enter_graphics();
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ extern "C" {
|
|||
|
||||
using namespace std;
|
||||
|
||||
vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format,
|
||||
bool ignore_compatibility)
|
||||
vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format, bool ignore_compatibility)
|
||||
{
|
||||
vector<FFmpegCodec> codecs;
|
||||
const AVCodec *codec;
|
||||
|
@ -38,8 +37,7 @@ vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format,
|
|||
if (!av_codec_is_encoder(codec))
|
||||
continue;
|
||||
// Skip if not supported and compatibility check not disabled
|
||||
if (!ignore_compatibility &&
|
||||
!av_codec_get_tag(format.codec_tags, codec->id)) {
|
||||
if (!ignore_compatibility && !av_codec_get_tag(format.codec_tags, codec->id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -82,8 +80,7 @@ vector<FFmpegFormat> GetSupportedFormats()
|
|||
|
||||
FFmpegCodec FFmpegFormat::GetDefaultEncoder(FFmpegCodecType codec_type) const
|
||||
{
|
||||
const AVCodecID codec_id = codec_type == VIDEO ? video_codec
|
||||
: audio_codec;
|
||||
const AVCodecID codec_id = codec_type == VIDEO ? video_codec : audio_codec;
|
||||
if (codec_type == UNKNOWN || codec_id == AV_CODEC_ID_NONE)
|
||||
return {};
|
||||
|
||||
|
@ -100,23 +97,19 @@ bool FFCodecAndFormatCompatible(const char *codec, const char *format)
|
|||
if (!codec || !format)
|
||||
return false;
|
||||
|
||||
const AVOutputFormat *output_format =
|
||||
av_guess_format(format, nullptr, nullptr);
|
||||
const AVOutputFormat *output_format = av_guess_format(format, nullptr, nullptr);
|
||||
if (!output_format)
|
||||
return false;
|
||||
|
||||
const AVCodecDescriptor *codec_desc =
|
||||
avcodec_descriptor_get_by_name(codec);
|
||||
const AVCodecDescriptor *codec_desc = avcodec_descriptor_get_by_name(codec);
|
||||
if (!codec_desc)
|
||||
return false;
|
||||
|
||||
return avformat_query_codec(output_format, codec_desc->id,
|
||||
FF_COMPLIANCE_NORMAL) == 1;
|
||||
return avformat_query_codec(output_format, codec_desc->id, FF_COMPLIANCE_NORMAL) == 1;
|
||||
}
|
||||
|
||||
static const unordered_set<string> builtin_codecs = {
|
||||
"h264", "hevc", "av1", "prores", "aac", "opus",
|
||||
"alac", "flac", "pcm_s16le", "pcm_s24le", "pcm_f32le",
|
||||
"h264", "hevc", "av1", "prores", "aac", "opus", "alac", "flac", "pcm_s16le", "pcm_s24le", "pcm_f32le",
|
||||
};
|
||||
|
||||
bool IsBuiltinCodec(const char *codec)
|
||||
|
|
|
@ -114,10 +114,7 @@ struct FFmpegCodec {
|
|||
{
|
||||
}
|
||||
|
||||
FFmpegCodec(const AVCodec *codec)
|
||||
: name(codec->name),
|
||||
long_name(codec->long_name),
|
||||
id(codec->id)
|
||||
FFmpegCodec(const AVCodec *codec) : name(codec->name), long_name(codec->long_name), id(codec->id)
|
||||
{
|
||||
switch (codec->type) {
|
||||
case AVMEDIA_TYPE_AUDIO:
|
||||
|
@ -142,10 +139,8 @@ struct FFmpegCodec {
|
|||
Q_DECLARE_METATYPE(FFmpegCodec)
|
||||
|
||||
std::vector<FFmpegFormat> GetSupportedFormats();
|
||||
std::vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format,
|
||||
bool ignore_compatibility);
|
||||
std::vector<FFmpegCodec> GetFormatCodecs(const FFmpegFormat &format, bool ignore_compatibility);
|
||||
|
||||
bool FFCodecAndFormatCompatible(const char *codec, const char *format);
|
||||
bool IsBuiltinCodec(const char *codec);
|
||||
bool ContainerSupportsCodec(const std::string &container,
|
||||
const std::string &codec);
|
||||
bool ContainerSupportsCodec(const std::string &container, const std::string &codec);
|
||||
|
|
|
@ -15,8 +15,7 @@ void FocusList::dragMoveEvent(QDragMoveEvent *event)
|
|||
QPoint pos = event->position().toPoint();
|
||||
int itemRow = row(itemAt(pos));
|
||||
|
||||
if ((itemRow == currentRow() + 1) ||
|
||||
(currentRow() == count() - 1 && itemRow == -1))
|
||||
if ((itemRow == currentRow() + 1) || (currentRow() == count() - 1 && itemRow == -1))
|
||||
event->ignore();
|
||||
else
|
||||
QListWidget::dragMoveEvent(event);
|
||||
|
|
|
@ -46,46 +46,36 @@ void AJAOutputUI::SetupPropertiesView()
|
|||
obs_data_apply(settings, data);
|
||||
} else {
|
||||
// apply default settings
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropOutput.id,
|
||||
static_cast<long long>(IOSelection::Invalid));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropVideoFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAVideoFormat));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropPixelFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAPixelFormat));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropSDITransport.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropSDITransport4K.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport4K));
|
||||
obs_data_set_default_int(settings, kUIPropOutput.id, static_cast<long long>(IOSelection::Invalid));
|
||||
obs_data_set_default_int(settings, kUIPropVideoFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAVideoFormat));
|
||||
obs_data_set_default_int(settings, kUIPropPixelFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAPixelFormat));
|
||||
obs_data_set_default_int(settings, kUIPropSDITransport.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport));
|
||||
obs_data_set_default_int(settings, kUIPropSDITransport4K.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport4K));
|
||||
}
|
||||
|
||||
// Assign an ID to the program output plugin instance for channel usage tracking
|
||||
obs_data_set_string(settings, kUIPropAJAOutputID.id, kProgramOutputID);
|
||||
|
||||
propertiesView = new OBSPropertiesView(
|
||||
settings, "aja_output",
|
||||
(PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
propertiesView =
|
||||
new OBSPropertiesView(settings, "aja_output", (PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
obs_data_release(settings);
|
||||
|
||||
connect(propertiesView, &OBSPropertiesView::Changed, this,
|
||||
&AJAOutputUI::PropertiesChanged);
|
||||
connect(propertiesView, &OBSPropertiesView::Changed, this, &AJAOutputUI::PropertiesChanged);
|
||||
}
|
||||
|
||||
void AJAOutputUI::SaveSettings(const char *filename, obs_data_t *settings)
|
||||
{
|
||||
BPtr<char> modulePath =
|
||||
obs_module_get_config_path(obs_current_module(), "");
|
||||
BPtr<char> modulePath = obs_module_get_config_path(obs_current_module(), "");
|
||||
|
||||
os_mkdirs(modulePath);
|
||||
|
||||
BPtr<char> path =
|
||||
obs_module_get_config_path(obs_current_module(), filename);
|
||||
BPtr<char> path = obs_module_get_config_path(obs_current_module(), filename);
|
||||
|
||||
if (settings)
|
||||
obs_data_save_json_safe(settings, path, "tmp", "bak");
|
||||
|
@ -103,35 +93,27 @@ void AJAOutputUI::SetupPreviewPropertiesView()
|
|||
obs_data_apply(settings, data);
|
||||
} else {
|
||||
// apply default settings
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropOutput.id,
|
||||
static_cast<long long>(IOSelection::Invalid));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropVideoFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAVideoFormat));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropPixelFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAPixelFormat));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropSDITransport.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport));
|
||||
obs_data_set_default_int(
|
||||
settings, kUIPropSDITransport4K.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport4K));
|
||||
obs_data_set_default_int(settings, kUIPropOutput.id, static_cast<long long>(IOSelection::Invalid));
|
||||
obs_data_set_default_int(settings, kUIPropVideoFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAVideoFormat));
|
||||
obs_data_set_default_int(settings, kUIPropPixelFormatSelect.id,
|
||||
static_cast<long long>(kDefaultAJAPixelFormat));
|
||||
obs_data_set_default_int(settings, kUIPropSDITransport.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport));
|
||||
obs_data_set_default_int(settings, kUIPropSDITransport4K.id,
|
||||
static_cast<long long>(kDefaultAJASDITransport4K));
|
||||
}
|
||||
|
||||
// Assign an ID to the program output plugin instance for channel usage tracking
|
||||
obs_data_set_string(settings, kUIPropAJAOutputID.id, kPreviewOutputID);
|
||||
|
||||
previewPropertiesView = new OBSPropertiesView(
|
||||
settings, "aja_output",
|
||||
(PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
previewPropertiesView =
|
||||
new OBSPropertiesView(settings, "aja_output", (PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
|
||||
ui->previewPropertiesLayout->addWidget(previewPropertiesView);
|
||||
obs_data_release(settings);
|
||||
|
||||
connect(previewPropertiesView, &OBSPropertiesView::Changed, this,
|
||||
&AJAOutputUI::PreviewPropertiesChanged);
|
||||
connect(previewPropertiesView, &OBSPropertiesView::Changed, this, &AJAOutputUI::PreviewPropertiesChanged);
|
||||
}
|
||||
|
||||
void AJAOutputUI::on_outputButton_clicked()
|
||||
|
@ -160,15 +142,13 @@ void AJAOutputUI::OutputStateChanged(bool active)
|
|||
|
||||
void AJAOutputUI::on_previewOutputButton_clicked()
|
||||
{
|
||||
SaveSettings(kPreviewPropsFilename,
|
||||
previewPropertiesView->GetSettings());
|
||||
SaveSettings(kPreviewPropsFilename, previewPropertiesView->GetSettings());
|
||||
preview_output_toggle();
|
||||
}
|
||||
|
||||
void AJAOutputUI::PreviewPropertiesChanged()
|
||||
{
|
||||
SaveSettings(kPreviewPropsFilename,
|
||||
previewPropertiesView->GetSettings());
|
||||
SaveSettings(kPreviewPropsFilename, previewPropertiesView->GetSettings());
|
||||
}
|
||||
|
||||
void AJAOutputUI::PreviewOutputStateChanged(bool active)
|
||||
|
@ -205,15 +185,13 @@ static obs_properties_t *create_misc_props_ui(void *vp)
|
|||
}
|
||||
|
||||
obs_properties_t *props = obs_properties_create();
|
||||
obs_property_t *deviceList = obs_properties_add_list(
|
||||
props, kUIPropDevice.id, obs_module_text(kUIPropDevice.text),
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_t *multiViewEnable = obs_properties_add_bool(
|
||||
props, kUIPropMultiViewEnable.id,
|
||||
obs_module_text(kUIPropMultiViewEnable.text));
|
||||
obs_property_t *deviceList = obs_properties_add_list(props, kUIPropDevice.id,
|
||||
obs_module_text(kUIPropDevice.text), OBS_COMBO_TYPE_LIST,
|
||||
OBS_COMBO_FORMAT_STRING);
|
||||
obs_property_t *multiViewEnable =
|
||||
obs_properties_add_bool(props, kUIPropMultiViewEnable.id, obs_module_text(kUIPropMultiViewEnable.text));
|
||||
obs_property_t *multiViewAudioSources = obs_properties_add_list(
|
||||
props, kUIPropMultiViewAudioSource.id,
|
||||
obs_module_text(kUIPropMultiViewAudioSource.text),
|
||||
props, kUIPropMultiViewAudioSource.id, obs_module_text(kUIPropMultiViewAudioSource.text),
|
||||
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
|
||||
|
||||
obs_property_list_clear(deviceList);
|
||||
|
@ -222,12 +200,9 @@ static obs_properties_t *create_misc_props_ui(void *vp)
|
|||
NTV2DeviceID firstDeviceID = DEVICE_ID_NOTFOUND;
|
||||
populate_misc_device_list(deviceList, cardManager, firstDeviceID);
|
||||
populate_multi_view_audio_sources(multiViewAudioSources, firstDeviceID);
|
||||
obs_property_set_modified_callback2(deviceList, on_misc_device_selected,
|
||||
cardManager);
|
||||
obs_property_set_modified_callback2(multiViewEnable,
|
||||
on_multi_view_toggle, cardManager);
|
||||
obs_property_set_modified_callback2(multiViewAudioSources,
|
||||
on_multi_view_toggle, cardManager);
|
||||
obs_property_set_modified_callback2(deviceList, on_misc_device_selected, cardManager);
|
||||
obs_property_set_modified_callback2(multiViewEnable, on_multi_view_toggle, cardManager);
|
||||
obs_property_set_modified_callback2(multiViewAudioSources, on_multi_view_toggle, cardManager);
|
||||
|
||||
outputUI->ui->label_3->setVisible(haveMultiView);
|
||||
obs_property_set_visible(deviceList, haveMultiView);
|
||||
|
@ -263,12 +238,10 @@ void AJAOutputUI::SetupMiscPropertiesView()
|
|||
obs_data_apply(settings, data);
|
||||
}
|
||||
|
||||
miscPropertiesView = new OBSPropertiesView(
|
||||
settings, this, (PropertiesReloadCallback)create_misc_props_ui,
|
||||
nullptr, nullptr, 170);
|
||||
miscPropertiesView = new OBSPropertiesView(settings, this, (PropertiesReloadCallback)create_misc_props_ui,
|
||||
nullptr, nullptr, 170);
|
||||
|
||||
ui->miscPropertiesLayout->addWidget(miscPropertiesView);
|
||||
obs_data_release(settings);
|
||||
connect(miscPropertiesView, &OBSPropertiesView::Changed, this,
|
||||
&AJAOutputUI::MiscPropertiesChanged);
|
||||
connect(miscPropertiesView, &OBSPropertiesView::Changed, this, &AJAOutputUI::MiscPropertiesChanged);
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ static struct preview_output context = {0};
|
|||
|
||||
OBSData load_settings(const char *filename)
|
||||
{
|
||||
BPtr<char> path =
|
||||
obs_module_get_config_path(obs_current_module(), filename);
|
||||
BPtr<char> path = obs_module_get_config_path(obs_current_module(), filename);
|
||||
BPtr<char> jsonData = os_quick_read_utf8_file(path);
|
||||
if (!!jsonData) {
|
||||
obs_data_t *data = obs_data_create_from_json(jsonData);
|
||||
|
@ -70,8 +69,7 @@ void output_start()
|
|||
OBSData settings = load_settings(kProgramPropsFilename);
|
||||
|
||||
if (settings != nullptr) {
|
||||
output = obs_output_create("aja_output", kProgramOutputID,
|
||||
settings, NULL);
|
||||
output = obs_output_create("aja_output", kProgramOutputID, settings, NULL);
|
||||
|
||||
bool started = obs_output_start(output);
|
||||
obs_data_release(settings);
|
||||
|
@ -122,8 +120,7 @@ void preview_output_start()
|
|||
OBSData settings = load_settings(kPreviewPropsFilename);
|
||||
|
||||
if (settings != nullptr) {
|
||||
context.output = obs_output_create(
|
||||
"aja_output", kPreviewOutputID, settings, NULL);
|
||||
context.output = obs_output_create("aja_output", kPreviewOutputID, settings, NULL);
|
||||
|
||||
obs_get_video_info(&context.ovi);
|
||||
|
||||
|
@ -132,12 +129,10 @@ void preview_output_start()
|
|||
|
||||
obs_enter_graphics();
|
||||
context.texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
context.stagesurface =
|
||||
gs_stagesurface_create(width, height, GS_BGRA);
|
||||
context.stagesurface = gs_stagesurface_create(width, height, GS_BGRA);
|
||||
obs_leave_graphics();
|
||||
|
||||
const video_output_info *mainVOI =
|
||||
video_output_get_info(obs_get_video());
|
||||
const video_output_info *mainVOI = video_output_get_info(obs_get_video());
|
||||
|
||||
video_output_info vi = {0};
|
||||
vi.format = VIDEO_FORMAT_BGRA;
|
||||
|
@ -152,19 +147,15 @@ void preview_output_start()
|
|||
|
||||
video_output_open(&context.video_queue, &vi);
|
||||
|
||||
obs_frontend_add_event_callback(on_preview_scene_changed,
|
||||
&context);
|
||||
obs_frontend_add_event_callback(on_preview_scene_changed, &context);
|
||||
if (obs_frontend_preview_program_mode_active()) {
|
||||
context.current_source =
|
||||
obs_frontend_get_current_preview_scene();
|
||||
context.current_source = obs_frontend_get_current_preview_scene();
|
||||
} else {
|
||||
context.current_source =
|
||||
obs_frontend_get_current_scene();
|
||||
context.current_source = obs_frontend_get_current_scene();
|
||||
}
|
||||
obs_add_main_render_callback(render_preview_source, &context);
|
||||
|
||||
obs_output_set_media(context.output, context.video_queue,
|
||||
obs_get_audio());
|
||||
obs_output_set_media(context.output, context.video_queue, obs_get_audio());
|
||||
bool started = obs_output_start(context.output);
|
||||
|
||||
obs_data_release(settings);
|
||||
|
@ -185,18 +176,15 @@ void preview_output_toggle()
|
|||
preview_output_start();
|
||||
}
|
||||
|
||||
void populate_misc_device_list(obs_property_t *list,
|
||||
aja::CardManager *cardManager,
|
||||
NTV2DeviceID &firstDeviceID)
|
||||
void populate_misc_device_list(obs_property_t *list, aja::CardManager *cardManager, NTV2DeviceID &firstDeviceID)
|
||||
{
|
||||
for (const auto &iter : *cardManager) {
|
||||
if (!iter.second)
|
||||
continue;
|
||||
if (firstDeviceID == DEVICE_ID_NOTFOUND)
|
||||
firstDeviceID = iter.second->GetDeviceID();
|
||||
obs_property_list_add_string(
|
||||
list, iter.second->GetDisplayName().c_str(),
|
||||
iter.second->GetCardID().c_str());
|
||||
obs_property_list_add_string(list, iter.second->GetDisplayName().c_str(),
|
||||
iter.second->GetCardID().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,16 +199,13 @@ void populate_multi_view_audio_sources(obs_property_t *list, NTV2DeviceID id)
|
|||
};
|
||||
for (const auto &inp : kMultiViewAudioInputs) {
|
||||
if (NTV2DeviceCanDoInputSource(id, inp)) {
|
||||
std::string inputSourceStr =
|
||||
NTV2InputSourceToString(inp, true);
|
||||
obs_property_list_add_int(list, inputSourceStr.c_str(),
|
||||
(long long)inp);
|
||||
std::string inputSourceStr = NTV2InputSourceToString(inp, true);
|
||||
obs_property_list_add_int(list, inputSourceStr.c_str(), (long long)inp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool on_misc_device_selected(void *data, obs_properties_t *props,
|
||||
obs_property_t *, obs_data_t *settings)
|
||||
bool on_misc_device_selected(void *data, obs_properties_t *props, obs_property_t *, obs_data_t *settings)
|
||||
{
|
||||
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
|
||||
if (!cardID || !cardID[0])
|
||||
|
@ -234,10 +219,8 @@ bool on_misc_device_selected(void *data, obs_properties_t *props,
|
|||
|
||||
NTV2DeviceID deviceID = cardEntry->GetDeviceID();
|
||||
bool enableMultiViewUI = NTV2DeviceCanDoHDMIMultiView(deviceID);
|
||||
obs_property_t *multiViewCheckbox =
|
||||
obs_properties_get(props, kUIPropMultiViewEnable.id);
|
||||
obs_property_t *multiViewAudioSource =
|
||||
obs_properties_get(props, kUIPropMultiViewAudioSource.id);
|
||||
obs_property_t *multiViewCheckbox = obs_properties_get(props, kUIPropMultiViewEnable.id);
|
||||
obs_property_t *multiViewAudioSource = obs_properties_get(props, kUIPropMultiViewAudioSource.id);
|
||||
populate_multi_view_audio_sources(multiViewAudioSource, deviceID);
|
||||
obs_property_set_enabled(multiViewCheckbox, enableMultiViewUI);
|
||||
obs_property_set_enabled(multiViewAudioSource, enableMultiViewUI);
|
||||
|
@ -249,8 +232,7 @@ static void toggle_multi_view(CNTV2Card *card, NTV2InputSource src, bool enable)
|
|||
std::ostringstream oss;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
std::string datastream = std::to_string(i);
|
||||
oss << "sdi[" << datastream << "][0]->hdmi[0][" << datastream
|
||||
<< "];";
|
||||
oss << "sdi[" << datastream << "][0]->hdmi[0][" << datastream << "];";
|
||||
}
|
||||
|
||||
NTV2DeviceID deviceId = card->GetDeviceID();
|
||||
|
@ -262,29 +244,19 @@ static void toggle_multi_view(CNTV2Card *card, NTV2InputSource src, bool enable)
|
|||
if (enable) {
|
||||
card->ApplySignalRoute(cnx, false);
|
||||
if (NTV2DeviceCanDoAudioMixer(deviceId)) {
|
||||
card->SetAudioMixerInputAudioSystem(
|
||||
NTV2_AudioMixerInputMain,
|
||||
audioSys);
|
||||
card->SetAudioMixerInputChannelSelect(
|
||||
NTV2_AudioMixerInputMain,
|
||||
NTV2_AudioChannel1_2);
|
||||
card->SetAudioMixerInputChannelsMute(
|
||||
NTV2_AudioMixerInputAux1,
|
||||
NTV2AudioChannelsMuteAll);
|
||||
card->SetAudioMixerInputChannelsMute(
|
||||
NTV2_AudioMixerInputAux2,
|
||||
NTV2AudioChannelsMuteAll);
|
||||
card->SetAudioMixerInputAudioSystem(NTV2_AudioMixerInputMain, audioSys);
|
||||
card->SetAudioMixerInputChannelSelect(NTV2_AudioMixerInputMain,
|
||||
NTV2_AudioChannel1_2);
|
||||
card->SetAudioMixerInputChannelsMute(NTV2_AudioMixerInputAux1,
|
||||
NTV2AudioChannelsMuteAll);
|
||||
card->SetAudioMixerInputChannelsMute(NTV2_AudioMixerInputAux2,
|
||||
NTV2AudioChannelsMuteAll);
|
||||
}
|
||||
card->SetAudioLoopBack(NTV2_AUDIO_LOOPBACK_ON,
|
||||
audioSys);
|
||||
card->SetAudioOutputMonitorSource(
|
||||
NTV2_AudioChannel1_2, audioSys);
|
||||
card->SetHDMIOutAudioChannels(
|
||||
NTV2_HDMIAudio8Channels);
|
||||
card->SetHDMIOutAudioSource2Channel(
|
||||
NTV2_AudioChannel1_2, audioSys);
|
||||
card->SetHDMIOutAudioSource8Channel(
|
||||
NTV2_AudioChannel1_8, audioSys);
|
||||
card->SetAudioLoopBack(NTV2_AUDIO_LOOPBACK_ON, audioSys);
|
||||
card->SetAudioOutputMonitorSource(NTV2_AudioChannel1_2, audioSys);
|
||||
card->SetHDMIOutAudioChannels(NTV2_HDMIAudio8Channels);
|
||||
card->SetHDMIOutAudioSource2Channel(NTV2_AudioChannel1_2, audioSys);
|
||||
card->SetHDMIOutAudioSource8Channel(NTV2_AudioChannel1_8, audioSys);
|
||||
} else {
|
||||
card->RemoveConnections(cnx);
|
||||
}
|
||||
|
@ -292,14 +264,11 @@ static void toggle_multi_view(CNTV2Card *card, NTV2InputSource src, bool enable)
|
|||
}
|
||||
}
|
||||
|
||||
bool on_multi_view_toggle(void *data, obs_properties_t *, obs_property_t *,
|
||||
obs_data_t *settings)
|
||||
bool on_multi_view_toggle(void *data, obs_properties_t *, obs_property_t *, obs_data_t *settings)
|
||||
{
|
||||
bool multiViewEnabled =
|
||||
obs_data_get_bool(settings, kUIPropMultiViewEnable.id) &&
|
||||
!main_output_running && !preview_output_running;
|
||||
const int audioInputSource =
|
||||
obs_data_get_int(settings, kUIPropMultiViewAudioSource.id);
|
||||
bool multiViewEnabled = obs_data_get_bool(settings, kUIPropMultiViewEnable.id) && !main_output_running &&
|
||||
!preview_output_running;
|
||||
const int audioInputSource = obs_data_get_int(settings, kUIPropMultiViewAudioSource.id);
|
||||
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
|
||||
if (!cardID || !cardID[0])
|
||||
return false;
|
||||
|
@ -359,8 +328,7 @@ void render_preview_source(void *param, uint32_t, uint32_t)
|
|||
vec4_zero(&background);
|
||||
|
||||
gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0);
|
||||
gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f,
|
||||
100.0f);
|
||||
gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);
|
||||
|
@ -371,24 +339,15 @@ void render_preview_source(void *param, uint32_t, uint32_t)
|
|||
gs_texrender_end(ctx->texrender);
|
||||
|
||||
struct video_frame output_frame;
|
||||
if (video_output_lock_frame(ctx->video_queue, &output_frame, 1,
|
||||
os_gettime_ns())) {
|
||||
gs_stage_texture(
|
||||
ctx->stagesurface,
|
||||
gs_texrender_get_texture(ctx->texrender));
|
||||
if (video_output_lock_frame(ctx->video_queue, &output_frame, 1, os_gettime_ns())) {
|
||||
gs_stage_texture(ctx->stagesurface, gs_texrender_get_texture(ctx->texrender));
|
||||
|
||||
if (gs_stagesurface_map(ctx->stagesurface,
|
||||
&ctx->video_data,
|
||||
&ctx->video_linesize)) {
|
||||
if (gs_stagesurface_map(ctx->stagesurface, &ctx->video_data, &ctx->video_linesize)) {
|
||||
uint32_t linesize = output_frame.linesize[0];
|
||||
for (uint32_t i = 0; i < ctx->ovi.base_height;
|
||||
i++) {
|
||||
for (uint32_t i = 0; i < ctx->ovi.base_height; i++) {
|
||||
uint32_t dst_offset = linesize * i;
|
||||
uint32_t src_offset =
|
||||
ctx->video_linesize * i;
|
||||
memcpy(output_frame.data[0] +
|
||||
dst_offset,
|
||||
ctx->video_data + src_offset,
|
||||
uint32_t src_offset = ctx->video_linesize * i;
|
||||
memcpy(output_frame.data[0] + dst_offset, ctx->video_data + src_offset,
|
||||
linesize);
|
||||
}
|
||||
|
||||
|
@ -403,8 +362,7 @@ void render_preview_source(void *param, uint32_t, uint32_t)
|
|||
|
||||
void addOutputUI(void)
|
||||
{
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
"AJA I/O Device Output");
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction("AJA I/O Device Output");
|
||||
|
||||
QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window();
|
||||
|
||||
|
@ -423,20 +381,16 @@ static void OBSEvent(enum obs_frontend_event event, void *)
|
|||
{
|
||||
if (event == OBS_FRONTEND_EVENT_FINISHED_LOADING) {
|
||||
OBSData settings = load_settings(kProgramPropsFilename);
|
||||
if (settings &&
|
||||
obs_data_get_bool(settings, kUIPropAutoStartOutput.id))
|
||||
if (settings && obs_data_get_bool(settings, kUIPropAutoStartOutput.id))
|
||||
output_start();
|
||||
|
||||
OBSData previewSettings = load_settings(kPreviewPropsFilename);
|
||||
if (previewSettings &&
|
||||
obs_data_get_bool(previewSettings,
|
||||
kUIPropAutoStartOutput.id))
|
||||
if (previewSettings && obs_data_get_bool(previewSettings, kUIPropAutoStartOutput.id))
|
||||
preview_output_start();
|
||||
|
||||
OBSData miscSettings = load_settings(kMiscPropsFilename);
|
||||
if (miscSettings && ajaOutputUI) {
|
||||
on_multi_view_toggle(ajaOutputUI->GetCardManager(),
|
||||
nullptr, nullptr, miscSettings);
|
||||
on_multi_view_toggle(ajaOutputUI->GetCardManager(), nullptr, nullptr, miscSettings);
|
||||
}
|
||||
} else if (event == OBS_FRONTEND_EVENT_EXIT) {
|
||||
if (main_output_running)
|
||||
|
@ -459,16 +413,14 @@ bool obs_module_load(void)
|
|||
CNTV2DeviceScanner scanner;
|
||||
auto numDevices = scanner.GetNumDevices();
|
||||
if (numDevices == 0) {
|
||||
blog(LOG_WARNING,
|
||||
"No AJA devices found, skipping loading AJA UI plugin");
|
||||
blog(LOG_WARNING, "No AJA devices found, skipping loading AJA UI plugin");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Signal to wait for AJA plugin to finish loading so we can access the CardManager instance
|
||||
auto signal_handler = obs_get_signal_handler();
|
||||
signal_handler_add(signal_handler, "void aja_loaded(ptr card_manager)");
|
||||
signal_handler_connect(signal_handler, "aja_loaded", aja_loaded,
|
||||
nullptr);
|
||||
signal_handler_connect(signal_handler, "aja_loaded", aja_loaded, nullptr);
|
||||
|
||||
addOutputUI();
|
||||
|
||||
|
|
|
@ -14,11 +14,7 @@ static const char *kMiscPropsFilename = "ajaMiscProps.json";
|
|||
OBSData load_settings(const char *filename);
|
||||
void output_toggle();
|
||||
void preview_output_toggle();
|
||||
void populate_misc_device_list(obs_property_t *list,
|
||||
aja::CardManager *cardManager,
|
||||
NTV2DeviceID &firstDeviceID);
|
||||
void populate_misc_device_list(obs_property_t *list, aja::CardManager *cardManager, NTV2DeviceID &firstDeviceID);
|
||||
void populate_multi_view_audio_sources(obs_property_t *list, NTV2DeviceID id);
|
||||
bool on_misc_device_selected(void *data, obs_properties_t *props,
|
||||
obs_property_t *list, obs_data_t *settings);
|
||||
bool on_multi_view_toggle(void *data, obs_properties_t *props,
|
||||
obs_property_t *list, obs_data_t *settings);
|
||||
bool on_misc_device_selected(void *data, obs_properties_t *props, obs_property_t *list, obs_data_t *settings);
|
||||
bool on_multi_view_toggle(void *data, obs_properties_t *props, obs_property_t *list, obs_data_t *settings);
|
||||
|
|
|
@ -22,9 +22,7 @@ obs_captions::obs_captions() {}
|
|||
|
||||
static obs_captions *captions = nullptr;
|
||||
|
||||
DecklinkCaptionsUI::DecklinkCaptionsUI(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_CaptionsDialog)
|
||||
DecklinkCaptionsUI::DecklinkCaptionsUI(QWidget *parent) : QDialog(parent), ui(new Ui_CaptionsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -50,11 +48,7 @@ DecklinkCaptionsUI::DecklinkCaptionsUI(QWidget *parent)
|
|||
ui->source->blockSignals(true);
|
||||
ui->source->addItem(QStringLiteral(""));
|
||||
ui->source->setCurrentIndex(0);
|
||||
obs_enum_sources(
|
||||
[](void *data, obs_source_t *source) {
|
||||
return (*static_cast<cb_t *>(data))(source);
|
||||
},
|
||||
&cb);
|
||||
obs_enum_sources([](void *data, obs_source_t *source) { return (*static_cast<cb_t *>(data))(source); }, &cb);
|
||||
ui->source->blockSignals(false);
|
||||
}
|
||||
|
||||
|
@ -68,13 +62,11 @@ void DecklinkCaptionsUI::on_source_currentIndexChanged(int)
|
|||
captions->start();
|
||||
}
|
||||
|
||||
static void caption_callback(void * /* param */, obs_source_t * /* source */,
|
||||
const struct obs_source_cea_708 *captions)
|
||||
static void caption_callback(void * /* param */, obs_source_t * /* source */, const struct obs_source_cea_708 *captions)
|
||||
{
|
||||
obs_output *output = obs_frontend_get_streaming_output();
|
||||
if (output) {
|
||||
if (obs_frontend_streaming_active() &&
|
||||
obs_output_active(output)) {
|
||||
if (obs_frontend_streaming_active() && obs_output_active(output)) {
|
||||
obs_output_caption(output, captions);
|
||||
}
|
||||
obs_output_release(output);
|
||||
|
@ -95,32 +87,27 @@ void obs_captions::stop()
|
|||
{
|
||||
OBSSource s = OBSGetStrongRef(source);
|
||||
if (s)
|
||||
obs_source_remove_caption_callback(s, caption_callback,
|
||||
nullptr);
|
||||
obs_source_remove_caption_callback(s, caption_callback, nullptr);
|
||||
}
|
||||
|
||||
static void save_decklink_caption_data(obs_data_t *save_data, bool saving,
|
||||
void *)
|
||||
static void save_decklink_caption_data(obs_data_t *save_data, bool saving, void *)
|
||||
{
|
||||
if (saving) {
|
||||
obs_data_t *obj = obs_data_create();
|
||||
|
||||
obs_data_set_string(obj, "source",
|
||||
captions->source_name.c_str());
|
||||
obs_data_set_string(obj, "source", captions->source_name.c_str());
|
||||
|
||||
obs_data_set_obj(save_data, "decklink_captions", obj);
|
||||
obs_data_release(obj);
|
||||
} else {
|
||||
captions->stop();
|
||||
|
||||
obs_data_t *obj =
|
||||
obs_data_get_obj(save_data, "decklink_captions");
|
||||
obs_data_t *obj = obs_data_get_obj(save_data, "decklink_captions");
|
||||
if (!obj)
|
||||
obj = obs_data_create();
|
||||
|
||||
captions->source_name = obs_data_get_string(obj, "source");
|
||||
captions->source =
|
||||
GetWeakSourceByName(captions->source_name.c_str());
|
||||
captions->source = GetWeakSourceByName(captions->source_name.c_str());
|
||||
obs_data_release(obj);
|
||||
|
||||
captions->start();
|
||||
|
@ -129,8 +116,7 @@ static void save_decklink_caption_data(obs_data_t *save_data, bool saving,
|
|||
|
||||
void addOutputUI(void)
|
||||
{
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("Decklink Captions"));
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("Decklink Captions"));
|
||||
|
||||
captions = new obs_captions;
|
||||
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
#include <util/util.hpp>
|
||||
#include "decklink-ui-main.h"
|
||||
|
||||
DecklinkOutputUI::DecklinkOutputUI(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_Output)
|
||||
DecklinkOutputUI::DecklinkOutputUI(QWidget *parent) : QDialog(parent), ui(new Ui_Output)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -37,26 +35,22 @@ void DecklinkOutputUI::SetupPropertiesView()
|
|||
if (data)
|
||||
obs_data_apply(settings, data);
|
||||
|
||||
propertiesView = new OBSPropertiesView(
|
||||
settings, "decklink_output",
|
||||
(PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
propertiesView = new OBSPropertiesView(settings, "decklink_output",
|
||||
(PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
obs_data_release(settings);
|
||||
|
||||
connect(propertiesView, &OBSPropertiesView::Changed, this,
|
||||
&DecklinkOutputUI::PropertiesChanged);
|
||||
connect(propertiesView, &OBSPropertiesView::Changed, this, &DecklinkOutputUI::PropertiesChanged);
|
||||
}
|
||||
|
||||
void DecklinkOutputUI::SaveSettings()
|
||||
{
|
||||
BPtr<char> modulePath =
|
||||
obs_module_get_config_path(obs_current_module(), "");
|
||||
BPtr<char> modulePath = obs_module_get_config_path(obs_current_module(), "");
|
||||
|
||||
os_mkdirs(modulePath);
|
||||
|
||||
BPtr<char> path = obs_module_get_config_path(
|
||||
obs_current_module(), "decklinkOutputProps.json");
|
||||
BPtr<char> path = obs_module_get_config_path(obs_current_module(), "decklinkOutputProps.json");
|
||||
|
||||
obs_data_t *settings = propertiesView->GetSettings();
|
||||
if (settings)
|
||||
|
@ -74,26 +68,22 @@ void DecklinkOutputUI::SetupPreviewPropertiesView()
|
|||
if (data)
|
||||
obs_data_apply(settings, data);
|
||||
|
||||
previewPropertiesView = new OBSPropertiesView(
|
||||
settings, "decklink_output",
|
||||
(PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
previewPropertiesView = new OBSPropertiesView(settings, "decklink_output",
|
||||
(PropertiesReloadCallback)obs_get_output_properties, 170);
|
||||
|
||||
ui->previewPropertiesLayout->addWidget(previewPropertiesView);
|
||||
obs_data_release(settings);
|
||||
|
||||
connect(previewPropertiesView, &OBSPropertiesView::Changed, this,
|
||||
&DecklinkOutputUI::PreviewPropertiesChanged);
|
||||
connect(previewPropertiesView, &OBSPropertiesView::Changed, this, &DecklinkOutputUI::PreviewPropertiesChanged);
|
||||
}
|
||||
|
||||
void DecklinkOutputUI::SavePreviewSettings()
|
||||
{
|
||||
BPtr<char> modulePath =
|
||||
obs_module_get_config_path(obs_current_module(), "");
|
||||
BPtr<char> modulePath = obs_module_get_config_path(obs_current_module(), "");
|
||||
|
||||
os_mkdirs(modulePath);
|
||||
|
||||
BPtr<char> path = obs_module_get_config_path(
|
||||
obs_current_module(), "decklinkPreviewOutputProps.json");
|
||||
BPtr<char> path = obs_module_get_config_path(obs_current_module(), "decklinkPreviewOutputProps.json");
|
||||
|
||||
obs_data_t *settings = previewPropertiesView->GetSettings();
|
||||
if (settings)
|
||||
|
|
|
@ -43,8 +43,7 @@ static struct decklink_ui_output context_preview = {0};
|
|||
|
||||
OBSData load_settings()
|
||||
{
|
||||
BPtr<char> path = obs_module_get_config_path(
|
||||
obs_current_module(), "decklinkOutputProps.json");
|
||||
BPtr<char> path = obs_module_get_config_path(obs_current_module(), "decklinkOutputProps.json");
|
||||
BPtr<char> jsonData = os_quick_read_utf8_file(path);
|
||||
if (!!jsonData) {
|
||||
obs_data_t *data = obs_data_create_from_json(jsonData);
|
||||
|
@ -90,10 +89,8 @@ void output_start()
|
|||
OBSData settings = load_settings();
|
||||
|
||||
if (settings != nullptr) {
|
||||
obs_output_t *const output = obs_output_create(
|
||||
"decklink_output", "decklink_output", settings, NULL);
|
||||
const struct video_scale_info *const conversion =
|
||||
obs_output_get_video_conversion(output);
|
||||
obs_output_t *const output = obs_output_create("decklink_output", "decklink_output", settings, NULL);
|
||||
const struct video_scale_info *const conversion = obs_output_get_video_conversion(output);
|
||||
if (conversion != nullptr) {
|
||||
context.output = output;
|
||||
obs_add_tick_callback(decklink_ui_tick, &context);
|
||||
|
@ -105,11 +102,9 @@ void output_start()
|
|||
|
||||
obs_enter_graphics();
|
||||
context.texrender_premultiplied = nullptr;
|
||||
context.texrender =
|
||||
gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
context.texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
for (gs_stagesurf_t *&surf : context.stagesurfaces)
|
||||
surf = gs_stagesurface_create(width, height,
|
||||
GS_BGRA);
|
||||
surf = gs_stagesurface_create(width, height, GS_BGRA);
|
||||
obs_leave_graphics();
|
||||
|
||||
for (bool &written : context.surf_written)
|
||||
|
@ -131,12 +126,9 @@ void output_start()
|
|||
video_output_open(&context.video_queue, &vi);
|
||||
|
||||
context.current_source = nullptr;
|
||||
obs_add_main_rendered_callback(decklink_ui_render,
|
||||
&context);
|
||||
obs_add_main_rendered_callback(decklink_ui_render, &context);
|
||||
|
||||
obs_output_set_media(context.output,
|
||||
context.video_queue,
|
||||
obs_get_audio());
|
||||
obs_output_set_media(context.output, context.video_queue, obs_get_audio());
|
||||
bool started = obs_output_start(context.output);
|
||||
|
||||
main_output_running = started;
|
||||
|
@ -162,8 +154,7 @@ void output_toggle()
|
|||
|
||||
OBSData load_preview_settings()
|
||||
{
|
||||
BPtr<char> path = obs_module_get_config_path(
|
||||
obs_current_module(), "decklinkPreviewOutputProps.json");
|
||||
BPtr<char> path = obs_module_get_config_path(obs_current_module(), "decklinkPreviewOutputProps.json");
|
||||
BPtr<char> jsonData = os_quick_read_utf8_file(path);
|
||||
if (!!jsonData) {
|
||||
obs_data_t *data = obs_data_create_from_json(jsonData);
|
||||
|
@ -191,8 +182,7 @@ static void decklink_ui_tick(void *param, float /* sec */)
|
|||
void preview_output_stop()
|
||||
{
|
||||
obs_remove_main_rendered_callback(decklink_ui_render, &context_preview);
|
||||
obs_frontend_remove_event_callback(on_preview_scene_changed,
|
||||
&context_preview);
|
||||
obs_frontend_remove_event_callback(on_preview_scene_changed, &context_preview);
|
||||
|
||||
obs_output_stop(context_preview.output);
|
||||
obs_output_release(context_preview.output);
|
||||
|
@ -224,14 +214,11 @@ void preview_output_start()
|
|||
OBSData settings = load_preview_settings();
|
||||
|
||||
if (settings != nullptr) {
|
||||
obs_output_t *const output = obs_output_create(
|
||||
"decklink_output", "decklink_output", settings, NULL);
|
||||
const struct video_scale_info *const conversion =
|
||||
obs_output_get_video_conversion(output);
|
||||
obs_output_t *const output = obs_output_create("decklink_output", "decklink_output", settings, NULL);
|
||||
const struct video_scale_info *const conversion = obs_output_get_video_conversion(output);
|
||||
if (conversion != nullptr) {
|
||||
context_preview.output = output;
|
||||
obs_add_tick_callback(decklink_ui_tick,
|
||||
&context_preview);
|
||||
obs_add_tick_callback(decklink_ui_tick, &context_preview);
|
||||
|
||||
obs_get_video_info(&context_preview.ovi);
|
||||
|
||||
|
@ -239,14 +226,10 @@ void preview_output_start()
|
|||
const uint32_t height = conversion->height;
|
||||
|
||||
obs_enter_graphics();
|
||||
context_preview.texrender_premultiplied =
|
||||
gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
context_preview.texrender =
|
||||
gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
for (gs_stagesurf_t *&surf :
|
||||
context_preview.stagesurfaces)
|
||||
surf = gs_stagesurface_create(width, height,
|
||||
GS_BGRA);
|
||||
context_preview.texrender_premultiplied = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
context_preview.texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
for (gs_stagesurf_t *&surf : context_preview.stagesurfaces)
|
||||
surf = gs_stagesurface_create(width, height, GS_BGRA);
|
||||
obs_leave_graphics();
|
||||
|
||||
for (bool &written : context_preview.surf_written)
|
||||
|
@ -267,21 +250,15 @@ void preview_output_start()
|
|||
|
||||
video_output_open(&context_preview.video_queue, &vi);
|
||||
|
||||
obs_frontend_add_event_callback(
|
||||
on_preview_scene_changed, &context_preview);
|
||||
obs_frontend_add_event_callback(on_preview_scene_changed, &context_preview);
|
||||
if (obs_frontend_preview_program_mode_active()) {
|
||||
context_preview.current_source =
|
||||
obs_frontend_get_current_preview_scene();
|
||||
context_preview.current_source = obs_frontend_get_current_preview_scene();
|
||||
} else {
|
||||
context_preview.current_source =
|
||||
obs_frontend_get_current_scene();
|
||||
context_preview.current_source = obs_frontend_get_current_scene();
|
||||
}
|
||||
obs_add_main_rendered_callback(decklink_ui_render,
|
||||
&context_preview);
|
||||
obs_add_main_rendered_callback(decklink_ui_render, &context_preview);
|
||||
|
||||
obs_output_set_media(context_preview.output,
|
||||
context_preview.video_queue,
|
||||
obs_get_audio());
|
||||
obs_output_set_media(context_preview.output, context_preview.video_queue, obs_get_audio());
|
||||
bool started = obs_output_start(context_preview.output);
|
||||
|
||||
preview_output_running = started;
|
||||
|
@ -356,8 +333,7 @@ static void decklink_ui_render(void *param)
|
|||
width = obs_source_get_base_width(ctx->current_source);
|
||||
height = obs_source_get_base_height(ctx->current_source);
|
||||
|
||||
gs_texrender_t *const texrender_premultiplied =
|
||||
ctx->texrender_premultiplied;
|
||||
gs_texrender_t *const texrender_premultiplied = ctx->texrender_premultiplied;
|
||||
if (!gs_texrender_begin(texrender_premultiplied, width, height))
|
||||
return;
|
||||
|
||||
|
@ -365,8 +341,7 @@ static void decklink_ui_render(void *param)
|
|||
vec4_zero(&background);
|
||||
|
||||
gs_clear(GS_CLEAR_COLOR, &background, 0.0f, 0);
|
||||
gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f,
|
||||
100.0f);
|
||||
gs_ortho(0.0f, (float)width, 0.0f, (float)height, -100.0f, 100.0f);
|
||||
|
||||
gs_blend_state_push();
|
||||
gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO);
|
||||
|
@ -381,8 +356,7 @@ static void decklink_ui_render(void *param)
|
|||
return;
|
||||
}
|
||||
|
||||
const struct video_scale_info *const conversion =
|
||||
obs_output_get_video_conversion(ctx->output);
|
||||
const struct video_scale_info *const conversion = obs_output_get_video_conversion(ctx->output);
|
||||
const uint32_t scaled_width = conversion->width;
|
||||
const uint32_t scaled_height = conversion->height;
|
||||
|
||||
|
@ -390,23 +364,17 @@ static void decklink_ui_render(void *param)
|
|||
return;
|
||||
|
||||
const bool previous = gs_framebuffer_srgb_enabled();
|
||||
const bool source_hdr = (ctx->ovi.colorspace == VIDEO_CS_2100_PQ) ||
|
||||
(ctx->ovi.colorspace == VIDEO_CS_2100_HLG);
|
||||
const bool target_hdr = source_hdr &&
|
||||
(conversion->colorspace == VIDEO_CS_2100_PQ);
|
||||
const bool source_hdr = (ctx->ovi.colorspace == VIDEO_CS_2100_PQ) || (ctx->ovi.colorspace == VIDEO_CS_2100_HLG);
|
||||
const bool target_hdr = source_hdr && (conversion->colorspace == VIDEO_CS_2100_PQ);
|
||||
gs_enable_framebuffer_srgb(!target_hdr);
|
||||
gs_enable_blending(false);
|
||||
|
||||
gs_effect_t *const effect = obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||
gs_effect_set_texture_srgb(gs_effect_get_param_by_name(effect, "image"),
|
||||
tex);
|
||||
const char *const tech_name =
|
||||
target_hdr ? "DrawAlphaDivideR10L"
|
||||
: (source_hdr ? "DrawAlphaDivideTonemap"
|
||||
: "DrawAlphaDivide");
|
||||
gs_effect_set_texture_srgb(gs_effect_get_param_by_name(effect, "image"), tex);
|
||||
const char *const tech_name = target_hdr ? "DrawAlphaDivideR10L"
|
||||
: (source_hdr ? "DrawAlphaDivideTonemap" : "DrawAlphaDivide");
|
||||
while (gs_effect_loop(effect, tech_name)) {
|
||||
gs_effect_set_float(gs_effect_get_param_by_name(effect,
|
||||
"multiplier"),
|
||||
gs_effect_set_float(gs_effect_get_param_by_name(effect, "multiplier"),
|
||||
obs_get_video_sdr_white_level() / 10000.f);
|
||||
gs_draw_sprite(tex, 0, 0, 0);
|
||||
}
|
||||
|
@ -417,28 +385,20 @@ static void decklink_ui_render(void *param)
|
|||
gs_texrender_end(ctx->texrender);
|
||||
|
||||
const size_t write_stage_index = ctx->stage_index;
|
||||
gs_stage_texture(ctx->stagesurfaces[write_stage_index],
|
||||
gs_texrender_get_texture(ctx->texrender));
|
||||
gs_stage_texture(ctx->stagesurfaces[write_stage_index], gs_texrender_get_texture(ctx->texrender));
|
||||
ctx->surf_written[write_stage_index] = true;
|
||||
|
||||
const size_t read_stage_index =
|
||||
(write_stage_index + 1) % STAGE_BUFFER_COUNT;
|
||||
const size_t read_stage_index = (write_stage_index + 1) % STAGE_BUFFER_COUNT;
|
||||
if (ctx->surf_written[read_stage_index]) {
|
||||
struct video_frame output_frame;
|
||||
if (video_output_lock_frame(ctx->video_queue, &output_frame, 1,
|
||||
os_gettime_ns())) {
|
||||
gs_stagesurf_t *const read_surf =
|
||||
ctx->stagesurfaces[read_stage_index];
|
||||
if (gs_stagesurface_map(read_surf, &ctx->video_data,
|
||||
&ctx->video_linesize)) {
|
||||
if (video_output_lock_frame(ctx->video_queue, &output_frame, 1, os_gettime_ns())) {
|
||||
gs_stagesurf_t *const read_surf = ctx->stagesurfaces[read_stage_index];
|
||||
if (gs_stagesurface_map(read_surf, &ctx->video_data, &ctx->video_linesize)) {
|
||||
uint32_t linesize = output_frame.linesize[0];
|
||||
for (uint32_t i = 0; i < scaled_height; i++) {
|
||||
uint32_t dst_offset = linesize * i;
|
||||
uint32_t src_offset =
|
||||
ctx->video_linesize * i;
|
||||
memcpy(output_frame.data[0] +
|
||||
dst_offset,
|
||||
ctx->video_data + src_offset,
|
||||
uint32_t src_offset = ctx->video_linesize * i;
|
||||
memcpy(output_frame.data[0] + dst_offset, ctx->video_data + src_offset,
|
||||
linesize);
|
||||
}
|
||||
|
||||
|
@ -455,8 +415,7 @@ static void decklink_ui_render(void *param)
|
|||
|
||||
void addOutputUI(void)
|
||||
{
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("Decklink Output"));
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("Decklink Output"));
|
||||
|
||||
QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window();
|
||||
|
||||
|
@ -481,8 +440,7 @@ static void OBSEvent(enum obs_frontend_event event, void *)
|
|||
|
||||
OBSData previewSettings = load_preview_settings();
|
||||
|
||||
if (previewSettings &&
|
||||
obs_data_get_bool(previewSettings, "auto_start"))
|
||||
if (previewSettings && obs_data_get_bool(previewSettings, "auto_start"))
|
||||
preview_output_start();
|
||||
} else if (event == OBS_FRONTEND_EVENT_EXIT) {
|
||||
shutting_down = true;
|
||||
|
|
|
@ -39,8 +39,7 @@ void CleanupSceneSwitcher()
|
|||
static bool ewmhIsSupported()
|
||||
{
|
||||
Display *display = disp();
|
||||
Atom netSupportingWmCheck =
|
||||
XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true);
|
||||
Atom netSupportingWmCheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", true);
|
||||
Atom actualType;
|
||||
int format = 0;
|
||||
unsigned long num = 0, bytes = 0;
|
||||
|
@ -53,10 +52,8 @@ static bool ewmhIsSupported()
|
|||
return false;
|
||||
}
|
||||
|
||||
int status = XGetWindowProperty(display, root_window,
|
||||
netSupportingWmCheck, 0L, 1L, false,
|
||||
XA_WINDOW, &actualType, &format, &num,
|
||||
&bytes, &data);
|
||||
int status = XGetWindowProperty(display, root_window, netSupportingWmCheck, 0L, 1L, false, XA_WINDOW,
|
||||
&actualType, &format, &num, &bytes, &data);
|
||||
|
||||
if (status == Success) {
|
||||
if (num > 0) {
|
||||
|
@ -69,12 +66,9 @@ static bool ewmhIsSupported()
|
|||
}
|
||||
|
||||
if (ewmh_window) {
|
||||
status = XGetWindowProperty(display, ewmh_window,
|
||||
netSupportingWmCheck, 0L, 1L, false,
|
||||
XA_WINDOW, &actualType, &format,
|
||||
&num, &bytes, &data);
|
||||
if (status != Success || num == 0 ||
|
||||
ewmh_window != ((Window *)data)[0]) {
|
||||
status = XGetWindowProperty(display, ewmh_window, netSupportingWmCheck, 0L, 1L, false, XA_WINDOW,
|
||||
&actualType, &format, &num, &bytes, &data);
|
||||
if (status != Success || num == 0 || ewmh_window != ((Window *)data)[0]) {
|
||||
ewmh_window = 0;
|
||||
}
|
||||
if (status == Success && data) {
|
||||
|
@ -107,10 +101,8 @@ static std::vector<Window> getTopLevelWindows()
|
|||
continue;
|
||||
}
|
||||
|
||||
int status = XGetWindowProperty(disp(), rootWin, netClList, 0L,
|
||||
~0L, false, AnyPropertyType,
|
||||
&actualType, &format, &num,
|
||||
&bytes, (uint8_t **)&data);
|
||||
int status = XGetWindowProperty(disp(), rootWin, netClList, 0L, ~0L, false, AnyPropertyType,
|
||||
&actualType, &format, &num, &bytes, (uint8_t **)&data);
|
||||
|
||||
if (status != Success) {
|
||||
continue;
|
||||
|
@ -141,8 +133,7 @@ static std::string GetWindowTitle(size_t i)
|
|||
XFree(name);
|
||||
} else {
|
||||
XTextProperty xtp_new_name;
|
||||
if (XGetWMName(disp(), w, &xtp_new_name) != 0 &&
|
||||
xtp_new_name.value != nullptr) {
|
||||
if (XGetWMName(disp(), w, &xtp_new_name) != 0 && xtp_new_name.value != nullptr) {
|
||||
std::string str((const char *)xtp_new_name.value);
|
||||
windowTitle = str;
|
||||
XFree(xtp_new_name.value);
|
||||
|
@ -180,8 +171,7 @@ void GetCurrentWindowTitle(string &title)
|
|||
return;
|
||||
}
|
||||
|
||||
XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, false,
|
||||
AnyPropertyType, &actualType, &format, &num, &bytes,
|
||||
XGetWindowProperty(disp(), rootWin, active, 0L, ~0L, false, AnyPropertyType, &actualType, &format, &num, &bytes,
|
||||
(uint8_t **)&data);
|
||||
|
||||
if (!data[0]) {
|
||||
|
@ -194,8 +184,7 @@ void GetCurrentWindowTitle(string &title)
|
|||
title = str;
|
||||
} else {
|
||||
XTextProperty xtp_new_name;
|
||||
if (XGetWMName(disp(), data[0], &xtp_new_name) != 0 &&
|
||||
xtp_new_name.value != nullptr) {
|
||||
if (XGetWMName(disp(), data[0], &xtp_new_name) != 0 && xtp_new_name.value != nullptr) {
|
||||
std::string str((const char *)xtp_new_name.value);
|
||||
title = str;
|
||||
XFree(xtp_new_name.value);
|
||||
|
|
|
@ -25,12 +25,7 @@ struct SceneSwitch {
|
|||
string window;
|
||||
regex re;
|
||||
|
||||
inline SceneSwitch(OBSWeakSource scene_, const char *window_)
|
||||
: scene(scene_),
|
||||
window(window_),
|
||||
re(window_)
|
||||
{
|
||||
}
|
||||
inline SceneSwitch(OBSWeakSource scene_, const char *window_) : scene(scene_), window(window_), re(window_) {}
|
||||
};
|
||||
|
||||
static inline bool WeakSourceValid(obs_weak_source_t *ws)
|
||||
|
@ -73,15 +68,12 @@ struct SwitcherData {
|
|||
|
||||
static SwitcherData *switcher = nullptr;
|
||||
|
||||
static inline QString MakeSwitchName(const QString &scene,
|
||||
const QString &window)
|
||||
static inline QString MakeSwitchName(const QString &scene, const QString &window)
|
||||
{
|
||||
return QStringLiteral("[") + scene + QStringLiteral("]: ") + window;
|
||||
}
|
||||
|
||||
SceneSwitcher::SceneSwitcher(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_SceneSwitcher)
|
||||
SceneSwitcher::SceneSwitcher(QWidget *parent) : QDialog(parent), ui(new Ui_SceneSwitcher)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -105,8 +97,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
|
|||
else
|
||||
ui->noMatchDontSwitch->setChecked(true);
|
||||
|
||||
ui->noMatchSwitchScene->setCurrentText(
|
||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||
ui->noMatchSwitchScene->setCurrentText(GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
||||
ui->checkInterval->setValue(switcher->interval);
|
||||
|
||||
vector<string> windows;
|
||||
|
@ -117,8 +108,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent)
|
|||
|
||||
for (auto &s : switcher->switches) {
|
||||
string sceneName = GetWeakSourceName(s.scene);
|
||||
QString text =
|
||||
MakeSwitchName(sceneName.c_str(), s.window.c_str());
|
||||
QString text = MakeSwitchName(sceneName.c_str(), s.window.c_str());
|
||||
|
||||
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
|
||||
item->setData(Qt::UserRole, s.window.c_str());
|
||||
|
@ -201,16 +191,13 @@ void SceneSwitcher::on_add_clicked()
|
|||
if (idx == -1) {
|
||||
try {
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
switcher->switches.emplace_back(
|
||||
source, windowName.toUtf8().constData());
|
||||
switcher->switches.emplace_back(source, windowName.toUtf8().constData());
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(text, ui->switches);
|
||||
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
|
||||
item->setData(Qt::UserRole, v);
|
||||
} catch (const regex_error &) {
|
||||
QMessageBox::warning(
|
||||
this, obs_module_text("InvalidRegex.Title"),
|
||||
obs_module_text("InvalidRegex.Text"));
|
||||
QMessageBox::warning(this, obs_module_text("InvalidRegex.Title"),
|
||||
obs_module_text("InvalidRegex.Text"));
|
||||
}
|
||||
} else {
|
||||
QListWidgetItem *item = ui->switches->item(idx);
|
||||
|
@ -238,8 +225,7 @@ void SceneSwitcher::on_remove_clicked()
|
|||
if (!item)
|
||||
return;
|
||||
|
||||
string window =
|
||||
item->data(Qt::UserRole).toString().toUtf8().constData();
|
||||
string window = item->data(Qt::UserRole).toString().toUtf8().constData();
|
||||
|
||||
{
|
||||
lock_guard<mutex> lock(switcher->m);
|
||||
|
@ -260,8 +246,7 @@ void SceneSwitcher::on_remove_clicked()
|
|||
|
||||
void SceneSwitcher::UpdateNonMatchingScene(const QString &name)
|
||||
{
|
||||
OBSSourceAutoRelease scene =
|
||||
obs_get_source_by_name(name.toUtf8().constData());
|
||||
OBSSourceAutoRelease scene = obs_get_source_by_name(name.toUtf8().constData());
|
||||
OBSWeakSourceAutoRelease ws = obs_source_get_weak_source(scene);
|
||||
|
||||
switcher->nonMatchingScene = ws.Get();
|
||||
|
@ -339,25 +324,20 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
for (SceneSwitch &s : switcher->switches) {
|
||||
OBSDataAutoRelease array_obj = obs_data_create();
|
||||
|
||||
OBSSourceAutoRelease source =
|
||||
obs_weak_source_get_source(s.scene);
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(s.scene);
|
||||
if (source) {
|
||||
const char *n = obs_source_get_name(source);
|
||||
obs_data_set_string(array_obj, "scene", n);
|
||||
obs_data_set_string(array_obj, "window_title",
|
||||
s.window.c_str());
|
||||
obs_data_set_string(array_obj, "window_title", s.window.c_str());
|
||||
obs_data_array_push_back(array, array_obj);
|
||||
}
|
||||
}
|
||||
|
||||
string nonMatchingSceneName =
|
||||
GetWeakSourceName(switcher->nonMatchingScene);
|
||||
string nonMatchingSceneName = GetWeakSourceName(switcher->nonMatchingScene);
|
||||
|
||||
obs_data_set_int(obj, "interval", switcher->interval);
|
||||
obs_data_set_string(obj, "non_matching_scene",
|
||||
nonMatchingSceneName.c_str());
|
||||
obs_data_set_bool(obj, "switch_if_not_matching",
|
||||
switcher->switchIfNotMatching);
|
||||
obs_data_set_string(obj, "non_matching_scene", nonMatchingSceneName.c_str());
|
||||
obs_data_set_bool(obj, "switch_if_not_matching", switcher->switchIfNotMatching);
|
||||
obs_data_set_bool(obj, "active", switcher->th.joinable());
|
||||
obs_data_set_array(obj, "switches", array);
|
||||
|
||||
|
@ -365,10 +345,8 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
} else {
|
||||
switcher->m.lock();
|
||||
|
||||
OBSDataAutoRelease obj =
|
||||
obs_data_get_obj(save_data, "auto-scene-switcher");
|
||||
OBSDataArrayAutoRelease array =
|
||||
obs_data_get_array(obj, "switches");
|
||||
OBSDataAutoRelease obj = obs_data_get_obj(save_data, "auto-scene-switcher");
|
||||
OBSDataArrayAutoRelease array = obs_data_get_array(obj, "switches");
|
||||
size_t count = obs_data_array_count(array);
|
||||
|
||||
if (!obj)
|
||||
|
@ -377,28 +355,21 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
obs_data_set_default_int(obj, "interval", DEFAULT_INTERVAL);
|
||||
|
||||
switcher->interval = obs_data_get_int(obj, "interval");
|
||||
switcher->switchIfNotMatching =
|
||||
obs_data_get_bool(obj, "switch_if_not_matching");
|
||||
string nonMatchingScene =
|
||||
obs_data_get_string(obj, "non_matching_scene");
|
||||
switcher->switchIfNotMatching = obs_data_get_bool(obj, "switch_if_not_matching");
|
||||
string nonMatchingScene = obs_data_get_string(obj, "non_matching_scene");
|
||||
bool active = obs_data_get_bool(obj, "active");
|
||||
|
||||
switcher->nonMatchingScene =
|
||||
GetWeakSourceByName(nonMatchingScene.c_str());
|
||||
switcher->nonMatchingScene = GetWeakSourceByName(nonMatchingScene.c_str());
|
||||
|
||||
switcher->switches.clear();
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
OBSDataAutoRelease array_obj =
|
||||
obs_data_array_item(array, i);
|
||||
OBSDataAutoRelease array_obj = obs_data_array_item(array, i);
|
||||
|
||||
const char *scene =
|
||||
obs_data_get_string(array_obj, "scene");
|
||||
const char *window =
|
||||
obs_data_get_string(array_obj, "window_title");
|
||||
const char *scene = obs_data_get_string(array_obj, "scene");
|
||||
const char *window = obs_data_get_string(array_obj, "window_title");
|
||||
|
||||
switcher->switches.emplace_back(
|
||||
GetWeakSourceByName(scene), window);
|
||||
switcher->switches.emplace_back(GetWeakSourceByName(scene), window);
|
||||
}
|
||||
|
||||
switcher->m.unlock();
|
||||
|
@ -412,8 +383,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
|
||||
void SwitcherData::Thread()
|
||||
{
|
||||
chrono::duration<long long, milli> duration =
|
||||
chrono::milliseconds(interval);
|
||||
chrono::duration<long long, milli> duration = chrono::milliseconds(interval);
|
||||
string lastTitle;
|
||||
string title;
|
||||
|
||||
|
@ -447,8 +417,7 @@ void SwitcherData::Thread()
|
|||
if (!match) {
|
||||
for (SceneSwitch &s : switches) {
|
||||
try {
|
||||
bool matches = regex_match(
|
||||
title, s.re);
|
||||
bool matches = regex_match(title, s.re);
|
||||
if (matches) {
|
||||
match = true;
|
||||
scene = s.scene;
|
||||
|
@ -465,10 +434,8 @@ void SwitcherData::Thread()
|
|||
}
|
||||
|
||||
if (match) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_weak_source_get_source(scene);
|
||||
OBSSourceAutoRelease currentSource =
|
||||
obs_frontend_get_current_scene();
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(scene);
|
||||
OBSSourceAutoRelease currentSource = obs_frontend_get_current_scene();
|
||||
|
||||
if (source && source != currentSource)
|
||||
obs_frontend_set_current_scene(source);
|
||||
|
@ -518,16 +485,14 @@ extern "C" void InitSceneSwitcher()
|
|||
return;
|
||||
#endif
|
||||
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("SceneSwitcher"));
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("SceneSwitcher"));
|
||||
|
||||
switcher = new SwitcherData;
|
||||
|
||||
auto cb = []() {
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
|
||||
QMainWindow *window =
|
||||
(QMainWindow *)obs_frontend_get_main_window();
|
||||
QMainWindow *window = (QMainWindow *)obs_frontend_get_main_window();
|
||||
|
||||
SceneSwitcher ss(window);
|
||||
ss.exec();
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
#include "captions-handler.hpp"
|
||||
|
||||
captions_handler::captions_handler(captions_cb callback,
|
||||
enum audio_format format,
|
||||
uint32_t sample_rate)
|
||||
: cb(callback)
|
||||
captions_handler::captions_handler(captions_cb callback, enum audio_format format, uint32_t sample_rate) : cb(callback)
|
||||
{
|
||||
if (!reset_resampler(format, sample_rate))
|
||||
throw CAPTIONS_ERROR_GENERIC_FAIL;
|
||||
}
|
||||
|
||||
bool captions_handler::reset_resampler(enum audio_format format,
|
||||
uint32_t sample_rate)
|
||||
bool captions_handler::reset_resampler(enum audio_format format, uint32_t sample_rate)
|
||||
try {
|
||||
obs_audio_info ai;
|
||||
if (!obs_get_audio_info(&ai))
|
||||
throw std::string("Failed to get OBS audio info");
|
||||
|
||||
resample_info src = {ai.samples_per_sec, AUDIO_FORMAT_FLOAT_PLANAR,
|
||||
ai.speakers};
|
||||
resample_info src = {ai.samples_per_sec, AUDIO_FORMAT_FLOAT_PLANAR, ai.speakers};
|
||||
resample_info dst = {sample_rate, format, SPEAKERS_MONO};
|
||||
|
||||
if (!resampler.reset(dst, src))
|
||||
|
@ -37,8 +32,7 @@ void captions_handler::push_audio(const audio_data *audio)
|
|||
uint64_t ts_offset;
|
||||
bool success;
|
||||
|
||||
success = audio_resampler_resample(resampler, out, &frames, &ts_offset,
|
||||
(const uint8_t *const *)audio->data,
|
||||
success = audio_resampler_resample(resampler, out, &frames, &ts_offset, (const uint8_t *const *)audio->data,
|
||||
audio->frames);
|
||||
if (success)
|
||||
pcm_data(out[0], frames);
|
||||
|
|
|
@ -25,8 +25,7 @@ public:
|
|||
|
||||
typedef std::function<void(const std::string &)> captions_cb;
|
||||
|
||||
#define CAPTIONS_ERROR_GENERIC_FAIL \
|
||||
std::string(obs_module_text("Captions.Error.GenericFail"))
|
||||
#define CAPTIONS_ERROR_GENERIC_FAIL std::string(obs_module_text("Captions.Error.GenericFail"))
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -44,8 +43,7 @@ protected:
|
|||
|
||||
public:
|
||||
/* throw std::string for errors shown to users */
|
||||
captions_handler(captions_cb callback, enum audio_format format,
|
||||
uint32_t sample_rate);
|
||||
captions_handler(captions_cb callback, enum audio_format format, uint32_t sample_rate);
|
||||
virtual ~captions_handler() {}
|
||||
|
||||
void push_audio(const audio_data *audio);
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
using namespace std;
|
||||
|
||||
#if 0
|
||||
#define debugfunc(format, ...) \
|
||||
blog(LOG_DEBUG, "[Captions] %s(" format ")", __FUNCTION__, \
|
||||
##__VA_ARGS__)
|
||||
#define debugfunc(format, ...) blog(LOG_DEBUG, "[Captions] %s(" format ")", __FUNCTION__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define debugfunc(format, ...)
|
||||
#endif
|
||||
|
@ -144,8 +142,7 @@ STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes, ULONG *)
|
|||
|
||||
// IStream methods
|
||||
|
||||
STDMETHODIMP CaptionStream::Seek(LARGE_INTEGER move, DWORD origin,
|
||||
ULARGE_INTEGER *new_pos)
|
||||
STDMETHODIMP CaptionStream::Seek(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos)
|
||||
{
|
||||
debugfunc("%lld, %lx, new_pos", move, origin);
|
||||
|
||||
|
@ -165,8 +162,7 @@ STDMETHODIMP CaptionStream::SetSize(ULARGE_INTEGER new_size)
|
|||
return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
|
||||
STDMETHODIMP CaptionStream::CopyTo(IStream *stream, ULARGE_INTEGER bytes,
|
||||
ULARGE_INTEGER *read_bytes,
|
||||
STDMETHODIMP CaptionStream::CopyTo(IStream *stream, ULARGE_INTEGER bytes, ULARGE_INTEGER *read_bytes,
|
||||
ULARGE_INTEGER *written_bytes)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -207,16 +203,14 @@ STDMETHODIMP CaptionStream::Revert(void)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CaptionStream::LockRegion(ULARGE_INTEGER offset,
|
||||
ULARGE_INTEGER size, DWORD type)
|
||||
STDMETHODIMP CaptionStream::LockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
|
||||
{
|
||||
debugfunc("%llu, %llu, %ld", offset, size, type);
|
||||
/* TODO? */
|
||||
return STG_E_INVALIDFUNCTION;
|
||||
}
|
||||
|
||||
STDMETHODIMP CaptionStream::UnlockRegion(ULARGE_INTEGER offset,
|
||||
ULARGE_INTEGER size, DWORD type)
|
||||
STDMETHODIMP CaptionStream::UnlockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type)
|
||||
{
|
||||
debugfunc("%llu, %llu, %ld", offset, size, type);
|
||||
/* TODO? */
|
||||
|
@ -255,8 +249,7 @@ STDMETHODIMP CaptionStream::Clone(IStream **stream)
|
|||
|
||||
// ISpStreamFormat methods
|
||||
|
||||
STDMETHODIMP CaptionStream::GetFormat(GUID *guid,
|
||||
WAVEFORMATEX **co_mem_wfex_out)
|
||||
STDMETHODIMP CaptionStream::GetFormat(GUID *guid, WAVEFORMATEX **co_mem_wfex_out)
|
||||
{
|
||||
debugfunc("guid, co_mem_wfex_out");
|
||||
|
||||
|
@ -284,8 +277,7 @@ STDMETHODIMP CaptionStream::SetState(SPAUDIOSTATE state_, ULONGLONG)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CaptionStream::SetFormat(REFGUID guid_ref,
|
||||
const WAVEFORMATEX *wfex)
|
||||
STDMETHODIMP CaptionStream::SetFormat(REFGUID guid_ref, const WAVEFORMATEX *wfex)
|
||||
{
|
||||
debugfunc("guid, wfex");
|
||||
if (!wfex)
|
||||
|
@ -294,8 +286,7 @@ STDMETHODIMP CaptionStream::SetFormat(REFGUID guid_ref,
|
|||
if (guid_ref == SPDFID_WaveFormatEx) {
|
||||
lock_guard<mutex> lock(m);
|
||||
memcpy(&format, wfex, sizeof(format));
|
||||
if (!handler->reset_resampler(AUDIO_FORMAT_16BIT,
|
||||
wfex->nSamplesPerSec))
|
||||
if (!handler->reset_resampler(AUDIO_FORMAT_16BIT, wfex->nSamplesPerSec))
|
||||
return E_FAIL;
|
||||
|
||||
/* 50 msec */
|
||||
|
@ -342,8 +333,7 @@ STDMETHODIMP CaptionStream::GetBufferInfo(SPAUDIOBUFFERINFO *buf_info_)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP CaptionStream::GetDefaultFormat(GUID *format,
|
||||
WAVEFORMATEX **co_mem_wfex_out)
|
||||
STDMETHODIMP CaptionStream::GetDefaultFormat(GUID *format, WAVEFORMATEX **co_mem_wfex_out)
|
||||
{
|
||||
debugfunc("format, co_mem_wfex_out");
|
||||
|
||||
|
|
|
@ -55,38 +55,30 @@ public:
|
|||
|
||||
// ISequentialStream methods
|
||||
STDMETHODIMP Read(void *data, ULONG bytes, ULONG *read_bytes) override;
|
||||
STDMETHODIMP Write(const void *data, ULONG bytes,
|
||||
ULONG *written_bytes) override;
|
||||
STDMETHODIMP Write(const void *data, ULONG bytes, ULONG *written_bytes) override;
|
||||
|
||||
// IStream methods
|
||||
STDMETHODIMP Seek(LARGE_INTEGER move, DWORD origin,
|
||||
ULARGE_INTEGER *new_pos) override;
|
||||
STDMETHODIMP Seek(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER *new_pos) override;
|
||||
STDMETHODIMP SetSize(ULARGE_INTEGER new_size) override;
|
||||
STDMETHODIMP CopyTo(IStream *stream, ULARGE_INTEGER bytes,
|
||||
ULARGE_INTEGER *read_bytes,
|
||||
STDMETHODIMP CopyTo(IStream *stream, ULARGE_INTEGER bytes, ULARGE_INTEGER *read_bytes,
|
||||
ULARGE_INTEGER *written_bytes) override;
|
||||
STDMETHODIMP Commit(DWORD commit_flags) override;
|
||||
STDMETHODIMP Revert(void) override;
|
||||
STDMETHODIMP LockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
|
||||
DWORD type) override;
|
||||
STDMETHODIMP UnlockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size,
|
||||
DWORD type) override;
|
||||
STDMETHODIMP LockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type) override;
|
||||
STDMETHODIMP UnlockRegion(ULARGE_INTEGER offset, ULARGE_INTEGER size, DWORD type) override;
|
||||
STDMETHODIMP Stat(STATSTG *stg, DWORD flags) override;
|
||||
STDMETHODIMP Clone(IStream **stream) override;
|
||||
|
||||
// ISpStreamFormat methods
|
||||
STDMETHODIMP GetFormat(GUID *guid,
|
||||
WAVEFORMATEX **co_mem_wfex_out) override;
|
||||
STDMETHODIMP GetFormat(GUID *guid, WAVEFORMATEX **co_mem_wfex_out) override;
|
||||
|
||||
// ISpAudio methods
|
||||
STDMETHODIMP SetState(SPAUDIOSTATE state, ULONGLONG reserved) override;
|
||||
STDMETHODIMP SetFormat(REFGUID guid_ref,
|
||||
const WAVEFORMATEX *wfex) override;
|
||||
STDMETHODIMP SetFormat(REFGUID guid_ref, const WAVEFORMATEX *wfex) override;
|
||||
STDMETHODIMP GetStatus(SPAUDIOSTATUS *status) override;
|
||||
STDMETHODIMP SetBufferInfo(const SPAUDIOBUFFERINFO *buf_info) override;
|
||||
STDMETHODIMP GetBufferInfo(SPAUDIOBUFFERINFO *buf_info) override;
|
||||
STDMETHODIMP GetDefaultFormat(GUID *format,
|
||||
WAVEFORMATEX **co_mem_wfex_out) override;
|
||||
STDMETHODIMP GetDefaultFormat(GUID *format, WAVEFORMATEX **co_mem_wfex_out) override;
|
||||
STDMETHODIMP_(HANDLE) EventHandle(void) override;
|
||||
STDMETHODIMP GetVolumeLevel(ULONG *level) override;
|
||||
STDMETHODIMP SetVolumeLevel(ULONG level) override;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "captions-mssapi.hpp"
|
||||
|
||||
#define do_log(type, format, ...) \
|
||||
blog(type, "[Captions] " format, ##__VA_ARGS__)
|
||||
#define do_log(type, format, ...) blog(type, "[Captions] " format, ##__VA_ARGS__)
|
||||
|
||||
#define error(format, ...) do_log(LOG_ERROR, format, ##__VA_ARGS__)
|
||||
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
|
||||
|
@ -29,8 +28,8 @@ try : captions_handler(callback, AUDIO_FORMAT_16BIT, 16000) {
|
|||
if (FAILED(hr))
|
||||
throw HRError("SpFindBestToken failed", hr);
|
||||
|
||||
hr = CoCreateInstance(CLSID_SpInprocRecognizer, nullptr, CLSCTX_ALL,
|
||||
__uuidof(ISpRecognizer), (void **)&recognizer);
|
||||
hr = CoCreateInstance(CLSID_SpInprocRecognizer, nullptr, CLSCTX_ALL, __uuidof(ISpRecognizer),
|
||||
(void **)&recognizer);
|
||||
if (FAILED(hr))
|
||||
throw HRError("CoCreateInstance for recognizer failed", hr);
|
||||
|
||||
|
@ -46,8 +45,7 @@ try : captions_handler(callback, AUDIO_FORMAT_16BIT, 16000) {
|
|||
if (FAILED(hr))
|
||||
throw HRError("CreateRecoContext failed", hr);
|
||||
|
||||
ULONGLONG interest = SPFEI(SPEI_RECOGNITION) |
|
||||
SPFEI(SPEI_END_SR_STREAM);
|
||||
ULONGLONG interest = SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_END_SR_STREAM);
|
||||
hr = context->SetInterest(interest, interest);
|
||||
if (FAILED(hr))
|
||||
throw HRError("SetInterest failed", hr);
|
||||
|
@ -130,8 +128,7 @@ try {
|
|||
ISpRecoResult *result = event.RecoResult();
|
||||
|
||||
CoTaskMemPtr<wchar_t> text;
|
||||
hr = result->GetText((ULONG)-1, (ULONG)-1, true,
|
||||
&text, nullptr);
|
||||
hr = result->GetText((ULONG)-1, (ULONG)-1, true, &text, nullptr);
|
||||
if (FAILED(hr))
|
||||
continue;
|
||||
|
||||
|
@ -164,8 +161,7 @@ void mssapi_captions::pcm_data(const void *data, size_t frames)
|
|||
audio->PushAudio(data, frames);
|
||||
}
|
||||
|
||||
captions_handler_info mssapi_info = {
|
||||
[]() -> std::string { return "Microsoft Speech-to-Text"; },
|
||||
[](captions_cb cb, const std::string &lang) -> captions_handler * {
|
||||
return new mssapi_captions(cb, lang);
|
||||
}};
|
||||
captions_handler_info mssapi_info = {[]() -> std::string { return "Microsoft Speech-to-Text"; },
|
||||
[](captions_cb cb, const std::string &lang) -> captions_handler * {
|
||||
return new mssapi_captions(cb, lang);
|
||||
}};
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
|
||||
#include "captions-mssapi.hpp"
|
||||
|
||||
#define do_log(type, format, ...) \
|
||||
blog(type, "[Captions] " format, ##__VA_ARGS__)
|
||||
#define do_log(type, format, ...) blog(type, "[Captions] " format, ##__VA_ARGS__)
|
||||
|
||||
#define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__)
|
||||
#define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__)
|
||||
|
@ -50,11 +49,7 @@ struct obs_captions {
|
|||
|
||||
std::unordered_map<std::string, captions_handler_info &> handler_types;
|
||||
|
||||
inline void register_handler(const char *id,
|
||||
captions_handler_info &info)
|
||||
{
|
||||
handler_types.emplace(id, info);
|
||||
}
|
||||
inline void register_handler(const char *id, captions_handler_info &info) { handler_types.emplace(id, info); }
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
@ -73,11 +68,7 @@ struct locale_info {
|
|||
|
||||
inline locale_info() {}
|
||||
inline locale_info(const locale_info &) = delete;
|
||||
inline locale_info(locale_info &&li)
|
||||
: name(std::move(li.name)),
|
||||
id(li.id)
|
||||
{
|
||||
}
|
||||
inline locale_info(locale_info &&li) : name(std::move(li.name)), id(li.id) {}
|
||||
};
|
||||
|
||||
static void get_valid_locale_names(vector<locale_info> &names);
|
||||
|
@ -85,9 +76,7 @@ static bool valid_lang(LANGID id);
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
CaptionsDialog::CaptionsDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_CaptionsDialog)
|
||||
CaptionsDialog::CaptionsDialog(QWidget *parent) : QDialog(parent), ui(new Ui_CaptionsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -111,11 +100,7 @@ CaptionsDialog::CaptionsDialog(QWidget *parent)
|
|||
ui->source->blockSignals(true);
|
||||
ui->source->addItem(QStringLiteral(""));
|
||||
ui->source->setCurrentIndex(0);
|
||||
obs_enum_sources(
|
||||
[](void *data, obs_source_t *source) {
|
||||
return (*static_cast<cb_t *>(data))(source);
|
||||
},
|
||||
&cb);
|
||||
obs_enum_sources([](void *data, obs_source_t *source) { return (*static_cast<cb_t *>(data))(source); }, &cb);
|
||||
ui->source->blockSignals(false);
|
||||
|
||||
for (auto &ht : captions->handler_types) {
|
||||
|
@ -217,8 +202,7 @@ void CaptionsDialog::on_provider_currentIndexChanged(int idx)
|
|||
if (started)
|
||||
captions->stop();
|
||||
|
||||
captions->handler_id =
|
||||
ui->provider->itemData(idx).toString().toUtf8().constData();
|
||||
captions->handler_id = ui->provider->itemData(idx).toString().toUtf8().constData();
|
||||
|
||||
if (started)
|
||||
captions->start();
|
||||
|
@ -234,8 +218,7 @@ static void caption_text(const std::string &text)
|
|||
}
|
||||
}
|
||||
|
||||
static void audio_capture(void *, obs_source_t *,
|
||||
const struct audio_data *audio, bool)
|
||||
static void audio_capture(void *, obs_source_t *, const struct audio_data *audio, bool)
|
||||
{
|
||||
captions->handler->push_audio(audio);
|
||||
}
|
||||
|
@ -252,8 +235,7 @@ void obs_captions::start()
|
|||
}
|
||||
|
||||
if (!LCIDToLocaleName(lang_id, wname, 256, 0)) {
|
||||
warn("Failed to get locale name: %d",
|
||||
(int)GetLastError());
|
||||
warn("Failed to get locale name: %d", (int)GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -272,24 +254,18 @@ void obs_captions::start()
|
|||
}
|
||||
|
||||
try {
|
||||
captions_handler *h =
|
||||
pair->second.create(caption_text, lang_name);
|
||||
captions_handler *h = pair->second.create(caption_text, lang_name);
|
||||
handler.reset(h);
|
||||
|
||||
OBSSource s = OBSGetStrongRef(source);
|
||||
obs_source_add_audio_capture_callback(s, audio_capture,
|
||||
nullptr);
|
||||
obs_source_add_audio_capture_callback(s, audio_capture, nullptr);
|
||||
|
||||
} catch (std::string text) {
|
||||
QWidget *window =
|
||||
(QWidget *)obs_frontend_get_main_window();
|
||||
QWidget *window = (QWidget *)obs_frontend_get_main_window();
|
||||
|
||||
warn("Failed to create handler: %s", text.c_str());
|
||||
|
||||
QMessageBox::warning(
|
||||
window,
|
||||
obs_module_text("Captions.Error.GenericFail"),
|
||||
text.c_str());
|
||||
QMessageBox::warning(window, obs_module_text("Captions.Error.GenericFail"), text.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,8 +274,7 @@ void obs_captions::stop()
|
|||
{
|
||||
OBSSource s = OBSGetStrongRef(source);
|
||||
if (s)
|
||||
obs_source_remove_audio_capture_callback(s, audio_capture,
|
||||
nullptr);
|
||||
obs_source_remove_audio_capture_callback(s, audio_capture, nullptr);
|
||||
handler.reset();
|
||||
}
|
||||
|
||||
|
@ -332,19 +307,16 @@ static void get_valid_locale_names(vector<locale_info> &locales)
|
|||
locale_info cur;
|
||||
char locale_name[256];
|
||||
|
||||
static const LANGID default_locales[] = {
|
||||
0x0409, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406,
|
||||
0x0407, 0x0408, 0x040a, 0x040b, 0x040c, 0x040d, 0x040e,
|
||||
0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415,
|
||||
0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0};
|
||||
static const LANGID default_locales[] = {0x0409, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408,
|
||||
0x040a, 0x040b, 0x040c, 0x040d, 0x040e, 0x040f, 0x0410, 0x0411, 0x0412,
|
||||
0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0};
|
||||
|
||||
/* ---------------------------------- */
|
||||
|
||||
LANGID def_id = GetUserDefaultUILanguage();
|
||||
LANGID id = def_id;
|
||||
if (valid_lang(id) && get_locale_name(id, locale_name)) {
|
||||
dstr_copy(cur.name,
|
||||
obs_module_text("Captions.CurrentSystemLanguage"));
|
||||
dstr_copy(cur.name, obs_module_text("Captions.CurrentSystemLanguage"));
|
||||
dstr_replace(cur.name, "%1", locale_name);
|
||||
cur.id = id;
|
||||
|
||||
|
@ -358,8 +330,7 @@ static void get_valid_locale_names(vector<locale_info> &locales)
|
|||
while (*locale) {
|
||||
id = *locale;
|
||||
|
||||
if (id != def_id && valid_lang(id) &&
|
||||
get_locale_name(id, locale_name)) {
|
||||
if (id != def_id && valid_lang(id) && get_locale_name(id, locale_name)) {
|
||||
|
||||
dstr_copy(cur.name, locale_name);
|
||||
cur.id = id;
|
||||
|
@ -399,32 +370,27 @@ static void save_caption_data(obs_data_t *save_data, bool saving, void *)
|
|||
if (saving) {
|
||||
OBSDataAutoRelease obj = obs_data_create();
|
||||
|
||||
obs_data_set_string(obj, "source",
|
||||
captions->source_name.c_str());
|
||||
obs_data_set_string(obj, "source", captions->source_name.c_str());
|
||||
obs_data_set_bool(obj, "enabled", !!captions->handler);
|
||||
obs_data_set_int(obj, "lang_id", captions->lang_id);
|
||||
obs_data_set_string(obj, "provider",
|
||||
captions->handler_id.c_str());
|
||||
obs_data_set_string(obj, "provider", captions->handler_id.c_str());
|
||||
|
||||
obs_data_set_obj(save_data, "captions", obj);
|
||||
} else {
|
||||
captions->stop();
|
||||
|
||||
OBSDataAutoRelease obj =
|
||||
obs_data_get_obj(save_data, "captions");
|
||||
OBSDataAutoRelease obj = obs_data_get_obj(save_data, "captions");
|
||||
if (!obj)
|
||||
obj = obs_data_create();
|
||||
|
||||
obs_data_set_default_int(obj, "lang_id",
|
||||
GetUserDefaultUILanguage());
|
||||
obs_data_set_default_int(obj, "lang_id", GetUserDefaultUILanguage());
|
||||
obs_data_set_default_string(obj, "provider", DEFAULT_HANDLER);
|
||||
|
||||
bool enabled = obs_data_get_bool(obj, "enabled");
|
||||
captions->source_name = obs_data_get_string(obj, "source");
|
||||
captions->lang_id = (int)obs_data_get_int(obj, "lang_id");
|
||||
captions->handler_id = obs_data_get_string(obj, "provider");
|
||||
captions->source =
|
||||
GetWeakSourceByName(captions->source_name.c_str());
|
||||
captions->source = GetWeakSourceByName(captions->source_name.c_str());
|
||||
|
||||
if (enabled)
|
||||
captions->start();
|
||||
|
@ -433,8 +399,7 @@ static void save_caption_data(obs_data_t *save_data, bool saving, void *)
|
|||
|
||||
extern "C" void InitCaptions()
|
||||
{
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("Captions"));
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("Captions"));
|
||||
|
||||
captions = new obs_captions;
|
||||
|
||||
|
|
|
@ -12,20 +12,16 @@ using namespace std;
|
|||
|
||||
OutputTimer *ot;
|
||||
|
||||
OutputTimer::OutputTimer(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_OutputTimer)
|
||||
OutputTimer::OutputTimer(QWidget *parent) : QDialog(parent), ui(new Ui_OutputTimer)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
QObject::connect(ui->outputTimerStream, &QPushButton::clicked, this,
|
||||
&OutputTimer::StreamingTimerButton);
|
||||
QObject::connect(ui->outputTimerRecord, &QPushButton::clicked, this,
|
||||
&OutputTimer::RecordingTimerButton);
|
||||
QObject::connect(ui->buttonBox->button(QDialogButtonBox::Close),
|
||||
&QPushButton::clicked, this, &OutputTimer::hide);
|
||||
QObject::connect(ui->outputTimerStream, &QPushButton::clicked, this, &OutputTimer::StreamingTimerButton);
|
||||
QObject::connect(ui->outputTimerRecord, &QPushButton::clicked, this, &OutputTimer::RecordingTimerButton);
|
||||
QObject::connect(ui->buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this,
|
||||
&OutputTimer::hide);
|
||||
|
||||
streamingTimer = new QTimer(this);
|
||||
streamingTimerDisplay = new QTimer(this);
|
||||
|
@ -33,14 +29,10 @@ OutputTimer::OutputTimer(QWidget *parent)
|
|||
recordingTimer = new QTimer(this);
|
||||
recordingTimerDisplay = new QTimer(this);
|
||||
|
||||
QObject::connect(streamingTimer, &QTimer::timeout, this,
|
||||
&OutputTimer::EventStopStreaming);
|
||||
QObject::connect(streamingTimerDisplay, &QTimer::timeout, this,
|
||||
&OutputTimer::UpdateStreamTimerDisplay);
|
||||
QObject::connect(recordingTimer, &QTimer::timeout, this,
|
||||
&OutputTimer::EventStopRecording);
|
||||
QObject::connect(recordingTimerDisplay, &QTimer::timeout, this,
|
||||
&OutputTimer::UpdateRecordTimerDisplay);
|
||||
QObject::connect(streamingTimer, &QTimer::timeout, this, &OutputTimer::EventStopStreaming);
|
||||
QObject::connect(streamingTimerDisplay, &QTimer::timeout, this, &OutputTimer::UpdateStreamTimerDisplay);
|
||||
QObject::connect(recordingTimer, &QTimer::timeout, this, &OutputTimer::EventStopRecording);
|
||||
QObject::connect(recordingTimerDisplay, &QTimer::timeout, this, &OutputTimer::UpdateRecordTimerDisplay);
|
||||
}
|
||||
|
||||
void OutputTimer::closeEvent(QCloseEvent *)
|
||||
|
@ -178,8 +170,7 @@ void OutputTimer::UpdateStreamTimerDisplay()
|
|||
int minutes = (remainingTime % 3600) / 60;
|
||||
int hours = remainingTime / 3600;
|
||||
|
||||
QString text =
|
||||
QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
|
||||
QString text = QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
|
||||
ui->streamTime->setText(text);
|
||||
}
|
||||
|
||||
|
@ -187,8 +178,7 @@ void OutputTimer::UpdateRecordTimerDisplay()
|
|||
{
|
||||
int remainingTime = 0;
|
||||
|
||||
if (obs_frontend_recording_paused() &&
|
||||
ui->pauseRecordTimer->isChecked())
|
||||
if (obs_frontend_recording_paused() && ui->pauseRecordTimer->isChecked())
|
||||
remainingTime = recordingTimeLeft / 1000;
|
||||
else
|
||||
remainingTime = recordingTimer->remainingTime() / 1000;
|
||||
|
@ -197,8 +187,7 @@ void OutputTimer::UpdateRecordTimerDisplay()
|
|||
int minutes = (remainingTime % 3600) / 60;
|
||||
int hours = remainingTime / 3600;
|
||||
|
||||
QString text =
|
||||
QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
|
||||
QString text = QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
|
||||
ui->recordTime->setText(text);
|
||||
}
|
||||
|
||||
|
@ -250,57 +239,38 @@ static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *)
|
|||
if (saving) {
|
||||
OBSDataAutoRelease obj = obs_data_create();
|
||||
|
||||
obs_data_set_int(obj, "streamTimerHours",
|
||||
ot->ui->streamingTimerHours->value());
|
||||
obs_data_set_int(obj, "streamTimerMinutes",
|
||||
ot->ui->streamingTimerMinutes->value());
|
||||
obs_data_set_int(obj, "streamTimerSeconds",
|
||||
ot->ui->streamingTimerSeconds->value());
|
||||
obs_data_set_int(obj, "streamTimerHours", ot->ui->streamingTimerHours->value());
|
||||
obs_data_set_int(obj, "streamTimerMinutes", ot->ui->streamingTimerMinutes->value());
|
||||
obs_data_set_int(obj, "streamTimerSeconds", ot->ui->streamingTimerSeconds->value());
|
||||
|
||||
obs_data_set_int(obj, "recordTimerHours",
|
||||
ot->ui->recordingTimerHours->value());
|
||||
obs_data_set_int(obj, "recordTimerMinutes",
|
||||
ot->ui->recordingTimerMinutes->value());
|
||||
obs_data_set_int(obj, "recordTimerSeconds",
|
||||
ot->ui->recordingTimerSeconds->value());
|
||||
obs_data_set_int(obj, "recordTimerHours", ot->ui->recordingTimerHours->value());
|
||||
obs_data_set_int(obj, "recordTimerMinutes", ot->ui->recordingTimerMinutes->value());
|
||||
obs_data_set_int(obj, "recordTimerSeconds", ot->ui->recordingTimerSeconds->value());
|
||||
|
||||
obs_data_set_bool(obj, "autoStartStreamTimer",
|
||||
ot->ui->autoStartStreamTimer->isChecked());
|
||||
obs_data_set_bool(obj, "autoStartRecordTimer",
|
||||
ot->ui->autoStartRecordTimer->isChecked());
|
||||
obs_data_set_bool(obj, "autoStartStreamTimer", ot->ui->autoStartStreamTimer->isChecked());
|
||||
obs_data_set_bool(obj, "autoStartRecordTimer", ot->ui->autoStartRecordTimer->isChecked());
|
||||
|
||||
obs_data_set_bool(obj, "pauseRecordTimer",
|
||||
ot->ui->pauseRecordTimer->isChecked());
|
||||
obs_data_set_bool(obj, "pauseRecordTimer", ot->ui->pauseRecordTimer->isChecked());
|
||||
|
||||
obs_data_set_obj(save_data, "output-timer", obj);
|
||||
} else {
|
||||
OBSDataAutoRelease obj =
|
||||
obs_data_get_obj(save_data, "output-timer");
|
||||
OBSDataAutoRelease obj = obs_data_get_obj(save_data, "output-timer");
|
||||
|
||||
if (!obj)
|
||||
obj = obs_data_create();
|
||||
|
||||
ot->ui->streamingTimerHours->setValue(
|
||||
obs_data_get_int(obj, "streamTimerHours"));
|
||||
ot->ui->streamingTimerMinutes->setValue(
|
||||
obs_data_get_int(obj, "streamTimerMinutes"));
|
||||
ot->ui->streamingTimerSeconds->setValue(
|
||||
obs_data_get_int(obj, "streamTimerSeconds"));
|
||||
ot->ui->streamingTimerHours->setValue(obs_data_get_int(obj, "streamTimerHours"));
|
||||
ot->ui->streamingTimerMinutes->setValue(obs_data_get_int(obj, "streamTimerMinutes"));
|
||||
ot->ui->streamingTimerSeconds->setValue(obs_data_get_int(obj, "streamTimerSeconds"));
|
||||
|
||||
ot->ui->recordingTimerHours->setValue(
|
||||
obs_data_get_int(obj, "recordTimerHours"));
|
||||
ot->ui->recordingTimerMinutes->setValue(
|
||||
obs_data_get_int(obj, "recordTimerMinutes"));
|
||||
ot->ui->recordingTimerSeconds->setValue(
|
||||
obs_data_get_int(obj, "recordTimerSeconds"));
|
||||
ot->ui->recordingTimerHours->setValue(obs_data_get_int(obj, "recordTimerHours"));
|
||||
ot->ui->recordingTimerMinutes->setValue(obs_data_get_int(obj, "recordTimerMinutes"));
|
||||
ot->ui->recordingTimerSeconds->setValue(obs_data_get_int(obj, "recordTimerSeconds"));
|
||||
|
||||
ot->ui->autoStartStreamTimer->setChecked(
|
||||
obs_data_get_bool(obj, "autoStartStreamTimer"));
|
||||
ot->ui->autoStartRecordTimer->setChecked(
|
||||
obs_data_get_bool(obj, "autoStartRecordTimer"));
|
||||
ot->ui->autoStartStreamTimer->setChecked(obs_data_get_bool(obj, "autoStartStreamTimer"));
|
||||
ot->ui->autoStartRecordTimer->setChecked(obs_data_get_bool(obj, "autoStartRecordTimer"));
|
||||
|
||||
ot->ui->pauseRecordTimer->setChecked(
|
||||
obs_data_get_bool(obj, "pauseRecordTimer"));
|
||||
ot->ui->pauseRecordTimer->setChecked(obs_data_get_bool(obj, "pauseRecordTimer"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,8 +298,7 @@ static void OBSEvent(enum obs_frontend_event event, void *)
|
|||
|
||||
extern "C" void InitOutputTimer()
|
||||
{
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("OutputTimer"));
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("OutputTimer"));
|
||||
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
|
||||
|
|
|
@ -93,8 +93,7 @@ ScriptLogWindow::ScriptLogWindow() : QDialog(nullptr)
|
|||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout();
|
||||
QPushButton *clearButton = new QPushButton(tr("Clear"));
|
||||
connect(clearButton, &QPushButton::clicked, this,
|
||||
&ScriptLogWindow::ClearWindow);
|
||||
connect(clearButton, &QPushButton::clicked, this, &ScriptLogWindow::ClearWindow);
|
||||
QPushButton *closeButton = new QPushButton(tr("Close"));
|
||||
connect(closeButton, &QPushButton::clicked, this, &QDialog::hide);
|
||||
|
||||
|
@ -114,8 +113,7 @@ ScriptLogWindow::ScriptLogWindow() : QDialog(nullptr)
|
|||
resize(600, 400);
|
||||
|
||||
config_t *global_config = obs_frontend_get_user_config();
|
||||
const char *geom =
|
||||
config_get_string(global_config, "ScriptLogWindow", "geometry");
|
||||
const char *geom = config_get_string(global_config, "ScriptLogWindow", "geometry");
|
||||
if (geom != nullptr) {
|
||||
QByteArray ba = QByteArray::fromBase64(QByteArray(geom));
|
||||
restoreGeometry(ba);
|
||||
|
@ -123,15 +121,13 @@ ScriptLogWindow::ScriptLogWindow() : QDialog(nullptr)
|
|||
|
||||
setWindowTitle(obs_module_text("ScriptLogWindow"));
|
||||
|
||||
connect(edit->verticalScrollBar(), &QAbstractSlider::sliderMoved, this,
|
||||
&ScriptLogWindow::ScrollChanged);
|
||||
connect(edit->verticalScrollBar(), &QAbstractSlider::sliderMoved, this, &ScriptLogWindow::ScrollChanged);
|
||||
}
|
||||
|
||||
ScriptLogWindow::~ScriptLogWindow()
|
||||
{
|
||||
config_t *global_config = obs_frontend_get_user_config();
|
||||
config_set_string(global_config, "ScriptLogWindow", "geometry",
|
||||
saveGeometry().toBase64().constData());
|
||||
config_set_string(global_config, "ScriptLogWindow", "geometry", saveGeometry().toBase64().constData());
|
||||
}
|
||||
|
||||
void ScriptLogWindow::ScrollChanged(int val)
|
||||
|
@ -190,8 +186,7 @@ ScriptsTool::ScriptsTool() : QDialog(nullptr), ui(new Ui_ScriptsTool)
|
|||
|
||||
#if PYTHON_UI
|
||||
config_t *config = obs_frontend_get_user_config();
|
||||
const char *path =
|
||||
config_get_string(config, "Python", "Path" ARCH_NAME);
|
||||
const char *path = config_get_string(config, "Python", "Path" ARCH_NAME);
|
||||
ui->pythonPath->setText(path);
|
||||
ui->pythonPathLabel->setText(obs_module_text(PYTHONPATH_LABEL_TEXT));
|
||||
updatePythonVersionLabel();
|
||||
|
@ -203,8 +198,7 @@ ScriptsTool::ScriptsTool() : QDialog(nullptr), ui(new Ui_ScriptsTool)
|
|||
|
||||
delete propertiesView;
|
||||
propertiesView = new QWidget();
|
||||
propertiesView->setSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding);
|
||||
propertiesView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
|
||||
config_t *user_config = obs_frontend_get_user_config();
|
||||
|
@ -215,8 +209,7 @@ ScriptsTool::ScriptsTool() : QDialog(nullptr), ui(new Ui_ScriptsTool)
|
|||
ScriptsTool::~ScriptsTool()
|
||||
{
|
||||
config_t *user_config = obs_frontend_get_user_config();
|
||||
config_set_int(user_config, "scripts-tool", "prevScriptRow",
|
||||
ui->scripts->currentRow());
|
||||
config_set_int(user_config, "scripts-tool", "prevScriptRow", ui->scripts->currentRow());
|
||||
}
|
||||
|
||||
void ScriptsTool::updatePythonVersionLabel()
|
||||
|
@ -225,8 +218,7 @@ void ScriptsTool::updatePythonVersionLabel()
|
|||
if (obs_scripting_python_loaded()) {
|
||||
char version[8];
|
||||
obs_scripting_python_version(version, sizeof(version));
|
||||
label = QString(obs_module_text("PythonSettings.PythonVersion"))
|
||||
.arg(version);
|
||||
label = QString(obs_module_text("PythonSettings.PythonVersion")).arg(version);
|
||||
} else {
|
||||
label = obs_module_text("PythonSettings.PythonNotLoaded");
|
||||
}
|
||||
|
@ -240,8 +232,7 @@ void ScriptsTool::RemoveScript(const char *path)
|
|||
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
if (strcmp(script_path, path) == 0) {
|
||||
scriptData->scripts.erase(scriptData->scripts.begin() +
|
||||
i);
|
||||
scriptData->scripts.erase(scriptData->scripts.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -256,8 +247,7 @@ void ScriptsTool::ReloadScript(const char *path)
|
|||
|
||||
OBSDataAutoRelease settings = obs_data_create();
|
||||
|
||||
obs_properties_t *prop =
|
||||
obs_script_get_properties(script);
|
||||
obs_properties_t *prop = obs_script_get_properties(script);
|
||||
obs_properties_apply_settings(prop, settings);
|
||||
obs_properties_destroy(prop);
|
||||
|
||||
|
@ -285,8 +275,7 @@ void ScriptsTool::SetScriptDefaults(const char *path)
|
|||
for (OBSScript &script : scriptData->scripts) {
|
||||
const char *script_path = obs_script_get_path(script);
|
||||
if (strcmp(script_path, path) == 0) {
|
||||
OBSDataAutoRelease settings =
|
||||
obs_script_get_settings(script);
|
||||
OBSDataAutoRelease settings = obs_script_get_settings(script);
|
||||
obs_data_clear(settings);
|
||||
|
||||
obs_script_update(script, nullptr);
|
||||
|
@ -335,15 +324,13 @@ void ScriptsTool::on_addScripts_clicked()
|
|||
lastBrowsedDir = baseScriptPath;
|
||||
}
|
||||
|
||||
QStringList files = OpenFiles(this,
|
||||
QT_UTF8(obs_module_text("AddScripts")),
|
||||
QT_UTF8(lastBrowsedDir.c_str()), filter);
|
||||
QStringList files =
|
||||
OpenFiles(this, QT_UTF8(obs_module_text("AddScripts")), QT_UTF8(lastBrowsedDir.c_str()), filter);
|
||||
if (!files.count())
|
||||
return;
|
||||
|
||||
for (const QString &file : files) {
|
||||
lastBrowsedDir =
|
||||
QFileInfo(file).absolutePath().toUtf8().constData();
|
||||
lastBrowsedDir = QFileInfo(file).absolutePath().toUtf8().constData();
|
||||
|
||||
QByteArray pathBytes = file.toUtf8();
|
||||
const char *path = pathBytes.constData();
|
||||
|
@ -358,15 +345,13 @@ void ScriptsTool::on_addScripts_clicked()
|
|||
|
||||
scriptData->scripts.emplace_back(script);
|
||||
|
||||
QListWidgetItem *item =
|
||||
new QListWidgetItem(script_file);
|
||||
QListWidgetItem *item = new QListWidgetItem(script_file);
|
||||
item->setData(Qt::UserRole, QString(file));
|
||||
ui->scripts->addItem(item);
|
||||
|
||||
OBSDataAutoRelease settings = obs_data_create();
|
||||
|
||||
obs_properties_t *prop =
|
||||
obs_script_get_properties(script);
|
||||
obs_properties_t *prop = obs_script_get_properties(script);
|
||||
obs_properties_apply_settings(prop, settings);
|
||||
obs_properties_destroy(prop);
|
||||
|
||||
|
@ -380,10 +365,7 @@ void ScriptsTool::on_removeScripts_clicked()
|
|||
QList<QListWidgetItem *> items = ui->scripts->selectedItems();
|
||||
|
||||
for (QListWidgetItem *item : items)
|
||||
RemoveScript(item->data(Qt::UserRole)
|
||||
.toString()
|
||||
.toUtf8()
|
||||
.constData());
|
||||
RemoveScript(item->data(Qt::UserRole).toString().toUtf8().constData());
|
||||
RefreshLists();
|
||||
}
|
||||
|
||||
|
@ -391,10 +373,7 @@ void ScriptsTool::on_reloadScripts_clicked()
|
|||
{
|
||||
QList<QListWidgetItem *> items = ui->scripts->selectedItems();
|
||||
for (QListWidgetItem *item : items)
|
||||
ReloadScript(item->data(Qt::UserRole)
|
||||
.toString()
|
||||
.toUtf8()
|
||||
.constData());
|
||||
ReloadScript(item->data(Qt::UserRole).toString().toUtf8().constData());
|
||||
|
||||
on_scripts_currentRowChanged(ui->scripts->currentRow());
|
||||
}
|
||||
|
@ -405,8 +384,7 @@ void ScriptsTool::OpenScriptParentDirectory()
|
|||
for (QListWidgetItem *item : items) {
|
||||
QDir dir(item->data(Qt::UserRole).toString());
|
||||
dir.cdUp();
|
||||
QDesktopServices::openUrl(
|
||||
QUrl::fromLocalFile(dir.absolutePath()));
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,13 +401,10 @@ void ScriptsTool::on_scripts_customContextMenuRequested(const QPoint &pos)
|
|||
|
||||
if (item) {
|
||||
popup.addSeparator();
|
||||
popup.addAction(obs_module_text("Reload"), this,
|
||||
&ScriptsTool::on_reloadScripts_clicked);
|
||||
popup.addAction(obs_module_text("OpenFileLocation"), this,
|
||||
&ScriptsTool::OpenScriptParentDirectory);
|
||||
popup.addAction(obs_module_text("Reload"), this, &ScriptsTool::on_reloadScripts_clicked);
|
||||
popup.addAction(obs_module_text("OpenFileLocation"), this, &ScriptsTool::OpenScriptParentDirectory);
|
||||
popup.addSeparator();
|
||||
popup.addAction(tr("Remove"), this,
|
||||
&ScriptsTool::on_removeScripts_clicked);
|
||||
popup.addAction(tr("Remove"), this, &ScriptsTool::on_removeScripts_clicked);
|
||||
}
|
||||
obs_frontend_pop_ui_translation();
|
||||
|
||||
|
@ -441,8 +416,7 @@ void ScriptsTool::on_editScript_clicked()
|
|||
int row = ui->scripts->currentRow();
|
||||
if (row == -1)
|
||||
return;
|
||||
QUrl url = QUrl::fromLocalFile(
|
||||
ui->scripts->item(row)->data(Qt::UserRole).toString());
|
||||
QUrl url = QUrl::fromLocalFile(ui->scripts->item(row)->data(Qt::UserRole).toString());
|
||||
QDesktopServices::openUrl(url);
|
||||
}
|
||||
|
||||
|
@ -455,8 +429,7 @@ void ScriptsTool::on_scriptLog_clicked()
|
|||
void ScriptsTool::on_pythonPathBrowse_clicked()
|
||||
{
|
||||
QString curPath = ui->pythonPath->text();
|
||||
QString newPath =
|
||||
SelectDirectory(this, ui->pythonPathLabel->text(), curPath);
|
||||
QString newPath = SelectDirectory(this, ui->pythonPathLabel->text(), curPath);
|
||||
|
||||
if (newPath.isEmpty())
|
||||
return;
|
||||
|
@ -474,14 +447,8 @@ void ScriptsTool::on_pythonPathBrowse_clicked()
|
|||
if (loaded && !newPath.isEmpty() && curPath.compare(newPath) != 0) {
|
||||
char version[8];
|
||||
obs_scripting_python_version(version, sizeof(version));
|
||||
QString message =
|
||||
QString(obs_module_text(
|
||||
"PythonSettings.AlreadyLoaded.Message"))
|
||||
.arg(version);
|
||||
OBSMessageBox::information(
|
||||
this,
|
||||
obs_module_text("PythonSettings.AlreadyLoaded.Title"),
|
||||
message);
|
||||
QString message = QString(obs_module_text("PythonSettings.AlreadyLoaded.Message")).arg(version);
|
||||
OBSMessageBox::information(this, obs_module_text("PythonSettings.AlreadyLoaded.Title"), message);
|
||||
return;
|
||||
} else if (loaded) {
|
||||
return;
|
||||
|
@ -509,15 +476,13 @@ void ScriptsTool::on_scripts_currentRowChanged(int row)
|
|||
|
||||
if (row == -1) {
|
||||
propertiesView = new QWidget();
|
||||
propertiesView->setSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding);
|
||||
propertiesView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
ui->description->setText(QString());
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray array =
|
||||
ui->scripts->item(row)->data(Qt::UserRole).toString().toUtf8();
|
||||
QByteArray array = ui->scripts->item(row)->data(Qt::UserRole).toString().toUtf8();
|
||||
const char *path = array.constData();
|
||||
|
||||
obs_script_t *script = scriptData->FindScript(path);
|
||||
|
@ -528,10 +493,9 @@ void ScriptsTool::on_scripts_currentRowChanged(int row)
|
|||
|
||||
OBSDataAutoRelease settings = obs_script_get_settings(script);
|
||||
|
||||
OBSPropertiesView *view = new OBSPropertiesView(
|
||||
settings.Get(), script,
|
||||
(PropertiesReloadCallback)obs_script_get_properties, nullptr,
|
||||
(PropertiesVisualUpdateCb)obs_script_update);
|
||||
OBSPropertiesView *view = new OBSPropertiesView(settings.Get(), script,
|
||||
(PropertiesReloadCallback)obs_script_get_properties, nullptr,
|
||||
(PropertiesVisualUpdateCb)obs_script_update);
|
||||
view->SetDeferrable(false);
|
||||
|
||||
propertiesView = view;
|
||||
|
@ -546,33 +510,26 @@ void ScriptsTool::on_defaults_clicked()
|
|||
if (!item)
|
||||
return;
|
||||
|
||||
SetScriptDefaults(
|
||||
item->data(Qt::UserRole).toString().toUtf8().constData());
|
||||
SetScriptDefaults(item->data(Qt::UserRole).toString().toUtf8().constData());
|
||||
}
|
||||
|
||||
void ScriptsTool::on_description_linkActivated(const QString &link)
|
||||
{
|
||||
QUrl url(link, QUrl::StrictMode);
|
||||
if (url.isValid() && (url.scheme().compare("http") == 0 ||
|
||||
url.scheme().compare("https") == 0)) {
|
||||
if (url.isValid() && (url.scheme().compare("http") == 0 || url.scheme().compare("https") == 0)) {
|
||||
QString msg(obs_module_text("ScriptDescriptionLink.Text"));
|
||||
msg += "\n\n";
|
||||
msg += QString(obs_module_text(
|
||||
"ScriptDescriptionLink.Text.Url"))
|
||||
.arg(link);
|
||||
msg += QString(obs_module_text("ScriptDescriptionLink.Text.Url")).arg(link);
|
||||
|
||||
const char *open =
|
||||
obs_module_text("ScriptDescriptionLink.OpenURL");
|
||||
const char *open = obs_module_text("ScriptDescriptionLink.OpenURL");
|
||||
|
||||
QMessageBox messageBox(this);
|
||||
messageBox.setWindowTitle(open);
|
||||
messageBox.setText(msg);
|
||||
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
QPushButton *yesButton =
|
||||
messageBox.addButton(open, QMessageBox::YesRole);
|
||||
QPushButton *noButton =
|
||||
messageBox.addButton(tr("Cancel"), QMessageBox::NoRole);
|
||||
QPushButton *yesButton = messageBox.addButton(open, QMessageBox::YesRole);
|
||||
QPushButton *noButton = messageBox.addButton(tr("Cancel"), QMessageBox::NoRole);
|
||||
obs_frontend_pop_ui_translation();
|
||||
messageBox.setDefaultButton(yesButton);
|
||||
messageBox.setEscapeButton(noButton);
|
||||
|
@ -615,8 +572,7 @@ static void obs_event(enum obs_frontend_event event, void *)
|
|||
|
||||
static void load_script_data(obs_data_t *load_data, bool, void *)
|
||||
{
|
||||
OBSDataArrayAutoRelease array =
|
||||
obs_data_get_array(load_data, "scripts-tool");
|
||||
OBSDataArrayAutoRelease array = obs_data_get_array(load_data, "scripts-tool");
|
||||
|
||||
delete scriptData;
|
||||
scriptData = new ScriptData;
|
||||
|
@ -657,20 +613,17 @@ static void save_script_data(obs_data_t *save_data, bool saving, void *)
|
|||
obs_data_set_array(save_data, "scripts-tool", array);
|
||||
}
|
||||
|
||||
static void script_log(void *, obs_script_t *script, int log_level,
|
||||
const char *message)
|
||||
static void script_log(void *, obs_script_t *script, int log_level, const char *message)
|
||||
{
|
||||
QString qmsg;
|
||||
|
||||
if (script) {
|
||||
qmsg = QStringLiteral("[%1] %2").arg(
|
||||
obs_script_get_file(script), message);
|
||||
qmsg = QStringLiteral("[%1] %2").arg(obs_script_get_file(script), message);
|
||||
} else {
|
||||
qmsg = QStringLiteral("[Unknown Script] %1").arg(message);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(scriptLogWindow, "AddLogMsg",
|
||||
Q_ARG(int, log_level), Q_ARG(QString, qmsg));
|
||||
QMetaObject::invokeMethod(scriptLogWindow, "AddLogMsg", Q_ARG(int, log_level), Q_ARG(QString, qmsg));
|
||||
}
|
||||
|
||||
extern "C" void InitScripts()
|
||||
|
@ -680,24 +633,20 @@ extern "C" void InitScripts()
|
|||
obs_scripting_load();
|
||||
obs_scripting_set_log_callback(script_log, nullptr);
|
||||
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(
|
||||
obs_module_text("Scripts"));
|
||||
QAction *action = (QAction *)obs_frontend_add_tools_menu_qaction(obs_module_text("Scripts"));
|
||||
|
||||
#if PYTHON_UI
|
||||
config_t *config = obs_frontend_get_user_config();
|
||||
const char *python_path =
|
||||
config_get_string(config, "Python", "Path" ARCH_NAME);
|
||||
const char *python_path = config_get_string(config, "Python", "Path" ARCH_NAME);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (python_path && *python_path) {
|
||||
std::string _python_path(python_path);
|
||||
std::size_t pos =
|
||||
_python_path.find("/Python.framework/Versions");
|
||||
std::size_t pos = _python_path.find("/Python.framework/Versions");
|
||||
|
||||
if (pos != std::string::npos) {
|
||||
std::string _temp = _python_path.substr(0, pos);
|
||||
config_set_string(config, "Python", "Path" ARCH_NAME,
|
||||
_temp.c_str());
|
||||
config_set_string(config, "Python", "Path" ARCH_NAME, _temp.c_str());
|
||||
config_save(config);
|
||||
python_path = _temp.c_str();
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ void censorRecurse(obs_data_t *data)
|
|||
censorRecurse(child_data);
|
||||
obs_data_release(child_data);
|
||||
} else if (typ == OBS_DATA_ARRAY) {
|
||||
obs_data_array_t *child_array =
|
||||
obs_data_item_get_array(item);
|
||||
obs_data_array_t *child_array = obs_data_item_get_array(item);
|
||||
censorRecurseArray(child_array);
|
||||
obs_data_array_release(child_array);
|
||||
}
|
||||
|
@ -55,8 +54,7 @@ QString censoredJson(obs_data_t *data, bool pretty)
|
|||
censorRecurse(clone);
|
||||
|
||||
// Turn our copy into JSON
|
||||
QString s = pretty ? obs_data_get_json_pretty(clone)
|
||||
: obs_data_get_json(clone);
|
||||
QString s = pretty ? obs_data_get_json_pretty(clone) : obs_data_get_json(clone);
|
||||
|
||||
// Eliminate our copy
|
||||
obs_data_release(clone);
|
||||
|
|
|
@ -17,8 +17,7 @@ using json = nlohmann::json;
|
|||
|
||||
Qt::ConnectionType BlockingConnectionTypeFor(QObject *object);
|
||||
|
||||
void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json,
|
||||
const GoLiveApi::Config &config)
|
||||
void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json, const GoLiveApi::Config &config)
|
||||
{
|
||||
using GoLiveApi::StatusResult;
|
||||
|
||||
|
@ -36,17 +35,12 @@ void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json,
|
|||
[=] {
|
||||
QMessageBox mb(parent);
|
||||
mb.setIcon(QMessageBox::Warning);
|
||||
mb.setWindowTitle(QTStr(
|
||||
"ConfigDownload.WarningMessageTitle"));
|
||||
mb.setWindowTitle(QTStr("ConfigDownload.WarningMessageTitle"));
|
||||
mb.setTextFormat(Qt::RichText);
|
||||
mb.setText(
|
||||
message +
|
||||
QTStr("FailedToStartStream.WarningRetry"));
|
||||
mb.setStandardButtons(
|
||||
QMessageBox::StandardButton::Yes |
|
||||
QMessageBox::StandardButton::No);
|
||||
return mb.exec() ==
|
||||
QMessageBox::StandardButton::No;
|
||||
mb.setText(message + QTStr("FailedToStartStream.WarningRetry"));
|
||||
mb.setStandardButtons(QMessageBox::StandardButton::Yes |
|
||||
QMessageBox::StandardButton::No);
|
||||
return mb.exec() == QMessageBox::StandardButton::No;
|
||||
},
|
||||
BlockingConnectionTypeFor(parent), &ret);
|
||||
if (ret)
|
||||
|
@ -54,66 +48,52 @@ void HandleGoLiveApiErrors(QWidget *parent, const json &raw_json,
|
|||
};
|
||||
|
||||
auto missing_html = [] {
|
||||
return QTStr("FailedToStartStream.StatusMissingHTML")
|
||||
.toStdString();
|
||||
return QTStr("FailedToStartStream.StatusMissingHTML").toStdString();
|
||||
};
|
||||
|
||||
if (status.result == StatusResult::Unknown) {
|
||||
return warn_continue(
|
||||
QTStr("FailedToStartStream.WarningUnknownStatus")
|
||||
.arg(raw_json["status"]["result"]
|
||||
.dump()
|
||||
.c_str()));
|
||||
return warn_continue(QTStr("FailedToStartStream.WarningUnknownStatus")
|
||||
.arg(raw_json["status"]["result"].dump().c_str()));
|
||||
|
||||
} else if (status.result == StatusResult::Warning) {
|
||||
if (config.encoder_configurations.empty()) {
|
||||
throw MultitrackVideoError::warning(
|
||||
status.html_en_us.value_or(missing_html())
|
||||
.c_str());
|
||||
throw MultitrackVideoError::warning(status.html_en_us.value_or(missing_html()).c_str());
|
||||
}
|
||||
|
||||
return warn_continue(
|
||||
status.html_en_us.value_or(missing_html()).c_str());
|
||||
return warn_continue(status.html_en_us.value_or(missing_html()).c_str());
|
||||
} else if (status.result == StatusResult::Error) {
|
||||
throw MultitrackVideoError::critical(
|
||||
status.html_en_us.value_or(missing_html()).c_str());
|
||||
throw MultitrackVideoError::critical(status.html_en_us.value_or(missing_html()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url,
|
||||
const GoLiveApi::PostData &post_data,
|
||||
GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url, const GoLiveApi::PostData &post_data,
|
||||
const QString &multitrack_video_name)
|
||||
{
|
||||
json post_data_json = post_data;
|
||||
blog(LOG_INFO, "Go live POST data: %s",
|
||||
censoredJson(post_data_json).toUtf8().constData());
|
||||
blog(LOG_INFO, "Go live POST data: %s", censoredJson(post_data_json).toUtf8().constData());
|
||||
|
||||
if (url.isEmpty())
|
||||
throw MultitrackVideoError::critical(
|
||||
QTStr("FailedToStartStream.MissingConfigURL"));
|
||||
throw MultitrackVideoError::critical(QTStr("FailedToStartStream.MissingConfigURL"));
|
||||
|
||||
std::string encodeConfigText;
|
||||
std::string libraryError;
|
||||
|
||||
std::vector<std::string> headers;
|
||||
headers.push_back("Content-Type: application/json");
|
||||
bool encodeConfigDownloadedOk = GetRemoteFile(
|
||||
url.toLocal8Bit(), encodeConfigText,
|
||||
libraryError, // out params
|
||||
nullptr,
|
||||
nullptr, // out params (response code and content type)
|
||||
"POST", post_data_json.dump().c_str(), headers,
|
||||
nullptr, // signature
|
||||
5); // timeout in seconds
|
||||
bool encodeConfigDownloadedOk = GetRemoteFile(url.toLocal8Bit(), encodeConfigText,
|
||||
libraryError, // out params
|
||||
nullptr,
|
||||
nullptr, // out params (response code and content type)
|
||||
"POST", post_data_json.dump().c_str(), headers,
|
||||
nullptr, // signature
|
||||
5); // timeout in seconds
|
||||
|
||||
if (!encodeConfigDownloadedOk)
|
||||
throw MultitrackVideoError::warning(
|
||||
QTStr("FailedToStartStream.ConfigRequestFailed")
|
||||
.arg(url, libraryError.c_str()));
|
||||
QTStr("FailedToStartStream.ConfigRequestFailed").arg(url, libraryError.c_str()));
|
||||
try {
|
||||
auto data = json::parse(encodeConfigText);
|
||||
blog(LOG_INFO, "Go live response data: %s",
|
||||
censoredJson(data, true).toUtf8().constData());
|
||||
blog(LOG_INFO, "Go live response data: %s", censoredJson(data, true).toUtf8().constData());
|
||||
GoLiveApi::Config config = data;
|
||||
HandleGoLiveApiErrors(parent, data, config);
|
||||
return config;
|
||||
|
@ -121,19 +101,16 @@ GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url,
|
|||
} catch (const json::exception &e) {
|
||||
blog(LOG_INFO, "Failed to parse go live config: %s", e.what());
|
||||
throw MultitrackVideoError::warning(
|
||||
QTStr("FailedToStartStream.FallbackToDefault")
|
||||
.arg(multitrack_video_name));
|
||||
QTStr("FailedToStartStream.FallbackToDefault").arg(multitrack_video_name));
|
||||
}
|
||||
}
|
||||
|
||||
QString MultitrackVideoAutoConfigURL(obs_service_t *service)
|
||||
{
|
||||
static const std::optional<QString> cli_url =
|
||||
[]() -> std::optional<QString> {
|
||||
static const std::optional<QString> cli_url = []() -> std::optional<QString> {
|
||||
auto args = qApp->arguments();
|
||||
for (int i = 0; i < args.length() - 1; i++) {
|
||||
if (args[i] == "--config-url" &&
|
||||
args.length() > (i + 1)) {
|
||||
if (args[i] == "--config-url" && args.length() > (i + 1)) {
|
||||
return args[i + 1];
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +122,7 @@ QString MultitrackVideoAutoConfigURL(obs_service_t *service)
|
|||
url = *cli_url;
|
||||
} else {
|
||||
OBSDataAutoRelease settings = obs_service_get_settings(service);
|
||||
url = obs_data_get_string(settings,
|
||||
"multitrack_video_configuration_url");
|
||||
url = obs_data_get_string(settings, "multitrack_video_configuration_url");
|
||||
}
|
||||
|
||||
blog(LOG_INFO, "Go live URL: %s", url.toUtf8().constData());
|
||||
|
|
|
@ -10,6 +10,5 @@ QString MultitrackVideoAutoConfigURL(obs_service_t *service);
|
|||
|
||||
class QWidget;
|
||||
|
||||
GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url,
|
||||
const GoLiveApi::PostData &post_data,
|
||||
GoLiveApi::Config DownloadGoLiveConfig(QWidget *parent, QString url, const GoLiveApi::PostData &post_data,
|
||||
const QString &multitrack_video_name);
|
||||
|
|
|
@ -6,11 +6,8 @@
|
|||
|
||||
#include "models/multitrack-video.hpp"
|
||||
|
||||
GoLiveApi::PostData
|
||||
constructGoLivePost(QString streamKey,
|
||||
const std::optional<uint64_t> &maximum_aggregate_bitrate,
|
||||
const std::optional<uint32_t> &maximum_video_tracks,
|
||||
bool vod_track_enabled)
|
||||
GoLiveApi::PostData constructGoLivePost(QString streamKey, const std::optional<uint64_t> &maximum_aggregate_bitrate,
|
||||
const std::optional<uint32_t> &maximum_video_tracks, bool vod_track_enabled)
|
||||
{
|
||||
GoLiveApi::PostData post_data{};
|
||||
post_data.service = "IVS";
|
||||
|
@ -25,8 +22,7 @@ constructGoLivePost(QString streamKey,
|
|||
client.version = obs_get_version_string();
|
||||
|
||||
auto add_codec = [&](const char *codec) {
|
||||
auto it = std::find(std::begin(client.supported_codecs),
|
||||
std::end(client.supported_codecs), codec);
|
||||
auto it = std::find(std::begin(client.supported_codecs), std::end(client.supported_codecs), codec);
|
||||
if (it != std::end(client.supported_codecs))
|
||||
return;
|
||||
|
||||
|
@ -67,8 +63,7 @@ constructGoLivePost(QString streamKey,
|
|||
}
|
||||
|
||||
if (maximum_aggregate_bitrate.has_value())
|
||||
preferences.maximum_aggregate_bitrate =
|
||||
maximum_aggregate_bitrate.value();
|
||||
preferences.maximum_aggregate_bitrate = maximum_aggregate_bitrate.value();
|
||||
if (maximum_video_tracks.has_value())
|
||||
preferences.maximum_video_tracks = maximum_video_tracks.value();
|
||||
|
||||
|
|
|
@ -5,8 +5,5 @@
|
|||
#include <QString>
|
||||
#include "models/multitrack-video.hpp"
|
||||
|
||||
GoLiveApi::PostData
|
||||
constructGoLivePost(QString streamKey,
|
||||
const std::optional<uint64_t> &maximum_aggregate_bitrate,
|
||||
const std::optional<uint32_t> &maximum_video_tracks,
|
||||
bool vod_track_enabled);
|
||||
GoLiveApi::PostData constructGoLivePost(QString streamKey, const std::optional<uint64_t> &maximum_aggregate_bitrate,
|
||||
const std::optional<uint32_t> &maximum_video_tracks, bool vod_track_enabled);
|
||||
|
|
|
@ -49,12 +49,10 @@ void OBSHotkeyEdit::keyPressEvent(QKeyEvent *event)
|
|||
#endif
|
||||
|
||||
default:
|
||||
new_key.key =
|
||||
obs_key_from_virtual_key(event->nativeVirtualKey());
|
||||
new_key.key = obs_key_from_virtual_key(event->nativeVirtualKey());
|
||||
}
|
||||
|
||||
new_key.modifiers =
|
||||
TranslateQtKeyboardEventModifiers(event->modifiers());
|
||||
new_key.modifiers = TranslateQtKeyboardEventModifiers(event->modifiers());
|
||||
|
||||
HandleNewKey(new_key);
|
||||
}
|
||||
|
@ -81,8 +79,7 @@ void OBSHotkeyEdit::keyReleaseEvent(QKeyEvent *event)
|
|||
|
||||
// kVK_CapsLock == 57
|
||||
new_key.key = obs_key_from_virtual_key(57);
|
||||
new_key.modifiers =
|
||||
TranslateQtKeyboardEventModifiers(event->modifiers());
|
||||
new_key.modifiers = TranslateQtKeyboardEventModifiers(event->modifiers());
|
||||
|
||||
HandleNewKey(new_key);
|
||||
}
|
||||
|
@ -135,8 +132,7 @@ void OBSHotkeyEdit::mousePressEvent(QMouseEvent *event)
|
|||
#undef MAP_BUTTON
|
||||
}
|
||||
|
||||
new_key.modifiers =
|
||||
TranslateQtKeyboardEventModifiers(event->modifiers());
|
||||
new_key.modifiers = TranslateQtKeyboardEventModifiers(event->modifiers());
|
||||
|
||||
HandleNewKey(new_key);
|
||||
}
|
||||
|
@ -198,22 +194,19 @@ void OBSHotkeyEdit::UpdateDuplicationState()
|
|||
|
||||
void OBSHotkeyEdit::InitSignalHandler()
|
||||
{
|
||||
layoutChanged = {
|
||||
obs_get_signal_handler(), "hotkey_layout_change",
|
||||
[](void *this_, calldata_t *) {
|
||||
auto edit = static_cast<OBSHotkeyEdit *>(this_);
|
||||
QMetaObject::invokeMethod(edit, "ReloadKeyLayout");
|
||||
},
|
||||
this};
|
||||
layoutChanged = {obs_get_signal_handler(), "hotkey_layout_change",
|
||||
[](void *this_, calldata_t *) {
|
||||
auto edit = static_cast<OBSHotkeyEdit *>(this_);
|
||||
QMetaObject::invokeMethod(edit, "ReloadKeyLayout");
|
||||
},
|
||||
this};
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::CreateDupeIcon()
|
||||
{
|
||||
dupeIcon = addAction(settings->GetHotkeyConflictIcon(),
|
||||
ActionPosition::TrailingPosition);
|
||||
dupeIcon = addAction(settings->GetHotkeyConflictIcon(), ActionPosition::TrailingPosition);
|
||||
dupeIcon->setToolTip(QTStr("Basic.Settings.Hotkeys.DuplicateWarning"));
|
||||
QObject::connect(dupeIcon, &QAction::triggered,
|
||||
[=] { emit SearchKey(key); });
|
||||
QObject::connect(dupeIcon, &QAction::triggered, [=] { emit SearchKey(key); });
|
||||
dupeIcon->setVisible(false);
|
||||
}
|
||||
|
||||
|
@ -222,8 +215,7 @@ void OBSHotkeyEdit::ReloadKeyLayout()
|
|||
RenderKey();
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::SetKeyCombinations(
|
||||
const std::vector<obs_key_combination_t> &combos)
|
||||
void OBSHotkeyWidget::SetKeyCombinations(const std::vector<obs_key_combination_t> &combos)
|
||||
{
|
||||
if (combos.empty())
|
||||
AddEdit({0, OBS_KEY_NONE});
|
||||
|
@ -234,9 +226,7 @@ void OBSHotkeyWidget::SetKeyCombinations(
|
|||
|
||||
bool OBSHotkeyWidget::Changed() const
|
||||
{
|
||||
return changed ||
|
||||
std::any_of(begin(edits), end(edits),
|
||||
[](OBSHotkeyEdit *edit) { return edit->changed; });
|
||||
return changed || std::any_of(begin(edits), end(edits), [](OBSHotkeyEdit *edit) { return edit->changed; });
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::Apply()
|
||||
|
@ -252,8 +242,7 @@ void OBSHotkeyWidget::Apply()
|
|||
revertButton->setEnabled(false);
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::GetCombinations(
|
||||
std::vector<obs_key_combination_t> &combinations) const
|
||||
void OBSHotkeyWidget::GetCombinations(std::vector<obs_key_combination_t> &combinations) const
|
||||
{
|
||||
combinations.clear();
|
||||
for (auto &edit : edits)
|
||||
|
@ -275,16 +264,14 @@ void OBSHotkeyWidget::Save(std::vector<obs_key_combination_t> &combinations)
|
|||
auto AtomicUpdate = [&]() {
|
||||
ignoreChangedBindings = true;
|
||||
|
||||
obs_hotkey_load_bindings(id, combinations.data(),
|
||||
combinations.size());
|
||||
obs_hotkey_load_bindings(id, combinations.data(), combinations.size());
|
||||
|
||||
ignoreChangedBindings = false;
|
||||
};
|
||||
using AtomicUpdate_t = decltype(&AtomicUpdate);
|
||||
|
||||
obs_hotkey_update_atomic(
|
||||
[](void *d) { (*static_cast<AtomicUpdate_t>(d))(); },
|
||||
static_cast<void *>(&AtomicUpdate));
|
||||
obs_hotkey_update_atomic([](void *d) { (*static_cast<AtomicUpdate_t>(d))(); },
|
||||
static_cast<void *>(&AtomicUpdate));
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
||||
|
@ -302,13 +289,10 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
|||
clear->setToolTip(QTStr("Clear"));
|
||||
clear->setEnabled(!obs_key_combination_is_empty(combo));
|
||||
|
||||
QObject::connect(
|
||||
edit, &OBSHotkeyEdit::KeyChanged,
|
||||
[=](obs_key_combination_t new_combo) {
|
||||
clear->setEnabled(
|
||||
!obs_key_combination_is_empty(new_combo));
|
||||
revert->setEnabled(edit->original != new_combo);
|
||||
});
|
||||
QObject::connect(edit, &OBSHotkeyEdit::KeyChanged, [=](obs_key_combination_t new_combo) {
|
||||
clear->setEnabled(!obs_key_combination_is_empty(new_combo));
|
||||
revert->setEnabled(edit->original != new_combo);
|
||||
});
|
||||
|
||||
auto add = new QPushButton;
|
||||
add->setProperty("class", "icon-plus");
|
||||
|
@ -320,8 +304,7 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
|||
remove->setEnabled(removeButtons.size() > 0);
|
||||
|
||||
auto CurrentIndex = [&, remove] {
|
||||
auto res = std::find(begin(removeButtons), end(removeButtons),
|
||||
remove);
|
||||
auto res = std::find(begin(removeButtons), end(removeButtons), remove);
|
||||
return std::distance(begin(removeButtons), res);
|
||||
};
|
||||
|
||||
|
@ -329,8 +312,7 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
|||
AddEdit({0, OBS_KEY_NONE}, CurrentIndex() + 1);
|
||||
});
|
||||
|
||||
QObject::connect(remove, &QPushButton::clicked,
|
||||
[&, CurrentIndex] { RemoveEdit(CurrentIndex()); });
|
||||
QObject::connect(remove, &QPushButton::clicked, [&, CurrentIndex] { RemoveEdit(CurrentIndex()); });
|
||||
|
||||
QHBoxLayout *subLayout = new QHBoxLayout;
|
||||
subLayout->setContentsMargins(0, 2, 0, 2);
|
||||
|
@ -355,17 +337,11 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
|||
|
||||
layout()->insertLayout(idx, subLayout);
|
||||
|
||||
QObject::connect(revert, &QPushButton::clicked, edit,
|
||||
&OBSHotkeyEdit::ResetKey);
|
||||
QObject::connect(clear, &QPushButton::clicked, edit,
|
||||
&OBSHotkeyEdit::ClearKey);
|
||||
QObject::connect(revert, &QPushButton::clicked, edit, &OBSHotkeyEdit::ResetKey);
|
||||
QObject::connect(clear, &QPushButton::clicked, edit, &OBSHotkeyEdit::ClearKey);
|
||||
|
||||
QObject::connect(edit, &OBSHotkeyEdit::KeyChanged,
|
||||
[&](obs_key_combination) { emit KeyChanged(); });
|
||||
QObject::connect(edit, &OBSHotkeyEdit::SearchKey,
|
||||
[=](obs_key_combination combo) {
|
||||
emit SearchKey(combo);
|
||||
});
|
||||
QObject::connect(edit, &OBSHotkeyEdit::KeyChanged, [&](obs_key_combination) { emit KeyChanged(); });
|
||||
QObject::connect(edit, &OBSHotkeyEdit::SearchKey, [=](obs_key_combination combo) { emit SearchKey(combo); });
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::RemoveEdit(size_t idx, bool signal)
|
||||
|
@ -398,8 +374,7 @@ void OBSHotkeyWidget::BindingsChanged(void *data, calldata_t *param)
|
|||
auto widget = static_cast<OBSHotkeyWidget *>(data);
|
||||
auto key = static_cast<obs_hotkey_t *>(calldata_ptr(param, "key"));
|
||||
|
||||
QMetaObject::invokeMethod(widget, "HandleChangedBindings",
|
||||
Q_ARG(obs_hotkey_id, obs_hotkey_get_id(key)));
|
||||
QMetaObject::invokeMethod(widget, "HandleChangedBindings", Q_ARG(obs_hotkey_id, obs_hotkey_get_id(key)));
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::HandleChangedBindings(obs_hotkey_id id_)
|
||||
|
|
|
@ -27,14 +27,12 @@
|
|||
|
||||
#include <obs.hpp>
|
||||
|
||||
static inline bool operator!=(const obs_key_combination_t &c1,
|
||||
const obs_key_combination_t &c2)
|
||||
static inline bool operator!=(const obs_key_combination_t &c1, const obs_key_combination_t &c2)
|
||||
{
|
||||
return c1.modifiers != c2.modifiers || c1.key != c2.key;
|
||||
}
|
||||
|
||||
static inline bool operator==(const obs_key_combination_t &c1,
|
||||
const obs_key_combination_t &c2)
|
||||
static inline bool operator==(const obs_key_combination_t &c1, const obs_key_combination_t &c2)
|
||||
{
|
||||
return !(c1 != c2);
|
||||
}
|
||||
|
@ -58,8 +56,7 @@ class OBSHotkeyEdit : public QLineEdit {
|
|||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
OBSHotkeyEdit(QWidget *parent, obs_key_combination_t original,
|
||||
OBSBasicSettings *settings)
|
||||
OBSHotkeyEdit(QWidget *parent, obs_key_combination_t original, OBSBasicSettings *settings)
|
||||
: QLineEdit(parent),
|
||||
original(original),
|
||||
settings(settings)
|
||||
|
@ -74,10 +71,7 @@ public:
|
|||
InitSignalHandler();
|
||||
ResetKey();
|
||||
}
|
||||
OBSHotkeyEdit(QWidget *parent = nullptr)
|
||||
: QLineEdit(parent),
|
||||
original({}),
|
||||
settings(nullptr)
|
||||
OBSHotkeyEdit(QWidget *parent = nullptr) : QLineEdit(parent), original({}), settings(nullptr)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// disable the input cursor on OSX, focus should be clear
|
||||
|
@ -129,14 +123,12 @@ class OBSHotkeyWidget : public QWidget {
|
|||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
OBSHotkeyWidget(QWidget *parent, obs_hotkey_id id, std::string name,
|
||||
OBSBasicSettings *settings,
|
||||
OBSHotkeyWidget(QWidget *parent, obs_hotkey_id id, std::string name, OBSBasicSettings *settings,
|
||||
const std::vector<obs_key_combination_t> &combos = {})
|
||||
: QWidget(parent),
|
||||
id(id),
|
||||
name(name),
|
||||
bindingsChanged(obs_get_signal_handler(),
|
||||
"hotkey_bindings_changed",
|
||||
bindingsChanged(obs_get_signal_handler(), "hotkey_bindings_changed",
|
||||
&OBSHotkeyWidget::BindingsChanged, this),
|
||||
settings(settings)
|
||||
{
|
||||
|
@ -187,10 +179,7 @@ private:
|
|||
bool ignoreChangedBindings = false;
|
||||
OBSBasicSettings *settings;
|
||||
|
||||
QVBoxLayout *layout() const
|
||||
{
|
||||
return dynamic_cast<QVBoxLayout *>(QWidget::layout());
|
||||
}
|
||||
QVBoxLayout *layout() const { return dynamic_cast<QVBoxLayout *>(QWidget::layout()); }
|
||||
|
||||
private slots:
|
||||
void HandleChangedBindings(obs_hotkey_id id_);
|
||||
|
|
|
@ -33,11 +33,9 @@ static bool source_name_exists(const Json::array &sources, const string &name)
|
|||
return false;
|
||||
}
|
||||
|
||||
#define translate_int(in_key, in, out_key, out, off) \
|
||||
out[out_key] = in[in_key].int_value() + off;
|
||||
#define translate_int(in_key, in, out_key, out, off) out[out_key] = in[in_key].int_value() + off;
|
||||
#define translate_string(in_key, in, out_key, out) out[out_key] = in[in_key];
|
||||
#define translate_bool(in_key, in, out_key, out) \
|
||||
out[out_key] = in[in_key].int_value() == 1;
|
||||
#define translate_bool(in_key, in, out_key, out) out[out_key] = in[in_key].int_value() == 1;
|
||||
|
||||
static Json::object translate_scene_item(const Json &in, const Json &source)
|
||||
{
|
||||
|
@ -122,22 +120,15 @@ static Json::object translate_source(const Json &in, const Json &sources)
|
|||
settings["outline_color"] = color;
|
||||
|
||||
translate_string("text", in_settings, "text", settings);
|
||||
translate_int("backgroundOpacity", in_settings, "bk_opacity",
|
||||
settings, 0);
|
||||
translate_int("backgroundOpacity", in_settings, "bk_opacity", settings, 0);
|
||||
translate_bool("vertical", in_settings, "vertical", settings);
|
||||
translate_int("textOpacity", in_settings, "opacity", settings,
|
||||
0);
|
||||
translate_int("textOpacity", in_settings, "opacity", settings, 0);
|
||||
translate_bool("useOutline", in_settings, "outline", settings);
|
||||
translate_int("outlineOpacity", in_settings, "outline_opacity",
|
||||
settings, 0);
|
||||
translate_int("outlineSize", in_settings, "outline_size",
|
||||
settings, 0);
|
||||
translate_bool("useTextExtents", in_settings, "extents",
|
||||
settings);
|
||||
translate_int("extentWidth", in_settings, "extents_cx",
|
||||
settings, 0);
|
||||
translate_int("extentHeight", in_settings, "extents_cy",
|
||||
settings, 0);
|
||||
translate_int("outlineOpacity", in_settings, "outline_opacity", settings, 0);
|
||||
translate_int("outlineSize", in_settings, "outline_size", settings, 0);
|
||||
translate_bool("useTextExtents", in_settings, "extents", settings);
|
||||
translate_int("extentWidth", in_settings, "extents_cx", settings, 0);
|
||||
translate_int("extentHeight", in_settings, "extents_cy", settings, 0);
|
||||
translate_bool("mode", in_settings, "read_from_file", settings);
|
||||
translate_bool("wrap", in_settings, "extents_wrap", settings);
|
||||
|
||||
|
@ -145,9 +136,7 @@ static Json::object translate_source(const Json &in, const Json &sources)
|
|||
settings["file"] = StringReplace(str, "\\\\", "/");
|
||||
|
||||
int in_align = in_settings["align"].int_value();
|
||||
string align = in_align == 0
|
||||
? "left"
|
||||
: (in_align == 1 ? "center" : "right");
|
||||
string align = in_align == 0 ? "left" : (in_align == 1 ? "center" : "right");
|
||||
|
||||
settings["align"] = align;
|
||||
|
||||
|
@ -181,8 +170,7 @@ static Json::object translate_source(const Json &in, const Json &sources)
|
|||
out["id"] = "monitor_capture";
|
||||
|
||||
translate_int("monitor", in_settings, "monitor", settings, 0);
|
||||
translate_bool("captureMouse", in_settings, "capture_cursor",
|
||||
settings);
|
||||
translate_bool("captureMouse", in_settings, "capture_cursor", settings);
|
||||
} else if (id == "BitmapImageSource") {
|
||||
out["id"] = "image_source";
|
||||
|
||||
|
@ -214,10 +202,7 @@ static Json::object translate_source(const Json &in, const Json &sources)
|
|||
out["id"] = "browser_source";
|
||||
|
||||
string browser_dec =
|
||||
QByteArray::fromBase64(in_settings["sourceSettings"]
|
||||
.string_value()
|
||||
.c_str())
|
||||
.toStdString();
|
||||
QByteArray::fromBase64(in_settings["sourceSettings"].string_value().c_str()).toStdString();
|
||||
|
||||
string err;
|
||||
|
||||
|
@ -258,8 +243,7 @@ static Json::object translate_source(const Json &in, const Json &sources)
|
|||
|
||||
settings["window"] = ":" + winClass + ":" + exec;
|
||||
|
||||
translate_bool("captureMouse", in_settings, "capture_cursor",
|
||||
settings);
|
||||
translate_bool("captureMouse", in_settings, "capture_cursor", settings);
|
||||
}
|
||||
|
||||
out["settings"] = settings;
|
||||
|
@ -303,10 +287,8 @@ static void translate_sc(const Json &in, Json &out)
|
|||
for (size_t x = sources.size(); x > 0; x--) {
|
||||
Json source = sources[x - 1];
|
||||
|
||||
Json::object out_source =
|
||||
translate_source(source, out_sources);
|
||||
Json::object out_item =
|
||||
translate_scene_item(source, out_source);
|
||||
Json::object out_source = translate_source(source, out_sources);
|
||||
Json::object out_item = translate_scene_item(source, out_source);
|
||||
|
||||
out_item["id"] = (int)x - 1;
|
||||
|
||||
|
@ -316,12 +298,10 @@ static void translate_sc(const Json &in, Json &out)
|
|||
out_sources.push_back(out_source);
|
||||
}
|
||||
|
||||
out_sources.push_back(Json::object{
|
||||
{"id", "scene"},
|
||||
{"name", in_scene["name"]},
|
||||
{"settings",
|
||||
Json::object{{"items", items},
|
||||
{"id_counter", (int)items.size()}}}});
|
||||
out_sources.push_back(
|
||||
Json::object{{"id", "scene"},
|
||||
{"name", in_scene["name"]},
|
||||
{"settings", Json::object{{"items", items}, {"id_counter", (int)items.size()}}}});
|
||||
}
|
||||
|
||||
res["current_scene"] = first_name;
|
||||
|
@ -332,8 +312,7 @@ static void translate_sc(const Json &in, Json &out)
|
|||
out = res;
|
||||
}
|
||||
|
||||
static void create_string(const string &name, Json::object &out,
|
||||
const string &data)
|
||||
static void create_string(const string &name, Json::object &out, const string &data)
|
||||
{
|
||||
string str = StringReplace(data, "\\\\", "/");
|
||||
out[name] = str;
|
||||
|
@ -346,15 +325,13 @@ static void create_string_obj(const string &data, Json::array &arr)
|
|||
arr.push_back(obj);
|
||||
}
|
||||
|
||||
static void create_double(const string &name, Json::object &out,
|
||||
const string &data)
|
||||
static void create_double(const string &name, Json::object &out, const string &data)
|
||||
{
|
||||
double d = atof(data.c_str());
|
||||
out[name] = d;
|
||||
}
|
||||
|
||||
static void create_int(const string &name, Json::object &out,
|
||||
const string &data)
|
||||
static void create_int(const string &name, Json::object &out, const string &data)
|
||||
{
|
||||
int i = atoi(data.c_str());
|
||||
out[name] = i;
|
||||
|
@ -376,8 +353,7 @@ static void create_data_item(Json::object &out, const string &line)
|
|||
|
||||
string first = line.substr(end_pos + 3);
|
||||
|
||||
if ((first[0] >= 'A' && first[0] <= 'Z') ||
|
||||
(first[0] >= 'a' && first[0] <= 'z') || first[0] == '\\' ||
|
||||
if ((first[0] >= 'A' && first[0] <= 'Z') || (first[0] >= 'a' && first[0] <= 'z') || first[0] == '\\' ||
|
||||
first[0] == '/') {
|
||||
if (out.find(c_name) != out.end()) {
|
||||
Json::array arr = out[c_name].array_items();
|
||||
|
@ -515,8 +491,7 @@ int ClassicImporter::ImportScenes(const string &path, string &name, Json &res)
|
|||
string line = ReadLine(file);
|
||||
|
||||
while (!line.empty() && line[0] != '\0') {
|
||||
string key = line != "global sources : {" ? "scenes"
|
||||
: "globals";
|
||||
string key = line != "global sources : {" ? "scenes" : "globals";
|
||||
|
||||
Json::array arr = create_sources(data, line, file);
|
||||
data[key] = arr;
|
||||
|
|
|
@ -32,8 +32,7 @@ void ImportersInit()
|
|||
importers.push_back(make_unique<XSplitImporter>());
|
||||
}
|
||||
|
||||
int ImportSCFromProg(const string &path, string &name, const string &program,
|
||||
Json &res)
|
||||
int ImportSCFromProg(const string &path, string &name, const string &program, Json &res)
|
||||
{
|
||||
if (!os_file_exists(path.c_str())) {
|
||||
return IMPORTER_FILE_NOT_FOUND;
|
||||
|
|
|
@ -41,8 +41,7 @@ class Importer {
|
|||
public:
|
||||
virtual ~Importer() {}
|
||||
virtual std::string Prog() { return "Null"; };
|
||||
virtual int ImportScenes(const std::string &path, std::string &name,
|
||||
json11::Json &res) = 0;
|
||||
virtual int ImportScenes(const std::string &path, std::string &name, json11::Json &res) = 0;
|
||||
virtual bool Check(const std::string &path) = 0;
|
||||
virtual std::string Name(const std::string &path) = 0;
|
||||
virtual OBSImporterFiles FindFiles()
|
||||
|
@ -55,8 +54,7 @@ public:
|
|||
class ClassicImporter : public Importer {
|
||||
public:
|
||||
std::string Prog() { return "OBSClassic"; };
|
||||
int ImportScenes(const std::string &path, std::string &name,
|
||||
json11::Json &res);
|
||||
int ImportScenes(const std::string &path, std::string &name, json11::Json &res);
|
||||
bool Check(const std::string &path);
|
||||
std::string Name(const std::string &path);
|
||||
OBSImporterFiles FindFiles();
|
||||
|
@ -65,8 +63,7 @@ public:
|
|||
class StudioImporter : public Importer {
|
||||
public:
|
||||
std::string Prog() { return "OBSStudio"; };
|
||||
int ImportScenes(const std::string &path, std::string &name,
|
||||
json11::Json &res);
|
||||
int ImportScenes(const std::string &path, std::string &name, json11::Json &res);
|
||||
bool Check(const std::string &path);
|
||||
std::string Name(const std::string &path);
|
||||
};
|
||||
|
@ -74,8 +71,7 @@ public:
|
|||
class SLImporter : public Importer {
|
||||
public:
|
||||
std::string Prog() { return "Streamlabs"; };
|
||||
int ImportScenes(const std::string &path, std::string &name,
|
||||
json11::Json &res);
|
||||
int ImportScenes(const std::string &path, std::string &name, json11::Json &res);
|
||||
bool Check(const std::string &path);
|
||||
std::string Name(const std::string &path);
|
||||
OBSImporterFiles FindFiles();
|
||||
|
@ -84,8 +80,7 @@ public:
|
|||
class XSplitImporter : public Importer {
|
||||
public:
|
||||
std::string Prog() { return "XSplitBroadcaster"; };
|
||||
int ImportScenes(const std::string &path, std::string &name,
|
||||
json11::Json &res);
|
||||
int ImportScenes(const std::string &path, std::string &name, json11::Json &res);
|
||||
bool Check(const std::string &path);
|
||||
std::string Name(const std::string &) { return "XSplit Import"; };
|
||||
OBSImporterFiles FindFiles();
|
||||
|
@ -96,8 +91,7 @@ void ImportersInit();
|
|||
std::string DetectProgram(const std::string &path);
|
||||
std::string GetSCName(const std::string &path, const std::string &prog);
|
||||
|
||||
int ImportSCFromProg(const std::string &path, std::string &name,
|
||||
const std::string &program, json11::Json &res);
|
||||
int ImportSCFromProg(const std::string &path, std::string &name, const std::string &program, json11::Json &res);
|
||||
int ImportSC(const std::string &path, std::string &name, json11::Json &res);
|
||||
|
||||
OBSImporterFiles ImportersFindFiles();
|
||||
|
@ -135,9 +129,7 @@ static inline std::string GetFolderFromPath(const std::string &path)
|
|||
return path.substr(0, pos + 1);
|
||||
}
|
||||
|
||||
static inline std::string StringReplace(const std::string &in,
|
||||
const std::string &search,
|
||||
const std::string &rep)
|
||||
static inline std::string StringReplace(const std::string &in, const std::string &search, const std::string &rep)
|
||||
{
|
||||
std::string res = in;
|
||||
size_t pos;
|
||||
|
|
|
@ -90,10 +90,8 @@ static string translate_hotkey(const Json &hotkey, const string &source)
|
|||
return out + source; \
|
||||
}
|
||||
|
||||
add_translation(name, "TOGGLE_SOURCE_VISIBILITY_SHOW",
|
||||
"libobs.show_scene_item.", source);
|
||||
add_translation(name, "TOGGLE_SOURCE_VISIBILITY_HIDE",
|
||||
"libobs.hide_scene_item.", source);
|
||||
add_translation(name, "TOGGLE_SOURCE_VISIBILITY_SHOW", "libobs.show_scene_item.", source);
|
||||
add_translation(name, "TOGGLE_SOURCE_VISIBILITY_HIDE", "libobs.hide_scene_item.", source);
|
||||
|
||||
string empty = "";
|
||||
|
||||
|
@ -103,8 +101,7 @@ static string translate_hotkey(const Json &hotkey, const string &source)
|
|||
add_translation(name, "TOGGLE_UNMUTE", "libobs.unmute", empty);
|
||||
add_translation(name, "PUSH_TO_MUTE", "libobs.push-to-mute", empty);
|
||||
add_translation(name, "PUSH_TO_TALK", "libobs.push-to-talk", empty);
|
||||
add_translation(name, "GAME_CAPTURE_HOTKEY_START", "hotkey_start",
|
||||
empty);
|
||||
add_translation(name, "GAME_CAPTURE_HOTKEY_START", "hotkey_start", empty);
|
||||
add_translation(name, "GAME_CAPTURE_HOTKEY_STOP", "hotkey_stop", empty);
|
||||
|
||||
return "";
|
||||
|
@ -124,9 +121,7 @@ static bool source_name_exists(const Json::array &sources, const string &name)
|
|||
return false;
|
||||
}
|
||||
|
||||
static string get_source_name_from_id(const Json &root,
|
||||
const Json::array &sources,
|
||||
const string &id)
|
||||
static string get_source_name_from_id(const Json &root, const Json::array &sources, const string &id)
|
||||
{
|
||||
for (size_t i = 0; i < sources.size(); i++) {
|
||||
Json item = sources[i];
|
||||
|
@ -158,8 +153,7 @@ static string get_source_name_from_id(const Json &root,
|
|||
return "";
|
||||
}
|
||||
|
||||
static void get_hotkey_bindings(Json::object &out_hotkeys,
|
||||
const Json &in_hotkeys, const string &name)
|
||||
static void get_hotkey_bindings(Json::object &out_hotkeys, const Json &in_hotkeys, const string &name)
|
||||
{
|
||||
Json::array hot_arr = in_hotkeys.array_items();
|
||||
for (size_t i = 0; i < hot_arr.size(); i++) {
|
||||
|
@ -173,26 +167,24 @@ static void get_hotkey_bindings(Json::object &out_hotkeys,
|
|||
Json binding = bindings[x];
|
||||
Json modifiers = binding["modifiers"];
|
||||
|
||||
string key =
|
||||
translate_key(binding["key"].string_value());
|
||||
string key = translate_key(binding["key"].string_value());
|
||||
|
||||
if (key == "IGNORE")
|
||||
continue;
|
||||
|
||||
out_hotkey.push_back(
|
||||
Json::object{{"control", modifiers["ctrl"]},
|
||||
{"shift", modifiers["shift"]},
|
||||
{"command", modifiers["meta"]},
|
||||
{"alt", modifiers["alt"]},
|
||||
{"key", key}});
|
||||
out_hotkey.push_back(Json::object{{"control", modifiers["ctrl"]},
|
||||
{"shift", modifiers["shift"]},
|
||||
{"command", modifiers["meta"]},
|
||||
{"alt", modifiers["alt"]},
|
||||
{"key", key}});
|
||||
}
|
||||
|
||||
out_hotkeys[hotkey_name] = out_hotkey;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_scene_items(const Json &root, const Json::array &out_sources,
|
||||
Json::object &scene, const Json::array &in)
|
||||
static void get_scene_items(const Json &root, const Json::array &out_sources, Json::object &scene,
|
||||
const Json::array &in)
|
||||
{
|
||||
int length = 0;
|
||||
|
||||
|
@ -206,35 +198,29 @@ static void get_scene_items(const Json &root, const Json::array &out_sources,
|
|||
string id = item["sourceId"].string_value();
|
||||
string name = get_source_name_from_id(root, out_sources, id);
|
||||
|
||||
Json::array hotkey_items =
|
||||
item["hotkeys"]["items"].array_items();
|
||||
Json::array hotkey_items = item["hotkeys"]["items"].array_items();
|
||||
|
||||
get_hotkey_bindings(hotkeys, hotkey_items, name);
|
||||
|
||||
out_items.push_back(Json::object{
|
||||
{"name", name},
|
||||
{"id", length++},
|
||||
{"pos",
|
||||
Json::object{{"x", item["x"]}, {"y", item["y"]}}},
|
||||
{"scale", Json::object{{"x", item["scaleX"]},
|
||||
{"y", item["scaleY"]}}},
|
||||
{"rot", item["rotation"]},
|
||||
{"visible", item["visible"]},
|
||||
{"crop_top", in_crop["top"]},
|
||||
{"crop_bottom", in_crop["bottom"]},
|
||||
{"crop_left", in_crop["left"]},
|
||||
{"crop_right", in_crop["right"]}});
|
||||
out_items.push_back(Json::object{{"name", name},
|
||||
{"id", length++},
|
||||
{"pos", Json::object{{"x", item["x"]}, {"y", item["y"]}}},
|
||||
{"scale", Json::object{{"x", item["scaleX"]}, {"y", item["scaleY"]}}},
|
||||
{"rot", item["rotation"]},
|
||||
{"visible", item["visible"]},
|
||||
{"crop_top", in_crop["top"]},
|
||||
{"crop_bottom", in_crop["bottom"]},
|
||||
{"crop_left", in_crop["left"]},
|
||||
{"crop_right", in_crop["right"]}});
|
||||
}
|
||||
|
||||
scene["hotkeys"] = hotkeys;
|
||||
scene["settings"] =
|
||||
Json::object{{"items", out_items}, {"id_counter", length}};
|
||||
scene["settings"] = Json::object{{"items", out_items}, {"id_counter", length}};
|
||||
}
|
||||
|
||||
static void translate_screen_capture(Json::object &out_settings, string &type)
|
||||
{
|
||||
string subtype_info =
|
||||
out_settings["capture_source_list"].string_value();
|
||||
string subtype_info = out_settings["capture_source_list"].string_value();
|
||||
size_t pos = subtype_info.find(':');
|
||||
string subtype = subtype_info.substr(0, pos);
|
||||
|
||||
|
@ -246,8 +232,7 @@ static void translate_screen_capture(Json::object &out_settings, string &type)
|
|||
} else if (subtype == "window") {
|
||||
type = "window_capture";
|
||||
out_settings["cursor"] = out_settings["capture_cursor"];
|
||||
out_settings["window"] =
|
||||
out_settings["capture_window_line"].string_value();
|
||||
out_settings["window"] = out_settings["capture_window_line"].string_value();
|
||||
out_settings["capture_cursor"] = nullptr;
|
||||
}
|
||||
out_settings["auto_capture_rules_path"] = nullptr;
|
||||
|
@ -272,16 +257,14 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
|||
Json source = source_arr[i];
|
||||
|
||||
Json in_hotkeys = source["hotkeys"];
|
||||
Json::array hotkey_items =
|
||||
source["hotkeys"]["items"].array_items();
|
||||
Json::array hotkey_items = source["hotkeys"]["items"].array_items();
|
||||
Json in_filters = source["filters"];
|
||||
Json::array filter_items = in_filters["items"].array_items();
|
||||
|
||||
Json in_settings = source["settings"];
|
||||
Json in_sync = source["syncOffset"];
|
||||
|
||||
int sync = (int)(in_sync["sec"].number_value() * 1000000000 +
|
||||
in_sync["nsec"].number_value());
|
||||
int sync = (int)(in_sync["sec"].number_value() * 1000000000 + in_sync["nsec"].number_value());
|
||||
|
||||
double vol = source["volume"].number_value();
|
||||
bool muted = source["muted"].bool_value();
|
||||
|
@ -313,17 +296,16 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
|||
translate_screen_capture(out_settings, type);
|
||||
}
|
||||
|
||||
out_sources.push_back(
|
||||
Json::object{{"filters", out_filters},
|
||||
{"hotkeys", out_hotkeys},
|
||||
{"id", type},
|
||||
{"sl_id", sl_id},
|
||||
{"settings", out_settings},
|
||||
{"sync", sync},
|
||||
{"volume", vol},
|
||||
{"muted", muted},
|
||||
{"name", out_name},
|
||||
{"monitoring_type", monitoring}});
|
||||
out_sources.push_back(Json::object{{"filters", out_filters},
|
||||
{"hotkeys", out_hotkeys},
|
||||
{"id", type},
|
||||
{"sl_id", sl_id},
|
||||
{"settings", out_settings},
|
||||
{"sync", sync},
|
||||
{"volume", vol},
|
||||
{"muted", muted},
|
||||
{"name", out_name},
|
||||
{"monitoring_type", monitoring}});
|
||||
}
|
||||
|
||||
string scene_name = "";
|
||||
|
@ -362,15 +344,10 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
|||
|
||||
string sl_id = scene["id"].string_value();
|
||||
|
||||
Json::object out =
|
||||
Json::object{{"filters", out_filters},
|
||||
{"hotkeys", out_hotkeys},
|
||||
{"id", "scene"},
|
||||
{"sl_id", sl_id},
|
||||
{"settings", in_settings},
|
||||
{"volume", 1.0},
|
||||
{"name", out_name},
|
||||
{"private_settings", Json::object{}}};
|
||||
Json::object out = Json::object{{"filters", out_filters}, {"hotkeys", out_hotkeys},
|
||||
{"id", "scene"}, {"sl_id", sl_id},
|
||||
{"settings", in_settings}, {"volume", 1.0},
|
||||
{"name", out_name}, {"private_settings", Json::object{}}};
|
||||
|
||||
Json in_items = scene["sceneItems"];
|
||||
Json::array items_arr = in_items["items"].array_items();
|
||||
|
@ -394,11 +371,10 @@ static int attempt_import(const Json &root, const string &name, Json &res)
|
|||
if (id == t_id)
|
||||
transition_name = name;
|
||||
|
||||
out_transitions.push_back(
|
||||
Json::object{{"id", transition["type"]},
|
||||
{"settings", in_settings},
|
||||
{"name", name},
|
||||
{"duration", duration}});
|
||||
out_transitions.push_back(Json::object{{"id", transition["type"]},
|
||||
{"settings", in_settings},
|
||||
{"name", name},
|
||||
{"duration", duration}});
|
||||
}
|
||||
|
||||
res = Json::object{{"sources", out_sources},
|
||||
|
@ -420,15 +396,13 @@ string SLImporter::Name(const string &path)
|
|||
string manifest_path = folder + "manifest.json";
|
||||
|
||||
if (os_file_exists(manifest_path.c_str())) {
|
||||
BPtr<char> file_data =
|
||||
os_quick_read_utf8_file(manifest_path.c_str());
|
||||
BPtr<char> file_data = os_quick_read_utf8_file(manifest_path.c_str());
|
||||
|
||||
string err;
|
||||
Json data = Json::parse(file_data, err);
|
||||
|
||||
if (err == "") {
|
||||
Json::array collections =
|
||||
data["collections"].array_items();
|
||||
Json::array collections = data["collections"].array_items();
|
||||
|
||||
bool name_set = false;
|
||||
|
||||
|
@ -513,8 +487,7 @@ OBSImporterFiles SLImporter::FindFiles()
|
|||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
char dst[512];
|
||||
|
||||
int found =
|
||||
os_get_config_path(dst, 512, "slobs-client/SceneCollections/");
|
||||
int found = os_get_config_path(dst, 512, "slobs-client/SceneCollections/");
|
||||
|
||||
if (found == -1)
|
||||
return res;
|
||||
|
|
|
@ -49,19 +49,13 @@ void TranslateOSStudio(Json &res)
|
|||
|
||||
ClearTranslation("game_capture", "syphon-input");
|
||||
|
||||
ClearTranslation("wasapi_input_capture",
|
||||
"coreaudio_input_capture");
|
||||
ClearTranslation("wasapi_output_capture",
|
||||
"coreaudio_output_capture");
|
||||
ClearTranslation("pulse_input_capture",
|
||||
"coreaudio_input_capture");
|
||||
ClearTranslation("pulse_output_capture",
|
||||
"coreaudio_output_capture");
|
||||
ClearTranslation("wasapi_input_capture", "coreaudio_input_capture");
|
||||
ClearTranslation("wasapi_output_capture", "coreaudio_output_capture");
|
||||
ClearTranslation("pulse_input_capture", "coreaudio_input_capture");
|
||||
ClearTranslation("pulse_output_capture", "coreaudio_output_capture");
|
||||
|
||||
ClearTranslation("jack_output_capture",
|
||||
"coreaudio_output_capture");
|
||||
ClearTranslation("alsa_input_capture",
|
||||
"coreaudio_input_capture");
|
||||
ClearTranslation("jack_output_capture", "coreaudio_output_capture");
|
||||
ClearTranslation("alsa_input_capture", "coreaudio_input_capture");
|
||||
|
||||
ClearTranslation("dshow_input", "av_capture_input");
|
||||
ClearTranslation("v4l2_input", "av_capture_input");
|
||||
|
@ -69,10 +63,8 @@ void TranslateOSStudio(Json &res)
|
|||
ClearTranslation("xcomposite_input", "window_capture");
|
||||
|
||||
if (id == "monitor_capture") {
|
||||
if (settings["show_cursor"].is_null() &&
|
||||
!settings["capture_cursor"].is_null()) {
|
||||
bool cursor =
|
||||
settings["capture_cursor"].bool_value();
|
||||
if (settings["show_cursor"].is_null() && !settings["capture_cursor"].is_null()) {
|
||||
bool cursor = settings["capture_cursor"].bool_value();
|
||||
|
||||
settings["show_cursor"] = cursor;
|
||||
}
|
||||
|
@ -84,16 +76,12 @@ void TranslateOSStudio(Json &res)
|
|||
|
||||
ClearTranslation("syphon-input", "game_capture");
|
||||
|
||||
ClearTranslation("coreaudio_input_capture",
|
||||
"wasapi_input_capture");
|
||||
ClearTranslation("coreaudio_output_capture",
|
||||
"wasapi_output_capture");
|
||||
ClearTranslation("coreaudio_input_capture", "wasapi_input_capture");
|
||||
ClearTranslation("coreaudio_output_capture", "wasapi_output_capture");
|
||||
ClearTranslation("pulse_input_capture", "wasapi_input_capture");
|
||||
ClearTranslation("pulse_output_capture",
|
||||
"wasapi_output_capture");
|
||||
ClearTranslation("pulse_output_capture", "wasapi_output_capture");
|
||||
|
||||
ClearTranslation("jack_output_capture",
|
||||
"wasapi_output_capture");
|
||||
ClearTranslation("jack_output_capture", "wasapi_output_capture");
|
||||
ClearTranslation("alsa_input_capture", "wasapi_input_capture");
|
||||
|
||||
ClearTranslation("av_capture_input", "dshow_input");
|
||||
|
@ -103,8 +91,7 @@ void TranslateOSStudio(Json &res)
|
|||
|
||||
if (id == "monitor_capture" || id == "xshm_input") {
|
||||
if (!settings["show_cursor"].is_null()) {
|
||||
bool cursor =
|
||||
settings["show_cursor"].bool_value();
|
||||
bool cursor = settings["show_cursor"].bool_value();
|
||||
|
||||
settings["capture_cursor"] = cursor;
|
||||
}
|
||||
|
@ -114,13 +101,10 @@ void TranslateOSStudio(Json &res)
|
|||
#else
|
||||
DirectTranslation("text_gdiplus", "text_ft2_source");
|
||||
|
||||
ClearTranslation("coreaudio_input_capture",
|
||||
"pulse_input_capture");
|
||||
ClearTranslation("coreaudio_output_capture",
|
||||
"pulse_output_capture");
|
||||
ClearTranslation("coreaudio_input_capture", "pulse_input_capture");
|
||||
ClearTranslation("coreaudio_output_capture", "pulse_output_capture");
|
||||
ClearTranslation("wasapi_input_capture", "pulse_input_capture");
|
||||
ClearTranslation("wasapi_output_capture",
|
||||
"pulse_output_capture");
|
||||
ClearTranslation("wasapi_output_capture", "pulse_output_capture");
|
||||
|
||||
ClearTranslation("av_capture_input", "v4l2_input");
|
||||
ClearTranslation("dshow_input", "v4l2_input");
|
||||
|
@ -130,10 +114,8 @@ void TranslateOSStudio(Json &res)
|
|||
if (id == "monitor_capture") {
|
||||
source["id"] = "xshm_input";
|
||||
|
||||
if (settings["show_cursor"].is_null() &&
|
||||
!settings["capture_cursor"].is_null()) {
|
||||
bool cursor =
|
||||
settings["capture_cursor"].bool_value();
|
||||
if (settings["show_cursor"].is_null() && !settings["capture_cursor"].is_null()) {
|
||||
bool cursor = settings["capture_cursor"].bool_value();
|
||||
|
||||
settings["show_cursor"] = cursor;
|
||||
}
|
||||
|
@ -158,8 +140,7 @@ static string CheckPath(const string &path, const string &rootDir)
|
|||
|
||||
char absPath[512];
|
||||
*absPath = 0;
|
||||
size_t len = os_get_abs_path((rootDir + path).c_str(), absPath,
|
||||
sizeof(absPath));
|
||||
size_t len = os_get_abs_path((rootDir + path).c_str(), absPath, sizeof(absPath));
|
||||
|
||||
if (len == 0)
|
||||
return path;
|
||||
|
@ -185,8 +166,7 @@ void TranslatePaths(Json &res, const string &rootDir)
|
|||
if (val.string_value().rfind("./", 0) != 0)
|
||||
continue;
|
||||
|
||||
out[it->first] =
|
||||
CheckPath(val.string_value(), rootDir);
|
||||
out[it->first] = CheckPath(val.string_value(), rootDir);
|
||||
} else if (val.is_array() || val.is_object()) {
|
||||
TranslatePaths(val, rootDir);
|
||||
out[it->first] = val;
|
||||
|
|
|
@ -74,17 +74,15 @@ static Json::object parse_text(QString &config)
|
|||
|
||||
Json font = Json::object{{"face", data["fontStyle"]}, {"size", 200}};
|
||||
|
||||
return Json::object{
|
||||
{"text", data["text"]},
|
||||
{"font", font},
|
||||
{"outline", out > 0},
|
||||
{"outline_size", out},
|
||||
{"outline_color",
|
||||
hex_string_to_int(data["outlineColor"].string_value())},
|
||||
{"color", hex_string_to_int(data["color"].string_value())},
|
||||
{"align", data["textAlign"]},
|
||||
{"valign", valign},
|
||||
{"alpha", data["opacity"]}};
|
||||
return Json::object{{"text", data["text"]},
|
||||
{"font", font},
|
||||
{"outline", out > 0},
|
||||
{"outline_size", out},
|
||||
{"outline_color", hex_string_to_int(data["outlineColor"].string_value())},
|
||||
{"color", hex_string_to_int(data["color"].string_value())},
|
||||
{"align", data["textAlign"]},
|
||||
{"valign", valign},
|
||||
{"alpha", data["opacity"]}};
|
||||
}
|
||||
|
||||
static Json::array parse_playlist(QString &playlist)
|
||||
|
@ -107,8 +105,7 @@ static Json::array parse_playlist(QString &playlist)
|
|||
return out;
|
||||
}
|
||||
|
||||
static void parse_media_types(QDomNamedNodeMap &attr, Json::object &source,
|
||||
Json::object &settings)
|
||||
static void parse_media_types(QDomNamedNodeMap &attr, Json::object &source, Json::object &settings)
|
||||
{
|
||||
QString playlist = attr.namedItem("FilePlaylist").nodeValue();
|
||||
|
||||
|
@ -143,8 +140,7 @@ static void parse_media_types(QDomNamedNodeMap &attr, Json::object &source,
|
|||
}
|
||||
} else {
|
||||
source["id"] = "ffmpeg_source";
|
||||
settings["local_file"] =
|
||||
url.replace("\\", "/").toStdString();
|
||||
settings["local_file"] = url.replace("\\", "/").toStdString();
|
||||
settings["is_local_file"] = true;
|
||||
}
|
||||
}
|
||||
|
@ -186,8 +182,7 @@ static Json::object parse_slideshow(QString &config)
|
|||
return Json::object{};
|
||||
|
||||
return Json::object{{"randomize", opt["random"]},
|
||||
{"slide_time",
|
||||
opt["delay"].number_value() * 1000 + 700},
|
||||
{"slide_time", opt["delay"].number_value() * 1000 + 700},
|
||||
{"files", files_out}};
|
||||
}
|
||||
|
||||
|
@ -211,8 +206,7 @@ static Json get_source_with_id(const string &src_id, const Json::array &sources)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static void parse_items(QDomNode &item, Json::array &items,
|
||||
Json::array &sources)
|
||||
static void parse_items(QDomNode &item, Json::array &items, Json::array &sources)
|
||||
{
|
||||
while (!item.isNull()) {
|
||||
QDomNamedNodeMap attr = item.attributes();
|
||||
|
@ -245,9 +239,7 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
name = temp_name;
|
||||
|
||||
settings = Json::object{};
|
||||
source = Json::object{{"name", name},
|
||||
{"src_id", srcid.toStdString()},
|
||||
{"volume", vol}};
|
||||
source = Json::object{{"name", name}, {"src_id", srcid.toStdString()}, {"volume", vol}};
|
||||
|
||||
/** type=1 means Media of some kind (Video Playlist, RTSP,
|
||||
RTMP, NDI or Media File).
|
||||
|
@ -270,8 +262,7 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
source["id"] = "wasapi_input_capture";
|
||||
int dev = audio.indexOf("\\wave:") + 6;
|
||||
|
||||
QString res =
|
||||
"{0.0.1.00000000}." + audio.mid(dev);
|
||||
QString res = "{0.0.1.00000000}." + audio.mid(dev);
|
||||
res = res.toLower();
|
||||
|
||||
settings["device_id"] = res.toStdString();
|
||||
|
@ -291,24 +282,18 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
QDomNode el = options.documentElement();
|
||||
|
||||
QDomNamedNodeMap o_attr = el.attributes();
|
||||
QString display =
|
||||
o_attr.namedItem("desktop").nodeValue();
|
||||
QString display = o_attr.namedItem("desktop").nodeValue();
|
||||
|
||||
if (!display.isEmpty()) {
|
||||
source["id"] = "monitor_capture";
|
||||
int cursor = attr.namedItem("ScrCapShowMouse")
|
||||
.nodeValue()
|
||||
.toInt();
|
||||
int cursor = attr.namedItem("ScrCapShowMouse").nodeValue().toInt();
|
||||
settings["capture_cursor"] = cursor == 1;
|
||||
} else {
|
||||
source["id"] = "window_capture";
|
||||
|
||||
QString exec =
|
||||
o_attr.namedItem("module").nodeValue();
|
||||
QString window =
|
||||
o_attr.namedItem("window").nodeValue();
|
||||
QString _class =
|
||||
o_attr.namedItem("class").nodeValue();
|
||||
QString exec = o_attr.namedItem("module").nodeValue();
|
||||
QString window = o_attr.namedItem("window").nodeValue();
|
||||
QString _class = o_attr.namedItem("class").nodeValue();
|
||||
|
||||
int pos = exec.lastIndexOf('\\');
|
||||
|
||||
|
@ -316,8 +301,7 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
_class = "class";
|
||||
}
|
||||
|
||||
QString res = window + ":" + _class + ":" +
|
||||
exec.mid(pos + 1);
|
||||
QString res = window + ":" + _class + ":" + exec.mid(pos + 1);
|
||||
|
||||
settings["window"] = res.toStdString();
|
||||
settings["priority"] = 2;
|
||||
|
@ -335,8 +319,7 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
QDomNamedNodeMap o_attr = el.attributes();
|
||||
|
||||
QString name = o_attr.namedItem("wndname").nodeValue();
|
||||
QString exec =
|
||||
o_attr.namedItem("imagename").nodeValue();
|
||||
QString exec = o_attr.namedItem("imagename").nodeValue();
|
||||
|
||||
QString res = name = "::" + exec;
|
||||
|
||||
|
@ -346,8 +329,7 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
} else if (type == 8) {
|
||||
QString plugin = attr.namedItem("item").nodeValue();
|
||||
|
||||
if (plugin.startsWith(
|
||||
"html:plugin:imageslideshowplg*")) {
|
||||
if (plugin.startsWith("html:plugin:imageslideshowplg*")) {
|
||||
source["id"] = "slideshow";
|
||||
settings = parse_slideshow(plugin);
|
||||
} else if (plugin.startsWith("html:plugin:titleplg")) {
|
||||
|
@ -356,13 +338,11 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
} else if (plugin.startsWith("http")) {
|
||||
source["id"] = "browser_source";
|
||||
int end = plugin.indexOf('*');
|
||||
settings["url"] =
|
||||
plugin.left(end).toStdString();
|
||||
settings["url"] = plugin.left(end).toStdString();
|
||||
}
|
||||
} else if (type == 11) {
|
||||
QString id = attr.namedItem("item").nodeValue();
|
||||
Json source =
|
||||
get_source_with_id(id.toStdString(), sources);
|
||||
Json source = get_source_with_id(id.toStdString(), sources);
|
||||
name = source["name"].string_value();
|
||||
|
||||
goto skip;
|
||||
|
@ -378,26 +358,19 @@ static void parse_items(QDomNode &item, Json::array &items,
|
|||
int width = ovi.base_width;
|
||||
int height = ovi.base_height;
|
||||
|
||||
double pos_left =
|
||||
attr.namedItem("pos_left").nodeValue().toDouble();
|
||||
double pos_right =
|
||||
attr.namedItem("pos_right").nodeValue().toDouble();
|
||||
double pos_top =
|
||||
attr.namedItem("pos_top").nodeValue().toDouble();
|
||||
double pos_bottom =
|
||||
attr.namedItem("pos_bottom").nodeValue().toDouble();
|
||||
double pos_left = attr.namedItem("pos_left").nodeValue().toDouble();
|
||||
double pos_right = attr.namedItem("pos_right").nodeValue().toDouble();
|
||||
double pos_top = attr.namedItem("pos_top").nodeValue().toDouble();
|
||||
double pos_bottom = attr.namedItem("pos_bottom").nodeValue().toDouble();
|
||||
|
||||
bool visible = attr.namedItem("visible").nodeValue() == "1";
|
||||
|
||||
Json out_item = Json::object{
|
||||
{"bounds_type", 2},
|
||||
{"pos", Json::object{{"x", pos_left * width},
|
||||
{"y", pos_top * height}}},
|
||||
{"bounds",
|
||||
Json::object{{"x", (pos_right - pos_left) * width},
|
||||
{"y", (pos_bottom - pos_top) * height}}},
|
||||
{"name", name},
|
||||
{"visible", visible}};
|
||||
Json out_item = Json::object{{"bounds_type", 2},
|
||||
{"pos", Json::object{{"x", pos_left * width}, {"y", pos_top * height}}},
|
||||
{"bounds", Json::object{{"x", (pos_right - pos_left) * width},
|
||||
{"y", (pos_bottom - pos_top) * height}}},
|
||||
{"name", name},
|
||||
{"visible", visible}};
|
||||
|
||||
items.push_back(out_item);
|
||||
|
||||
|
@ -424,10 +397,9 @@ static Json::object parse_scenes(QDomElement &scenes)
|
|||
if (first.isEmpty())
|
||||
first = name;
|
||||
|
||||
Json out = Json::object{
|
||||
{"id", "scene"},
|
||||
{"name", name.toStdString().c_str()},
|
||||
{"src_id", id.toStdString().c_str()}};
|
||||
Json out = Json::object{{"id", "scene"},
|
||||
{"name", name.toStdString().c_str()},
|
||||
{"src_id", id.toStdString().c_str()}};
|
||||
|
||||
sources.push_back(out);
|
||||
}
|
||||
|
@ -442,8 +414,7 @@ static Json::object parse_scenes(QDomElement &scenes)
|
|||
|
||||
parse_items(firstChild, items, sources);
|
||||
|
||||
Json settings = Json::object{{"items", items},
|
||||
{"id_counter", (int)items.size()}};
|
||||
Json settings = Json::object{{"items", items}, {"id_counter", (int)items.size()}};
|
||||
|
||||
source["settings"] = settings;
|
||||
sources[i] = source;
|
||||
|
@ -456,8 +427,7 @@ static Json::object parse_scenes(QDomElement &scenes)
|
|||
{"current_program_scene", first.toStdString()}};
|
||||
}
|
||||
|
||||
int XSplitImporter::ImportScenes(const string &path, string &name,
|
||||
json11::Json &res)
|
||||
int XSplitImporter::ImportScenes(const string &path, string &name, json11::Json &res)
|
||||
{
|
||||
if (name == "")
|
||||
name = "XSplit Import";
|
||||
|
@ -516,8 +486,7 @@ OBSImporterFiles XSplitImporter::FindFiles()
|
|||
OBSImporterFiles res;
|
||||
#ifdef _WIN32
|
||||
char dst[512];
|
||||
int found = os_get_program_data_path(
|
||||
dst, 512, "SplitMediaLabs\\XSplit\\Presentation2.0\\");
|
||||
int found = os_get_program_data_path(dst, 512, "SplitMediaLabs\\XSplit\\Presentation2.0\\");
|
||||
|
||||
if (found == -1)
|
||||
return res;
|
||||
|
|
|
@ -29,8 +29,7 @@ QListWidgetItem *TakeListItem(QListWidget *widget, int row);
|
|||
void DeleteListItem(QListWidget *widget, QListWidgetItem *item);
|
||||
void ClearListItems(QListWidget *widget);
|
||||
|
||||
template<typename QObjectPtr>
|
||||
void InsertQObjectByName(std::vector<QObjectPtr> &controls, QObjectPtr control)
|
||||
template<typename QObjectPtr> void InsertQObjectByName(std::vector<QObjectPtr> &controls, QObjectPtr control)
|
||||
{
|
||||
QString name = control->objectName();
|
||||
auto finder = [name](QObjectPtr elem) {
|
||||
|
|
|
@ -2,10 +2,8 @@
|
|||
|
||||
LineEditAutoResize::LineEditAutoResize() : m_maxLength(32767)
|
||||
{
|
||||
connect(this, &LineEditAutoResize::textChanged, this,
|
||||
&LineEditAutoResize::checkTextLength);
|
||||
connect(document()->documentLayout(),
|
||||
&QAbstractTextDocumentLayout::documentSizeChanged, this,
|
||||
connect(this, &LineEditAutoResize::textChanged, this, &LineEditAutoResize::checkTextLength);
|
||||
connect(document()->documentLayout(), &QAbstractTextDocumentLayout::documentSizeChanged, this,
|
||||
&LineEditAutoResize::resizeVertically);
|
||||
}
|
||||
|
||||
|
@ -63,8 +61,7 @@ void LineEditAutoResize::keyPressEvent(QKeyEvent *event)
|
|||
* allow all. Actions that will still exceed the limit (like
|
||||
* Paste) can be caught in a later step. */
|
||||
default:
|
||||
if (toPlainText().length() >= m_maxLength &&
|
||||
event->modifiers() == Qt::NoModifier &&
|
||||
if (toPlainText().length() >= m_maxLength && event->modifiers() == Qt::NoModifier &&
|
||||
!textCursor().hasSelection())
|
||||
event->ignore();
|
||||
else
|
||||
|
@ -86,8 +83,7 @@ QString LineEditAutoResize::text()
|
|||
|
||||
void LineEditAutoResize::setText(const QString &text)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "SetPlainText", Qt::QueuedConnection,
|
||||
Q_ARG(const QString &, text));
|
||||
QMetaObject::invokeMethod(this, "SetPlainText", Qt::QueuedConnection, Q_ARG(const QString &, text));
|
||||
}
|
||||
|
||||
void LineEditAutoResize::SetPlainText(const QString &text)
|
||||
|
|
|
@ -12,23 +12,18 @@
|
|||
|
||||
#include "moc_log-viewer.cpp"
|
||||
|
||||
OBSLogViewer::OBSLogViewer(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui::OBSLogViewer)
|
||||
OBSLogViewer::OBSLogViewer(QWidget *parent) : QDialog(parent), ui(new Ui::OBSLogViewer)
|
||||
{
|
||||
setWindowFlags(windowFlags() & Qt::WindowMaximizeButtonHint &
|
||||
~Qt::WindowContextHelpButtonHint);
|
||||
setWindowFlags(windowFlags() & Qt::WindowMaximizeButtonHint & ~Qt::WindowContextHelpButtonHint);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
bool showLogViewerOnStartup = config_get_bool(
|
||||
App()->GetUserConfig(), "LogViewer", "ShowLogStartup");
|
||||
bool showLogViewerOnStartup = config_get_bool(App()->GetUserConfig(), "LogViewer", "ShowLogStartup");
|
||||
|
||||
ui->showStartup->setChecked(showLogViewerOnStartup);
|
||||
|
||||
const char *geom = config_get_string(App()->GetUserConfig(),
|
||||
"LogViewer", "geometry");
|
||||
const char *geom = config_get_string(App()->GetUserConfig(), "LogViewer", "geometry");
|
||||
|
||||
if (geom != nullptr) {
|
||||
QByteArray ba = QByteArray::fromBase64(QByteArray(geom));
|
||||
|
@ -40,14 +35,12 @@ OBSLogViewer::OBSLogViewer(QWidget *parent)
|
|||
|
||||
OBSLogViewer::~OBSLogViewer()
|
||||
{
|
||||
config_set_string(App()->GetUserConfig(), "LogViewer", "geometry",
|
||||
saveGeometry().toBase64().constData());
|
||||
config_set_string(App()->GetUserConfig(), "LogViewer", "geometry", saveGeometry().toBase64().constData());
|
||||
}
|
||||
|
||||
void OBSLogViewer::on_showStartup_clicked(bool checked)
|
||||
{
|
||||
config_set_bool(App()->GetUserConfig(), "LogViewer", "ShowLogStartup",
|
||||
checked);
|
||||
config_set_bool(App()->GetUserConfig(), "LogViewer", "ShowLogStartup", checked);
|
||||
}
|
||||
|
||||
extern QPointer<OBSLogViewer> obsLogViewer;
|
||||
|
|
|
@ -43,9 +43,7 @@ void MediaControls::OBSMediaPrevious(void *data, calldata_t *)
|
|||
QMetaObject::invokeMethod(media, "UpdateSlideCounter");
|
||||
}
|
||||
|
||||
MediaControls::MediaControls(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
ui(new Ui::MediaControls)
|
||||
MediaControls::MediaControls(QWidget *parent) : QWidget(parent), ui(new Ui::MediaControls)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->playPauseButton->setProperty("class", "icon-media-play");
|
||||
|
@ -54,47 +52,36 @@ MediaControls::MediaControls(QWidget *parent)
|
|||
ui->stopButton->setProperty("class", "icon-media-stop");
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
connect(&mediaTimer, &QTimer::timeout, this,
|
||||
&MediaControls::SetSliderPosition);
|
||||
connect(&seekTimer, &QTimer::timeout, this,
|
||||
&MediaControls::SeekTimerCallback);
|
||||
connect(ui->slider, &AbsoluteSlider::sliderPressed, this,
|
||||
&MediaControls::AbsoluteSliderClicked);
|
||||
connect(ui->slider, &AbsoluteSlider::absoluteSliderHovered, this,
|
||||
&MediaControls::AbsoluteSliderHovered);
|
||||
connect(ui->slider, &AbsoluteSlider::sliderReleased, this,
|
||||
&MediaControls::AbsoluteSliderReleased);
|
||||
connect(ui->slider, &AbsoluteSlider::sliderMoved, this,
|
||||
&MediaControls::AbsoluteSliderMoved);
|
||||
connect(&mediaTimer, &QTimer::timeout, this, &MediaControls::SetSliderPosition);
|
||||
connect(&seekTimer, &QTimer::timeout, this, &MediaControls::SeekTimerCallback);
|
||||
connect(ui->slider, &AbsoluteSlider::sliderPressed, this, &MediaControls::AbsoluteSliderClicked);
|
||||
connect(ui->slider, &AbsoluteSlider::absoluteSliderHovered, this, &MediaControls::AbsoluteSliderHovered);
|
||||
connect(ui->slider, &AbsoluteSlider::sliderReleased, this, &MediaControls::AbsoluteSliderReleased);
|
||||
connect(ui->slider, &AbsoluteSlider::sliderMoved, this, &MediaControls::AbsoluteSliderMoved);
|
||||
|
||||
countDownTimer = config_get_bool(App()->GetUserConfig(), "BasicWindow",
|
||||
"MediaControlsCountdownTimer");
|
||||
countDownTimer = config_get_bool(App()->GetUserConfig(), "BasicWindow", "MediaControlsCountdownTimer");
|
||||
|
||||
QAction *restartAction = new QAction(this);
|
||||
restartAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
restartAction->setShortcut({Qt::Key_R});
|
||||
connect(restartAction, &QAction::triggered, this,
|
||||
&MediaControls::RestartMedia);
|
||||
connect(restartAction, &QAction::triggered, this, &MediaControls::RestartMedia);
|
||||
addAction(restartAction);
|
||||
|
||||
QAction *sliderFoward = new QAction(this);
|
||||
sliderFoward->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
connect(sliderFoward, &QAction::triggered, this,
|
||||
&MediaControls::MoveSliderFoward);
|
||||
connect(sliderFoward, &QAction::triggered, this, &MediaControls::MoveSliderFoward);
|
||||
sliderFoward->setShortcut({Qt::Key_Right});
|
||||
addAction(sliderFoward);
|
||||
|
||||
QAction *sliderBack = new QAction(this);
|
||||
sliderBack->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
connect(sliderBack, &QAction::triggered, this,
|
||||
&MediaControls::MoveSliderBackwards);
|
||||
connect(sliderBack, &QAction::triggered, this, &MediaControls::MoveSliderBackwards);
|
||||
sliderBack->setShortcut({Qt::Key_Left});
|
||||
addAction(sliderBack);
|
||||
|
||||
QAction *playPause = new QAction(this);
|
||||
playPause->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||
connect(playPause, &QAction::triggered, this,
|
||||
&MediaControls::on_playPauseButton_clicked);
|
||||
connect(playPause, &QAction::triggered, this, &MediaControls::on_playPauseButton_clicked);
|
||||
playPause->setShortcut({Qt::Key_Space});
|
||||
addAction(playPause);
|
||||
}
|
||||
|
@ -216,8 +203,7 @@ void MediaControls::SetPlayingState()
|
|||
ui->playPauseButton->setProperty("class", "icon-media-pause");
|
||||
ui->playPauseButton->style()->unpolish(ui->playPauseButton);
|
||||
ui->playPauseButton->style()->polish(ui->playPauseButton);
|
||||
ui->playPauseButton->setToolTip(
|
||||
QTStr("ContextBar.MediaControls.PauseMedia"));
|
||||
ui->playPauseButton->setToolTip(QTStr("ContextBar.MediaControls.PauseMedia"));
|
||||
|
||||
prevPaused = false;
|
||||
|
||||
|
@ -230,8 +216,7 @@ void MediaControls::SetPausedState()
|
|||
ui->playPauseButton->setProperty("class", "icon-media-play");
|
||||
ui->playPauseButton->style()->unpolish(ui->playPauseButton);
|
||||
ui->playPauseButton->style()->polish(ui->playPauseButton);
|
||||
ui->playPauseButton->setToolTip(
|
||||
QTStr("ContextBar.MediaControls.PlayMedia"));
|
||||
ui->playPauseButton->setToolTip(QTStr("ContextBar.MediaControls.PlayMedia"));
|
||||
|
||||
StopMediaTimer();
|
||||
}
|
||||
|
@ -241,8 +226,7 @@ void MediaControls::SetRestartState()
|
|||
ui->playPauseButton->setProperty("class", "icon-media-restart");
|
||||
ui->playPauseButton->style()->unpolish(ui->playPauseButton);
|
||||
ui->playPauseButton->style()->polish(ui->playPauseButton);
|
||||
ui->playPauseButton->setToolTip(
|
||||
QTStr("ContextBar.MediaControls.RestartMedia"));
|
||||
ui->playPauseButton->setToolTip(QTStr("ContextBar.MediaControls.RestartMedia"));
|
||||
|
||||
ui->slider->setValue(0);
|
||||
|
||||
|
@ -354,8 +338,7 @@ void MediaControls::SetSliderPosition()
|
|||
float sliderPosition;
|
||||
|
||||
if (duration)
|
||||
sliderPosition =
|
||||
(time / duration) * (float)ui->slider->maximum();
|
||||
sliderPosition = (time / duration) * (float)ui->slider->maximum();
|
||||
else
|
||||
sliderPosition = 0.0f;
|
||||
|
||||
|
@ -465,8 +448,7 @@ void MediaControls::on_durationLabel_clicked()
|
|||
{
|
||||
countDownTimer = !countDownTimer;
|
||||
|
||||
config_set_bool(App()->GetUserConfig(), "BasicWindow",
|
||||
"MediaControlsCountdownTimer", countDownTimer);
|
||||
config_set_bool(App()->GetUserConfig(), "BasicWindow", "MediaControlsCountdownTimer", countDownTimer);
|
||||
|
||||
if (MediaPaused())
|
||||
SetSliderPosition();
|
||||
|
@ -544,10 +526,7 @@ void MediaControls::UpdateLabels(int val)
|
|||
ui->timerLabel->setText(FormatSeconds((int)(time / 1000.0f)));
|
||||
|
||||
if (!countDownTimer)
|
||||
ui->durationLabel->setText(
|
||||
FormatSeconds((int)(duration / 1000.0f)));
|
||||
ui->durationLabel->setText(FormatSeconds((int)(duration / 1000.0f)));
|
||||
else
|
||||
ui->durationLabel->setText(
|
||||
QString("-") +
|
||||
FormatSeconds((int)((duration - time) / 1000.0f)));
|
||||
ui->durationLabel->setText(QString("-") + FormatSeconds((int)((duration - time) / 1000.0f)));
|
||||
}
|
||||
|
|
|
@ -10,14 +10,7 @@ protected:
|
|||
void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
public:
|
||||
explicit inline MenuButton(QWidget *parent = nullptr)
|
||||
: QPushButton(parent)
|
||||
{
|
||||
}
|
||||
explicit inline MenuButton(QWidget *parent = nullptr) : QPushButton(parent) {}
|
||||
|
||||
explicit inline MenuButton(const QString &text,
|
||||
QWidget *parent = nullptr)
|
||||
: QPushButton(text, parent)
|
||||
{
|
||||
}
|
||||
explicit inline MenuButton(const QString &text, QWidget *parent = nullptr) : QPushButton(text, parent) {}
|
||||
};
|
||||
|
|
|
@ -47,18 +47,16 @@ template<typename T> struct nlohmann::adl_serializer<std::optional<T>> {
|
|||
}
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(obs_scale_type,
|
||||
{
|
||||
{OBS_SCALE_DISABLE, "OBS_SCALE_DISABLE"},
|
||||
{OBS_SCALE_POINT, "OBS_SCALE_POINT"},
|
||||
{OBS_SCALE_BICUBIC, "OBS_SCALE_BICUBIC"},
|
||||
{OBS_SCALE_BILINEAR, "OBS_SCALE_BILINEAR"},
|
||||
{OBS_SCALE_LANCZOS, "OBS_SCALE_LANCZOS"},
|
||||
{OBS_SCALE_AREA, "OBS_SCALE_AREA"},
|
||||
})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(obs_scale_type, {
|
||||
{OBS_SCALE_DISABLE, "OBS_SCALE_DISABLE"},
|
||||
{OBS_SCALE_POINT, "OBS_SCALE_POINT"},
|
||||
{OBS_SCALE_BICUBIC, "OBS_SCALE_BICUBIC"},
|
||||
{OBS_SCALE_BILINEAR, "OBS_SCALE_BILINEAR"},
|
||||
{OBS_SCALE_LANCZOS, "OBS_SCALE_LANCZOS"},
|
||||
{OBS_SCALE_AREA, "OBS_SCALE_AREA"},
|
||||
})
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(media_frames_per_second, numerator,
|
||||
denominator)
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(media_frames_per_second, numerator, denominator)
|
||||
|
||||
namespace GoLiveApi {
|
||||
using std::string;
|
||||
|
@ -79,8 +77,7 @@ struct Cpu {
|
|||
optional<uint32_t> speed;
|
||||
optional<string> name;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Cpu, physical_cores, logical_cores,
|
||||
speed, name)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Cpu, physical_cores, logical_cores, speed, name)
|
||||
};
|
||||
|
||||
struct Memory {
|
||||
|
@ -98,9 +95,8 @@ struct Gpu {
|
|||
uint64_t shared_system_memory;
|
||||
optional<string> driver_version;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Gpu, model, vendor_id, device_id,
|
||||
dedicated_video_memory,
|
||||
shared_system_memory, driver_version)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Gpu, model, vendor_id, device_id, dedicated_video_memory, shared_system_memory,
|
||||
driver_version)
|
||||
};
|
||||
|
||||
struct GamingFeatures {
|
||||
|
@ -111,10 +107,8 @@ struct GamingFeatures {
|
|||
optional<bool> game_mode_enabled;
|
||||
optional<bool> hags_enabled;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(GamingFeatures, game_bar_enabled,
|
||||
game_dvr_allowed, game_dvr_enabled,
|
||||
game_dvr_bg_recording, game_mode_enabled,
|
||||
hags_enabled)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(GamingFeatures, game_bar_enabled, game_dvr_allowed, game_dvr_enabled,
|
||||
game_dvr_bg_recording, game_mode_enabled, hags_enabled)
|
||||
};
|
||||
|
||||
struct System {
|
||||
|
@ -127,8 +121,7 @@ struct System {
|
|||
bool arm;
|
||||
bool armEmulation;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(System, version, name, build, release,
|
||||
revision, bits, arm, armEmulation)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(System, version, name, build, release, revision, bits, arm, armEmulation)
|
||||
};
|
||||
|
||||
struct Capabilities {
|
||||
|
@ -138,8 +131,7 @@ struct Capabilities {
|
|||
System system;
|
||||
optional<std::vector<Gpu>> gpu;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Capabilities, cpu, memory,
|
||||
gaming_features, system, gpu)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Capabilities, cpu, memory, gaming_features, system, gpu)
|
||||
};
|
||||
|
||||
struct Preferences {
|
||||
|
@ -153,10 +145,8 @@ struct Preferences {
|
|||
uint32_t canvas_height;
|
||||
optional<uint32_t> composition_gpu_index;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Preferences, maximum_aggregate_bitrate,
|
||||
maximum_video_tracks, vod_track_audio,
|
||||
width, height, framerate, canvas_width,
|
||||
canvas_height, composition_gpu_index)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Preferences, maximum_aggregate_bitrate, maximum_video_tracks, vod_track_audio,
|
||||
width, height, framerate, canvas_width, canvas_height, composition_gpu_index)
|
||||
};
|
||||
|
||||
struct PostData {
|
||||
|
@ -168,8 +158,7 @@ struct PostData {
|
|||
Capabilities capabilities;
|
||||
Preferences preferences;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PostData, service, schema_version,
|
||||
authentication, client, capabilities,
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(PostData, service, schema_version, authentication, client, capabilities,
|
||||
preferences)
|
||||
};
|
||||
|
||||
|
@ -190,13 +179,12 @@ enum struct StatusResult {
|
|||
Error,
|
||||
};
|
||||
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(StatusResult,
|
||||
{
|
||||
{StatusResult::Unknown, nullptr},
|
||||
{StatusResult::Success, "success"},
|
||||
{StatusResult::Warning, "warning"},
|
||||
{StatusResult::Error, "error"},
|
||||
})
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM(StatusResult, {
|
||||
{StatusResult::Unknown, nullptr},
|
||||
{StatusResult::Success, "success"},
|
||||
{StatusResult::Warning, "warning"},
|
||||
{StatusResult::Error, "error"},
|
||||
})
|
||||
|
||||
struct Status {
|
||||
StatusResult result = StatusResult::Unknown;
|
||||
|
@ -209,9 +197,7 @@ struct IngestEndpoint {
|
|||
string url_template;
|
||||
optional<string> authentication;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(IngestEndpoint, protocol,
|
||||
url_template,
|
||||
authentication)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(IngestEndpoint, protocol, url_template, authentication)
|
||||
};
|
||||
|
||||
struct VideoEncoderConfiguration {
|
||||
|
@ -222,10 +208,8 @@ struct VideoEncoderConfiguration {
|
|||
optional<obs_scale_type> gpu_scale_type;
|
||||
json settings;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(VideoEncoderConfiguration,
|
||||
type, width, height,
|
||||
framerate, gpu_scale_type,
|
||||
settings)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(VideoEncoderConfiguration, type, width, height, framerate,
|
||||
gpu_scale_type, settings)
|
||||
};
|
||||
|
||||
struct AudioEncoderConfiguration {
|
||||
|
@ -234,16 +218,14 @@ struct AudioEncoderConfiguration {
|
|||
uint32_t channels;
|
||||
json settings;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(AudioEncoderConfiguration, codec,
|
||||
track_id, channels, settings)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(AudioEncoderConfiguration, codec, track_id, channels, settings)
|
||||
};
|
||||
|
||||
struct AudioConfigurations {
|
||||
std::vector<AudioEncoderConfiguration> live;
|
||||
optional<std::vector<AudioEncoderConfiguration>> vod;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(AudioConfigurations, live,
|
||||
vod)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(AudioConfigurations, live, vod)
|
||||
};
|
||||
|
||||
struct Config {
|
||||
|
@ -253,9 +235,7 @@ struct Config {
|
|||
std::vector<VideoEncoderConfiguration> encoder_configurations;
|
||||
AudioConfigurations audio_configurations;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Config, meta, status,
|
||||
ingest_endpoints,
|
||||
encoder_configurations,
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Config, meta, status, ingest_endpoints, encoder_configurations,
|
||||
audio_configurations)
|
||||
};
|
||||
} // namespace GoLiveApi
|
||||
|
|
|
@ -19,21 +19,17 @@ MultitrackVideoError MultitrackVideoError::cancel()
|
|||
return {Type::Cancel, {}};
|
||||
}
|
||||
|
||||
bool MultitrackVideoError::ShowDialog(
|
||||
QWidget *parent, const QString &multitrack_video_name) const
|
||||
bool MultitrackVideoError::ShowDialog(QWidget *parent, const QString &multitrack_video_name) const
|
||||
{
|
||||
QMessageBox mb(parent);
|
||||
mb.setTextFormat(Qt::RichText);
|
||||
mb.setWindowTitle(QTStr("Output.StartStreamFailed"));
|
||||
|
||||
if (type == Type::Warning) {
|
||||
mb.setText(
|
||||
error +
|
||||
QTStr("FailedToStartStream.WarningRetryNonMultitrackVideo")
|
||||
.arg(multitrack_video_name));
|
||||
mb.setText(error +
|
||||
QTStr("FailedToStartStream.WarningRetryNonMultitrackVideo").arg(multitrack_video_name));
|
||||
mb.setIcon(QMessageBox::Warning);
|
||||
QAbstractButton *yesButton =
|
||||
mb.addButton(QTStr("Yes"), QMessageBox::YesRole);
|
||||
QAbstractButton *yesButton = mb.addButton(QTStr("Yes"), QMessageBox::YesRole);
|
||||
mb.addButton(QTStr("No"), QMessageBox::NoRole);
|
||||
mb.exec();
|
||||
|
||||
|
@ -41,8 +37,7 @@ bool MultitrackVideoError::ShowDialog(
|
|||
} else if (type == Type::Critical) {
|
||||
mb.setText(error);
|
||||
mb.setIcon(QMessageBox::Critical);
|
||||
mb.setStandardButtons(
|
||||
QMessageBox::StandardButton::Ok); // cannot continue
|
||||
mb.setStandardButtons(QMessageBox::StandardButton::Ok); // cannot continue
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@ struct MultitrackVideoError {
|
|||
static MultitrackVideoError warning(QString error);
|
||||
static MultitrackVideoError cancel();
|
||||
|
||||
bool ShowDialog(QWidget *parent,
|
||||
const QString &multitrack_video_name) const;
|
||||
bool ShowDialog(QWidget *parent, const QString &multitrack_video_name) const;
|
||||
|
||||
enum struct Type {
|
||||
Critical,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,24 +25,17 @@ bool MultitrackVideoDeveloperModeEnabled();
|
|||
|
||||
struct MultitrackVideoOutput {
|
||||
public:
|
||||
void PrepareStreaming(QWidget *parent, const char *service_name,
|
||||
obs_service_t *service,
|
||||
const std::optional<std::string> &rtmp_url,
|
||||
const QString &stream_key,
|
||||
const char *audio_encoder_id,
|
||||
std::optional<uint32_t> maximum_aggregate_bitrate,
|
||||
std::optional<uint32_t> maximum_video_tracks,
|
||||
std::optional<std::string> custom_config,
|
||||
obs_data_t *dump_stream_to_file_config,
|
||||
size_t main_audio_mixer,
|
||||
void PrepareStreaming(QWidget *parent, const char *service_name, obs_service_t *service,
|
||||
const std::optional<std::string> &rtmp_url, const QString &stream_key,
|
||||
const char *audio_encoder_id, std::optional<uint32_t> maximum_aggregate_bitrate,
|
||||
std::optional<uint32_t> maximum_video_tracks, std::optional<std::string> custom_config,
|
||||
obs_data_t *dump_stream_to_file_config, size_t main_audio_mixer,
|
||||
std::optional<size_t> vod_track_mixer);
|
||||
signal_handler_t *StreamingSignalHandler();
|
||||
void StartedStreaming();
|
||||
void StopStreaming();
|
||||
bool HandleIncompatibleSettings(QWidget *parent, config_t *config,
|
||||
obs_service_t *service, bool &useDelay,
|
||||
bool &enableNewSocketLoop,
|
||||
bool &enableDynBitrate);
|
||||
bool HandleIncompatibleSettings(QWidget *parent, config_t *config, obs_service_t *service, bool &useDelay,
|
||||
bool &enableNewSocketLoop, bool &enableDynBitrate);
|
||||
|
||||
OBSOutputAutoRelease StreamingOutput()
|
||||
{
|
||||
|
@ -62,8 +55,7 @@ private:
|
|||
std::optional<OBSOutputObjects> take_current();
|
||||
std::optional<OBSOutputObjects> take_current_stream_dump();
|
||||
|
||||
static void
|
||||
ReleaseOnMainThread(std::optional<OBSOutputObjects> objects);
|
||||
static void ReleaseOnMainThread(std::optional<OBSOutputObjects> objects);
|
||||
|
||||
std::mutex current_mutex;
|
||||
std::optional<OBSOutputObjects> current;
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
Multiview::Multiview()
|
||||
{
|
||||
InitSafeAreas(&actionSafeMargin, &graphicsSafeMargin,
|
||||
&fourByThreeSafeMargin, &leftLine, &topLine, &rightLine);
|
||||
InitSafeAreas(&actionSafeMargin, &graphicsSafeMargin, &fourByThreeSafeMargin, &leftLine, &topLine, &rightLine);
|
||||
}
|
||||
|
||||
Multiview::~Multiview()
|
||||
|
@ -59,14 +58,12 @@ static OBSSource CreateLabel(const char *name, size_t h)
|
|||
const char *text_source_id = "text_ft2_source";
|
||||
#endif
|
||||
|
||||
OBSSourceAutoRelease txtSource =
|
||||
obs_source_create_private(text_source_id, name, settings);
|
||||
OBSSourceAutoRelease txtSource = obs_source_create_private(text_source_id, name, settings);
|
||||
|
||||
return txtSource.Get();
|
||||
}
|
||||
|
||||
void Multiview::Update(MultiviewLayout multiviewLayout, bool drawLabel,
|
||||
bool drawSafeArea)
|
||||
void Multiview::Update(MultiviewLayout multiviewLayout, bool drawLabel, bool drawSafeArea)
|
||||
{
|
||||
this->multiviewLayout = multiviewLayout;
|
||||
this->drawLabel = drawLabel;
|
||||
|
@ -87,10 +84,8 @@ void Multiview::Update(MultiviewLayout multiviewLayout, bool drawLabel,
|
|||
struct obs_frontend_source_list scenes = {};
|
||||
obs_frontend_get_scenes(&scenes);
|
||||
|
||||
multiviewLabels.emplace_back(
|
||||
CreateLabel(Str("StudioMode.Preview"), h / 2));
|
||||
multiviewLabels.emplace_back(
|
||||
CreateLabel(Str("StudioMode.Program"), h / 2));
|
||||
multiviewLabels.emplace_back(CreateLabel(Str("StudioMode.Preview"), h / 2));
|
||||
multiviewLabels.emplace_back(CreateLabel(Str("StudioMode.Program"), h / 2));
|
||||
|
||||
switch (multiviewLayout) {
|
||||
case MultiviewLayout::HORIZONTAL_TOP_18_SCENES:
|
||||
|
@ -175,15 +170,13 @@ void Multiview::Update(MultiviewLayout multiviewLayout, bool drawLabel,
|
|||
multiviewScenes.emplace_back(OBSGetWeakRef(src));
|
||||
obs_source_inc_showing(src);
|
||||
|
||||
multiviewLabels.emplace_back(
|
||||
CreateLabel(obs_source_get_name(src), h / 3));
|
||||
multiviewLabels.emplace_back(CreateLabel(obs_source_get_name(src), h / 3));
|
||||
}
|
||||
|
||||
obs_frontend_source_list_free(&scenes);
|
||||
}
|
||||
|
||||
static inline uint32_t labelOffset(MultiviewLayout multiviewLayout,
|
||||
obs_source_t *label, uint32_t cx)
|
||||
static inline uint32_t labelOffset(MultiviewLayout multiviewLayout, obs_source_t *label, uint32_t cx)
|
||||
{
|
||||
uint32_t w = obs_source_get_width(label);
|
||||
|
||||
|
@ -232,8 +225,7 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
|
||||
auto drawBox = [&](float cx, float cy, uint32_t colorVal) {
|
||||
gs_effect_t *solid = obs_get_base_effect(OBS_EFFECT_SOLID);
|
||||
gs_eparam_t *color =
|
||||
gs_effect_get_param_by_name(solid, "color");
|
||||
gs_eparam_t *color = gs_effect_get_param_by_name(solid, "color");
|
||||
|
||||
gs_effect_set_color(color, colorVal);
|
||||
while (gs_effect_loop(solid, "Solid"))
|
||||
|
@ -375,8 +367,7 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
}
|
||||
};
|
||||
|
||||
auto paintAreaWithColor = [&](float tx, float ty, float cx, float cy,
|
||||
uint32_t color) {
|
||||
auto paintAreaWithColor = [&](float tx, float ty, float cx, float cy, uint32_t color) {
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(tx, ty, 0.0f);
|
||||
drawBox(cx, cy, color);
|
||||
|
@ -384,8 +375,7 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
};
|
||||
|
||||
// Define the whole usable region for the multiview
|
||||
startRegion(x, y, targetCX * scale, targetCY * scale, 0.0f, fw, 0.0f,
|
||||
fh);
|
||||
startRegion(x, y, targetCX * scale, targetCY * scale, 0.0f, fw, 0.0f, fh);
|
||||
|
||||
// Change the background color to highlight all sources
|
||||
drawBox(fw, fh, outerColor);
|
||||
|
@ -399,10 +389,8 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
|
||||
if (i >= numSrcs) {
|
||||
// Just paint the background and continue
|
||||
paintAreaWithColor(sourceX, sourceY, scenesCX, scenesCY,
|
||||
outerColor);
|
||||
paintAreaWithColor(siX, siY, siCX, siCY,
|
||||
backgroundColor);
|
||||
paintAreaWithColor(sourceX, sourceY, scenesCX, scenesCY, outerColor);
|
||||
paintAreaWithColor(siX, siY, siCX, siCY, backgroundColor);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -416,8 +404,7 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
colorVal = studioMode ? previewColor : programColor;
|
||||
|
||||
// Paint the background
|
||||
paintAreaWithColor(sourceX, sourceY, scenesCX, scenesCY,
|
||||
colorVal);
|
||||
paintAreaWithColor(sourceX, sourceY, scenesCX, scenesCY, colorVal);
|
||||
paintAreaWithColor(siX, siY, siCX, siCY, backgroundColor);
|
||||
|
||||
/* ----------- */
|
||||
|
@ -444,15 +431,11 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
offset = labelOffset(multiviewLayout, label, scenesCX);
|
||||
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(
|
||||
sourceX + offset,
|
||||
sourceY + scenesCY -
|
||||
(obs_source_get_height(label) * ppiScaleY) -
|
||||
(thickness * 3),
|
||||
0.0f);
|
||||
gs_matrix_translate3f(sourceX + offset,
|
||||
sourceY + scenesCY - (obs_source_get_height(label) * ppiScaleY) - (thickness * 3),
|
||||
0.0f);
|
||||
gs_matrix_scale3f(ppiScaleX, ppiScaleY, 1.0f);
|
||||
drawBox(obs_source_get_width(label),
|
||||
obs_source_get_height(label) + thicknessx2, labelColor);
|
||||
drawBox(obs_source_get_width(label), obs_source_get_height(label) + thicknessx2, labelColor);
|
||||
gs_matrix_translate3f(0, thickness, 0.0f);
|
||||
obs_source_video_render(label);
|
||||
gs_matrix_pop();
|
||||
|
@ -504,15 +487,9 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
if (drawLabel) {
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(
|
||||
labelX,
|
||||
labelY -
|
||||
(obs_source_get_height(previewLabel) *
|
||||
ppiScaleY) -
|
||||
(thickness * 3),
|
||||
0.0f);
|
||||
labelX, labelY - (obs_source_get_height(previewLabel) * ppiScaleY) - (thickness * 3), 0.0f);
|
||||
gs_matrix_scale3f(ppiScaleX, ppiScaleY, 1.0f);
|
||||
drawBox(obs_source_get_width(previewLabel),
|
||||
obs_source_get_height(previewLabel) + thicknessx2,
|
||||
drawBox(obs_source_get_width(previewLabel), obs_source_get_height(previewLabel) + thicknessx2,
|
||||
labelColor);
|
||||
gs_matrix_translate3f(0, thickness, 0.0f);
|
||||
obs_source_video_render(previewLabel);
|
||||
|
@ -543,15 +520,9 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
if (drawLabel) {
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(
|
||||
labelX,
|
||||
labelY -
|
||||
(obs_source_get_height(programLabel) *
|
||||
ppiScaleY) -
|
||||
(thickness * 3),
|
||||
0.0f);
|
||||
labelX, labelY - (obs_source_get_height(programLabel) * ppiScaleY) - (thickness * 3), 0.0f);
|
||||
gs_matrix_scale3f(ppiScaleX, ppiScaleY, 1.0f);
|
||||
drawBox(obs_source_get_width(programLabel),
|
||||
obs_source_get_height(programLabel) + thicknessx2,
|
||||
drawBox(obs_source_get_width(programLabel), obs_source_get_height(programLabel) + thicknessx2,
|
||||
labelColor);
|
||||
gs_matrix_translate3f(0, thickness, 0.0f);
|
||||
obs_source_video_render(programLabel);
|
||||
|
@ -561,10 +532,8 @@ void Multiview::Render(uint32_t cx, uint32_t cy)
|
|||
// Region for future usage with additional info.
|
||||
if (multiviewLayout == MultiviewLayout::HORIZONTAL_TOP_24_SCENES) {
|
||||
// Just paint the background for now
|
||||
paintAreaWithColor(thickness, thickness, siCX,
|
||||
siCY * 2 + thicknessx2, backgroundColor);
|
||||
paintAreaWithColor(thickness + 2.5 * (thicknessx2 + ppiCX),
|
||||
thickness, siCX, siCY * 2 + thicknessx2,
|
||||
paintAreaWithColor(thickness, thickness, siCX, siCY * 2 + thicknessx2, backgroundColor);
|
||||
paintAreaWithColor(thickness + 2.5 * (thicknessx2 + ppiCX), thickness, siCX, siCY * 2 + thicknessx2,
|
||||
backgroundColor);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ class Multiview {
|
|||
public:
|
||||
Multiview();
|
||||
~Multiview();
|
||||
void Update(MultiviewLayout multiviewLayout, bool drawLabel,
|
||||
bool drawSafeArea);
|
||||
void Update(MultiviewLayout multiviewLayout, bool drawLabel, bool drawSafeArea);
|
||||
void Render(uint32_t cx, uint32_t cy);
|
||||
OBSSource GetSourceByPosition(int x, int y);
|
||||
|
||||
|
@ -41,10 +40,9 @@ private:
|
|||
|
||||
// Multiview position helpers
|
||||
float thickness = 6;
|
||||
float offset, thicknessx2 = thickness * 2, pvwprgCX, pvwprgCY, sourceX,
|
||||
sourceY, labelX, labelY, scenesCX, scenesCY, ppiCX, ppiCY,
|
||||
siX, siY, siCX, siCY, ppiScaleX, ppiScaleY, siScaleX,
|
||||
siScaleY, fw, fh, ratio;
|
||||
float offset, thicknessx2 = thickness * 2, pvwprgCX, pvwprgCY, sourceX, sourceY, labelX, labelY, scenesCX,
|
||||
scenesCY, ppiCX, ppiCY, siX, siY, siCX, siCY, ppiScaleX, ppiScaleY, siScaleX, siScaleY, fw, fh,
|
||||
ratio;
|
||||
|
||||
// argb colors
|
||||
static const uint32_t outerColor = 0xFF999999;
|
||||
|
@ -54,8 +52,7 @@ private:
|
|||
static const uint32_t programColor = 0xFFD00000;
|
||||
};
|
||||
|
||||
static inline void startRegion(int vX, int vY, int vCX, int vCY, float oL,
|
||||
float oR, float oT, float oB)
|
||||
static inline void startRegion(int vX, int vY, int vCX, int vCY, float oL, float oR, float oT, float oB)
|
||||
{
|
||||
gs_projection_push();
|
||||
gs_viewport_push();
|
||||
|
|
|
@ -11,13 +11,6 @@ class NonCheckableButton : public QPushButton {
|
|||
inline void nextCheckState() override {}
|
||||
|
||||
public:
|
||||
inline NonCheckableButton(QWidget *parent = nullptr)
|
||||
: QPushButton(parent)
|
||||
{
|
||||
}
|
||||
inline NonCheckableButton(const QString &text,
|
||||
QWidget *parent = nullptr)
|
||||
: QPushButton(text, parent)
|
||||
{
|
||||
}
|
||||
inline NonCheckableButton(QWidget *parent = nullptr) : QPushButton(parent) {}
|
||||
inline NonCheckableButton(const QString &text, QWidget *parent = nullptr) : QPushButton(text, parent) {}
|
||||
};
|
||||
|
|
3
UI/obf.c
3
UI/obf.c
|
@ -13,8 +13,7 @@ void deobfuscate_str(char *str, uint64_t val)
|
|||
int pos = i / 2;
|
||||
bool bottom = (i % 2) == 0;
|
||||
uint8_t *ch = (uint8_t *)str;
|
||||
uint8_t xor = bottom ? LOWER_HALFBYTE(dec_val[pos])
|
||||
: UPPER_HALFBYTE(dec_val[pos]);
|
||||
uint8_t xor = bottom ? LOWER_HALFBYTE(dec_val[pos]) : UPPER_HALFBYTE(dec_val[pos]);
|
||||
|
||||
*ch ^= xor;
|
||||
|
||||
|
|
|
@ -81,13 +81,11 @@ static optional<OBSTheme> ParseThemeMeta(const QString &path)
|
|||
if (!cf_next_token(cfp))
|
||||
return nullopt;
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_NAME, "name",
|
||||
nullptr);
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_NAME, "name", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
break;
|
||||
|
||||
string name(cfp->cur_token->str.array,
|
||||
cfp->cur_token->str.len);
|
||||
string name(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ":", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
|
@ -96,14 +94,12 @@ static optional<OBSTheme> ParseThemeMeta(const QString &path)
|
|||
if (!cf_next_token(cfp))
|
||||
return nullopt;
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_STRING, "value",
|
||||
";");
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_STRING, "value", ";");
|
||||
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
|
||||
BPtr str = cf_literal_to_str(cfp->cur_token->str.array,
|
||||
cfp->cur_token->str.len);
|
||||
BPtr str = cf_literal_to_str(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
|
||||
if (str) {
|
||||
if (name == "dark")
|
||||
|
@ -127,8 +123,7 @@ static optional<OBSTheme> ParseThemeMeta(const QString &path)
|
|||
meta.isBaseTheme = filepath.extension() == ".obt";
|
||||
meta.filename = filepath.stem();
|
||||
|
||||
if (meta.id.isEmpty() || meta.name.isEmpty() ||
|
||||
(!meta.isBaseTheme && meta.extends.isEmpty())) {
|
||||
if (meta.id.isEmpty() || meta.name.isEmpty() || (!meta.isBaseTheme && meta.extends.isEmpty())) {
|
||||
/* Theme is invalid */
|
||||
return nullopt;
|
||||
} else {
|
||||
|
@ -156,8 +151,7 @@ static bool ParseVarName(CFParser &cfp, QString &value)
|
|||
if (!cf_next_token(cfp))
|
||||
return false;
|
||||
|
||||
value = QString::fromUtf8(cfp->cur_token->str.array,
|
||||
cfp->cur_token->str.len);
|
||||
value = QString::fromUtf8(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ")", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
|
@ -212,8 +206,7 @@ static QColor ParseColor(CFParser &cfp)
|
|||
return res;
|
||||
}
|
||||
|
||||
static bool ParseCalc(CFParser &cfp, QStringList &calc,
|
||||
vector<OBSThemeVariable> &vars)
|
||||
static bool ParseCalc(CFParser &cfp, QStringList &calc, vector<OBSThemeVariable> &vars)
|
||||
{
|
||||
int ret = cf_next_token_should_be(cfp, "(", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
|
@ -231,9 +224,7 @@ static bool ParseCalc(CFParser &cfp, QStringList &calc,
|
|||
OBSThemeVariable var;
|
||||
QStringList subcalc;
|
||||
|
||||
var.name = QString("__unnamed_%1")
|
||||
.arg(QRandomGenerator::global()
|
||||
->generate64());
|
||||
var.name = QString("__unnamed_%1").arg(QRandomGenerator::global()->generate64());
|
||||
|
||||
if (!ParseCalc(cfp, subcalc, vars))
|
||||
return false;
|
||||
|
@ -249,8 +240,7 @@ static bool ParseCalc(CFParser &cfp, QStringList &calc,
|
|||
|
||||
calc << value;
|
||||
} else {
|
||||
calc << QString::fromUtf8(cfp->cur_token->str.array,
|
||||
cfp->cur_token->str.len);
|
||||
calc << QString::fromUtf8(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp))
|
||||
|
@ -305,8 +295,7 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
|||
if (ret != PARSE_SUCCESS)
|
||||
break;
|
||||
|
||||
QString key = QString::fromUtf8(cfp->cur_token->str.array,
|
||||
cfp->cur_token->str.len);
|
||||
QString key = QString::fromUtf8(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
OBSThemeVariable var;
|
||||
var.name = key;
|
||||
|
||||
|
@ -318,8 +307,7 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
|||
const QString osPrefix = "os_lin_";
|
||||
#endif
|
||||
|
||||
if (key.startsWith(osPrefix) &&
|
||||
key.length() > osPrefix.length()) {
|
||||
if (key.startsWith(osPrefix) && key.length() > osPrefix.length()) {
|
||||
var.name = key.sliced(osPrefix.length());
|
||||
}
|
||||
|
||||
|
@ -340,17 +328,14 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
|||
|
||||
/* Look for a suffix and mark variable as size if it exists */
|
||||
while (ch < end) {
|
||||
if (!isdigit(*ch) && !isspace(*ch) &&
|
||||
*ch != '.') {
|
||||
var.suffix =
|
||||
QString::fromUtf8(ch, end - ch);
|
||||
if (!isdigit(*ch) && !isspace(*ch) && *ch != '.') {
|
||||
var.suffix = QString::fromUtf8(ch, end - ch);
|
||||
var.type = OBSThemeVariable::Size;
|
||||
break;
|
||||
}
|
||||
ch++;
|
||||
}
|
||||
} else if (cf_token_is(cfp, "rgb") || cf_token_is(cfp, "#") ||
|
||||
cf_token_is(cfp, "bikeshed")) {
|
||||
} else if (cf_token_is(cfp, "rgb") || cf_token_is(cfp, "#") || cf_token_is(cfp, "bikeshed")) {
|
||||
QColor color = ParseColor(cfp);
|
||||
if (!color.isValid())
|
||||
continue;
|
||||
|
@ -375,9 +360,7 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
|||
var.value = calc;
|
||||
} else {
|
||||
var.type = OBSThemeVariable::String;
|
||||
BPtr strVal =
|
||||
cf_literal_to_str(cfp->cur_token->str.array,
|
||||
cfp->cur_token->str.len);
|
||||
BPtr strVal = cf_literal_to_str(cfp->cur_token->str.array, cfp->cur_token->str.len);
|
||||
var.value = QString::fromUtf8(strVal.Get());
|
||||
}
|
||||
|
||||
|
@ -385,12 +368,9 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
|||
return vars;
|
||||
|
||||
if (cf_token_is(cfp, "!") &&
|
||||
cf_next_token_should_be(cfp, "editable", nullptr,
|
||||
nullptr) == PARSE_SUCCESS) {
|
||||
if (var.type == OBSThemeVariable::Calc ||
|
||||
var.type == OBSThemeVariable::Alias) {
|
||||
blog(LOG_WARNING,
|
||||
"Variable of calc/alias type cannot be editable: %s",
|
||||
cf_next_token_should_be(cfp, "editable", nullptr, nullptr) == PARSE_SUCCESS) {
|
||||
if (var.type == OBSThemeVariable::Calc || var.type == OBSThemeVariable::Alias) {
|
||||
blog(LOG_WARNING, "Variable of calc/alias type cannot be editable: %s",
|
||||
QT_TO_UTF8(var.name));
|
||||
} else {
|
||||
var.editable = true;
|
||||
|
@ -399,8 +379,7 @@ static vector<OBSThemeVariable> ParseThemeVariables(const char *themeData)
|
|||
|
||||
vars.push_back(std::move(var));
|
||||
|
||||
if (!cf_token_is(cfp, ";") &&
|
||||
!cf_go_to_token(cfp, ";", nullptr))
|
||||
if (!cf_token_is(cfp, ";") && !cf_go_to_token(cfp, ";", nullptr))
|
||||
return vars;
|
||||
}
|
||||
|
||||
|
@ -419,8 +398,7 @@ void OBSApp::FindThemes()
|
|||
{
|
||||
string themeDir;
|
||||
GetDataFilePath("themes/", themeDir);
|
||||
QDirIterator it(QString::fromStdString(themeDir), filters,
|
||||
QDir::Files);
|
||||
QDirIterator it(QString::fromStdString(themeDir), filters, QDir::Files);
|
||||
while (it.hasNext()) {
|
||||
auto theme = ParseThemeMeta(it.next());
|
||||
if (theme && !themes.contains(theme->id))
|
||||
|
@ -429,12 +407,9 @@ void OBSApp::FindThemes()
|
|||
}
|
||||
|
||||
{
|
||||
const std::string themeDir =
|
||||
App()->userConfigLocation.u8string() +
|
||||
"/obs-studio/themes";
|
||||
const std::string themeDir = App()->userConfigLocation.u8string() + "/obs-studio/themes";
|
||||
|
||||
QDirIterator it(QString::fromStdString(themeDir), filters,
|
||||
QDir::Files);
|
||||
QDirIterator it(QString::fromStdString(themeDir), filters, QDir::Files);
|
||||
|
||||
while (it.hasNext()) {
|
||||
auto theme = ParseThemeMeta(it.next());
|
||||
|
@ -449,8 +424,7 @@ void OBSApp::FindThemes()
|
|||
for (OBSTheme &theme : themes) {
|
||||
if (theme.extends.isEmpty()) {
|
||||
if (!theme.isBaseTheme) {
|
||||
blog(LOG_ERROR,
|
||||
R"(Theme "%s" is not base, but does not specify parent!)",
|
||||
blog(LOG_ERROR, R"(Theme "%s" is not base, but does not specify parent!)",
|
||||
QT_TO_UTF8(theme.id));
|
||||
invalid.insert(theme.id);
|
||||
}
|
||||
|
@ -462,46 +436,36 @@ void OBSApp::FindThemes()
|
|||
while (!parentId.isEmpty()) {
|
||||
OBSTheme *parent = GetTheme(parentId);
|
||||
if (!parent) {
|
||||
blog(LOG_ERROR,
|
||||
R"(Theme "%s" is missing ancestor "%s"!)",
|
||||
QT_TO_UTF8(theme.id),
|
||||
blog(LOG_ERROR, R"(Theme "%s" is missing ancestor "%s"!)", QT_TO_UTF8(theme.id),
|
||||
QT_TO_UTF8(parentId));
|
||||
invalid.insert(theme.id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (theme.isBaseTheme && !parent->isBaseTheme) {
|
||||
blog(LOG_ERROR,
|
||||
R"(Ancestor "%s" of base theme "%s" is not a base theme!)",
|
||||
QT_TO_UTF8(parent->id),
|
||||
QT_TO_UTF8(theme.id));
|
||||
blog(LOG_ERROR, R"(Ancestor "%s" of base theme "%s" is not a base theme!)",
|
||||
QT_TO_UTF8(parent->id), QT_TO_UTF8(theme.id));
|
||||
invalid.insert(theme.id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (parent->id == theme.id ||
|
||||
theme.dependencies.contains(parent->id)) {
|
||||
blog(LOG_ERROR,
|
||||
R"(Dependency chain of "%s" ("%s") contains recursion!)",
|
||||
QT_TO_UTF8(theme.id),
|
||||
QT_TO_UTF8(parent->id));
|
||||
if (parent->id == theme.id || theme.dependencies.contains(parent->id)) {
|
||||
blog(LOG_ERROR, R"(Dependency chain of "%s" ("%s") contains recursion!)",
|
||||
QT_TO_UTF8(theme.id), QT_TO_UTF8(parent->id));
|
||||
invalid.insert(theme.id);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mark this theme as a variant of first parent that is a base theme. */
|
||||
if (!theme.isBaseTheme && parent->isBaseTheme &&
|
||||
theme.parent.isEmpty())
|
||||
if (!theme.isBaseTheme && parent->isBaseTheme && theme.parent.isEmpty())
|
||||
theme.parent = parent->id;
|
||||
|
||||
theme.dependencies.push_front(parent->id);
|
||||
parentId = parent->extends;
|
||||
|
||||
if (parentId.isEmpty() && !parent->isBaseTheme) {
|
||||
blog(LOG_ERROR,
|
||||
R"(Final ancestor of "%s" ("%s") is not a base theme!)",
|
||||
QT_TO_UTF8(theme.id),
|
||||
QT_TO_UTF8(parent->id));
|
||||
blog(LOG_ERROR, R"(Final ancestor of "%s" ("%s") is not a base theme!)",
|
||||
QT_TO_UTF8(theme.id), QT_TO_UTF8(parent->id));
|
||||
invalid.insert(theme.id);
|
||||
break;
|
||||
}
|
||||
|
@ -513,8 +477,7 @@ void OBSApp::FindThemes()
|
|||
}
|
||||
}
|
||||
|
||||
static bool ResolveVariable(const QHash<QString, OBSThemeVariable> &vars,
|
||||
OBSThemeVariable &var)
|
||||
static bool ResolveVariable(const QHash<QString, OBSThemeVariable> &vars, OBSThemeVariable &var)
|
||||
{
|
||||
if (var.type != OBSThemeVariable::Alias)
|
||||
return true;
|
||||
|
@ -524,9 +487,8 @@ static bool ResolveVariable(const QHash<QString, OBSThemeVariable> &vars,
|
|||
key = vars[key].value.toString();
|
||||
|
||||
if (!vars.contains(key)) {
|
||||
blog(LOG_ERROR,
|
||||
R"(Variable "%s" (aliased by "%s") does not exist!)",
|
||||
QT_TO_UTF8(key), QT_TO_UTF8(var.name));
|
||||
blog(LOG_ERROR, R"(Variable "%s" (aliased by "%s") does not exist!)", QT_TO_UTF8(key),
|
||||
QT_TO_UTF8(var.name));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -536,12 +498,11 @@ static bool ResolveVariable(const QHash<QString, OBSThemeVariable> &vars,
|
|||
return true;
|
||||
}
|
||||
|
||||
static QString EvalCalc(const QHash<QString, OBSThemeVariable> &vars,
|
||||
const OBSThemeVariable &var, const int recursion = 0);
|
||||
static QString EvalCalc(const QHash<QString, OBSThemeVariable> &vars, const OBSThemeVariable &var,
|
||||
const int recursion = 0);
|
||||
|
||||
static OBSThemeVariable
|
||||
ParseCalcVariable(const QHash<QString, OBSThemeVariable> &vars,
|
||||
const QString &value, const int recursion = 0)
|
||||
static OBSThemeVariable ParseCalcVariable(const QHash<QString, OBSThemeVariable> &vars, const QString &value,
|
||||
const int recursion = 0)
|
||||
{
|
||||
OBSThemeVariable var;
|
||||
const QByteArray utf8 = value.toUtf8();
|
||||
|
@ -555,8 +516,7 @@ ParseCalcVariable(const QHash<QString, OBSThemeVariable> &vars,
|
|||
const char *dataEnd = data + utf8.size();
|
||||
while (data < dataEnd) {
|
||||
if (*data && !isdigit(*data) && *data != '.') {
|
||||
var.suffix =
|
||||
QString::fromUtf8(data, dataEnd - data);
|
||||
var.suffix = QString::fromUtf8(data, dataEnd - data);
|
||||
var.type = OBSThemeVariable::Size;
|
||||
break;
|
||||
}
|
||||
|
@ -576,11 +536,8 @@ ParseCalcVariable(const QHash<QString, OBSThemeVariable> &vars,
|
|||
}
|
||||
|
||||
/* Only number or size would be valid here */
|
||||
if (var.type != OBSThemeVariable::Number &&
|
||||
var.type != OBSThemeVariable::Size) {
|
||||
blog(LOG_ERROR,
|
||||
"calc() operand is not a size or number: %s",
|
||||
QT_TO_UTF8(var.value.toString()));
|
||||
if (var.type != OBSThemeVariable::Number && var.type != OBSThemeVariable::Size) {
|
||||
blog(LOG_ERROR, "calc() operand is not a size or number: %s", QT_TO_UTF8(var.value.toString()));
|
||||
throw invalid_argument("Operand not of numeric type");
|
||||
}
|
||||
}
|
||||
|
@ -588,8 +545,7 @@ ParseCalcVariable(const QHash<QString, OBSThemeVariable> &vars,
|
|||
return var;
|
||||
}
|
||||
|
||||
static QString EvalCalc(const QHash<QString, OBSThemeVariable> &vars,
|
||||
const OBSThemeVariable &var, const int recursion)
|
||||
static QString EvalCalc(const QHash<QString, OBSThemeVariable> &vars, const OBSThemeVariable &var, const int recursion)
|
||||
{
|
||||
if (recursion >= 10) {
|
||||
/* Abort after 10 levels of recursion */
|
||||
|
@ -599,16 +555,14 @@ static QString EvalCalc(const QHash<QString, OBSThemeVariable> &vars,
|
|||
|
||||
QStringList args = var.value.toStringList();
|
||||
if (args.length() != 3) {
|
||||
blog(LOG_ERROR,
|
||||
"calc() had invalid number of arguments: %lld (%s)",
|
||||
args.length(), QT_TO_UTF8(args.join(", ")));
|
||||
blog(LOG_ERROR, "calc() had invalid number of arguments: %lld (%s)", args.length(),
|
||||
QT_TO_UTF8(args.join(", ")));
|
||||
return "'Invalid expression'";
|
||||
}
|
||||
|
||||
QString &opt = args[1];
|
||||
if (opt != '*' && opt != '+' && opt != '-' && opt != '/') {
|
||||
blog(LOG_ERROR, "Unknown/invalid calc() operator: %s",
|
||||
QT_TO_UTF8(opt));
|
||||
blog(LOG_ERROR, "Unknown/invalid calc() operator: %s", QT_TO_UTF8(opt));
|
||||
return "'Invalid expression'";
|
||||
}
|
||||
|
||||
|
@ -621,19 +575,15 @@ static QString EvalCalc(const QHash<QString, OBSThemeVariable> &vars,
|
|||
}
|
||||
|
||||
/* Ensure that suffixes match (if any) */
|
||||
if (!val1.suffix.isEmpty() && !val2.suffix.isEmpty() &&
|
||||
val1.suffix != val2.suffix) {
|
||||
blog(LOG_ERROR,
|
||||
"calc() requires suffixes to match or only one to be present! %s != %s",
|
||||
if (!val1.suffix.isEmpty() && !val2.suffix.isEmpty() && val1.suffix != val2.suffix) {
|
||||
blog(LOG_ERROR, "calc() requires suffixes to match or only one to be present! %s != %s",
|
||||
QT_TO_UTF8(val1.suffix), QT_TO_UTF8(val2.suffix));
|
||||
return "'Invalid expression'";
|
||||
}
|
||||
|
||||
double val = numeric_limits<double>::quiet_NaN();
|
||||
double d1 = val1.userValue.isValid() ? val1.userValue.toDouble()
|
||||
: val1.value.toDouble();
|
||||
double d2 = val2.userValue.isValid() ? val2.userValue.toDouble()
|
||||
: val2.value.toDouble();
|
||||
double d1 = val1.userValue.isValid() ? val1.userValue.toDouble() : val1.value.toDouble();
|
||||
double d2 = val2.userValue.isValid() ? val2.userValue.toDouble() : val2.value.toDouble();
|
||||
|
||||
if (!isfinite(d1) || !isfinite(d2)) {
|
||||
blog(LOG_ERROR,
|
||||
|
@ -687,8 +637,7 @@ static qsizetype FindEndOfOBSMetadata(const QString &content)
|
|||
return end;
|
||||
}
|
||||
|
||||
static QString PrepareQSS(const QHash<QString, OBSThemeVariable> &vars,
|
||||
const QStringList &contents)
|
||||
static QString PrepareQSS(const QHash<QString, OBSThemeVariable> &vars, const QStringList &contents)
|
||||
{
|
||||
QString stylesheet;
|
||||
QString needleTemplate("var(--%1)");
|
||||
|
@ -710,15 +659,13 @@ static QString PrepareQSS(const QHash<QString, OBSThemeVariable> &vars,
|
|||
QString needle = needleTemplate.arg(var_.name);
|
||||
QString replace;
|
||||
|
||||
QVariant value = var.userValue.isValid() ? var.userValue
|
||||
: var.value;
|
||||
QVariant value = var.userValue.isValid() ? var.userValue : var.value;
|
||||
|
||||
if (var.type == OBSThemeVariable::Color) {
|
||||
replace = value.value<QColor>().name(QColor::HexRgb);
|
||||
} else if (var.type == OBSThemeVariable::Calc) {
|
||||
replace = EvalCalc(vars, var);
|
||||
} else if (var.type == OBSThemeVariable::Size ||
|
||||
var.type == OBSThemeVariable::Number) {
|
||||
} else if (var.type == OBSThemeVariable::Size || var.type == OBSThemeVariable::Number) {
|
||||
double val = value.toDouble();
|
||||
bool isInteger = ceill(val) == val;
|
||||
replace = QString::number(val, 'f', isInteger ? 0 : -1);
|
||||
|
@ -747,8 +694,7 @@ template<typename T> static void FillEnumMap(QHash<QString, T> &map)
|
|||
}
|
||||
}
|
||||
|
||||
static QPalette PreparePalette(const QHash<QString, OBSThemeVariable> &vars,
|
||||
const QPalette &defaultPalette)
|
||||
static QPalette PreparePalette(const QHash<QString, OBSThemeVariable> &vars, const QPalette &defaultPalette)
|
||||
{
|
||||
static QHash<QString, QPalette::ColorRole> roleMap;
|
||||
static QHash<QString, QPalette::ColorGroup> groupMap;
|
||||
|
@ -767,8 +713,7 @@ static QPalette PreparePalette(const QHash<QString, OBSThemeVariable> &vars,
|
|||
continue;
|
||||
|
||||
OBSThemeVariable var(var_);
|
||||
if (!ResolveVariable(vars, var) ||
|
||||
var.type != OBSThemeVariable::Color)
|
||||
if (!ResolveVariable(vars, var) || var.type != OBSThemeVariable::Color)
|
||||
continue;
|
||||
|
||||
/* Determine role and optionally group based on name.
|
||||
|
@ -780,9 +725,7 @@ static QPalette PreparePalette(const QHash<QString, OBSThemeVariable> &vars,
|
|||
if (parts.length() >= 2) {
|
||||
QString key = parts[1].toLower();
|
||||
if (!roleMap.contains(key)) {
|
||||
blog(LOG_WARNING,
|
||||
"Palette role \"%s\" is not valid!",
|
||||
QT_TO_UTF8(parts[1]));
|
||||
blog(LOG_WARNING, "Palette role \"%s\" is not valid!", QT_TO_UTF8(parts[1]));
|
||||
continue;
|
||||
}
|
||||
role = roleMap[key];
|
||||
|
@ -791,16 +734,13 @@ static QPalette PreparePalette(const QHash<QString, OBSThemeVariable> &vars,
|
|||
if (parts.length() == 3) {
|
||||
QString key = parts[2].toLower();
|
||||
if (!groupMap.contains(key)) {
|
||||
blog(LOG_WARNING,
|
||||
"Palette group \"%s\" is not valid!",
|
||||
QT_TO_UTF8(parts[2]));
|
||||
blog(LOG_WARNING, "Palette group \"%s\" is not valid!", QT_TO_UTF8(parts[2]));
|
||||
continue;
|
||||
}
|
||||
group = groupMap[key];
|
||||
}
|
||||
|
||||
QVariant value = var.userValue.isValid() ? var.userValue
|
||||
: var.value;
|
||||
QVariant value = var.userValue.isValid() ? var.userValue : var.value;
|
||||
|
||||
QColor color = value.value<QColor>().name(QColor::HexRgb);
|
||||
pal.setColor(group, role, color);
|
||||
|
@ -860,8 +800,7 @@ bool OBSApp::SetTheme(const QString &name)
|
|||
return false;
|
||||
const QByteArray content = file.readAll();
|
||||
|
||||
for (OBSThemeVariable &var :
|
||||
ParseThemeVariables(content.constData())) {
|
||||
for (OBSThemeVariable &var : ParseThemeVariables(content.constData())) {
|
||||
vars[var.name] = std::move(var);
|
||||
}
|
||||
|
||||
|
@ -881,8 +820,7 @@ bool OBSApp::SetTheme(const QString &name)
|
|||
|
||||
filesystem::path debugOut;
|
||||
char configPath[512];
|
||||
if (GetAppConfigPath(configPath, sizeof(configPath),
|
||||
filename.c_str())) {
|
||||
if (GetAppConfigPath(configPath, sizeof(configPath), filename.c_str())) {
|
||||
debugOut = absolute(filesystem::u8path(configPath));
|
||||
filesystem::create_directories(debugOut.parent_path());
|
||||
}
|
||||
|
@ -904,8 +842,7 @@ bool OBSApp::SetTheme(const QString &name)
|
|||
themeWatcher->addPaths(filenames);
|
||||
/* Give it 250 ms before re-enabling the watcher to prevent too
|
||||
* many reloads when edited with an auto-saving IDE. */
|
||||
QTimer::singleShot(250, this,
|
||||
[&] { themeWatcher->blockSignals(false); });
|
||||
QTimer::singleShot(250, this, [&] { themeWatcher->blockSignals(false); });
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -914,8 +851,7 @@ bool OBSApp::SetTheme(const QString &name)
|
|||
void OBSApp::themeFileChanged(const QString &path)
|
||||
{
|
||||
themeWatcher->blockSignals(true);
|
||||
blog(LOG_INFO, "Theme file \"%s\" changed, reloading...",
|
||||
QT_TO_UTF8(path));
|
||||
blog(LOG_INFO, "Theme file \"%s\" changed, reloading...", QT_TO_UTF8(path));
|
||||
SetTheme(currentTheme->id);
|
||||
}
|
||||
|
||||
|
@ -957,24 +893,20 @@ bool OBSApp::InitTheme()
|
|||
if (config_get_bool(userConfig, "Appearance", "AutoReload")) {
|
||||
/* Set up Qt file watcher to automatically reload themes */
|
||||
themeWatcher = new QFileSystemWatcher(this);
|
||||
connect(themeWatcher.get(), &QFileSystemWatcher::fileChanged,
|
||||
this, &OBSApp::themeFileChanged);
|
||||
connect(themeWatcher.get(), &QFileSystemWatcher::fileChanged, this, &OBSApp::themeFileChanged);
|
||||
}
|
||||
|
||||
/* Migrate old theme config key */
|
||||
if (config_has_user_value(userConfig, "General", "CurrentTheme3") &&
|
||||
!config_has_user_value(userConfig, "Appearance", "Theme")) {
|
||||
const char *old = config_get_string(userConfig, "General",
|
||||
"CurrentTheme3");
|
||||
const char *old = config_get_string(userConfig, "General", "CurrentTheme3");
|
||||
|
||||
if (themeMigrations.count(old)) {
|
||||
config_set_string(userConfig, "Appearance", "Theme",
|
||||
themeMigrations[old].c_str());
|
||||
config_set_string(userConfig, "Appearance", "Theme", themeMigrations[old].c_str());
|
||||
}
|
||||
}
|
||||
|
||||
QString themeName =
|
||||
config_get_string(userConfig, "Appearance", "Theme");
|
||||
QString themeName = config_get_string(userConfig, "Appearance", "Theme");
|
||||
|
||||
if (themeName.isEmpty() || !GetTheme(themeName)) {
|
||||
if (!themeName.isEmpty()) {
|
||||
|
@ -984,8 +916,7 @@ bool OBSApp::InitTheme()
|
|||
QT_TO_UTF8(themeName), DEFAULT_THEME);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
themeName = HighContrastEnabled() ? "com.obsproject.System"
|
||||
: DEFAULT_THEME;
|
||||
themeName = HighContrastEnabled() ? "com.obsproject.System" : DEFAULT_THEME;
|
||||
#else
|
||||
themeName = DEFAULT_THEME;
|
||||
#endif
|
||||
|
|
711
UI/obs-app.cpp
711
UI/obs-app.cpp
File diff suppressed because it is too large
Load diff
|
@ -45,15 +45,12 @@
|
|||
|
||||
std::string CurrentTimeString();
|
||||
std::string CurrentDateTimeString();
|
||||
std::string GenerateTimeDateFilename(const char *extension,
|
||||
bool noSpace = false);
|
||||
std::string GenerateSpecifiedFilename(const char *extension, bool noSpace,
|
||||
const char *format);
|
||||
std::string GetFormatString(const char *format, const char *prefix,
|
||||
const char *suffix);
|
||||
std::string GenerateTimeDateFilename(const char *extension, bool noSpace = false);
|
||||
std::string GenerateSpecifiedFilename(const char *extension, bool noSpace, const char *format);
|
||||
std::string GetFormatString(const char *format, const char *prefix, const char *suffix);
|
||||
std::string GetFormatExt(const char *container);
|
||||
std::string GetOutputFilename(const char *path, const char *container,
|
||||
bool noSpace, bool overwrite, const char *format);
|
||||
std::string GetOutputFilename(const char *path, const char *container, bool noSpace, bool overwrite,
|
||||
const char *format);
|
||||
QObject *CreateShortcutFilter();
|
||||
|
||||
struct BaseLexer {
|
||||
|
@ -71,8 +68,7 @@ class OBSTranslator : public QTranslator {
|
|||
public:
|
||||
virtual bool isEmpty() const override { return false; }
|
||||
|
||||
virtual QString translate(const char *context, const char *sourceText,
|
||||
const char *disambiguation,
|
||||
virtual QString translate(const char *context, const char *sourceText, const char *disambiguation,
|
||||
int n) const override;
|
||||
};
|
||||
|
||||
|
@ -119,8 +115,7 @@ private:
|
|||
bool MigrateGlobalSettings();
|
||||
bool MigrateLegacySettings(uint32_t lastVersion);
|
||||
|
||||
bool InitUserConfig(std::filesystem::path &userConfigLocation,
|
||||
uint32_t lastVersion);
|
||||
bool InitUserConfig(std::filesystem::path &userConfigLocation, uint32_t lastVersion);
|
||||
void InitUserConfigDefaults();
|
||||
|
||||
bool InitLocale();
|
||||
|
@ -158,10 +153,7 @@ public:
|
|||
void UpdateHotkeyFocusSetting(bool reset = true);
|
||||
void DisableHotkeys();
|
||||
|
||||
inline bool HotkeysEnabledInFocus() const
|
||||
{
|
||||
return enableHotkeysInFocus;
|
||||
}
|
||||
inline bool HotkeysEnabledInFocus() const { return enableHotkeysInFocus; }
|
||||
|
||||
inline QMainWindow *GetMainWindow() const { return mainWindow.data(); }
|
||||
|
||||
|
@ -177,27 +169,18 @@ public:
|
|||
QList<OBSTheme> GetThemes() const { return themes.values(); }
|
||||
OBSTheme *GetTheme(const QString &name);
|
||||
bool SetTheme(const QString &name);
|
||||
bool IsThemeDark() const
|
||||
{
|
||||
return currentTheme ? currentTheme->isDark : false;
|
||||
}
|
||||
bool IsThemeDark() const { return currentTheme ? currentTheme->isDark : false; }
|
||||
|
||||
void SetBranchData(const std::string &data);
|
||||
std::vector<UpdateBranch> GetBranches();
|
||||
|
||||
inline lookup_t *GetTextLookup() const { return textLookup; }
|
||||
|
||||
inline const char *GetString(const char *lookupVal) const
|
||||
{
|
||||
return textLookup.GetString(lookupVal);
|
||||
}
|
||||
inline const char *GetString(const char *lookupVal) const { return textLookup.GetString(lookupVal); }
|
||||
|
||||
bool TranslateString(const char *lookupVal, const char **out) const;
|
||||
|
||||
profiler_name_store_t *GetProfilerNameStore() const
|
||||
{
|
||||
return profilerNameStore;
|
||||
}
|
||||
profiler_name_store_t *GetProfilerNameStore() const { return profilerNameStore; }
|
||||
|
||||
const char *GetLastLog() const;
|
||||
const char *GetCurrentLog() const;
|
||||
|
@ -232,10 +215,7 @@ public:
|
|||
os_inhibit_sleep_set_active(sleepInhibitor, false);
|
||||
}
|
||||
|
||||
inline void PushUITranslation(obs_frontend_translate_ui_cb cb)
|
||||
{
|
||||
translatorHooks.emplace_front(cb);
|
||||
}
|
||||
inline void PushUITranslation(obs_frontend_translate_ui_cb cb) { translatorHooks.emplace_front(cb); }
|
||||
|
||||
inline void PopUITranslation() { translatorHooks.pop_front(); }
|
||||
#ifndef _WIN32
|
||||
|
|
|
@ -13,8 +13,7 @@ void obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks)
|
|||
static inline bool callbacks_valid_(const char *func_name)
|
||||
{
|
||||
if (!c) {
|
||||
blog(LOG_ERROR, "Tried to call %s with no callbacks!",
|
||||
func_name);
|
||||
blog(LOG_ERROR, "Tried to call %s with no callbacks!", func_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -59,20 +58,17 @@ static char **convert_string_list(vector<string> &strings)
|
|||
|
||||
void *obs_frontend_get_main_window(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_main_window()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_main_window() : nullptr;
|
||||
}
|
||||
|
||||
void *obs_frontend_get_main_window_handle(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_main_window_handle()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_main_window_handle() : nullptr;
|
||||
}
|
||||
|
||||
void *obs_frontend_get_system_tray(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_system_tray()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_system_tray() : nullptr;
|
||||
}
|
||||
|
||||
char **obs_frontend_get_scene_names(void)
|
||||
|
@ -102,8 +98,7 @@ void obs_frontend_get_scenes(struct obs_frontend_source_list *sources)
|
|||
|
||||
obs_source_t *obs_frontend_get_current_scene(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_scene()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_scene() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene(obs_source_t *scene)
|
||||
|
@ -120,8 +115,7 @@ void obs_frontend_get_transitions(struct obs_frontend_source_list *sources)
|
|||
|
||||
obs_source_t *obs_frontend_get_current_transition(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_transition()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_transition() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_transition(obs_source_t *transition)
|
||||
|
@ -132,8 +126,7 @@ void obs_frontend_set_current_transition(obs_source_t *transition)
|
|||
|
||||
int obs_frontend_get_transition_duration(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_transition_duration()
|
||||
: 0;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_transition_duration() : 0;
|
||||
}
|
||||
|
||||
void obs_frontend_set_transition_duration(int duration)
|
||||
|
@ -171,9 +164,7 @@ char **obs_frontend_get_scene_collections(void)
|
|||
|
||||
char *obs_frontend_get_current_scene_collection(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_scene_collection()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_scene_collection() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene_collection(const char *collection)
|
||||
|
@ -184,8 +175,7 @@ void obs_frontend_set_current_scene_collection(const char *collection)
|
|||
|
||||
bool obs_frontend_add_scene_collection(const char *name)
|
||||
{
|
||||
return callbacks_valid() ? c->obs_frontend_add_scene_collection(name)
|
||||
: false;
|
||||
return callbacks_valid() ? c->obs_frontend_add_scene_collection(name) : false;
|
||||
}
|
||||
|
||||
char **obs_frontend_get_profiles(void)
|
||||
|
@ -200,14 +190,12 @@ char **obs_frontend_get_profiles(void)
|
|||
|
||||
char *obs_frontend_get_current_profile(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_profile()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_profile() : nullptr;
|
||||
}
|
||||
|
||||
char *obs_frontend_get_current_profile_path(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_profile_path()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_profile_path() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_profile(const char *profile)
|
||||
|
@ -281,14 +269,12 @@ bool obs_frontend_recording_paused(void)
|
|||
|
||||
bool obs_frontend_recording_split_file(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_recording_split_file()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_recording_split_file() : false;
|
||||
}
|
||||
|
||||
bool obs_frontend_recording_add_chapter(const char *name)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_recording_add_chapter(name)
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_recording_add_chapter(name) : false;
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_start(void)
|
||||
|
@ -311,24 +297,18 @@ void obs_frontend_replay_buffer_stop(void)
|
|||
|
||||
bool obs_frontend_replay_buffer_active(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_replay_buffer_active()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_replay_buffer_active() : false;
|
||||
}
|
||||
|
||||
void *obs_frontend_add_tools_menu_qaction(const char *name)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_add_tools_menu_qaction(name)
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_add_tools_menu_qaction(name) : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_tools_menu_item(name, callback,
|
||||
private_data);
|
||||
c->obs_frontend_add_tools_menu_item(name, callback, private_data);
|
||||
}
|
||||
|
||||
void *obs_frontend_add_dock(void *dock)
|
||||
|
@ -336,12 +316,9 @@ void *obs_frontend_add_dock(void *dock)
|
|||
return !!callbacks_valid() ? c->obs_frontend_add_dock(dock) : nullptr;
|
||||
}
|
||||
|
||||
bool obs_frontend_add_dock_by_id(const char *id, const char *title,
|
||||
void *widget)
|
||||
bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_add_dock_by_id(id, title, widget)
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_add_dock_by_id(id, title, widget) : false;
|
||||
}
|
||||
|
||||
void obs_frontend_remove_dock(const char *id)
|
||||
|
@ -352,19 +329,16 @@ void obs_frontend_remove_dock(const char *id)
|
|||
|
||||
bool obs_frontend_add_custom_qdock(const char *id, void *dock)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_add_custom_qdock(id, dock)
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_add_custom_qdock(id, dock) : false;
|
||||
}
|
||||
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_event_callback(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_remove_event_callback(callback, private_data);
|
||||
|
@ -372,26 +346,22 @@ void obs_frontend_remove_event_callback(obs_frontend_event_cb callback,
|
|||
|
||||
obs_output_t *obs_frontend_get_streaming_output(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_streaming_output()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_streaming_output() : nullptr;
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_recording_output(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_recording_output()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_recording_output() : nullptr;
|
||||
}
|
||||
|
||||
obs_output_t *obs_frontend_get_replay_buffer_output(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_replay_buffer_output()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_replay_buffer_output() : nullptr;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_profile_config(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_profile_config()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_profile_config() : nullptr;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_app_config(void)
|
||||
|
@ -401,8 +371,7 @@ config_t *obs_frontend_get_app_config(void)
|
|||
|
||||
config_t *obs_frontend_get_user_config(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_user_config()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_user_config() : nullptr;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_global_config(void)
|
||||
|
@ -412,8 +381,7 @@ config_t *obs_frontend_get_global_config(void)
|
|||
return !!callbacks_valid() ? c->obs_frontend_get_app_config() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_open_projector(const char *type, int monitor,
|
||||
const char *geometry, const char *name)
|
||||
void obs_frontend_open_projector(const char *type, int monitor, const char *geometry, const char *name)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_open_projector(type, monitor, geometry, name);
|
||||
|
@ -437,29 +405,25 @@ void obs_frontend_defer_save_end(void)
|
|||
c->obs_frontend_defer_save_end();
|
||||
}
|
||||
|
||||
void obs_frontend_add_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_save_callback(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_remove_save_callback(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_preload_callback(callback, private_data);
|
||||
}
|
||||
|
||||
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data)
|
||||
void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_remove_preload_callback(callback, private_data);
|
||||
|
@ -479,8 +443,7 @@ void obs_frontend_pop_ui_translation(void)
|
|||
|
||||
obs_service_t *obs_frontend_get_streaming_service(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_streaming_service()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_streaming_service() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_streaming_service(obs_service_t *service)
|
||||
|
@ -497,9 +460,7 @@ void obs_frontend_save_streaming_service(void)
|
|||
|
||||
bool obs_frontend_preview_program_mode_active(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_preview_program_mode_active()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_preview_program_mode_active() : false;
|
||||
}
|
||||
|
||||
void obs_frontend_set_preview_program_mode(bool enable)
|
||||
|
@ -527,8 +488,7 @@ void obs_frontend_set_preview_enabled(bool enable)
|
|||
|
||||
obs_source_t *obs_frontend_get_current_preview_scene(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_preview_scene()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_preview_scene() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_preview_scene(obs_source_t *scene)
|
||||
|
@ -551,8 +511,7 @@ void obs_frontend_take_source_screenshot(obs_source_t *source)
|
|||
|
||||
obs_output_t *obs_frontend_get_virtualcam_output(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_virtualcam_output()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_virtualcam_output() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_start_virtualcam(void)
|
||||
|
@ -569,8 +528,7 @@ void obs_frontend_stop_virtualcam(void)
|
|||
|
||||
bool obs_frontend_virtualcam_active(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_virtualcam_active()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_virtualcam_active() : false;
|
||||
}
|
||||
|
||||
void obs_frontend_reset_video(void)
|
||||
|
@ -605,15 +563,12 @@ void obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item)
|
|||
|
||||
char *obs_frontend_get_current_record_output_path(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_record_output_path()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_record_output_path() : nullptr;
|
||||
}
|
||||
|
||||
const char *obs_frontend_get_locale_string(const char *string)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_locale_string(string)
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_locale_string(string) : nullptr;
|
||||
}
|
||||
|
||||
bool obs_frontend_is_theme_dark(void)
|
||||
|
@ -623,29 +578,22 @@ bool obs_frontend_is_theme_dark(void)
|
|||
|
||||
char *obs_frontend_get_last_recording(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_last_recording()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_last_recording() : nullptr;
|
||||
}
|
||||
|
||||
char *obs_frontend_get_last_screenshot(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_last_screenshot()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_last_screenshot() : nullptr;
|
||||
}
|
||||
|
||||
char *obs_frontend_get_last_replay(void)
|
||||
{
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_last_replay()
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_last_replay() : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_add_undo_redo_action(const char *name,
|
||||
const undo_redo_cb undo,
|
||||
const undo_redo_cb redo,
|
||||
const char *undo_data,
|
||||
const char *redo_data, bool repeatable)
|
||||
void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
|
||||
const char *undo_data, const char *redo_data, bool repeatable)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_undo_redo_action(
|
||||
name, undo, redo, undo_data, redo_data, repeatable);
|
||||
c->obs_frontend_add_undo_redo_action(name, undo, redo, undo_data, redo_data, repeatable);
|
||||
}
|
||||
|
|
|
@ -72,8 +72,7 @@ struct obs_frontend_source_list {
|
|||
DARRAY(obs_source_t *) sources;
|
||||
};
|
||||
|
||||
static inline void
|
||||
obs_frontend_source_list_free(struct obs_frontend_source_list *source_list)
|
||||
static inline void obs_frontend_source_list_free(struct obs_frontend_source_list *source_list)
|
||||
{
|
||||
size_t num = source_list->sources.num;
|
||||
for (size_t i = 0; i < num; i++)
|
||||
|
@ -107,8 +106,7 @@ EXPORT void obs_frontend_get_scenes(struct obs_frontend_source_list *sources);
|
|||
EXPORT obs_source_t *obs_frontend_get_current_scene(void);
|
||||
EXPORT void obs_frontend_set_current_scene(obs_source_t *scene);
|
||||
|
||||
EXPORT void
|
||||
obs_frontend_get_transitions(struct obs_frontend_source_list *sources);
|
||||
EXPORT void obs_frontend_get_transitions(struct obs_frontend_source_list *sources);
|
||||
EXPORT obs_source_t *obs_frontend_get_current_transition(void);
|
||||
EXPORT void obs_frontend_set_current_transition(obs_source_t *transition);
|
||||
EXPORT int obs_frontend_get_transition_duration(void);
|
||||
|
@ -133,49 +131,36 @@ EXPORT void obs_frontend_delete_profile(const char *profile);
|
|||
typedef void (*obs_frontend_cb)(void *private_data);
|
||||
|
||||
EXPORT void *obs_frontend_add_tools_menu_qaction(const char *name);
|
||||
EXPORT void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback, void *private_data);
|
||||
|
||||
/* takes QDockWidget and returns QAction */
|
||||
OBS_DEPRECATED
|
||||
EXPORT void *obs_frontend_add_dock(void *dock);
|
||||
|
||||
/* takes QWidget for widget */
|
||||
EXPORT bool obs_frontend_add_dock_by_id(const char *id, const char *title,
|
||||
void *widget);
|
||||
EXPORT bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget);
|
||||
|
||||
EXPORT void obs_frontend_remove_dock(const char *id);
|
||||
|
||||
/* takes QDockWidget for dock */
|
||||
EXPORT bool obs_frontend_add_custom_qdock(const char *id, void *dock);
|
||||
|
||||
typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event,
|
||||
void *private_data);
|
||||
typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event, void *private_data);
|
||||
|
||||
EXPORT void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_remove_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data);
|
||||
EXPORT void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data);
|
||||
|
||||
typedef void (*obs_frontend_save_cb)(obs_data_t *save_data, bool saving,
|
||||
void *private_data);
|
||||
typedef void (*obs_frontend_save_cb)(obs_data_t *save_data, bool saving, void *private_data);
|
||||
|
||||
EXPORT void obs_frontend_add_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_remove_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data);
|
||||
EXPORT void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data);
|
||||
|
||||
EXPORT void obs_frontend_add_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data);
|
||||
EXPORT void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data);
|
||||
EXPORT void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data);
|
||||
|
||||
typedef bool (*obs_frontend_translate_ui_cb)(const char *text,
|
||||
const char **out);
|
||||
typedef bool (*obs_frontend_translate_ui_cb)(const char *text, const char **out);
|
||||
|
||||
EXPORT void
|
||||
obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate);
|
||||
EXPORT void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate);
|
||||
EXPORT void obs_frontend_pop_ui_translation(void);
|
||||
|
||||
#endif //!SWIG
|
||||
|
@ -197,8 +182,7 @@ EXPORT void obs_frontend_replay_buffer_save(void);
|
|||
EXPORT void obs_frontend_replay_buffer_stop(void);
|
||||
EXPORT bool obs_frontend_replay_buffer_active(void);
|
||||
|
||||
EXPORT void obs_frontend_open_projector(const char *type, int monitor,
|
||||
const char *geometry, const char *name);
|
||||
EXPORT void obs_frontend_open_projector(const char *type, int monitor, const char *geometry, const char *name);
|
||||
EXPORT void obs_frontend_save(void);
|
||||
EXPORT void obs_frontend_defer_save_begin(void);
|
||||
EXPORT void obs_frontend_defer_save_end(void);
|
||||
|
@ -251,9 +235,8 @@ EXPORT char *obs_frontend_get_last_screenshot(void);
|
|||
EXPORT char *obs_frontend_get_last_replay(void);
|
||||
|
||||
typedef void (*undo_redo_cb)(const char *data);
|
||||
EXPORT void obs_frontend_add_undo_redo_action(
|
||||
const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
|
||||
const char *undo_data, const char *redo_data, bool repeatable);
|
||||
EXPORT void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo, const undo_redo_cb redo,
|
||||
const char *undo_data, const char *redo_data, bool repeatable);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
|
|
@ -11,31 +11,25 @@ struct obs_frontend_callbacks {
|
|||
virtual void *obs_frontend_get_main_window_handle(void) = 0;
|
||||
virtual void *obs_frontend_get_system_tray(void) = 0;
|
||||
|
||||
virtual void
|
||||
obs_frontend_get_scenes(struct obs_frontend_source_list *sources) = 0;
|
||||
virtual void obs_frontend_get_scenes(struct obs_frontend_source_list *sources) = 0;
|
||||
virtual obs_source_t *obs_frontend_get_current_scene(void) = 0;
|
||||
virtual void obs_frontend_set_current_scene(obs_source_t *scene) = 0;
|
||||
|
||||
virtual void obs_frontend_get_transitions(
|
||||
struct obs_frontend_source_list *sources) = 0;
|
||||
virtual void obs_frontend_get_transitions(struct obs_frontend_source_list *sources) = 0;
|
||||
virtual obs_source_t *obs_frontend_get_current_transition(void) = 0;
|
||||
virtual void
|
||||
obs_frontend_set_current_transition(obs_source_t *transition) = 0;
|
||||
virtual void obs_frontend_set_current_transition(obs_source_t *transition) = 0;
|
||||
virtual int obs_frontend_get_transition_duration(void) = 0;
|
||||
virtual void obs_frontend_set_transition_duration(int duration) = 0;
|
||||
virtual void obs_frontend_release_tbar(void) = 0;
|
||||
virtual int obs_frontend_get_tbar_position(void) = 0;
|
||||
virtual void obs_frontend_set_tbar_position(int position) = 0;
|
||||
|
||||
virtual void obs_frontend_get_scene_collections(
|
||||
std::vector<std::string> &strings) = 0;
|
||||
virtual void obs_frontend_get_scene_collections(std::vector<std::string> &strings) = 0;
|
||||
virtual char *obs_frontend_get_current_scene_collection(void) = 0;
|
||||
virtual void
|
||||
obs_frontend_set_current_scene_collection(const char *collection) = 0;
|
||||
virtual void obs_frontend_set_current_scene_collection(const char *collection) = 0;
|
||||
virtual bool obs_frontend_add_scene_collection(const char *name) = 0;
|
||||
|
||||
virtual void
|
||||
obs_frontend_get_profiles(std::vector<std::string> &strings) = 0;
|
||||
virtual void obs_frontend_get_profiles(std::vector<std::string> &strings) = 0;
|
||||
virtual char *obs_frontend_get_current_profile(void) = 0;
|
||||
virtual char *obs_frontend_get_current_profile_path(void) = 0;
|
||||
virtual void obs_frontend_set_current_profile(const char *profile) = 0;
|
||||
|
@ -61,64 +55,44 @@ struct obs_frontend_callbacks {
|
|||
virtual bool obs_frontend_replay_buffer_active(void) = 0;
|
||||
|
||||
virtual void *obs_frontend_add_tools_menu_qaction(const char *name) = 0;
|
||||
virtual void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback,
|
||||
virtual void obs_frontend_add_tools_menu_item(const char *name, obs_frontend_cb callback,
|
||||
void *private_data) = 0;
|
||||
|
||||
virtual void *obs_frontend_add_dock(void *dock) = 0;
|
||||
|
||||
virtual bool obs_frontend_add_dock_by_id(const char *id,
|
||||
const char *title,
|
||||
void *widget) = 0;
|
||||
virtual bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget) = 0;
|
||||
virtual void obs_frontend_remove_dock(const char *id) = 0;
|
||||
virtual bool obs_frontend_add_custom_qdock(const char *id,
|
||||
void *dock) = 0;
|
||||
virtual bool obs_frontend_add_custom_qdock(const char *id, void *dock) = 0;
|
||||
|
||||
virtual void
|
||||
obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data) = 0;
|
||||
virtual void
|
||||
obs_frontend_remove_event_callback(obs_frontend_event_cb callback,
|
||||
void *private_data) = 0;
|
||||
virtual void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data) = 0;
|
||||
virtual void obs_frontend_remove_event_callback(obs_frontend_event_cb callback, void *private_data) = 0;
|
||||
|
||||
virtual obs_output_t *obs_frontend_get_streaming_output(void) = 0;
|
||||
virtual obs_output_t *obs_frontend_get_recording_output(void) = 0;
|
||||
virtual obs_output_t *obs_frontend_get_replay_buffer_output(void) = 0;
|
||||
|
||||
virtual config_t *obs_frontend_get_profile_config(void) = 0;
|
||||
OBS_DEPRECATED virtual config_t *
|
||||
obs_frontend_get_global_config(void) = 0;
|
||||
OBS_DEPRECATED virtual config_t *obs_frontend_get_global_config(void) = 0;
|
||||
|
||||
virtual config_t *obs_frontend_get_app_config(void) = 0;
|
||||
virtual config_t *obs_frontend_get_user_config(void) = 0;
|
||||
|
||||
virtual void obs_frontend_open_projector(const char *type, int monitor,
|
||||
const char *geometry,
|
||||
virtual void obs_frontend_open_projector(const char *type, int monitor, const char *geometry,
|
||||
const char *name) = 0;
|
||||
virtual void obs_frontend_save(void) = 0;
|
||||
virtual void obs_frontend_defer_save_begin(void) = 0;
|
||||
virtual void obs_frontend_defer_save_end(void) = 0;
|
||||
virtual void
|
||||
obs_frontend_add_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) = 0;
|
||||
virtual void
|
||||
obs_frontend_remove_save_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) = 0;
|
||||
virtual void obs_frontend_add_save_callback(obs_frontend_save_cb callback, void *private_data) = 0;
|
||||
virtual void obs_frontend_remove_save_callback(obs_frontend_save_cb callback, void *private_data) = 0;
|
||||
|
||||
virtual void
|
||||
obs_frontend_add_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) = 0;
|
||||
virtual void
|
||||
obs_frontend_remove_preload_callback(obs_frontend_save_cb callback,
|
||||
void *private_data) = 0;
|
||||
virtual void obs_frontend_add_preload_callback(obs_frontend_save_cb callback, void *private_data) = 0;
|
||||
virtual void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback, void *private_data) = 0;
|
||||
|
||||
virtual void obs_frontend_push_ui_translation(
|
||||
obs_frontend_translate_ui_cb translate) = 0;
|
||||
virtual void obs_frontend_push_ui_translation(obs_frontend_translate_ui_cb translate) = 0;
|
||||
virtual void obs_frontend_pop_ui_translation(void) = 0;
|
||||
|
||||
virtual obs_service_t *obs_frontend_get_streaming_service(void) = 0;
|
||||
virtual void
|
||||
obs_frontend_set_streaming_service(obs_service_t *service) = 0;
|
||||
virtual void obs_frontend_set_streaming_service(obs_service_t *service) = 0;
|
||||
virtual void obs_frontend_save_streaming_service() = 0;
|
||||
|
||||
virtual bool obs_frontend_preview_program_mode_active(void) = 0;
|
||||
|
@ -129,8 +103,7 @@ struct obs_frontend_callbacks {
|
|||
virtual void obs_frontend_set_preview_enabled(bool enable) = 0;
|
||||
|
||||
virtual obs_source_t *obs_frontend_get_current_preview_scene(void) = 0;
|
||||
virtual void
|
||||
obs_frontend_set_current_preview_scene(obs_source_t *scene) = 0;
|
||||
virtual void obs_frontend_set_current_preview_scene(obs_source_t *scene) = 0;
|
||||
|
||||
virtual void on_load(obs_data_t *settings) = 0;
|
||||
virtual void on_preload(obs_data_t *settings) = 0;
|
||||
|
@ -138,8 +111,7 @@ struct obs_frontend_callbacks {
|
|||
virtual void on_event(enum obs_frontend_event event) = 0;
|
||||
|
||||
virtual void obs_frontend_take_screenshot() = 0;
|
||||
virtual void
|
||||
obs_frontend_take_source_screenshot(obs_source_t *source) = 0;
|
||||
virtual void obs_frontend_take_source_screenshot(obs_source_t *source) = 0;
|
||||
|
||||
virtual obs_output_t *obs_frontend_get_virtualcam_output(void) = 0;
|
||||
virtual void obs_frontend_start_virtualcam(void) = 0;
|
||||
|
@ -148,17 +120,13 @@ struct obs_frontend_callbacks {
|
|||
|
||||
virtual void obs_frontend_reset_video(void) = 0;
|
||||
|
||||
virtual void
|
||||
obs_frontend_open_source_properties(obs_source_t *source) = 0;
|
||||
virtual void obs_frontend_open_source_properties(obs_source_t *source) = 0;
|
||||
virtual void obs_frontend_open_source_filters(obs_source_t *source) = 0;
|
||||
virtual void
|
||||
obs_frontend_open_source_interaction(obs_source_t *source) = 0;
|
||||
virtual void
|
||||
obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item) = 0;
|
||||
virtual void obs_frontend_open_source_interaction(obs_source_t *source) = 0;
|
||||
virtual void obs_frontend_open_sceneitem_edit_transform(obs_sceneitem_t *item) = 0;
|
||||
|
||||
virtual char *obs_frontend_get_current_record_output_path(void) = 0;
|
||||
virtual const char *
|
||||
obs_frontend_get_locale_string(const char *string) = 0;
|
||||
virtual const char *obs_frontend_get_locale_string(const char *string) = 0;
|
||||
|
||||
virtual bool obs_frontend_is_theme_dark(void) = 0;
|
||||
|
||||
|
@ -166,13 +134,9 @@ struct obs_frontend_callbacks {
|
|||
virtual char *obs_frontend_get_last_screenshot(void) = 0;
|
||||
virtual char *obs_frontend_get_last_replay(void) = 0;
|
||||
|
||||
virtual void obs_frontend_add_undo_redo_action(const char *name,
|
||||
const undo_redo_cb undo,
|
||||
const undo_redo_cb redo,
|
||||
const char *undo_data,
|
||||
const char *redo_data,
|
||||
bool repeatable) = 0;
|
||||
virtual void obs_frontend_add_undo_redo_action(const char *name, const undo_redo_cb undo,
|
||||
const undo_redo_cb redo, const char *undo_data,
|
||||
const char *redo_data, bool repeatable) = 0;
|
||||
};
|
||||
|
||||
EXPORT void
|
||||
obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks);
|
||||
EXPORT void obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks);
|
||||
|
|
|
@ -12,20 +12,16 @@ static inline uint qt_intensity(uint r, uint g, uint b)
|
|||
*
|
||||
* https://code.woboq.org/qt5/qtbase/src/widgets/styles/qcommonstyle.cpp.html#6429
|
||||
*/
|
||||
QPixmap
|
||||
OBSContextBarProxyStyle::generatedIconPixmap(QIcon::Mode iconMode,
|
||||
const QPixmap &pixmap,
|
||||
const QStyleOption *option) const
|
||||
QPixmap OBSContextBarProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap,
|
||||
const QStyleOption *option) const
|
||||
{
|
||||
if (iconMode == QIcon::Disabled) {
|
||||
QImage im =
|
||||
pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
|
||||
QImage im = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
/* Create a colortable based on the background
|
||||
* (black -> bg -> white) */
|
||||
|
||||
QColor bg = option->palette.color(QPalette::Disabled,
|
||||
QPalette::Window);
|
||||
QColor bg = option->palette.color(QPalette::Disabled, QPalette::Window);
|
||||
int red = bg.red();
|
||||
int green = bg.green();
|
||||
int blue = bg.blue();
|
||||
|
@ -49,8 +45,7 @@ OBSContextBarProxyStyle::generatedIconPixmap(QIcon::Mode iconMode,
|
|||
int intensity = qt_intensity(red, green, blue);
|
||||
const int factor = 191;
|
||||
|
||||
if ((red - factor > green && red - factor > blue) ||
|
||||
(green - factor > red && green - factor > blue) ||
|
||||
if ((red - factor > green && red - factor > blue) || (green - factor > red && green - factor > blue) ||
|
||||
(blue - factor > red && blue - factor > green))
|
||||
qMin(255, intensity + 20);
|
||||
else if (intensity <= 128)
|
||||
|
@ -63,10 +58,8 @@ OBSContextBarProxyStyle::generatedIconPixmap(QIcon::Mode iconMode,
|
|||
/* Calculate color table index, taking
|
||||
* intensity adjustment and a magic offset into
|
||||
* account. */
|
||||
uint ci = uint(qGray(pixel) / 3 +
|
||||
(130 - intensity / 3));
|
||||
*scanLine = qRgba(reds[ci], greens[ci],
|
||||
blues[ci], qAlpha(pixel));
|
||||
uint ci = uint(qGray(pixel) / 3 + (130 - intensity / 3));
|
||||
*scanLine = qRgba(reds[ci], greens[ci], blues[ci], qAlpha(pixel));
|
||||
++scanLine;
|
||||
}
|
||||
}
|
||||
|
@ -77,8 +70,7 @@ OBSContextBarProxyStyle::generatedIconPixmap(QIcon::Mode iconMode,
|
|||
return QProxyStyle::generatedIconPixmap(iconMode, pixmap, option);
|
||||
}
|
||||
|
||||
int OBSProxyStyle::styleHint(StyleHint hint, const QStyleOption *option,
|
||||
const QWidget *widget,
|
||||
int OBSProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
|
||||
QStyleHintReturn *returnData) const
|
||||
{
|
||||
if (hint == SH_ComboBox_AllowWheelScrolling)
|
||||
|
|
|
@ -8,8 +8,7 @@ public:
|
|||
|
||||
OBSProxyStyle(const QString &key) : QProxyStyle(key) {}
|
||||
|
||||
int styleHint(StyleHint hint, const QStyleOption *option,
|
||||
const QWidget *widget,
|
||||
int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget,
|
||||
QStyleHintReturn *returnData) const override;
|
||||
};
|
||||
|
||||
|
|
|
@ -39,8 +39,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static inline bool check_path(const char *data, const char *path,
|
||||
string &output)
|
||||
static inline bool check_path(const char *data, const char *path, string &output)
|
||||
{
|
||||
ostringstream str;
|
||||
str << path << data;
|
||||
|
@ -64,8 +63,7 @@ string GetDefaultVideoSavePath()
|
|||
wchar_t path_utf16[MAX_PATH];
|
||||
char path_utf8[MAX_PATH] = {};
|
||||
|
||||
SHGetFolderPathW(NULL, CSIDL_MYVIDEO, NULL, SHGFP_TYPE_CURRENT,
|
||||
path_utf16);
|
||||
SHGetFolderPathW(NULL, CSIDL_MYVIDEO, NULL, SHGFP_TYPE_CURRENT, path_utf16);
|
||||
|
||||
os_wcs_to_utf8(path_utf16, wcslen(path_utf16), path_utf8, MAX_PATH);
|
||||
return string(path_utf8);
|
||||
|
@ -76,13 +74,11 @@ static vector<string> GetUserPreferredLocales()
|
|||
vector<string> result;
|
||||
|
||||
ULONG num, length = 0;
|
||||
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &num, nullptr,
|
||||
&length))
|
||||
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &num, nullptr, &length))
|
||||
return result;
|
||||
|
||||
vector<wchar_t> buffer(length);
|
||||
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &num,
|
||||
&buffer.front(), &length))
|
||||
if (!GetUserPreferredUILanguages(MUI_LANGUAGE_NAME, &num, &buffer.front(), &length))
|
||||
return result;
|
||||
|
||||
result.reserve(num);
|
||||
|
@ -192,13 +188,11 @@ void SetProcessPriority(const char *priority)
|
|||
if (strcmp(priority, "High") == 0)
|
||||
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
|
||||
else if (strcmp(priority, "AboveNormal") == 0)
|
||||
SetPriorityClass(GetCurrentProcess(),
|
||||
ABOVE_NORMAL_PRIORITY_CLASS);
|
||||
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
|
||||
else if (strcmp(priority, "Normal") == 0)
|
||||
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
|
||||
else if (strcmp(priority, "BelowNormal") == 0)
|
||||
SetPriorityClass(GetCurrentProcess(),
|
||||
BELOW_NORMAL_PRIORITY_CLASS);
|
||||
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
|
||||
else if (strcmp(priority, "Idle") == 0)
|
||||
SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
|
||||
}
|
||||
|
@ -220,8 +214,7 @@ bool SetDisplayAffinitySupported(void)
|
|||
older Windows builds behaves like WDA_MONITOR (black box) */
|
||||
|
||||
if (!checked) {
|
||||
if (GetWindowsVersion() > 0x0A00 ||
|
||||
GetWindowsVersion() == 0x0A00 && GetWindowsBuild() >= 19041)
|
||||
if (GetWindowsVersion() > 0x0A00 || GetWindowsVersion() == 0x0A00 && GetWindowsBuild() >= 19041)
|
||||
supported = true;
|
||||
else
|
||||
supported = false;
|
||||
|
@ -240,10 +233,8 @@ bool DisableAudioDucking(bool disable)
|
|||
ComPtr<IAudioSessionControl> sessionControl;
|
||||
ComPtr<IAudioSessionControl2> sessionControl2;
|
||||
|
||||
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IMMDeviceEnumerator),
|
||||
(void **)&devEmum);
|
||||
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IMMDeviceEnumerator), (void **)&devEmum);
|
||||
if (FAILED(result))
|
||||
return false;
|
||||
|
||||
|
@ -251,14 +242,12 @@ bool DisableAudioDucking(bool disable)
|
|||
if (FAILED(result))
|
||||
return false;
|
||||
|
||||
result = device->Activate(__uuidof(IAudioSessionManager2),
|
||||
CLSCTX_INPROC_SERVER, nullptr,
|
||||
result = device->Activate(__uuidof(IAudioSessionManager2), CLSCTX_INPROC_SERVER, nullptr,
|
||||
(void **)&sessionManager2);
|
||||
if (FAILED(result))
|
||||
return false;
|
||||
|
||||
result = sessionManager2->GetAudioSessionControl(nullptr, 0,
|
||||
&sessionControl);
|
||||
result = sessionManager2->GetAudioSessionControl(nullptr, 0, &sessionControl);
|
||||
if (FAILED(result))
|
||||
return false;
|
||||
|
||||
|
@ -341,8 +330,7 @@ struct MonitorData {
|
|||
bool found;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK GetMonitorCallback(HMONITOR monitor, HDC, LPRECT,
|
||||
LPARAM param)
|
||||
static BOOL CALLBACK GetMonitorCallback(HMONITOR monitor, HDC, LPRECT, LPARAM param)
|
||||
{
|
||||
MonitorData *data = (MonitorData *)param;
|
||||
|
||||
|
@ -385,9 +373,7 @@ void TaskbarOverlayInit()
|
|||
void TaskbarOverlaySetStatus(TaskbarOverlayStatus status)
|
||||
{
|
||||
ITaskbarList4 *taskbarIcon;
|
||||
auto hr = CoCreateInstance(CLSID_TaskbarList, NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&taskbarIcon));
|
||||
auto hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&taskbarIcon));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
taskbarIcon->Release();
|
||||
|
@ -404,12 +390,10 @@ void TaskbarOverlaySetStatus(TaskbarOverlayStatus status)
|
|||
QIcon qicon;
|
||||
switch (status) {
|
||||
case TaskbarOverlayStatusActive:
|
||||
qicon = QIcon::fromTheme("obs-active",
|
||||
QIcon(":/res/images/active.png"));
|
||||
qicon = QIcon::fromTheme("obs-active", QIcon(":/res/images/active.png"));
|
||||
break;
|
||||
case TaskbarOverlayStatusPaused:
|
||||
qicon = QIcon::fromTheme("obs-paused",
|
||||
QIcon(":/res/images/paused.png"));
|
||||
qicon = QIcon::fromTheme("obs-paused", QIcon(":/res/images/paused.png"));
|
||||
break;
|
||||
case TaskbarOverlayStatusInactive:
|
||||
taskbarIcon->SetOverlayIcon(hwnd, nullptr, nullptr);
|
||||
|
@ -420,8 +404,7 @@ void TaskbarOverlaySetStatus(TaskbarOverlayStatus status)
|
|||
HICON hicon = nullptr;
|
||||
if (!qicon.isNull()) {
|
||||
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p);
|
||||
hicon = qt_pixmapToWinHICON(
|
||||
qicon.pixmap(GetSystemMetrics(SM_CXSMICON)));
|
||||
hicon = qt_pixmapToWinHICON(qicon.pixmap(GetSystemMetrics(SM_CXSMICON)));
|
||||
if (!hicon)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -61,8 +61,7 @@ void CheckIfAlreadyRunning(bool &already_running)
|
|||
int uniq = socket(AF_LOCAL, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
|
||||
if (uniq == -1) {
|
||||
blog(LOG_ERROR,
|
||||
"Failed to check for running instance, socket: %d", errno);
|
||||
blog(LOG_ERROR, "Failed to check for running instance, socket: %d", errno);
|
||||
already_running = 0;
|
||||
return;
|
||||
}
|
||||
|
@ -70,13 +69,10 @@ void CheckIfAlreadyRunning(bool &already_running)
|
|||
struct sockaddr_un bindInfo;
|
||||
memset(&bindInfo, 0, sizeof(sockaddr_un));
|
||||
bindInfo.sun_family = AF_LOCAL;
|
||||
auto bindInfoStrlen = snprintf(bindInfo.sun_path + 1,
|
||||
sizeof(bindInfo.sun_path) - 1,
|
||||
"%s %d %s", "/com/obsproject", getpid(),
|
||||
App()->GetVersionString().c_str());
|
||||
auto bindInfoStrlen = snprintf(bindInfo.sun_path + 1, sizeof(bindInfo.sun_path) - 1, "%s %d %s",
|
||||
"/com/obsproject", getpid(), App()->GetVersionString().c_str());
|
||||
|
||||
int bindErr = bind(uniq, (struct sockaddr *)&bindInfo,
|
||||
sizeof(sa_family_t) + 1 + bindInfoStrlen);
|
||||
int bindErr = bind(uniq, (struct sockaddr *)&bindInfo, sizeof(sa_family_t) + 1 + bindInfoStrlen);
|
||||
already_running = bindErr == 0 ? 0 : 1;
|
||||
|
||||
if (already_running) {
|
||||
|
@ -139,8 +135,7 @@ const char *RunOnce::thr_name = "OBS runonce";
|
|||
|
||||
void CheckIfAlreadyRunning(bool &already_running)
|
||||
{
|
||||
std::string tmpfile_name =
|
||||
"/tmp/obs-studio.lock." + std::to_string(geteuid());
|
||||
std::string tmpfile_name = "/tmp/obs-studio.lock." + std::to_string(geteuid());
|
||||
int fd = open(tmpfile_name.c_str(), O_RDWR | O_CREAT | O_EXLOCK, 0600);
|
||||
if (fd == -1) {
|
||||
already_running = true;
|
||||
|
@ -151,11 +146,9 @@ void CheckIfAlreadyRunning(bool &already_running)
|
|||
|
||||
procstat *ps = procstat_open_sysctl();
|
||||
unsigned int count;
|
||||
auto procs = procstat_getprocs(ps, KERN_PROC_UID | KERN_PROC_INC_THREAD,
|
||||
geteuid(), &count);
|
||||
auto procs = procstat_getprocs(ps, KERN_PROC_UID | KERN_PROC_INC_THREAD, geteuid(), &count);
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
if (!strncmp(procs[i].ki_tdname, RunOnce::thr_name,
|
||||
sizeof(procs[i].ki_tdname))) {
|
||||
if (!strncmp(procs[i].ki_tdname, RunOnce::thr_name, sizeof(procs[i].ki_tdname))) {
|
||||
already_running = true;
|
||||
break;
|
||||
}
|
||||
|
@ -175,8 +168,7 @@ void CheckIfAlreadyRunning(bool &already_running)
|
|||
}
|
||||
#endif
|
||||
|
||||
static inline bool check_path(const char *data, const char *path,
|
||||
string &output)
|
||||
static inline bool check_path(const char *data, const char *path, string &output)
|
||||
{
|
||||
ostringstream str;
|
||||
str << path << data;
|
||||
|
@ -197,8 +189,7 @@ bool GetDataFilePath(const char *data, string &output)
|
|||
return true;
|
||||
}
|
||||
|
||||
char *relative_data_path =
|
||||
os_get_executable_path_ptr("../" OBS_DATA_PATH "/obs-studio/");
|
||||
char *relative_data_path = os_get_executable_path_ptr("../" OBS_DATA_PATH "/obs-studio/");
|
||||
|
||||
if (relative_data_path) {
|
||||
bool result = check_path(data, relative_data_path, output);
|
||||
|
@ -276,18 +267,16 @@ void TaskbarOverlaySetStatus(TaskbarOverlayStatus) {}
|
|||
bool HighContrastEnabled()
|
||||
{
|
||||
QDBusReply<QVariant> reply;
|
||||
QDBusMessage msgXdpSettingsVersion = QDBusMessage::createMethodCall(
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.DBus.Properties", "Get");
|
||||
QDBusMessage msgXdpSettingsVersion = QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.DBus.Properties", "Get");
|
||||
msgXdpSettingsVersion << "org.freedesktop.portal.Settings"
|
||||
<< "version";
|
||||
|
||||
reply = QDBusConnection::sessionBus().call(msgXdpSettingsVersion);
|
||||
|
||||
if (!reply.isValid()) {
|
||||
blog(LOG_WARNING,
|
||||
"Get on org.freedesktop.portal.Settings returned an invalid reply");
|
||||
blog(LOG_WARNING, "Get on org.freedesktop.portal.Settings returned an invalid reply");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -295,17 +284,14 @@ bool HighContrastEnabled()
|
|||
* the ReadOne method. So assumes that if ReadOne is not available, contrast
|
||||
* isn't available either. */
|
||||
if (uint32_t version = reply.value().toUInt() < 2) {
|
||||
blog(LOG_WARNING,
|
||||
"org.freedesktop.portal.Settings version %u does not support ReadOne",
|
||||
version);
|
||||
blog(LOG_WARNING, "org.freedesktop.portal.Settings version %u does not support ReadOne", version);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NOTE: If contrast is not available if will return 0 (false). */
|
||||
QDBusMessage msgXdpSettingsContrast = QDBusMessage::createMethodCall(
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.portal.Settings", "ReadOne");
|
||||
QDBusMessage msgXdpSettingsContrast =
|
||||
QDBusMessage::createMethodCall("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.portal.Settings", "ReadOne");
|
||||
|
||||
msgXdpSettingsContrast << "org.freedesktop.appearance"
|
||||
<< "contrast";
|
||||
|
@ -313,8 +299,7 @@ bool HighContrastEnabled()
|
|||
reply = QDBusConnection::sessionBus().call(msgXdpSettingsContrast);
|
||||
|
||||
if (!reply.isValid()) {
|
||||
blog(LOG_WARNING,
|
||||
"ReadOne on org.freedesktop.portal.Settings returned an invalid reply");
|
||||
blog(LOG_WARNING, "ReadOne on org.freedesktop.portal.Settings returned an invalid reply");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,8 +102,7 @@ void InstallNSThreadLocks();
|
|||
void disableColorSpaceConversion(QWidget *window);
|
||||
void SetMacOSDarkMode(bool dark);
|
||||
|
||||
MacPermissionStatus CheckPermissionWithPrompt(MacPermissionType type,
|
||||
bool prompt_for_permission);
|
||||
MacPermissionStatus CheckPermissionWithPrompt(MacPermissionType type, bool prompt_for_permission);
|
||||
#define CheckPermission(x) CheckPermissionWithPrompt(x, false)
|
||||
#define RequestPermission(x) CheckPermissionWithPrompt(x, true)
|
||||
void OpenMacOSPrivacyPreferences(const char *tab);
|
||||
|
|
|
@ -51,8 +51,7 @@ void OBSPreviewScalingComboBox::OutputResized(uint32_t width, uint32_t height)
|
|||
{
|
||||
SetOutputSize(width, height);
|
||||
|
||||
bool canvasMatchesOutput = output_width == canvas_width &&
|
||||
output_height == canvas_height;
|
||||
bool canvasMatchesOutput = output_width == canvas_width && output_height == canvas_height;
|
||||
|
||||
SetScaleOutputEnabled(!canvasMatchesOutput);
|
||||
UpdateOutputText();
|
||||
|
@ -94,8 +93,7 @@ void OBSPreviewScalingComboBox::UpdateAllText()
|
|||
void OBSPreviewScalingComboBox::UpdateCanvasText()
|
||||
{
|
||||
QString text = QTStr("Basic.MainMenu.Edit.Scale.Canvas");
|
||||
text = text.arg(QString::number(canvas_width),
|
||||
QString::number(canvas_height));
|
||||
text = text.arg(QString::number(canvas_width), QString::number(canvas_height));
|
||||
setItemText(1, text);
|
||||
}
|
||||
|
||||
|
@ -103,8 +101,7 @@ void OBSPreviewScalingComboBox::UpdateOutputText()
|
|||
{
|
||||
if (scaleOutputEnabled) {
|
||||
QString text = QTStr("Basic.MainMenu.Edit.Scale.Output");
|
||||
text = text.arg(QString::number(output_width),
|
||||
QString::number(output_height));
|
||||
text = text.arg(QString::number(output_width), QString::number(output_height));
|
||||
setItemText(2, text);
|
||||
}
|
||||
}
|
||||
|
@ -127,8 +124,7 @@ void OBSPreviewScalingComboBox::UpdateSelection()
|
|||
} else {
|
||||
if (previewScale == 1.0f) {
|
||||
setCurrentIndex(1);
|
||||
} else if (scaleOutputEnabled &&
|
||||
(previewScale == outputScale)) {
|
||||
} else if (scaleOutputEnabled && (previewScale == outputScale)) {
|
||||
setCurrentIndex(2);
|
||||
} else {
|
||||
setCurrentIndex(-1);
|
||||
|
|
|
@ -38,9 +38,7 @@ class OBSPreviewScalingComboBox : public QComboBox {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OBSPreviewScalingComboBox(QWidget *parent = nullptr) : QComboBox(parent)
|
||||
{
|
||||
}
|
||||
OBSPreviewScalingComboBox(QWidget *parent = nullptr) : QComboBox(parent) {}
|
||||
|
||||
inline void SetCanvasSize(uint32_t width, uint32_t height)
|
||||
{
|
||||
|
|
|
@ -35,8 +35,7 @@ protected:
|
|||
|
||||
switch (event->type()) {
|
||||
case QEvent::PlatformSurface:
|
||||
surfaceEvent =
|
||||
static_cast<QPlatformSurfaceEvent *>(event);
|
||||
surfaceEvent = static_cast<QPlatformSurfaceEvent *>(event);
|
||||
|
||||
switch (surfaceEvent->surfaceEventType()) {
|
||||
case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
|
||||
|
@ -60,14 +59,12 @@ static inline long long color_to_int(const QColor &color)
|
|||
return ((val & 0xff) << shift);
|
||||
};
|
||||
|
||||
return shift(color.red(), 0) | shift(color.green(), 8) |
|
||||
shift(color.blue(), 16) | shift(color.alpha(), 24);
|
||||
return shift(color.red(), 0) | shift(color.green(), 8) | shift(color.blue(), 16) | shift(color.alpha(), 24);
|
||||
}
|
||||
|
||||
static inline QColor rgba_to_color(uint32_t rgba)
|
||||
{
|
||||
return QColor::fromRgb(rgba & 0xFF, (rgba >> 8) & 0xFF,
|
||||
(rgba >> 16) & 0xFF, (rgba >> 24) & 0xFF);
|
||||
return QColor::fromRgb(rgba & 0xFF, (rgba >> 8) & 0xFF, (rgba >> 16) & 0xFF, (rgba >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
static bool QTToGSWindow(QWindow *window, gs_window &gswindow)
|
||||
|
@ -86,10 +83,8 @@ static bool QTToGSWindow(QWindow *window, gs_window &gswindow)
|
|||
break;
|
||||
#ifdef ENABLE_WAYLAND
|
||||
case OBS_NIX_PLATFORM_WAYLAND: {
|
||||
QPlatformNativeInterface *native =
|
||||
QGuiApplication::platformNativeInterface();
|
||||
gswindow.display =
|
||||
native->nativeResourceForWindow("surface", window);
|
||||
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
|
||||
gswindow.display = native->nativeResourceForWindow("surface", window);
|
||||
success = gswindow.display != nullptr;
|
||||
break;
|
||||
}
|
||||
|
@ -102,8 +97,7 @@ static bool QTToGSWindow(QWindow *window, gs_window &gswindow)
|
|||
return success;
|
||||
}
|
||||
|
||||
OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
||||
: QWidget(parent, flags)
|
||||
OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags) : QWidget(parent, flags)
|
||||
{
|
||||
setAttribute(Qt::WA_PaintOnScreen);
|
||||
setAttribute(Qt::WA_StaticContents);
|
||||
|
@ -124,8 +118,7 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
|||
CreateDisplay();
|
||||
} else {
|
||||
QSize size = GetPixelSize(this);
|
||||
obs_display_resize(display, size.width(),
|
||||
size.height());
|
||||
obs_display_resize(display, size.width(), size.height());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
|
||||
class OBSQTDisplay : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor displayBackgroundColor MEMBER backgroundColor READ
|
||||
GetDisplayBackgroundColor WRITE
|
||||
SetDisplayBackgroundColor)
|
||||
Q_PROPERTY(QColor displayBackgroundColor MEMBER backgroundColor READ GetDisplayBackgroundColor WRITE
|
||||
SetDisplayBackgroundColor)
|
||||
|
||||
OBSDisplay display;
|
||||
bool destroying = false;
|
||||
|
@ -17,16 +16,14 @@ class OBSQTDisplay : public QWidget {
|
|||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message,
|
||||
qintptr *result) override;
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||
|
||||
signals:
|
||||
void DisplayCreated(OBSQTDisplay *window);
|
||||
void DisplayResized();
|
||||
|
||||
public:
|
||||
OBSQTDisplay(QWidget *parent = nullptr,
|
||||
Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
OBSQTDisplay(QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||
~OBSQTDisplay() { display = nullptr; }
|
||||
|
||||
virtual QPaintEngine *paintEngine() const override;
|
||||
|
|
|
@ -58,8 +58,7 @@ void RemoteTextThread::run()
|
|||
header = curl_slist_append(header, versionString.c_str());
|
||||
|
||||
if (!contentTypeString.empty()) {
|
||||
header = curl_slist_append(header,
|
||||
contentTypeString.c_str());
|
||||
header = curl_slist_append(header, contentTypeString.c_str());
|
||||
}
|
||||
|
||||
for (std::string &h : extraHeaders)
|
||||
|
@ -70,24 +69,20 @@ void RemoteTextThread::run()
|
|||
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, header);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, error);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION,
|
||||
string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
|
||||
curl_obs_set_revoke_setting(curl.get());
|
||||
|
||||
if (timeoutSec)
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT,
|
||||
timeoutSec);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, timeoutSec);
|
||||
|
||||
if (!postData.empty()) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS,
|
||||
postData.c_str());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, postData.c_str());
|
||||
}
|
||||
|
||||
code = curl_easy_perform(curl.get());
|
||||
if (code != CURLE_OK) {
|
||||
blog(LOG_WARNING,
|
||||
"RemoteTextThread: HTTP request failed. %s",
|
||||
blog(LOG_WARNING, "RemoteTextThread: HTTP request failed. %s",
|
||||
strlen(error) ? error : curl_easy_strerror(code));
|
||||
emit Result(QString(), QT_UTF8(error));
|
||||
} else {
|
||||
|
@ -98,8 +93,7 @@ void RemoteTextThread::run()
|
|||
}
|
||||
}
|
||||
|
||||
static size_t header_write(char *ptr, size_t size, size_t nmemb,
|
||||
vector<string> &list)
|
||||
static size_t header_write(char *ptr, size_t size, size_t nmemb, vector<string> &list)
|
||||
{
|
||||
string str;
|
||||
|
||||
|
@ -116,12 +110,9 @@ static size_t header_write(char *ptr, size_t size, size_t nmemb,
|
|||
return total;
|
||||
}
|
||||
|
||||
bool GetRemoteFile(const char *url, std::string &str, std::string &error,
|
||||
long *responseCode, const char *contentType,
|
||||
std::string request_type, const char *postData,
|
||||
std::vector<std::string> extraHeaders,
|
||||
std::string *signature, int timeoutSec, bool fail_on_error,
|
||||
int postDataSize)
|
||||
bool GetRemoteFile(const char *url, std::string &str, std::string &error, long *responseCode, const char *contentType,
|
||||
std::string request_type, const char *postData, std::vector<std::string> extraHeaders,
|
||||
std::string *signature, int timeoutSec, bool fail_on_error, int postDataSize)
|
||||
{
|
||||
vector<string> header_in_list;
|
||||
char error_in[CURL_ERROR_SIZE];
|
||||
|
@ -145,8 +136,7 @@ bool GetRemoteFile(const char *url, std::string &str, std::string &error,
|
|||
header = curl_slist_append(header, versionString.c_str());
|
||||
|
||||
if (!contentTypeString.empty()) {
|
||||
header = curl_slist_append(header,
|
||||
contentTypeString.c_str());
|
||||
header = curl_slist_append(header, contentTypeString.c_str());
|
||||
}
|
||||
|
||||
for (std::string &h : extraHeaders)
|
||||
|
@ -158,61 +148,47 @@ bool GetRemoteFile(const char *url, std::string &str, std::string &error,
|
|||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, error_in);
|
||||
if (fail_on_error)
|
||||
curl_easy_setopt(curl.get(), CURLOPT_FAILONERROR, 1L);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION,
|
||||
string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION, string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
|
||||
curl_obs_set_revoke_setting(curl.get());
|
||||
|
||||
if (signature) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HEADERFUNCTION,
|
||||
header_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA,
|
||||
&header_in_list);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HEADERFUNCTION, header_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA, &header_in_list);
|
||||
}
|
||||
|
||||
if (timeoutSec)
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT,
|
||||
timeoutSec);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT, timeoutSec);
|
||||
|
||||
if (!request_type.empty()) {
|
||||
if (request_type != "GET")
|
||||
curl_easy_setopt(curl.get(),
|
||||
CURLOPT_CUSTOMREQUEST,
|
||||
request_type.c_str());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_CUSTOMREQUEST, request_type.c_str());
|
||||
|
||||
// Special case of "POST"
|
||||
if (request_type == "POST") {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POST, 1);
|
||||
if (!postData)
|
||||
curl_easy_setopt(curl.get(),
|
||||
CURLOPT_POSTFIELDS,
|
||||
"{}");
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, "{}");
|
||||
}
|
||||
}
|
||||
if (postData) {
|
||||
if (postDataSize > 0) {
|
||||
curl_easy_setopt(curl.get(),
|
||||
CURLOPT_POSTFIELDSIZE,
|
||||
(long)postDataSize);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDSIZE, (long)postDataSize);
|
||||
}
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS,
|
||||
postData);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS, postData);
|
||||
}
|
||||
|
||||
code = curl_easy_perform(curl.get());
|
||||
if (responseCode)
|
||||
curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE,
|
||||
responseCode);
|
||||
curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE, responseCode);
|
||||
|
||||
if (code != CURLE_OK) {
|
||||
error = strlen(error_in) ? error_in
|
||||
: curl_easy_strerror(code);
|
||||
error = strlen(error_in) ? error_in : curl_easy_strerror(code);
|
||||
} else if (signature) {
|
||||
for (string &h : header_in_list) {
|
||||
string name = h.substr(0, 13);
|
||||
// HTTP headers are technically case-insensitive
|
||||
if (name == "X-Signature: " ||
|
||||
name == "x-signature: ") {
|
||||
if (name == "X-Signature: " || name == "x-signature: ") {
|
||||
*signature = h.substr(13);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -38,10 +38,8 @@ signals:
|
|||
void Result(const QString &text, const QString &error);
|
||||
|
||||
public:
|
||||
inline RemoteTextThread(std::string url_,
|
||||
std::string contentType_ = std::string(),
|
||||
std::string postData_ = std::string(),
|
||||
int timeoutSec_ = 0)
|
||||
inline RemoteTextThread(std::string url_, std::string contentType_ = std::string(),
|
||||
std::string postData_ = std::string(), int timeoutSec_ = 0)
|
||||
: url(url_),
|
||||
contentType(contentType_),
|
||||
postData(postData_),
|
||||
|
@ -49,10 +47,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
inline RemoteTextThread(std::string url_,
|
||||
std::vector<std::string> &&extraHeaders_,
|
||||
std::string contentType_ = std::string(),
|
||||
std::string postData_ = std::string(),
|
||||
inline RemoteTextThread(std::string url_, std::vector<std::string> &&extraHeaders_,
|
||||
std::string contentType_ = std::string(), std::string postData_ = std::string(),
|
||||
int timeoutSec_ = 0)
|
||||
: url(url_),
|
||||
contentType(contentType_),
|
||||
|
@ -63,10 +59,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
bool GetRemoteFile(
|
||||
const char *url, std::string &str, std::string &error,
|
||||
long *responseCode = nullptr, const char *contentType = nullptr,
|
||||
std::string request_type = "", const char *postData = nullptr,
|
||||
std::vector<std::string> extraHeaders = std::vector<std::string>(),
|
||||
std::string *signature = nullptr, int timeoutSec = 0,
|
||||
bool fail_on_error = true, int postDataSize = 0);
|
||||
bool GetRemoteFile(const char *url, std::string &str, std::string &error, long *responseCode = nullptr,
|
||||
const char *contentType = nullptr, std::string request_type = "", const char *postData = nullptr,
|
||||
std::vector<std::string> extraHeaders = std::vector<std::string>(), std::string *signature = nullptr,
|
||||
int timeoutSec = 0, bool fail_on_error = true, int postDataSize = 0);
|
||||
|
|
|
@ -182,9 +182,7 @@ void SceneTree::RepositionGrid(QDragMoveEvent *event)
|
|||
|
||||
QModelIndex index = indexFromItem(wItem);
|
||||
|
||||
int off = (i >= r ? 1 : 0) -
|
||||
(i > orig && i > r ? 1 : 0) -
|
||||
(i > orig && i == r ? 2 : 0);
|
||||
int off = (i >= r ? 1 : 0) - (i > orig && i > r ? 1 : 0) - (i > orig && i == r ? 2 : 0);
|
||||
|
||||
int xPos = (i + off) % (int)std::ceil(wid / maxWidth);
|
||||
int yPos = (i + off) / (int)std::ceil(wid / maxWidth);
|
||||
|
@ -240,11 +238,9 @@ void SceneTree::rowsInserted(const QModelIndex &parent, int start, int end)
|
|||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 3)
|
||||
// Workaround for QTBUG-105870. Remove once that is solved upstream.
|
||||
void SceneTree::selectionChanged(const QItemSelection &selected,
|
||||
const QItemSelection &deselected)
|
||||
void SceneTree::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
if (selected.count() == 0 && deselected.count() > 0 &&
|
||||
!property("clearing").toBool())
|
||||
if (selected.count() == 0 && deselected.count() > 0 && !property("clearing").toBool())
|
||||
setCurrentRow(deselected.indexes().front().row());
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
|
||||
class SceneTree : public QListWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int gridItemWidth READ GetGridItemWidth WRITE
|
||||
SetGridItemWidth DESIGNABLE true)
|
||||
Q_PROPERTY(int gridItemHeight READ GetGridItemHeight WRITE
|
||||
SetGridItemHeight DESIGNABLE true)
|
||||
Q_PROPERTY(int gridItemWidth READ GetGridItemWidth WRITE SetGridItemWidth DESIGNABLE true)
|
||||
Q_PROPERTY(int gridItemHeight READ GetGridItemHeight WRITE SetGridItemHeight DESIGNABLE true)
|
||||
|
||||
bool gridMode = false;
|
||||
int maxWidth = 150;
|
||||
|
@ -36,12 +34,9 @@ protected:
|
|||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
virtual void rowsInserted(const QModelIndex &parent, int start,
|
||||
int end) override;
|
||||
virtual void rowsInserted(const QModelIndex &parent, int start, int end) override;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 3)
|
||||
virtual void
|
||||
selectionChanged(const QItemSelection &selected,
|
||||
const QItemSelection &deselected) override;
|
||||
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override;
|
||||
#endif
|
||||
|
||||
signals:
|
||||
|
|
|
@ -28,15 +28,11 @@ public:
|
|||
OBSSignal removedSignal;
|
||||
OBSSignal destroyedSignal;
|
||||
|
||||
OBSSourceLabel(const obs_source_t *source, QWidget *parent = nullptr,
|
||||
Qt::WindowFlags f = Qt::WindowFlags())
|
||||
OBSSourceLabel(const obs_source_t *source, QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags())
|
||||
: QLabel(obs_source_get_name(source), parent, f),
|
||||
renamedSignal(obs_source_get_signal_handler(source), "rename",
|
||||
&OBSSourceLabel::SourceRenamed, this),
|
||||
removedSignal(obs_source_get_signal_handler(source), "remove",
|
||||
&OBSSourceLabel::SourceRemoved, this),
|
||||
destroyedSignal(obs_source_get_signal_handler(source),
|
||||
"destroy", &OBSSourceLabel::SourceDestroyed,
|
||||
renamedSignal(obs_source_get_signal_handler(source), "rename", &OBSSourceLabel::SourceRenamed, this),
|
||||
removedSignal(obs_source_get_signal_handler(source), "remove", &OBSSourceLabel::SourceRemoved, this),
|
||||
destroyedSignal(obs_source_get_signal_handler(source), "destroy", &OBSSourceLabel::SourceDestroyed,
|
||||
this)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -30,9 +30,7 @@ static inline OBSScene GetCurrentScene()
|
|||
|
||||
/* ========================================================================= */
|
||||
|
||||
SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
|
||||
: tree(tree_),
|
||||
sceneitem(sceneitem_)
|
||||
SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) : tree(tree_), sceneitem(sceneitem_)
|
||||
{
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
setMouseTracking(true);
|
||||
|
@ -40,8 +38,7 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
|
|||
obs_source_t *source = obs_sceneitem_get_source(sceneitem);
|
||||
const char *name = obs_source_get_name(source);
|
||||
|
||||
OBSDataAutoRelease privData =
|
||||
obs_sceneitem_get_private_settings(sceneitem);
|
||||
OBSDataAutoRelease privData = obs_sceneitem_get_private_settings(sceneitem);
|
||||
int preset = obs_data_get_int(privData, "color-preset");
|
||||
|
||||
if (preset == 1) {
|
||||
|
@ -84,15 +81,13 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
|
|||
vis->setProperty("class", "checkbox-icon indicator-visibility");
|
||||
vis->setChecked(sourceVisible);
|
||||
vis->setAccessibleName(QTStr("Basic.Main.Sources.Visibility"));
|
||||
vis->setAccessibleDescription(
|
||||
QTStr("Basic.Main.Sources.VisibilityDescription").arg(name));
|
||||
vis->setAccessibleDescription(QTStr("Basic.Main.Sources.VisibilityDescription").arg(name));
|
||||
|
||||
lock = new QCheckBox();
|
||||
lock->setProperty("class", "checkbox-icon indicator-lock");
|
||||
lock->setChecked(obs_sceneitem_locked(sceneitem));
|
||||
lock->setAccessibleName(QTStr("Basic.Main.Sources.Lock"));
|
||||
lock->setAccessibleDescription(
|
||||
QTStr("Basic.Main.Sources.LockDescription").arg(name));
|
||||
lock->setAccessibleDescription(QTStr("Basic.Main.Sources.LockDescription").arg(name));
|
||||
|
||||
label = new OBSSourceLabel(source);
|
||||
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
@ -135,26 +130,20 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
|
|||
const char *uuid = obs_source_get_uuid(scenesource);
|
||||
obs_source_t *source = obs_sceneitem_get_source(sceneitem);
|
||||
|
||||
auto undo_redo = [](const std::string &uuid, int64_t id,
|
||||
bool val) {
|
||||
OBSSourceAutoRelease s =
|
||||
obs_get_source_by_uuid(uuid.c_str());
|
||||
auto undo_redo = [](const std::string &uuid, int64_t id, bool val) {
|
||||
OBSSourceAutoRelease s = obs_get_source_by_uuid(uuid.c_str());
|
||||
obs_scene_t *sc = obs_group_or_scene_from_source(s);
|
||||
obs_sceneitem_t *si =
|
||||
obs_scene_find_sceneitem_by_id(sc, id);
|
||||
obs_sceneitem_t *si = obs_scene_find_sceneitem_by_id(sc, id);
|
||||
if (si)
|
||||
obs_sceneitem_set_visible(si, val);
|
||||
};
|
||||
|
||||
QString str = QTStr(val ? "Undo.ShowSceneItem"
|
||||
: "Undo.HideSceneItem");
|
||||
QString str = QTStr(val ? "Undo.ShowSceneItem" : "Undo.HideSceneItem");
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
main->undo_s.add_action(
|
||||
str.arg(obs_source_get_name(source), name),
|
||||
std::bind(undo_redo, std::placeholders::_1, id, !val),
|
||||
std::bind(undo_redo, std::placeholders::_1, id, val),
|
||||
uuid, uuid);
|
||||
main->undo_s.add_action(str.arg(obs_source_get_name(source), name),
|
||||
std::bind(undo_redo, std::placeholders::_1, id, !val),
|
||||
std::bind(undo_redo, std::placeholders::_1, id, val), uuid, uuid);
|
||||
|
||||
QSignalBlocker sourcesSignalBlocker(this);
|
||||
obs_sceneitem_set_visible(sceneitem, val);
|
||||
|
@ -200,16 +189,12 @@ void SourceTreeItem::ReconnectSignals()
|
|||
/* --------------------------------------------------------- */
|
||||
|
||||
auto removeItem = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
obs_scene_t *curScene =
|
||||
(obs_scene_t *)calldata_ptr(cd, "scene");
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
obs_scene_t *curScene = (obs_scene_t *)calldata_ptr(cd, "scene");
|
||||
|
||||
if (curItem == this_->sceneitem) {
|
||||
QMetaObject::invokeMethod(this_->tree, "Remove",
|
||||
Q_ARG(OBSSceneItem, curItem),
|
||||
QMetaObject::invokeMethod(this_->tree, "Remove", Q_ARG(OBSSceneItem, curItem),
|
||||
Q_ARG(OBSScene, curScene));
|
||||
curItem = nullptr;
|
||||
}
|
||||
|
@ -218,52 +203,41 @@ void SourceTreeItem::ReconnectSignals()
|
|||
};
|
||||
|
||||
auto itemVisible = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
bool visible = calldata_bool(cd, "visible");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
QMetaObject::invokeMethod(this_, "VisibilityChanged",
|
||||
Q_ARG(bool, visible));
|
||||
QMetaObject::invokeMethod(this_, "VisibilityChanged", Q_ARG(bool, visible));
|
||||
};
|
||||
|
||||
auto itemLocked = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
bool locked = calldata_bool(cd, "locked");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
QMetaObject::invokeMethod(this_, "LockedChanged",
|
||||
Q_ARG(bool, locked));
|
||||
QMetaObject::invokeMethod(this_, "LockedChanged", Q_ARG(bool, locked));
|
||||
};
|
||||
|
||||
auto itemSelect = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
QMetaObject::invokeMethod(this_, "Select");
|
||||
};
|
||||
|
||||
auto itemDeselect = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
|
||||
if (curItem == this_->sceneitem)
|
||||
QMetaObject::invokeMethod(this_, "Deselect");
|
||||
};
|
||||
|
||||
auto reorderGroup = [](void *data, calldata_t *) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
QMetaObject::invokeMethod(this_->tree, "ReorderItems");
|
||||
};
|
||||
|
||||
|
@ -288,8 +262,7 @@ void SourceTreeItem::ReconnectSignals()
|
|||
/* --------------------------------------------------------- */
|
||||
|
||||
auto removeSource = [](void *data, calldata_t *) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem *>(data);
|
||||
this_->DisconnectSignals();
|
||||
this_->sceneitem = nullptr;
|
||||
QMetaObject::invokeMethod(this_->tree, "RefreshItems");
|
||||
|
@ -308,8 +281,7 @@ void SourceTreeItem::mouseDoubleClickEvent(QMouseEvent *event)
|
|||
expand->setChecked(!expand->isChecked());
|
||||
} else {
|
||||
obs_source_t *source = obs_sceneitem_get_source(sceneitem);
|
||||
OBSBasic *main =
|
||||
reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
if (obs_source_configurable(source)) {
|
||||
main->CreatePropertiesWindow(source);
|
||||
}
|
||||
|
@ -366,8 +338,7 @@ void SourceTreeItem::ExitEditMode(bool save)
|
|||
OBSData redoSceneData = main->BackupScene(GetCurrentScene());
|
||||
|
||||
QString text = QTStr("Undo.GroupItems").arg(newName.c_str());
|
||||
main->CreateSceneUndoRedoAction(text, tree->undoSceneData,
|
||||
redoSceneData);
|
||||
main->CreateSceneUndoRedoAction(text, tree->undoSceneData, redoSceneData);
|
||||
|
||||
tree->undoSceneData = nullptr;
|
||||
}
|
||||
|
@ -400,8 +371,7 @@ void SourceTreeItem::ExitEditModeInternal(bool save)
|
|||
return;
|
||||
|
||||
if (newName.empty()) {
|
||||
OBSMessageBox::information(main, QTStr("NoNameEntered.Title"),
|
||||
QTStr("NoNameEntered.Text"));
|
||||
OBSMessageBox::information(main, QTStr("NoNameEntered.Title"), QTStr("NoNameEntered.Text"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -415,13 +385,11 @@ void SourceTreeItem::ExitEditModeInternal(bool save)
|
|||
/* ----------------------------------------- */
|
||||
/* check for existing source */
|
||||
|
||||
OBSSourceAutoRelease existingSource =
|
||||
obs_get_source_by_name(newName.c_str());
|
||||
OBSSourceAutoRelease existingSource = obs_get_source_by_name(newName.c_str());
|
||||
bool exists = !!existingSource;
|
||||
|
||||
if (exists) {
|
||||
OBSMessageBox::information(main, QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
OBSMessageBox::information(main, QTStr("NameExists.Title"), QTStr("NameExists.Text"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -430,33 +398,27 @@ void SourceTreeItem::ExitEditModeInternal(bool save)
|
|||
|
||||
QSignalBlocker sourcesSignalBlocker(this);
|
||||
std::string prevName(obs_source_get_name(source));
|
||||
std::string scene_uuid =
|
||||
obs_source_get_uuid(main->GetCurrentSceneSource());
|
||||
std::string scene_uuid = obs_source_get_uuid(main->GetCurrentSceneSource());
|
||||
auto undo = [scene_uuid, prevName, main](const std::string &data) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(data.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(data.c_str());
|
||||
obs_source_set_name(source, prevName.c_str());
|
||||
|
||||
OBSSourceAutoRelease scene_source =
|
||||
obs_get_source_by_uuid(scene_uuid.c_str());
|
||||
OBSSourceAutoRelease scene_source = obs_get_source_by_uuid(scene_uuid.c_str());
|
||||
main->SetCurrentScene(scene_source.Get(), true);
|
||||
};
|
||||
|
||||
std::string editedName = newName;
|
||||
|
||||
auto redo = [scene_uuid, main, editedName](const std::string &data) {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_get_source_by_uuid(data.c_str());
|
||||
OBSSourceAutoRelease source = obs_get_source_by_uuid(data.c_str());
|
||||
obs_source_set_name(source, editedName.c_str());
|
||||
|
||||
OBSSourceAutoRelease scene_source =
|
||||
obs_get_source_by_uuid(scene_uuid.c_str());
|
||||
OBSSourceAutoRelease scene_source = obs_get_source_by_uuid(scene_uuid.c_str());
|
||||
main->SetCurrentScene(scene_source.Get(), true);
|
||||
};
|
||||
|
||||
const char *uuid = obs_source_get_uuid(source);
|
||||
main->undo_s.add_action(QTStr("Undo.Rename").arg(newName.c_str()), undo,
|
||||
redo, uuid, uuid);
|
||||
main->undo_s.add_action(QTStr("Undo.Rename").arg(newName.c_str()), undo, redo, uuid, uuid);
|
||||
|
||||
obs_source_set_name(source, newName.c_str());
|
||||
}
|
||||
|
@ -467,15 +429,11 @@ bool SourceTreeItem::eventFilter(QObject *object, QEvent *event)
|
|||
return false;
|
||||
|
||||
if (LineEditCanceled(event)) {
|
||||
QMetaObject::invokeMethod(this, "ExitEditMode",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(bool, false));
|
||||
QMetaObject::invokeMethod(this, "ExitEditMode", Qt::QueuedConnection, Q_ARG(bool, false));
|
||||
return true;
|
||||
}
|
||||
if (LineEditChanged(event)) {
|
||||
QMetaObject::invokeMethod(this, "ExitEditMode",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(bool, true));
|
||||
QMetaObject::invokeMethod(this, "ExitEditMode", Qt::QueuedConnection, Q_ARG(bool, true));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -559,14 +517,12 @@ void SourceTreeItem::Update(bool force)
|
|||
#endif
|
||||
boxLayout->insertWidget(0, expand);
|
||||
|
||||
OBSDataAutoRelease data =
|
||||
obs_sceneitem_get_private_settings(sceneitem);
|
||||
OBSDataAutoRelease data = obs_sceneitem_get_private_settings(sceneitem);
|
||||
expand->blockSignals(true);
|
||||
expand->setChecked(obs_data_get_bool(data, "collapsed"));
|
||||
expand->blockSignals(false);
|
||||
|
||||
connect(expand, &QPushButton::toggled, this,
|
||||
&SourceTreeItem::ExpandClicked);
|
||||
connect(expand, &QPushButton::toggled, this, &SourceTreeItem::ExpandClicked);
|
||||
|
||||
} else {
|
||||
spacer = new QSpacerItem(3, 1);
|
||||
|
@ -633,8 +589,7 @@ void SourceTreeModel::Clear()
|
|||
|
||||
static bool enumItem(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
||||
{
|
||||
QVector<OBSSceneItem> &items =
|
||||
*reinterpret_cast<QVector<OBSSceneItem> *>(ptr);
|
||||
QVector<OBSSceneItem> &items = *reinterpret_cast<QVector<OBSSceneItem> *>(ptr);
|
||||
|
||||
obs_source_t *src = obs_sceneitem_get_source(item);
|
||||
if (obs_source_removed(src)) {
|
||||
|
@ -642,13 +597,11 @@ static bool enumItem(obs_scene_t *, obs_sceneitem_t *item, void *ptr)
|
|||
}
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
OBSDataAutoRelease data =
|
||||
obs_sceneitem_get_private_settings(item);
|
||||
OBSDataAutoRelease data = obs_sceneitem_get_private_settings(item);
|
||||
|
||||
bool collapse = obs_data_get_bool(data, "collapsed");
|
||||
if (!collapse) {
|
||||
obs_scene_t *scene =
|
||||
obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
|
||||
obs_scene_enum_items(scene, enumItem, &items);
|
||||
}
|
||||
|
@ -674,15 +627,13 @@ void SourceTreeModel::SceneChanged()
|
|||
bool select = obs_sceneitem_selected(items[i]);
|
||||
QModelIndex index = createIndex(i, 0);
|
||||
|
||||
st->selectionModel()->select(
|
||||
index, select ? QItemSelectionModel::Select
|
||||
: QItemSelectionModel::Deselect);
|
||||
st->selectionModel()->select(index,
|
||||
select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
|
||||
}
|
||||
}
|
||||
|
||||
/* moves a scene item index (blame linux distros for using older Qt builds) */
|
||||
static inline void MoveItem(QVector<OBSSceneItem> &items, int oldIdx,
|
||||
int newIdx)
|
||||
static inline void MoveItem(QVector<OBSSceneItem> &items, int oldIdx, int newIdx)
|
||||
{
|
||||
OBSSceneItem item = items[oldIdx];
|
||||
items.remove(oldIdx);
|
||||
|
@ -755,8 +706,7 @@ void SourceTreeModel::ReorderItems()
|
|||
}
|
||||
|
||||
/* move items */
|
||||
beginMoveRows(QModelIndex(), idx1Old, idx1Old + count - 1,
|
||||
QModelIndex(), idx1New + count);
|
||||
beginMoveRows(QModelIndex(), idx1Old, idx1Old + count - 1, QModelIndex(), idx1New + count);
|
||||
for (i = 0; i < count; i++) {
|
||||
int to = idx1New + count;
|
||||
if (to > idx1Old)
|
||||
|
@ -802,8 +752,7 @@ void SourceTreeModel::Remove(obs_sceneitem_t *item)
|
|||
|
||||
for (int i = endIdx + 1; i < items.count(); i++) {
|
||||
obs_sceneitem_t *subitem = items[i];
|
||||
obs_scene_t *subscene =
|
||||
obs_sceneitem_get_scene(subitem);
|
||||
obs_scene_t *subscene = obs_sceneitem_get_scene(subitem);
|
||||
|
||||
if (subscene == scene)
|
||||
endIdx = i;
|
||||
|
@ -829,9 +778,7 @@ OBSSceneItem SourceTreeModel::Get(int idx)
|
|||
return items[idx];
|
||||
}
|
||||
|
||||
SourceTreeModel::SourceTreeModel(SourceTree *st_)
|
||||
: QAbstractListModel(st_),
|
||||
st(st_)
|
||||
SourceTreeModel::SourceTreeModel(SourceTree *st_) : QAbstractListModel(st_), st(st_)
|
||||
{
|
||||
obs_frontend_add_event_callback(OBSFrontendEvent, this);
|
||||
}
|
||||
|
@ -860,8 +807,7 @@ Qt::ItemFlags SourceTreeModel::flags(const QModelIndex &index) const
|
|||
obs_sceneitem_t *item = items[index.row()];
|
||||
bool is_group = obs_sceneitem_is_group(item);
|
||||
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsEditable |
|
||||
Qt::ItemIsDragEnabled |
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsEditable | Qt::ItemIsDragEnabled |
|
||||
(is_group ? Qt::ItemIsDropEnabled : Qt::NoItemFlags);
|
||||
}
|
||||
|
||||
|
@ -877,8 +823,7 @@ QString SourceTreeModel::GetNewGroupName()
|
|||
|
||||
int i = 2;
|
||||
for (;;) {
|
||||
OBSSourceAutoRelease group =
|
||||
obs_get_source_by_name(QT_TO_UTF8(name));
|
||||
OBSSourceAutoRelease group = obs_get_source_by_name(QT_TO_UTF8(name));
|
||||
if (!group)
|
||||
break;
|
||||
name = QTStr("Basic.Main.Group").arg(QString::number(i++));
|
||||
|
@ -890,8 +835,7 @@ QString SourceTreeModel::GetNewGroupName()
|
|||
void SourceTreeModel::AddGroup()
|
||||
{
|
||||
QString name = GetNewGroupName();
|
||||
obs_sceneitem_t *group =
|
||||
obs_scene_add_group(GetCurrentScene(), QT_TO_UTF8(name));
|
||||
obs_sceneitem_t *group = obs_scene_add_group(GetCurrentScene(), QT_TO_UTF8(name));
|
||||
if (!group)
|
||||
return;
|
||||
|
||||
|
@ -902,8 +846,7 @@ void SourceTreeModel::AddGroup()
|
|||
st->UpdateWidget(createIndex(0, 0, nullptr), group);
|
||||
UpdateGroupState(true);
|
||||
|
||||
QMetaObject::invokeMethod(st, "Edit", Qt::QueuedConnection,
|
||||
Q_ARG(int, 0));
|
||||
QMetaObject::invokeMethod(st, "Edit", Qt::QueuedConnection, Q_ARG(int, 0));
|
||||
}
|
||||
|
||||
void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
||||
|
@ -924,8 +867,7 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
|||
|
||||
st->undoSceneData = main->BackupScene(scene);
|
||||
|
||||
obs_sceneitem_t *item = obs_scene_insert_group(
|
||||
scene, QT_TO_UTF8(name), item_order.data(), item_order.size());
|
||||
obs_sceneitem_t *item = obs_scene_insert_group(scene, QT_TO_UTF8(name), item_order.data(), item_order.size());
|
||||
if (!item) {
|
||||
st->undoSceneData = nullptr;
|
||||
return;
|
||||
|
@ -947,8 +889,7 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
|||
/* that's created automatically. */
|
||||
|
||||
int newIdx = indices[0].row();
|
||||
QMetaObject::invokeMethod(st, "NewGroupEdit", Qt::QueuedConnection,
|
||||
Q_ARG(int, newIdx));
|
||||
QMetaObject::invokeMethod(st, "NewGroupEdit", Qt::QueuedConnection, Q_ARG(int, newIdx));
|
||||
}
|
||||
|
||||
void SourceTreeModel::UngroupSelectedGroups(QModelIndexList &indices)
|
||||
|
@ -968,8 +909,7 @@ void SourceTreeModel::UngroupSelectedGroups(QModelIndexList &indices)
|
|||
SceneChanged();
|
||||
|
||||
OBSData redoData = main->BackupScene(scene);
|
||||
main->CreateSceneUndoRedoAction(QTStr("Basic.Main.Ungroup"), undoData,
|
||||
redoData);
|
||||
main->CreateSceneUndoRedoAction(QTStr("Basic.Main.Ungroup"), undoData, redoData);
|
||||
}
|
||||
|
||||
void SourceTreeModel::ExpandGroup(obs_sceneitem_t *item)
|
||||
|
@ -1045,19 +985,17 @@ SourceTree::SourceTree(QWidget *parent_) : QListView(parent_)
|
|||
{
|
||||
SourceTreeModel *stm_ = new SourceTreeModel(this);
|
||||
setModel(stm_);
|
||||
setStyleSheet(QString(
|
||||
"*[bgColor=\"1\"]{background-color:rgba(255,68,68,33%);}"
|
||||
"*[bgColor=\"2\"]{background-color:rgba(255,255,68,33%);}"
|
||||
"*[bgColor=\"3\"]{background-color:rgba(68,255,68,33%);}"
|
||||
"*[bgColor=\"4\"]{background-color:rgba(68,255,255,33%);}"
|
||||
"*[bgColor=\"5\"]{background-color:rgba(68,68,255,33%);}"
|
||||
"*[bgColor=\"6\"]{background-color:rgba(255,68,255,33%);}"
|
||||
"*[bgColor=\"7\"]{background-color:rgba(68,68,68,33%);}"
|
||||
"*[bgColor=\"8\"]{background-color:rgba(255,255,255,33%);}"));
|
||||
setStyleSheet(QString("*[bgColor=\"1\"]{background-color:rgba(255,68,68,33%);}"
|
||||
"*[bgColor=\"2\"]{background-color:rgba(255,255,68,33%);}"
|
||||
"*[bgColor=\"3\"]{background-color:rgba(68,255,68,33%);}"
|
||||
"*[bgColor=\"4\"]{background-color:rgba(68,255,255,33%);}"
|
||||
"*[bgColor=\"5\"]{background-color:rgba(68,68,255,33%);}"
|
||||
"*[bgColor=\"6\"]{background-color:rgba(255,68,255,33%);}"
|
||||
"*[bgColor=\"7\"]{background-color:rgba(68,68,68,33%);}"
|
||||
"*[bgColor=\"8\"]{background-color:rgba(255,255,255,33%);}"));
|
||||
|
||||
UpdateNoSourcesMessage();
|
||||
connect(App(), &OBSApp::StyleChanged, this,
|
||||
&SourceTree::UpdateNoSourcesMessage);
|
||||
connect(App(), &OBSApp::StyleChanged, this, &SourceTree::UpdateNoSourcesMessage);
|
||||
connect(App(), &OBSApp::StyleChanged, this, &SourceTree::UpdateIcons);
|
||||
|
||||
setItemDelegate(new SourceTreeDelegate(this));
|
||||
|
@ -1126,9 +1064,7 @@ void SourceTree::SelectItem(obs_sceneitem_t *sceneitem, bool select)
|
|||
|
||||
QModelIndex index = stm->createIndex(i, 0);
|
||||
if (index.isValid() && select != selectionModel()->isSelected(index))
|
||||
selectionModel()->select(
|
||||
index, select ? QItemSelectionModel::Select
|
||||
: QItemSelectionModel::Deselect);
|
||||
selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(OBSSceneItem);
|
||||
|
@ -1175,9 +1111,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
obs_sceneitem_t *dropItem = items[row]; /* item being dropped on */
|
||||
bool itemIsGroup = obs_sceneitem_is_group(dropItem);
|
||||
|
||||
obs_sceneitem_t *dropGroup =
|
||||
itemIsGroup ? dropItem
|
||||
: obs_sceneitem_get_group(scene, dropItem);
|
||||
obs_sceneitem_t *dropGroup = itemIsGroup ? dropItem : obs_sceneitem_get_group(scene, dropItem);
|
||||
|
||||
/* not a group if moving above the group */
|
||||
if (indicator == QAbstractItemView::AboveItem && itemIsGroup)
|
||||
|
@ -1191,14 +1125,12 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
|
||||
bool dropOnCollapsed = false;
|
||||
if (dropGroup) {
|
||||
obs_data_t *data =
|
||||
obs_sceneitem_get_private_settings(dropGroup);
|
||||
obs_data_t *data = obs_sceneitem_get_private_settings(dropGroup);
|
||||
dropOnCollapsed = obs_data_get_bool(data, "collapsed");
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
if (indicator == QAbstractItemView::BelowItem ||
|
||||
indicator == QAbstractItemView::OnItem ||
|
||||
if (indicator == QAbstractItemView::BelowItem || indicator == QAbstractItemView::OnItem ||
|
||||
indicator == QAbstractItemView::OnViewport)
|
||||
row++;
|
||||
|
||||
|
@ -1230,8 +1162,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
itemBelow = stm->items[row];
|
||||
|
||||
if (hasGroups) {
|
||||
if (!itemBelow ||
|
||||
obs_sceneitem_get_group(scene, itemBelow) != dropGroup) {
|
||||
if (!itemBelow || obs_sceneitem_get_group(scene, itemBelow) != dropGroup) {
|
||||
dropGroup = nullptr;
|
||||
dropOnCollapsed = false;
|
||||
}
|
||||
|
@ -1252,8 +1183,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
for (int i = 0; i < indices.size(); i++) {
|
||||
obs_sceneitem_t *item = items[indices[i].row()];
|
||||
if (obs_sceneitem_get_scene(item) != scene)
|
||||
sources.push_back(obs_scene_get_source(
|
||||
obs_sceneitem_get_scene(item)));
|
||||
sources.push_back(obs_scene_get_source(obs_sceneitem_get_scene(item)));
|
||||
}
|
||||
if (dropGroup)
|
||||
sources.push_back(obs_sceneitem_get_source(dropGroup));
|
||||
|
@ -1282,13 +1212,10 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
if (obs_sceneitem_is_group(item)) {
|
||||
for (int j = items.size() - 1; j >= 0; j--) {
|
||||
obs_sceneitem_t *subitem = items[j];
|
||||
obs_sceneitem_t *subitemGroup =
|
||||
obs_sceneitem_get_group(
|
||||
scene, subitem);
|
||||
obs_sceneitem_t *subitemGroup = obs_sceneitem_get_group(scene, subitem);
|
||||
|
||||
if (subitemGroup == item) {
|
||||
QModelIndex idx =
|
||||
stm->createIndex(j, 0);
|
||||
QModelIndex idx = stm->createIndex(j, 0);
|
||||
indices.insert(i + 1, idx);
|
||||
}
|
||||
}
|
||||
|
@ -1318,8 +1245,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
itemTo--;
|
||||
|
||||
if (itemTo != from) {
|
||||
stm->beginMoveRows(QModelIndex(), from, from,
|
||||
QModelIndex(), to);
|
||||
stm->beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
|
||||
MoveItem(items, from, itemTo);
|
||||
stm->endMoveRows();
|
||||
}
|
||||
|
@ -1348,22 +1274,18 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
|
||||
using insertCollapsed_t = decltype(insertCollapsed);
|
||||
|
||||
auto preInsertCollapsed = [](obs_scene_t *, obs_sceneitem_t *item,
|
||||
void *param) {
|
||||
auto preInsertCollapsed = [](obs_scene_t *, obs_sceneitem_t *item, void *param) {
|
||||
(*reinterpret_cast<insertCollapsed_t *>(param))(item);
|
||||
return true;
|
||||
};
|
||||
|
||||
auto insertLastGroup = [&]() {
|
||||
OBSDataAutoRelease data =
|
||||
obs_sceneitem_get_private_settings(lastGroup);
|
||||
OBSDataAutoRelease data = obs_sceneitem_get_private_settings(lastGroup);
|
||||
bool collapsed = obs_data_get_bool(data, "collapsed");
|
||||
|
||||
if (collapsed) {
|
||||
insertCollapsedIdx = 0;
|
||||
obs_sceneitem_group_enum_items(lastGroup,
|
||||
preInsertCollapsed,
|
||||
&insertCollapsed);
|
||||
obs_sceneitem_group_enum_items(lastGroup, preInsertCollapsed, &insertCollapsed);
|
||||
}
|
||||
|
||||
struct obs_sceneitem_order_info info;
|
||||
|
@ -1407,8 +1329,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
insertLastGroup();
|
||||
}
|
||||
|
||||
obs_scene_reorder_items2(scene, orderList.data(),
|
||||
orderList.size());
|
||||
obs_scene_reorder_items2(scene, orderList.data(), orderList.size());
|
||||
};
|
||||
|
||||
using updateScene_t = decltype(updateScene);
|
||||
|
@ -1454,8 +1375,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
QListView::dropEvent(event);
|
||||
}
|
||||
|
||||
void SourceTree::selectionChanged(const QItemSelection &selected,
|
||||
const QItemSelection &deselected)
|
||||
void SourceTree::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
{
|
||||
QSignalBlocker sourcesSignalBlocker(this);
|
||||
|
@ -1504,8 +1424,7 @@ void SourceTree::NewGroupEdit(int row)
|
|||
OBSData redoSceneData = main->BackupScene(GetCurrentScene());
|
||||
|
||||
QString text = QTStr("Undo.GroupItems").arg("Unknown");
|
||||
main->CreateSceneUndoRedoAction(text, undoSceneData,
|
||||
redoSceneData);
|
||||
main->CreateSceneUndoRedoAction(text, undoSceneData, redoSceneData);
|
||||
|
||||
undoSceneData = nullptr;
|
||||
}
|
||||
|
@ -1610,10 +1529,8 @@ void SourceTree::Remove(OBSSceneItem item, OBSScene scene)
|
|||
if (!main->SavingDisabled()) {
|
||||
obs_source_t *sceneSource = obs_scene_get_source(scene);
|
||||
obs_source_t *itemSource = obs_sceneitem_get_source(item);
|
||||
blog(LOG_INFO, "User Removed source '%s' (%s) from scene '%s'",
|
||||
obs_source_get_name(itemSource),
|
||||
obs_source_get_id(itemSource),
|
||||
obs_source_get_name(sceneSource));
|
||||
blog(LOG_INFO, "User Removed source '%s' (%s) from scene '%s'", obs_source_get_name(itemSource),
|
||||
obs_source_get_id(itemSource), obs_source_get_name(sceneSource));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1637,8 +1554,7 @@ void SourceTree::AddGroup()
|
|||
|
||||
void SourceTree::UpdateNoSourcesMessage()
|
||||
{
|
||||
QString file = !App()->IsThemeDark() ? ":res/images/no_sources.svg"
|
||||
: "theme:Dark/no_sources.svg";
|
||||
QString file = !App()->IsThemeDark() ? ":res/images/no_sources.svg" : "theme:Dark/no_sources.svg";
|
||||
iconNoSources.load(file);
|
||||
|
||||
QTextOption opt(Qt::AlignHCenter);
|
||||
|
@ -1668,8 +1584,7 @@ void SourceTree::paintEvent(QPaintEvent *event)
|
|||
QSizeF thisSize = size();
|
||||
const qreal spacing = 16.0;
|
||||
|
||||
qreal totalHeight =
|
||||
iconSize.height() + spacing + textSize.height();
|
||||
qreal totalHeight = iconSize.height() + spacing + textSize.height();
|
||||
|
||||
qreal x = thisSize.width() / 2.0 - iconSize.width() / 2.0;
|
||||
qreal y = thisSize.height() / 2.0 - totalHeight / 2.0;
|
||||
|
@ -1684,13 +1599,9 @@ void SourceTree::paintEvent(QPaintEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
SourceTreeDelegate::SourceTreeDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
SourceTreeDelegate::SourceTreeDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
|
||||
|
||||
QSize SourceTreeDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
QSize SourceTreeDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
SourceTree *tree = qobject_cast<SourceTree *>(parent());
|
||||
QWidget *item = tree->indexWidget(index);
|
||||
|
|
|
@ -120,8 +120,7 @@ public:
|
|||
explicit SourceTreeModel(SourceTree *st);
|
||||
|
||||
virtual int rowCount(const QModelIndex &parent) const override;
|
||||
virtual QVariant data(const QModelIndex &index,
|
||||
int role) const override;
|
||||
virtual QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
virtual Qt::DropActions supportedDropActions() const override;
|
||||
|
@ -149,10 +148,7 @@ class SourceTree : public QListView {
|
|||
void UpdateWidget(const QModelIndex &idx, obs_sceneitem_t *item);
|
||||
void UpdateWidgets(bool force = false);
|
||||
|
||||
inline SourceTreeModel *GetStm() const
|
||||
{
|
||||
return reinterpret_cast<SourceTreeModel *>(model());
|
||||
}
|
||||
inline SourceTreeModel *GetStm() const { return reinterpret_cast<SourceTreeModel *>(model()); }
|
||||
|
||||
public:
|
||||
inline SourceTreeItem *GetItemWidget(int idx)
|
||||
|
@ -194,9 +190,7 @@ protected:
|
|||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
virtual void
|
||||
selectionChanged(const QItemSelection &selected,
|
||||
const QItemSelection &deselected) override;
|
||||
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override;
|
||||
};
|
||||
|
||||
class SourceTreeDelegate : public QStyledItemDelegate {
|
||||
|
@ -204,6 +198,5 @@ class SourceTreeDelegate : public QStyledItemDelegate {
|
|||
|
||||
public:
|
||||
SourceTreeDelegate(QObject *parent);
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
};
|
||||
|
|
|
@ -49,16 +49,14 @@ static std::optional<std::vector<GoLiveApi::Gpu>> system_gpu_data()
|
|||
|
||||
/* driver version */
|
||||
LARGE_INTEGER umd;
|
||||
hr = adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice),
|
||||
&umd);
|
||||
hr = adapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &umd);
|
||||
if (SUCCEEDED(hr)) {
|
||||
const uint64_t version = umd.QuadPart;
|
||||
const uint16_t aa = (version >> 48) & 0xffff;
|
||||
const uint16_t bb = (version >> 32) & 0xffff;
|
||||
const uint16_t ccccc = (version >> 16) & 0xffff;
|
||||
const uint16_t ddddd = version & 0xffff;
|
||||
snprintf(driver_version, sizeof(driver_version),
|
||||
"%" PRIu16 ".%" PRIu16 ".%" PRIu16 ".%" PRIu16,
|
||||
snprintf(driver_version, sizeof(driver_version), "%" PRIu16 ".%" PRIu16 ".%" PRIu16 ".%" PRIu16,
|
||||
aa, bb, ccccc, ddddd);
|
||||
data.driver_version = driver_version;
|
||||
}
|
||||
|
@ -78,15 +76,12 @@ static void get_processor_info(char **name, DWORD *speed)
|
|||
|
||||
memset(data, 0, sizeof(data));
|
||||
|
||||
status = RegOpenKeyW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);
|
||||
status = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &key);
|
||||
if (status != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
size = sizeof(data);
|
||||
status = RegQueryValueExW(key, L"ProcessorNameString", NULL, NULL,
|
||||
(LPBYTE)data, &size);
|
||||
status = RegQueryValueExW(key, L"ProcessorNameString", NULL, NULL, (LPBYTE)data, &size);
|
||||
if (status == ERROR_SUCCESS) {
|
||||
os_wcs_to_utf8_ptr(data, 0, name);
|
||||
} else {
|
||||
|
@ -94,25 +89,20 @@ static void get_processor_info(char **name, DWORD *speed)
|
|||
}
|
||||
|
||||
size = sizeof(*speed);
|
||||
status = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE)speed,
|
||||
&size);
|
||||
status = RegQueryValueExW(key, L"~MHz", NULL, NULL, (LPBYTE)speed, &size);
|
||||
if (status != ERROR_SUCCESS)
|
||||
*speed = 0;
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
#define WIN10_GAME_BAR_REG_KEY \
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR"
|
||||
#define WIN10_GAME_DVR_POLICY_REG_KEY \
|
||||
L"SOFTWARE\\Policies\\Microsoft\\Windows\\GameDVR"
|
||||
#define WIN10_GAME_BAR_REG_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\GameDVR"
|
||||
#define WIN10_GAME_DVR_POLICY_REG_KEY L"SOFTWARE\\Policies\\Microsoft\\Windows\\GameDVR"
|
||||
#define WIN10_GAME_DVR_REG_KEY L"System\\GameConfigStore"
|
||||
#define WIN10_GAME_MODE_REG_KEY L"Software\\Microsoft\\GameBar"
|
||||
#define WIN10_HAGS_REG_KEY \
|
||||
L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers"
|
||||
#define WIN10_HAGS_REG_KEY L"SYSTEM\\CurrentControlSet\\Control\\GraphicsDrivers"
|
||||
|
||||
static std::optional<GoLiveApi::GamingFeatures>
|
||||
get_gaming_features_data(const win_version_info &ver)
|
||||
static std::optional<GoLiveApi::GamingFeatures> get_gaming_features_data(const win_version_info &ver)
|
||||
{
|
||||
uint32_t win_ver = (ver.major << 8) | ver.minor;
|
||||
if (win_ver < 0xA00)
|
||||
|
@ -130,36 +120,29 @@ get_gaming_features_data(const win_version_info &ver)
|
|||
DWORD disabled_value;
|
||||
};
|
||||
struct feature_mapping_s features[] = {
|
||||
{&gaming_features.game_bar_enabled, HKEY_CURRENT_USER,
|
||||
WIN10_GAME_BAR_REG_KEY, L"AppCaptureEnabled", 0, false, 0},
|
||||
{&gaming_features.game_dvr_allowed, HKEY_CURRENT_USER,
|
||||
WIN10_GAME_DVR_POLICY_REG_KEY, L"AllowGameDVR", 0, false, 0},
|
||||
{&gaming_features.game_dvr_enabled, HKEY_CURRENT_USER,
|
||||
WIN10_GAME_DVR_REG_KEY, L"GameDVR_Enabled", 0, false, 0},
|
||||
{&gaming_features.game_dvr_bg_recording, HKEY_CURRENT_USER,
|
||||
WIN10_GAME_BAR_REG_KEY, L"HistoricalCaptureEnabled", 0, false,
|
||||
0},
|
||||
{&gaming_features.game_mode_enabled, HKEY_CURRENT_USER,
|
||||
WIN10_GAME_MODE_REG_KEY, L"AutoGameModeEnabled",
|
||||
{&gaming_features.game_bar_enabled, HKEY_CURRENT_USER, WIN10_GAME_BAR_REG_KEY, L"AppCaptureEnabled", 0,
|
||||
false, 0},
|
||||
{&gaming_features.game_dvr_allowed, HKEY_CURRENT_USER, WIN10_GAME_DVR_POLICY_REG_KEY, L"AllowGameDVR",
|
||||
0, false, 0},
|
||||
{&gaming_features.game_dvr_enabled, HKEY_CURRENT_USER, WIN10_GAME_DVR_REG_KEY, L"GameDVR_Enabled", 0,
|
||||
false, 0},
|
||||
{&gaming_features.game_dvr_bg_recording, HKEY_CURRENT_USER, WIN10_GAME_BAR_REG_KEY,
|
||||
L"HistoricalCaptureEnabled", 0, false, 0},
|
||||
{&gaming_features.game_mode_enabled, HKEY_CURRENT_USER, WIN10_GAME_MODE_REG_KEY, L"AutoGameModeEnabled",
|
||||
L"AllowAutoGameMode", false, 0},
|
||||
{&gaming_features.hags_enabled, HKEY_LOCAL_MACHINE,
|
||||
WIN10_HAGS_REG_KEY, L"HwSchMode", 0, true, 1}};
|
||||
{&gaming_features.hags_enabled, HKEY_LOCAL_MACHINE, WIN10_HAGS_REG_KEY, L"HwSchMode", 0, true, 1}};
|
||||
|
||||
for (int i = 0; i < sizeof(features) / sizeof(*features); ++i) {
|
||||
struct reg_dword info;
|
||||
|
||||
get_reg_dword(features[i].hkey, features[i].sub_key,
|
||||
features[i].value_name, &info);
|
||||
get_reg_dword(features[i].hkey, features[i].sub_key, features[i].value_name, &info);
|
||||
|
||||
if (info.status != ERROR_SUCCESS &&
|
||||
features[i].backup_value_name) {
|
||||
get_reg_dword(features[i].hkey, features[i].sub_key,
|
||||
features[i].backup_value_name, &info);
|
||||
if (info.status != ERROR_SUCCESS && features[i].backup_value_name) {
|
||||
get_reg_dword(features[i].hkey, features[i].sub_key, features[i].backup_value_name, &info);
|
||||
}
|
||||
|
||||
if (info.status == ERROR_SUCCESS) {
|
||||
*features[i].field = info.return_value !=
|
||||
features[i].disabled_value;
|
||||
*features[i].field = info.return_value != features[i].disabled_value;
|
||||
} else if (features[i].non_existence_is_false) {
|
||||
*features[i].field = false;
|
||||
}
|
||||
|
@ -168,11 +151,9 @@ get_gaming_features_data(const win_version_info &ver)
|
|||
return gaming_features;
|
||||
}
|
||||
|
||||
static inline bool get_reg_sz(HKEY key, const wchar_t *val, wchar_t *buf,
|
||||
DWORD size)
|
||||
static inline bool get_reg_sz(HKEY key, const wchar_t *val, wchar_t *buf, DWORD size)
|
||||
{
|
||||
const LSTATUS status =
|
||||
RegGetValueW(key, NULL, val, RRF_RT_REG_SZ, NULL, buf, &size);
|
||||
const LSTATUS status = RegGetValueW(key, NULL, val, RRF_RT_REG_SZ, NULL, buf, &size);
|
||||
return status == ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -194,18 +175,15 @@ static inline void get_reg_ver(struct win_version_info *ver)
|
|||
|
||||
size = sizeof(dw_val);
|
||||
|
||||
status = RegQueryValueExW(key, L"CurrentMajorVersionNumber", NULL, NULL,
|
||||
(LPBYTE)&dw_val, &size);
|
||||
status = RegQueryValueExW(key, L"CurrentMajorVersionNumber", NULL, NULL, (LPBYTE)&dw_val, &size);
|
||||
if (status == ERROR_SUCCESS)
|
||||
ver->major = (int)dw_val;
|
||||
|
||||
status = RegQueryValueExW(key, L"CurrentMinorVersionNumber", NULL, NULL,
|
||||
(LPBYTE)&dw_val, &size);
|
||||
status = RegQueryValueExW(key, L"CurrentMinorVersionNumber", NULL, NULL, (LPBYTE)&dw_val, &size);
|
||||
if (status == ERROR_SUCCESS)
|
||||
ver->minor = (int)dw_val;
|
||||
|
||||
status = RegQueryValueExW(key, L"UBR", NULL, NULL, (LPBYTE)&dw_val,
|
||||
&size);
|
||||
status = RegQueryValueExW(key, L"UBR", NULL, NULL, (LPBYTE)&dw_val, &size);
|
||||
if (status == ERROR_SUCCESS)
|
||||
ver->revis = (int)dw_val;
|
||||
|
||||
|
@ -213,8 +191,7 @@ static inline void get_reg_ver(struct win_version_info *ver)
|
|||
ver->build = wcstol(str, NULL, 10);
|
||||
}
|
||||
|
||||
const wchar_t *release_key = ver->build > 19041 ? L"DisplayVersion"
|
||||
: L"ReleaseId";
|
||||
const wchar_t *release_key = ver->build > 19041 ? L"DisplayVersion" : L"ReleaseId";
|
||||
if (get_reg_sz(key, release_key, str, sizeof(str))) {
|
||||
os_wcs_to_utf8(str, 0, win_release_id, MAX_SZ_LEN);
|
||||
}
|
||||
|
|
|
@ -44,8 +44,7 @@ bool UIValidation::NoSourcesConfirmation(QWidget *parent)
|
|||
messageBox.setWindowTitle(QTStr("NoSources.Title"));
|
||||
messageBox.setText(msg);
|
||||
|
||||
QAbstractButton *yesButton =
|
||||
messageBox.addButton(QTStr("Yes"), QMessageBox::YesRole);
|
||||
QAbstractButton *yesButton = messageBox.addButton(QTStr("Yes"), QMessageBox::YesRole);
|
||||
messageBox.addButton(QTStr("No"), QMessageBox::NoRole);
|
||||
messageBox.setIcon(QMessageBox::Question);
|
||||
messageBox.exec();
|
||||
|
@ -56,8 +55,7 @@ bool UIValidation::NoSourcesConfirmation(QWidget *parent)
|
|||
return true;
|
||||
}
|
||||
|
||||
StreamSettingsAction
|
||||
UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
||||
StreamSettingsAction UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
||||
{
|
||||
if (obs_service_can_try_to_connect(service))
|
||||
return StreamSettingsAction::ContinueStream;
|
||||
|
@ -65,10 +63,8 @@ UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
|||
char const *serviceType = obs_service_get_type(service);
|
||||
bool isCustomService = (strcmp(serviceType, "rtmp_custom") == 0);
|
||||
|
||||
char const *streamUrl = obs_service_get_connect_info(
|
||||
service, OBS_SERVICE_CONNECT_INFO_SERVER_URL);
|
||||
char const *streamKey = obs_service_get_connect_info(
|
||||
service, OBS_SERVICE_CONNECT_INFO_STREAM_KEY);
|
||||
char const *streamUrl = obs_service_get_connect_info(service, OBS_SERVICE_CONNECT_INFO_SERVER_URL);
|
||||
char const *streamKey = obs_service_get_connect_info(service, OBS_SERVICE_CONNECT_INFO_STREAM_KEY);
|
||||
|
||||
bool streamUrlMissing = !(streamUrl != NULL && streamUrl[0] != '\0');
|
||||
bool streamKeyMissing = !(streamKey != NULL && streamKey[0] != '\0');
|
||||
|
@ -83,8 +79,7 @@ UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
|||
}
|
||||
|
||||
QMessageBox messageBox(parent);
|
||||
messageBox.setWindowTitle(
|
||||
QTStr("Basic.Settings.Stream.MissingSettingAlert"));
|
||||
messageBox.setWindowTitle(QTStr("Basic.Settings.Stream.MissingSettingAlert"));
|
||||
messageBox.setText(msg);
|
||||
|
||||
QPushButton *cancel;
|
||||
|
@ -97,9 +92,7 @@ UIValidation::StreamSettingsConfirmation(QWidget *parent, OBSService service)
|
|||
#define ACCEPT_BUTTON QMessageBox::NoRole
|
||||
#define REJECT_BUTTON QMessageBox::NoRole
|
||||
#endif
|
||||
settings = messageBox.addButton(
|
||||
QTStr("Basic.Settings.Stream.StreamSettingsWarning"),
|
||||
ACCEPT_BUTTON);
|
||||
settings = messageBox.addButton(QTStr("Basic.Settings.Stream.StreamSettingsWarning"), ACCEPT_BUTTON);
|
||||
cancel = messageBox.addButton(QTStr("Cancel"), REJECT_BUTTON);
|
||||
|
||||
messageBox.setDefaultButton(settings);
|
||||
|
|
|
@ -25,6 +25,5 @@ public:
|
|||
* basics is missing in stream, explain missing fields and offer to
|
||||
* open settings, cancel, or continue. Returns Continue if all
|
||||
* settings are valid. */
|
||||
static StreamSettingsAction
|
||||
StreamSettingsConfirmation(QWidget *parent, OBSService service);
|
||||
static StreamSettingsAction StreamSettingsConfirmation(QWidget *parent, OBSService service);
|
||||
};
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
undo_stack::undo_stack(ui_ptr ui) : ui(ui)
|
||||
{
|
||||
QObject::connect(&repeat_reset_timer, &QTimer::timeout, this,
|
||||
&undo_stack::reset_repeatable_state);
|
||||
QObject::connect(&repeat_reset_timer, &QTimer::timeout, this, &undo_stack::reset_repeatable_state);
|
||||
repeat_reset_timer.setSingleShot(true);
|
||||
repeat_reset_timer.setInterval(3000);
|
||||
}
|
||||
|
@ -30,10 +29,8 @@ void undo_stack::clear()
|
|||
ui->actionMainRedo->setDisabled(true);
|
||||
}
|
||||
|
||||
void undo_stack::add_action(const QString &name, const undo_redo_cb &undo,
|
||||
const undo_redo_cb &redo,
|
||||
const std::string &undo_data,
|
||||
const std::string &redo_data, bool repeatable)
|
||||
void undo_stack::add_action(const QString &name, const undo_redo_cb &undo, const undo_redo_cb &redo,
|
||||
const std::string &undo_data, const std::string &redo_data, bool repeatable)
|
||||
{
|
||||
if (!is_enabled())
|
||||
return;
|
||||
|
@ -85,8 +82,7 @@ void undo_stack::undo()
|
|||
ui->actionMainUndo->setDisabled(true);
|
||||
ui->actionMainUndo->setText(QTStr("Undo.Undo"));
|
||||
} else {
|
||||
ui->actionMainUndo->setText(
|
||||
QTStr("Undo.Item.Undo").arg(undo_items.front().name));
|
||||
ui->actionMainUndo->setText(QTStr("Undo.Item.Undo").arg(undo_items.front().name));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,8 +105,7 @@ void undo_stack::redo()
|
|||
ui->actionMainRedo->setDisabled(true);
|
||||
ui->actionMainRedo->setText(QTStr("Undo.Redo"));
|
||||
} else {
|
||||
ui->actionMainRedo->setText(
|
||||
QTStr("Undo.Item.Redo").arg(redo_items.front().name));
|
||||
ui->actionMainRedo->setText(QTStr("Undo.Item.Redo").arg(redo_items.front().name));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,9 +53,8 @@ public:
|
|||
void pop_disabled();
|
||||
|
||||
void clear();
|
||||
void add_action(const QString &name, const undo_redo_cb &undo,
|
||||
const undo_redo_cb &redo, const std::string &undo_data,
|
||||
const std::string &redo_data, bool repeatable = false);
|
||||
void add_action(const QString &name, const undo_redo_cb &undo, const undo_redo_cb &redo,
|
||||
const std::string &undo_data, const std::string &redo_data, bool repeatable = false);
|
||||
void undo();
|
||||
void redo();
|
||||
};
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/pk.h"
|
||||
|
||||
bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen,
|
||||
const uint8_t *buf, const size_t len, const uint8_t *sig,
|
||||
const size_t sigLen)
|
||||
bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen, const uint8_t *buf, const size_t len,
|
||||
const uint8_t *sig, const size_t sigLen)
|
||||
{
|
||||
bool result = false;
|
||||
int ret = 1;
|
||||
|
@ -15,18 +14,15 @@ bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen,
|
|||
mbedtls_pk_init(&pk);
|
||||
|
||||
// Parse PEM key
|
||||
if ((ret = mbedtls_pk_parse_public_key(&pk, pubKey, pubKeyLen + 1)) !=
|
||||
0) {
|
||||
if ((ret = mbedtls_pk_parse_public_key(&pk, pubKey, pubKeyLen + 1)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
// Hash input buffer
|
||||
if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), buf,
|
||||
len, hash)) != 0) {
|
||||
if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), buf, len, hash)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
// Verify signautre
|
||||
if ((ret = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA512, hash, 64, sig,
|
||||
sigLen)) != 0) {
|
||||
if ((ret = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA512, hash, 64, sig, sigLen)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,5 @@
|
|||
#include <stdlib.h>
|
||||
#include <cstdint>
|
||||
|
||||
bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen,
|
||||
const uint8_t *buf, const size_t len, const uint8_t *sig,
|
||||
const size_t sigLen);
|
||||
bool VerifySignature(const uint8_t *pubKey, const size_t pubKeyLen, const uint8_t *buf, const size_t len,
|
||||
const uint8_t *sig, const size_t sigLen);
|
||||
|
|
|
@ -10,16 +10,14 @@
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static const char *MAC_BRANCHES_URL =
|
||||
"https://obsproject.com/update_studio/branches.json";
|
||||
static const char *MAC_BRANCHES_URL = "https://obsproject.com/update_studio/branches.json";
|
||||
static const char *MAC_DEFAULT_BRANCH = "stable";
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
bool GetBranch(std::string &selectedBranch)
|
||||
{
|
||||
const char *config_branch = config_get_string(
|
||||
App()->GetAppConfig(), "General", "UpdateBranch");
|
||||
const char *config_branch = config_get_string(App()->GetAppConfig(), "General", "UpdateBranch");
|
||||
if (!config_branch)
|
||||
return true;
|
||||
|
||||
|
@ -50,8 +48,8 @@ void MacUpdateThread::infoMsg(const QString &title, const QString &text)
|
|||
|
||||
void MacUpdateThread::info(const QString &title, const QString &text)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "infoMsg", Qt::BlockingQueuedConnection,
|
||||
Q_ARG(QString, title), Q_ARG(QString, text));
|
||||
QMetaObject::invokeMethod(this, "infoMsg", Qt::BlockingQueuedConnection, Q_ARG(QString, title),
|
||||
Q_ARG(QString, text));
|
||||
}
|
||||
|
||||
void MacUpdateThread::run()
|
||||
|
@ -62,18 +60,15 @@ try {
|
|||
/* ----------------------------------- *
|
||||
* get branches from server */
|
||||
|
||||
if (FetchAndVerifyFile("branches", "obs-studio/updates/branches.json",
|
||||
MAC_BRANCHES_URL, &text))
|
||||
if (FetchAndVerifyFile("branches", "obs-studio/updates/branches.json", MAC_BRANCHES_URL, &text))
|
||||
App()->SetBranchData(text);
|
||||
|
||||
/* ----------------------------------- *
|
||||
* Validate branch selection */
|
||||
|
||||
if (!GetBranch(branch)) {
|
||||
config_set_string(App()->GetAppConfig(), "General",
|
||||
"UpdateBranch", MAC_DEFAULT_BRANCH);
|
||||
info(QTStr("Updater.BranchNotFound.Title"),
|
||||
QTStr("Updater.BranchNotFound.Text"));
|
||||
config_set_string(App()->GetAppConfig(), "General", "UpdateBranch", MAC_DEFAULT_BRANCH);
|
||||
info(QTStr("Updater.BranchNotFound.Title"), QTStr("Updater.BranchNotFound.Text"));
|
||||
}
|
||||
|
||||
emit Result(QString::fromStdString(branch), manualUpdate);
|
||||
|
|
|
@ -34,10 +34,8 @@ struct JsonBranch {
|
|||
bool windows = false;
|
||||
bool macos = false;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(JsonBranch, name,
|
||||
display_name, description,
|
||||
enabled, visible, windows,
|
||||
macos)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(JsonBranch, name, display_name, description, enabled, visible,
|
||||
windows, macos)
|
||||
};
|
||||
|
||||
using JsonBranches = std::vector<JsonBranch>;
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
template<typename T> struct nlohmann::adl_serializer<std::optional<T>> {
|
||||
static std::optional<T> from_json(const json &json)
|
||||
{
|
||||
return json.is_null() ? std::nullopt
|
||||
: std::optional{json.get<T>()};
|
||||
return json.is_null() ? std::nullopt : std::optional{json.get<T>()};
|
||||
}
|
||||
|
||||
static void to_json(json &json, std::optional<T> t)
|
||||
|
@ -46,8 +45,7 @@ struct WhatsNewPlatforms {
|
|||
bool macos = false;
|
||||
bool linux = false;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WhatsNewPlatforms, windows,
|
||||
macos, linux)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WhatsNewPlatforms, windows, macos, linux)
|
||||
};
|
||||
|
||||
struct WhatsNewItem {
|
||||
|
@ -63,8 +61,7 @@ struct WhatsNewItem {
|
|||
/* Optional OS filter */
|
||||
std::optional<WhatsNewPlatforms> os = std::nullopt;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WhatsNewItem, version, Beta,
|
||||
RC, url, increment, os)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(WhatsNewItem, version, Beta, RC, url, increment, os)
|
||||
};
|
||||
|
||||
using WhatsNewList = std::vector<WhatsNewItem>;
|
||||
|
|
|
@ -50,16 +50,13 @@ extern QCef *cef;
|
|||
|
||||
static bool QuickWriteFile(const char *file, const std::string &data)
|
||||
try {
|
||||
std::ofstream fileStream(std::filesystem::u8path(file),
|
||||
std::ios::binary);
|
||||
std::ofstream fileStream(std::filesystem::u8path(file), std::ios::binary);
|
||||
if (fileStream.fail())
|
||||
throw strprintf("Failed to open file '%s': %s", file,
|
||||
strerror(errno));
|
||||
throw strprintf("Failed to open file '%s': %s", file, strerror(errno));
|
||||
|
||||
fileStream.write(data.data(), data.size());
|
||||
if (fileStream.fail())
|
||||
throw strprintf("Failed to write file '%s': %s", file,
|
||||
strerror(errno));
|
||||
throw strprintf("Failed to write file '%s': %s", file, strerror(errno));
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -70,11 +67,9 @@ try {
|
|||
|
||||
static bool QuickReadFile(const char *file, std::string &data)
|
||||
try {
|
||||
std::ifstream fileStream(std::filesystem::u8path(file),
|
||||
std::ios::binary);
|
||||
std::ifstream fileStream(std::filesystem::u8path(file), std::ios::binary);
|
||||
if (!fileStream.is_open() || fileStream.fail())
|
||||
throw strprintf("Failed to open file '%s': %s", file,
|
||||
strerror(errno));
|
||||
throw strprintf("Failed to open file '%s': %s", file, strerror(errno));
|
||||
|
||||
fileStream.seekg(0, fileStream.end);
|
||||
size_t size = fileStream.tellg();
|
||||
|
@ -84,8 +79,7 @@ try {
|
|||
fileStream.read(&data[0], size);
|
||||
|
||||
if (fileStream.fail())
|
||||
throw strprintf("Failed to write file '%s': %s", file,
|
||||
strerror(errno));
|
||||
throw strprintf("Failed to write file '%s': %s", file, strerror(errno));
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -147,8 +141,7 @@ std::string GetProgramGUID()
|
|||
/* NOTE: this is an arbitrary random number that we use to count the
|
||||
* number of unique OBS installations and is not associated with any
|
||||
* kind of identifiable information */
|
||||
const char *pguid = config_get_string(App()->GetAppConfig(), "General",
|
||||
"InstallGUID");
|
||||
const char *pguid = config_get_string(App()->GetAppConfig(), "General", "InstallGUID");
|
||||
std::string guid;
|
||||
if (pguid)
|
||||
guid = pguid;
|
||||
|
@ -157,8 +150,7 @@ std::string GetProgramGUID()
|
|||
GenerateGUID(guid);
|
||||
|
||||
if (!guid.empty())
|
||||
config_set_string(App()->GetAppConfig(), "General",
|
||||
"InstallGUID", guid.c_str());
|
||||
config_set_string(App()->GetAppConfig(), "General", "InstallGUID", guid.c_str());
|
||||
}
|
||||
|
||||
return guid;
|
||||
|
@ -176,16 +168,13 @@ static void LoadPublicKey(std::string &pubkey)
|
|||
throw std::string("Could not read OBS public key file!");
|
||||
}
|
||||
|
||||
static bool CheckDataSignature(const char *name, const std::string &data,
|
||||
const std::string &hexSig)
|
||||
static bool CheckDataSignature(const char *name, const std::string &data, const std::string &hexSig)
|
||||
try {
|
||||
static std::mutex pubkey_mutex;
|
||||
static std::string obsPubKey;
|
||||
|
||||
if (hexSig.empty() || hexSig.length() > 0xFFFF ||
|
||||
(hexSig.length() & 1) != 0)
|
||||
throw strprintf("Missing or invalid signature for %s: %s", name,
|
||||
hexSig.c_str());
|
||||
if (hexSig.empty() || hexSig.length() > 0xFFFF || (hexSig.length() & 1) != 0)
|
||||
throw strprintf("Missing or invalid signature for %s: %s", name, hexSig.c_str());
|
||||
|
||||
std::scoped_lock lock(pubkey_mutex);
|
||||
if (obsPubKey.empty())
|
||||
|
@ -194,8 +183,7 @@ try {
|
|||
// Convert hex string to bytes
|
||||
auto signature = QByteArray::fromHex(hexSig.data());
|
||||
|
||||
if (!VerifySignature((uint8_t *)obsPubKey.data(), obsPubKey.size(),
|
||||
(uint8_t *)data.data(), data.size(),
|
||||
if (!VerifySignature((uint8_t *)obsPubKey.data(), obsPubKey.size(), (uint8_t *)data.data(), data.size(),
|
||||
(uint8_t *)signature.data(), signature.size()))
|
||||
throw strprintf("Signature check failed for %s", name);
|
||||
|
||||
|
@ -208,8 +196,7 @@ try {
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
bool FetchAndVerifyFile(const char *name, const char *file, const char *url,
|
||||
std::string *out,
|
||||
bool FetchAndVerifyFile(const char *name, const char *file, const char *url, std::string *out,
|
||||
const std::vector<std::string> &extraHeaders)
|
||||
{
|
||||
long responseCode;
|
||||
|
@ -223,16 +210,14 @@ bool FetchAndVerifyFile(const char *name, const char *file, const char *url,
|
|||
BPtr<char> filePath = GetAppConfigPathPtr(file);
|
||||
|
||||
if (!extraHeaders.empty()) {
|
||||
headers.insert(headers.end(), extraHeaders.begin(),
|
||||
extraHeaders.end());
|
||||
headers.insert(headers.end(), extraHeaders.begin(), extraHeaders.end());
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
* avoid downloading file again */
|
||||
|
||||
if (CalculateFileHash(filePath, fileHash)) {
|
||||
auto hash = QByteArray::fromRawData((const char *)fileHash,
|
||||
BLAKE2_HASH_LENGTH);
|
||||
auto hash = QByteArray::fromRawData((const char *)fileHash, BLAKE2_HASH_LENGTH);
|
||||
|
||||
QString header = "If-None-Match: " + hash.toHex();
|
||||
headers.push_back(header.toStdString());
|
||||
|
@ -251,15 +236,13 @@ bool FetchAndVerifyFile(const char *name, const char *file, const char *url,
|
|||
/* ----------------------------------- *
|
||||
* get file from server */
|
||||
|
||||
success = GetRemoteFile(url, data, error, &responseCode, nullptr, "",
|
||||
nullptr, headers, &signature);
|
||||
success = GetRemoteFile(url, data, error, &responseCode, nullptr, "", nullptr, headers, &signature);
|
||||
|
||||
if (!success || (responseCode != 200 && responseCode != 304)) {
|
||||
if (responseCode == 404)
|
||||
return false;
|
||||
|
||||
throw strprintf("Failed to fetch %s file: %s", name,
|
||||
error.c_str());
|
||||
throw strprintf("Failed to fetch %s file: %s", name, error.c_str());
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
|
@ -276,12 +259,10 @@ bool FetchAndVerifyFile(const char *name, const char *file, const char *url,
|
|||
|
||||
if (responseCode == 200) {
|
||||
if (!QuickWriteFile(filePath, data))
|
||||
throw strprintf("Could not write file '%s'",
|
||||
filePath.Get());
|
||||
throw strprintf("Could not write file '%s'", filePath.Get());
|
||||
} else if (out) { /* Only read file if caller wants data */
|
||||
if (!QuickReadFile(filePath, data))
|
||||
throw strprintf("Could not read file '%s'",
|
||||
filePath.Get());
|
||||
throw strprintf("Could not read file '%s'", filePath.Get());
|
||||
}
|
||||
|
||||
if (out)
|
||||
|
@ -296,8 +277,7 @@ void WhatsNewInfoThread::run()
|
|||
try {
|
||||
std::string text;
|
||||
|
||||
if (FetchAndVerifyFile("whatsnew", "obs-studio/updates/whatsnew.json",
|
||||
WHATSNEW_URL, &text)) {
|
||||
if (FetchAndVerifyFile("whatsnew", "obs-studio/updates/whatsnew.json", WHATSNEW_URL, &text)) {
|
||||
emit Result(QString::fromStdString(text));
|
||||
}
|
||||
} catch (std::string &text) {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue