mirror of
https://github.com/obsproject/obs-studio
synced 2024-10-24 00:21:34 +00:00
Merge pull request #1935 from obsproject/clang-format
Apply clang-format to the project
This commit is contained in:
commit
c938ea712b
106
.clang-format
Normal file
106
.clang-format
Normal file
|
@ -0,0 +1,106 @@
|
|||
# please use clang-format version 8 or later
|
||||
|
||||
Language: Cpp
|
||||
Standard: Cpp11
|
||||
AccessModifierOffset: -8
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
#AllowAllArgumentsOnNextLine: false # requires clang-format 9
|
||||
#AllowAllConstructorInitializersOnNextLine: false # requires clang-format 9
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
#AllowShortLambdasOnASingleLine: Inline # requires clang-format 9
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakStringLiterals: false # apparently unpredictable
|
||||
ColumnLimit: 80
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 8
|
||||
ContinuationIndentWidth: 8
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- 'json_object_foreach'
|
||||
- 'json_object_foreach_safe'
|
||||
- 'json_array_foreach'
|
||||
IncludeBlocks: Preserve
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 8
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto # requires clang-format 7
|
||||
ObjCBlockIndentWidth: 8
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakString: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
#SpaceAfterLogicalNot: false # requires clang-format 9
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCtorInitializerColon: true # requires clang-format 7
|
||||
SpaceBeforeInheritanceColon: true # requires clang-format 7
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: true # requires clang-format 7
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
StatementMacros: # requires clang-format 8
|
||||
- 'Q_OBJECT'
|
||||
TabWidth: 8
|
||||
#TypenameMacros: # requires clang-format 9
|
||||
# - 'DARRAY'
|
||||
UseTab: ForContinuationAndIndentation
|
|
@ -87,8 +87,8 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
forceMono->setChecked((flags & OBS_SOURCE_FLAG_FORCE_MONO) != 0);
|
||||
|
||||
forceMonoContainer->layout()->addWidget(forceMono);
|
||||
forceMonoContainer->layout()->setAlignment(forceMono,
|
||||
Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
forceMonoContainer->layout()->setAlignment(
|
||||
forceMono, Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
balance->setOrientation(Qt::Horizontal);
|
||||
balance->setMinimum(0);
|
||||
|
@ -98,8 +98,8 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
|
||||
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);
|
||||
|
@ -156,32 +156,32 @@ OBSAdvAudioCtrl::OBSAdvAudioCtrl(QGridLayout *, obs_source_t *source_)
|
|||
mixerContainer->layout()->addWidget(mixer5);
|
||||
mixerContainer->layout()->addWidget(mixer6);
|
||||
|
||||
QWidget::connect(volume, SIGNAL(valueChanged(double)),
|
||||
this, SLOT(volumeChanged(double)));
|
||||
QWidget::connect(forceMono, SIGNAL(clicked(bool)),
|
||||
this, SLOT(downmixMonoChanged(bool)));
|
||||
QWidget::connect(balance, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(balanceChanged(int)));
|
||||
QWidget::connect(balance, SIGNAL(doubleClicked()),
|
||||
this, SLOT(ResetBalance()));
|
||||
QWidget::connect(syncOffset, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(syncOffsetChanged(int)));
|
||||
QWidget::connect(volume, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(volumeChanged(double)));
|
||||
QWidget::connect(forceMono, SIGNAL(clicked(bool)), this,
|
||||
SLOT(downmixMonoChanged(bool)));
|
||||
QWidget::connect(balance, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(balanceChanged(int)));
|
||||
QWidget::connect(balance, SIGNAL(doubleClicked()), this,
|
||||
SLOT(ResetBalance()));
|
||||
QWidget::connect(syncOffset, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(syncOffsetChanged(int)));
|
||||
#if defined(_WIN32) || defined(__APPLE__) || HAVE_PULSEAUDIO
|
||||
QWidget::connect(monitoringType, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(monitoringTypeChanged(int)));
|
||||
QWidget::connect(monitoringType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(monitoringTypeChanged(int)));
|
||||
#endif
|
||||
QWidget::connect(mixer1, SIGNAL(clicked(bool)),
|
||||
this, SLOT(mixer1Changed(bool)));
|
||||
QWidget::connect(mixer2, SIGNAL(clicked(bool)),
|
||||
this, SLOT(mixer2Changed(bool)));
|
||||
QWidget::connect(mixer3, SIGNAL(clicked(bool)),
|
||||
this, SLOT(mixer3Changed(bool)));
|
||||
QWidget::connect(mixer4, SIGNAL(clicked(bool)),
|
||||
this, SLOT(mixer4Changed(bool)));
|
||||
QWidget::connect(mixer5, SIGNAL(clicked(bool)),
|
||||
this, SLOT(mixer5Changed(bool)));
|
||||
QWidget::connect(mixer6, SIGNAL(clicked(bool)),
|
||||
this, SLOT(mixer6Changed(bool)));
|
||||
QWidget::connect(mixer1, SIGNAL(clicked(bool)), this,
|
||||
SLOT(mixer1Changed(bool)));
|
||||
QWidget::connect(mixer2, SIGNAL(clicked(bool)), this,
|
||||
SLOT(mixer2Changed(bool)));
|
||||
QWidget::connect(mixer3, SIGNAL(clicked(bool)), this,
|
||||
SLOT(mixer3Changed(bool)));
|
||||
QWidget::connect(mixer4, SIGNAL(clicked(bool)), this,
|
||||
SLOT(mixer4Changed(bool)));
|
||||
QWidget::connect(mixer5, SIGNAL(clicked(bool)), this,
|
||||
SLOT(mixer5Changed(bool)));
|
||||
QWidget::connect(mixer6, SIGNAL(clicked(bool)), this,
|
||||
SLOT(mixer6Changed(bool)));
|
||||
|
||||
setObjectName(sourceName);
|
||||
}
|
||||
|
@ -225,7 +225,6 @@ 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));
|
||||
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::OBSSourceVolumeChanged(void *param, calldata_t *calldata)
|
||||
|
@ -246,7 +245,8 @@ void OBSAdvAudioCtrl::OBSSourceMixersChanged(void *param, calldata_t *calldata)
|
|||
{
|
||||
uint32_t mixers = (uint32_t)calldata_int(calldata, "mixers");
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSAdvAudioCtrl *>(param),
|
||||
"SourceMixersChanged", Q_ARG(uint32_t, mixers));
|
||||
"SourceMixersChanged",
|
||||
Q_ARG(uint32_t, mixers));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -335,14 +335,13 @@ void OBSAdvAudioCtrl::ResetBalance()
|
|||
balance->setValue(50);
|
||||
}
|
||||
|
||||
|
||||
void OBSAdvAudioCtrl::syncOffsetChanged(int milliseconds)
|
||||
{
|
||||
int64_t cur_val = obs_source_get_sync_offset(source);
|
||||
|
||||
if (cur_val / NSEC_PER_MSEC != milliseconds)
|
||||
obs_source_set_sync_offset(source,
|
||||
int64_t(milliseconds) * NSEC_PER_MSEC);
|
||||
obs_source_set_sync_offset(source, int64_t(milliseconds) *
|
||||
NSEC_PER_MSEC);
|
||||
}
|
||||
|
||||
void OBSAdvAudioCtrl::monitoringTypeChanged(int index)
|
||||
|
@ -374,8 +373,10 @@ static inline void setMixer(obs_source_t *source, const int mixerIdx,
|
|||
uint32_t mixers = obs_source_get_audio_mixers(source);
|
||||
uint32_t new_mixers = mixers;
|
||||
|
||||
if (checked) new_mixers |= (1<<mixerIdx);
|
||||
else new_mixers &= ~(1<<mixerIdx);
|
||||
if (checked)
|
||||
new_mixers |= (1 << mixerIdx);
|
||||
else
|
||||
new_mixers &= ~(1 << mixerIdx);
|
||||
|
||||
obs_source_set_audio_mixers(source, new_mixers);
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ using namespace std;
|
|||
Q_DECLARE_METATYPE(OBSScene);
|
||||
Q_DECLARE_METATYPE(OBSSource);
|
||||
|
||||
template <typename T>
|
||||
static T GetOBSRef(QListWidgetItem *item)
|
||||
template<typename T> static T GetOBSRef(QListWidgetItem *item)
|
||||
{
|
||||
return item->data(static_cast<int>(QtDataRole::OBSRef)).value<T>();
|
||||
}
|
||||
|
@ -30,13 +29,13 @@ 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,
|
||||
template<typename T>
|
||||
inline size_t GetCallbackIdx(vector<OBSStudioCallback<T>> &callbacks,
|
||||
T callback, void *private_data)
|
||||
{
|
||||
for (size_t i = 0; i < callbacks.size(); i++) {
|
||||
|
@ -101,12 +100,12 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
void obs_frontend_set_current_scene(obs_source_t *scene) override
|
||||
{
|
||||
if (main->IsPreviewProgramMode()) {
|
||||
QMetaObject::invokeMethod(main, "TransitionToScene",
|
||||
WaitConnection(),
|
||||
QMetaObject::invokeMethod(
|
||||
main, "TransitionToScene", WaitConnection(),
|
||||
Q_ARG(OBSSource, OBSSource(scene)));
|
||||
} else {
|
||||
QMetaObject::invokeMethod(main, "SetCurrentScene",
|
||||
WaitConnection(),
|
||||
QMetaObject::invokeMethod(
|
||||
main, "SetCurrentScene", WaitConnection(),
|
||||
Q_ARG(OBSSource, OBSSource(scene)),
|
||||
Q_ARG(bool, false));
|
||||
}
|
||||
|
@ -132,11 +131,12 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return 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)));
|
||||
Q_ARG(OBSSource,
|
||||
OBSSource(transition)));
|
||||
}
|
||||
|
||||
int obs_frontend_get_transition_duration(void) override
|
||||
|
@ -146,15 +146,14 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
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_get_scene_collections(
|
||||
std::vector<std::string> &strings) override
|
||||
{
|
||||
auto addCollection = [&](const char *name, const char *)
|
||||
{
|
||||
auto addCollection = [&](const char *name, const char *) {
|
||||
strings.emplace_back(name);
|
||||
return true;
|
||||
};
|
||||
|
@ -164,8 +163,8 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
char *obs_frontend_get_current_scene_collection(void) override
|
||||
{
|
||||
const char *cur_name = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
const char *cur_name = config_get_string(
|
||||
App()->GlobalConfig(), "Basic", "SceneCollection");
|
||||
return bstrdup(cur_name);
|
||||
}
|
||||
|
||||
|
@ -189,12 +188,10 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
}
|
||||
}
|
||||
|
||||
bool obs_frontend_add_scene_collection(
|
||||
const char *name) override
|
||||
bool obs_frontend_add_scene_collection(const char *name) override
|
||||
{
|
||||
bool success = false;
|
||||
QMetaObject::invokeMethod(main,
|
||||
"AddSceneCollection",
|
||||
QMetaObject::invokeMethod(main, "AddSceneCollection",
|
||||
WaitConnection(),
|
||||
Q_RETURN_ARG(bool, success),
|
||||
Q_ARG(bool, true),
|
||||
|
@ -202,11 +199,10 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return success;
|
||||
}
|
||||
|
||||
void obs_frontend_get_profiles(
|
||||
std::vector<std::string> &strings) override
|
||||
{
|
||||
auto addProfile = [&](const char *name, const char *)
|
||||
void
|
||||
obs_frontend_get_profiles(std::vector<std::string> &strings) override
|
||||
{
|
||||
auto addProfile = [&](const char *name, const char *) {
|
||||
strings.emplace_back(name);
|
||||
return true;
|
||||
};
|
||||
|
@ -223,8 +219,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
|
||||
void obs_frontend_set_current_profile(const char *profile) override
|
||||
{
|
||||
QList<QAction*> menuActions =
|
||||
main->ui->profileMenu->actions();
|
||||
QList<QAction *> menuActions = main->ui->profileMenu->actions();
|
||||
QString qstrProfile = QT_UTF8(profile);
|
||||
|
||||
for (int i = 0; i < menuActions.count(); i++) {
|
||||
|
@ -297,12 +292,12 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
}
|
||||
|
||||
void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback, void *private_data) override
|
||||
obs_frontend_cb callback,
|
||||
void *private_data) override
|
||||
{
|
||||
main->ui->menuTools->setEnabled(true);
|
||||
|
||||
auto func = [private_data, callback] ()
|
||||
{
|
||||
auto func = [private_data, callback]() {
|
||||
callback(private_data);
|
||||
};
|
||||
|
||||
|
@ -364,10 +359,7 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return App()->GlobalConfig();
|
||||
}
|
||||
|
||||
void obs_frontend_save(void) override
|
||||
{
|
||||
main->SaveProject();
|
||||
}
|
||||
void obs_frontend_save(void) override { main->SaveProject(); }
|
||||
|
||||
void obs_frontend_defer_save_begin(void) override
|
||||
{
|
||||
|
@ -382,8 +374,8 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
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);
|
||||
}
|
||||
|
@ -391,8 +383,8 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
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;
|
||||
|
||||
|
@ -483,11 +475,13 @@ struct OBSStudioAPI : obs_frontend_callbacks {
|
|||
return source;
|
||||
}
|
||||
|
||||
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)),
|
||||
Q_ARG(OBSSource,
|
||||
OBSSource(scene)),
|
||||
Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ static void HandleListProperty(obs_property_t *prop, const char *id)
|
|||
{
|
||||
obs_combo_format format = obs_property_list_format(prop);
|
||||
if (format != OBS_COMBO_FORMAT_INT) {
|
||||
blog(LOG_ERROR, "Encoder '%s' (%s) returned bitrate "
|
||||
blog(LOG_ERROR,
|
||||
"Encoder '%s' (%s) returned bitrate "
|
||||
"OBS_PROPERTY_LIST property of unhandled "
|
||||
"format %d",
|
||||
EncoderName(id), id, static_cast<int>(format));
|
||||
|
@ -60,24 +61,21 @@ 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));
|
||||
bitrateMap[bitrate] = id;
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleSampleRate(obs_property_t *prop, const char *id)
|
||||
{
|
||||
auto ReleaseData = [](obs_data_t *data)
|
||||
{
|
||||
obs_data_release(data);
|
||||
};
|
||||
auto ReleaseData = [](obs_data_t *data) { obs_data_release(data); };
|
||||
std::unique_ptr<obs_data_t, decltype(ReleaseData)> data{
|
||||
obs_encoder_defaults(id),
|
||||
ReleaseData};
|
||||
obs_encoder_defaults(id), ReleaseData};
|
||||
|
||||
if (!data) {
|
||||
blog(LOG_ERROR, "Failed to get defaults for encoder '%s' (%s) "
|
||||
blog(LOG_ERROR,
|
||||
"Failed to get defaults for encoder '%s' (%s) "
|
||||
"while populating bitrate map",
|
||||
EncoderName(id), id);
|
||||
return;
|
||||
|
@ -90,8 +88,8 @@ 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);
|
||||
|
||||
|
@ -100,23 +98,22 @@ static void HandleSampleRate(obs_property_t* prop, const char *id)
|
|||
|
||||
static void HandleEncoderProperties(const char *id)
|
||||
{
|
||||
auto DestroyProperties = [](obs_properties_t *props)
|
||||
{
|
||||
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};
|
||||
obs_get_encoder_properties(id), DestroyProperties};
|
||||
|
||||
if (!props) {
|
||||
blog(LOG_ERROR, "Failed to get properties for encoder "
|
||||
blog(LOG_ERROR,
|
||||
"Failed to get properties for encoder "
|
||||
"'%s' (%s)",
|
||||
EncoderName(id), id);
|
||||
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);
|
||||
|
||||
|
@ -130,12 +127,14 @@ static void HandleEncoderProperties(const char *id)
|
|||
case OBS_PROPERTY_LIST:
|
||||
return HandleListProperty(bitrate, id);
|
||||
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
blog(LOG_ERROR, "Encoder '%s' (%s) returned bitrate property "
|
||||
"of unhandled type %d", EncoderName(id), id,
|
||||
static_cast<int>(type));
|
||||
blog(LOG_ERROR,
|
||||
"Encoder '%s' (%s) returned bitrate property "
|
||||
"of unhandled type %d",
|
||||
EncoderName(id), id, static_cast<int>(type));
|
||||
}
|
||||
|
||||
static const char *GetCodec(const char *id)
|
||||
|
@ -146,8 +145,7 @@ static const char *GetCodec(const char *id)
|
|||
static const string aac_ = "AAC";
|
||||
static void PopulateBitrateMap()
|
||||
{
|
||||
call_once(populateBitrateMap, []()
|
||||
{
|
||||
call_once(populateBitrateMap, []() {
|
||||
struct obs_audio_info aoi;
|
||||
obs_get_audio_info(&aoi);
|
||||
uint32_t output_channels = get_audio_channels(aoi.speakers);
|
||||
|
@ -156,8 +154,7 @@ static void PopulateBitrateMap()
|
|||
|
||||
const char *id = nullptr;
|
||||
for (size_t i = 0; obs_enum_encoder_types(i, &id); i++) {
|
||||
auto Compare = [=](const string &val)
|
||||
{
|
||||
auto Compare = [=](const string &val) {
|
||||
return val == NullToEmpty(id);
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,8 @@ void Auth::Load()
|
|||
{
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
const char *typeStr = config_get_string(main->Config(), "Auth", "Type");
|
||||
if (!typeStr) typeStr = "";
|
||||
if (!typeStr)
|
||||
typeStr = "";
|
||||
|
||||
main->auth = Create(typeStr);
|
||||
if (main->auth) {
|
||||
|
|
|
@ -19,13 +19,14 @@ protected:
|
|||
|
||||
ErrorInfo(std::string message_, std::string error_)
|
||||
: message(message_), error(error_)
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
enum class Type {
|
||||
None,
|
||||
OAuth_StreamKey
|
||||
OAuth_StreamKey,
|
||||
};
|
||||
|
||||
struct Def {
|
||||
|
|
|
@ -26,24 +26,16 @@ extern QCefCookieManager *panel_cookies;
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define MIXER_AUTH_URL \
|
||||
"https://obsproject.com/app-auth/mixer?action=redirect"
|
||||
#define MIXER_TOKEN_URL \
|
||||
"https://obsproject.com/app-auth/mixer-token"
|
||||
#define MIXER_AUTH_URL "https://obsproject.com/app-auth/mixer?action=redirect"
|
||||
#define MIXER_TOKEN_URL "https://obsproject.com/app-auth/mixer-token"
|
||||
|
||||
#define MIXER_SCOPE_VERSION 1
|
||||
|
||||
static Auth::Def mixerDef = {
|
||||
"Mixer",
|
||||
Auth::Type::OAuth_StreamKey
|
||||
};
|
||||
static Auth::Def mixerDef = {"Mixer", Auth::Type::OAuth_StreamKey};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
MixerAuth::MixerAuth(const Def &d)
|
||||
: OAuthStreamKey(d)
|
||||
{
|
||||
}
|
||||
MixerAuth::MixerAuth(const Def &d) : OAuthStreamKey(d) {}
|
||||
|
||||
bool MixerAuth::GetChannelInfo(bool allow_retry)
|
||||
try {
|
||||
|
@ -74,19 +66,12 @@ try {
|
|||
auto func = [&]() {
|
||||
success = GetRemoteFile(
|
||||
"https://mixer.com/api/v1/users/current",
|
||||
output,
|
||||
error,
|
||||
nullptr,
|
||||
"application/json",
|
||||
nullptr,
|
||||
headers,
|
||||
nullptr,
|
||||
5);
|
||||
output, error, nullptr, "application/json",
|
||||
nullptr, headers, nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
func,
|
||||
QTStr("Auth.LoadingChannel.Title"),
|
||||
func, QTStr("Auth.LoadingChannel.Title"),
|
||||
QTStr("Auth.LoadingChannel.Text").arg(service()));
|
||||
if (!success || output.empty())
|
||||
throw ErrorInfo("Failed to get user info from remote",
|
||||
|
@ -98,7 +83,8 @@ try {
|
|||
|
||||
error = json["error"].string_value();
|
||||
if (!error.empty())
|
||||
throw ErrorInfo(error,
|
||||
throw ErrorInfo(
|
||||
error,
|
||||
json["error_description"].string_value());
|
||||
|
||||
id = std::to_string(json["channel"]["id"].int_value());
|
||||
|
@ -115,21 +101,13 @@ try {
|
|||
output.clear();
|
||||
|
||||
auto func = [&]() {
|
||||
success = GetRemoteFile(
|
||||
url.c_str(),
|
||||
output,
|
||||
error,
|
||||
nullptr,
|
||||
"application/json",
|
||||
nullptr,
|
||||
headers,
|
||||
nullptr,
|
||||
5);
|
||||
success = GetRemoteFile(url.c_str(), output, error, nullptr,
|
||||
"application/json", nullptr, headers,
|
||||
nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
func,
|
||||
QTStr("Auth.LoadingChannel.Title"),
|
||||
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);
|
||||
|
@ -140,7 +118,8 @@ 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());
|
||||
|
||||
std::string key_suffix = json["streamKey"].string_value();
|
||||
|
||||
|
@ -161,13 +140,12 @@ try {
|
|||
} 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());
|
||||
.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(),
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -184,9 +162,7 @@ void MixerAuth::SaveInternal()
|
|||
OAuthStreamKey::SaveInternal();
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(
|
||||
OBSBasic *main,
|
||||
const char *section,
|
||||
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);
|
||||
|
@ -252,8 +228,8 @@ void MixerAuth::LoadUI()
|
|||
if (firstLoad) {
|
||||
chat->setVisible(true);
|
||||
} else {
|
||||
const char *dockStateStr = config_get_string(main->Config(),
|
||||
service(), "DockState");
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
main->restoreState(dockState);
|
||||
|
@ -328,9 +304,6 @@ static void DeleteCookies()
|
|||
|
||||
void RegisterMixerAuth()
|
||||
{
|
||||
OAuth::RegisterOAuth(
|
||||
mixerDef,
|
||||
CreateMixerAuth,
|
||||
MixerAuth::Login,
|
||||
OAuth::RegisterOAuth(mixerDef, CreateMixerAuth, MixerAuth::Login,
|
||||
DeleteCookies);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ extern QCefCookieManager *panel_cookies;
|
|||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
OAuthLogin::OAuthLogin(QWidget *parent, const std::string &url, bool token)
|
||||
: QDialog (parent),
|
||||
get_token (token)
|
||||
: QDialog(parent), get_token(token)
|
||||
{
|
||||
if (!cef) {
|
||||
return;
|
||||
|
@ -46,14 +45,13 @@ OAuthLogin::OAuthLogin(QWidget *parent, const std::string &url, bool token)
|
|||
return;
|
||||
}
|
||||
|
||||
connect(cefWidget, SIGNAL(titleChanged(const QString &)),
|
||||
this, SLOT(setWindowTitle(const QString &)));
|
||||
connect(cefWidget, SIGNAL(urlChanged(const QString &)),
|
||||
this, SLOT(urlChanged(const QString &)));
|
||||
connect(cefWidget, SIGNAL(titleChanged(const QString &)), this,
|
||||
SLOT(setWindowTitle(const QString &)));
|
||||
connect(cefWidget, SIGNAL(urlChanged(const QString &)), this,
|
||||
SLOT(urlChanged(const QString &)));
|
||||
|
||||
QPushButton *close = new QPushButton(QTStr("Cancel"));
|
||||
connect(close, &QAbstractButton::clicked,
|
||||
this, &QDialog::reject);
|
||||
connect(close, &QAbstractButton::clicked, this, &QDialog::reject);
|
||||
|
||||
QHBoxLayout *bottomLayout = new QHBoxLayout();
|
||||
bottomLayout->addStretch();
|
||||
|
@ -148,9 +146,7 @@ void OAuth::SaveInternal()
|
|||
config_set_int(main->Config(), service(), "ScopeVer", currentScopeVer);
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(
|
||||
OBSBasic *main,
|
||||
const char *section,
|
||||
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);
|
||||
|
@ -163,11 +159,9 @@ 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");
|
||||
return implicit
|
||||
? !token.empty()
|
||||
: !refresh_token.empty();
|
||||
currentScopeVer =
|
||||
(int)config_get_int(main->Config(), service(), "ScopeVer");
|
||||
return implicit ? !token.empty() : !refresh_token.empty();
|
||||
}
|
||||
|
||||
bool OAuth::TokenExpired()
|
||||
|
@ -191,8 +185,8 @@ 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);
|
||||
}
|
||||
|
@ -217,21 +211,13 @@ try {
|
|||
bool success = false;
|
||||
|
||||
auto func = [&]() {
|
||||
success = GetRemoteFile(
|
||||
url,
|
||||
output,
|
||||
error,
|
||||
nullptr,
|
||||
success = GetRemoteFile(url, output, error, nullptr,
|
||||
"application/x-www-form-urlencoded",
|
||||
post_data.c_str(),
|
||||
std::vector<std::string>(),
|
||||
nullptr,
|
||||
5);
|
||||
std::vector<std::string>(), nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
func,
|
||||
QTStr("Auth.Authing.Title"),
|
||||
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);
|
||||
|
@ -250,7 +236,8 @@ try {
|
|||
}
|
||||
}
|
||||
if (!error.empty())
|
||||
throw ErrorInfo(error, json["error_description"].string_value());
|
||||
throw ErrorInfo(error,
|
||||
json["error_description"].string_value());
|
||||
|
||||
/* -------------------------- */
|
||||
/* success! */
|
||||
|
@ -264,7 +251,8 @@ try {
|
|||
refresh_token = json["refresh_token"].string_value();
|
||||
if (refresh_token.empty())
|
||||
throw ErrorInfo("Failed to get refresh token from "
|
||||
"remote", error);
|
||||
"remote",
|
||||
error);
|
||||
|
||||
currentScopeVer = scope_ver;
|
||||
}
|
||||
|
@ -275,14 +263,13 @@ try {
|
|||
if (!retry) {
|
||||
QString title = QTStr("Auth.AuthFailure.Title");
|
||||
QString text = QTStr("Auth.AuthFailure.Text")
|
||||
.arg(service(), info.message.c_str(), info.error.c_str());
|
||||
.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(),
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,8 @@ public:
|
|||
static void DeleteCookies(const std::string &service);
|
||||
|
||||
static void RegisterOAuth(const Def &d, create_cb create,
|
||||
login_cb login, delete_cookies_cb delete_cookies);
|
||||
login_cb login,
|
||||
delete_cookies_cb delete_cookies);
|
||||
|
||||
protected:
|
||||
std::string refresh_token;
|
||||
|
|
|
@ -22,23 +22,17 @@ extern QCefCookieManager *panel_cookies;
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define RESTREAM_AUTH_URL "https://obsproject.com/app-auth/restream?action=redirect"
|
||||
#define RESTREAM_AUTH_URL \
|
||||
"https://obsproject.com/app-auth/restream?action=redirect"
|
||||
#define RESTREAM_TOKEN_URL "https://obsproject.com/app-auth/restream-token"
|
||||
#define RESTREAM_STREAMKEY_URL "https://api.restream.io/v2/user/streamKey"
|
||||
#define RESTREAM_SCOPE_VERSION 1
|
||||
|
||||
|
||||
static Auth::Def restreamDef = {
|
||||
"Restream",
|
||||
Auth::Type::OAuth_StreamKey
|
||||
};
|
||||
static Auth::Def restreamDef = {"Restream", Auth::Type::OAuth_StreamKey};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
RestreamAuth::RestreamAuth(const Def &d)
|
||||
: OAuthStreamKey(d)
|
||||
{
|
||||
}
|
||||
RestreamAuth::RestreamAuth(const Def &d) : OAuthStreamKey(d) {}
|
||||
|
||||
bool RestreamAuth::GetChannelInfo()
|
||||
try {
|
||||
|
@ -66,21 +60,13 @@ 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"),
|
||||
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);
|
||||
|
@ -91,7 +77,8 @@ 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();
|
||||
|
||||
|
@ -99,13 +86,12 @@ try {
|
|||
} 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());
|
||||
.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(),
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -118,9 +104,7 @@ void RestreamAuth::SaveInternal()
|
|||
OAuthStreamKey::SaveInternal();
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(
|
||||
OBSBasic *main,
|
||||
const char *section,
|
||||
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);
|
||||
|
@ -201,10 +185,9 @@ void RestreamAuth::LoadUI()
|
|||
if (firstLoad) {
|
||||
chat->setVisible(true);
|
||||
info->setVisible(true);
|
||||
}
|
||||
else {
|
||||
const char *dockStateStr = config_get_string(main->Config(),
|
||||
service(), "DockState");
|
||||
} else {
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
main->restoreState(dockState);
|
||||
|
@ -227,8 +210,7 @@ bool RestreamAuth::RetryLogin()
|
|||
std::string client_id = RESTREAM_CLIENTID;
|
||||
deobfuscate_str(&client_id[0], RESTREAM_HASH);
|
||||
|
||||
return GetToken(RESTREAM_TOKEN_URL, client_id,
|
||||
RESTREAM_SCOPE_VERSION,
|
||||
return GetToken(RESTREAM_TOKEN_URL, client_id, RESTREAM_SCOPE_VERSION,
|
||||
QT_TO_UTF8(login.GetCode()), true);
|
||||
}
|
||||
|
||||
|
@ -275,9 +257,6 @@ static void DeleteCookies()
|
|||
|
||||
void RegisterRestreamAuth()
|
||||
{
|
||||
OAuth::RegisterOAuth(
|
||||
restreamDef,
|
||||
CreateRestreamAuth,
|
||||
RestreamAuth::Login,
|
||||
DeleteCookies);
|
||||
OAuth::RegisterOAuth(restreamDef, CreateRestreamAuth,
|
||||
RestreamAuth::Login, DeleteCookies);
|
||||
}
|
||||
|
|
|
@ -24,24 +24,17 @@ extern QCefCookieManager *panel_cookies;
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#define TWITCH_AUTH_URL \
|
||||
"https://obsproject.com/app-auth/twitch?action=redirect"
|
||||
#define TWITCH_TOKEN_URL \
|
||||
"https://obsproject.com/app-auth/twitch-token"
|
||||
#define ACCEPT_HEADER \
|
||||
"Accept: application/vnd.twitchtv.v5+json"
|
||||
#define TWITCH_AUTH_URL "https://obsproject.com/app-auth/twitch?action=redirect"
|
||||
#define TWITCH_TOKEN_URL "https://obsproject.com/app-auth/twitch-token"
|
||||
#define ACCEPT_HEADER "Accept: application/vnd.twitchtv.v5+json"
|
||||
|
||||
#define TWITCH_SCOPE_VERSION 1
|
||||
|
||||
static Auth::Def twitchDef = {
|
||||
"Twitch",
|
||||
Auth::Type::OAuth_StreamKey
|
||||
};
|
||||
static Auth::Def twitchDef = {"Twitch", Auth::Type::OAuth_StreamKey};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
TwitchAuth::TwitchAuth(const Def &d)
|
||||
: OAuthStreamKey(d)
|
||||
TwitchAuth::TwitchAuth(const Def &d) : OAuthStreamKey(d)
|
||||
{
|
||||
if (!cef)
|
||||
return;
|
||||
|
@ -51,8 +44,8 @@ TwitchAuth::TwitchAuth(const Def &d)
|
|||
this);
|
||||
uiLoadTimer.setSingleShot(true);
|
||||
uiLoadTimer.setInterval(500);
|
||||
connect(&uiLoadTimer, &QTimer::timeout,
|
||||
this, &TwitchAuth::TryLoadSecondaryUIPanes);
|
||||
connect(&uiLoadTimer, &QTimer::timeout, this,
|
||||
&TwitchAuth::TryLoadSecondaryUIPanes);
|
||||
}
|
||||
|
||||
bool TwitchAuth::GetChannelInfo()
|
||||
|
@ -83,29 +76,21 @@ try {
|
|||
bool success = false;
|
||||
|
||||
auto func = [&]() {
|
||||
success = GetRemoteFile(
|
||||
"https://api.twitch.tv/kraken/channel",
|
||||
output,
|
||||
error,
|
||||
&error_code,
|
||||
"application/json",
|
||||
nullptr,
|
||||
headers,
|
||||
nullptr,
|
||||
5);
|
||||
success = GetRemoteFile("https://api.twitch.tv/kraken/channel",
|
||||
output, error, &error_code,
|
||||
"application/json", nullptr, headers,
|
||||
nullptr, 5);
|
||||
};
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
func,
|
||||
QTStr("Auth.LoadingChannel.Title"),
|
||||
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);
|
||||
blog(LOG_WARNING, "%s: %s",
|
||||
__FUNCTION__,
|
||||
blog(LOG_WARNING, "%s: %s", __FUNCTION__,
|
||||
"Got 403 from Twitch, user probably does not "
|
||||
"have two-factor authentication enabled on "
|
||||
"their account");
|
||||
|
@ -125,10 +110,10 @@ try {
|
|||
if (RetryLogin()) {
|
||||
return GetChannelInfo();
|
||||
}
|
||||
throw ErrorInfo(error,
|
||||
json["message"].string_value());
|
||||
throw ErrorInfo(error, json["message"].string_value());
|
||||
}
|
||||
throw ErrorInfo(error, json["error_description"].string_value());
|
||||
throw ErrorInfo(error,
|
||||
json["error_description"].string_value());
|
||||
}
|
||||
|
||||
name = json["name"].string_value();
|
||||
|
@ -138,13 +123,12 @@ try {
|
|||
} 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());
|
||||
.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(),
|
||||
blog(LOG_WARNING, "%s: %s: %s", __FUNCTION__, info.message.c_str(),
|
||||
info.error.c_str());
|
||||
return false;
|
||||
}
|
||||
|
@ -160,9 +144,7 @@ void TwitchAuth::SaveInternal()
|
|||
OAuthStreamKey::SaveInternal();
|
||||
}
|
||||
|
||||
static inline std::string get_config_str(
|
||||
OBSBasic *main,
|
||||
const char *section,
|
||||
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);
|
||||
|
@ -266,8 +248,8 @@ void TwitchAuth::LoadUI()
|
|||
if (firstLoad) {
|
||||
chat->setVisible(true);
|
||||
} else {
|
||||
const char *dockStateStr = config_get_string(main->Config(),
|
||||
service(), "DockState");
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
main->restoreState(dockState);
|
||||
|
@ -376,15 +358,15 @@ void TwitchAuth::LoadSecondaryUIPanes()
|
|||
stat->setVisible(false);
|
||||
feed->setVisible(false);
|
||||
} else {
|
||||
uint32_t lastVersion = config_get_int(App()->GlobalConfig(), "General",
|
||||
"LastVersion");
|
||||
uint32_t lastVersion = config_get_int(App()->GlobalConfig(),
|
||||
"General", "LastVersion");
|
||||
|
||||
if (lastVersion <= MAKE_SEMANTIC_VERSION(23, 0, 2)) {
|
||||
feed->setVisible(false);
|
||||
}
|
||||
|
||||
const char *dockStateStr = config_get_string(main->Config(),
|
||||
service(), "DockState");
|
||||
const char *dockStateStr = config_get_string(
|
||||
main->Config(), service(), "DockState");
|
||||
QByteArray dockState =
|
||||
QByteArray::fromBase64(QByteArray(dockStateStr));
|
||||
main->restoreState(dockState);
|
||||
|
@ -405,21 +387,21 @@ void TwitchAuth::TryLoadSecondaryUIPanes()
|
|||
{
|
||||
QPointer<TwitchAuth> this_ = this;
|
||||
|
||||
auto cb = [this_] (bool found)
|
||||
{
|
||||
auto cb = [this_](bool found) {
|
||||
if (!this_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
QMetaObject::invokeMethod(&this_->uiLoadTimer,
|
||||
"start");
|
||||
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()
|
||||
|
@ -429,7 +411,8 @@ 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);
|
||||
|
||||
|
@ -444,7 +427,8 @@ std::shared_ptr<Auth> TwitchAuth::Login(QWidget *parent)
|
|||
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);
|
||||
|
@ -475,9 +459,6 @@ static void DeleteCookies()
|
|||
|
||||
void RegisterTwitchAuth()
|
||||
{
|
||||
OAuth::RegisterOAuth(
|
||||
twitchDef,
|
||||
CreateTwitchAuth,
|
||||
TwitchAuth::Login,
|
||||
OAuth::RegisterOAuth(twitchDef, CreateTwitchAuth, TwitchAuth::Login,
|
||||
DeleteCookies);
|
||||
}
|
||||
|
|
|
@ -32,10 +32,10 @@ OBSCrashReport::OBSCrashReport(QWidget *parent, const char *text)
|
|||
|
||||
setLayout(mainLayout);
|
||||
|
||||
QWidget::connect(copyButton, SIGNAL(clicked()),
|
||||
this, SLOT(CopyClicked()));
|
||||
QWidget::connect(exitButton, SIGNAL(clicked()),
|
||||
this, SLOT(ExitClicked()));
|
||||
QWidget::connect(copyButton, SIGNAL(clicked()), this,
|
||||
SLOT(CopyClicked()));
|
||||
QWidget::connect(exitButton, SIGNAL(clicked()), this,
|
||||
SLOT(ExitClicked()));
|
||||
|
||||
resize(800, 600);
|
||||
setWindowTitle("Oops, OBS has crashed!");
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
#define SUPPORTS_FRACTIONAL_SCALING
|
||||
#endif
|
||||
|
||||
static inline void GetScaleAndCenterPos(
|
||||
int baseCX, int baseCY, int windowCX, int windowCY,
|
||||
int &x, int &y, float &scale)
|
||||
static inline void GetScaleAndCenterPos(int baseCX, int baseCY, int windowCX,
|
||||
int windowCY, int &x, int &y,
|
||||
float &scale)
|
||||
{
|
||||
double windowAspect, baseAspect;
|
||||
int newCX, newCY;
|
||||
|
@ -45,8 +45,8 @@ static inline void GetScaleAndCenterPos(
|
|||
y = windowCY / 2 - newCY / 2;
|
||||
}
|
||||
|
||||
static inline void GetCenterPosFromFixedScale(
|
||||
int baseCX, int baseCY, int windowCX, int windowCY,
|
||||
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;
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
DoubleSlider::DoubleSlider(QWidget *parent) : SliderIgnoreScroll(parent)
|
||||
{
|
||||
connect(this, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(intValChanged(int)));
|
||||
connect(this, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(intValChanged(int)));
|
||||
}
|
||||
|
||||
void DoubleSlider::setDoubleConstraints(double newMin, double newMax,
|
||||
|
|
|
@ -11,8 +11,8 @@ class DoubleSlider : public SliderIgnoreScroll {
|
|||
public:
|
||||
DoubleSlider(QWidget *parent = nullptr);
|
||||
|
||||
void setDoubleConstraints(double newMin, double newMax,
|
||||
double newStep, double val);
|
||||
void setDoubleConstraints(double newMin, double newMax, double newStep,
|
||||
double val);
|
||||
|
||||
signals:
|
||||
void doubleValChanged(double val);
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
#include <QListWidget>
|
||||
|
||||
class FocusList : public QListWidget
|
||||
{
|
||||
class FocusList : public QListWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
#include "decklink-ui-main.h"
|
||||
|
||||
DecklinkOutputUI::DecklinkOutputUI(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_Output)
|
||||
: QDialog(parent), ui(new Ui_Output)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -20,8 +19,10 @@ DecklinkOutputUI::DecklinkOutputUI(QWidget *parent)
|
|||
connect(ui->startOutput, SIGNAL(released()), this, SLOT(StartOutput()));
|
||||
connect(ui->stopOutput, SIGNAL(released()), this, SLOT(StopOutput()));
|
||||
|
||||
connect(ui->startPreviewOutput, SIGNAL(released()), this, SLOT(StartPreviewOutput()));
|
||||
connect(ui->stopPreviewOutput, SIGNAL(released()), this, SLOT(StopPreviewOutput()));
|
||||
connect(ui->startPreviewOutput, SIGNAL(released()), this,
|
||||
SLOT(StartPreviewOutput()));
|
||||
connect(ui->stopPreviewOutput, SIGNAL(released()), this,
|
||||
SLOT(StopPreviewOutput()));
|
||||
}
|
||||
|
||||
void DecklinkOutputUI::ShowHideDialog()
|
||||
|
@ -43,25 +44,26 @@ 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, SIGNAL(Changed()), this, SLOT(PropertiesChanged()));
|
||||
connect(propertiesView, SIGNAL(Changed()), this,
|
||||
SLOT(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)
|
||||
|
@ -79,15 +81,15 @@ 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, SIGNAL(Changed()), this, SLOT(PreviewPropertiesChanged()));
|
||||
connect(previewPropertiesView, SIGNAL(Changed()), this,
|
||||
SLOT(PreviewPropertiesChanged()));
|
||||
}
|
||||
|
||||
void DecklinkOutputUI::SavePreviewSettings()
|
||||
|
@ -96,15 +98,14 @@ void DecklinkOutputUI::SavePreviewSettings()
|
|||
|
||||
os_mkdirs(modulePath);
|
||||
|
||||
char *path = obs_module_get_config_path(obs_current_module(),
|
||||
"decklinkPreviewOutputProps.json");
|
||||
char *path = obs_module_get_config_path(
|
||||
obs_current_module(), "decklinkPreviewOutputProps.json");
|
||||
|
||||
obs_data_t *settings = previewPropertiesView->GetSettings();
|
||||
if (settings)
|
||||
obs_data_save_json_safe(settings, path, "tmp", "bak");
|
||||
}
|
||||
|
||||
|
||||
void DecklinkOutputUI::StartOutput()
|
||||
{
|
||||
SaveSettings();
|
||||
|
@ -121,7 +122,6 @@ void DecklinkOutputUI::PropertiesChanged()
|
|||
SaveSettings();
|
||||
}
|
||||
|
||||
|
||||
void DecklinkOutputUI::StartPreviewOutput()
|
||||
{
|
||||
SavePreviewSettings();
|
||||
|
|
|
@ -37,8 +37,8 @@ static struct preview_output context = {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);
|
||||
|
@ -58,7 +58,8 @@ void output_start()
|
|||
|
||||
if (settings != nullptr) {
|
||||
output = obs_output_create("decklink_output",
|
||||
"decklink_output", settings, NULL);
|
||||
"decklink_output", settings,
|
||||
NULL);
|
||||
|
||||
obs_output_start(output);
|
||||
obs_data_release(settings);
|
||||
|
@ -77,11 +78,10 @@ void output_stop()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
@ -103,8 +103,9 @@ void preview_output_start()
|
|||
OBSData settings = load_preview_settings();
|
||||
|
||||
if (settings != nullptr) {
|
||||
context.output = obs_output_create("decklink_output",
|
||||
"decklink_preview_output", settings, NULL);
|
||||
context.output = obs_output_create(
|
||||
"decklink_output", "decklink_preview_output",
|
||||
settings, NULL);
|
||||
|
||||
obs_get_video_info(&context.ovi);
|
||||
|
||||
|
@ -112,11 +113,14 @@ void preview_output_start()
|
|||
uint32_t height = context.ovi.base_height;
|
||||
|
||||
obs_enter_graphics();
|
||||
context.texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
context.stagesurface = gs_stagesurface_create(width, height, GS_BGRA);
|
||||
context.texrender =
|
||||
gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||
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;
|
||||
|
@ -131,15 +135,21 @@ 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_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());
|
||||
obs_output_start(context.output);
|
||||
|
||||
preview_output_running = true;
|
||||
|
@ -153,8 +163,10 @@ void preview_output_stop()
|
|||
obs_output_stop(context.output);
|
||||
video_output_stop(context.video_queue);
|
||||
|
||||
obs_remove_main_render_callback(render_preview_source, &context);
|
||||
obs_frontend_remove_event_callback(on_preview_scene_changed, &context);
|
||||
obs_remove_main_render_callback(render_preview_source,
|
||||
&context);
|
||||
obs_frontend_remove_event_callback(on_preview_scene_changed,
|
||||
&context);
|
||||
|
||||
obs_source_release(context.current_source);
|
||||
|
||||
|
@ -197,7 +209,8 @@ void render_preview_source(void *param, uint32_t cx, uint32_t cy)
|
|||
{
|
||||
auto ctx = (struct preview_output *)param;
|
||||
|
||||
if (!ctx->current_source) return;
|
||||
if (!ctx->current_source)
|
||||
return;
|
||||
|
||||
uint32_t width = obs_source_get_base_width(ctx->current_source);
|
||||
uint32_t height = obs_source_get_base_height(ctx->current_source);
|
||||
|
@ -209,7 +222,8 @@ void render_preview_source(void *param, uint32_t cx, uint32_t cy)
|
|||
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);
|
||||
|
@ -220,16 +234,23 @@ void render_preview_source(void *param, uint32_t cx, uint32_t cy)
|
|||
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,
|
||||
uint32_t src_offset =
|
||||
ctx->video_linesize * i;
|
||||
memcpy(output_frame.data[0] +
|
||||
dst_offset,
|
||||
ctx->video_data + src_offset,
|
||||
linesize);
|
||||
}
|
||||
|
@ -254,9 +275,7 @@ void addOutputUI(void)
|
|||
doUI = new DecklinkOutputUI(window);
|
||||
obs_frontend_pop_ui_translation();
|
||||
|
||||
auto cb = []() {
|
||||
doUI->ShowHideDialog();
|
||||
};
|
||||
auto cb = []() { doUI->ShowHideDialog(); };
|
||||
|
||||
action->connect(action, &QAction::triggered, cb);
|
||||
}
|
||||
|
@ -271,7 +290,8 @@ 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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,27 +39,18 @@ void cleanupDisplay()
|
|||
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;
|
||||
unsigned char *data = NULL;
|
||||
Window ewmh_window = 0;
|
||||
|
||||
int status = XGetWindowProperty(
|
||||
display,
|
||||
DefaultRootWindow(display),
|
||||
netSupportingWmCheck,
|
||||
0L,
|
||||
1L,
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
&data);
|
||||
int status = XGetWindowProperty(display, DefaultRootWindow(display),
|
||||
netSupportingWmCheck, 0L, 1L, false,
|
||||
XA_WINDOW, &actualType, &format, &num,
|
||||
&bytes, &data);
|
||||
|
||||
if (status == Success) {
|
||||
if (num > 0) {
|
||||
|
@ -72,19 +63,10 @@ static bool ewmhIsSupported()
|
|||
}
|
||||
|
||||
if (ewmh_window) {
|
||||
status = XGetWindowProperty(
|
||||
display,
|
||||
ewmh_window,
|
||||
netSupportingWmCheck,
|
||||
0L,
|
||||
1L,
|
||||
false,
|
||||
XA_WINDOW,
|
||||
&actualType,
|
||||
&format,
|
||||
&num,
|
||||
&bytes,
|
||||
&data);
|
||||
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;
|
||||
|
@ -116,19 +98,10 @@ static std::vector<Window> getTopLevelWindows()
|
|||
for (int i = 0; i < ScreenCount(disp()); ++i) {
|
||||
Window rootWin = RootWindow(disp(), i);
|
||||
|
||||
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;
|
||||
|
@ -150,8 +123,7 @@ static std::string GetWindowTitle(size_t i)
|
|||
char *name;
|
||||
|
||||
int status = XFetchName(disp(), w, &name);
|
||||
if (status >= Success && name != nullptr)
|
||||
{
|
||||
if (status >= Success && name != nullptr) {
|
||||
std::string str(name);
|
||||
windowTitle = str;
|
||||
}
|
||||
|
@ -186,18 +158,8 @@ void GetCurrentWindowTitle(string &title)
|
|||
|
||||
Window rootWin = RootWindow(disp(), 0);
|
||||
|
||||
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);
|
||||
|
||||
int status = XFetchName(disp(), data[0], &name);
|
||||
|
|
|
@ -69,10 +69,7 @@ struct SwitcherData {
|
|||
}
|
||||
}
|
||||
|
||||
inline ~SwitcherData()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
inline ~SwitcherData() { Stop(); }
|
||||
};
|
||||
|
||||
static SwitcherData *switcher = nullptr;
|
||||
|
@ -84,8 +81,7 @@ static inline QString MakeSwitchName(const QString &scene,
|
|||
}
|
||||
|
||||
SceneSwitcher::SceneSwitcher(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_SceneSwitcher)
|
||||
: QDialog(parent), ui(new Ui_SceneSwitcher)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -121,11 +117,10 @@ 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);
|
||||
QListWidgetItem *item = new QListWidgetItem(text, ui->switches);
|
||||
item->setData(Qt::UserRole, s.window.c_str());
|
||||
}
|
||||
|
||||
|
@ -149,8 +144,7 @@ int SceneSwitcher::FindByData(const QString &window)
|
|||
|
||||
for (int i = 0; i < count; i++) {
|
||||
QListWidgetItem *item = ui->switches->item(i);
|
||||
QString itemWindow =
|
||||
item->data(Qt::UserRole).toString();
|
||||
QString itemWindow = item->data(Qt::UserRole).toString();
|
||||
|
||||
if (itemWindow == window) {
|
||||
idx = i;
|
||||
|
@ -206,15 +200,15 @@ 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"),
|
||||
QMessageBox::warning(
|
||||
this, obs_module_text("InvalidRegex.Title"),
|
||||
obs_module_text("InvalidRegex.Text"));
|
||||
}
|
||||
} else {
|
||||
|
@ -274,8 +268,7 @@ void SceneSwitcher::on_startAtLaunch_toggled(bool value)
|
|||
|
||||
void SceneSwitcher::UpdateNonMatchingScene(const QString &name)
|
||||
{
|
||||
obs_source_t *scene = obs_get_source_by_name(
|
||||
name.toUtf8().constData());
|
||||
obs_source_t *scene = obs_get_source_by_name(name.toUtf8().constData());
|
||||
obs_weak_source_t *ws = obs_source_get_weak_source(scene);
|
||||
|
||||
switcher->nonMatchingScene = ws;
|
||||
|
@ -303,8 +296,7 @@ void SceneSwitcher::on_noMatchSwitch_clicked()
|
|||
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
|
||||
}
|
||||
|
||||
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
|
||||
const QString &text)
|
||||
void SceneSwitcher::on_noMatchSwitchScene_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (loading)
|
||||
return;
|
||||
|
@ -357,8 +349,8 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
for (SceneSwitch &s : switcher->switches) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(
|
||||
s.scene);
|
||||
obs_source_t *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);
|
||||
|
@ -389,8 +381,8 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
} else {
|
||||
switcher->m.lock();
|
||||
|
||||
obs_data_t *obj = obs_data_get_obj(save_data,
|
||||
"auto-scene-switcher");
|
||||
obs_data_t *obj =
|
||||
obs_data_get_obj(save_data, "auto-scene-switcher");
|
||||
obs_data_array_t *array = obs_data_get_array(obj, "switches");
|
||||
size_t count = obs_data_array_count(array);
|
||||
|
||||
|
@ -420,8 +412,7 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||
obs_data_get_string(array_obj, "window_title");
|
||||
|
||||
switcher->switches.emplace_back(
|
||||
GetWeakSourceByName(scene),
|
||||
window);
|
||||
GetWeakSourceByName(scene), window);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
|
@ -482,12 +473,12 @@ void SwitcherData::Thread()
|
|||
scene = s.scene;
|
||||
break;
|
||||
}
|
||||
} catch (const regex_error &) {}
|
||||
} catch (const regex_error &) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!match && switchIfNotMatching &&
|
||||
nonMatchingScene) {
|
||||
if (!match && switchIfNotMatching && nonMatchingScene) {
|
||||
match = true;
|
||||
scene = nonMatchingScene;
|
||||
}
|
||||
|
@ -547,8 +538,7 @@ extern "C" void InitSceneSwitcher()
|
|||
|
||||
switcher = new SwitcherData;
|
||||
|
||||
auto cb = [] ()
|
||||
{
|
||||
auto cb = []() {
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
|
||||
QMainWindow *window =
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "captions-handler.hpp"
|
||||
|
||||
captions_handler::captions_handler(
|
||||
captions_cb callback,
|
||||
captions_handler::captions_handler(captions_cb callback,
|
||||
enum audio_format format,
|
||||
uint32_t sample_rate)
|
||||
: cb(callback)
|
||||
|
@ -10,24 +9,16 @@ captions_handler::captions_handler(
|
|||
throw CAPTIONS_ERROR_GENERIC_FAIL;
|
||||
}
|
||||
|
||||
bool captions_handler::reset_resampler(
|
||||
enum audio_format format,
|
||||
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 dst = {
|
||||
sample_rate,
|
||||
format,
|
||||
SPEAKERS_MONO
|
||||
};
|
||||
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))
|
||||
throw std::string("Failed to create audio resampler");
|
||||
|
@ -46,9 +37,9 @@ 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, audio->frames);
|
||||
success = audio_resampler_resample(resampler, out, &frames, &ts_offset,
|
||||
(const uint8_t *const *)audio->data,
|
||||
audio->frames);
|
||||
if (success)
|
||||
pcm_data(out[0], frames);
|
||||
}
|
||||
|
|
|
@ -9,10 +9,7 @@ class resampler_obj {
|
|||
audio_resampler_t *resampler = nullptr;
|
||||
|
||||
public:
|
||||
inline ~resampler_obj()
|
||||
{
|
||||
audio_resampler_destroy(resampler);
|
||||
}
|
||||
inline ~resampler_obj() { audio_resampler_destroy(resampler); }
|
||||
|
||||
inline bool reset(const resample_info &dst, const resample_info &src)
|
||||
{
|
||||
|
@ -38,10 +35,7 @@ class captions_handler {
|
|||
resampler_obj resampler;
|
||||
|
||||
protected:
|
||||
inline void callback(const std::string &text)
|
||||
{
|
||||
cb(text);
|
||||
}
|
||||
inline void callback(const std::string &text) { cb(text); }
|
||||
|
||||
virtual void pcm_data(const void *data, size_t frames) = 0;
|
||||
|
||||
|
@ -50,9 +44,7 @@ protected:
|
|||
|
||||
public:
|
||||
/* throw std::string for errors shown to users */
|
||||
captions_handler(
|
||||
captions_cb callback,
|
||||
enum audio_format format,
|
||||
captions_handler(captions_cb callback, enum audio_format format,
|
||||
uint32_t sample_rate);
|
||||
virtual ~captions_handler() {}
|
||||
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
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
|
||||
|
||||
CaptionStream::CaptionStream(DWORD samplerate_, mssapi_captions *handler_) :
|
||||
handler(handler_),
|
||||
CaptionStream::CaptionStream(DWORD samplerate_, mssapi_captions *handler_)
|
||||
: handler(handler_),
|
||||
samplerate(samplerate_),
|
||||
event(CreateEvent(nullptr, false, false, nullptr))
|
||||
{
|
||||
|
@ -134,8 +135,7 @@ STDMETHODIMP CaptionStream::Read(void *data, ULONG bytes, ULONG *read_bytes)
|
|||
return hr;
|
||||
}
|
||||
|
||||
STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes,
|
||||
ULONG*)
|
||||
STDMETHODIMP CaptionStream::Write(const void *, ULONG bytes, ULONG *)
|
||||
{
|
||||
debugfunc("data, %lu, written_bytes", bytes);
|
||||
UNUSED_PARAMETER(bytes);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
class CircleBuf {
|
||||
circlebuf buf = {};
|
||||
|
||||
public:
|
||||
inline ~CircleBuf() { circlebuf_free(&buf); }
|
||||
inline operator circlebuf *() { return &buf; }
|
||||
|
@ -54,8 +55,8 @@ 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,
|
||||
|
@ -74,13 +75,13 @@ public:
|
|||
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;
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
#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__)
|
||||
|
||||
mssapi_captions::mssapi_captions(
|
||||
captions_cb callback,
|
||||
const std::string &lang) try
|
||||
: captions_handler(callback, AUDIO_FORMAT_16BIT, 16000)
|
||||
{
|
||||
mssapi_captions::mssapi_captions(captions_cb callback, const std::string &lang)
|
||||
try : captions_handler(callback, AUDIO_FORMAT_16BIT, 16000) {
|
||||
HRESULT hr;
|
||||
|
||||
std::wstring wlang;
|
||||
|
@ -133,8 +130,8 @@ 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;
|
||||
|
||||
|
@ -168,12 +165,7 @@ void mssapi_captions::pcm_data(const void *data, size_t frames)
|
|||
}
|
||||
|
||||
captions_handler_info mssapi_info = {
|
||||
[] () -> std::string
|
||||
{
|
||||
return "Microsoft Speech-to-Text";
|
||||
},
|
||||
[] (captions_cb cb, const std::string &lang) -> captions_handler *
|
||||
{
|
||||
[]() -> 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,8 @@
|
|||
|
||||
#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__)
|
||||
|
@ -74,9 +74,9 @@ 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)
|
||||
{}
|
||||
: name(std::move(li.name)), id(li.id)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static void get_valid_locale_names(vector<locale_info> &names);
|
||||
|
@ -84,16 +84,14 @@ 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);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
auto cb = [this] (obs_source_t *source)
|
||||
{
|
||||
auto cb = [this](obs_source_t *source) {
|
||||
uint32_t caps = obs_source_get_output_flags(source);
|
||||
QString name = obs_source_get_name(source);
|
||||
|
||||
|
@ -111,8 +109,11 @@ 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) {
|
||||
|
@ -245,8 +246,7 @@ void obs_captions::start()
|
|||
|
||||
auto pair = handler_types.find(handler_id);
|
||||
if (pair == handler_types.end()) {
|
||||
warn("Failed to find handler '%s'",
|
||||
handler_id.c_str());
|
||||
warn("Failed to find handler '%s'", handler_id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -271,13 +271,13 @@ 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 =
|
||||
|
@ -285,10 +285,10 @@ void obs_captions::start()
|
|||
|
||||
warn("Failed to create handler: %s", text.c_str());
|
||||
|
||||
QMessageBox::warning(window,
|
||||
QMessageBox::warning(
|
||||
window,
|
||||
obs_module_text("Captions.Error.GenericFail"),
|
||||
text.c_str());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -297,8 +297,8 @@ 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,42 +332,18 @@ static void get_valid_locale_names(vector<locale_info> &locales)
|
|||
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
|
||||
};
|
||||
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;
|
||||
|
||||
|
@ -381,8 +357,7 @@ static void get_valid_locale_names(vector<locale_info> &locales)
|
|||
while (*locale) {
|
||||
id = *locale;
|
||||
|
||||
if (id != def_id &&
|
||||
valid_lang(id) &&
|
||||
if (id != def_id && valid_lang(id) &&
|
||||
get_locale_name(id, locale_name)) {
|
||||
|
||||
dstr_copy(cur.name, locale_name);
|
||||
|
@ -447,8 +422,8 @@ static void save_caption_data(obs_data_t *save_data, bool saving, void*)
|
|||
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());
|
||||
obs_data_release(obj);
|
||||
|
||||
if (enabled)
|
||||
|
@ -463,12 +438,10 @@ extern "C" void InitCaptions()
|
|||
|
||||
captions = new obs_captions;
|
||||
|
||||
auto cb = [] ()
|
||||
{
|
||||
auto cb = []() {
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
|
||||
QWidget *window =
|
||||
(QWidget*)obs_frontend_get_main_window();
|
||||
QWidget *window = (QWidget *)obs_frontend_get_main_window();
|
||||
|
||||
CaptionsDialog dialog(window);
|
||||
dialog.exec();
|
||||
|
|
|
@ -13,8 +13,7 @@ using namespace std;
|
|||
OutputTimer *ot;
|
||||
|
||||
OutputTimer::OutputTimer(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_OutputTimer)
|
||||
: QDialog(parent), ui(new Ui_OutputTimer)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -78,9 +77,7 @@ void OutputTimer::StreamTimerStart()
|
|||
int minutes = ui->streamingTimerMinutes->value();
|
||||
int seconds = ui->streamingTimerSeconds->value();
|
||||
|
||||
int total = (((hours * 3600) +
|
||||
(minutes * 60)) +
|
||||
seconds) * 1000;
|
||||
int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000;
|
||||
|
||||
if (total == 0)
|
||||
total = 1000;
|
||||
|
@ -112,9 +109,7 @@ void OutputTimer::RecordTimerStart()
|
|||
int minutes = ui->recordingTimerMinutes->value();
|
||||
int seconds = ui->recordingTimerSeconds->value();
|
||||
|
||||
int total = (((hours * 3600) +
|
||||
(minutes * 60)) +
|
||||
seconds) * 1000;
|
||||
int total = (((hours * 3600) + (minutes * 60)) + seconds) * 1000;
|
||||
|
||||
if (total == 0)
|
||||
total = 1000;
|
||||
|
@ -248,8 +243,7 @@ static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *)
|
|||
|
||||
obs_data_release(obj);
|
||||
} else {
|
||||
obs_data_t *obj = obs_data_get_obj(save_data,
|
||||
"output-timer");
|
||||
obs_data_t *obj = obs_data_get_obj(save_data, "output-timer");
|
||||
|
||||
if (!obj)
|
||||
obj = obs_data_create();
|
||||
|
@ -277,9 +271,7 @@ static void SaveOutputTimer(obs_data_t *save_data, bool saving, void *)
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" void FreeOutputTimer()
|
||||
{
|
||||
}
|
||||
extern "C" void FreeOutputTimer() {}
|
||||
|
||||
static void OBSEvent(enum obs_frontend_event event, void *)
|
||||
{
|
||||
|
@ -308,10 +300,7 @@ extern "C" void InitOutputTimer()
|
|||
|
||||
ot = new OutputTimer(window);
|
||||
|
||||
auto cb = [] ()
|
||||
{
|
||||
ot->ShowHideDialog();
|
||||
};
|
||||
auto cb = []() { ot->ShowHideDialog(); };
|
||||
|
||||
obs_frontend_pop_ui_translation();
|
||||
|
||||
|
|
|
@ -92,11 +92,10 @@ ScriptLogWindow::ScriptLogWindow() : QWidget(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);
|
||||
connect(closeButton, &QPushButton::clicked, this, &QDialog::hide);
|
||||
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->addWidget(clearButton);
|
||||
|
@ -112,8 +111,8 @@ ScriptLogWindow::ScriptLogWindow() : QWidget(nullptr)
|
|||
resize(600, 400);
|
||||
|
||||
config_t *global_config = obs_frontend_get_global_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);
|
||||
|
@ -121,15 +120,14 @@ ScriptLogWindow::ScriptLogWindow() : QWidget(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_global_config();
|
||||
config_set_string(global_config,
|
||||
"ScriptLogWindow", "geometry",
|
||||
config_set_string(global_config, "ScriptLogWindow", "geometry",
|
||||
saveGeometry().toBase64().constData());
|
||||
}
|
||||
|
||||
|
@ -180,17 +178,15 @@ void ScriptLogWindow::Clear()
|
|||
|
||||
/* ----------------------------------------------------------------- */
|
||||
|
||||
ScriptsTool::ScriptsTool()
|
||||
: QWidget (nullptr),
|
||||
ui (new Ui_ScriptsTool)
|
||||
ScriptsTool::ScriptsTool() : QWidget(nullptr), ui(new Ui_ScriptsTool)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
RefreshLists();
|
||||
|
||||
#if PYTHON_UI
|
||||
config_t *config = obs_frontend_get_global_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));
|
||||
#else
|
||||
|
@ -217,8 +213,8 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -323,7 +319,8 @@ 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);
|
||||
|
||||
|
@ -343,8 +340,10 @@ 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();
|
||||
}
|
||||
|
||||
|
@ -352,8 +351,10 @@ 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());
|
||||
}
|
||||
|
@ -368,9 +369,7 @@ void ScriptsTool::on_pythonPathBrowse_clicked()
|
|||
{
|
||||
QString curPath = ui->pythonPath->text();
|
||||
QString newPath = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
ui->pythonPathLabel->text(),
|
||||
curPath);
|
||||
this, ui->pythonPathLabel->text(), curPath);
|
||||
|
||||
if (newPath.isEmpty())
|
||||
return;
|
||||
|
@ -412,8 +411,8 @@ void ScriptsTool::on_scripts_currentRowChanged(int row)
|
|||
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);
|
||||
|
@ -425,7 +424,8 @@ void ScriptsTool::on_scripts_currentRowChanged(int row)
|
|||
OBSData settings = obs_script_get_settings(script);
|
||||
obs_data_release(settings);
|
||||
|
||||
propertiesView = new OBSPropertiesView(settings, script,
|
||||
propertiesView = new OBSPropertiesView(
|
||||
settings, script,
|
||||
(PropertiesReloadCallback)obs_script_get_properties,
|
||||
(PropertiesUpdateCallback)obs_script_update);
|
||||
ui->propertiesLayout->addWidget(propertiesView);
|
||||
|
@ -457,8 +457,7 @@ static void obs_event(enum obs_frontend_event event, void *)
|
|||
|
||||
static void load_script_data(obs_data_t *load_data, bool, void *)
|
||||
{
|
||||
obs_data_array_t *array = obs_data_get_array(load_data,
|
||||
"scripts-tool");
|
||||
obs_data_array_t *array = obs_data_get_array(load_data, "scripts-tool");
|
||||
|
||||
delete scriptData;
|
||||
scriptData = new ScriptData;
|
||||
|
@ -515,15 +514,13 @@ static void script_log(void *, obs_script_t *script, int log_level,
|
|||
|
||||
if (script) {
|
||||
qmsg = QStringLiteral("[%1] %2").arg(
|
||||
obs_script_get_file(script),
|
||||
message);
|
||||
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));
|
||||
Q_ARG(int, log_level), Q_ARG(QString, qmsg));
|
||||
}
|
||||
|
||||
extern "C" void InitScripts()
|
||||
|
@ -538,8 +535,8 @@ extern "C" void InitScripts()
|
|||
|
||||
#if PYTHON_UI
|
||||
config_t *config = obs_frontend_get_global_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);
|
||||
|
||||
if (!obs_scripting_python_loaded() && python_path && *python_path)
|
||||
obs_scripting_load_python(python_path);
|
||||
|
@ -547,8 +544,7 @@ extern "C" void InitScripts()
|
|||
|
||||
scriptData = new ScriptData;
|
||||
|
||||
auto cb = [] ()
|
||||
{
|
||||
auto cb = []() {
|
||||
obs_frontend_push_ui_translation(obs_module_get_string);
|
||||
|
||||
if (!scriptsWindow) {
|
||||
|
|
|
@ -8,8 +8,7 @@ class HScrollArea : public QScrollArea {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
inline HScrollArea(QWidget *parent = nullptr)
|
||||
: QScrollArea(parent)
|
||||
inline HScrollArea(QWidget *parent = nullptr) : QScrollArea(parent)
|
||||
{
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
|
|
@ -105,32 +105,34 @@ void OBSHotkeyEdit::mousePressEvent(QMouseEvent *event)
|
|||
new_key.key = OBS_KEY_MOUSE3;
|
||||
break;
|
||||
|
||||
#define MAP_BUTTON(i, j) case Qt::ExtraButton ## i: \
|
||||
new_key.key = OBS_KEY_MOUSE ## j; break;
|
||||
MAP_BUTTON( 1, 4);
|
||||
MAP_BUTTON( 2, 5);
|
||||
MAP_BUTTON( 3, 6);
|
||||
MAP_BUTTON( 4, 7);
|
||||
MAP_BUTTON( 5, 8);
|
||||
MAP_BUTTON( 6, 9);
|
||||
MAP_BUTTON( 7, 10);
|
||||
MAP_BUTTON( 8, 11);
|
||||
MAP_BUTTON( 9, 12);
|
||||
MAP_BUTTON(10, 13);
|
||||
MAP_BUTTON(11, 14);
|
||||
MAP_BUTTON(12, 15);
|
||||
MAP_BUTTON(13, 16);
|
||||
MAP_BUTTON(14, 17);
|
||||
MAP_BUTTON(15, 18);
|
||||
MAP_BUTTON(16, 19);
|
||||
MAP_BUTTON(17, 20);
|
||||
MAP_BUTTON(18, 21);
|
||||
MAP_BUTTON(19, 22);
|
||||
MAP_BUTTON(20, 23);
|
||||
MAP_BUTTON(21, 24);
|
||||
MAP_BUTTON(22, 25);
|
||||
MAP_BUTTON(23, 26);
|
||||
MAP_BUTTON(24, 27);
|
||||
#define MAP_BUTTON(i, j) \
|
||||
case Qt::ExtraButton##i: \
|
||||
new_key.key = OBS_KEY_MOUSE##j; \
|
||||
break;
|
||||
MAP_BUTTON(1, 4)
|
||||
MAP_BUTTON(2, 5)
|
||||
MAP_BUTTON(3, 6)
|
||||
MAP_BUTTON(4, 7)
|
||||
MAP_BUTTON(5, 8)
|
||||
MAP_BUTTON(6, 9)
|
||||
MAP_BUTTON(7, 10)
|
||||
MAP_BUTTON(8, 11)
|
||||
MAP_BUTTON(9, 12)
|
||||
MAP_BUTTON(10, 13)
|
||||
MAP_BUTTON(11, 14)
|
||||
MAP_BUTTON(12, 15)
|
||||
MAP_BUTTON(13, 16)
|
||||
MAP_BUTTON(14, 17)
|
||||
MAP_BUTTON(15, 18)
|
||||
MAP_BUTTON(16, 19)
|
||||
MAP_BUTTON(17, 20)
|
||||
MAP_BUTTON(18, 21)
|
||||
MAP_BUTTON(19, 22)
|
||||
MAP_BUTTON(20, 23)
|
||||
MAP_BUTTON(21, 24)
|
||||
MAP_BUTTON(22, 25)
|
||||
MAP_BUTTON(23, 26)
|
||||
MAP_BUTTON(24, 27)
|
||||
#undef MAP_BUTTON
|
||||
}
|
||||
|
||||
|
@ -183,13 +185,13 @@ void OBSHotkeyEdit::ClearKey()
|
|||
|
||||
void OBSHotkeyEdit::InitSignalHandler()
|
||||
{
|
||||
layoutChanged = {obs_get_signal_handler(),
|
||||
"hotkey_layout_change",
|
||||
[](void *this_, calldata_t*)
|
||||
{
|
||||
layoutChanged = {
|
||||
obs_get_signal_handler(), "hotkey_layout_change",
|
||||
[](void *this_, calldata_t *) {
|
||||
auto edit = static_cast<OBSHotkeyEdit *>(this_);
|
||||
QMetaObject::invokeMethod(edit, "ReloadKeyLayout");
|
||||
}, this};
|
||||
},
|
||||
this};
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::ReloadKeyLayout()
|
||||
|
@ -210,10 +212,8 @@ void OBSHotkeyWidget::SetKeyCombinations(
|
|||
bool OBSHotkeyWidget::Changed() const
|
||||
{
|
||||
return changed ||
|
||||
std::any_of(begin(edits), end(edits), [](OBSHotkeyEdit *edit)
|
||||
{
|
||||
return edit->changed;
|
||||
});
|
||||
std::any_of(begin(edits), end(edits),
|
||||
[](OBSHotkeyEdit *edit) { return edit->changed; });
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::Apply()
|
||||
|
@ -249,21 +249,19 @@ void OBSHotkeyWidget::Save(std::vector<obs_key_combination_t> &combinations)
|
|||
GetCombinations(combinations);
|
||||
Apply();
|
||||
|
||||
auto AtomicUpdate = [&]()
|
||||
{
|
||||
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)
|
||||
|
@ -285,10 +283,11 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
|||
clear->setFlat(true);
|
||||
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));
|
||||
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);
|
||||
});
|
||||
|
||||
|
@ -303,25 +302,18 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
|||
remove->setFixedSize(24, 24);
|
||||
remove->setFlat(true);
|
||||
|
||||
auto CurrentIndex = [&, remove]
|
||||
{
|
||||
auto res = std::find(begin(removeButtons),
|
||||
end(removeButtons),
|
||||
auto CurrentIndex = [&, remove] {
|
||||
auto res = std::find(begin(removeButtons), end(removeButtons),
|
||||
remove);
|
||||
return std::distance(begin(removeButtons), res);
|
||||
};
|
||||
|
||||
QObject::connect(add, &QPushButton::clicked,
|
||||
[&, CurrentIndex]
|
||||
{
|
||||
QObject::connect(add, &QPushButton::clicked, [&, CurrentIndex] {
|
||||
AddEdit({0, OBS_KEY_NONE}, CurrentIndex() + 1);
|
||||
});
|
||||
|
||||
QObject::connect(remove, &QPushButton::clicked,
|
||||
[&, CurrentIndex]
|
||||
{
|
||||
RemoveEdit(CurrentIndex());
|
||||
});
|
||||
[&, CurrentIndex] { RemoveEdit(CurrentIndex()); });
|
||||
|
||||
QHBoxLayout *subLayout = new QHBoxLayout;
|
||||
subLayout->setContentsMargins(0, 4, 0, 0);
|
||||
|
@ -346,16 +338,13 @@ 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();
|
||||
});
|
||||
[&](obs_key_combination) { emit KeyChanged(); });
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::RemoveEdit(size_t idx, bool signal)
|
||||
|
@ -393,25 +382,26 @@ void OBSHotkeyWidget::BindingsChanged(void *data, calldata_t *param)
|
|||
|
||||
void OBSHotkeyWidget::HandleChangedBindings(obs_hotkey_id id_)
|
||||
{
|
||||
if (ignoreChangedBindings || id != id_) return;
|
||||
if (ignoreChangedBindings || id != id_)
|
||||
return;
|
||||
|
||||
std::vector<obs_key_combination_t> bindings;
|
||||
auto LoadBindings = [&](obs_hotkey_binding_t *binding)
|
||||
{
|
||||
if (obs_hotkey_binding_get_hotkey_id(binding) != id) return;
|
||||
auto LoadBindings = [&](obs_hotkey_binding_t *binding) {
|
||||
if (obs_hotkey_binding_get_hotkey_id(binding) != id)
|
||||
return;
|
||||
|
||||
auto get_combo = obs_hotkey_binding_get_key_combination;
|
||||
bindings.push_back(get_combo(binding));
|
||||
};
|
||||
using LoadBindings_t = decltype(&LoadBindings);
|
||||
|
||||
obs_enum_hotkey_bindings([](void *data,
|
||||
size_t, obs_hotkey_binding_t *binding)
|
||||
{
|
||||
obs_enum_hotkey_bindings(
|
||||
[](void *data, size_t, obs_hotkey_binding_t *binding) {
|
||||
auto LoadBindings = *static_cast<LoadBindings_t>(data);
|
||||
LoadBindings(binding);
|
||||
return true;
|
||||
}, static_cast<void*>(&LoadBindings));
|
||||
},
|
||||
static_cast<void *>(&LoadBindings));
|
||||
|
||||
while (edits.size() > 0)
|
||||
RemoveEdit(edits.size() - 1, false);
|
||||
|
|
|
@ -45,10 +45,8 @@ class OBSHotkeyEdit : public QLineEdit {
|
|||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
OBSHotkeyEdit(obs_key_combination_t original,
|
||||
QWidget *parent=nullptr)
|
||||
: QLineEdit(parent),
|
||||
original(original)
|
||||
OBSHotkeyEdit(obs_key_combination_t original, QWidget *parent = nullptr)
|
||||
: QLineEdit(parent), original(original)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// disable the input cursor on OSX, focus should be clear
|
||||
|
@ -64,6 +62,7 @@ public:
|
|||
obs_key_combination_t original;
|
||||
obs_key_combination_t key;
|
||||
bool changed = false;
|
||||
|
||||
protected:
|
||||
OBSSignal layoutChanged;
|
||||
|
||||
|
@ -99,8 +98,7 @@ public:
|
|||
name(name),
|
||||
bindingsChanged(obs_get_signal_handler(),
|
||||
"hotkey_bindings_changed",
|
||||
&OBSHotkeyWidget::BindingsChanged,
|
||||
this)
|
||||
&OBSHotkeyWidget::BindingsChanged, this)
|
||||
{
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->setSpacing(0);
|
||||
|
|
5
UI/obf.c
5
UI/obf.c
|
@ -13,9 +13,8 @@ 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;
|
||||
|
||||
|
|
420
UI/obs-app.cpp
420
UI/obs-app.cpp
|
@ -91,10 +91,8 @@ extern "C" __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
|||
|
||||
QObject *CreateShortcutFilter()
|
||||
{
|
||||
return new OBSEventFilter([](QObject *obj, QEvent *event)
|
||||
{
|
||||
auto mouse_event = [](QMouseEvent &event)
|
||||
{
|
||||
return new OBSEventFilter([](QObject *obj, QEvent *event) {
|
||||
auto mouse_event = [](QMouseEvent &event) {
|
||||
obs_key_combination_t hotkey = {0, OBS_KEY_NONE};
|
||||
bool pressed = event.type() == QEvent::MouseButtonPress;
|
||||
|
||||
|
@ -110,8 +108,10 @@ QObject *CreateShortcutFilter()
|
|||
hotkey.key = OBS_KEY_MOUSE3;
|
||||
break;
|
||||
|
||||
#define MAP_BUTTON(i, j) case Qt::ExtraButton ## i: \
|
||||
hotkey.key = OBS_KEY_MOUSE ## j; break;
|
||||
#define MAP_BUTTON(i, j) \
|
||||
case Qt::ExtraButton##i: \
|
||||
hotkey.key = OBS_KEY_MOUSE##j; \
|
||||
break;
|
||||
MAP_BUTTON(1, 4);
|
||||
MAP_BUTTON(2, 5);
|
||||
MAP_BUTTON(3, 6);
|
||||
|
@ -146,8 +146,7 @@ QObject *CreateShortcutFilter()
|
|||
return true;
|
||||
};
|
||||
|
||||
auto key_event = [&](QKeyEvent *event)
|
||||
{
|
||||
auto key_event = [&](QKeyEvent *event) {
|
||||
QDialog *dialog = qobject_cast<QDialog *>(obj);
|
||||
|
||||
obs_key_combination_t hotkey = {0, OBS_KEY_NONE};
|
||||
|
@ -217,10 +216,8 @@ string CurrentTimeString()
|
|||
size_t written = strftime(buf, sizeof(buf), "%X", &tstruct);
|
||||
if (ratio_less<system_clock::period, seconds::period>::value &&
|
||||
written && (sizeof(buf) - written) > 5) {
|
||||
auto tp_secs =
|
||||
time_point_cast<seconds>(tp);
|
||||
auto millis =
|
||||
duration_cast<milliseconds>(tp - tp_secs).count();
|
||||
auto tp_secs = time_point_cast<seconds>(tp);
|
||||
auto millis = duration_cast<milliseconds>(tp - tp_secs).count();
|
||||
|
||||
snprintf(buf + written, sizeof(buf) - written, ".%03u",
|
||||
static_cast<unsigned>(millis));
|
||||
|
@ -307,10 +304,10 @@ static inline bool too_many_repeated_entries(fstream &logFile, const char *msg,
|
|||
}
|
||||
|
||||
if (rep_count > MAX_REPEATED_LINES) {
|
||||
logFile << CurrentTimeString() <<
|
||||
": Last log entry repeated for " <<
|
||||
to_string(rep_count - MAX_REPEATED_LINES) <<
|
||||
" more lines" << endl;
|
||||
logFile << CurrentTimeString()
|
||||
<< ": Last log entry repeated for "
|
||||
<< to_string(rep_count - MAX_REPEATED_LINES)
|
||||
<< " more lines" << endl;
|
||||
}
|
||||
|
||||
last_msg_ptr = msg;
|
||||
|
@ -393,36 +390,36 @@ bool OBSApp::InitGlobalConfigDefaults()
|
|||
"PreviewProgramMode", false);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SceneDuplicationMode", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SwapScenesMode", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SnappingEnabled", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"ScreenSnapping", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SourceSnapping", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"CenterSnapping", false);
|
||||
config_set_default_double(globalConfig, "BasicWindow",
|
||||
"SnapDistance", 10.0);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "SwapScenesMode",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "SnappingEnabled",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "ScreenSnapping",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "SourceSnapping",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "CenterSnapping",
|
||||
false);
|
||||
config_set_default_double(globalConfig, "BasicWindow", "SnapDistance",
|
||||
10.0);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"RecordWhenStreaming", false);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"KeepRecordingWhenStreamStops", false);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SysTrayEnabled", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "SysTrayEnabled",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SysTrayWhenStarted", false);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"SaveProjectors", false);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"ShowTransitions", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "SaveProjectors",
|
||||
false);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "ShowTransitions",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"ShowListboxToolbars", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"ShowStatusBar", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow",
|
||||
"StudioModeLabels", true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "ShowStatusBar",
|
||||
true);
|
||||
config_set_default_bool(globalConfig, "BasicWindow", "StudioModeLabels",
|
||||
true);
|
||||
|
||||
if (!config_get_bool(globalConfig, "General", "Pre21Defaults")) {
|
||||
config_set_default_string(globalConfig, "General",
|
||||
|
@ -550,8 +547,8 @@ static string GetProfileDirFromName(const char *name)
|
|||
if (config.Open(path, CONFIG_OPEN_EXISTING) != 0)
|
||||
continue;
|
||||
|
||||
const char *curName = config_get_string(config, "General",
|
||||
"Name");
|
||||
const char *curName =
|
||||
config_get_string(config, "General", "Name");
|
||||
if (astrcmpi(curName, name) == 0) {
|
||||
outputPath = ent.path;
|
||||
break;
|
||||
|
@ -621,28 +618,32 @@ bool OBSApp::UpdatePre22MultiviewLayout(const char *layout)
|
|||
return false;
|
||||
|
||||
if (astrcmpi(layout, "horizontaltop") == 0) {
|
||||
config_set_int(globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
config_set_int(
|
||||
globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
static_cast<int>(
|
||||
MultiviewLayout::HORIZONTAL_TOP_8_SCENES));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (astrcmpi(layout, "horizontalbottom") == 0) {
|
||||
config_set_int(globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
config_set_int(
|
||||
globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
static_cast<int>(
|
||||
MultiviewLayout::HORIZONTAL_BOTTOM_8_SCENES));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (astrcmpi(layout, "verticalleft") == 0) {
|
||||
config_set_int(globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
config_set_int(
|
||||
globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
static_cast<int>(
|
||||
MultiviewLayout::VERTICAL_LEFT_8_SCENES));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (astrcmpi(layout, "verticalright") == 0) {
|
||||
config_set_int(globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
config_set_int(
|
||||
globalConfig, "BasicWindow", "MultiviewLayout",
|
||||
static_cast<int>(
|
||||
MultiviewLayout::VERTICAL_RIGHT_8_SCENES));
|
||||
return true;
|
||||
|
@ -656,8 +657,7 @@ bool OBSApp::InitGlobalConfig()
|
|||
char path[512];
|
||||
bool changed = false;
|
||||
|
||||
int len = GetConfigPath(path, sizeof(path),
|
||||
"obs-studio/global.ini");
|
||||
int len = GetConfigPath(path, sizeof(path), "obs-studio/global.ini");
|
||||
if (len <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -672,19 +672,18 @@ bool OBSApp::InitGlobalConfig()
|
|||
string path = GetSceneCollectionFileFromName(
|
||||
opt_starting_collection.c_str());
|
||||
if (!path.empty()) {
|
||||
config_set_string(globalConfig,
|
||||
"Basic", "SceneCollection",
|
||||
config_set_string(globalConfig, "Basic",
|
||||
"SceneCollection",
|
||||
opt_starting_collection.c_str());
|
||||
config_set_string(globalConfig,
|
||||
"Basic", "SceneCollectionFile",
|
||||
path.c_str());
|
||||
config_set_string(globalConfig, "Basic",
|
||||
"SceneCollectionFile", path.c_str());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!opt_starting_profile.empty()) {
|
||||
string path = GetProfileDirFromName(
|
||||
opt_starting_profile.c_str());
|
||||
string path =
|
||||
GetProfileDirFromName(opt_starting_profile.c_str());
|
||||
if (!path.empty()) {
|
||||
config_set_string(globalConfig, "Basic", "Profile",
|
||||
opt_starting_profile.c_str());
|
||||
|
@ -695,10 +694,11 @@ bool OBSApp::InitGlobalConfig()
|
|||
}
|
||||
|
||||
if (!config_has_user_value(globalConfig, "General", "Pre19Defaults")) {
|
||||
uint32_t lastVersion = config_get_int(globalConfig, "General",
|
||||
"LastVersion");
|
||||
uint32_t lastVersion =
|
||||
config_get_int(globalConfig, "General", "LastVersion");
|
||||
bool useOldDefaults = lastVersion &&
|
||||
lastVersion < MAKE_SEMANTIC_VERSION(19, 0, 0);
|
||||
lastVersion <
|
||||
MAKE_SEMANTIC_VERSION(19, 0, 0);
|
||||
|
||||
config_set_bool(globalConfig, "General", "Pre19Defaults",
|
||||
useOldDefaults);
|
||||
|
@ -706,10 +706,11 @@ bool OBSApp::InitGlobalConfig()
|
|||
}
|
||||
|
||||
if (!config_has_user_value(globalConfig, "General", "Pre21Defaults")) {
|
||||
uint32_t lastVersion = config_get_int(globalConfig, "General",
|
||||
"LastVersion");
|
||||
uint32_t lastVersion =
|
||||
config_get_int(globalConfig, "General", "LastVersion");
|
||||
bool useOldDefaults = lastVersion &&
|
||||
lastVersion < MAKE_SEMANTIC_VERSION(21, 0, 0);
|
||||
lastVersion <
|
||||
MAKE_SEMANTIC_VERSION(21, 0, 0);
|
||||
|
||||
config_set_bool(globalConfig, "General", "Pre21Defaults",
|
||||
useOldDefaults);
|
||||
|
@ -717,10 +718,11 @@ bool OBSApp::InitGlobalConfig()
|
|||
}
|
||||
|
||||
if (!config_has_user_value(globalConfig, "General", "Pre23Defaults")) {
|
||||
uint32_t lastVersion = config_get_int(globalConfig, "General",
|
||||
"LastVersion");
|
||||
uint32_t lastVersion =
|
||||
config_get_int(globalConfig, "General", "LastVersion");
|
||||
bool useOldDefaults = lastVersion &&
|
||||
lastVersion < MAKE_SEMANTIC_VERSION(23, 0, 0);
|
||||
lastVersion <
|
||||
MAKE_SEMANTIC_VERSION(23, 0, 0);
|
||||
|
||||
config_set_bool(globalConfig, "General", "Pre23Defaults",
|
||||
useOldDefaults);
|
||||
|
@ -729,8 +731,8 @@ bool OBSApp::InitGlobalConfig()
|
|||
|
||||
if (config_has_user_value(globalConfig, "BasicWindow",
|
||||
"MultiviewLayout")) {
|
||||
const char *layout = config_get_string(globalConfig,
|
||||
"BasicWindow", "MultiviewLayout");
|
||||
const char *layout = config_get_string(
|
||||
globalConfig, "BasicWindow", "MultiviewLayout");
|
||||
changed |= UpdatePre22MultiviewLayout(layout);
|
||||
}
|
||||
|
||||
|
@ -743,8 +745,8 @@ bool OBSApp::InitGlobalConfig()
|
|||
bool OBSApp::InitLocale()
|
||||
{
|
||||
ProfileScope("OBSApp::InitLocale");
|
||||
const char *lang = config_get_string(globalConfig, "General",
|
||||
"Language");
|
||||
const char *lang =
|
||||
config_get_string(globalConfig, "General", "Language");
|
||||
|
||||
locale = lang;
|
||||
|
||||
|
@ -761,8 +763,8 @@ bool OBSApp::InitLocale()
|
|||
return false;
|
||||
}
|
||||
|
||||
bool userLocale = config_has_user_value(globalConfig, "General",
|
||||
"Language");
|
||||
bool userLocale =
|
||||
config_has_user_value(globalConfig, "General", "Language");
|
||||
bool defaultLang = astrcmpi(lang, DEFAULT_LANG) == 0;
|
||||
|
||||
if (userLocale && defaultLang)
|
||||
|
@ -808,15 +810,14 @@ bool OBSApp::InitLocale()
|
|||
return true;
|
||||
}
|
||||
|
||||
void OBSApp::AddExtraThemeColor(QPalette &pal, int group,
|
||||
const char *name, uint32_t color)
|
||||
void OBSApp::AddExtraThemeColor(QPalette &pal, int group, const char *name,
|
||||
uint32_t color)
|
||||
{
|
||||
std::function<void(QPalette::ColorGroup)> func;
|
||||
|
||||
#define DEF_PALETTE_ASSIGN(name) \
|
||||
do { \
|
||||
func = [&] (QPalette::ColorGroup group) \
|
||||
{ \
|
||||
func = [&](QPalette::ColorGroup group) { \
|
||||
pal.setColor(group, QPalette::name, \
|
||||
QColor::fromRgb(color)); \
|
||||
}; \
|
||||
|
@ -900,16 +901,19 @@ void OBSApp::ParseExtraThemeData(const char *path)
|
|||
cf_parser_parse(cfp, data, path);
|
||||
|
||||
while (cf_go_to_token(cfp, "OBSTheme", nullptr)) {
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
int group = -1;
|
||||
|
||||
if (cf_token_is(cfp, ":")) {
|
||||
ret = cf_next_token_should_be(cfp, ":", nullptr,
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
if (cf_token_is(cfp, "disabled")) {
|
||||
group = QPalette::Disabled;
|
||||
|
@ -921,13 +925,16 @@ void OBSApp::ParseExtraThemeData(const char *path)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "{")) continue;
|
||||
if (!cf_token_is(cfp, "{"))
|
||||
continue;
|
||||
|
||||
for (;;) {
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_NAME, "name",
|
||||
nullptr);
|
||||
|
@ -937,11 +944,12 @@ void OBSApp::ParseExtraThemeData(const char *path)
|
|||
DStr name;
|
||||
dstr_copy_strref(name, &cfp->cur_token->str);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ":", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
ret = cf_next_token_should_be(cfp, ":", ";", nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
const char *array;
|
||||
uint32_t color = 0;
|
||||
|
@ -953,24 +961,30 @@ void OBSApp::ParseExtraThemeData(const char *path)
|
|||
} else if (cf_token_is(cfp, "rgb")) {
|
||||
ret = cf_next_token_should_be(cfp, "(", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10) << 16;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ",", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10) << 8;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ",", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (!cf_next_token(cfp)) return;
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
if (!cf_next_token(cfp))
|
||||
return;
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10);
|
||||
|
@ -982,13 +996,15 @@ void OBSApp::ParseExtraThemeData(const char *path)
|
|||
color = 0;
|
||||
}
|
||||
|
||||
if (!cf_go_to_token(cfp, ";", nullptr)) return;
|
||||
if (!cf_go_to_token(cfp, ";", nullptr))
|
||||
return;
|
||||
|
||||
AddExtraThemeColor(pal, group, name->array, color);
|
||||
}
|
||||
|
||||
ret = cf_token_should_be(cfp, "}", "}", nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (ret != PARSE_SUCCESS)
|
||||
continue;
|
||||
}
|
||||
|
||||
setPalette(pal);
|
||||
|
@ -1003,8 +1019,7 @@ bool OBSApp::SetTheme(std::string name, std::string path)
|
|||
char userDir[512];
|
||||
name = "themes/" + name + ".qss";
|
||||
string temp = "obs-studio/" + name;
|
||||
int ret = GetConfigPath(userDir, sizeof(userDir),
|
||||
temp.c_str());
|
||||
int ret = GetConfigPath(userDir, sizeof(userDir), temp.c_str());
|
||||
|
||||
if (ret > 0 && QFile::exists(userDir)) {
|
||||
path = string(userDir);
|
||||
|
@ -1027,13 +1042,12 @@ bool OBSApp::InitTheme()
|
|||
{
|
||||
defaultPalette = palette();
|
||||
|
||||
const char *themeName = config_get_string(globalConfig, "General",
|
||||
"CurrentTheme");
|
||||
const char *themeName =
|
||||
config_get_string(globalConfig, "General", "CurrentTheme");
|
||||
|
||||
if (!themeName) {
|
||||
/* Use deprecated "Theme" value if available */
|
||||
themeName = config_get_string(globalConfig,
|
||||
"General", "Theme");
|
||||
themeName = config_get_string(globalConfig, "General", "Theme");
|
||||
if (!themeName)
|
||||
themeName = DEFAULT_THEME;
|
||||
if (!themeName)
|
||||
|
@ -1047,8 +1061,7 @@ bool OBSApp::InitTheme()
|
|||
}
|
||||
|
||||
OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
|
||||
: QApplication(argc, argv),
|
||||
profilerNameStore(store)
|
||||
: QApplication(argc, argv), profilerNameStore(store)
|
||||
{
|
||||
sleepInhibitor = os_inhibit_sleep_create("OBS Video/audio");
|
||||
|
||||
|
@ -1058,17 +1071,17 @@ OBSApp::OBSApp(int &argc, char **argv, profiler_name_store_t *store)
|
|||
OBSApp::~OBSApp()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
bool disableAudioDucking = config_get_bool(globalConfig, "Audio",
|
||||
"DisableAudioDucking");
|
||||
bool disableAudioDucking =
|
||||
config_get_bool(globalConfig, "Audio", "DisableAudioDucking");
|
||||
if (disableAudioDucking)
|
||||
DisableAudioDucking(false);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
bool vsyncDiabled = config_get_bool(globalConfig, "Video",
|
||||
"DisableOSXVSync");
|
||||
bool resetVSync = config_get_bool(globalConfig, "Video",
|
||||
"ResetOSXVSyncOnExit");
|
||||
bool vsyncDiabled =
|
||||
config_get_bool(globalConfig, "Video", "DisableOSXVSync");
|
||||
bool resetVSync =
|
||||
config_get_bool(globalConfig, "Video", "ResetOSXVSyncOnExit");
|
||||
if (vsyncDiabled && resetVSync)
|
||||
EnableOSXVSync(true);
|
||||
#endif
|
||||
|
@ -1190,15 +1203,15 @@ void OBSApp::AppInit()
|
|||
}
|
||||
|
||||
if (!config_has_user_value(globalConfig, "Basic", "SceneCollection")) {
|
||||
config_set_string(globalConfig, "Basic",
|
||||
"SceneCollection", Str("Untitled"));
|
||||
config_set_string(globalConfig, "Basic",
|
||||
"SceneCollectionFile", Str("Untitled"));
|
||||
config_set_string(globalConfig, "Basic", "SceneCollection",
|
||||
Str("Untitled"));
|
||||
config_set_string(globalConfig, "Basic", "SceneCollectionFile",
|
||||
Str("Untitled"));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
bool disableAudioDucking = config_get_bool(globalConfig, "Audio",
|
||||
"DisableAudioDucking");
|
||||
bool disableAudioDucking =
|
||||
config_get_bool(globalConfig, "Audio", "DisableAudioDucking");
|
||||
if (disableAudioDucking)
|
||||
DisableAudioDucking(true);
|
||||
#endif
|
||||
|
@ -1220,11 +1233,10 @@ void OBSApp::AppInit()
|
|||
|
||||
const char *OBSApp::GetRenderModule() const
|
||||
{
|
||||
const char *renderer = config_get_string(globalConfig, "Video",
|
||||
"Renderer");
|
||||
const char *renderer =
|
||||
config_get_string(globalConfig, "Video", "Renderer");
|
||||
|
||||
return (astrcmpi(renderer, "Direct3D 11") == 0) ?
|
||||
DL_D3D11 : DL_OPENGL;
|
||||
return (astrcmpi(renderer, "Direct3D 11") == 0) ? DL_D3D11 : DL_OPENGL;
|
||||
}
|
||||
|
||||
static bool StartupOBS(const char *locale, profiler_name_store_t *store)
|
||||
|
@ -1239,8 +1251,7 @@ static bool StartupOBS(const char *locale, profiler_name_store_t *store)
|
|||
|
||||
inline void OBSApp::ResetHotkeyState(bool inFocus)
|
||||
{
|
||||
obs_hotkey_enable_background_press(
|
||||
inFocus || enableHotkeysInFocus);
|
||||
obs_hotkey_enable_background_press(inFocus || enableHotkeysInFocus);
|
||||
}
|
||||
|
||||
void OBSApp::EnableInFocusHotkeys(bool enable)
|
||||
|
@ -1268,22 +1279,22 @@ bool OBSApp::OBSInit()
|
|||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
bool browserHWAccel = config_get_bool(globalConfig, "General",
|
||||
"BrowserHWAccel");
|
||||
bool browserHWAccel =
|
||||
config_get_bool(globalConfig, "General", "BrowserHWAccel");
|
||||
|
||||
obs_data_t *settings = obs_data_create();
|
||||
obs_data_set_bool(settings, "BrowserHWAccel", browserHWAccel);
|
||||
obs_apply_private_data(settings);
|
||||
obs_data_release(settings);
|
||||
|
||||
blog(LOG_INFO, "Current Date/Time: %s", CurrentDateTimeString().c_str());
|
||||
blog(LOG_INFO, "Current Date/Time: %s",
|
||||
CurrentDateTimeString().c_str());
|
||||
|
||||
blog(LOG_INFO, "Browser Hardware Acceleration: %s",
|
||||
browserHWAccel ? "true" : "false");
|
||||
#endif
|
||||
|
||||
blog(LOG_INFO, "Portable mode: %s",
|
||||
portable_mode ? "true" : "false");
|
||||
blog(LOG_INFO, "Portable mode: %s", portable_mode ? "true" : "false");
|
||||
|
||||
setQuitOnLastWindowClosed(false);
|
||||
|
||||
|
@ -1295,10 +1306,8 @@ bool OBSApp::OBSInit()
|
|||
mainWindow->OBSInit();
|
||||
|
||||
connect(this, &QGuiApplication::applicationStateChanged,
|
||||
[this](Qt::ApplicationState state)
|
||||
{
|
||||
ResetHotkeyState(
|
||||
state != Qt::ApplicationActive);
|
||||
[this](Qt::ApplicationState state) {
|
||||
ResetHotkeyState(state != Qt::ApplicationActive);
|
||||
});
|
||||
ResetHotkeyState(applicationState() != Qt::ApplicationActive);
|
||||
return true;
|
||||
|
@ -1311,9 +1320,8 @@ string OBSApp::GetVersionString() const
|
|||
#ifdef HAVE_OBSCONFIG_H
|
||||
ver << OBS_VERSION;
|
||||
#else
|
||||
ver << LIBOBS_API_MAJOR_VER << "." <<
|
||||
LIBOBS_API_MINOR_VER << "." <<
|
||||
LIBOBS_API_PATCH_VER;
|
||||
ver << LIBOBS_API_MAJOR_VER << "." << LIBOBS_API_MINOR_VER << "."
|
||||
<< LIBOBS_API_PATCH_VER;
|
||||
|
||||
#endif
|
||||
ver << " (";
|
||||
|
@ -1432,19 +1440,30 @@ static uint64_t convert_log_name(bool has_prefix, const char *name)
|
|||
|
||||
if (has_prefix) {
|
||||
string temp;
|
||||
if (!get_token(lex, temp, BASETOKEN_ALPHA)) return 0;
|
||||
if (!get_token(lex, temp, BASETOKEN_ALPHA))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!get_token(lex, year, BASETOKEN_DIGIT)) return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) return 0;
|
||||
if (!get_token(lex, month, BASETOKEN_DIGIT)) return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) return 0;
|
||||
if (!get_token(lex, day, BASETOKEN_DIGIT)) return 0;
|
||||
if (!get_token(lex, hour, BASETOKEN_DIGIT)) return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) return 0;
|
||||
if (!get_token(lex, minute, BASETOKEN_DIGIT)) return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER)) return 0;
|
||||
if (!get_token(lex, second, BASETOKEN_DIGIT)) return 0;
|
||||
if (!get_token(lex, year, BASETOKEN_DIGIT))
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
return 0;
|
||||
if (!get_token(lex, month, BASETOKEN_DIGIT))
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
return 0;
|
||||
if (!get_token(lex, day, BASETOKEN_DIGIT))
|
||||
return 0;
|
||||
if (!get_token(lex, hour, BASETOKEN_DIGIT))
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
return 0;
|
||||
if (!get_token(lex, minute, BASETOKEN_DIGIT))
|
||||
return 0;
|
||||
if (!expect_token(lex, "-", BASETOKEN_OTHER))
|
||||
return 0;
|
||||
if (!get_token(lex, second, BASETOKEN_DIGIT))
|
||||
return 0;
|
||||
|
||||
stringstream timestring;
|
||||
timestring << year << month << day << hour << minute << second;
|
||||
|
@ -1469,8 +1488,8 @@ static void delete_oldest_file(bool has_prefix, const char *location)
|
|||
if (entry->directory || *entry->d_name == '.')
|
||||
continue;
|
||||
|
||||
uint64_t ts = convert_log_name(has_prefix,
|
||||
entry->d_name);
|
||||
uint64_t ts =
|
||||
convert_log_name(has_prefix, entry->d_name);
|
||||
|
||||
if (ts) {
|
||||
if (ts < oldest_ts) {
|
||||
|
@ -1506,8 +1525,8 @@ static void get_last_log(bool has_prefix, const char *subdir_to_use,
|
|||
if (entry->directory || *entry->d_name == '.')
|
||||
continue;
|
||||
|
||||
uint64_t ts = convert_log_name(has_prefix,
|
||||
entry->d_name);
|
||||
uint64_t ts =
|
||||
convert_log_name(has_prefix, entry->d_name);
|
||||
|
||||
if (ts > highest_ts) {
|
||||
last = entry->d_name;
|
||||
|
@ -1527,14 +1546,9 @@ string GenerateTimeDateFilename(const char *extension, bool noSpace)
|
|||
|
||||
cur_time = localtime(&now);
|
||||
snprintf(file, sizeof(file), "%d-%02d-%02d%c%02d-%02d-%02d.%s",
|
||||
cur_time->tm_year+1900,
|
||||
cur_time->tm_mon+1,
|
||||
cur_time->tm_mday,
|
||||
noSpace ? '_' : ' ',
|
||||
cur_time->tm_hour,
|
||||
cur_time->tm_min,
|
||||
cur_time->tm_sec,
|
||||
extension);
|
||||
cur_time->tm_year + 1900, cur_time->tm_mon + 1,
|
||||
cur_time->tm_mday, noSpace ? '_' : ' ', cur_time->tm_hour,
|
||||
cur_time->tm_min, cur_time->tm_sec, extension);
|
||||
|
||||
return string(file);
|
||||
}
|
||||
|
@ -1548,8 +1562,8 @@ string GenerateSpecifiedFilename(const char *extension, bool noSpace,
|
|||
if ((strcmp(extension, "mp4") == 0) && autoRemux)
|
||||
extension = "mkv";
|
||||
|
||||
BPtr<char> filename = os_generate_formatted_filename(extension,
|
||||
!noSpace, format);
|
||||
BPtr<char> filename =
|
||||
os_generate_formatted_filename(extension, !noSpace, format);
|
||||
|
||||
remuxFilename = string(filename);
|
||||
remuxAfterRecord = autoRemux;
|
||||
|
@ -1597,11 +1611,9 @@ static void create_log_file(fstream &logFile)
|
|||
#ifdef _WIN32
|
||||
BPtr<wchar_t> wpath;
|
||||
os_utf8_to_wcs_ptr(path, 0, &wpath);
|
||||
logFile.open(wpath,
|
||||
ios_base::in | ios_base::out | ios_base::trunc);
|
||||
logFile.open(wpath, ios_base::in | ios_base::out | ios_base::trunc);
|
||||
#else
|
||||
logFile.open(path,
|
||||
ios_base::in | ios_base::out | ios_base::trunc);
|
||||
logFile.open(path, ios_base::in | ios_base::out | ios_base::trunc);
|
||||
#endif
|
||||
|
||||
if (logFile.is_open()) {
|
||||
|
@ -1612,13 +1624,11 @@ static void create_log_file(fstream &logFile)
|
|||
}
|
||||
}
|
||||
|
||||
static auto ProfilerNameStoreRelease = [](profiler_name_store_t *store)
|
||||
{
|
||||
static auto ProfilerNameStoreRelease = [](profiler_name_store_t *store) {
|
||||
profiler_name_store_free(store);
|
||||
};
|
||||
|
||||
using ProfilerNameStore =
|
||||
std::unique_ptr<profiler_name_store_t,
|
||||
using ProfilerNameStore = std::unique_ptr<profiler_name_store_t,
|
||||
decltype(ProfilerNameStoreRelease)>;
|
||||
|
||||
ProfilerNameStore CreateNameStore()
|
||||
|
@ -1627,8 +1637,7 @@ ProfilerNameStore CreateNameStore()
|
|||
ProfilerNameStoreRelease};
|
||||
}
|
||||
|
||||
static auto SnapshotRelease = [](profiler_snapshot_t *snap)
|
||||
{
|
||||
static auto SnapshotRelease = [](profiler_snapshot_t *snap) {
|
||||
profile_snapshot_free(snap);
|
||||
};
|
||||
|
||||
|
@ -1662,8 +1671,7 @@ static void SaveProfilerData(const ProfilerSnapshot &snap)
|
|||
static_cast<const char *>(path));
|
||||
}
|
||||
|
||||
static auto ProfilerFree = [](void *)
|
||||
{
|
||||
static auto ProfilerFree = [](void *) {
|
||||
profiler_stop();
|
||||
|
||||
auto snap = GetSnapshot();
|
||||
|
@ -1683,9 +1691,8 @@ static int run_program(fstream &logFile, int argc, char *argv[])
|
|||
|
||||
auto profilerNameStore = CreateNameStore();
|
||||
|
||||
std::unique_ptr<void, decltype(ProfilerFree)>
|
||||
prof_release(static_cast<void*>(&ProfilerFree),
|
||||
ProfilerFree);
|
||||
std::unique_ptr<void, decltype(ProfilerFree)> prof_release(
|
||||
static_cast<void *>(&ProfilerFree), ProfilerFree);
|
||||
|
||||
profiler_start();
|
||||
profile_register_root(run_program_init, 0);
|
||||
|
@ -1771,7 +1778,8 @@ run:
|
|||
for (int i = 2; i < argc; ++i) {
|
||||
stor << " " << argv[i];
|
||||
}
|
||||
blog(LOG_INFO, "Command Line Arguments: %s", stor.str().c_str());
|
||||
blog(LOG_INFO, "Command Line Arguments: %s",
|
||||
stor.str().c_str());
|
||||
}
|
||||
|
||||
if (!program.OBSInit())
|
||||
|
@ -1863,8 +1871,8 @@ static void load_debug_privilege(void)
|
|||
tp.Privileges[0].Luid = val;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
AdjustTokenPrivileges(token, false, &tp,
|
||||
sizeof(tp), NULL, NULL);
|
||||
AdjustTokenPrivileges(token, false, &tp, sizeof(tp), NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
CloseHandle(token);
|
||||
|
@ -1989,8 +1997,8 @@ bool WindowPositionValid(QRect rect)
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool arg_is(const char *arg,
|
||||
const char *long_form, const char *short_form)
|
||||
static inline bool arg_is(const char *arg, const char *long_form,
|
||||
const char *short_form)
|
||||
{
|
||||
return (long_form && strcmp(arg, long_form) == 0) ||
|
||||
(short_form && strcmp(arg, short_form) == 0);
|
||||
|
@ -2100,8 +2108,8 @@ static bool update_reconnect(ConfigFile &config)
|
|||
if (!mode)
|
||||
return false;
|
||||
|
||||
const char *section = (strcmp(mode, "Advanced") == 0) ?
|
||||
"AdvOut" : "SimpleOutput";
|
||||
const char *section = (strcmp(mode, "Advanced") == 0) ? "AdvOut"
|
||||
: "SimpleOutput";
|
||||
|
||||
if (move_reconnect_settings(config, section)) {
|
||||
config_remove_value(config, "SimpleOutput", "Reconnect");
|
||||
|
@ -2196,12 +2204,11 @@ static void upgrade_settings(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (config) {
|
||||
const char *sEnc = config_get_string(config,
|
||||
"AdvOut", "Encoder");
|
||||
const char *rEnc = config_get_string(config,
|
||||
"AdvOut", "RecEncoder");
|
||||
const char *sEnc = config_get_string(
|
||||
config, "AdvOut", "Encoder");
|
||||
const char *rEnc = config_get_string(
|
||||
config, "AdvOut", "RecEncoder");
|
||||
|
||||
/* replace "cbr" option with "rate_control" for
|
||||
* each profile's encoder data */
|
||||
|
@ -2227,7 +2234,8 @@ static void upgrade_settings(void)
|
|||
os_closedir(dir);
|
||||
}
|
||||
|
||||
void ctrlc_handler (int s) {
|
||||
void ctrlc_handler(int s)
|
||||
{
|
||||
UNUSED_PARAMETER(s);
|
||||
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
|
@ -2247,7 +2255,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
sigaction(SIGINT, &sig_handler, NULL);
|
||||
|
||||
|
||||
/* Block SIGPIPE in all threads, this can happen if a thread calls write on
|
||||
a closed pipe. */
|
||||
sigset_t sigpipe_mask;
|
||||
|
@ -2301,13 +2308,16 @@ int main(int argc, char *argv[])
|
|||
opt_start_replaybuffer = true;
|
||||
|
||||
} else if (arg_is(argv[i], "--collection", nullptr)) {
|
||||
if (++i < argc) opt_starting_collection = argv[i];
|
||||
if (++i < argc)
|
||||
opt_starting_collection = argv[i];
|
||||
|
||||
} else if (arg_is(argv[i], "--profile", nullptr)) {
|
||||
if (++i < argc) opt_starting_profile = argv[i];
|
||||
if (++i < argc)
|
||||
opt_starting_profile = argv[i];
|
||||
|
||||
} else if (arg_is(argv[i], "--scene", nullptr)) {
|
||||
if (++i < argc) opt_starting_scene = argv[i];
|
||||
if (++i < argc)
|
||||
opt_starting_scene = argv[i];
|
||||
|
||||
} else if (arg_is(argv[i], "--minimize-to-tray", nullptr)) {
|
||||
opt_minimize_tray = true;
|
||||
|
@ -2319,30 +2329,30 @@ int main(int argc, char *argv[])
|
|||
opt_allow_opengl = true;
|
||||
|
||||
} else if (arg_is(argv[i], "--help", "-h")) {
|
||||
std::cout <<
|
||||
"--help, -h: Get list of available commands.\n\n" <<
|
||||
"--startstreaming: Automatically start streaming.\n" <<
|
||||
"--startrecording: Automatically start recording.\n" <<
|
||||
"--startreplaybuffer: Start replay buffer.\n\n" <<
|
||||
"--collection <string>: Use specific scene collection."
|
||||
<< "\n" <<
|
||||
"--profile <string>: Use specific profile.\n" <<
|
||||
"--scene <string>: Start with specific scene.\n\n" <<
|
||||
"--studio-mode: Enable studio mode.\n" <<
|
||||
"--minimize-to-tray: Minimize to system tray.\n" <<
|
||||
"--portable, -p: Use portable mode.\n" <<
|
||||
"--multi, -m: Don't warn when launching multiple instances.\n\n" <<
|
||||
"--verbose: Make log more verbose.\n" <<
|
||||
"--always-on-top: Start in 'always on top' mode.\n\n" <<
|
||||
"--unfiltered_log: Make log unfiltered.\n\n" <<
|
||||
"--allow-opengl: Allow OpenGL on Windows.\n\n" <<
|
||||
"--version, -V: Get current version.\n";
|
||||
std::cout
|
||||
<< "--help, -h: Get list of available commands.\n\n"
|
||||
<< "--startstreaming: Automatically start streaming.\n"
|
||||
<< "--startrecording: Automatically start recording.\n"
|
||||
<< "--startreplaybuffer: Start replay buffer.\n\n"
|
||||
<< "--collection <string>: Use specific scene collection."
|
||||
<< "\n"
|
||||
<< "--profile <string>: Use specific profile.\n"
|
||||
<< "--scene <string>: Start with specific scene.\n\n"
|
||||
<< "--studio-mode: Enable studio mode.\n"
|
||||
<< "--minimize-to-tray: Minimize to system tray.\n"
|
||||
<< "--portable, -p: Use portable mode.\n"
|
||||
<< "--multi, -m: Don't warn when launching multiple instances.\n\n"
|
||||
<< "--verbose: Make log more verbose.\n"
|
||||
<< "--always-on-top: Start in 'always on top' mode.\n\n"
|
||||
<< "--unfiltered_log: Make log unfiltered.\n\n"
|
||||
<< "--allow-opengl: Allow OpenGL on Windows.\n\n"
|
||||
<< "--version, -V: Get current version.\n";
|
||||
|
||||
exit(0);
|
||||
|
||||
} else if (arg_is(argv[i], "--version", "-V")) {
|
||||
std::cout << "OBS Studio - " <<
|
||||
App()->GetVersionString() << "\n";
|
||||
std::cout << "OBS Studio - "
|
||||
<< App()->GetVersionString() << "\n";
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,13 +36,15 @@
|
|||
|
||||
std::string CurrentTimeString();
|
||||
std::string CurrentDateTimeString();
|
||||
std::string GenerateTimeDateFilename(const char *extension, bool noSpace=false);
|
||||
std::string GenerateTimeDateFilename(const char *extension,
|
||||
bool noSpace = false);
|
||||
std::string GenerateSpecifiedFilename(const char *extension, bool noSpace,
|
||||
const char *format);
|
||||
QObject *CreateShortcutFilter();
|
||||
|
||||
struct BaseLexer {
|
||||
lexer lex;
|
||||
|
||||
public:
|
||||
inline BaseLexer() { lexer_init(&lex); }
|
||||
inline ~BaseLexer() { lexer_free(&lex); }
|
||||
|
@ -56,7 +58,8 @@ public:
|
|||
virtual bool isEmpty() const override { return false; }
|
||||
|
||||
virtual QString translate(const char *context, const char *sourceText,
|
||||
const char *disambiguation, int n) const override;
|
||||
const char *disambiguation,
|
||||
int n) const override;
|
||||
};
|
||||
|
||||
typedef std::function<void()> VoidFunc;
|
||||
|
@ -78,7 +81,6 @@ private:
|
|||
|
||||
bool enableHotkeysInFocus = true;
|
||||
|
||||
|
||||
std::deque<obs_frontend_translate_ui_cb> translatorHooks;
|
||||
|
||||
bool UpdatePre22MultiviewLayout(const char *layout);
|
||||
|
@ -93,8 +95,8 @@ private:
|
|||
QPalette defaultPalette;
|
||||
|
||||
void ParseExtraThemeData(const char *path);
|
||||
void AddExtraThemeColor(QPalette &pal, int group,
|
||||
const char *name, uint32_t color);
|
||||
void AddExtraThemeColor(QPalette &pal, int group, const char *name,
|
||||
uint32_t color);
|
||||
|
||||
public:
|
||||
OBSApp(int &argc, char **argv, profiler_name_store_t *store);
|
||||
|
@ -109,10 +111,7 @@ public:
|
|||
|
||||
inline config_t *GlobalConfig() const { return globalConfig; }
|
||||
|
||||
inline const char *GetLocale() const
|
||||
{
|
||||
return locale.c_str();
|
||||
}
|
||||
inline const char *GetLocale() const { return locale.c_str(); }
|
||||
|
||||
inline const char *GetTheme() const { return theme.c_str(); }
|
||||
bool SetTheme(std::string name, std::string path = "");
|
||||
|
@ -146,15 +145,18 @@ public:
|
|||
|
||||
inline void IncrementSleepInhibition()
|
||||
{
|
||||
if (!sleepInhibitor) return;
|
||||
if (!sleepInhibitor)
|
||||
return;
|
||||
if (sleepInhibitRefs++ == 0)
|
||||
os_inhibit_sleep_set_active(sleepInhibitor, true);
|
||||
}
|
||||
|
||||
inline void DecrementSleepInhibition()
|
||||
{
|
||||
if (!sleepInhibitor) return;
|
||||
if (sleepInhibitRefs == 0) return;
|
||||
if (!sleepInhibitor)
|
||||
return;
|
||||
if (sleepInhibitRefs == 0)
|
||||
return;
|
||||
if (--sleepInhibitRefs == 0)
|
||||
os_inhibit_sleep_set_active(sleepInhibitor, false);
|
||||
}
|
||||
|
@ -164,10 +166,7 @@ public:
|
|||
translatorHooks.emplace_front(cb);
|
||||
}
|
||||
|
||||
inline void PopUITranslation()
|
||||
{
|
||||
translatorHooks.pop_front();
|
||||
}
|
||||
inline void PopUITranslation() { translatorHooks.pop_front(); }
|
||||
|
||||
public slots:
|
||||
void Exec(VoidFunc func);
|
||||
|
@ -182,12 +181,21 @@ char *GetConfigPathPtr(const char *name);
|
|||
int GetProgramDataPath(char *path, size_t size, const char *name);
|
||||
char *GetProgramDataPathPtr(const char *name);
|
||||
|
||||
inline OBSApp *App() {return static_cast<OBSApp*>(qApp);}
|
||||
inline OBSApp *App()
|
||||
{
|
||||
return static_cast<OBSApp *>(qApp);
|
||||
}
|
||||
|
||||
inline config_t *GetGlobalConfig() {return App()->GlobalConfig();}
|
||||
inline config_t *GetGlobalConfig()
|
||||
{
|
||||
return App()->GlobalConfig();
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> GetLocaleNames();
|
||||
inline const char *Str(const char *lookup) {return App()->GetString(lookup);}
|
||||
inline const char *Str(const char *lookup)
|
||||
{
|
||||
return App()->GetString(lookup);
|
||||
}
|
||||
#define QTStr(lookupVal) QString::fromUtf8(Str(lookupVal))
|
||||
|
||||
bool GetFileSafeName(const char *name, std::string &file);
|
||||
|
@ -197,8 +205,8 @@ bool WindowPositionValid(QRect rect);
|
|||
|
||||
static inline int GetProfilePath(char *path, size_t size, const char *file)
|
||||
{
|
||||
OBSMainWindow *window = reinterpret_cast<OBSMainWindow*>(
|
||||
App()->GetMainWindow());
|
||||
OBSMainWindow *window =
|
||||
reinterpret_cast<OBSMainWindow *>(App()->GetMainWindow());
|
||||
return window->GetProfilePath(path, size, file);
|
||||
}
|
||||
|
||||
|
|
|
@ -59,22 +59,19 @@ static char **convert_string_list(vector<string> &strings)
|
|||
|
||||
void *obs_frontend_get_main_window(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_main_window()
|
||||
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()
|
||||
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()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_system_tray()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
@ -99,30 +96,31 @@ char **obs_frontend_get_scene_names(void)
|
|||
|
||||
void obs_frontend_get_scenes(struct obs_frontend_source_list *sources)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_get_scenes(sources);
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_get_scenes(sources);
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_scene(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_scene()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_scene()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_set_current_scene(obs_source_t *scene)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_set_current_scene(scene);
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_set_current_scene(scene);
|
||||
}
|
||||
|
||||
void obs_frontend_get_transitions(struct obs_frontend_source_list *sources)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_get_transitions(sources);
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_get_transitions(sources);
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_transition(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_transition()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_transition()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
@ -134,8 +132,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()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_transition_duration()
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
@ -170,8 +167,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)
|
||||
return callbacks_valid() ? c->obs_frontend_add_scene_collection(name)
|
||||
: false;
|
||||
}
|
||||
|
||||
|
@ -187,8 +183,7 @@ char **obs_frontend_get_profiles(void)
|
|||
|
||||
char *obs_frontend_get_current_profile(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_profile()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_profile()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
@ -200,57 +195,59 @@ void obs_frontend_set_current_profile(const char *profile)
|
|||
|
||||
void obs_frontend_streaming_start(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_streaming_start();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_streaming_start();
|
||||
}
|
||||
|
||||
void obs_frontend_streaming_stop(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_streaming_stop();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_streaming_stop();
|
||||
}
|
||||
|
||||
bool obs_frontend_streaming_active(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_streaming_active()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_streaming_active() : false;
|
||||
}
|
||||
|
||||
void obs_frontend_recording_start(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_recording_start();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_recording_start();
|
||||
}
|
||||
|
||||
void obs_frontend_recording_stop(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_recording_stop();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_recording_stop();
|
||||
}
|
||||
|
||||
bool obs_frontend_recording_active(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_recording_active()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_recording_active() : false;
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_start(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_replay_buffer_start();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_replay_buffer_start();
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_save(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_replay_buffer_save();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_replay_buffer_save();
|
||||
}
|
||||
|
||||
void obs_frontend_replay_buffer_stop(void)
|
||||
{
|
||||
if (callbacks_valid()) c->obs_frontend_replay_buffer_stop();
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_replay_buffer_stop();
|
||||
}
|
||||
|
||||
bool obs_frontend_replay_buffer_active(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_replay_buffer_active()
|
||||
return !!callbacks_valid() ? c->obs_frontend_replay_buffer_active()
|
||||
: false;
|
||||
}
|
||||
|
||||
|
@ -262,7 +259,8 @@ void *obs_frontend_add_tools_menu_qaction(const char *name)
|
|||
}
|
||||
|
||||
void obs_frontend_add_tools_menu_item(const char *name,
|
||||
obs_frontend_cb callback, void *private_data)
|
||||
obs_frontend_cb callback,
|
||||
void *private_data)
|
||||
{
|
||||
if (callbacks_valid())
|
||||
c->obs_frontend_add_tools_menu_item(name, callback,
|
||||
|
@ -271,9 +269,7 @@ void obs_frontend_add_tools_menu_item(const char *name,
|
|||
|
||||
void *obs_frontend_add_dock(void *dock)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_add_dock(dock)
|
||||
: nullptr;
|
||||
return !!callbacks_valid() ? c->obs_frontend_add_dock(dock) : nullptr;
|
||||
}
|
||||
|
||||
void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
|
||||
|
@ -292,36 +288,31 @@ 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()
|
||||
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()
|
||||
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()
|
||||
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()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_profile_config()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
config_t *obs_frontend_get_global_config(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_global_config()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_global_config()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
@ -391,8 +382,7 @@ void obs_frontend_set_streaming_service(obs_service_t *service)
|
|||
|
||||
obs_service_t *obs_frontend_get_streaming_service(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_streaming_service()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_streaming_service()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
@ -429,15 +419,12 @@ void obs_frontend_set_preview_enabled(bool enable)
|
|||
|
||||
bool obs_frontend_preview_enabled(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_preview_enabled()
|
||||
: false;
|
||||
return !!callbacks_valid() ? c->obs_frontend_preview_enabled() : false;
|
||||
}
|
||||
|
||||
obs_source_t *obs_frontend_get_current_preview_scene(void)
|
||||
{
|
||||
return !!callbacks_valid()
|
||||
? c->obs_frontend_get_current_preview_scene()
|
||||
return !!callbacks_valid() ? c->obs_frontend_get_current_preview_scene()
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ enum obs_frontend_event {
|
|||
OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED,
|
||||
|
||||
OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP,
|
||||
OBS_FRONTEND_EVENT_FINISHED_LOADING
|
||||
OBS_FRONTEND_EVENT_FINISHED_LOADING,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
@ -54,8 +54,8 @@ 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++)
|
||||
|
@ -89,8 +89,8 @@ 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);
|
||||
|
@ -109,7 +109,8 @@ 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);
|
||||
obs_frontend_cb callback,
|
||||
void *private_data);
|
||||
|
||||
/* takes QDockWidget and returns QAction */
|
||||
EXPORT void *obs_frontend_add_dock(void *dock);
|
||||
|
@ -138,8 +139,8 @@ EXPORT void obs_frontend_remove_preload_callback(obs_frontend_save_cb callback,
|
|||
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
|
||||
|
|
|
@ -11,28 +11,28 @@ 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 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_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 void obs_frontend_set_current_profile(const char *profile) = 0;
|
||||
|
||||
|
@ -51,14 +51,17 @@ struct obs_frontend_callbacks {
|
|||
|
||||
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, void *private_data)=0;
|
||||
obs_frontend_cb callback,
|
||||
void *private_data) = 0;
|
||||
|
||||
virtual void *obs_frontend_add_dock(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;
|
||||
|
@ -70,22 +73,26 @@ struct obs_frontend_callbacks {
|
|||
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_pop_ui_translation(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 obs_service_t *obs_frontend_get_streaming_service(void) = 0;
|
||||
virtual void obs_frontend_save_streaming_service() = 0;
|
||||
|
||||
|
@ -97,7 +104,8 @@ 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;
|
||||
|
@ -105,5 +113,5 @@ struct obs_frontend_callbacks {
|
|||
virtual void on_event(enum obs_frontend_event event) = 0;
|
||||
};
|
||||
|
||||
EXPORT void obs_frontend_set_callbacks_internal(
|
||||
obs_frontend_callbacks *callbacks);
|
||||
EXPORT void
|
||||
obs_frontend_set_callbacks_internal(obs_frontend_callbacks *callbacks);
|
||||
|
|
|
@ -79,8 +79,8 @@ 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);
|
||||
|
@ -176,8 +176,8 @@ void SetAeroEnabled(bool enable)
|
|||
return;
|
||||
}
|
||||
|
||||
func = reinterpret_cast<decltype(func)>(GetProcAddress(dwm,
|
||||
"DwmEnableComposition"));
|
||||
func = reinterpret_cast<decltype(func)>(
|
||||
GetProcAddress(dwm, "DwmEnableComposition"));
|
||||
if (!func) {
|
||||
failed = true;
|
||||
return;
|
||||
|
@ -208,11 +208,13 @@ 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);
|
||||
}
|
||||
|
@ -233,8 +235,8 @@ bool DisableAudioDucking(bool disable)
|
|||
ComPtr<IAudioSessionControl> sessionControl;
|
||||
ComPtr<IAudioSessionControl2> sessionControl2;
|
||||
|
||||
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator),
|
||||
nullptr, CLSCTX_INPROC_SERVER,
|
||||
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(IMMDeviceEnumerator),
|
||||
(void **)&devEmum);
|
||||
if (FAILED(result))
|
||||
|
|
|
@ -48,6 +48,7 @@ struct RunOnceMutexData;
|
|||
|
||||
class RunOnceMutex {
|
||||
RunOnceMutexData *data = nullptr;
|
||||
|
||||
public:
|
||||
RunOnceMutex(RunOnceMutexData *data_) : data(data_) {}
|
||||
RunOnceMutex(const RunOnceMutex &rom) = delete;
|
||||
|
|
|
@ -37,23 +37,18 @@ using namespace std;
|
|||
|
||||
static inline QColor color_from_int(long long val)
|
||||
{
|
||||
return QColor( val & 0xff,
|
||||
(val >> 8) & 0xff,
|
||||
(val >> 16) & 0xff,
|
||||
return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff,
|
||||
(val >> 24) & 0xff);
|
||||
}
|
||||
|
||||
static inline long long color_to_int(QColor color)
|
||||
{
|
||||
auto shift = [&](unsigned val, int shift)
|
||||
{
|
||||
auto shift = [&](unsigned val, int shift) {
|
||||
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);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -68,14 +63,9 @@ struct frame_rate_tag {
|
|||
|
||||
frame_rate_tag() = default;
|
||||
|
||||
explicit frame_rate_tag(tag_type type)
|
||||
: type(type)
|
||||
{}
|
||||
explicit frame_rate_tag(tag_type type) : type(type) {}
|
||||
|
||||
explicit frame_rate_tag(const char *val)
|
||||
: type(USER),
|
||||
val(val)
|
||||
{}
|
||||
explicit frame_rate_tag(const char *val) : type(USER), val(val) {}
|
||||
|
||||
static frame_rate_tag simple() { return frame_rate_tag{SIMPLE}; }
|
||||
static frame_rate_tag rational() { return frame_rate_tag{RATIONAL}; }
|
||||
|
@ -182,7 +172,8 @@ void OBSPropertiesView::GetScrollPos(int &h, int &v)
|
|||
|
||||
OBSPropertiesView::OBSPropertiesView(OBSData settings_, void *obj_,
|
||||
PropertiesReloadCallback reloadCallback,
|
||||
PropertiesUpdateCallback callback_, int minSize_)
|
||||
PropertiesUpdateCallback callback_,
|
||||
int minSize_)
|
||||
: VScrollArea(nullptr),
|
||||
properties(nullptr, obs_properties_destroy),
|
||||
settings(settings_),
|
||||
|
@ -196,7 +187,8 @@ OBSPropertiesView::OBSPropertiesView(OBSData settings_, void *obj_,
|
|||
}
|
||||
|
||||
OBSPropertiesView::OBSPropertiesView(OBSData settings_, const char *type_,
|
||||
PropertiesReloadCallback reloadCallback_, int minSize_)
|
||||
PropertiesReloadCallback reloadCallback_,
|
||||
int minSize_)
|
||||
: VScrollArea(nullptr),
|
||||
properties(nullptr, obs_properties_destroy),
|
||||
settings(settings_),
|
||||
|
@ -263,10 +255,9 @@ QWidget *OBSPropertiesView::AddText(obs_property_t *prop, QFormLayout *layout,
|
|||
subLayout->addWidget(show);
|
||||
|
||||
WidgetInfo *info = new WidgetInfo(this, prop, edit);
|
||||
connect(show, &QAbstractButton::toggled,
|
||||
info, &WidgetInfo::TogglePasswordText);
|
||||
connect(show, &QAbstractButton::toggled, [=](bool hide)
|
||||
{
|
||||
connect(show, &QAbstractButton::toggled, info,
|
||||
&WidgetInfo::TogglePasswordText);
|
||||
connect(show, &QAbstractButton::toggled, [=](bool hide) {
|
||||
show->setText(hide ? QTStr("Hide") : QTStr("Show"));
|
||||
});
|
||||
children.emplace_back(info);
|
||||
|
@ -276,8 +267,8 @@ QWidget *OBSPropertiesView::AddText(obs_property_t *prop, QFormLayout *layout,
|
|||
|
||||
edit->setToolTip(QT_UTF8(obs_property_long_description(prop)));
|
||||
|
||||
connect(edit, SIGNAL(textEdited(const QString &)),
|
||||
info, SLOT(ControlChanged()));
|
||||
connect(edit, SIGNAL(textEdited(const QString &)), info,
|
||||
SLOT(ControlChanged()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -356,10 +347,10 @@ void OBSPropertiesView::AddInt(obs_property_t *prop, QFormLayout *layout,
|
|||
slider->setOrientation(Qt::Horizontal);
|
||||
subLayout->addWidget(slider);
|
||||
|
||||
connect(slider, SIGNAL(valueChanged(int)),
|
||||
spin, SLOT(setValue(int)));
|
||||
connect(spin, SIGNAL(valueChanged(int)),
|
||||
slider, SLOT(setValue(int)));
|
||||
connect(slider, SIGNAL(valueChanged(int)), spin,
|
||||
SLOT(setValue(int)));
|
||||
connect(spin, SIGNAL(valueChanged(int)), slider,
|
||||
SLOT(setValue(int)));
|
||||
}
|
||||
|
||||
connect(spin, SIGNAL(valueChanged(int)), info, SLOT(ControlChanged()));
|
||||
|
@ -404,10 +395,10 @@ void OBSPropertiesView::AddFloat(obs_property_t *prop, QFormLayout *layout,
|
|||
slider->setOrientation(Qt::Horizontal);
|
||||
subLayout->addWidget(slider);
|
||||
|
||||
connect(slider, SIGNAL(doubleValChanged(double)),
|
||||
spin, SLOT(setValue(double)));
|
||||
connect(spin, SIGNAL(valueChanged(double)),
|
||||
slider, SLOT(setDoubleVal(double)));
|
||||
connect(slider, SIGNAL(doubleValChanged(double)), spin,
|
||||
SLOT(setValue(double)));
|
||||
connect(spin, SIGNAL(valueChanged(double)), slider,
|
||||
SLOT(setDoubleVal(double)));
|
||||
}
|
||||
|
||||
connect(spin, SIGNAL(valueChanged(double)), info,
|
||||
|
@ -485,7 +476,8 @@ static string from_obs_data_autoselect(obs_data_t *data, const char *name,
|
|||
{
|
||||
return from_obs_data<obs_data_get_autoselect_int,
|
||||
obs_data_get_autoselect_double,
|
||||
obs_data_get_autoselect_string>(data, name, format);
|
||||
obs_data_get_autoselect_string>(data, name,
|
||||
format);
|
||||
}
|
||||
|
||||
QWidget *OBSPropertiesView::AddList(obs_property_t *prop, bool &warning)
|
||||
|
@ -537,7 +529,6 @@ QWidget *OBSPropertiesView::AddList(obs_property_t *prop, bool &warning)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
QAbstractItemModel *model = combo->model();
|
||||
warning = idx != -1 &&
|
||||
model->flags(model->index(idx, 0)) == Qt::NoItemFlags;
|
||||
|
@ -554,8 +545,7 @@ QWidget *OBSPropertiesView::AddList(obs_property_t *prop, bool &warning)
|
|||
return combo;
|
||||
}
|
||||
|
||||
static void NewButton(QLayout *layout, WidgetInfo *info,
|
||||
const char *themeIcon,
|
||||
static void NewButton(QLayout *layout, WidgetInfo *info, const char *themeIcon,
|
||||
void (WidgetInfo::*method)())
|
||||
{
|
||||
QPushButton *button = new QPushButton();
|
||||
|
@ -597,8 +587,7 @@ void OBSPropertiesView::AddEditableList(obs_property_t *prop,
|
|||
WidgetInfo *info = new WidgetInfo(this, prop, list);
|
||||
|
||||
QVBoxLayout *sideLayout = new QVBoxLayout();
|
||||
NewButton(sideLayout, info, "addIconSmall",
|
||||
&WidgetInfo::EditListAdd);
|
||||
NewButton(sideLayout, info, "addIconSmall", &WidgetInfo::EditListAdd);
|
||||
NewButton(sideLayout, info, "removeIconSmall",
|
||||
&WidgetInfo::EditListRemove);
|
||||
NewButton(sideLayout, info, "configIconSmall",
|
||||
|
@ -657,8 +646,10 @@ void OBSPropertiesView::AddColor(obs_property_t *prop, QFormLayout *layout,
|
|||
colorLabel->setPalette(palette);
|
||||
colorLabel->setStyleSheet(
|
||||
QString("background-color :%1; color: %2;")
|
||||
.arg(palette.color(QPalette::Window).name(QColor::HexArgb))
|
||||
.arg(palette.color(QPalette::WindowText).name(QColor::HexArgb)));
|
||||
.arg(palette.color(QPalette::Window)
|
||||
.name(QColor::HexArgb))
|
||||
.arg(palette.color(QPalette::WindowText)
|
||||
.name(QColor::HexArgb)));
|
||||
colorLabel->setAutoFillBackground(true);
|
||||
colorLabel->setAlignment(Qt::AlignCenter);
|
||||
colorLabel->setToolTip(QT_UTF8(obs_property_long_description(prop)));
|
||||
|
@ -692,16 +683,22 @@ static void MakeQFont(obs_data_t *font_obj, QFont &font, bool limit = false)
|
|||
if (size) {
|
||||
if (limit) {
|
||||
int max_size = font.pointSize();
|
||||
if (max_size < 28) max_size = 28;
|
||||
if (size > max_size) size = max_size;
|
||||
if (max_size < 28)
|
||||
max_size = 28;
|
||||
if (size > max_size)
|
||||
size = max_size;
|
||||
}
|
||||
font.setPointSize(size);
|
||||
}
|
||||
|
||||
if (flags & OBS_FONT_BOLD) font.setBold(true);
|
||||
if (flags & OBS_FONT_ITALIC) font.setItalic(true);
|
||||
if (flags & OBS_FONT_UNDERLINE) font.setUnderline(true);
|
||||
if (flags & OBS_FONT_STRIKEOUT) font.setStrikeOut(true);
|
||||
if (flags & OBS_FONT_BOLD)
|
||||
font.setBold(true);
|
||||
if (flags & OBS_FONT_ITALIC)
|
||||
font.setItalic(true);
|
||||
if (flags & OBS_FONT_UNDERLINE)
|
||||
font.setUnderline(true);
|
||||
if (flags & OBS_FONT_STRIKEOUT)
|
||||
font.setStrikeOut(true);
|
||||
}
|
||||
|
||||
void OBSPropertiesView::AddFont(obs_property_t *prop, QFormLayout *layout,
|
||||
|
@ -751,26 +748,17 @@ void OBSPropertiesView::AddFont(obs_property_t *prop, QFormLayout *layout,
|
|||
|
||||
namespace std {
|
||||
|
||||
template <>
|
||||
struct default_delete<obs_data_t> {
|
||||
void operator()(obs_data_t *data)
|
||||
{
|
||||
obs_data_release(data);
|
||||
}
|
||||
template<> struct default_delete<obs_data_t> {
|
||||
void operator()(obs_data_t *data) { obs_data_release(data); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct default_delete<obs_data_item_t> {
|
||||
void operator()(obs_data_item_t *item)
|
||||
{
|
||||
obs_data_item_release(&item);
|
||||
}
|
||||
template<> struct default_delete<obs_data_item_t> {
|
||||
void operator()(obs_data_item_t *item) { obs_data_item_release(&item); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static double make_epsilon(T val)
|
||||
template<typename T> static double make_epsilon(T val)
|
||||
{
|
||||
return val * 0.00001;
|
||||
}
|
||||
|
@ -793,7 +781,8 @@ static bool matches_range(media_frames_per_second &match,
|
|||
|
||||
static bool matches_ranges(media_frames_per_second &best_match,
|
||||
media_frames_per_second fps,
|
||||
const frame_rate_ranges_t &fps_ranges, bool exact=false)
|
||||
const frame_rate_ranges_t &fps_ranges,
|
||||
bool exact = false)
|
||||
{
|
||||
auto convert_fn = media_frames_per_second_to_frame_interval;
|
||||
auto val = convert_fn(fps);
|
||||
|
@ -830,7 +819,6 @@ static bool matches_ranges(media_frames_per_second &best_match,
|
|||
match = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return match;
|
||||
|
@ -845,15 +833,9 @@ static media_frames_per_second make_fps(uint32_t num, uint32_t den)
|
|||
}
|
||||
|
||||
static const common_frame_rate common_fps[] = {
|
||||
{"60", {60, 1}},
|
||||
{"59.94", {60000, 1001}},
|
||||
{"50", {50, 1}},
|
||||
{"48", {48, 1}},
|
||||
{"30", {30, 1}},
|
||||
{"29.97", {30000, 1001}},
|
||||
{"25", {25, 1}},
|
||||
{"24", {24, 1}},
|
||||
{"23.976", {24000, 1001}},
|
||||
{"60", {60, 1}}, {"59.94", {60000, 1001}}, {"50", {50, 1}},
|
||||
{"48", {48, 1}}, {"30", {30, 1}}, {"29.97", {30000, 1001}},
|
||||
{"25", {25, 1}}, {"24", {24, 1}}, {"23.976", {24000, 1001}},
|
||||
};
|
||||
|
||||
static void UpdateSimpleFPSSelection(OBSFrameRatePropertyWidget *fpsProps,
|
||||
|
@ -885,8 +867,7 @@ static void UpdateSimpleFPSSelection(OBSFrameRatePropertyWidget *fpsProps,
|
|||
static void AddFPSRanges(vector<common_frame_rate> &items,
|
||||
const frame_rate_ranges_t &ranges)
|
||||
{
|
||||
auto InsertFPS = [&](media_frames_per_second fps)
|
||||
{
|
||||
auto InsertFPS = [&](media_frames_per_second fps) {
|
||||
auto fps_val = media_frames_per_second_to_fps(fps);
|
||||
|
||||
auto end_ = end(items);
|
||||
|
@ -911,8 +892,9 @@ static void AddFPSRanges(vector<common_frame_rate> &items,
|
|||
}
|
||||
}
|
||||
|
||||
static QWidget *CreateSimpleFPSValues(OBSFrameRatePropertyWidget *fpsProps,
|
||||
bool &selected, const media_frames_per_second *current_fps)
|
||||
static QWidget *
|
||||
CreateSimpleFPSValues(OBSFrameRatePropertyWidget *fpsProps, bool &selected,
|
||||
const media_frames_per_second *current_fps)
|
||||
{
|
||||
auto widget = new QWidget{};
|
||||
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
@ -938,10 +920,11 @@ static QWidget *CreateSimpleFPSValues(OBSFrameRatePropertyWidget *fpsProps,
|
|||
|
||||
for (const auto &item : items) {
|
||||
auto var = QVariant::fromValue(item.fps);
|
||||
auto name = item.fps_name ?
|
||||
QString(item.fps_name) :
|
||||
QString("%1")
|
||||
.arg(media_frames_per_second_to_fps(item.fps));
|
||||
auto name = item.fps_name
|
||||
? QString(item.fps_name)
|
||||
: QString("%1").arg(
|
||||
media_frames_per_second_to_fps(
|
||||
item.fps));
|
||||
combo->addItem(name, var);
|
||||
|
||||
bool select = current_fps && *current_fps == item.fps;
|
||||
|
@ -991,7 +974,8 @@ static void UpdateRationalFPSWidgets(OBSFrameRatePropertyWidget *fpsProps,
|
|||
}
|
||||
|
||||
static QWidget *CreateRationalFPS(OBSFrameRatePropertyWidget *fpsProps,
|
||||
bool &selected, const media_frames_per_second *current_fps)
|
||||
bool &selected,
|
||||
const media_frames_per_second *current_fps)
|
||||
{
|
||||
auto widget = new QWidget{};
|
||||
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
|
@ -1043,8 +1027,8 @@ static QWidget *CreateRationalFPS(OBSFrameRatePropertyWidget *fpsProps,
|
|||
return widget;
|
||||
}
|
||||
|
||||
static OBSFrameRatePropertyWidget *CreateFrameRateWidget(obs_property_t *prop,
|
||||
bool &warning, const char *option,
|
||||
static OBSFrameRatePropertyWidget *
|
||||
CreateFrameRateWidget(obs_property_t *prop, bool &warning, const char *option,
|
||||
media_frames_per_second *current_fps,
|
||||
frame_rate_ranges_t &fps_ranges)
|
||||
{
|
||||
|
@ -1084,8 +1068,7 @@ static OBSFrameRatePropertyWidget *CreateFrameRateWidget(obs_property_t *prop,
|
|||
auto stack = widget->modeDisplay = new QStackedWidget{};
|
||||
|
||||
bool match_found = option_found;
|
||||
auto AddWidget = [&](decltype(CreateRationalFPS) func)
|
||||
{
|
||||
auto AddWidget = [&](decltype(CreateRationalFPS) func) {
|
||||
bool selected = false;
|
||||
stack->addWidget(func(widget, selected, current_fps));
|
||||
|
||||
|
@ -1149,16 +1132,14 @@ static OBSFrameRatePropertyWidget *CreateFrameRateWidget(obs_property_t *prop,
|
|||
|
||||
static void UpdateMinMaxLabels(OBSFrameRatePropertyWidget *w)
|
||||
{
|
||||
auto Hide = [&](bool hide)
|
||||
{
|
||||
auto Hide = [&](bool hide) {
|
||||
w->minLabel->setHidden(hide);
|
||||
w->maxLabel->setHidden(hide);
|
||||
};
|
||||
|
||||
auto variant = w->modeSelect->currentData();
|
||||
if (!variant.canConvert<frame_rate_tag>() ||
|
||||
variant.value<frame_rate_tag>().type !=
|
||||
frame_rate_tag::RATIONAL) {
|
||||
variant.value<frame_rate_tag>().type != frame_rate_tag::RATIONAL) {
|
||||
Hide(true);
|
||||
return;
|
||||
}
|
||||
|
@ -1199,8 +1180,7 @@ static void UpdateFPSLabels(OBSFrameRatePropertyWidget *w)
|
|||
media_frames_per_second *valid_fps = nullptr;
|
||||
if (obs_data_item_get_autoselect_frames_per_second(obj.get(), &fps,
|
||||
nullptr) ||
|
||||
obs_data_item_get_frames_per_second(obj.get(), &fps,
|
||||
nullptr))
|
||||
obs_data_item_get_frames_per_second(obj.get(), &fps, nullptr))
|
||||
valid_fps = &fps;
|
||||
|
||||
const char *option = nullptr;
|
||||
|
@ -1229,9 +1209,10 @@ static void UpdateFPSLabels(OBSFrameRatePropertyWidget *w)
|
|||
auto convert_to_frame_interval =
|
||||
media_frames_per_second_to_frame_interval;
|
||||
|
||||
w->currentFPS->setText(QString("FPS: %1")
|
||||
.arg(convert_to_fps(*valid_fps)));
|
||||
w->timePerFrame->setText(QString("Frame Interval: %1 ms")
|
||||
w->currentFPS->setText(
|
||||
QString("FPS: %1").arg(convert_to_fps(*valid_fps)));
|
||||
w->timePerFrame->setText(
|
||||
QString("Frame Interval: %1 ms")
|
||||
.arg(convert_to_frame_interval(*valid_fps) * 1000));
|
||||
}
|
||||
|
||||
|
@ -1290,9 +1271,7 @@ void OBSPropertiesView::AddFrameRate(obs_property_t *prop, bool &warning,
|
|||
|
||||
auto comboIndexChanged = static_cast<void (QComboBox::*)(int)>(
|
||||
&QComboBox::currentIndexChanged);
|
||||
connect(combo, comboIndexChanged, stack,
|
||||
[=](int index)
|
||||
{
|
||||
connect(combo, comboIndexChanged, stack, [=](int index) {
|
||||
bool out_of_bounds = index >= stack->count();
|
||||
auto idx = out_of_bounds ? stack->count() - 1 : index;
|
||||
stack->setCurrentIndex(idx);
|
||||
|
@ -1304,34 +1283,30 @@ void OBSPropertiesView::AddFrameRate(obs_property_t *prop, bool &warning,
|
|||
emit info->ControlChanged();
|
||||
});
|
||||
|
||||
connect(widget->simpleFPS, comboIndexChanged, [=](int)
|
||||
{
|
||||
connect(widget->simpleFPS, comboIndexChanged, [=](int) {
|
||||
if (widget->updating)
|
||||
return;
|
||||
|
||||
emit info->ControlChanged();
|
||||
});
|
||||
|
||||
connect(widget->fpsRange, comboIndexChanged, [=](int)
|
||||
{
|
||||
connect(widget->fpsRange, comboIndexChanged, [=](int) {
|
||||
if (widget->updating)
|
||||
return;
|
||||
|
||||
UpdateFPSLabels(widget);
|
||||
});
|
||||
|
||||
auto sbValueChanged = static_cast<void (QSpinBox::*)(int)>(
|
||||
&QSpinBox::valueChanged);
|
||||
connect(widget->numEdit, sbValueChanged, [=](int)
|
||||
{
|
||||
auto sbValueChanged =
|
||||
static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
|
||||
connect(widget->numEdit, sbValueChanged, [=](int) {
|
||||
if (widget->updating)
|
||||
return;
|
||||
|
||||
emit info->ControlChanged();
|
||||
});
|
||||
|
||||
connect(widget->denEdit, sbValueChanged, [=](int)
|
||||
{
|
||||
connect(widget->denEdit, sbValueChanged, [=](int) {
|
||||
if (widget->updating)
|
||||
return;
|
||||
|
||||
|
@ -1433,10 +1408,8 @@ void OBSPropertiesView::AddProperty(obs_property_t *property,
|
|||
if (widget && !obs_property_enabled(property))
|
||||
widget->setEnabled(false);
|
||||
|
||||
if (!label &&
|
||||
type != OBS_PROPERTY_BOOL &&
|
||||
type != OBS_PROPERTY_BUTTON &&
|
||||
type != OBS_PROPERTY_GROUP)
|
||||
if (!label && type != OBS_PROPERTY_BOOL &&
|
||||
type != OBS_PROPERTY_BUTTON && type != OBS_PROPERTY_GROUP)
|
||||
label = new QLabel(QT_UTF8(obs_property_description(property)));
|
||||
|
||||
if (warning && label) //TODO: select color based on background color
|
||||
|
@ -1466,7 +1439,8 @@ void OBSPropertiesView::SignalChanged()
|
|||
}
|
||||
|
||||
static bool FrameRateChangedVariant(const QVariant &variant,
|
||||
media_frames_per_second &fps, obs_data_item_t *&obj,
|
||||
media_frames_per_second &fps,
|
||||
obs_data_item_t *&obj,
|
||||
const media_frames_per_second *valid_fps)
|
||||
{
|
||||
if (!variant.canConvert<media_frames_per_second>())
|
||||
|
@ -1481,7 +1455,8 @@ static bool FrameRateChangedVariant(const QVariant &variant,
|
|||
}
|
||||
|
||||
static bool FrameRateChangedCommon(OBSFrameRatePropertyWidget *w,
|
||||
obs_data_item_t *&obj, const media_frames_per_second *valid_fps)
|
||||
obs_data_item_t *&obj,
|
||||
const media_frames_per_second *valid_fps)
|
||||
{
|
||||
media_frames_per_second fps{};
|
||||
if (!FrameRateChangedVariant(w->simpleFPS->currentData(), fps, obj,
|
||||
|
@ -1493,7 +1468,8 @@ static bool FrameRateChangedCommon(OBSFrameRatePropertyWidget *w,
|
|||
}
|
||||
|
||||
static bool FrameRateChangedRational(OBSFrameRatePropertyWidget *w,
|
||||
obs_data_item_t *&obj, const media_frames_per_second *valid_fps)
|
||||
obs_data_item_t *&obj,
|
||||
const media_frames_per_second *valid_fps)
|
||||
{
|
||||
auto num = w->numEdit->value();
|
||||
auto den = w->denEdit->value();
|
||||
|
@ -1519,10 +1495,7 @@ static bool FrameRateChanged(QWidget *widget, const char *name,
|
|||
if (!variant.canConvert<frame_rate_tag>())
|
||||
return false;
|
||||
|
||||
auto StopUpdating = [&](void*)
|
||||
{
|
||||
w->updating = false;
|
||||
};
|
||||
auto StopUpdating = [&](void *) { w->updating = false; };
|
||||
unique_ptr<void, decltype(StopUpdating)> signalGuard(
|
||||
static_cast<void *>(w), StopUpdating);
|
||||
w->updating = true;
|
||||
|
@ -1532,8 +1505,7 @@ static bool FrameRateChanged(QWidget *widget, const char *name,
|
|||
|
||||
unique_ptr<obs_data_item_t> obj{obs_data_item_byname(settings, name)};
|
||||
auto obj_ptr = obj.get();
|
||||
auto CheckObj = [&]()
|
||||
{
|
||||
auto CheckObj = [&]() {
|
||||
if (!obj_ptr)
|
||||
obj.release();
|
||||
};
|
||||
|
@ -1614,17 +1586,17 @@ bool WidgetInfo::PathChanged(const char *setting)
|
|||
QString path;
|
||||
|
||||
if (type == OBS_PATH_DIRECTORY)
|
||||
path = QFileDialog::getExistingDirectory(view,
|
||||
QT_UTF8(desc), QT_UTF8(default_path),
|
||||
path = QFileDialog::getExistingDirectory(
|
||||
view, QT_UTF8(desc), QT_UTF8(default_path),
|
||||
QFileDialog::ShowDirsOnly |
|
||||
QFileDialog::DontResolveSymlinks);
|
||||
else if (type == OBS_PATH_FILE)
|
||||
path = QFileDialog::getOpenFileName(view,
|
||||
QT_UTF8(desc), QT_UTF8(default_path),
|
||||
path = QFileDialog::getOpenFileName(view, QT_UTF8(desc),
|
||||
QT_UTF8(default_path),
|
||||
QT_UTF8(filter));
|
||||
else if (type == OBS_PATH_FILE_SAVE)
|
||||
path = QFileDialog::getSaveFileName(view,
|
||||
QT_UTF8(desc), QT_UTF8(default_path),
|
||||
path = QFileDialog::getSaveFileName(view, QT_UTF8(desc),
|
||||
QT_UTF8(default_path),
|
||||
QT_UTF8(filter));
|
||||
|
||||
if (path.isEmpty())
|
||||
|
@ -1697,10 +1669,11 @@ bool WidgetInfo::ColorChanged(const char *setting)
|
|||
label->setText(color.name(QColor::HexArgb));
|
||||
QPalette palette = QPalette(color);
|
||||
label->setPalette(palette);
|
||||
label->setStyleSheet(
|
||||
QString("background-color :%1; color: %2;")
|
||||
.arg(palette.color(QPalette::Window).name(QColor::HexArgb))
|
||||
.arg(palette.color(QPalette::WindowText).name(QColor::HexArgb)));
|
||||
label->setStyleSheet(QString("background-color :%1; color: %2;")
|
||||
.arg(palette.color(QPalette::Window)
|
||||
.name(QColor::HexArgb))
|
||||
.arg(palette.color(QPalette::WindowText)
|
||||
.name(QColor::HexArgb)));
|
||||
|
||||
obs_data_set_int(view->settings, setting, color_to_int(color));
|
||||
|
||||
|
@ -1722,10 +1695,12 @@ bool WidgetInfo::FontChanged(const char *setting)
|
|||
|
||||
if (!font_obj) {
|
||||
QFont initial;
|
||||
font = QFontDialog::getFont(&success, initial, view, "Pick a Font", options);
|
||||
font = QFontDialog::getFont(&success, initial, view,
|
||||
"Pick a Font", options);
|
||||
} else {
|
||||
MakeQFont(font_obj, font);
|
||||
font = QFontDialog::getFont(&success, font, view, "Pick a Font", options);
|
||||
font = QFontDialog::getFont(&success, font, view, "Pick a Font",
|
||||
options);
|
||||
obs_data_release(font_obj);
|
||||
}
|
||||
|
||||
|
@ -1758,7 +1733,8 @@ void WidgetInfo::GroupChanged(const char *setting)
|
|||
{
|
||||
QGroupBox *groupbox = static_cast<QGroupBox *>(widget);
|
||||
obs_data_set_bool(view->settings, setting,
|
||||
groupbox->isCheckable() ? groupbox->isChecked() : true);
|
||||
groupbox->isCheckable() ? groupbox->isChecked()
|
||||
: true);
|
||||
}
|
||||
|
||||
void WidgetInfo::EditableListChanged()
|
||||
|
@ -1772,10 +1748,8 @@ void WidgetInfo::EditableListChanged()
|
|||
obs_data_t *arrayItem = obs_data_create();
|
||||
obs_data_set_string(arrayItem, "value",
|
||||
QT_TO_UTF8(item->text()));
|
||||
obs_data_set_bool(arrayItem, "selected",
|
||||
item->isSelected());
|
||||
obs_data_set_bool(arrayItem, "hidden",
|
||||
item->isHidden());
|
||||
obs_data_set_bool(arrayItem, "selected", item->isSelected());
|
||||
obs_data_set_bool(arrayItem, "hidden", item->isHidden());
|
||||
obs_data_array_push_back(array, arrayItem);
|
||||
obs_data_release(arrayItem);
|
||||
}
|
||||
|
@ -1806,13 +1780,26 @@ void WidgetInfo::ControlChanged()
|
|||
obs_property_type type = obs_property_get_type(property);
|
||||
|
||||
switch (type) {
|
||||
case OBS_PROPERTY_INVALID: return;
|
||||
case OBS_PROPERTY_BOOL: BoolChanged(setting); break;
|
||||
case OBS_PROPERTY_INT: IntChanged(setting); break;
|
||||
case OBS_PROPERTY_FLOAT: FloatChanged(setting); break;
|
||||
case OBS_PROPERTY_TEXT: TextChanged(setting); break;
|
||||
case OBS_PROPERTY_LIST: ListChanged(setting); break;
|
||||
case OBS_PROPERTY_BUTTON: ButtonClicked(); return;
|
||||
case OBS_PROPERTY_INVALID:
|
||||
return;
|
||||
case OBS_PROPERTY_BOOL:
|
||||
BoolChanged(setting);
|
||||
break;
|
||||
case OBS_PROPERTY_INT:
|
||||
IntChanged(setting);
|
||||
break;
|
||||
case OBS_PROPERTY_FLOAT:
|
||||
FloatChanged(setting);
|
||||
break;
|
||||
case OBS_PROPERTY_TEXT:
|
||||
TextChanged(setting);
|
||||
break;
|
||||
case OBS_PROPERTY_LIST:
|
||||
ListChanged(setting);
|
||||
break;
|
||||
case OBS_PROPERTY_BUTTON:
|
||||
ButtonClicked();
|
||||
return;
|
||||
case OBS_PROPERTY_COLOR:
|
||||
if (!ColorChanged(setting))
|
||||
return;
|
||||
|
@ -1825,12 +1812,15 @@ void WidgetInfo::ControlChanged()
|
|||
if (!PathChanged(setting))
|
||||
return;
|
||||
break;
|
||||
case OBS_PROPERTY_EDITABLE_LIST: break;
|
||||
case OBS_PROPERTY_EDITABLE_LIST:
|
||||
break;
|
||||
case OBS_PROPERTY_FRAME_RATE:
|
||||
if (!FrameRateChanged(widget, setting, view->settings))
|
||||
return;
|
||||
break;
|
||||
case OBS_PROPERTY_GROUP: GroupChanged(setting); return;
|
||||
case OBS_PROPERTY_GROUP:
|
||||
GroupChanged(setting);
|
||||
return;
|
||||
}
|
||||
|
||||
if (view->callback && !view->deferUpdate)
|
||||
|
@ -1858,8 +1848,8 @@ class EditableItemDialog : public QDialog {
|
|||
curPath = default_path;
|
||||
|
||||
QString path = QFileDialog::getOpenFileName(
|
||||
App()->GetMainWindow(), QTStr("Browse"),
|
||||
curPath, filter);
|
||||
App()->GetMainWindow(), QTStr("Browse"), curPath,
|
||||
filter);
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
|
@ -1867,8 +1857,8 @@ class EditableItemDialog : public QDialog {
|
|||
}
|
||||
|
||||
public:
|
||||
EditableItemDialog(QWidget *parent, const QString &text,
|
||||
bool browse, const char *filter_ = nullptr,
|
||||
EditableItemDialog(QWidget *parent, const QString &text, bool browse,
|
||||
const char *filter_ = nullptr,
|
||||
const char *default_path_ = nullptr)
|
||||
: QDialog(parent),
|
||||
filter(QT_UTF8(filter_)),
|
||||
|
@ -1894,8 +1884,7 @@ public:
|
|||
}
|
||||
|
||||
QDialogButtonBox::StandardButtons buttons =
|
||||
QDialogButtonBox::Ok |
|
||||
QDialogButtonBox::Cancel;
|
||||
QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(buttons);
|
||||
buttonBox->setCenterButtons(true);
|
||||
|
@ -1915,8 +1904,8 @@ public:
|
|||
|
||||
void WidgetInfo::EditListAdd()
|
||||
{
|
||||
enum obs_editable_list_type type = obs_property_editable_list_type(
|
||||
property);
|
||||
enum obs_editable_list_type type =
|
||||
obs_property_editable_list_type(property);
|
||||
|
||||
if (type == OBS_EDITABLE_LIST_TYPE_STRINGS) {
|
||||
EditListAddText();
|
||||
|
@ -1929,20 +1918,19 @@ void WidgetInfo::EditListAdd()
|
|||
QAction *action;
|
||||
|
||||
action = new QAction(QTStr("Basic.PropertiesWindow.AddFiles"), this);
|
||||
connect(action, &QAction::triggered,
|
||||
this, &WidgetInfo::EditListAddFiles);
|
||||
connect(action, &QAction::triggered, this,
|
||||
&WidgetInfo::EditListAddFiles);
|
||||
popup.addAction(action);
|
||||
|
||||
action = new QAction(QTStr("Basic.PropertiesWindow.AddDir"), this);
|
||||
connect(action, &QAction::triggered,
|
||||
this, &WidgetInfo::EditListAddDir);
|
||||
connect(action, &QAction::triggered, this, &WidgetInfo::EditListAddDir);
|
||||
popup.addAction(action);
|
||||
|
||||
if (type == OBS_EDITABLE_LIST_TYPE_FILES_AND_URLS) {
|
||||
action = new QAction(QTStr("Basic.PropertiesWindow.AddURL"),
|
||||
this);
|
||||
connect(action, &QAction::triggered,
|
||||
this, &WidgetInfo::EditListAddText);
|
||||
connect(action, &QAction::triggered, this,
|
||||
&WidgetInfo::EditListAddText);
|
||||
popup.addAction(action);
|
||||
}
|
||||
|
||||
|
@ -1955,8 +1943,8 @@ void WidgetInfo::EditListAddText()
|
|||
const char *desc = obs_property_description(property);
|
||||
|
||||
EditableItemDialog dialog(widget->window(), QString(), false);
|
||||
auto title = QTStr("Basic.PropertiesWindow.AddEditableListEntry").arg(
|
||||
QT_UTF8(desc));
|
||||
auto title = QTStr("Basic.PropertiesWindow.AddEditableListEntry")
|
||||
.arg(QT_UTF8(desc));
|
||||
dialog.setWindowTitle(title);
|
||||
if (dialog.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
@ -2024,8 +2012,8 @@ void WidgetInfo::EditListRemove()
|
|||
void WidgetInfo::EditListEdit()
|
||||
{
|
||||
QListWidget *list = reinterpret_cast<QListWidget *>(widget);
|
||||
enum obs_editable_list_type type = obs_property_editable_list_type(
|
||||
property);
|
||||
enum obs_editable_list_type type =
|
||||
obs_property_editable_list_type(property);
|
||||
const char *desc = obs_property_description(property);
|
||||
const char *filter = obs_property_editable_list_filter(property);
|
||||
QList<QListWidgetItem *> selectedItems = list->selectedItems();
|
||||
|
@ -2041,8 +2029,7 @@ void WidgetInfo::EditListEdit()
|
|||
|
||||
if (pathDir.exists())
|
||||
path = QFileDialog::getExistingDirectory(
|
||||
App()->GetMainWindow(),
|
||||
QTStr("Browse"),
|
||||
App()->GetMainWindow(), QTStr("Browse"),
|
||||
item->text(),
|
||||
QFileDialog::ShowDirsOnly |
|
||||
QFileDialog::DontResolveSymlinks);
|
||||
|
@ -2060,9 +2047,10 @@ void WidgetInfo::EditListEdit()
|
|||
}
|
||||
|
||||
EditableItemDialog dialog(widget->window(), item->text(),
|
||||
type != OBS_EDITABLE_LIST_TYPE_STRINGS, filter);
|
||||
auto title = QTStr("Basic.PropertiesWindow.EditEditableListEntry").arg(
|
||||
QT_UTF8(desc));
|
||||
type != OBS_EDITABLE_LIST_TYPE_STRINGS,
|
||||
filter);
|
||||
auto title = QTStr("Basic.PropertiesWindow.EditEditableListEntry")
|
||||
.arg(QT_UTF8(desc));
|
||||
dialog.setWindowTitle(title);
|
||||
if (dialog.exec() == QDialog::Rejected)
|
||||
return;
|
||||
|
|
|
@ -10,8 +10,7 @@ class OBSPropertiesView;
|
|||
class QLabel;
|
||||
|
||||
typedef obs_properties_t *(*PropertiesReloadCallback)(void *obj);
|
||||
typedef void (*PropertiesUpdateCallback)(void *obj,
|
||||
obs_data_t *settings);
|
||||
typedef void (*PropertiesUpdateCallback)(void *obj, obs_data_t *settings);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
@ -43,7 +42,8 @@ public:
|
|||
inline WidgetInfo(OBSPropertiesView *view_, obs_property_t *prop,
|
||||
QWidget *widget_)
|
||||
: view(view_), property(prop), widget(widget_)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -99,7 +99,8 @@ private:
|
|||
void AddEditableList(obs_property_t *prop, QFormLayout *layout,
|
||||
QLabel *&label);
|
||||
QWidget *AddButton(obs_property_t *prop);
|
||||
void AddColor(obs_property_t *prop, QFormLayout *layout, QLabel *&label);
|
||||
void AddColor(obs_property_t *prop, QFormLayout *layout,
|
||||
QLabel *&label);
|
||||
void AddFont(obs_property_t *prop, QFormLayout *layout, QLabel *&label);
|
||||
void AddFrameRate(obs_property_t *prop, bool &warning,
|
||||
QFormLayout *layout, QLabel *&label);
|
||||
|
@ -126,8 +127,7 @@ signals:
|
|||
public:
|
||||
OBSPropertiesView(OBSData settings, void *obj,
|
||||
PropertiesReloadCallback reloadCallback,
|
||||
PropertiesUpdateCallback callback,
|
||||
int minSize = 0);
|
||||
PropertiesUpdateCallback callback, int minSize = 0);
|
||||
OBSPropertiesView(OBSData settings, const char *type,
|
||||
PropertiesReloadCallback reloadCallback,
|
||||
int minSize = 0);
|
||||
|
|
|
@ -8,23 +8,18 @@
|
|||
|
||||
static inline long long color_to_int(QColor color)
|
||||
{
|
||||
auto shift = [&](unsigned val, int shift)
|
||||
{
|
||||
auto shift = [&](unsigned val, int shift) {
|
||||
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);
|
||||
}
|
||||
|
||||
OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
||||
|
@ -37,8 +32,7 @@ OBSQTDisplay::OBSQTDisplay(QWidget *parent, Qt::WindowFlags flags)
|
|||
setAttribute(Qt::WA_DontCreateNativeAncestors);
|
||||
setAttribute(Qt::WA_NativeWindow);
|
||||
|
||||
auto windowVisible = [this] (bool visible)
|
||||
{
|
||||
auto windowVisible = [this](bool visible) {
|
||||
if (!visible)
|
||||
return;
|
||||
|
||||
|
@ -46,12 +40,12 @@ 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());
|
||||
}
|
||||
};
|
||||
|
||||
auto sizeChanged = [this] (QScreen*)
|
||||
{
|
||||
auto sizeChanged = [this](QScreen *) {
|
||||
CreateDisplay();
|
||||
|
||||
QSize size = GetPixelSize(this);
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
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;
|
||||
|
||||
|
|
|
@ -45,18 +45,15 @@ void OBSErrorBox(QWidget *parent, const char *msg, ...)
|
|||
va_end(args);
|
||||
}
|
||||
|
||||
QMessageBox::StandardButton OBSMessageBox::question(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
QMessageBox::StandardButton
|
||||
OBSMessageBox::question(QWidget *parent, const QString &title,
|
||||
const QString &text,
|
||||
QMessageBox::StandardButtons buttons,
|
||||
QMessageBox::StandardButton defaultButton)
|
||||
{
|
||||
QMessageBox mb(QMessageBox::Question,
|
||||
title, text, buttons,
|
||||
parent);
|
||||
QMessageBox mb(QMessageBox::Question, title, text, buttons, parent);
|
||||
mb.setDefaultButton(defaultButton);
|
||||
if (buttons & QMessageBox::Ok) \
|
||||
if (buttons & QMessageBox::Ok)
|
||||
mb.setButtonText(QMessageBox::Ok, QTStr("OK"));
|
||||
#define translate_button(x) \
|
||||
if (buttons & QMessageBox::x) \
|
||||
|
@ -78,26 +75,19 @@ QMessageBox::StandardButton OBSMessageBox::question(
|
|||
return (QMessageBox::StandardButton)mb.exec();
|
||||
}
|
||||
|
||||
void OBSMessageBox::information(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
void OBSMessageBox::information(QWidget *parent, const QString &title,
|
||||
const QString &text)
|
||||
{
|
||||
QMessageBox mb(QMessageBox::Information,
|
||||
title, text, QMessageBox::Ok,
|
||||
QMessageBox mb(QMessageBox::Information, title, text, QMessageBox::Ok,
|
||||
parent);
|
||||
mb.setButtonText(QMessageBox::Ok, QTStr("OK"));
|
||||
mb.exec();
|
||||
}
|
||||
|
||||
void OBSMessageBox::warning(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &text,
|
||||
bool enableRichText)
|
||||
void OBSMessageBox::warning(QWidget *parent, const QString &title,
|
||||
const QString &text, bool enableRichText)
|
||||
{
|
||||
QMessageBox mb(QMessageBox::Warning,
|
||||
title, text, QMessageBox::Ok,
|
||||
QMessageBox mb(QMessageBox::Warning, title, text, QMessageBox::Ok,
|
||||
parent);
|
||||
if (enableRichText)
|
||||
mb.setTextFormat(Qt::RichText);
|
||||
|
@ -105,13 +95,10 @@ void OBSMessageBox::warning(
|
|||
mb.exec();
|
||||
}
|
||||
|
||||
void OBSMessageBox::critical(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
void OBSMessageBox::critical(QWidget *parent, const QString &title,
|
||||
const QString &text)
|
||||
{
|
||||
QMessageBox mb(QMessageBox::Critical,
|
||||
title, text, QMessageBox::Ok,
|
||||
QMessageBox mb(QMessageBox::Critical, title, text, QMessageBox::Ok,
|
||||
parent);
|
||||
mb.setButtonText(QMessageBox::Ok, QTStr("OK"));
|
||||
mb.exec();
|
||||
|
@ -234,15 +221,12 @@ void DeleteLayout(QLayout *layout)
|
|||
|
||||
class QuickThread : public QThread {
|
||||
public:
|
||||
explicit inline QuickThread(std::function<void()> func_)
|
||||
: func(func_)
|
||||
{}
|
||||
explicit inline QuickThread(std::function<void()> func_) : func(func_)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void run() override
|
||||
{
|
||||
func();
|
||||
}
|
||||
virtual void run() override { func(); }
|
||||
|
||||
std::function<void()> func;
|
||||
};
|
||||
|
@ -258,8 +242,7 @@ void ExecuteFuncSafeBlock(std::function<void()> func)
|
|||
{
|
||||
QEventLoop eventLoop;
|
||||
|
||||
auto wait = [&] ()
|
||||
{
|
||||
auto wait = [&]() {
|
||||
func();
|
||||
QMetaObject::invokeMethod(&eventLoop, "quit",
|
||||
Qt::QueuedConnection);
|
||||
|
@ -273,10 +256,8 @@ void ExecuteFuncSafeBlock(std::function<void()> func)
|
|||
os_atomic_dec_long(&insideEventLoop);
|
||||
}
|
||||
|
||||
void ExecuteFuncSafeBlockMsgBox(
|
||||
std::function<void()> func,
|
||||
const QString &title,
|
||||
const QString &text)
|
||||
void ExecuteFuncSafeBlockMsgBox(std::function<void()> func,
|
||||
const QString &title, const QString &text)
|
||||
{
|
||||
QMessageBox dlg;
|
||||
dlg.setWindowFlags(dlg.windowFlags() & ~Qt::WindowCloseButtonHint);
|
||||
|
@ -284,8 +265,7 @@ void ExecuteFuncSafeBlockMsgBox(
|
|||
dlg.setText(text);
|
||||
dlg.setStandardButtons(0);
|
||||
|
||||
auto wait = [&] ()
|
||||
{
|
||||
auto wait = [&]() {
|
||||
func();
|
||||
QMetaObject::invokeMethod(&dlg, "accept", Qt::QueuedConnection);
|
||||
};
|
||||
|
@ -305,10 +285,8 @@ void EnableThreadedMessageBoxes(bool enable)
|
|||
enable_message_boxes = enable;
|
||||
}
|
||||
|
||||
void ExecThreadedWithoutBlocking(
|
||||
std::function<void()> func,
|
||||
const QString &title,
|
||||
const QString &text)
|
||||
void ExecThreadedWithoutBlocking(std::function<void()> func,
|
||||
const QString &title, const QString &text)
|
||||
{
|
||||
if (!enable_message_boxes)
|
||||
ExecuteFuncSafeBlock(func);
|
||||
|
|
|
@ -38,24 +38,18 @@ struct gs_window;
|
|||
|
||||
class OBSMessageBox {
|
||||
public:
|
||||
static QMessageBox::StandardButton question(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &text,
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::StandardButtons( QMessageBox::Yes | QMessageBox::No ),
|
||||
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
|
||||
static void information(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
static QMessageBox::StandardButton
|
||||
question(QWidget *parent, const QString &title, const QString &text,
|
||||
QMessageBox::StandardButtons buttons =
|
||||
QMessageBox::StandardButtons(QMessageBox::Yes |
|
||||
QMessageBox::No),
|
||||
QMessageBox::StandardButton defaultButton =
|
||||
QMessageBox::NoButton);
|
||||
static void information(QWidget *parent, const QString &title,
|
||||
const QString &text);
|
||||
static void warning(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
const QString &text,
|
||||
bool enableRichText = false);
|
||||
static void critical(
|
||||
QWidget *parent,
|
||||
const QString &title,
|
||||
static void warning(QWidget *parent, const QString &title,
|
||||
const QString &text, bool enableRichText = false);
|
||||
static void critical(QWidget *parent, const QString &title,
|
||||
const QString &text);
|
||||
};
|
||||
|
||||
|
@ -65,7 +59,8 @@ void QTToGSWindow(WId windowId, gs_window &gswindow);
|
|||
|
||||
uint32_t TranslateQtKeyboardEventModifiers(Qt::KeyboardModifiers mods);
|
||||
|
||||
QDataStream &operator<<(QDataStream &out,
|
||||
QDataStream &
|
||||
operator<<(QDataStream &out,
|
||||
const std::vector<std::shared_ptr<OBSSignal>> &signal_vec);
|
||||
QDataStream &operator>>(QDataStream &in,
|
||||
std::vector<std::shared_ptr<OBSSignal>> &signal_vec);
|
||||
|
@ -77,18 +72,14 @@ QDataStream &operator>>(QDataStream &in, OBSSceneItem &si);
|
|||
QThread *CreateQThread(std::function<void()> func);
|
||||
|
||||
void ExecuteFuncSafeBlock(std::function<void()> func);
|
||||
void ExecuteFuncSafeBlockMsgBox(
|
||||
std::function<void()> func,
|
||||
const QString &title,
|
||||
const QString &text);
|
||||
void ExecuteFuncSafeBlockMsgBox(std::function<void()> func,
|
||||
const QString &title, const QString &text);
|
||||
|
||||
/* allows executing without message boxes if starting up, otherwise with a
|
||||
* message box */
|
||||
void EnableThreadedMessageBoxes(bool enable);
|
||||
void ExecThreadedWithoutBlocking(
|
||||
std::function<void()> func,
|
||||
const QString &title,
|
||||
const QString &text);
|
||||
void ExecThreadedWithoutBlocking(std::function<void()> func,
|
||||
const QString &title, const QString &text);
|
||||
|
||||
class SignalBlocker {
|
||||
QWidget *widget;
|
||||
|
@ -100,10 +91,7 @@ public:
|
|||
blocked = widget->blockSignals(true);
|
||||
}
|
||||
|
||||
inline ~SignalBlocker()
|
||||
{
|
||||
widget->blockSignals(blocked);
|
||||
}
|
||||
inline ~SignalBlocker() { widget->blockSignals(blocked); }
|
||||
};
|
||||
|
||||
void DeleteLayout(QLayout *layout);
|
||||
|
|
|
@ -53,8 +53,7 @@ void RemoteTextThread::run()
|
|||
struct curl_slist *header = nullptr;
|
||||
string str;
|
||||
|
||||
header = curl_slist_append(header,
|
||||
versionString.c_str());
|
||||
header = curl_slist_append(header, versionString.c_str());
|
||||
|
||||
if (!contentTypeString.empty()) {
|
||||
header = curl_slist_append(header,
|
||||
|
@ -66,14 +65,11 @@ void RemoteTextThread::run()
|
|||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER,
|
||||
header);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER,
|
||||
error);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, header);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, error);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION,
|
||||
string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA,
|
||||
&str);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
|
||||
|
||||
if (timeoutSec)
|
||||
curl_easy_setopt(curl.get(), CURLOPT_TIMEOUT,
|
||||
|
@ -118,16 +114,10 @@ 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,
|
||||
const char *postData,
|
||||
std::vector<std::string> extraHeaders,
|
||||
std::string *signature,
|
||||
int timeoutSec)
|
||||
bool GetRemoteFile(const char *url, std::string &str, std::string &error,
|
||||
long *responseCode, const char *contentType,
|
||||
const char *postData, std::vector<std::string> extraHeaders,
|
||||
std::string *signature, int timeoutSec)
|
||||
{
|
||||
vector<string> header_in_list;
|
||||
char error_in[CURL_ERROR_SIZE];
|
||||
|
@ -148,8 +138,7 @@ bool GetRemoteFile(
|
|||
if (curl) {
|
||||
struct curl_slist *header = nullptr;
|
||||
|
||||
header = curl_slist_append(header,
|
||||
versionString.c_str());
|
||||
header = curl_slist_append(header, versionString.c_str());
|
||||
|
||||
if (!contentTypeString.empty()) {
|
||||
header = curl_slist_append(header,
|
||||
|
@ -161,14 +150,11 @@ bool GetRemoteFile(
|
|||
|
||||
curl_easy_setopt(curl.get(), CURLOPT_URL, url);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ACCEPT_ENCODING, "");
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER,
|
||||
header);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER,
|
||||
error_in);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER, header);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER, error_in);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION,
|
||||
string_write);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA,
|
||||
&str);
|
||||
curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA, &str);
|
||||
if (signature) {
|
||||
curl_easy_setopt(curl.get(), CURLOPT_HEADERFUNCTION,
|
||||
header_write);
|
||||
|
|
|
@ -38,8 +38,7 @@ signals:
|
|||
void Result(const QString &text, const QString &error);
|
||||
|
||||
public:
|
||||
inline RemoteTextThread(
|
||||
std::string url_,
|
||||
inline RemoteTextThread(std::string url_,
|
||||
std::string contentType_ = std::string(),
|
||||
std::string postData_ = std::string(),
|
||||
int timeoutSec_ = 0)
|
||||
|
@ -47,10 +46,10 @@ public:
|
|||
contentType(contentType_),
|
||||
postData(postData_),
|
||||
timeoutSec(timeoutSec_)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
inline RemoteTextThread(
|
||||
std::string url_,
|
||||
inline RemoteTextThread(std::string url_,
|
||||
std::vector<std::string> &&extraHeaders_,
|
||||
std::string contentType_ = std::string(),
|
||||
std::string postData_ = std::string(),
|
||||
|
@ -60,16 +59,13 @@ public:
|
|||
postData(postData_),
|
||||
extraHeaders(std::move(extraHeaders_)),
|
||||
timeoutSec(timeoutSec_)
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
bool GetRemoteFile(
|
||||
const char *url,
|
||||
std::string &str,
|
||||
std::string &error,
|
||||
long *responseCode = nullptr,
|
||||
const char *contentType = nullptr,
|
||||
const char *url, std::string &str, std::string &error,
|
||||
long *responseCode = nullptr, const char *contentType = nullptr,
|
||||
const char *postData = nullptr,
|
||||
std::vector<std::string> extraHeaders = std::vector<std::string>(),
|
||||
std::string *signature = nullptr,
|
||||
int timeoutSec = 0);
|
||||
std::string *signature = nullptr, int timeoutSec = 0);
|
||||
|
|
|
@ -10,7 +10,8 @@ SliderAbsoluteSetStyle::SliderAbsoluteSetStyle(QStyle* baseStyle)
|
|||
}
|
||||
|
||||
int SliderAbsoluteSetStyle::styleHint(QStyle::StyleHint hint,
|
||||
const QStyleOption* option = 0, const QWidget* widget = 0,
|
||||
const QStyleOption *option = 0,
|
||||
const QWidget *widget = 0,
|
||||
QStyleHintReturn *returnData = 0) const
|
||||
{
|
||||
if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
#include <QProxyStyle>
|
||||
|
||||
class SliderAbsoluteSetStyle : public QProxyStyle
|
||||
{
|
||||
class SliderAbsoluteSetStyle : public QProxyStyle {
|
||||
public:
|
||||
SliderAbsoluteSetStyle(const QString &baseStyle);
|
||||
SliderAbsoluteSetStyle(QStyle *baseStyle = Q_NULLPTR);
|
||||
int styleHint(QStyle::StyleHint hint, const QStyleOption *option,
|
||||
const QWidget* widget, QStyleHintReturn* returnData) const;
|
||||
const QWidget *widget,
|
||||
QStyleHintReturn *returnData) const;
|
||||
};
|
||||
|
|
|
@ -9,7 +9,8 @@ class SliderIgnoreScroll : public QSlider {
|
|||
|
||||
public:
|
||||
SliderIgnoreScroll(QWidget *parent = nullptr);
|
||||
SliderIgnoreScroll(Qt::Orientation orientation, QWidget *parent = nullptr);
|
||||
SliderIgnoreScroll(Qt::Orientation orientation,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent(QWheelEvent *event) override;
|
||||
|
|
|
@ -38,7 +38,8 @@ public:
|
|||
destroyedSignal(obs_source_get_signal_handler(source),
|
||||
"destroy", &OBSSourceLabel::SourceDestroyed,
|
||||
this)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
static void SourceRenamed(void *data, calldata_t *params);
|
||||
|
|
|
@ -32,8 +32,7 @@ static inline OBSScene GetCurrentScene()
|
|||
/* ========================================================================= */
|
||||
|
||||
SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
|
||||
: tree (tree_),
|
||||
sceneitem (sceneitem_)
|
||||
: tree(tree_), sceneitem(sceneitem_)
|
||||
{
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
setMouseTracking(true);
|
||||
|
@ -98,14 +97,12 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
|
|||
|
||||
/* --------------------------------------------------------- */
|
||||
|
||||
auto setItemVisible = [this] (bool checked)
|
||||
{
|
||||
auto setItemVisible = [this](bool checked) {
|
||||
SignalBlocker sourcesSignalBlocker(this);
|
||||
obs_sceneitem_set_visible(sceneitem, checked);
|
||||
};
|
||||
|
||||
auto setItemLocked = [this] (bool checked)
|
||||
{
|
||||
auto setItemLocked = [this](bool checked) {
|
||||
SignalBlocker sourcesSignalBlocker(this);
|
||||
obs_sceneitem_set_locked(sceneitem, checked);
|
||||
};
|
||||
|
@ -150,15 +147,14 @@ void SourceTreeItem::ReconnectSignals()
|
|||
|
||||
/* --------------------------------------------------------- */
|
||||
|
||||
auto removeItem = [] (void *data, calldata_t *cd)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto removeItem = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
|
||||
if (curItem == this_->sceneitem) {
|
||||
QMetaObject::invokeMethod(this_->tree,
|
||||
"Remove",
|
||||
QMetaObject::invokeMethod(this_->tree, "Remove",
|
||||
Q_ARG(OBSSceneItem, curItem));
|
||||
curItem = nullptr;
|
||||
}
|
||||
|
@ -166,9 +162,9 @@ void SourceTreeItem::ReconnectSignals()
|
|||
QMetaObject::invokeMethod(this_, "Clear");
|
||||
};
|
||||
|
||||
auto itemVisible = [] (void *data, calldata_t *cd)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto itemVisible = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
bool visible = calldata_bool(cd, "visible");
|
||||
|
@ -178,9 +174,9 @@ void SourceTreeItem::ReconnectSignals()
|
|||
Q_ARG(bool, visible));
|
||||
};
|
||||
|
||||
auto itemLocked = [] (void *data, calldata_t *cd)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto itemLocked = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
bool locked = calldata_bool(cd, "locked");
|
||||
|
@ -190,9 +186,9 @@ void SourceTreeItem::ReconnectSignals()
|
|||
Q_ARG(bool, locked));
|
||||
};
|
||||
|
||||
auto itemDeselect = [] (void *data, calldata_t *cd)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto itemDeselect = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(cd, "item");
|
||||
|
||||
|
@ -200,9 +196,9 @@ void SourceTreeItem::ReconnectSignals()
|
|||
QMetaObject::invokeMethod(this_, "Deselect");
|
||||
};
|
||||
|
||||
auto reorderGroup = [] (void *data, calldata_t*)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto reorderGroup = [](void *data, calldata_t *) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
QMetaObject::invokeMethod(this_->tree, "ReorderItems");
|
||||
};
|
||||
|
||||
|
@ -229,18 +225,18 @@ void SourceTreeItem::ReconnectSignals()
|
|||
|
||||
/* --------------------------------------------------------- */
|
||||
|
||||
auto renamed = [] (void *data, calldata_t *cd)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto renamed = [](void *data, calldata_t *cd) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
const char *name = calldata_string(cd, "new_name");
|
||||
|
||||
QMetaObject::invokeMethod(this_, "Renamed",
|
||||
Q_ARG(QString, QT_UTF8(name)));
|
||||
};
|
||||
|
||||
auto removeSource = [] (void *data, calldata_t *)
|
||||
{
|
||||
SourceTreeItem *this_ = reinterpret_cast<SourceTreeItem*>(data);
|
||||
auto removeSource = [](void *data, calldata_t *) {
|
||||
SourceTreeItem *this_ =
|
||||
reinterpret_cast<SourceTreeItem *>(data);
|
||||
this_->DisconnectSignals();
|
||||
this_->sceneitem = nullptr;
|
||||
};
|
||||
|
@ -308,8 +304,7 @@ void SourceTreeItem::ExitEditMode(bool save)
|
|||
return;
|
||||
|
||||
if (newName.empty()) {
|
||||
OBSMessageBox::information(main,
|
||||
QTStr("NoNameEntered.Title"),
|
||||
OBSMessageBox::information(main, QTStr("NoNameEntered.Title"),
|
||||
QTStr("NoNameEntered.Text"));
|
||||
return;
|
||||
}
|
||||
|
@ -324,14 +319,12 @@ void SourceTreeItem::ExitEditMode(bool save)
|
|||
/* ----------------------------------------- */
|
||||
/* check for existing source */
|
||||
|
||||
obs_source_t *existingSource =
|
||||
obs_get_source_by_name(newName.c_str());
|
||||
obs_source_t *existingSource = obs_get_source_by_name(newName.c_str());
|
||||
obs_source_release(existingSource);
|
||||
bool exists = !!existingSource;
|
||||
|
||||
if (exists) {
|
||||
OBSMessageBox::information(main,
|
||||
QTStr("NameExists.Title"),
|
||||
OBSMessageBox::information(main, QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
return;
|
||||
}
|
||||
|
@ -448,8 +441,7 @@ void SourceTreeItem::Update(bool force)
|
|||
|
||||
} else if (type == Type::Group) {
|
||||
expand = new SourceTreeSubItemCheckBox();
|
||||
expand->setSizePolicy(
|
||||
QSizePolicy::Maximum,
|
||||
expand->setSizePolicy(QSizePolicy::Maximum,
|
||||
QSizePolicy::Maximum);
|
||||
expand->setMaximumSize(10, 16);
|
||||
expand->setMinimumSize(10, 0);
|
||||
|
@ -458,14 +450,15 @@ void SourceTreeItem::Update(bool force)
|
|||
#endif
|
||||
boxLayout->insertWidget(0, expand);
|
||||
|
||||
obs_data_t *data = obs_sceneitem_get_private_settings(sceneitem);
|
||||
obs_data_t *data =
|
||||
obs_sceneitem_get_private_settings(sceneitem);
|
||||
expand->blockSignals(true);
|
||||
expand->setChecked(obs_data_get_bool(data, "collapsed"));
|
||||
expand->blockSignals(false);
|
||||
obs_data_release(data);
|
||||
|
||||
connect(expand, &QPushButton::toggled,
|
||||
this, &SourceTreeItem::ExpandClicked);
|
||||
connect(expand, &QPushButton::toggled, this,
|
||||
&SourceTreeItem::ExpandClicked);
|
||||
|
||||
} else {
|
||||
spacer = new QSpacerItem(3, 1);
|
||||
|
@ -556,14 +549,15 @@ void SourceTreeModel::SceneChanged()
|
|||
bool select = obs_sceneitem_selected(items[i]);
|
||||
QModelIndex index = createIndex(i, 0);
|
||||
|
||||
st->selectionModel()->select(index, select
|
||||
? QItemSelectionModel::Select
|
||||
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);
|
||||
|
@ -709,8 +703,7 @@ OBSSceneItem SourceTreeModel::Get(int idx)
|
|||
}
|
||||
|
||||
SourceTreeModel::SourceTreeModel(SourceTree *st_)
|
||||
: QAbstractListModel (st_),
|
||||
st (st_)
|
||||
: QAbstractListModel(st_), st(st_)
|
||||
{
|
||||
obs_frontend_add_event_callback(OBSFrontendEvent, this);
|
||||
}
|
||||
|
@ -744,8 +737,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 |
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsEditable |
|
||||
Qt::ItemIsDragEnabled |
|
||||
(is_group ? Qt::ItemIsDropEnabled : Qt::NoItemFlags);
|
||||
}
|
||||
|
@ -775,8 +767,8 @@ 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;
|
||||
|
||||
|
@ -807,8 +799,7 @@ void SourceTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
|||
}
|
||||
|
||||
obs_sceneitem_t *item = obs_scene_insert_group(
|
||||
scene, QT_TO_UTF8(name),
|
||||
item_order.data(), item_order.size());
|
||||
scene, QT_TO_UTF8(name), item_order.data(), item_order.size());
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
@ -929,20 +920,20 @@ 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=\"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%);}"));
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
UpdateNoSourcesMessage();
|
||||
connect(App(), &OBSApp::StyleChanged,
|
||||
this, &SourceTree::UpdateNoSourcesMessage);
|
||||
connect(App(), &OBSApp::StyleChanged, this,
|
||||
&SourceTree::UpdateNoSourcesMessage);
|
||||
}
|
||||
|
||||
void SourceTree::ResetWidgets()
|
||||
|
@ -994,8 +985,8 @@ void SourceTree::SelectItem(obs_sceneitem_t *sceneitem, bool select)
|
|||
|
||||
QModelIndex index = stm->createIndex(i, 0);
|
||||
if (index.isValid())
|
||||
selectionModel()->select(index, select
|
||||
? QItemSelectionModel::Select
|
||||
selectionModel()->select(
|
||||
index, select ? QItemSelectionModel::Select
|
||||
: QItemSelectionModel::Deselect);
|
||||
}
|
||||
|
||||
|
@ -1040,8 +1031,8 @@ 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_t *dropGroup =
|
||||
itemIsGroup ? dropItem
|
||||
: obs_sceneitem_get_group(scene, dropItem);
|
||||
|
||||
/* not a group if moving above the group */
|
||||
|
@ -1056,7 +1047,8 @@ 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);
|
||||
}
|
||||
|
@ -1086,9 +1078,8 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
/* if dropping a group, detect if it's */
|
||||
/* below another group */
|
||||
|
||||
obs_sceneitem_t *itemBelow = row == stm->items.count()
|
||||
? nullptr
|
||||
: stm->items[row];
|
||||
obs_sceneitem_t *itemBelow =
|
||||
row == stm->items.count() ? nullptr : stm->items[row];
|
||||
if (hasGroups) {
|
||||
if (!itemBelow ||
|
||||
obs_sceneitem_get_group(scene, itemBelow) != dropGroup) {
|
||||
|
@ -1131,8 +1122,8 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
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_get_group(
|
||||
scene, subitem);
|
||||
|
||||
if (subitemGroup == item) {
|
||||
QModelIndex idx =
|
||||
|
@ -1186,8 +1177,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
obs_sceneitem_t *lastGroup = nullptr;
|
||||
int insertCollapsedIdx = 0;
|
||||
|
||||
auto insertCollapsed = [&] (obs_sceneitem_t *item)
|
||||
{
|
||||
auto insertCollapsed = [&](obs_sceneitem_t *item) {
|
||||
struct obs_sceneitem_order_info info;
|
||||
info.group = lastGroup;
|
||||
info.item = item;
|
||||
|
@ -1198,22 +1188,20 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
using insertCollapsed_t = decltype(insertCollapsed);
|
||||
|
||||
auto preInsertCollapsed = [](obs_scene_t *, obs_sceneitem_t *item,
|
||||
void *param)
|
||||
{
|
||||
void *param) {
|
||||
(*reinterpret_cast<insertCollapsed_t *>(param))(item);
|
||||
return true;
|
||||
};
|
||||
|
||||
auto insertLastGroup = [&] ()
|
||||
{
|
||||
obs_data_t *data = obs_sceneitem_get_private_settings(lastGroup);
|
||||
auto insertLastGroup = [&]() {
|
||||
obs_data_t *data =
|
||||
obs_sceneitem_get_private_settings(lastGroup);
|
||||
bool collapsed = obs_data_get_bool(data, "collapsed");
|
||||
obs_data_release(data);
|
||||
|
||||
if (collapsed) {
|
||||
insertCollapsedIdx = 0;
|
||||
obs_sceneitem_group_enum_items(
|
||||
lastGroup,
|
||||
obs_sceneitem_group_enum_items(lastGroup,
|
||||
preInsertCollapsed,
|
||||
&insertCollapsed);
|
||||
}
|
||||
|
@ -1224,8 +1212,7 @@ void SourceTree::dropEvent(QDropEvent *event)
|
|||
orderList.insert(0, info);
|
||||
};
|
||||
|
||||
auto updateScene = [&] ()
|
||||
{
|
||||
auto updateScene = [&]() {
|
||||
struct obs_sceneitem_order_info info;
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
|
@ -1260,14 +1247,13 @@ 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);
|
||||
|
||||
auto preUpdateScene = [] (void *data, obs_scene_t *)
|
||||
{
|
||||
auto preUpdateScene = [](void *data, obs_scene_t *) {
|
||||
(*reinterpret_cast<updateScene_t *>(data))();
|
||||
};
|
||||
|
||||
|
@ -1314,8 +1300,7 @@ void SourceTree::leaveEvent(QEvent *event)
|
|||
QListView::leaveEvent(event);
|
||||
}
|
||||
|
||||
void SourceTree::selectionChanged(
|
||||
const QItemSelection &selected,
|
||||
void SourceTree::selectionChanged(const QItemSelection &selected,
|
||||
const QItemSelection &deselected)
|
||||
{
|
||||
{
|
||||
|
@ -1465,8 +1450,7 @@ void SourceTree::UpdateNoSourcesMessage()
|
|||
|
||||
QColor color = palette().text().color();
|
||||
bool lightTheme = (color.redF() < 0.5);
|
||||
QString file = lightTheme
|
||||
? ":res/images/no_sources.svg"
|
||||
QString file = lightTheme ? ":res/images/no_sources.svg"
|
||||
: darkPath.c_str();
|
||||
iconNoSources.load(file);
|
||||
|
||||
|
|
|
@ -123,7 +123,8 @@ public:
|
|||
~SourceTreeModel();
|
||||
|
||||
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;
|
||||
|
@ -189,5 +190,7 @@ protected:
|
|||
virtual void leaveEvent(QEvent *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;
|
||||
};
|
||||
|
|
|
@ -8,8 +8,7 @@ class VScrollArea : public QScrollArea {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
inline VScrollArea(QWidget *parent = nullptr)
|
||||
: QScrollArea(parent)
|
||||
inline VScrollArea(QWidget *parent = nullptr) : QScrollArea(parent)
|
||||
{
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
|
|
@ -38,8 +38,8 @@ VisibilityItemWidget::VisibilityItemWidget(obs_source_t *source_)
|
|||
setLayout(itemLayout);
|
||||
setStyleSheet("background-color: rgba(255, 255, 255, 0);");
|
||||
|
||||
connect(vis, SIGNAL(clicked(bool)),
|
||||
this, SLOT(VisibilityClicked(bool)));
|
||||
connect(vis, SIGNAL(clicked(bool)), this,
|
||||
SLOT(VisibilityClicked(bool)));
|
||||
}
|
||||
|
||||
VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
|
||||
|
@ -90,18 +90,15 @@ VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
|
|||
|
||||
signal_handler_t *signal = obs_source_get_signal_handler(sceneSource);
|
||||
signal_handler_connect(signal, "remove", OBSSceneRemove, this);
|
||||
signal_handler_connect(signal, "item_remove", OBSSceneItemRemove,
|
||||
this);
|
||||
signal_handler_connect(signal, "item_remove", OBSSceneItemRemove, this);
|
||||
signal_handler_connect(signal, "item_visible", OBSSceneItemVisible,
|
||||
this);
|
||||
signal_handler_connect(signal, "item_locked", OBSSceneItemLocked,
|
||||
this);
|
||||
signal_handler_connect(signal, "item_locked", OBSSceneItemLocked, this);
|
||||
|
||||
connect(vis, SIGNAL(clicked(bool)),
|
||||
this, SLOT(VisibilityClicked(bool)));
|
||||
connect(vis, SIGNAL(clicked(bool)), this,
|
||||
SLOT(VisibilityClicked(bool)));
|
||||
|
||||
connect(lock, SIGNAL(clicked(bool)),
|
||||
this, SLOT(LockClicked(bool)));
|
||||
connect(lock, SIGNAL(clicked(bool)), this, SLOT(LockClicked(bool)));
|
||||
}
|
||||
|
||||
VisibilityItemWidget::~VisibilityItemWidget()
|
||||
|
@ -153,7 +150,8 @@ void VisibilityItemWidget::OBSSceneItemVisible(void *param, calldata_t *data)
|
|||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget *>(param);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t*)calldata_ptr(data, "item");
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
bool enabled = calldata_bool(data, "visible");
|
||||
|
||||
if (window->item == curItem)
|
||||
|
@ -165,7 +163,8 @@ void VisibilityItemWidget::OBSSceneItemLocked(void *param, calldata_t *data)
|
|||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget *>(param);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t*)calldata_ptr(data, "item");
|
||||
obs_sceneitem_t *curItem =
|
||||
(obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
bool locked = calldata_bool(data, "locked");
|
||||
|
||||
if (window->item == curItem)
|
||||
|
@ -225,8 +224,8 @@ void VisibilityItemWidget::SourceRenamed(QString name)
|
|||
label->setText(name);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SetColor(const QColor &color,
|
||||
bool active_, bool selected_)
|
||||
void VisibilityItemWidget::SetColor(const QColor &color, bool active_,
|
||||
bool selected_)
|
||||
{
|
||||
/* Do not update unless the state has actually changed */
|
||||
if (active_ == active && selected_ == selected)
|
||||
|
@ -269,8 +268,8 @@ void VisibilityItemDelegate::paint(QPainter *painter,
|
|||
|
||||
QPalette palette = list->palette();
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
QPalette::ColorGroup group = active ?
|
||||
QPalette::Active : QPalette::Inactive;
|
||||
QPalette::ColorGroup group = active ? QPalette::Active
|
||||
: QPalette::Inactive;
|
||||
#else
|
||||
QPalette::ColorGroup group = QPalette::Active;
|
||||
#endif
|
||||
|
|
|
@ -48,8 +48,8 @@ void VolControl::OBSVolumeMuted(void *data, calldata_t *calldata)
|
|||
void VolControl::VolumeChanged()
|
||||
{
|
||||
slider->blockSignals(true);
|
||||
slider->setValue((int) (obs_fader_get_deflection(obs_fader) *
|
||||
FADER_PRECISION));
|
||||
slider->setValue(
|
||||
(int)(obs_fader_get_deflection(obs_fader) * FADER_PRECISION));
|
||||
slider->blockSignals(false);
|
||||
|
||||
updateText();
|
||||
|
@ -79,8 +79,7 @@ void VolControl::updateText()
|
|||
volLabel->setText(db);
|
||||
|
||||
bool muted = obs_source_muted(source);
|
||||
const char *accTextLookup = muted
|
||||
? "VolControl.SliderMuted"
|
||||
const char *accTextLookup = muted ? "VolControl.SliderMuted"
|
||||
: "VolControl.SliderUnmuted";
|
||||
|
||||
QString sourceName = obs_source_get_name(source);
|
||||
|
@ -138,11 +137,11 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
|
|||
config->setMaximumSize(22, 22);
|
||||
config->setAutoDefault(false);
|
||||
|
||||
config->setAccessibleName(QTStr("VolControl.Properties")
|
||||
.arg(sourceName));
|
||||
config->setAccessibleName(
|
||||
QTStr("VolControl.Properties").arg(sourceName));
|
||||
|
||||
connect(config, &QAbstractButton::clicked,
|
||||
this, &VolControl::EmitConfigClicked);
|
||||
connect(config, &QAbstractButton::clicked, this,
|
||||
&VolControl::EmitConfigClicked);
|
||||
}
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
|
@ -244,13 +243,13 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
|
|||
obs_fader_add_callback(obs_fader, OBSVolumeChanged, this);
|
||||
obs_volmeter_add_callback(obs_volmeter, OBSVolumeLevel, this);
|
||||
|
||||
signal_handler_connect(obs_source_get_signal_handler(source),
|
||||
"mute", OBSVolumeMuted, this);
|
||||
signal_handler_connect(obs_source_get_signal_handler(source), "mute",
|
||||
OBSVolumeMuted, this);
|
||||
|
||||
QWidget::connect(slider, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(SliderChanged(int)));
|
||||
QWidget::connect(mute, SIGNAL(clicked(bool)),
|
||||
this, SLOT(SetMuted(bool)));
|
||||
QWidget::connect(slider, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(SliderChanged(int)));
|
||||
QWidget::connect(mute, SIGNAL(clicked(bool)), this,
|
||||
SLOT(SetMuted(bool)));
|
||||
|
||||
obs_fader_attach_source(obs_fader, source);
|
||||
obs_volmeter_attach_source(obs_volmeter, source);
|
||||
|
@ -276,8 +275,8 @@ VolControl::~VolControl()
|
|||
obs_fader_remove_callback(obs_fader, OBSVolumeChanged, this);
|
||||
obs_volmeter_remove_callback(obs_volmeter, OBSVolumeLevel, this);
|
||||
|
||||
signal_handler_disconnect(obs_source_get_signal_handler(source),
|
||||
"mute", OBSVolumeMuted, this);
|
||||
signal_handler_disconnect(obs_source_get_signal_handler(source), "mute",
|
||||
OBSVolumeMuted, this);
|
||||
|
||||
obs_fader_destroy(obs_fader);
|
||||
obs_volmeter_destroy(obs_volmeter);
|
||||
|
@ -518,8 +517,7 @@ void VolumeMeter::wheelEvent(QWheelEvent *event)
|
|||
|
||||
VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
|
||||
bool vertical)
|
||||
: QWidget(parent), obs_volmeter(obs_volmeter),
|
||||
vertical(vertical)
|
||||
: QWidget(parent), obs_volmeter(obs_volmeter), vertical(vertical)
|
||||
{
|
||||
// Use a font that can be rendered small.
|
||||
tickFont = QFont("Arial");
|
||||
|
@ -632,8 +630,9 @@ inline bool VolumeMeter::detectIdle(uint64_t ts)
|
|||
}
|
||||
}
|
||||
|
||||
inline void VolumeMeter::calculateBallisticsForChannel(int channelNr,
|
||||
uint64_t ts, qreal timeSinceLastRedraw)
|
||||
inline void
|
||||
VolumeMeter::calculateBallisticsForChannel(int channelNr, uint64_t ts,
|
||||
qreal timeSinceLastRedraw)
|
||||
{
|
||||
if (currentPeak[channelNr] >= displayPeak[channelNr] ||
|
||||
isnan(displayPeak[channelNr])) {
|
||||
|
@ -657,8 +656,10 @@ inline void VolumeMeter::calculateBallisticsForChannel(int channelNr,
|
|||
} else {
|
||||
// The peak and hold falls back to peak
|
||||
// after 20 seconds.
|
||||
qreal timeSinceLastPeak = (uint64_t)(ts -
|
||||
displayPeakHoldLastUpdateTime[channelNr]) * 0.000000001;
|
||||
qreal timeSinceLastPeak =
|
||||
(uint64_t)(ts -
|
||||
displayPeakHoldLastUpdateTime[channelNr]) *
|
||||
0.000000001;
|
||||
if (timeSinceLastPeak > peakHoldDuration) {
|
||||
displayPeakHold[channelNr] = currentPeak[channelNr];
|
||||
displayPeakHoldLastUpdateTime[channelNr] = ts;
|
||||
|
@ -673,14 +674,15 @@ inline void VolumeMeter::calculateBallisticsForChannel(int channelNr,
|
|||
displayInputPeakHoldLastUpdateTime[channelNr] = ts;
|
||||
} else {
|
||||
// The peak and hold falls back to peak after 1 second.
|
||||
qreal timeSinceLastPeak = (uint64_t)(ts -
|
||||
qreal timeSinceLastPeak =
|
||||
(uint64_t)(
|
||||
ts -
|
||||
displayInputPeakHoldLastUpdateTime[channelNr]) *
|
||||
0.000000001;
|
||||
if (timeSinceLastPeak > inputPeakHoldDuration) {
|
||||
displayInputPeakHold[channelNr] =
|
||||
currentInputPeak[channelNr];
|
||||
displayInputPeakHoldLastUpdateTime[channelNr] =
|
||||
ts;
|
||||
displayInputPeakHoldLastUpdateTime[channelNr] = ts;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -692,12 +694,14 @@ inline void VolumeMeter::calculateBallisticsForChannel(int channelNr,
|
|||
// A VU meter will integrate to the new value to 99% in 300 ms.
|
||||
// The calculation here is very simplified and is more accurate
|
||||
// with higher frame-rate.
|
||||
float attack = float((currentMagnitude[channelNr] -
|
||||
float attack =
|
||||
float((currentMagnitude[channelNr] -
|
||||
displayMagnitude[channelNr]) *
|
||||
(timeSinceLastRedraw /
|
||||
magnitudeIntegrationTime) * 0.99);
|
||||
displayMagnitude[channelNr] = CLAMP(displayMagnitude[channelNr]
|
||||
+ attack, (float)minimumLevel, 0);
|
||||
(timeSinceLastRedraw / magnitudeIntegrationTime) *
|
||||
0.99);
|
||||
displayMagnitude[channelNr] =
|
||||
CLAMP(displayMagnitude[channelNr] + attack,
|
||||
(float)minimumLevel, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -798,7 +802,8 @@ void VolumeMeter::ClipEnding()
|
|||
}
|
||||
|
||||
void VolumeMeter::paintHMeter(QPainter &painter, int x, int y, int width,
|
||||
int height, float magnitude, float peak, float peakHold)
|
||||
int height, float magnitude, float peak,
|
||||
float peakHold)
|
||||
{
|
||||
qreal scale = width / minimumLevel;
|
||||
|
||||
|
@ -828,11 +833,12 @@ void VolumeMeter::paintHMeter(QPainter &painter, int x, int y, int width,
|
|||
painter.fillRect(errorPosition, y, errorLength, height,
|
||||
backgroundErrorColor);
|
||||
} else if (peakPosition < warningPosition) {
|
||||
painter.fillRect(minimumPosition, y, peakPosition -
|
||||
minimumPosition, height,
|
||||
painter.fillRect(minimumPosition, y,
|
||||
peakPosition - minimumPosition, height,
|
||||
foregroundNominalColor);
|
||||
painter.fillRect(peakPosition, y, warningPosition -
|
||||
peakPosition, height, backgroundNominalColor);
|
||||
painter.fillRect(peakPosition, y,
|
||||
warningPosition - peakPosition, height,
|
||||
backgroundNominalColor);
|
||||
painter.fillRect(warningPosition, y, warningLength, height,
|
||||
backgroundWarningColor);
|
||||
painter.fillRect(errorPosition, y, errorLength, height,
|
||||
|
@ -843,8 +849,8 @@ void VolumeMeter::paintHMeter(QPainter &painter, int x, int y, int width,
|
|||
painter.fillRect(warningPosition, y,
|
||||
peakPosition - warningPosition, height,
|
||||
foregroundWarningColor);
|
||||
painter.fillRect(peakPosition, y, errorPosition -
|
||||
peakPosition, height, backgroundWarningColor);
|
||||
painter.fillRect(peakPosition, y, errorPosition - peakPosition,
|
||||
height, backgroundWarningColor);
|
||||
painter.fillRect(errorPosition, y, errorLength, height,
|
||||
backgroundErrorColor);
|
||||
} else if (peakPosition < maximumPosition) {
|
||||
|
@ -887,7 +893,8 @@ void VolumeMeter::paintHMeter(QPainter &painter, int x, int y, int width,
|
|||
}
|
||||
|
||||
void VolumeMeter::paintVMeter(QPainter &painter, int x, int y, int width,
|
||||
int height, float magnitude, float peak, float peakHold)
|
||||
int height, float magnitude, float peak,
|
||||
float peakHold)
|
||||
{
|
||||
qreal scale = height / minimumLevel;
|
||||
|
||||
|
@ -917,10 +924,12 @@ void VolumeMeter::paintVMeter(QPainter &painter, int x, int y, int width,
|
|||
painter.fillRect(x, errorPosition, width, errorLength,
|
||||
backgroundErrorColor);
|
||||
} else if (peakPosition < warningPosition) {
|
||||
painter.fillRect(x, minimumPosition, width, peakPosition -
|
||||
minimumPosition, foregroundNominalColor);
|
||||
painter.fillRect(x, peakPosition, width, warningPosition -
|
||||
peakPosition, backgroundNominalColor);
|
||||
painter.fillRect(x, minimumPosition, width,
|
||||
peakPosition - minimumPosition,
|
||||
foregroundNominalColor);
|
||||
painter.fillRect(x, peakPosition, width,
|
||||
warningPosition - peakPosition,
|
||||
backgroundNominalColor);
|
||||
painter.fillRect(x, warningPosition, width, warningLength,
|
||||
backgroundWarningColor);
|
||||
painter.fillRect(x, errorPosition, width, errorLength,
|
||||
|
@ -928,10 +937,12 @@ void VolumeMeter::paintVMeter(QPainter &painter, int x, int y, int width,
|
|||
} else if (peakPosition < errorPosition) {
|
||||
painter.fillRect(x, minimumPosition, width, nominalLength,
|
||||
foregroundNominalColor);
|
||||
painter.fillRect(x, warningPosition, width, peakPosition -
|
||||
warningPosition, foregroundWarningColor);
|
||||
painter.fillRect(x, peakPosition, width, errorPosition -
|
||||
peakPosition, backgroundWarningColor);
|
||||
painter.fillRect(x, warningPosition, width,
|
||||
peakPosition - warningPosition,
|
||||
foregroundWarningColor);
|
||||
painter.fillRect(x, peakPosition, width,
|
||||
errorPosition - peakPosition,
|
||||
backgroundWarningColor);
|
||||
painter.fillRect(x, errorPosition, width, errorLength,
|
||||
backgroundErrorColor);
|
||||
} else if (peakPosition < maximumPosition) {
|
||||
|
@ -939,10 +950,12 @@ void VolumeMeter::paintVMeter(QPainter &painter, int x, int y, int width,
|
|||
foregroundNominalColor);
|
||||
painter.fillRect(x, warningPosition, width, warningLength,
|
||||
foregroundWarningColor);
|
||||
painter.fillRect(x, errorPosition, width, peakPosition -
|
||||
errorPosition, foregroundErrorColor);
|
||||
painter.fillRect(x, peakPosition, width, maximumPosition -
|
||||
peakPosition, backgroundErrorColor);
|
||||
painter.fillRect(x, errorPosition, width,
|
||||
peakPosition - errorPosition,
|
||||
foregroundErrorColor);
|
||||
painter.fillRect(x, peakPosition, width,
|
||||
maximumPosition - peakPosition,
|
||||
backgroundErrorColor);
|
||||
} else {
|
||||
if (!clipping) {
|
||||
QTimer::singleShot(CLIP_FLASH_DURATION_MS, this,
|
||||
|
@ -1028,8 +1041,8 @@ void VolumeMeter::paintEvent(QPaintEvent *event)
|
|||
for (int channelNr = 0; channelNr < displayNrAudioChannels;
|
||||
channelNr++) {
|
||||
|
||||
int channelNrFixed = (displayNrAudioChannels == 1 &&
|
||||
channels > 2)
|
||||
int channelNrFixed =
|
||||
(displayNrAudioChannels == 1 && channels > 2)
|
||||
? 2
|
||||
: channelNr;
|
||||
|
||||
|
|
|
@ -11,73 +11,54 @@
|
|||
class QPushButton;
|
||||
class VolumeMeterTimer;
|
||||
|
||||
class VolumeMeter : public QWidget
|
||||
{
|
||||
class VolumeMeter : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QColor backgroundNominalColor
|
||||
READ getBackgroundNominalColor
|
||||
Q_PROPERTY(QColor backgroundNominalColor READ getBackgroundNominalColor
|
||||
WRITE setBackgroundNominalColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor backgroundWarningColor
|
||||
READ getBackgroundWarningColor
|
||||
Q_PROPERTY(QColor backgroundWarningColor READ getBackgroundWarningColor
|
||||
WRITE setBackgroundWarningColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor backgroundErrorColor
|
||||
READ getBackgroundErrorColor
|
||||
Q_PROPERTY(QColor backgroundErrorColor READ getBackgroundErrorColor
|
||||
WRITE setBackgroundErrorColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor foregroundNominalColor
|
||||
READ getForegroundNominalColor
|
||||
Q_PROPERTY(QColor foregroundNominalColor READ getForegroundNominalColor
|
||||
WRITE setForegroundNominalColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor foregroundWarningColor
|
||||
READ getForegroundWarningColor
|
||||
Q_PROPERTY(QColor foregroundWarningColor READ getForegroundWarningColor
|
||||
WRITE setForegroundWarningColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor foregroundErrorColor
|
||||
READ getForegroundErrorColor
|
||||
Q_PROPERTY(QColor foregroundErrorColor READ getForegroundErrorColor
|
||||
WRITE setForegroundErrorColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor clipColor
|
||||
READ getClipColor
|
||||
WRITE setClipColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor magnitudeColor
|
||||
READ getMagnitudeColor
|
||||
WRITE setMagnitudeColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor majorTickColor
|
||||
READ getMajorTickColor
|
||||
WRITE setMajorTickColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor minorTickColor
|
||||
READ getMinorTickColor
|
||||
WRITE setMinorTickColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor clipColor READ getClipColor WRITE setClipColor
|
||||
DESIGNABLE true)
|
||||
Q_PROPERTY(QColor magnitudeColor READ getMagnitudeColor WRITE
|
||||
setMagnitudeColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor majorTickColor READ getMajorTickColor WRITE
|
||||
setMajorTickColor DESIGNABLE true)
|
||||
Q_PROPERTY(QColor minorTickColor READ getMinorTickColor WRITE
|
||||
setMinorTickColor DESIGNABLE true)
|
||||
|
||||
// Levels are denoted in dBFS.
|
||||
Q_PROPERTY(qreal minimumLevel
|
||||
READ getMinimumLevel
|
||||
WRITE setMinimumLevel DESIGNABLE true)
|
||||
Q_PROPERTY(qreal warningLevel
|
||||
READ getWarningLevel
|
||||
WRITE setWarningLevel DESIGNABLE true)
|
||||
Q_PROPERTY(qreal errorLevel
|
||||
READ getErrorLevel
|
||||
WRITE setErrorLevel DESIGNABLE true)
|
||||
Q_PROPERTY(qreal clipLevel
|
||||
READ getClipLevel
|
||||
WRITE setClipLevel DESIGNABLE true)
|
||||
Q_PROPERTY(qreal minimumInputLevel
|
||||
READ getMinimumInputLevel
|
||||
WRITE setMinimumInputLevel DESIGNABLE true)
|
||||
Q_PROPERTY(qreal minimumLevel READ getMinimumLevel WRITE setMinimumLevel
|
||||
DESIGNABLE true)
|
||||
Q_PROPERTY(qreal warningLevel READ getWarningLevel WRITE setWarningLevel
|
||||
DESIGNABLE true)
|
||||
Q_PROPERTY(qreal errorLevel READ getErrorLevel WRITE setErrorLevel
|
||||
DESIGNABLE true)
|
||||
Q_PROPERTY(qreal clipLevel READ getClipLevel WRITE setClipLevel
|
||||
DESIGNABLE true)
|
||||
Q_PROPERTY(qreal minimumInputLevel READ getMinimumInputLevel WRITE
|
||||
setMinimumInputLevel DESIGNABLE true)
|
||||
|
||||
// Rates are denoted in dB/second.
|
||||
Q_PROPERTY(qreal peakDecayRate
|
||||
READ getPeakDecayRate
|
||||
WRITE setPeakDecayRate DESIGNABLE true)
|
||||
Q_PROPERTY(qreal peakDecayRate READ getPeakDecayRate WRITE
|
||||
setPeakDecayRate DESIGNABLE true)
|
||||
|
||||
// Time in seconds for the VU meter to integrate over.
|
||||
Q_PROPERTY(qreal magnitudeIntegrationTime
|
||||
READ getMagnitudeIntegrationTime
|
||||
Q_PROPERTY(
|
||||
qreal magnitudeIntegrationTime READ getMagnitudeIntegrationTime
|
||||
WRITE setMagnitudeIntegrationTime DESIGNABLE true)
|
||||
|
||||
// Duration is denoted in seconds.
|
||||
Q_PROPERTY(qreal peakHoldDuration
|
||||
READ getPeakHoldDuration
|
||||
WRITE setPeakHoldDuration DESIGNABLE true)
|
||||
Q_PROPERTY(qreal inputPeakHoldDuration
|
||||
READ getInputPeakHoldDuration
|
||||
Q_PROPERTY(qreal peakHoldDuration READ getPeakHoldDuration WRITE
|
||||
setPeakHoldDuration DESIGNABLE true)
|
||||
Q_PROPERTY(qreal inputPeakHoldDuration READ getInputPeakHoldDuration
|
||||
WRITE setInputPeakHoldDuration DESIGNABLE true)
|
||||
|
||||
private slots:
|
||||
|
@ -93,8 +74,8 @@ private:
|
|||
inline bool detectIdle(uint64_t ts);
|
||||
inline void calculateBallistics(uint64_t ts,
|
||||
qreal timeSinceLastRedraw = 0.0);
|
||||
inline void calculateBallisticsForChannel(int channelNr,
|
||||
uint64_t ts, qreal timeSinceLastRedraw);
|
||||
inline void calculateBallisticsForChannel(int channelNr, uint64_t ts,
|
||||
qreal timeSinceLastRedraw);
|
||||
|
||||
void paintInputMeter(QPainter &painter, int x, int y, int width,
|
||||
int height, float peakHold);
|
||||
|
@ -154,8 +135,7 @@ public:
|
|||
bool vertical = false);
|
||||
~VolumeMeter();
|
||||
|
||||
void setLevels(
|
||||
const float magnitude[MAX_AUDIO_CHANNELS],
|
||||
void setLevels(const float magnitude[MAX_AUDIO_CHANNELS],
|
||||
const float peak[MAX_AUDIO_CHANNELS],
|
||||
const float inputPeak[MAX_AUDIO_CHANNELS]);
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
#include "obs-app.hpp"
|
||||
|
||||
OBSUpdate::OBSUpdate(QWidget *parent, bool manualUpdate, const QString &text)
|
||||
: QDialog (parent, Qt::WindowSystemMenuHint |
|
||||
Qt::WindowTitleHint |
|
||||
: QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint |
|
||||
Qt::WindowCloseButtonHint),
|
||||
ui(new Ui_OBSUpdate)
|
||||
{
|
||||
|
|
|
@ -9,11 +9,7 @@ class OBSUpdate : public QDialog {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum ReturnVal {
|
||||
No,
|
||||
Yes,
|
||||
Skip
|
||||
};
|
||||
enum ReturnVal { No, Yes, Skip };
|
||||
|
||||
OBSUpdate(QWidget *parent, bool manualUpdate, const QString &text);
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static bool ReadZippedHTTPData(string &responseBuf, z_stream *strm,
|
||||
string &zipBuf, const uint8_t *buffer, DWORD outSize)
|
||||
string &zipBuf, const uint8_t *buffer,
|
||||
DWORD outSize)
|
||||
{
|
||||
strm->avail_in = outSize;
|
||||
strm->next_in = buffer;
|
||||
|
@ -85,11 +86,8 @@ static bool ReadHTTPData(string &responseBuf, const uint8_t *buffer,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool HTTPPostData(const wchar_t *url,
|
||||
const BYTE * data,
|
||||
int dataLen,
|
||||
const wchar_t *extraHeaders,
|
||||
int * responseCode,
|
||||
bool HTTPPostData(const wchar_t *url, const BYTE *data, int dataLen,
|
||||
const wchar_t *extraHeaders, int *responseCode,
|
||||
string &responseBuf)
|
||||
{
|
||||
HttpHandle hSession;
|
||||
|
@ -129,8 +127,7 @@ bool HTTPPostData(const wchar_t *url,
|
|||
|
||||
hSession = WinHttpOpen(L"OBS Studio Updater/2.1",
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
if (!hSession) {
|
||||
*responseCode = -1;
|
||||
|
@ -141,9 +138,9 @@ bool HTTPPostData(const wchar_t *url,
|
|||
(LPVOID)&tlsProtocols, sizeof(tlsProtocols));
|
||||
|
||||
hConnect = WinHttpConnect(hSession, hostName,
|
||||
secure
|
||||
? INTERNET_DEFAULT_HTTPS_PORT
|
||||
: INTERNET_DEFAULT_HTTP_PORT, 0);
|
||||
secure ? INTERNET_DEFAULT_HTTPS_PORT
|
||||
: INTERNET_DEFAULT_HTTP_PORT,
|
||||
0);
|
||||
if (!hConnect) {
|
||||
*responseCode = -2;
|
||||
return false;
|
||||
|
@ -152,14 +149,9 @@ bool HTTPPostData(const wchar_t *url,
|
|||
/* -------------------------------------- *
|
||||
* request data */
|
||||
|
||||
hRequest = WinHttpOpenRequest(hConnect,
|
||||
L"POST",
|
||||
path,
|
||||
nullptr,
|
||||
WINHTTP_NO_REFERER,
|
||||
acceptTypes,
|
||||
secure
|
||||
? WINHTTP_FLAG_SECURE |
|
||||
hRequest = WinHttpOpenRequest(hConnect, L"POST", path, nullptr,
|
||||
WINHTTP_NO_REFERER, acceptTypes,
|
||||
secure ? WINHTTP_FLAG_SECURE |
|
||||
WINHTTP_FLAG_REFRESH
|
||||
: WINHTTP_FLAG_REFRESH);
|
||||
if (!hRequest) {
|
||||
|
@ -191,12 +183,9 @@ bool HTTPPostData(const wchar_t *url,
|
|||
DWORD statusCodeLen;
|
||||
|
||||
statusCodeLen = sizeof(statusCode);
|
||||
if (!WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
&statusCode,
|
||||
&statusCodeLen,
|
||||
WINHTTP_NO_HEADER_INDEX)) {
|
||||
if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX, &statusCode,
|
||||
&statusCodeLen, WINHTTP_NO_HEADER_INDEX)) {
|
||||
*responseCode = -4;
|
||||
return false;
|
||||
} else {
|
||||
|
@ -204,12 +193,9 @@ bool HTTPPostData(const wchar_t *url,
|
|||
}
|
||||
|
||||
encodingLen = sizeof(encoding);
|
||||
if (!WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_CONTENT_ENCODING,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
encoding,
|
||||
&encodingLen,
|
||||
WINHTTP_NO_HEADER_INDEX)) {
|
||||
if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_ENCODING,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX, encoding,
|
||||
&encodingLen, WINHTTP_NO_HEADER_INDEX)) {
|
||||
encoding[0] = 0;
|
||||
if (GetLastError() != ERROR_WINHTTP_HEADER_NOT_FOUND) {
|
||||
*responseCode = -5;
|
||||
|
@ -311,8 +297,8 @@ bool HTTPPostData(const wchar_t *url,
|
|||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static bool ReadHTTPZippedFile(z_stream *strm, HANDLE updateFile,
|
||||
string &zipBuf, const uint8_t *buffer, DWORD outSize,
|
||||
int *responseCode)
|
||||
string &zipBuf, const uint8_t *buffer,
|
||||
DWORD outSize, int *responseCode)
|
||||
{
|
||||
strm->avail_in = outSize;
|
||||
strm->next_in = buffer;
|
||||
|
@ -326,10 +312,8 @@ static bool ReadHTTPZippedFile(z_stream *strm, HANDLE updateFile,
|
|||
return false;
|
||||
|
||||
DWORD written;
|
||||
if (!WriteFile(updateFile,
|
||||
zipBuf.data(),
|
||||
MAX_BUF_SIZE - strm->avail_out,
|
||||
&written,
|
||||
if (!WriteFile(updateFile, zipBuf.data(),
|
||||
MAX_BUF_SIZE - strm->avail_out, &written,
|
||||
nullptr)) {
|
||||
*responseCode = -10;
|
||||
return false;
|
||||
|
@ -363,10 +347,8 @@ static bool ReadHTTPFile(HANDLE updateFile, const uint8_t *buffer,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool HTTPGetFile(HINTERNET hConnect,
|
||||
const wchar_t *url,
|
||||
const wchar_t *outputPath,
|
||||
const wchar_t *extraHeaders,
|
||||
bool HTTPGetFile(HINTERNET hConnect, const wchar_t *url,
|
||||
const wchar_t *outputPath, const wchar_t *extraHeaders,
|
||||
int *responseCode)
|
||||
{
|
||||
HttpHandle hRequest;
|
||||
|
@ -399,14 +381,9 @@ bool HTTPGetFile(HINTERNET hConnect,
|
|||
/* -------------------------------------- *
|
||||
* request data */
|
||||
|
||||
hRequest = WinHttpOpenRequest(hConnect,
|
||||
L"GET",
|
||||
path,
|
||||
nullptr,
|
||||
WINHTTP_NO_REFERER,
|
||||
acceptTypes,
|
||||
secure
|
||||
? WINHTTP_FLAG_SECURE |
|
||||
hRequest = WinHttpOpenRequest(hConnect, L"GET", path, nullptr,
|
||||
WINHTTP_NO_REFERER, acceptTypes,
|
||||
secure ? WINHTTP_FLAG_SECURE |
|
||||
WINHTTP_FLAG_REFRESH
|
||||
: WINHTTP_FLAG_REFRESH);
|
||||
if (!hRequest) {
|
||||
|
@ -415,7 +392,8 @@ bool HTTPGetFile(HINTERNET hConnect,
|
|||
}
|
||||
|
||||
bool bResults = !!WinHttpSendRequest(hRequest, extraHeaders,
|
||||
extraHeaders ? -1 : 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
|
||||
extraHeaders ? -1 : 0,
|
||||
WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
|
||||
|
||||
/* -------------------------------------- *
|
||||
* end request */
|
||||
|
@ -437,12 +415,9 @@ bool HTTPGetFile(HINTERNET hConnect,
|
|||
DWORD statusCodeLen;
|
||||
|
||||
statusCodeLen = sizeof(statusCode);
|
||||
if (!WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_STATUS_CODE,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
&statusCode,
|
||||
&statusCodeLen,
|
||||
WINHTTP_NO_HEADER_INDEX)) {
|
||||
if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX, &statusCode,
|
||||
&statusCodeLen, WINHTTP_NO_HEADER_INDEX)) {
|
||||
*responseCode = -4;
|
||||
return false;
|
||||
} else {
|
||||
|
@ -450,12 +425,9 @@ bool HTTPGetFile(HINTERNET hConnect,
|
|||
}
|
||||
|
||||
encodingLen = sizeof(encoding);
|
||||
if (!WinHttpQueryHeaders(hRequest,
|
||||
WINHTTP_QUERY_CONTENT_ENCODING,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX,
|
||||
encoding,
|
||||
&encodingLen,
|
||||
WINHTTP_NO_HEADER_INDEX)) {
|
||||
if (!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_ENCODING,
|
||||
WINHTTP_HEADER_NAME_BY_INDEX, encoding,
|
||||
&encodingLen, WINHTTP_NO_HEADER_INDEX)) {
|
||||
encoding[0] = 0;
|
||||
if (GetLastError() != ERROR_WINHTTP_HEADER_NOT_FOUND) {
|
||||
*responseCode = -5;
|
||||
|
@ -502,8 +474,8 @@ bool HTTPGetFile(HINTERNET hConnect,
|
|||
DWORD dwSize, outSize;
|
||||
int lastPosition = 0;
|
||||
|
||||
WinHandle updateFile = CreateFile(outputPath, GENERIC_WRITE, 0,
|
||||
nullptr, CREATE_ALWAYS, 0, nullptr);
|
||||
WinHandle updateFile = CreateFile(outputPath, GENERIC_WRITE, 0, nullptr,
|
||||
CREATE_ALWAYS, 0, nullptr);
|
||||
if (!updateFile.Valid()) {
|
||||
*responseCode = -7;
|
||||
return false;
|
||||
|
@ -529,17 +501,18 @@ bool HTTPGetFile(HINTERNET hConnect,
|
|||
|
||||
if (gzip) {
|
||||
if (!ReadHTTPZippedFile(strm, updateFile,
|
||||
zipBuf, buffer,
|
||||
outSize, responseCode))
|
||||
zipBuf, buffer, outSize,
|
||||
responseCode))
|
||||
return false;
|
||||
} else {
|
||||
if (!ReadHTTPFile(updateFile, buffer,
|
||||
outSize, responseCode))
|
||||
if (!ReadHTTPFile(updateFile, buffer, outSize,
|
||||
responseCode))
|
||||
return false;
|
||||
}
|
||||
|
||||
int position = (int)(((float)completedFileSize /
|
||||
(float)totalFileSize) * 100.0f);
|
||||
(float)totalFileSize) *
|
||||
100.0f);
|
||||
if (position > lastPosition) {
|
||||
lastPosition = position;
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS,
|
||||
|
|
|
@ -48,10 +48,7 @@ public:
|
|||
|
||||
inline bool init_decoder()
|
||||
{
|
||||
lzma_ret ret = lzma_stream_decoder(
|
||||
&strm,
|
||||
200 * 1024 * 1024,
|
||||
0);
|
||||
lzma_ret ret = lzma_stream_decoder(&strm, 200 * 1024 * 1024, 0);
|
||||
initialized = (ret == LZMA_OK);
|
||||
return initialized;
|
||||
}
|
||||
|
@ -225,8 +222,8 @@ try {
|
|||
/* --------------------------------- *
|
||||
* open patch and file to patch */
|
||||
|
||||
hPatch = CreateFile(patchFile, GENERIC_READ, 0, nullptr,
|
||||
OPEN_EXISTING, 0, nullptr);
|
||||
hPatch = CreateFile(patchFile, GENERIC_READ, 0, nullptr, OPEN_EXISTING,
|
||||
0, nullptr);
|
||||
if (!hPatch.Valid())
|
||||
throw int(GetLastError());
|
||||
|
||||
|
@ -311,8 +308,8 @@ try {
|
|||
|
||||
DWORD written;
|
||||
|
||||
success = !!WriteFile(hTarget, newData.data(), (DWORD)newsize,
|
||||
&written, nullptr);
|
||||
success = !!WriteFile(hTarget, newData.data(), (DWORD)newsize, &written,
|
||||
nullptr);
|
||||
if (!success || written != newsize)
|
||||
throw int(GetLastError());
|
||||
|
||||
|
|
|
@ -65,8 +65,7 @@ static inline bool HasVS2017Redist2()
|
|||
wchar_t path[MAX_PATH];
|
||||
WIN32_FIND_DATAW wfd;
|
||||
HANDLE handle;
|
||||
int folder = (is32bit && is_64bit_windows())
|
||||
? CSIDL_SYSTEMX86
|
||||
int folder = (is32bit && is_64bit_windows()) ? CSIDL_SYSTEMX86
|
||||
: CSIDL_SYSTEM;
|
||||
|
||||
SHGetFolderPathW(NULL, folder, NULL, SHGFP_TYPE_CURRENT, base);
|
||||
|
@ -97,7 +96,8 @@ static bool HasVS2017Redist()
|
|||
PVOID old = nullptr;
|
||||
bool redirect = !!Wow64DisableWow64FsRedirection(&old);
|
||||
bool success = HasVS2017Redist2();
|
||||
if (redirect) Wow64RevertWow64FsRedirection(old);
|
||||
if (redirect)
|
||||
Wow64RevertWow64FsRedirection(old);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -139,8 +139,8 @@ try {
|
|||
if (!hSrc.Valid())
|
||||
throw LastError();
|
||||
|
||||
hDest = CreateFile(dest, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS,
|
||||
0, nullptr);
|
||||
hDest = CreateFile(dest, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0,
|
||||
nullptr);
|
||||
if (!hDest.Valid())
|
||||
throw LastError();
|
||||
|
||||
|
@ -182,10 +182,7 @@ static bool IsSafeFilename(const wchar_t *path)
|
|||
return false;
|
||||
|
||||
while (*p) {
|
||||
if (!isalnum(*p) &&
|
||||
*p != '.' &&
|
||||
*p != '/' &&
|
||||
*p != '_' &&
|
||||
if (!isalnum(*p) && *p != '.' && *p != '/' && *p != '_' &&
|
||||
*p != '-')
|
||||
return false;
|
||||
p++;
|
||||
|
@ -213,11 +210,7 @@ static string QuickReadFile(const wchar_t *path)
|
|||
data.resize((size_t)size.QuadPart);
|
||||
|
||||
DWORD read;
|
||||
if (!ReadFile(handle,
|
||||
&data[0],
|
||||
(DWORD)data.size(),
|
||||
&read,
|
||||
nullptr)) {
|
||||
if (!ReadFile(handle, &data[0], (DWORD)data.size(), &read, nullptr)) {
|
||||
return string();
|
||||
}
|
||||
if (read != size.QuadPart) {
|
||||
|
@ -293,8 +286,7 @@ struct update_t {
|
|||
|
||||
void CleanPartialUpdate()
|
||||
{
|
||||
if (state == STATE_INSTALL_FAILED ||
|
||||
state == STATE_INSTALLED) {
|
||||
if (state == STATE_INSTALL_FAILED || state == STATE_INSTALLED) {
|
||||
if (!previousFile.empty()) {
|
||||
DeleteFile(outputPath.c_str());
|
||||
MyCopyFile(previousFile.c_str(),
|
||||
|
@ -347,8 +339,7 @@ bool DownloadWorkerThread()
|
|||
HttpHandle hSession = WinHttpOpen(L"OBS Studio Updater/2.1",
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
WINHTTP_NO_PROXY_BYPASS, 0);
|
||||
if (!hSession) {
|
||||
downloadThreadFailure = true;
|
||||
Status(L"Update failed: Couldn't open obsproject.com");
|
||||
|
@ -358,7 +349,8 @@ bool DownloadWorkerThread()
|
|||
WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS,
|
||||
(LPVOID)&tlsProtocols, sizeof(tlsProtocols));
|
||||
|
||||
HttpHandle hConnect = WinHttpConnect(hSession, L"cdn-fastly.obsproject.com",
|
||||
HttpHandle hConnect = WinHttpConnect(hSession,
|
||||
L"cdn-fastly.obsproject.com",
|
||||
INTERNET_DEFAULT_HTTPS_PORT, 0);
|
||||
if (!hConnect) {
|
||||
downloadThreadFailure = true;
|
||||
|
@ -395,8 +387,7 @@ bool DownloadWorkerThread()
|
|||
|
||||
Status(L"Downloading %s", update.outputPath.c_str());
|
||||
|
||||
if (!HTTPGetFile(hConnect,
|
||||
update.sourceURL.c_str(),
|
||||
if (!HTTPGetFile(hConnect, update.sourceURL.c_str(),
|
||||
update.tempPath.c_str(),
|
||||
L"Accept-Encoding: gzip",
|
||||
&responseCode)) {
|
||||
|
@ -405,8 +396,7 @@ bool DownloadWorkerThread()
|
|||
DeleteFile(update.tempPath.c_str());
|
||||
Status(L"Update failed: Could not download "
|
||||
L"%s (error code %d)",
|
||||
update.outputPath.c_str(),
|
||||
responseCode);
|
||||
update.outputPath.c_str(), responseCode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -415,8 +405,7 @@ bool DownloadWorkerThread()
|
|||
DeleteFile(update.tempPath.c_str());
|
||||
Status(L"Update failed: Could not download "
|
||||
L"%s (error code %d)",
|
||||
update.outputPath.c_str(),
|
||||
responseCode);
|
||||
update.outputPath.c_str(), responseCode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -489,10 +478,8 @@ static inline DWORD WaitIfOBS(DWORD id, const wchar_t *expected)
|
|||
wchar_t *name;
|
||||
*path = 0;
|
||||
|
||||
WinHandle proc = OpenProcess(
|
||||
PROCESS_QUERY_INFORMATION |
|
||||
PROCESS_VM_READ |
|
||||
SYNCHRONIZE,
|
||||
WinHandle proc = OpenProcess(PROCESS_QUERY_INFORMATION |
|
||||
PROCESS_VM_READ | SYNCHRONIZE,
|
||||
false, id);
|
||||
if (!proc.Valid())
|
||||
return WAITIFOBS_WRONG_PROCESS;
|
||||
|
@ -578,13 +565,15 @@ static bool NonCorePackageInstalled(const char *name)
|
|||
{
|
||||
if (is32bit) {
|
||||
if (strcmp(name, "obs-browser") == 0) {
|
||||
return FileExists(L"obs-plugins\\32bit\\obs-browser.dll");
|
||||
return FileExists(
|
||||
L"obs-plugins\\32bit\\obs-browser.dll");
|
||||
} else if (strcmp(name, "realsense") == 0) {
|
||||
return FileExists(L"obs-plugins\\32bit\\win-ivcam.dll");
|
||||
}
|
||||
} else {
|
||||
if (strcmp(name, "obs-browser") == 0) {
|
||||
return FileExists(L"obs-plugins\\64bit\\obs-browser.dll");
|
||||
return FileExists(
|
||||
L"obs-plugins\\64bit\\obs-browser.dll");
|
||||
} else if (strcmp(name, "realsense") == 0) {
|
||||
return FileExists(L"obs-plugins\\64bit\\win-ivcam.dll");
|
||||
}
|
||||
|
@ -694,14 +683,15 @@ static bool AddPackageUpdateFiles(json_t *root, size_t idx,
|
|||
|
||||
if (!IsSafeFilename(updateFileName)) {
|
||||
Status(L"Update failed: Unsafe path '%s' found in "
|
||||
L"manifest", updateFileName);
|
||||
L"manifest",
|
||||
updateFileName);
|
||||
return false;
|
||||
}
|
||||
|
||||
StringCbPrintf(sourceURL, sizeof(sourceURL), L"%s/%s/%s",
|
||||
UPDATE_URL, wPackageName, updateFileName);
|
||||
StringCbPrintf(tempFilePath, sizeof(tempFilePath),
|
||||
L"%s\\%s", tempPath, updateHashStr);
|
||||
StringCbPrintf(tempFilePath, sizeof(tempFilePath), L"%s\\%s",
|
||||
tempPath, updateHashStr);
|
||||
|
||||
/* Check file hash */
|
||||
|
||||
|
@ -750,8 +740,7 @@ static bool AddPackageUpdateFiles(json_t *root, size_t idx,
|
|||
}
|
||||
|
||||
static void UpdateWithPatchIfAvailable(const char *name, const char *hash,
|
||||
const char *source,
|
||||
int size)
|
||||
const char *source, int size)
|
||||
{
|
||||
wchar_t widePatchableFilename[MAX_PATH];
|
||||
wchar_t widePatchHash[MAX_PATH];
|
||||
|
@ -825,11 +814,9 @@ static bool UpdateFile(update_t &file)
|
|||
curFileName = baseName;
|
||||
|
||||
/* Backup the existing file in case a rollback is needed */
|
||||
StringCbCopy(oldFileRenamedPath,
|
||||
sizeof(oldFileRenamedPath),
|
||||
StringCbCopy(oldFileRenamedPath, sizeof(oldFileRenamedPath),
|
||||
file.outputPath.c_str());
|
||||
StringCbCat(oldFileRenamedPath,
|
||||
sizeof(oldFileRenamedPath),
|
||||
StringCbCat(oldFileRenamedPath, sizeof(oldFileRenamedPath),
|
||||
L".old");
|
||||
|
||||
if (!MyCopyFile(file.outputPath.c_str(), oldFileRenamedPath)) {
|
||||
|
@ -853,8 +840,7 @@ static bool UpdateFile(update_t &file)
|
|||
bool installed_ok;
|
||||
|
||||
if (file.patchable) {
|
||||
error_code = ApplyPatch(
|
||||
file.tempPath.c_str(),
|
||||
error_code = ApplyPatch(file.tempPath.c_str(),
|
||||
file.outputPath.c_str());
|
||||
installed_ok = (error_code == 0);
|
||||
|
||||
|
@ -882,8 +868,7 @@ static bool UpdateFile(update_t &file)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
installed_ok = MyCopyFile(
|
||||
file.tempPath.c_str(),
|
||||
installed_ok = MyCopyFile(file.tempPath.c_str(),
|
||||
file.outputPath.c_str());
|
||||
error_code = GetLastError();
|
||||
}
|
||||
|
@ -900,8 +885,7 @@ static bool UpdateFile(update_t &file)
|
|||
else
|
||||
Status(L"Update failed: Couldn't update %s "
|
||||
L"(error %d)",
|
||||
curFileName,
|
||||
GetLastError());
|
||||
curFileName, GetLastError());
|
||||
|
||||
file.state = STATE_INSTALL_FAILED;
|
||||
return false;
|
||||
|
@ -923,13 +907,11 @@ static bool UpdateFile(update_t &file)
|
|||
|
||||
file.previousFile = L"";
|
||||
|
||||
bool success = !!MyCopyFile(
|
||||
file.tempPath.c_str(),
|
||||
bool success = !!MyCopyFile(file.tempPath.c_str(),
|
||||
file.outputPath.c_str());
|
||||
if (!success) {
|
||||
Status(L"Update failed: Couldn't install %s (error %d)",
|
||||
file.outputPath.c_str(),
|
||||
GetLastError());
|
||||
file.outputPath.c_str(), GetLastError());
|
||||
file.state = STATE_INSTALL_FAILED;
|
||||
return false;
|
||||
}
|
||||
|
@ -944,8 +926,7 @@ static wchar_t tempPath[MAX_PATH] = {};
|
|||
|
||||
#define PATCH_MANIFEST_URL \
|
||||
L"https://obsproject.com/update_studio/getpatchmanifest"
|
||||
#define HASH_NULL \
|
||||
L"0000000000000000000000000000000000000000"
|
||||
#define HASH_NULL L"0000000000000000000000000000000000000000"
|
||||
|
||||
static bool UpdateVS2017Redists(json_t *root)
|
||||
{
|
||||
|
@ -957,8 +938,7 @@ static bool UpdateVS2017Redists(json_t *root)
|
|||
HttpHandle hSession = WinHttpOpen(L"OBS Studio Updater/2.1",
|
||||
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME,
|
||||
WINHTTP_NO_PROXY_BYPASS,
|
||||
0);
|
||||
WINHTTP_NO_PROXY_BYPASS, 0);
|
||||
if (!hSession) {
|
||||
Status(L"Update failed: Couldn't open obsproject.com");
|
||||
return false;
|
||||
|
@ -967,7 +947,8 @@ static bool UpdateVS2017Redists(json_t *root)
|
|||
WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS,
|
||||
(LPVOID)&tlsProtocols, sizeof(tlsProtocols));
|
||||
|
||||
HttpHandle hConnect = WinHttpConnect(hSession, L"cdn-fastly.obsproject.com",
|
||||
HttpHandle hConnect = WinHttpConnect(hSession,
|
||||
L"cdn-fastly.obsproject.com",
|
||||
INTERNET_DEFAULT_HTTPS_PORT, 0);
|
||||
if (!hConnect) {
|
||||
Status(L"Update failed: Couldn't connect to cdn-fastly.obsproject.com");
|
||||
|
@ -986,8 +967,7 @@ static bool UpdateVS2017Redists(json_t *root)
|
|||
|
||||
Status(L"Downloading %s", L"Visual C++ 2017 Redistributable");
|
||||
|
||||
const wchar_t *file = (is32bit)
|
||||
? L"vc2017redist_x86.exe"
|
||||
const wchar_t *file = (is32bit) ? L"vc2017redist_x86.exe"
|
||||
: L"vc2017redist_x64.exe";
|
||||
|
||||
wstring sourceURL;
|
||||
|
@ -999,26 +979,21 @@ static bool UpdateVS2017Redists(json_t *root)
|
|||
destPath += L"\\";
|
||||
destPath += file;
|
||||
|
||||
if (!HTTPGetFile(hConnect,
|
||||
sourceURL.c_str(),
|
||||
destPath.c_str(),
|
||||
L"Accept-Encoding: gzip",
|
||||
&responseCode)) {
|
||||
if (!HTTPGetFile(hConnect, sourceURL.c_str(), destPath.c_str(),
|
||||
L"Accept-Encoding: gzip", &responseCode)) {
|
||||
|
||||
DeleteFile(destPath.c_str());
|
||||
Status(L"Update failed: Could not download "
|
||||
L"%s (error code %d)",
|
||||
L"Visual C++ 2017 Redistributable",
|
||||
responseCode);
|
||||
L"Visual C++ 2017 Redistributable", responseCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------ *
|
||||
* Get expected hash */
|
||||
|
||||
json_t *redistJson = json_object_get(root, is32bit
|
||||
? "vc2017_redist_x86"
|
||||
: "vc2017_redist_x64");
|
||||
json_t *redistJson = json_object_get(
|
||||
root, is32bit ? "vc2017_redist_x86" : "vc2017_redist_x64");
|
||||
if (!redistJson) {
|
||||
Status(L"Update failed: Could not parse VC2017 redist json");
|
||||
return false;
|
||||
|
@ -1071,8 +1046,8 @@ static bool UpdateVS2017Redists(json_t *root)
|
|||
STARTUPINFO si = {};
|
||||
si.cb = sizeof(si);
|
||||
|
||||
bool success = !!CreateProcessW(destPath.c_str(), commandline,
|
||||
nullptr, nullptr, false, CREATE_NO_WINDOW,
|
||||
bool success = !!CreateProcessW(destPath.c_str(), commandline, nullptr,
|
||||
nullptr, false, CREATE_NO_WINDOW,
|
||||
nullptr, nullptr, &si, &pi);
|
||||
if (success) {
|
||||
Status(L"Installing %s...", L"Visual C++ 2017 Redistributable");
|
||||
|
@ -1083,8 +1058,7 @@ static bool UpdateVS2017Redists(json_t *root)
|
|||
} else {
|
||||
Status(L"Update failed: Could not execute "
|
||||
L"%s (error code %d)",
|
||||
L"Visual C++ 2017 Redistributable",
|
||||
(int)GetLastError());
|
||||
L"Visual C++ 2017 Redistributable", (int)GetLastError());
|
||||
}
|
||||
|
||||
DeleteFile(destPath.c_str());
|
||||
|
@ -1102,8 +1076,8 @@ static bool Update(wchar_t *cmdLine)
|
|||
/* ------------------------------------- *
|
||||
* Check to make sure OBS isn't running */
|
||||
|
||||
HANDLE hObsUpdateMutex = OpenMutexW(SYNCHRONIZE, false,
|
||||
L"OBSStudioUpdateMutex");
|
||||
HANDLE hObsUpdateMutex =
|
||||
OpenMutexW(SYNCHRONIZE, false, L"OBSStudioUpdateMutex");
|
||||
if (hObsUpdateMutex) {
|
||||
HANDLE hWait[2];
|
||||
hWait[0] = hObsUpdateMutex;
|
||||
|
@ -1179,7 +1153,8 @@ static bool Update(wchar_t *cmdLine)
|
|||
} else {
|
||||
CoTaskMemPtr<wchar_t> pOut;
|
||||
HRESULT hr = SHGetKnownFolderPath(FOLDERID_RoamingAppData,
|
||||
KF_FLAG_DEFAULT, nullptr, &pOut);
|
||||
KF_FLAG_DEFAULT, nullptr,
|
||||
&pOut);
|
||||
if (hr != S_OK) {
|
||||
Status(L"Update failed: Could not determine AppData "
|
||||
L"location");
|
||||
|
@ -1189,8 +1164,7 @@ static bool Update(wchar_t *cmdLine)
|
|||
StringCbCopy(lpAppDataPath, sizeof(lpAppDataPath), pOut);
|
||||
}
|
||||
|
||||
StringCbCat(lpAppDataPath, sizeof(lpAppDataPath),
|
||||
L"\\obs-studio");
|
||||
StringCbCat(lpAppDataPath, sizeof(lpAppDataPath), L"\\obs-studio");
|
||||
|
||||
/* ------------------------------------- *
|
||||
* Get download path */
|
||||
|
@ -1233,7 +1207,8 @@ static bool Update(wchar_t *cmdLine)
|
|||
|
||||
if (!root) {
|
||||
Status(L"Update failed: Couldn't parse update "
|
||||
L"manifest: %S", error.text);
|
||||
L"manifest: %S",
|
||||
error.text);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1327,15 +1302,14 @@ static bool Update(wchar_t *cmdLine)
|
|||
|
||||
compressedJson.resize(compressSize);
|
||||
compress2((Bytef *)&compressedJson[0], &compressSize,
|
||||
(const Bytef*)post_body, len,
|
||||
Z_BEST_COMPRESSION);
|
||||
(const Bytef *)post_body, len, Z_BEST_COMPRESSION);
|
||||
compressedJson.resize(compressSize);
|
||||
|
||||
bool success = !!HTTPPostData(PATCH_MANIFEST_URL,
|
||||
(BYTE *)&compressedJson[0],
|
||||
(int)compressedJson.size(),
|
||||
L"Accept-Encoding: gzip", &responseCode,
|
||||
newManifest);
|
||||
L"Accept-Encoding: gzip",
|
||||
&responseCode, newManifest);
|
||||
free(post_body);
|
||||
|
||||
if (!success)
|
||||
|
@ -1416,8 +1390,7 @@ static bool Update(wchar_t *cmdLine)
|
|||
int updatesInstalled = 0;
|
||||
int lastPosition = 0;
|
||||
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS,
|
||||
PBM_SETPOS, 0, 0);
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS, PBM_SETPOS, 0, 0);
|
||||
|
||||
for (update_t &update : updates) {
|
||||
if (!UpdateFile(update)) {
|
||||
|
@ -1425,7 +1398,8 @@ static bool Update(wchar_t *cmdLine)
|
|||
} else {
|
||||
updatesInstalled++;
|
||||
int position = (int)(((float)updatesInstalled /
|
||||
(float)completedUpdates) * 100.0f);
|
||||
(float)completedUpdates) *
|
||||
100.0f);
|
||||
if (position > lastPosition) {
|
||||
lastPosition = position;
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS,
|
||||
|
@ -1445,8 +1419,7 @@ static bool Update(wchar_t *cmdLine)
|
|||
DeleteFile(update.tempPath.c_str());
|
||||
}
|
||||
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS,
|
||||
PBM_SETPOS, 100, 0);
|
||||
SendDlgItemMessage(hwndMain, IDC_PROGRESS, PBM_SETPOS, 100, 0);
|
||||
|
||||
Status(L"Update complete.");
|
||||
SetDlgItemText(hwndMain, IDC_BUTTON, L"Launch OBS");
|
||||
|
@ -1508,15 +1481,13 @@ static void LaunchOBS()
|
|||
GetCurrentDirectory(_countof(cwd) - 1, cwd);
|
||||
|
||||
StringCbCopy(obsPath, sizeof(obsPath), cwd);
|
||||
StringCbCat(obsPath, sizeof(obsPath), is32bit
|
||||
? L"\\bin\\32bit"
|
||||
: L"\\bin\\64bit");
|
||||
StringCbCat(obsPath, sizeof(obsPath),
|
||||
is32bit ? L"\\bin\\32bit" : L"\\bin\\64bit");
|
||||
SetCurrentDirectory(obsPath);
|
||||
StringCbCopy(newCwd, sizeof(newCwd), obsPath);
|
||||
|
||||
StringCbCat(obsPath, sizeof(obsPath), is32bit
|
||||
? L"\\obs32.exe"
|
||||
: L"\\obs64.exe");
|
||||
StringCbCat(obsPath, sizeof(obsPath),
|
||||
is32bit ? L"\\obs32.exe" : L"\\obs64.exe");
|
||||
|
||||
if (!FileExists(obsPath)) {
|
||||
StringCbCopy(obsPath, sizeof(obsPath), cwd);
|
||||
|
@ -1544,13 +1515,13 @@ static void LaunchOBS()
|
|||
ShellExecuteEx(&execInfo);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK UpdateDialogProc(HWND hwnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
static INT_PTR CALLBACK UpdateDialogProc(HWND hwnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: {
|
||||
static HICON hMainIcon = LoadIcon(hinstMain,
|
||||
MAKEINTRESOURCE(IDI_ICON1));
|
||||
static HICON hMainIcon =
|
||||
LoadIcon(hinstMain, MAKEINTRESOURCE(IDI_ICON1));
|
||||
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hMainIcon);
|
||||
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hMainIcon);
|
||||
return true;
|
||||
|
@ -1559,8 +1530,8 @@ static INT_PTR CALLBACK UpdateDialogProc(HWND hwnd, UINT message,
|
|||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDC_BUTTON) {
|
||||
if (HIWORD(wParam) == BN_CLICKED) {
|
||||
DWORD result = WaitForSingleObject(
|
||||
updateThread, 0);
|
||||
DWORD result =
|
||||
WaitForSingleObject(updateThread, 0);
|
||||
if (result == WAIT_OBJECT_0) {
|
||||
if (updateFailed)
|
||||
PostQuitMessage(0);
|
||||
|
@ -1627,7 +1598,8 @@ static bool HasElevation()
|
|||
BOOL success;
|
||||
|
||||
success = AllocateAndInitializeSid(&sia, 2, SECURITY_BUILTIN_DOMAIN_RID,
|
||||
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid);
|
||||
DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0,
|
||||
0, 0, &sid);
|
||||
if (success && sid) {
|
||||
CheckTokenMembership(nullptr, sid, &elevated);
|
||||
FreeSid(sid);
|
||||
|
@ -1641,8 +1613,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
|||
INITCOMMONCONTROLSEX icce;
|
||||
|
||||
if (!HasElevation()) {
|
||||
HANDLE hLowMutex = CreateMutexW(nullptr, true,
|
||||
L"OBSUpdaterRunningAsNonAdminUser");
|
||||
HANDLE hLowMutex = CreateMutexW(
|
||||
nullptr, true, L"OBSUpdaterRunningAsNonAdminUser");
|
||||
|
||||
RestartAsAdmin(lpCmdLine);
|
||||
|
||||
|
@ -1674,8 +1646,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
|||
InitCommonControlsEx(&icce);
|
||||
|
||||
hwndMain = CreateDialog(hInstance,
|
||||
MAKEINTRESOURCE(IDD_UPDATEDIALOG), nullptr,
|
||||
UpdateDialogProc);
|
||||
MAKEINTRESOURCE(IDD_UPDATEDIALOG),
|
||||
nullptr, UpdateDialogProc);
|
||||
if (!hwndMain) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -1684,8 +1656,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
|||
SetForegroundWindow(hwndMain);
|
||||
|
||||
cancelRequested = CreateEvent(nullptr, true, false, nullptr);
|
||||
updateThread = CreateThread(nullptr, 0, UpdateThread,
|
||||
lpCmdLine, 0, nullptr);
|
||||
updateThread = CreateThread(nullptr, 0, UpdateThread, lpCmdLine,
|
||||
0, nullptr);
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, nullptr, 0, 0)) {
|
||||
|
@ -1697,8 +1669,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
|
|||
|
||||
/* there is no non-elevated process waiting for us if UAC is
|
||||
* disabled */
|
||||
WinHandle hMutex = OpenMutex(SYNCHRONIZE, false,
|
||||
L"OBSUpdaterRunningAsNonAdminUser");
|
||||
WinHandle hMutex = OpenMutex(
|
||||
SYNCHRONIZE, false, L"OBSUpdaterRunningAsNonAdminUser");
|
||||
if (msg.wParam == 1 && !hMutex) {
|
||||
LaunchOBS();
|
||||
}
|
||||
|
|
|
@ -45,32 +45,28 @@
|
|||
#define BLAKE2_HASH_STR_LENGTH ((BLAKE2_HASH_LENGTH * 2) + 1)
|
||||
|
||||
#if defined _M_IX86
|
||||
#pragma comment(linker, \
|
||||
"/manifestdependency:\"type='win32' " \
|
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' " \
|
||||
"name='Microsoft.Windows.Common-Controls' " \
|
||||
"version='6.0.0.0' " \
|
||||
"processorArchitecture='x86' " \
|
||||
"publicKeyToken='6595b64144ccf1df' " \
|
||||
"language='*'\"")
|
||||
#elif defined _M_IA64
|
||||
#pragma comment(linker, \
|
||||
"/manifestdependency:\"type='win32' " \
|
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' " \
|
||||
"name='Microsoft.Windows.Common-Controls' " \
|
||||
"version='6.0.0.0' " \
|
||||
"processorArchitecture='ia64' " \
|
||||
"publicKeyToken='6595b64144ccf1df' " \
|
||||
"language='*'\"")
|
||||
#elif defined _M_X64
|
||||
#pragma comment(linker, \
|
||||
"/manifestdependency:\"type='win32' " \
|
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' " \
|
||||
"name='Microsoft.Windows.Common-Controls' " \
|
||||
"version='6.0.0.0' " \
|
||||
"processorArchitecture='amd64' " \
|
||||
"publicKeyToken='6595b64144ccf1df' " \
|
||||
"language='*'\"")
|
||||
#else
|
||||
#pragma comment(linker, \
|
||||
"/manifestdependency:\"type='win32' " \
|
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' " \
|
||||
"name='Microsoft.Windows.Common-Controls' " \
|
||||
"version='6.0.0.0' processorArchitecture='*' " \
|
||||
"publicKeyToken='6595b64144ccf1df' " \
|
||||
|
@ -81,16 +77,11 @@
|
|||
#include <jansson.h>
|
||||
#include "resource.h"
|
||||
|
||||
bool HTTPGetFile(HINTERNET hConnect,
|
||||
const wchar_t *url,
|
||||
const wchar_t *outputPath,
|
||||
const wchar_t *extraHeaders,
|
||||
bool HTTPGetFile(HINTERNET hConnect, const wchar_t *url,
|
||||
const wchar_t *outputPath, const wchar_t *extraHeaders,
|
||||
int *responseCode);
|
||||
bool HTTPPostData(const wchar_t *url,
|
||||
const BYTE * data,
|
||||
int dataLen,
|
||||
const wchar_t *extraHeaders,
|
||||
int * responseCode,
|
||||
bool HTTPPostData(const wchar_t *url, const BYTE *data, int dataLen,
|
||||
const wchar_t *extraHeaders, int *responseCode,
|
||||
std::string &response);
|
||||
|
||||
void HashToString(const BYTE *in, wchar_t *out);
|
||||
|
|
|
@ -78,7 +78,8 @@ public:
|
|||
inline Json(const Json &from) : json(json_incref(from.json)) {}
|
||||
inline Json(Json &&from) : json(from.json) { from.json = nullptr; }
|
||||
|
||||
inline ~Json() {
|
||||
inline ~Json()
|
||||
{
|
||||
if (json)
|
||||
json_decref(json);
|
||||
}
|
||||
|
|
|
@ -120,8 +120,7 @@ static const unsigned char obs_pub[] = {
|
|||
0x42, 0x61, 0x35, 0x66, 0x37, 0x4c, 0x6f, 0x4b, 0x38, 0x43, 0x41, 0x77,
|
||||
0x45, 0x41, 0x41, 0x51, 0x3d, 0x3d, 0x0a, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x45, 0x4e, 0x44, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x20, 0x4b,
|
||||
0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
|
||||
};
|
||||
0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a};
|
||||
static const unsigned int obs_pub_len = 800;
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -132,23 +131,18 @@ try {
|
|||
if (os_utf8_to_wcs_ptr(file, 0, &w_file) == 0)
|
||||
return false;
|
||||
|
||||
WinHandle handle = CreateFileW(
|
||||
w_file,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
nullptr,
|
||||
CREATE_ALWAYS,
|
||||
FILE_FLAG_WRITE_THROUGH,
|
||||
WinHandle handle = CreateFileW(w_file, GENERIC_WRITE, 0, nullptr,
|
||||
CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH,
|
||||
nullptr);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
throw strprintf("Failed to open file '%s': %lu",
|
||||
file, GetLastError());
|
||||
throw strprintf("Failed to open file '%s': %lu", file,
|
||||
GetLastError());
|
||||
|
||||
DWORD written;
|
||||
if (!WriteFile(handle, data, (DWORD)size, &written, nullptr))
|
||||
throw strprintf("Failed to write file '%s': %lu",
|
||||
file, GetLastError());
|
||||
throw strprintf("Failed to write file '%s': %lu", file,
|
||||
GetLastError());
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -163,26 +157,20 @@ try {
|
|||
if (os_utf8_to_wcs_ptr(file, 0, &w_file) == 0)
|
||||
return false;
|
||||
|
||||
WinHandle handle = CreateFileW(
|
||||
w_file,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ,
|
||||
nullptr,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
nullptr);
|
||||
WinHandle handle = CreateFileW(w_file, GENERIC_READ, FILE_SHARE_READ,
|
||||
nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
throw strprintf("Failed to open file '%s': %lu",
|
||||
file, GetLastError());
|
||||
throw strprintf("Failed to open file '%s': %lu", file,
|
||||
GetLastError());
|
||||
|
||||
DWORD size = GetFileSize(handle, nullptr);
|
||||
data.resize(size);
|
||||
|
||||
DWORD read;
|
||||
if (!ReadFile(handle, &data[0], size, &read, nullptr))
|
||||
throw strprintf("Failed to write file '%s': %lu",
|
||||
file, GetLastError());
|
||||
throw strprintf("Failed to write file '%s': %lu", file,
|
||||
GetLastError());
|
||||
|
||||
return true;
|
||||
|
||||
|
@ -216,8 +204,8 @@ try {
|
|||
WinHandle handle = CreateFileW(w_path, GENERIC_READ, FILE_SHARE_READ,
|
||||
nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
throw strprintf("Failed to open file '%s': %lu",
|
||||
path, GetLastError());
|
||||
throw strprintf("Failed to open file '%s': %lu", path,
|
||||
GetLastError());
|
||||
|
||||
vector<BYTE> buf;
|
||||
buf.resize(65536);
|
||||
|
@ -226,8 +214,8 @@ try {
|
|||
DWORD read = 0;
|
||||
if (!ReadFile(handle, buf.data(), (DWORD)buf.size(), &read,
|
||||
nullptr))
|
||||
throw strprintf("Failed to read file '%s': %lu",
|
||||
path, GetLastError());
|
||||
throw strprintf("Failed to read file '%s': %lu", path,
|
||||
GetLastError());
|
||||
|
||||
if (!read)
|
||||
break;
|
||||
|
@ -272,41 +260,26 @@ static bool VerifyDigitalSignature(uint8_t *buf, size_t len, uint8_t *sig,
|
|||
/* Signature in little-endian format */
|
||||
vector<BYTE> reversedSig;
|
||||
|
||||
if (!CryptStringToBinaryA((LPCSTR)obs_pub,
|
||||
obs_pub_len,
|
||||
CRYPT_STRING_BASE64HEADER,
|
||||
binaryKey,
|
||||
&binaryKeyLen,
|
||||
nullptr,
|
||||
nullptr))
|
||||
if (!CryptStringToBinaryA((LPCSTR)obs_pub, obs_pub_len,
|
||||
CRYPT_STRING_BASE64HEADER, binaryKey,
|
||||
&binaryKeyLen, nullptr, nullptr))
|
||||
return false;
|
||||
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
|
||||
X509_PUBLIC_KEY_INFO,
|
||||
binaryKey,
|
||||
binaryKeyLen,
|
||||
CRYPT_ENCODE_ALLOC_FLAG,
|
||||
nullptr,
|
||||
&publicPBLOB,
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
|
||||
binaryKey, binaryKeyLen,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, nullptr, &publicPBLOB,
|
||||
&iPBLOBSize))
|
||||
return false;
|
||||
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING,
|
||||
RSA_CSP_PUBLICKEYBLOB,
|
||||
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, RSA_CSP_PUBLICKEYBLOB,
|
||||
publicPBLOB->PublicKey.pbData,
|
||||
publicPBLOB->PublicKey.cbData,
|
||||
CRYPT_ENCODE_ALLOC_FLAG,
|
||||
nullptr,
|
||||
&rsaPublicBLOB,
|
||||
&rsaPublicBLOBSize))
|
||||
CRYPT_ENCODE_ALLOC_FLAG, nullptr,
|
||||
&rsaPublicBLOB, &rsaPublicBLOBSize))
|
||||
return false;
|
||||
|
||||
if (!CryptImportKey(provider,
|
||||
(const BYTE *)rsaPublicBLOB.get(),
|
||||
rsaPublicBLOBSize,
|
||||
0,
|
||||
0,
|
||||
&keyOut))
|
||||
if (!CryptImportKey(provider, (const BYTE *)rsaPublicBLOB.get(),
|
||||
rsaPublicBLOBSize, 0, 0, &keyOut))
|
||||
return false;
|
||||
|
||||
if (!CryptCreateHash(provider, CALG_SHA_512, 0, 0, &hash))
|
||||
|
@ -321,12 +294,8 @@ static bool VerifyDigitalSignature(uint8_t *buf, size_t len, uint8_t *sig,
|
|||
for (size_t i = 0; i < sigLen; i++)
|
||||
reversedSig[i] = sig[sigLen - i - 1];
|
||||
|
||||
if (!CryptVerifySignature(hash,
|
||||
reversedSig.data(),
|
||||
(DWORD)sigLen,
|
||||
keyOut,
|
||||
nullptr,
|
||||
0))
|
||||
if (!CryptVerifySignature(hash, reversedSig.data(), (DWORD)sigLen,
|
||||
keyOut, nullptr, 0))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -357,10 +326,8 @@ try {
|
|||
signature.reserve(sigLen);
|
||||
HexToByteArray(hexSig, sigLen, signature);
|
||||
|
||||
if (!VerifyDigitalSignature((uint8_t*)data.data(),
|
||||
data.size(),
|
||||
signature.data(),
|
||||
signature.size()))
|
||||
if (!VerifyDigitalSignature((uint8_t *)data.data(), data.size(),
|
||||
signature.data(), signature.size()))
|
||||
throw strprintf("Signature check failed for %s", name);
|
||||
|
||||
return true;
|
||||
|
@ -378,8 +345,8 @@ try {
|
|||
uint8_t updateFileHash[BLAKE2_HASH_LENGTH];
|
||||
vector<string> extraHeaders;
|
||||
|
||||
BPtr<char> updateFilePath = GetConfigPathPtr(
|
||||
"obs-studio\\updates\\updater.exe");
|
||||
BPtr<char> updateFilePath =
|
||||
GetConfigPathPtr("obs-studio\\updates\\updater.exe");
|
||||
|
||||
if (CalculateFileHash(updateFilePath, updateFileHash)) {
|
||||
char hashString[BLAKE2_HASH_STR_LENGTH];
|
||||
|
@ -394,8 +361,8 @@ try {
|
|||
string error;
|
||||
string data;
|
||||
|
||||
bool success = GetRemoteFile(url, data, error, &responseCode,
|
||||
nullptr, nullptr, extraHeaders, &signature);
|
||||
bool success = GetRemoteFile(url, data, error, &responseCode, nullptr,
|
||||
nullptr, extraHeaders, &signature);
|
||||
|
||||
if (!success || (responseCode != 200 && responseCode != 304)) {
|
||||
if (responseCode == 404)
|
||||
|
@ -442,10 +409,8 @@ try {
|
|||
int patch = root.GetInt("version_patch");
|
||||
|
||||
if (major == 0)
|
||||
throw strprintf("Invalid version number: %d.%d.%d",
|
||||
major,
|
||||
minor,
|
||||
patch);
|
||||
throw strprintf("Invalid version number: %d.%d.%d", major,
|
||||
minor, patch);
|
||||
|
||||
json_t *notes = json_object_get(root, "notes");
|
||||
if (!json_is_string(notes))
|
||||
|
@ -491,8 +456,8 @@ 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(GetGlobalConfig(),
|
||||
"General", "InstallGUID");
|
||||
const char *pguid =
|
||||
config_get_string(GetGlobalConfig(), "General", "InstallGUID");
|
||||
string guid;
|
||||
if (pguid)
|
||||
guid = pguid;
|
||||
|
@ -501,9 +466,8 @@ string GetProgramGUID()
|
|||
GenerateGUID(guid);
|
||||
|
||||
if (!guid.empty())
|
||||
config_set_string(GetGlobalConfig(),
|
||||
"General", "InstallGUID",
|
||||
guid.c_str());
|
||||
config_set_string(GetGlobalConfig(), "General",
|
||||
"InstallGUID", guid.c_str());
|
||||
}
|
||||
|
||||
return guid;
|
||||
|
@ -516,13 +480,12 @@ void AutoUpdateThread::infoMsg(const QString &title, const QString &text)
|
|||
|
||||
void AutoUpdateThread::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));
|
||||
}
|
||||
|
||||
int AutoUpdateThread::queryUpdateSlot(bool localManualUpdate, const QString &text)
|
||||
int AutoUpdateThread::queryUpdateSlot(bool localManualUpdate,
|
||||
const QString &text)
|
||||
{
|
||||
OBSUpdate updateDlg(App()->GetMainWindow(), localManualUpdate, text);
|
||||
return updateDlg.exec();
|
||||
|
@ -557,8 +520,7 @@ static bool IsFileInUse(const wstring &file)
|
|||
static bool IsGameCaptureInUse()
|
||||
{
|
||||
wstring path = L"..\\..\\data\\obs-plugins\\win-capture\\graphics-hook";
|
||||
return IsFileInUse(path + L"32.dll") ||
|
||||
IsFileInUse(path + L"64.dll");
|
||||
return IsFileInUse(path + L"32.dll") || IsFileInUse(path + L"64.dll");
|
||||
}
|
||||
|
||||
void AutoUpdateThread::run()
|
||||
|
@ -581,11 +543,10 @@ try {
|
|||
}
|
||||
} finishedTrigger;
|
||||
|
||||
BPtr<char> manifestPath = GetConfigPathPtr(
|
||||
"obs-studio\\updates\\manifest.json");
|
||||
BPtr<char> manifestPath =
|
||||
GetConfigPathPtr("obs-studio\\updates\\manifest.json");
|
||||
|
||||
auto ActiveOrGameCaptureLocked = [this] ()
|
||||
{
|
||||
auto ActiveOrGameCaptureLocked = [this]() {
|
||||
if (obs_video_active()) {
|
||||
if (manualUpdate)
|
||||
info(QTStr("Updater.Running.Title"),
|
||||
|
@ -611,11 +572,8 @@ try {
|
|||
/* ----------------------------------- *
|
||||
* create signature provider */
|
||||
|
||||
if (!CryptAcquireContext(&localProvider,
|
||||
nullptr,
|
||||
MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT))
|
||||
if (!CryptAcquireContext(&localProvider, nullptr, MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
|
||||
throw strprintf("CryptAcquireContext failed: %lu",
|
||||
GetLastError());
|
||||
|
||||
|
@ -653,7 +611,8 @@ try {
|
|||
if (responseCode == 404)
|
||||
return;
|
||||
|
||||
throw strprintf("Failed to fetch manifest file: %s", error.c_str());
|
||||
throw strprintf("Failed to fetch manifest file: %s",
|
||||
error.c_str());
|
||||
}
|
||||
|
||||
/* ----------------------------------- *
|
||||
|
@ -661,8 +620,8 @@ try {
|
|||
|
||||
/* a new file must be digitally signed */
|
||||
if (responseCode == 200) {
|
||||
success = CheckDataSignature(text, "manifest",
|
||||
signature.data(), signature.size());
|
||||
success = CheckDataSignature(text, "manifest", signature.data(),
|
||||
signature.size());
|
||||
if (!success)
|
||||
throw string("Invalid manifest signature");
|
||||
}
|
||||
|
@ -749,8 +708,8 @@ try {
|
|||
/* ----------------------------------- *
|
||||
* execute updater */
|
||||
|
||||
BPtr<char> updateFilePath = GetConfigPathPtr(
|
||||
"obs-studio\\updates\\updater.exe");
|
||||
BPtr<char> updateFilePath =
|
||||
GetConfigPathPtr("obs-studio\\updates\\updater.exe");
|
||||
BPtr<wchar_t> wUpdateFilePath;
|
||||
|
||||
size_t size = os_utf8_to_wcs_ptr(updateFilePath, 0, &wUpdateFilePath);
|
||||
|
@ -808,17 +767,14 @@ try {
|
|||
BYTE whatsnewHash[BLAKE2_HASH_LENGTH];
|
||||
bool success;
|
||||
|
||||
BPtr<char> whatsnewPath = GetConfigPathPtr(
|
||||
"obs-studio\\updates\\whatsnew.json");
|
||||
BPtr<char> whatsnewPath =
|
||||
GetConfigPathPtr("obs-studio\\updates\\whatsnew.json");
|
||||
|
||||
/* ----------------------------------- *
|
||||
* create signature provider */
|
||||
|
||||
if (!CryptAcquireContext(&localProvider,
|
||||
nullptr,
|
||||
MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES,
|
||||
CRYPT_VERIFYCONTEXT))
|
||||
if (!CryptAcquireContext(&localProvider, nullptr, MS_ENH_RSA_AES_PROV,
|
||||
PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
|
||||
throw strprintf("CryptAcquireContext failed: %lu",
|
||||
GetLastError());
|
||||
|
||||
|
@ -865,8 +821,8 @@ try {
|
|||
* verify file signature */
|
||||
|
||||
if (responseCode == 200) {
|
||||
success = CheckDataSignature(text, "whatsnew",
|
||||
signature.data(), signature.size());
|
||||
success = CheckDataSignature(text, "whatsnew", signature.data(),
|
||||
signature.size());
|
||||
if (!success)
|
||||
throw string("Invalid whatsnew signature");
|
||||
}
|
||||
|
|
|
@ -9,9 +9,7 @@
|
|||
|
||||
using namespace json11;
|
||||
|
||||
OBSAbout::OBSAbout(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
ui(new Ui::OBSAbout)
|
||||
OBSAbout::OBSAbout(QWidget *parent) : QDialog(parent), ui(new Ui::OBSAbout)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -28,20 +26,21 @@ OBSAbout::OBSAbout(QWidget *parent)
|
|||
#ifdef HAVE_OBSCONFIG_H
|
||||
ver += OBS_VERSION;
|
||||
#else
|
||||
ver += LIBOBS_API_MAJOR_VER + "." +
|
||||
LIBOBS_API_MINOR_VER + "." +
|
||||
ver += LIBOBS_API_MAJOR_VER + "." + LIBOBS_API_MINOR_VER + "." +
|
||||
LIBOBS_API_PATCH_VER;
|
||||
#endif
|
||||
|
||||
ui->version->setText(ver + bitness);
|
||||
|
||||
ui->contribute->setText(QTStr("About.Contribute"));
|
||||
ui->donate->setText(" <a href='https://obsproject.com/donate'>" +
|
||||
ui->donate->setText(
|
||||
" <a href='https://obsproject.com/donate'>" +
|
||||
QTStr("About.Donate") + "</a>");
|
||||
ui->donate->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
ui->donate->setOpenExternalLinks(true);
|
||||
|
||||
ui->getInvolved->setText(" <a href='https://github.com/obsproject/obs-studio/blob/master/CONTRIBUTING.rst'>" +
|
||||
ui->getInvolved->setText(
|
||||
" <a href='https://github.com/obsproject/obs-studio/blob/master/CONTRIBUTING.rst'>" +
|
||||
QTStr("About.GetInvolved") + "</a>");
|
||||
ui->getInvolved->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
ui->getInvolved->setOpenExternalLinks(true);
|
||||
|
@ -68,10 +67,12 @@ OBSAbout::OBSAbout(QWidget *parent)
|
|||
RemoteTextThread *thread = new RemoteTextThread(
|
||||
"https://obsproject.com/patreon/about-box.json",
|
||||
"application/json");
|
||||
QObject::connect(thread, &RemoteTextThread::Result,
|
||||
main, &OBSBasic::UpdatePatronJson);
|
||||
QObject::connect(thread, SIGNAL(Result(const QString &, const QString &)),
|
||||
this, SLOT(ShowAbout()));
|
||||
QObject::connect(thread, &RemoteTextThread::Result, main,
|
||||
&OBSBasic::UpdatePatronJson);
|
||||
QObject::connect(
|
||||
thread,
|
||||
SIGNAL(Result(const QString &, const QString &)), this,
|
||||
SLOT(ShowAbout()));
|
||||
main->patronJsonThread.reset(thread);
|
||||
thread->start();
|
||||
} else {
|
||||
|
|
|
@ -31,17 +31,14 @@ class TestMode {
|
|||
gs_eparam_t *randomvals[3] = {
|
||||
gs_effect_get_param_by_name(solid, "randomvals1"),
|
||||
gs_effect_get_param_by_name(solid, "randomvals2"),
|
||||
gs_effect_get_param_by_name(solid, "randomvals3")
|
||||
};
|
||||
gs_effect_get_param_by_name(solid, "randomvals3")};
|
||||
|
||||
struct vec4 r;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
vec4_set(&r,
|
||||
vec4_set(&r, rand_float(true) * 100.0f,
|
||||
rand_float(true) * 100.0f,
|
||||
rand_float(true) * 100.0f,
|
||||
rand_float(true) * 50000.0f + 10000.0f,
|
||||
0.0f);
|
||||
rand_float(true) * 50000.0f + 10000.0f, 0.0f);
|
||||
gs_effect_set_vec4(randomvals[i], &r);
|
||||
}
|
||||
|
||||
|
@ -181,16 +178,15 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
/* -----------------------------------*/
|
||||
/* create obs objects */
|
||||
|
||||
const char *serverType = wiz->customServer
|
||||
? "rtmp_custom"
|
||||
const char *serverType = wiz->customServer ? "rtmp_custom"
|
||||
: "rtmp_common";
|
||||
|
||||
OBSEncoder vencoder = obs_video_encoder_create("obs_x264",
|
||||
"test_x264", nullptr, nullptr);
|
||||
OBSEncoder aencoder = obs_audio_encoder_create("ffmpeg_aac",
|
||||
"test_aac", nullptr, 0, nullptr);
|
||||
OBSService service = obs_service_create(serverType,
|
||||
"test_service", nullptr, nullptr);
|
||||
OBSEncoder vencoder = obs_video_encoder_create("obs_x264", "test_x264",
|
||||
nullptr, nullptr);
|
||||
OBSEncoder aencoder = obs_audio_encoder_create("ffmpeg_aac", "test_aac",
|
||||
nullptr, 0, nullptr);
|
||||
OBSService service = obs_service_create(serverType, "test_service",
|
||||
nullptr, nullptr);
|
||||
obs_encoder_release(vencoder);
|
||||
obs_encoder_release(aencoder);
|
||||
obs_service_release(service);
|
||||
|
@ -218,8 +214,8 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
if (wiz->service == AutoConfig::Service::Twitch) {
|
||||
string_depad_key(key);
|
||||
key += "?bandwidthtest";
|
||||
}
|
||||
else if(wiz->serviceName == "Restream.io" || wiz->serviceName == "Restream.io - RTMP") {
|
||||
} else if (wiz->serviceName == "Restream.io" ||
|
||||
wiz->serviceName == "Restream.io - RTMP") {
|
||||
string_depad_key(key);
|
||||
key += "?test=true";
|
||||
}
|
||||
|
@ -236,8 +232,8 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
obs_data_set_int(aencoder_settings, "bitrate", 32);
|
||||
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
const char *bind_ip = config_get_string(main->Config(), "Output",
|
||||
"BindIP");
|
||||
const char *bind_ip =
|
||||
config_get_string(main->Config(), "Output", "BindIP");
|
||||
obs_data_set_string(output_settings, "bind_ip", bind_ip);
|
||||
|
||||
/* -----------------------------------*/
|
||||
|
@ -267,8 +263,8 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
/* apply service settings */
|
||||
|
||||
obs_service_update(service, service_settings);
|
||||
obs_service_apply_encoder_settings(service,
|
||||
vencoder_settings, aencoder_settings);
|
||||
obs_service_apply_encoder_settings(service, vencoder_settings,
|
||||
aencoder_settings);
|
||||
|
||||
/* -----------------------------------*/
|
||||
/* create output */
|
||||
|
@ -277,18 +273,17 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
if (!output_type)
|
||||
output_type = "rtmp_output";
|
||||
|
||||
OBSOutput output = obs_output_create(output_type,
|
||||
"test_stream", nullptr, nullptr);
|
||||
OBSOutput output =
|
||||
obs_output_create(output_type, "test_stream", nullptr, nullptr);
|
||||
obs_output_release(output);
|
||||
obs_output_update(output, output_settings);
|
||||
|
||||
const char *audio_codec =
|
||||
obs_output_get_supported_audio_codecs(output);
|
||||
const char *audio_codec = obs_output_get_supported_audio_codecs(output);
|
||||
|
||||
if (strcmp(audio_codec, "aac") != 0) {
|
||||
const char *id = FindAudioEncoderFromCodec(audio_codec);
|
||||
aencoder = obs_audio_encoder_create(id,
|
||||
"test_audio", nullptr, 0, nullptr);
|
||||
aencoder = obs_audio_encoder_create(id, "test_audio", nullptr,
|
||||
0, nullptr);
|
||||
obs_encoder_release(aencoder);
|
||||
}
|
||||
|
||||
|
@ -308,16 +303,14 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
/* -----------------------------------*/
|
||||
/* connect signals */
|
||||
|
||||
auto on_started = [&] ()
|
||||
{
|
||||
auto on_started = [&]() {
|
||||
unique_lock<mutex> lock(m);
|
||||
connected = true;
|
||||
stopped = false;
|
||||
cv.notify_one();
|
||||
};
|
||||
|
||||
auto on_stopped = [&] ()
|
||||
{
|
||||
auto on_stopped = [&]() {
|
||||
unique_lock<mutex> lock(m);
|
||||
connected = false;
|
||||
stopped = true;
|
||||
|
@ -327,15 +320,13 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
using on_started_t = decltype(on_started);
|
||||
using on_stopped_t = decltype(on_stopped);
|
||||
|
||||
auto pre_on_started = [] (void *data, calldata_t *)
|
||||
{
|
||||
auto pre_on_started = [](void *data, calldata_t *) {
|
||||
on_started_t &on_started =
|
||||
*reinterpret_cast<on_started_t *>(data);
|
||||
on_started();
|
||||
};
|
||||
|
||||
auto pre_on_stopped = [] (void *data, calldata_t *)
|
||||
{
|
||||
auto pre_on_stopped = [](void *data, calldata_t *) {
|
||||
on_stopped_t &on_stopped =
|
||||
*reinterpret_cast<on_stopped_t *>(data);
|
||||
on_stopped();
|
||||
|
@ -358,7 +349,8 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
|
||||
int per = int((i + 1) * 100 / servers.size());
|
||||
QMetaObject::invokeMethod(this, "Progress", Q_ARG(int, per));
|
||||
QMetaObject::invokeMethod(this, "UpdateMessage",
|
||||
QMetaObject::invokeMethod(
|
||||
this, "UpdateMessage",
|
||||
Q_ARG(QString, QTStr(TEST_BW_CONNECTING)
|
||||
.arg(server.name.c_str())));
|
||||
|
||||
|
@ -385,9 +377,10 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
if (!connected)
|
||||
continue;
|
||||
|
||||
QMetaObject::invokeMethod(this, "UpdateMessage",
|
||||
Q_ARG(QString, QTStr(TEST_BW_SERVER)
|
||||
.arg(server.name.c_str())));
|
||||
QMetaObject::invokeMethod(
|
||||
this, "UpdateMessage",
|
||||
Q_ARG(QString,
|
||||
QTStr(TEST_BW_SERVER).arg(server.name.c_str())));
|
||||
|
||||
/* ignore first 2.5 seconds due to possible buffering skewing
|
||||
* the result */
|
||||
|
@ -418,10 +411,10 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
|
||||
uint64_t total_time = os_gettime_ns() - t_start;
|
||||
|
||||
int total_bytes = (int)obs_output_get_total_bytes(output) -
|
||||
start_bytes;
|
||||
uint64_t bitrate = (uint64_t)total_bytes * 8
|
||||
* 1000000000 / total_time / 1000;
|
||||
int total_bytes =
|
||||
(int)obs_output_get_total_bytes(output) - start_bytes;
|
||||
uint64_t bitrate = (uint64_t)total_bytes * 8 * 1000000000 /
|
||||
total_time / 1000;
|
||||
|
||||
if (obs_output_get_frames_dropped(output) ||
|
||||
(int)bitrate < (wiz->startingBitrate * 75 / 100)) {
|
||||
|
@ -436,7 +429,8 @@ void AutoConfigTestPage::TestBandwidthThread()
|
|||
|
||||
if (!success) {
|
||||
QMetaObject::invokeMethod(this, "Failure",
|
||||
Q_ARG(QString, QTStr(TEST_BW_CONNECT_FAIL)));
|
||||
Q_ARG(QString,
|
||||
QTStr(TEST_BW_CONNECT_FAIL)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -480,7 +474,8 @@ static long double EstimateMinBitrate(int cx, int cy, int fps_num, int fps_den)
|
|||
return EstimateBitrateVal(cx, cy, fps_num, fps_den) / val;
|
||||
}
|
||||
|
||||
static long double EstimateUpperBitrate(int cx, int cy, int fps_num, int fps_den)
|
||||
static long double EstimateUpperBitrate(int cx, int cy, int fps_num,
|
||||
int fps_den)
|
||||
{
|
||||
long double val = EstimateBitrateVal(1280, 720, 30, 1) / 3000.0l;
|
||||
return EstimateBitrateVal(cx, cy, fps_num, fps_den) / val;
|
||||
|
@ -525,12 +520,12 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
/* -----------------------------------*/
|
||||
/* create obs objects */
|
||||
|
||||
OBSEncoder vencoder = obs_video_encoder_create("obs_x264",
|
||||
"test_x264", nullptr, nullptr);
|
||||
OBSEncoder aencoder = obs_audio_encoder_create("ffmpeg_aac",
|
||||
"test_aac", nullptr, 0, nullptr);
|
||||
OBSOutput output = obs_output_create("null_output",
|
||||
"null", nullptr, nullptr);
|
||||
OBSEncoder vencoder = obs_video_encoder_create("obs_x264", "test_x264",
|
||||
nullptr, nullptr);
|
||||
OBSEncoder aencoder = obs_audio_encoder_create("ffmpeg_aac", "test_aac",
|
||||
nullptr, 0, nullptr);
|
||||
OBSOutput output =
|
||||
obs_output_create("null_output", "null", nullptr, nullptr);
|
||||
obs_output_release(output);
|
||||
obs_encoder_release(vencoder);
|
||||
obs_encoder_release(aencoder);
|
||||
|
@ -573,16 +568,14 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
/* -----------------------------------*/
|
||||
/* connect signals */
|
||||
|
||||
auto on_stopped = [&] ()
|
||||
{
|
||||
auto on_stopped = [&]() {
|
||||
unique_lock<mutex> lock(m);
|
||||
cv.notify_one();
|
||||
};
|
||||
|
||||
using on_stopped_t = decltype(on_stopped);
|
||||
|
||||
auto pre_on_stopped = [] (void *data, calldata_t *)
|
||||
{
|
||||
auto pre_on_stopped = [](void *data, calldata_t *) {
|
||||
on_stopped_t &on_stopped =
|
||||
*reinterpret_cast<on_stopped_t *>(data);
|
||||
on_stopped();
|
||||
|
@ -629,8 +622,7 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
int count = 1;
|
||||
|
||||
auto testRes = [&](long double div, int fps_num, int fps_den,
|
||||
bool force)
|
||||
{
|
||||
bool force) {
|
||||
int per = ++i * 100 / count;
|
||||
QMetaObject::invokeMethod(this, "Progress", Q_ARG(int, per));
|
||||
|
||||
|
@ -669,13 +661,13 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
QString cxStr = QString::number(cx);
|
||||
QString cyStr = QString::number(cy);
|
||||
|
||||
QString fpsStr = (fps_den > 1)
|
||||
? QString::number(fps, 'f', 2)
|
||||
QString fpsStr = (fps_den > 1) ? QString::number(fps, 'f', 2)
|
||||
: QString::number(fps, 'g', 2);
|
||||
|
||||
QMetaObject::invokeMethod(this, "UpdateMessage",
|
||||
Q_ARG(QString, QTStr(TEST_RES_VAL)
|
||||
.arg(cxStr, cyStr, fpsStr)));
|
||||
QMetaObject::invokeMethod(
|
||||
this, "UpdateMessage",
|
||||
Q_ARG(QString,
|
||||
QTStr(TEST_RES_VAL).arg(cxStr, cyStr, fpsStr)));
|
||||
|
||||
unique_lock<mutex> ul(m);
|
||||
if (cancel)
|
||||
|
@ -683,7 +675,8 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
|
||||
if (!obs_output_start(output)) {
|
||||
QMetaObject::invokeMethod(this, "Failure",
|
||||
Q_ARG(QString, QTStr(TEST_RES_FAIL)));
|
||||
Q_ARG(QString,
|
||||
QTStr(TEST_RES_FAIL)));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -692,8 +685,8 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
obs_output_stop(output);
|
||||
cv.wait(ul);
|
||||
|
||||
int skipped = (int)video_output_get_skipped_frames(
|
||||
obs_get_video());
|
||||
int skipped =
|
||||
(int)video_output_get_skipped_frames(obs_get_video());
|
||||
if (force || skipped <= 10)
|
||||
results.emplace_back(cx, cy, fps_num, fps_den);
|
||||
|
||||
|
@ -702,23 +695,38 @@ bool AutoConfigTestPage::TestSoftwareEncoding()
|
|||
|
||||
if (wiz->specificFPSNum && wiz->specificFPSDen) {
|
||||
count = 5;
|
||||
if (!testRes(1.0, 0, 0, false)) return false;
|
||||
if (!testRes(1.5, 0, 0, false)) return false;
|
||||
if (!testRes(1.0 / 0.6, 0, 0, false)) return false;
|
||||
if (!testRes(2.0, 0, 0, false)) return false;
|
||||
if (!testRes(2.25, 0, 0, true)) return false;
|
||||
if (!testRes(1.0, 0, 0, false))
|
||||
return false;
|
||||
if (!testRes(1.5, 0, 0, false))
|
||||
return false;
|
||||
if (!testRes(1.0 / 0.6, 0, 0, false))
|
||||
return false;
|
||||
if (!testRes(2.0, 0, 0, false))
|
||||
return false;
|
||||
if (!testRes(2.25, 0, 0, true))
|
||||
return false;
|
||||
} else {
|
||||
count = 10;
|
||||
if (!testRes(1.0, 60, 1, false)) return false;
|
||||
if (!testRes(1.0, 30, 1, false)) return false;
|
||||
if (!testRes(1.5, 60, 1, false)) return false;
|
||||
if (!testRes(1.5, 30, 1, false)) return false;
|
||||
if (!testRes(1.0 / 0.6, 60, 1, false)) return false;
|
||||
if (!testRes(1.0 / 0.6, 30, 1, false)) return false;
|
||||
if (!testRes(2.0, 60, 1, false)) return false;
|
||||
if (!testRes(2.0, 30, 1, false)) return false;
|
||||
if (!testRes(2.25, 60, 1, false)) return false;
|
||||
if (!testRes(2.25, 30, 1, true)) return false;
|
||||
if (!testRes(1.0, 60, 1, false))
|
||||
return false;
|
||||
if (!testRes(1.0, 30, 1, false))
|
||||
return false;
|
||||
if (!testRes(1.5, 60, 1, false))
|
||||
return false;
|
||||
if (!testRes(1.5, 30, 1, false))
|
||||
return false;
|
||||
if (!testRes(1.0 / 0.6, 60, 1, false))
|
||||
return false;
|
||||
if (!testRes(1.0 / 0.6, 30, 1, false))
|
||||
return false;
|
||||
if (!testRes(2.0, 60, 1, false))
|
||||
return false;
|
||||
if (!testRes(2.0, 30, 1, false))
|
||||
return false;
|
||||
if (!testRes(2.25, 60, 1, false))
|
||||
return false;
|
||||
if (!testRes(2.25, 30, 1, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -----------------------------------*/
|
||||
|
@ -777,8 +785,7 @@ void AutoConfigTestPage::FindIdealHardwareResolution()
|
|||
}
|
||||
|
||||
auto testRes = [&](long double div, int fps_num, int fps_den,
|
||||
bool force)
|
||||
{
|
||||
bool force) {
|
||||
if (results.size() >= 3)
|
||||
return;
|
||||
|
||||
|
@ -805,7 +812,8 @@ void AutoConfigTestPage::FindIdealHardwareResolution()
|
|||
* ratio, so increase the minimum bitrate estimate for them.
|
||||
* NVENC currently is the exception because of the improvements
|
||||
* its made to its quality in recent generations. */
|
||||
if (!nvenc) minBitrate = minBitrate * 114 / 100;
|
||||
if (!nvenc)
|
||||
minBitrate = minBitrate * 114 / 100;
|
||||
|
||||
if (wiz->type == AutoConfig::Type::Recording)
|
||||
force = true;
|
||||
|
@ -933,8 +941,7 @@ void AutoConfigTestPage::FinalizeResults()
|
|||
|
||||
QFormLayout *form = results;
|
||||
|
||||
auto encName = [] (AutoConfig::Encoder enc) -> QString
|
||||
{
|
||||
auto encName = [](AutoConfig::Encoder enc) -> QString {
|
||||
switch (enc) {
|
||||
case AutoConfig::Encoder::x264:
|
||||
return QTStr(ENCODER_SOFTWARE);
|
||||
|
@ -951,18 +958,16 @@ void AutoConfigTestPage::FinalizeResults()
|
|||
return QTStr(ENCODER_SOFTWARE);
|
||||
};
|
||||
|
||||
auto newLabel = [this] (const char *str) -> QLabel *
|
||||
{
|
||||
auto newLabel = [this](const char *str) -> QLabel * {
|
||||
return new QLabel(QTStr(str), this);
|
||||
};
|
||||
|
||||
if (wiz->type != AutoConfig::Type::Recording) {
|
||||
const char *serverType = wiz->customServer
|
||||
? "rtmp_custom"
|
||||
const char *serverType = wiz->customServer ? "rtmp_custom"
|
||||
: "rtmp_common";
|
||||
|
||||
OBSService service = obs_service_create(serverType,
|
||||
"temp_service", nullptr, nullptr);
|
||||
OBSService service = obs_service_create(
|
||||
serverType, "temp_service", nullptr, nullptr);
|
||||
obs_service_release(service);
|
||||
|
||||
OBSData service_settings = obs_data_create();
|
||||
|
@ -976,11 +981,11 @@ void AutoConfigTestPage::FinalizeResults()
|
|||
obs_data_set_string(service_settings, "service",
|
||||
wiz->serviceName.c_str());
|
||||
obs_service_update(service, service_settings);
|
||||
obs_service_apply_encoder_settings(service,
|
||||
vencoder_settings, nullptr);
|
||||
obs_service_apply_encoder_settings(service, vencoder_settings,
|
||||
nullptr);
|
||||
|
||||
wiz->idealBitrate = (int)obs_data_get_int(vencoder_settings,
|
||||
"bitrate");
|
||||
wiz->idealBitrate =
|
||||
(int)obs_data_get_int(vencoder_settings, "bitrate");
|
||||
|
||||
if (!wiz->customServer)
|
||||
form->addRow(
|
||||
|
@ -988,7 +993,8 @@ void AutoConfigTestPage::FinalizeResults()
|
|||
new QLabel(wiz->serviceName.c_str(),
|
||||
ui->finishPage));
|
||||
form->addRow(newLabel("Basic.AutoConfig.StreamPage.Server"),
|
||||
new QLabel(wiz->serverName.c_str(), ui->finishPage));
|
||||
new QLabel(wiz->serverName.c_str(),
|
||||
ui->finishPage));
|
||||
form->addRow(newLabel("Basic.Settings.Output.VideoBitrate"),
|
||||
new QLabel(QString::number(wiz->idealBitrate),
|
||||
ui->finishPage));
|
||||
|
@ -997,11 +1003,11 @@ void AutoConfigTestPage::FinalizeResults()
|
|||
ui->finishPage));
|
||||
}
|
||||
|
||||
QString baseRes = QString("%1x%2").arg(
|
||||
QString::number(wiz->baseResolutionCX),
|
||||
QString baseRes =
|
||||
QString("%1x%2").arg(QString::number(wiz->baseResolutionCX),
|
||||
QString::number(wiz->baseResolutionCY));
|
||||
QString scaleRes = QString("%1x%2").arg(
|
||||
QString::number(wiz->idealResolutionCX),
|
||||
QString scaleRes =
|
||||
QString("%1x%2").arg(QString::number(wiz->idealResolutionCX),
|
||||
QString::number(wiz->idealResolutionCY));
|
||||
|
||||
if (wiz->recordingEncoder != AutoConfig::Encoder::Stream ||
|
||||
|
@ -1027,8 +1033,7 @@ void AutoConfigTestPage::FinalizeResults()
|
|||
long double fps =
|
||||
(long double)wiz->idealFPSNum / (long double)wiz->idealFPSDen;
|
||||
|
||||
QString fpsStr = (wiz->idealFPSDen > 1)
|
||||
? QString::number(fps, 'f', 2)
|
||||
QString fpsStr = (wiz->idealFPSDen > 1) ? QString::number(fps, 'f', 2)
|
||||
: QString::number(fps, 'g', 2);
|
||||
|
||||
form->addRow(newLabel("Basic.Settings.Video.BaseResolution"),
|
||||
|
@ -1103,8 +1108,7 @@ void AutoConfigTestPage::Progress(int percentage)
|
|||
}
|
||||
|
||||
AutoConfigTestPage::AutoConfigTestPage(QWidget *parent)
|
||||
: QWizardPage (parent),
|
||||
ui (new Ui_AutoConfigTestPage)
|
||||
: QWizardPage(parent), ui(new Ui_AutoConfigTestPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setTitle(QTStr("Basic.AutoConfig.TestPage"));
|
||||
|
|
|
@ -37,8 +37,8 @@ static OBSData OpenServiceSettings(std::string &type)
|
|||
if (ret <= 0)
|
||||
return OBSData();
|
||||
|
||||
OBSData data = obs_data_create_from_json_file_safe(serviceJsonPath,
|
||||
"bak");
|
||||
OBSData data =
|
||||
obs_data_create_from_json_file_safe(serviceJsonPath, "bak");
|
||||
obs_data_release(data);
|
||||
|
||||
obs_data_set_default_string(data, "type", "rtmp_common");
|
||||
|
@ -63,8 +63,7 @@ static void GetServiceInfo(std::string &type, std::string &service,
|
|||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
AutoConfigStartPage::AutoConfigStartPage(QWidget *parent)
|
||||
: QWizardPage (parent),
|
||||
ui (new Ui_AutoConfigStartPage)
|
||||
: QWizardPage(parent), ui(new Ui_AutoConfigStartPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setTitle(QTStr("Basic.AutoConfig.StartPage"));
|
||||
|
@ -101,8 +100,7 @@ void AutoConfigStartPage::on_prioritizeRecording_clicked()
|
|||
#define FPS_PREFER_HIGH_RES RES_TEXT("FPS.PreferHighRes")
|
||||
|
||||
AutoConfigVideoPage::AutoConfigVideoPage(QWidget *parent)
|
||||
: QWizardPage (parent),
|
||||
ui (new Ui_AutoConfigVideoPage)
|
||||
: QWizardPage(parent), ui(new Ui_AutoConfigVideoPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -115,8 +113,7 @@ AutoConfigVideoPage::AutoConfigVideoPage(QWidget *parent)
|
|||
long double fpsVal =
|
||||
(long double)ovi.fps_num / (long double)ovi.fps_den;
|
||||
|
||||
QString fpsStr = (ovi.fps_den > 1)
|
||||
? QString::number(fpsVal, 'f', 2)
|
||||
QString fpsStr = (ovi.fps_den > 1) ? QString::number(fpsVal, 'f', 2)
|
||||
: QString::number(fpsVal, 'g', 2);
|
||||
|
||||
ui->fps->addItem(QTStr(FPS_PREFER_HIGH_FPS),
|
||||
|
@ -151,11 +148,9 @@ AutoConfigVideoPage::AutoConfigVideoPage(QWidget *parent)
|
|||
ui->canvasRes->addItem(str, encRes);
|
||||
}
|
||||
|
||||
auto addRes = [&] (int cx, int cy)
|
||||
{
|
||||
auto addRes = [&](int cx, int cy) {
|
||||
encRes = (cx << 16) | cy;
|
||||
QString str = QString("%1x%2").arg(
|
||||
QString::number(cx),
|
||||
QString str = QString("%1x%2").arg(QString::number(cx),
|
||||
QString::number(cy));
|
||||
ui->canvasRes->addItem(str, encRes);
|
||||
};
|
||||
|
@ -223,12 +218,11 @@ bool AutoConfigVideoPage::validatePage()
|
|||
|
||||
enum class ListOpt : int {
|
||||
ShowAll = 1,
|
||||
Custom
|
||||
Custom,
|
||||
};
|
||||
|
||||
AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent)
|
||||
: QWizardPage (parent),
|
||||
ui (new Ui_AutoConfigStreamPage)
|
||||
: QWizardPage(parent), ui(new Ui_AutoConfigStreamPage)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->bitrateLabel->setVisible(false);
|
||||
|
@ -255,29 +249,29 @@ AutoConfigStreamPage::AutoConfigStreamPage(QWidget *parent)
|
|||
|
||||
LoadServices(false);
|
||||
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(ServiceChanged()));
|
||||
connect(ui->customServer, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(ServiceChanged()));
|
||||
connect(ui->doBandwidthTest, SIGNAL(toggled(bool)),
|
||||
this, SLOT(ServiceChanged()));
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ServiceChanged()));
|
||||
connect(ui->customServer, SIGNAL(textChanged(const QString &)), this,
|
||||
SLOT(ServiceChanged()));
|
||||
connect(ui->doBandwidthTest, SIGNAL(toggled(bool)), this,
|
||||
SLOT(ServiceChanged()));
|
||||
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(UpdateServerList()));
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(UpdateServerList()));
|
||||
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(UpdateKeyLink()));
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(UpdateKeyLink()));
|
||||
|
||||
connect(ui->key, SIGNAL(textChanged(const QString &)),
|
||||
this, SLOT(UpdateCompleted()));
|
||||
connect(ui->regionUS, SIGNAL(toggled(bool)),
|
||||
this, SLOT(UpdateCompleted()));
|
||||
connect(ui->regionEU, SIGNAL(toggled(bool)),
|
||||
this, SLOT(UpdateCompleted()));
|
||||
connect(ui->regionAsia, SIGNAL(toggled(bool)),
|
||||
this, SLOT(UpdateCompleted()));
|
||||
connect(ui->regionOther, SIGNAL(toggled(bool)),
|
||||
this, SLOT(UpdateCompleted()));
|
||||
connect(ui->key, SIGNAL(textChanged(const QString &)), this,
|
||||
SLOT(UpdateCompleted()));
|
||||
connect(ui->regionUS, SIGNAL(toggled(bool)), this,
|
||||
SLOT(UpdateCompleted()));
|
||||
connect(ui->regionEU, SIGNAL(toggled(bool)), this,
|
||||
SLOT(UpdateCompleted()));
|
||||
connect(ui->regionAsia, SIGNAL(toggled(bool)), this,
|
||||
SLOT(UpdateCompleted()));
|
||||
connect(ui->regionOther, SIGNAL(toggled(bool)), this,
|
||||
SLOT(UpdateCompleted()));
|
||||
}
|
||||
|
||||
AutoConfigStreamPage::~AutoConfigStreamPage()
|
||||
|
@ -307,8 +301,7 @@ bool AutoConfigStreamPage::validatePage()
|
|||
|
||||
wiz->customServer = IsCustom();
|
||||
|
||||
const char *serverType = wiz->customServer
|
||||
? "rtmp_custom"
|
||||
const char *serverType = wiz->customServer ? "rtmp_custom"
|
||||
: "rtmp_common";
|
||||
|
||||
if (!wiz->customServer) {
|
||||
|
@ -365,8 +358,7 @@ bool AutoConfigStreamPage::validatePage()
|
|||
if (wiz->service != AutoConfig::Service::Twitch && wiz->bandwidthTest) {
|
||||
QMessageBox::StandardButton button;
|
||||
#define WARNING_TEXT(x) QTStr("Basic.AutoConfig.StreamPage.StreamWarning." x)
|
||||
button = OBSMessageBox::question(this,
|
||||
WARNING_TEXT("Title"),
|
||||
button = OBSMessageBox::question(this, WARNING_TEXT("Title"),
|
||||
WARNING_TEXT("Text"));
|
||||
#undef WARNING_TEXT
|
||||
|
||||
|
@ -440,8 +432,7 @@ void AutoConfigStreamPage::on_disconnectAccount_clicked()
|
|||
{
|
||||
QMessageBox::StandardButton button;
|
||||
|
||||
button = OBSMessageBox::question(this,
|
||||
QTStr(DISCONNECT_COMFIRM_TITLE),
|
||||
button = OBSMessageBox::question(this, QTStr(DISCONNECT_COMFIRM_TITLE),
|
||||
QTStr(DISCONNECT_COMFIRM_TEXT));
|
||||
|
||||
if (button == QMessageBox::No) {
|
||||
|
@ -479,14 +470,13 @@ static inline bool is_auth_service(const std::string &service)
|
|||
|
||||
void AutoConfigStreamPage::ServiceChanged()
|
||||
{
|
||||
bool showMore =
|
||||
ui->service->currentData().toInt() == (int)ListOpt::ShowAll;
|
||||
bool showMore = ui->service->currentData().toInt() ==
|
||||
(int)ListOpt::ShowAll;
|
||||
if (showMore)
|
||||
return;
|
||||
|
||||
std::string service = QT_TO_UTF8(ui->service->currentText());
|
||||
bool regionBased = service == "Twitch" ||
|
||||
service == "Smashcast";
|
||||
bool regionBased = service == "Twitch" || service == "Smashcast";
|
||||
bool testBandwidth = ui->doBandwidthTest->isChecked();
|
||||
bool custom = IsCustom();
|
||||
|
||||
|
@ -496,8 +486,7 @@ void AutoConfigStreamPage::ServiceChanged()
|
|||
if (cef) {
|
||||
if (lastService != service.c_str()) {
|
||||
bool can_auth = is_auth_service(service);
|
||||
int page = can_auth
|
||||
? (int)Section::Connect
|
||||
int page = can_auth ? (int)Section::Connect
|
||||
: (int)Section::StreamKey;
|
||||
|
||||
ui->stackedWidget->setCurrentIndex(page);
|
||||
|
@ -533,8 +522,8 @@ void AutoConfigStreamPage::ServiceChanged()
|
|||
ui->serverLabel->setVisible(true);
|
||||
} else {
|
||||
if (!testBandwidth)
|
||||
ui->streamkeyPageLayout->insertRow(2, ui->serverLabel,
|
||||
ui->serverStackedWidget);
|
||||
ui->streamkeyPageLayout->insertRow(
|
||||
2, ui->serverLabel, ui->serverStackedWidget);
|
||||
|
||||
ui->region->setVisible(regionBased && testBandwidth);
|
||||
ui->serverStackedWidget->setCurrentIndex(0);
|
||||
|
@ -574,13 +563,15 @@ void AutoConfigStreamPage::UpdateKeyLink()
|
|||
text += " <a href=\"https://";
|
||||
text += "www.twitch.tv/broadcast/dashboard/streamkey";
|
||||
text += "\">";
|
||||
text += QTStr("Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += QTStr(
|
||||
"Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += "</a>";
|
||||
} else if (serviceName == "YouTube / YouTube Gaming") {
|
||||
text += " <a href=\"https://";
|
||||
text += "www.youtube.com/live_dashboard";
|
||||
text += "\">";
|
||||
text += QTStr("Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += QTStr(
|
||||
"Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += "</a>";
|
||||
|
||||
isYoutube = true;
|
||||
|
@ -632,8 +623,8 @@ void AutoConfigStreamPage::LoadServices(bool showAll)
|
|||
QVariant((int)ListOpt::ShowAll));
|
||||
}
|
||||
|
||||
ui->service->insertItem(0,
|
||||
QTStr("Basic.AutoConfig.StreamPage.Service.Custom"),
|
||||
ui->service->insertItem(
|
||||
0, QTStr("Basic.AutoConfig.StreamPage.Service.Custom"),
|
||||
QVariant((int)ListOpt::Custom));
|
||||
|
||||
if (!lastService.isEmpty()) {
|
||||
|
@ -650,8 +641,8 @@ void AutoConfigStreamPage::LoadServices(bool showAll)
|
|||
void AutoConfigStreamPage::UpdateServerList()
|
||||
{
|
||||
QString serviceName = ui->service->currentText();
|
||||
bool showMore =
|
||||
ui->service->currentData().toInt() == (int)ListOpt::ShowAll;
|
||||
bool showMore = ui->service->currentData().toInt() ==
|
||||
(int)ListOpt::ShowAll;
|
||||
|
||||
if (showMore) {
|
||||
LoadServices(true);
|
||||
|
@ -706,8 +697,7 @@ void AutoConfigStreamPage::UpdateCompleted()
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
AutoConfig::AutoConfig(QWidget *parent)
|
||||
: QWizard(parent)
|
||||
AutoConfig::AutoConfig(QWidget *parent) : QWizard(parent)
|
||||
{
|
||||
EnableThreadedMessageBoxes(true);
|
||||
|
||||
|
@ -812,7 +802,8 @@ AutoConfig::AutoConfig(QWidget *parent)
|
|||
if (!key.empty())
|
||||
streamPage->ui->key->setText(key.c_str());
|
||||
|
||||
int bitrate = config_get_int(main->Config(), "SimpleOutput", "VBitrate");
|
||||
int bitrate =
|
||||
config_get_int(main->Config(), "SimpleOutput", "VBitrate");
|
||||
streamPage->ui->bitrate->setValue(bitrate);
|
||||
streamPage->ServiceChanged();
|
||||
|
||||
|
@ -929,9 +920,7 @@ void AutoConfig::SaveStreamSettings()
|
|||
/* ---------------------------------- */
|
||||
/* save service */
|
||||
|
||||
const char *service_id = customServer
|
||||
? "rtmp_custom"
|
||||
: "rtmp_common";
|
||||
const char *service_id = customServer ? "rtmp_custom" : "rtmp_common";
|
||||
|
||||
obs_service_t *oldService = main->GetService();
|
||||
OBSData hotkeyData = obs_hotkeys_save_service(oldService);
|
||||
|
@ -945,8 +934,8 @@ void AutoConfig::SaveStreamSettings()
|
|||
obs_data_set_string(settings, "server", server.c_str());
|
||||
obs_data_set_string(settings, "key", key.c_str());
|
||||
|
||||
OBSService newService = obs_service_create(service_id,
|
||||
"default_service", settings, hotkeyData);
|
||||
OBSService newService = obs_service_create(
|
||||
service_id, "default_service", settings, hotkeyData);
|
||||
obs_service_release(newService);
|
||||
|
||||
if (!newService)
|
||||
|
@ -976,12 +965,12 @@ void AutoConfig::SaveSettings()
|
|||
config_set_string(main->Config(), "SimpleOutput", "RecEncoder",
|
||||
GetEncoderId(recordingEncoder));
|
||||
|
||||
const char *quality = recordingQuality == Quality::High
|
||||
? "Small"
|
||||
const char *quality = recordingQuality == Quality::High ? "Small"
|
||||
: "Stream";
|
||||
|
||||
config_set_string(main->Config(), "Output", "Mode", "Simple");
|
||||
config_set_string(main->Config(), "SimpleOutput", "RecQuality", quality);
|
||||
config_set_string(main->Config(), "SimpleOutput", "RecQuality",
|
||||
quality);
|
||||
config_set_int(main->Config(), "Video", "BaseCX", baseResolutionCX);
|
||||
config_set_int(main->Config(), "Video", "BaseCY", baseResolutionCY);
|
||||
config_set_int(main->Config(), "Video", "OutputCX", idealResolutionCX);
|
||||
|
|
|
@ -32,13 +32,13 @@ class AutoConfig : public QWizard {
|
|||
enum class Type {
|
||||
Invalid,
|
||||
Streaming,
|
||||
Recording
|
||||
Recording,
|
||||
};
|
||||
|
||||
enum class Service {
|
||||
Twitch,
|
||||
Smashcast,
|
||||
Other
|
||||
Other,
|
||||
};
|
||||
|
||||
enum class Encoder {
|
||||
|
@ -46,12 +46,12 @@ class AutoConfig : public QWizard {
|
|||
NVENC,
|
||||
QSV,
|
||||
AMD,
|
||||
Stream
|
||||
Stream,
|
||||
};
|
||||
|
||||
enum class Quality {
|
||||
Stream,
|
||||
High
|
||||
High,
|
||||
};
|
||||
|
||||
enum class FPSType : int {
|
||||
|
@ -59,7 +59,7 @@ class AutoConfig : public QWizard {
|
|||
PreferHighRes,
|
||||
UseCurrent,
|
||||
fps30,
|
||||
fps60
|
||||
fps60,
|
||||
};
|
||||
|
||||
static inline const char *GetEncoderId(Encoder enc);
|
||||
|
@ -119,7 +119,7 @@ public:
|
|||
StartPage,
|
||||
VideoPage,
|
||||
StreamPage,
|
||||
TestPage
|
||||
TestPage,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -216,7 +216,7 @@ class AutoConfigTestPage : public QWizardPage {
|
|||
BandwidthTest,
|
||||
StreamEncoder,
|
||||
RecordingEncoder,
|
||||
Finished
|
||||
Finished,
|
||||
};
|
||||
|
||||
Stage stage = Stage::Starting;
|
||||
|
|
|
@ -39,23 +39,16 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
|||
: QDialog(parent),
|
||||
ui(new Ui::OBSBasicFilters),
|
||||
source(source_),
|
||||
addSignal (obs_source_get_signal_handler(source),
|
||||
"filter_add",
|
||||
OBSBasicFilters::OBSSourceFilterAdded,
|
||||
this),
|
||||
removeSignal (obs_source_get_signal_handler(source),
|
||||
"filter_remove",
|
||||
OBSBasicFilters::OBSSourceFilterRemoved,
|
||||
this),
|
||||
addSignal(obs_source_get_signal_handler(source), "filter_add",
|
||||
OBSBasicFilters::OBSSourceFilterAdded, this),
|
||||
removeSignal(obs_source_get_signal_handler(source), "filter_remove",
|
||||
OBSBasicFilters::OBSSourceFilterRemoved, this),
|
||||
reorderSignal(obs_source_get_signal_handler(source),
|
||||
"reorder_filters",
|
||||
OBSBasicFilters::OBSSourceReordered,
|
||||
"reorder_filters", OBSBasicFilters::OBSSourceReordered,
|
||||
this),
|
||||
removeSourceSignal (obs_source_get_signal_handler(source),
|
||||
"remove",
|
||||
removeSourceSignal(obs_source_get_signal_handler(source), "remove",
|
||||
OBSBasicFilters::SourceRemoved, this),
|
||||
renameSourceSignal (obs_source_get_signal_handler(source),
|
||||
"rename",
|
||||
renameSourceSignal(obs_source_get_signal_handler(source), "rename",
|
||||
OBSBasicFilters::SourceRenamed, this),
|
||||
noPreviewMargin(13)
|
||||
{
|
||||
|
@ -74,7 +67,8 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
|||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
#ifndef QT_NO_SHORTCUT
|
||||
ui->actionRemoveFilter->setShortcut(QApplication::translate("OBSBasicFilters", "Del", nullptr));
|
||||
ui->actionRemoveFilter->setShortcut(
|
||||
QApplication::translate("OBSBasicFilters", "Del", nullptr));
|
||||
#endif // QT_NO_SHORTCUT
|
||||
|
||||
addAction(ui->actionRemoveFilter);
|
||||
|
@ -87,22 +81,22 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
|||
SIGNAL(closeEditor(QWidget *,
|
||||
QAbstractItemDelegate::EndEditHint)),
|
||||
this,
|
||||
SLOT(AsyncFilterNameEdited(QWidget*,
|
||||
QAbstractItemDelegate::EndEditHint)));
|
||||
SLOT(AsyncFilterNameEdited(
|
||||
QWidget *, QAbstractItemDelegate::EndEditHint)));
|
||||
|
||||
connect(ui->effectFilters->itemDelegate(),
|
||||
SIGNAL(closeEditor(QWidget *,
|
||||
QAbstractItemDelegate::EndEditHint)),
|
||||
this,
|
||||
SLOT(EffectFilterNameEdited(QWidget*,
|
||||
QAbstractItemDelegate::EndEditHint)));
|
||||
SLOT(EffectFilterNameEdited(
|
||||
QWidget *, QAbstractItemDelegate::EndEditHint)));
|
||||
|
||||
QPushButton *close = ui->buttonBox->button(QDialogButtonBox::Close);
|
||||
connect(close, SIGNAL(clicked()), this, SLOT(close()));
|
||||
close->setDefault(true);
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->setText(
|
||||
QTStr("Defaults"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)
|
||||
->setText(QTStr("Defaults"));
|
||||
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Reset),
|
||||
SIGNAL(clicked()), this, SLOT(ResetFilters()));
|
||||
|
@ -124,10 +118,10 @@ OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
|||
if (audioOnly || (audio && !async))
|
||||
ui->asyncLabel->setText(QTStr("Basic.Filters.AudioFilters"));
|
||||
|
||||
auto addDrawCallback = [this] ()
|
||||
{
|
||||
auto addDrawCallback = [this]() {
|
||||
obs_display_add_draw_callback(ui->preview->GetDisplay(),
|
||||
OBSBasicFilters::DrawPreview, this);
|
||||
OBSBasicFilters::DrawPreview,
|
||||
this);
|
||||
};
|
||||
|
||||
enum obs_source_type type = obs_source_get_type(source);
|
||||
|
@ -187,14 +181,14 @@ void OBSBasicFilters::UpdatePropertiesView(int row, bool async)
|
|||
|
||||
obs_data_t *settings = obs_source_get_settings(filter);
|
||||
|
||||
view = new OBSPropertiesView(settings, filter,
|
||||
view = new OBSPropertiesView(
|
||||
settings, filter,
|
||||
(PropertiesReloadCallback)obs_source_properties,
|
||||
(PropertiesUpdateCallback)obs_source_update);
|
||||
|
||||
updatePropertiesSignal.Connect(obs_source_get_signal_handler(filter),
|
||||
"update_properties",
|
||||
OBSBasicFilters::UpdateProperties,
|
||||
this);
|
||||
OBSBasicFilters::UpdateProperties, this);
|
||||
|
||||
obs_data_release(settings);
|
||||
|
||||
|
@ -265,8 +259,8 @@ struct FilterOrderInfo {
|
|||
inline FilterOrderInfo(OBSBasicFilters *window_) : window(window_) {}
|
||||
};
|
||||
|
||||
void OBSBasicFilters::ReorderFilter(QListWidget *list,
|
||||
obs_source_t *filter, size_t idx)
|
||||
void OBSBasicFilters::ReorderFilter(QListWidget *list, obs_source_t *filter,
|
||||
size_t idx)
|
||||
{
|
||||
int count = list->count();
|
||||
|
||||
|
@ -282,8 +276,8 @@ void OBSBasicFilters::ReorderFilter(QListWidget *list,
|
|||
listItem = TakeListItem(list, i);
|
||||
if (listItem) {
|
||||
list->insertItem((int)idx, listItem);
|
||||
SetupVisibilityItem(list,
|
||||
listItem, filterItem);
|
||||
SetupVisibilityItem(list, listItem,
|
||||
filterItem);
|
||||
|
||||
if (sel)
|
||||
list->setCurrentRow((int)idx);
|
||||
|
@ -299,9 +293,9 @@ void OBSBasicFilters::ReorderFilters()
|
|||
{
|
||||
FilterOrderInfo info(this);
|
||||
|
||||
obs_source_enum_filters(source,
|
||||
[] (obs_source_t*, obs_source_t *filter, void *p)
|
||||
{
|
||||
obs_source_enum_filters(
|
||||
source,
|
||||
[](obs_source_t *, obs_source_t *filter, void *p) {
|
||||
FilterOrderInfo *info =
|
||||
reinterpret_cast<FilterOrderInfo *>(p);
|
||||
uint32_t flags;
|
||||
|
@ -312,14 +306,15 @@ void OBSBasicFilters::ReorderFilters()
|
|||
|
||||
if (async) {
|
||||
info->window->ReorderFilter(
|
||||
info->window->ui->asyncFilters,
|
||||
filter, info->asyncIdx++);
|
||||
info->window->ui->asyncFilters, filter,
|
||||
info->asyncIdx++);
|
||||
} else {
|
||||
info->window->ReorderFilter(
|
||||
info->window->ui->effectFilters,
|
||||
filter, info->effectIdx++);
|
||||
info->window->ui->effectFilters, filter,
|
||||
info->effectIdx++);
|
||||
}
|
||||
}, &info);
|
||||
},
|
||||
&info);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::UpdateFilters()
|
||||
|
@ -330,14 +325,15 @@ void OBSBasicFilters::UpdateFilters()
|
|||
ClearListItems(ui->effectFilters);
|
||||
ClearListItems(ui->asyncFilters);
|
||||
|
||||
obs_source_enum_filters(source,
|
||||
[] (obs_source_t*, obs_source_t *filter, void *p)
|
||||
{
|
||||
obs_source_enum_filters(
|
||||
source,
|
||||
[](obs_source_t *, obs_source_t *filter, void *p) {
|
||||
OBSBasicFilters *window =
|
||||
reinterpret_cast<OBSBasicFilters *>(p);
|
||||
|
||||
window->AddFilter(filter);
|
||||
}, this);
|
||||
},
|
||||
this);
|
||||
|
||||
main->SaveProject();
|
||||
}
|
||||
|
@ -372,7 +368,8 @@ QMenu *OBSBasicFilters::CreateAddFilterPopupMenu(bool async)
|
|||
|
||||
inline FilterInfo(const char *type_, const char *name_)
|
||||
: type(type_), name(name_)
|
||||
{}
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
vector<FilterInfo> types;
|
||||
|
@ -396,17 +393,17 @@ QMenu *OBSBasicFilters::CreateAddFilterPopupMenu(bool async)
|
|||
|
||||
QMenu *popup = new QMenu(QTStr("Add"), this);
|
||||
for (FilterInfo &type : types) {
|
||||
uint32_t filterFlags = obs_get_source_output_flags(
|
||||
type.type.c_str());
|
||||
uint32_t filterFlags =
|
||||
obs_get_source_output_flags(type.type.c_str());
|
||||
|
||||
if (!filter_compatible(async, sourceFlags, filterFlags))
|
||||
continue;
|
||||
|
||||
QAction *popupItem = new QAction(QT_UTF8(type.name.c_str()),
|
||||
this);
|
||||
QAction *popupItem =
|
||||
new QAction(QT_UTF8(type.name.c_str()), this);
|
||||
popupItem->setData(QT_UTF8(type.type.c_str()));
|
||||
connect(popupItem, SIGNAL(triggered(bool)),
|
||||
this, SLOT(AddFilterFromAction()));
|
||||
connect(popupItem, SIGNAL(triggered(bool)), this,
|
||||
SLOT(AddFilterFromAction()));
|
||||
popup->addAction(popupItem);
|
||||
|
||||
foundValues = true;
|
||||
|
@ -426,8 +423,8 @@ void OBSBasicFilters::AddNewFilter(const char *id)
|
|||
obs_source_t *existing_filter;
|
||||
string name = obs_source_get_display_name(id);
|
||||
|
||||
bool success = NameDialog::AskForName(this,
|
||||
QTStr("Basic.Filters.AddFilter.Title"),
|
||||
bool success = NameDialog::AskForName(
|
||||
this, QTStr("Basic.Filters.AddFilter.Title"),
|
||||
QTStr("Basic.FIlters.AddFilter.Text"), name,
|
||||
QT_UTF8(name.c_str()));
|
||||
if (!success)
|
||||
|
@ -441,23 +438,23 @@ void OBSBasicFilters::AddNewFilter(const char *id)
|
|||
return;
|
||||
}
|
||||
|
||||
existing_filter = obs_source_get_filter_by_name(source,
|
||||
name.c_str());
|
||||
existing_filter =
|
||||
obs_source_get_filter_by_name(source, name.c_str());
|
||||
if (existing_filter) {
|
||||
OBSMessageBox::warning(this,
|
||||
QTStr("NameExists.Title"),
|
||||
OBSMessageBox::warning(this, QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
obs_source_release(existing_filter);
|
||||
AddNewFilter(id);
|
||||
return;
|
||||
}
|
||||
|
||||
obs_source_t *filter = obs_source_create(id, name.c_str(),
|
||||
nullptr, nullptr);
|
||||
obs_source_t *filter =
|
||||
obs_source_create(id, name.c_str(), nullptr, nullptr);
|
||||
if (filter) {
|
||||
const char *sourceName = obs_source_get_name(source);
|
||||
|
||||
blog(LOG_INFO, "User added filter '%s' (%s) "
|
||||
blog(LOG_INFO,
|
||||
"User added filter '%s' (%s) "
|
||||
"to source '%s'",
|
||||
name.c_str(), id, sourceName);
|
||||
|
||||
|
@ -574,8 +571,8 @@ static bool QueryRemove(QWidget *parent, obs_source_t *source)
|
|||
|
||||
QMessageBox remove_source(parent);
|
||||
remove_source.setText(text);
|
||||
QAbstractButton *Yes = remove_source.addButton(QTStr("Yes"),
|
||||
QMessageBox::YesRole);
|
||||
QAbstractButton *Yes =
|
||||
remove_source.addButton(QTStr("Yes"), QMessageBox::YesRole);
|
||||
remove_source.addButton(QTStr("No"), QMessageBox::NoRole);
|
||||
remove_source.setIcon(QMessageBox::Question);
|
||||
remove_source.setWindowTitle(QTStr("ConfirmRemove.Title"));
|
||||
|
@ -704,11 +701,11 @@ void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async)
|
|||
popup.addMenu(addMenu);
|
||||
|
||||
if (item) {
|
||||
const char *renameSlot = async ?
|
||||
SLOT(RenameAsyncFilter()) : SLOT(RenameEffectFilter());
|
||||
const char *removeSlot = async ?
|
||||
SLOT(on_removeAsyncFilter_clicked()) :
|
||||
SLOT(on_removeEffectFilter_clicked());
|
||||
const char *renameSlot = async ? SLOT(RenameAsyncFilter())
|
||||
: SLOT(RenameEffectFilter());
|
||||
const char *removeSlot =
|
||||
async ? SLOT(on_removeAsyncFilter_clicked())
|
||||
: SLOT(on_removeEffectFilter_clicked());
|
||||
|
||||
popup.addSeparator();
|
||||
popup.addAction(QTStr("Rename"), this, renameSlot);
|
||||
|
@ -766,8 +763,8 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list)
|
|||
obs_source_t *foundFilter = nullptr;
|
||||
|
||||
if (!sameName)
|
||||
foundFilter = obs_source_get_filter_by_name(source,
|
||||
name.c_str());
|
||||
foundFilter =
|
||||
obs_source_get_filter_by_name(source, name.c_str());
|
||||
|
||||
if (foundFilter || name.empty() || sameName) {
|
||||
listItem->setText(QT_UTF8(prevName));
|
||||
|
@ -786,7 +783,8 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list)
|
|||
} else {
|
||||
const char *sourceName = obs_source_get_name(source);
|
||||
|
||||
blog(LOG_INFO, "User renamed filter '%s' on source '%s' to '%s'",
|
||||
blog(LOG_INFO,
|
||||
"User renamed filter '%s' on source '%s' to '%s'",
|
||||
prevName, sourceName, name.c_str());
|
||||
|
||||
listItem->setText(QT_UTF8(name.c_str()));
|
||||
|
@ -797,15 +795,15 @@ void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list)
|
|||
SetupVisibilityItem(list, listItem, filter);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::AsyncFilterNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint)
|
||||
void OBSBasicFilters::AsyncFilterNameEdited(
|
||||
QWidget *editor, QAbstractItemDelegate::EndEditHint endHint)
|
||||
{
|
||||
FilterNameEdited(editor, ui->asyncFilters);
|
||||
UNUSED_PARAMETER(endHint);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::EffectFilterNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint)
|
||||
void OBSBasicFilters::EffectFilterNameEdited(
|
||||
QWidget *editor, QAbstractItemDelegate::EndEditHint endHint)
|
||||
{
|
||||
FilterNameEdited(editor, ui->effectFilters);
|
||||
UNUSED_PARAMETER(endHint);
|
||||
|
|
|
@ -59,10 +59,10 @@ OBSBasicInteraction::OBSBasicInteraction(QWidget *parent, OBSSource source_)
|
|||
const char *name = obs_source_get_name(source);
|
||||
setWindowTitle(QTStr("Basic.InteractionWindow").arg(QT_UTF8(name)));
|
||||
|
||||
auto addDrawCallback = [this] ()
|
||||
{
|
||||
auto addDrawCallback = [this]() {
|
||||
obs_display_add_draw_callback(ui->preview->GetDisplay(),
|
||||
OBSBasicInteraction::DrawPreview, this);
|
||||
OBSBasicInteraction::DrawPreview,
|
||||
this);
|
||||
};
|
||||
|
||||
connect(ui->preview, &OBSQTDisplay::DisplayCreated, addDrawCallback);
|
||||
|
@ -77,9 +77,7 @@ OBSBasicInteraction::~OBSBasicInteraction()
|
|||
|
||||
OBSEventFilter *OBSBasicInteraction::BuildEventFilter()
|
||||
{
|
||||
return new OBSEventFilter(
|
||||
[this](QObject *obj, QEvent *event)
|
||||
{
|
||||
return new OBSEventFilter([this](QObject *obj, QEvent *event) {
|
||||
UNUSED_PARAMETER(obj);
|
||||
|
||||
switch (event->type()) {
|
||||
|
@ -149,8 +147,7 @@ void OBSBasicInteraction::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
|||
|
||||
gs_viewport_push();
|
||||
gs_projection_push();
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY),
|
||||
-100.0f, 100.0f);
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f);
|
||||
gs_set_viewport(x, y, newCX, newCY);
|
||||
obs_source_video_render(window->source);
|
||||
|
||||
|
@ -170,10 +167,13 @@ void OBSBasicInteraction::closeEvent(QCloseEvent *event)
|
|||
height());
|
||||
|
||||
obs_display_remove_draw_callback(ui->preview->GetDisplay(),
|
||||
OBSBasicInteraction::DrawPreview, this);
|
||||
OBSBasicInteraction::DrawPreview,
|
||||
this);
|
||||
}
|
||||
|
||||
static int TranslateQtKeyboardEventModifiers(QInputEvent *event, bool mouseEvent) {
|
||||
static int TranslateQtKeyboardEventModifiers(QInputEvent *event,
|
||||
bool mouseEvent)
|
||||
{
|
||||
int obsModifiers = INTERACT_NONE;
|
||||
|
||||
if (event->modifiers().testFlag(Qt::ShiftModifier))
|
||||
|
@ -200,8 +200,7 @@ static int TranslateQtKeyboardEventModifiers(QInputEvent *event, bool mouseEvent
|
|||
return obsModifiers;
|
||||
}
|
||||
|
||||
static int TranslateQtMouseEventModifiers(
|
||||
QMouseEvent *event)
|
||||
static int TranslateQtMouseEventModifiers(QMouseEvent *event)
|
||||
{
|
||||
int modifiers = TranslateQtKeyboardEventModifiers(event, true);
|
||||
|
||||
|
@ -215,8 +214,8 @@ static int TranslateQtMouseEventModifiers(
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
bool OBSBasicInteraction::GetSourceRelativeXY(
|
||||
int mouseX, int mouseY, int &relX, int &relY)
|
||||
bool OBSBasicInteraction::GetSourceRelativeXY(int mouseX, int mouseY, int &relX,
|
||||
int &relY)
|
||||
{
|
||||
QSize size = GetPixelSize(ui->preview);
|
||||
|
||||
|
@ -226,8 +225,8 @@ bool OBSBasicInteraction::GetSourceRelativeXY(
|
|||
int x, y;
|
||||
float scale;
|
||||
|
||||
GetScaleAndCenterPos(sourceCX, sourceCY, size.width(), size.height(),
|
||||
x, y, scale);
|
||||
GetScaleAndCenterPos(sourceCX, sourceCY, size.width(), size.height(), x,
|
||||
y, scale);
|
||||
|
||||
if (x > 0) {
|
||||
relX = int(float(mouseX - x) / scale);
|
||||
|
@ -246,8 +245,7 @@ bool OBSBasicInteraction::GetSourceRelativeXY(
|
|||
return true;
|
||||
}
|
||||
|
||||
bool OBSBasicInteraction::HandleMouseClickEvent(
|
||||
QMouseEvent *event)
|
||||
bool OBSBasicInteraction::HandleMouseClickEvent(QMouseEvent *event)
|
||||
{
|
||||
bool mouseUp = event->type() == QEvent::MouseButtonRelease;
|
||||
int clickCount = 1;
|
||||
|
@ -271,8 +269,7 @@ bool OBSBasicInteraction::HandleMouseClickEvent(
|
|||
button = MOUSE_RIGHT;
|
||||
break;
|
||||
default:
|
||||
blog(LOG_WARNING, "unknown button type %d",
|
||||
event->button());
|
||||
blog(LOG_WARNING, "unknown button type %d", event->button());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,13 +69,10 @@ protected:
|
|||
|
||||
typedef std::function<bool(QObject *, QEvent *)> EventFilterFunc;
|
||||
|
||||
class OBSEventFilter : public QObject
|
||||
{
|
||||
class OBSEventFilter : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OBSEventFilter(EventFilterFunc filter_)
|
||||
: filter(filter_)
|
||||
{}
|
||||
OBSEventFilter(EventFilterFunc filter_) : filter(filter_) {}
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event)
|
||||
|
|
|
@ -52,7 +52,8 @@ void CheckExistingCookieId()
|
|||
if (config_has_user_value(main->Config(), "Panels", "CookieId"))
|
||||
return;
|
||||
|
||||
config_set_string(main->Config(), "Panels", "CookieId", GenId().c_str());
|
||||
config_set_string(main->Config(), "Panels", "CookieId",
|
||||
GenId().c_str());
|
||||
}
|
||||
|
||||
#ifdef BROWSER_AVAILABLE
|
||||
|
@ -66,8 +67,8 @@ static void InitPanelCookieManager()
|
|||
CheckExistingCookieId();
|
||||
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
const char *cookie_id = config_get_string(main->Config(),
|
||||
"Panels", "CookieId");
|
||||
const char *cookie_id =
|
||||
config_get_string(main->Config(), "Panels", "CookieId");
|
||||
|
||||
std::string sub_path;
|
||||
sub_path += "obs_profile_cookies/";
|
||||
|
@ -102,8 +103,8 @@ void DuplicateCurrentCookieProfile(ConfigFile &config)
|
|||
#ifdef BROWSER_AVAILABLE
|
||||
if (cef) {
|
||||
OBSBasic *main = OBSBasic::Get();
|
||||
std::string cookie_id = config_get_string(main->Config(),
|
||||
"Panels", "CookieId");
|
||||
std::string cookie_id =
|
||||
config_get_string(main->Config(), "Panels", "CookieId");
|
||||
|
||||
std::string src_path;
|
||||
src_path += "obs_profile_cookies/";
|
||||
|
@ -155,8 +156,7 @@ void OBSBasic::InitBrowserPanelSafeBlock()
|
|||
return;
|
||||
}
|
||||
|
||||
ExecThreadedWithoutBlocking(
|
||||
[] {cef->wait_for_browser_init();},
|
||||
ExecThreadedWithoutBlocking([] { cef->wait_for_browser_init(); },
|
||||
QTStr("BrowserPanelInit.Title"),
|
||||
QTStr("BrowserPanelInit.Text"));
|
||||
InitPanelCookieManager();
|
||||
|
|
|
@ -11,34 +11,29 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
static const char *textExtensions[] = {
|
||||
"txt", "log", nullptr
|
||||
};
|
||||
static const char *textExtensions[] = {"txt", "log", nullptr};
|
||||
|
||||
static const char *imageExtensions[] = {
|
||||
"bmp", "tga", "png", "jpg", "jpeg", "gif", nullptr
|
||||
};
|
||||
static const char *imageExtensions[] = {"bmp", "tga", "png", "jpg",
|
||||
"jpeg", "gif", nullptr};
|
||||
|
||||
static const char *htmlExtensions[] = {
|
||||
"htm", "html", nullptr
|
||||
};
|
||||
static const char *htmlExtensions[] = {"htm", "html", nullptr};
|
||||
|
||||
static const char *mediaExtensions[] = {
|
||||
"3ga", "669", "a52", "aac", "ac3", "adt", "adts", "aif", "aifc",
|
||||
"aiff", "amb", "amr", "aob", "ape", "au", "awb", "caf", "dts",
|
||||
"flac", "it", "kar", "m4a", "m4b", "m4p", "m5p", "mid", "mka",
|
||||
"mlp", "mod", "mpa", "mp1", "mp2", "mp3", "mpc", "mpga", "mus",
|
||||
"oga", "ogg", "oma", "opus", "qcp", "ra", "rmi", "s3m", "sid",
|
||||
"spx", "tak", "thd", "tta", "voc", "vqf", "w64", "wav", "wma",
|
||||
"wv", "xa", "xm", "3g2", "3gp", "3gp2", "3gpp", "amv", "asf", "avi",
|
||||
"bik", "crf", "divx", "drc", "dv", "evo", "f4v", "flv", "gvi",
|
||||
"gxf", "iso", "m1v", "m2v", "m2t", "m2ts", "m4v", "mkv", "mov",
|
||||
"mp2", "mp2v", "mp4", "mp4v", "mpe", "mpeg", "mpeg1", "mpeg2",
|
||||
"mpeg4", "mpg", "mpv2", "mts", "mtv", "mxf", "mxg", "nsv", "nuv",
|
||||
"ogg", "ogm", "ogv", "ogx", "ps", "rec", "rm", "rmvb", "rpl", "thp",
|
||||
"tod", "ts", "tts", "txd", "vob", "vro", "webm", "wm", "wmv", "wtv",
|
||||
nullptr
|
||||
};
|
||||
"3ga", "669", "a52", "aac", "ac3", "adt", "adts", "aif",
|
||||
"aifc", "aiff", "amb", "amr", "aob", "ape", "au", "awb",
|
||||
"caf", "dts", "flac", "it", "kar", "m4a", "m4b", "m4p",
|
||||
"m5p", "mid", "mka", "mlp", "mod", "mpa", "mp1", "mp2",
|
||||
"mp3", "mpc", "mpga", "mus", "oga", "ogg", "oma", "opus",
|
||||
"qcp", "ra", "rmi", "s3m", "sid", "spx", "tak", "thd",
|
||||
"tta", "voc", "vqf", "w64", "wav", "wma", "wv", "xa",
|
||||
"xm", "3g2", "3gp", "3gp2", "3gpp", "amv", "asf", "avi",
|
||||
"bik", "crf", "divx", "drc", "dv", "evo", "f4v", "flv",
|
||||
"gvi", "gxf", "iso", "m1v", "m2v", "m2t", "m2ts", "m4v",
|
||||
"mkv", "mov", "mp2", "mp2v", "mp4", "mp4v", "mpe", "mpeg",
|
||||
"mpeg1", "mpeg2", "mpeg4", "mpg", "mpv2", "mts", "mtv", "mxf",
|
||||
"mxg", "nsv", "nuv", "ogg", "ogm", "ogv", "ogx", "ps",
|
||||
"rec", "rm", "rmvb", "rpl", "thp", "tod", "ts", "tts",
|
||||
"txd", "vob", "vro", "webm", "wm", "wmv", "wtv", nullptr};
|
||||
|
||||
static string GenerateSourceName(const char *base)
|
||||
{
|
||||
|
@ -188,4 +183,3 @@ if (found) \
|
|||
AddDropSource(QT_TO_UTF8(mimeData->text()), DropType_RawText);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ static void OBSStreamStarting(void *data, calldata_t *params)
|
|||
return;
|
||||
|
||||
output->delayActive = true;
|
||||
QMetaObject::invokeMethod(output->main,
|
||||
"StreamDelayStarting", Q_ARG(int, sec));
|
||||
QMetaObject::invokeMethod(output->main, "StreamDelayStarting",
|
||||
Q_ARG(int, sec));
|
||||
}
|
||||
|
||||
static void OBSStreamStopping(void *data, calldata_t *params)
|
||||
|
@ -37,8 +37,8 @@ static void OBSStreamStopping(void *data, calldata_t *params)
|
|||
if (sec == 0)
|
||||
QMetaObject::invokeMethod(output->main, "StreamStopping");
|
||||
else
|
||||
QMetaObject::invokeMethod(output->main,
|
||||
"StreamDelayStopping", Q_ARG(int, sec));
|
||||
QMetaObject::invokeMethod(output->main, "StreamDelayStopping",
|
||||
Q_ARG(int, sec));
|
||||
}
|
||||
|
||||
static void OBSStartStreaming(void *data, calldata_t *params)
|
||||
|
@ -62,8 +62,8 @@ static void OBSStopStreaming(void *data, calldata_t *params)
|
|||
output->streamingActive = false;
|
||||
output->delayActive = false;
|
||||
os_atomic_set_bool(&streaming_active, false);
|
||||
QMetaObject::invokeMethod(output->main,
|
||||
"StreamingStop", Q_ARG(int, code),
|
||||
QMetaObject::invokeMethod(output->main, "StreamingStop",
|
||||
Q_ARG(int, code),
|
||||
Q_ARG(QString, arg_last_error));
|
||||
}
|
||||
|
||||
|
@ -88,8 +88,8 @@ static void OBSStopRecording(void *data, calldata_t *params)
|
|||
|
||||
output->recordingActive = false;
|
||||
os_atomic_set_bool(&recording_active, false);
|
||||
QMetaObject::invokeMethod(output->main,
|
||||
"RecordingStop", Q_ARG(int, code),
|
||||
QMetaObject::invokeMethod(output->main, "RecordingStop",
|
||||
Q_ARG(int, code),
|
||||
Q_ARG(QString, arg_last_error));
|
||||
|
||||
UNUSED_PARAMETER(params);
|
||||
|
@ -121,8 +121,8 @@ static void OBSStopReplayBuffer(void *data, calldata_t *params)
|
|||
|
||||
output->replayBufferActive = false;
|
||||
os_atomic_set_bool(&replaybuf_active, false);
|
||||
QMetaObject::invokeMethod(output->main,
|
||||
"ReplayBufferStop", Q_ARG(int, code));
|
||||
QMetaObject::invokeMethod(output->main, "ReplayBufferStop",
|
||||
Q_ARG(int, code));
|
||||
|
||||
UNUSED_PARAMETER(params);
|
||||
}
|
||||
|
@ -247,8 +247,8 @@ struct SimpleOutput : BasicOutputHandler {
|
|||
|
||||
void SimpleOutput::LoadRecordingPreset_Lossless()
|
||||
{
|
||||
fileOutput = obs_output_create("ffmpeg_output",
|
||||
"simple_ffmpeg_output", nullptr, nullptr);
|
||||
fileOutput = obs_output_create("ffmpeg_output", "simple_ffmpeg_output",
|
||||
nullptr, nullptr);
|
||||
if (!fileOutput)
|
||||
throw "Failed to create recording FFmpeg output "
|
||||
"(simple output)";
|
||||
|
@ -267,8 +267,8 @@ void SimpleOutput::LoadRecordingPreset_Lossless()
|
|||
|
||||
void SimpleOutput::LoadRecordingPreset_h264(const char *encoderId)
|
||||
{
|
||||
h264Recording = obs_video_encoder_create(encoderId,
|
||||
"simple_h264_recording", nullptr, nullptr);
|
||||
h264Recording = obs_video_encoder_create(
|
||||
encoderId, "simple_h264_recording", nullptr, nullptr);
|
||||
if (!h264Recording)
|
||||
throw "Failed to create h264 recording encoder (simple output)";
|
||||
obs_encoder_release(h264Recording);
|
||||
|
@ -276,8 +276,8 @@ void SimpleOutput::LoadRecordingPreset_h264(const char *encoderId)
|
|||
|
||||
void SimpleOutput::LoadStreamingPreset_h264(const char *encoderId)
|
||||
{
|
||||
h264Streaming = obs_video_encoder_create(encoderId,
|
||||
"simple_h264_stream", nullptr, nullptr);
|
||||
h264Streaming = obs_video_encoder_create(
|
||||
encoderId, "simple_h264_stream", nullptr, nullptr);
|
||||
if (!h264Streaming)
|
||||
throw "Failed to create h264 streaming encoder (simple output)";
|
||||
obs_encoder_release(h264Streaming);
|
||||
|
@ -285,10 +285,10 @@ void SimpleOutput::LoadStreamingPreset_h264(const char *encoderId)
|
|||
|
||||
void SimpleOutput::LoadRecordingPreset()
|
||||
{
|
||||
const char *quality = config_get_string(main->Config(), "SimpleOutput",
|
||||
"RecQuality");
|
||||
const char *encoder = config_get_string(main->Config(), "SimpleOutput",
|
||||
"RecEncoder");
|
||||
const char *quality =
|
||||
config_get_string(main->Config(), "SimpleOutput", "RecQuality");
|
||||
const char *encoder =
|
||||
config_get_string(main->Config(), "SimpleOutput", "RecEncoder");
|
||||
|
||||
videoEncoder = encoder;
|
||||
videoQuality = quality;
|
||||
|
@ -345,8 +345,7 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
LoadStreamingPreset_h264("amd_amf_h264");
|
||||
|
||||
} else if (strcmp(encoder, SIMPLE_ENCODER_NVENC) == 0) {
|
||||
const char *id = EncoderAvailable("jim_nvenc")
|
||||
? "jim_nvenc"
|
||||
const char *id = EncoderAvailable("jim_nvenc") ? "jim_nvenc"
|
||||
: "ffmpeg_nvenc";
|
||||
LoadStreamingPreset_h264(id);
|
||||
|
||||
|
@ -364,11 +363,12 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
bool useReplayBuffer = config_get_bool(main->Config(),
|
||||
"SimpleOutput", "RecRB");
|
||||
if (useReplayBuffer) {
|
||||
const char *str = config_get_string(main->Config(),
|
||||
"Hotkeys", "ReplayBuffer");
|
||||
const char *str = config_get_string(
|
||||
main->Config(), "Hotkeys", "ReplayBuffer");
|
||||
obs_data_t *hotkey = obs_data_create_from_json(str);
|
||||
replayBuffer = obs_output_create("replay_buffer",
|
||||
Str("ReplayBuffer"), nullptr, hotkey);
|
||||
Str("ReplayBuffer"),
|
||||
nullptr, hotkey);
|
||||
|
||||
obs_data_release(hotkey);
|
||||
if (!replayBuffer)
|
||||
|
@ -384,11 +384,12 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
stopReplayBuffer.Connect(signal, "stop",
|
||||
OBSStopReplayBuffer, this);
|
||||
replayBufferStopping.Connect(signal, "stopping",
|
||||
OBSReplayBufferStopping, this);
|
||||
OBSReplayBufferStopping,
|
||||
this);
|
||||
}
|
||||
|
||||
fileOutput = obs_output_create("ffmpeg_muxer",
|
||||
"simple_file_output", nullptr, nullptr);
|
||||
fileOutput = obs_output_create(
|
||||
"ffmpeg_muxer", "simple_file_output", nullptr, nullptr);
|
||||
if (!fileOutput)
|
||||
throw "Failed to create recording output "
|
||||
"(simple output)";
|
||||
|
@ -397,8 +398,8 @@ SimpleOutput::SimpleOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
|
||||
startRecording.Connect(obs_output_get_signal_handler(fileOutput),
|
||||
"start", OBSStartRecording, this);
|
||||
stopRecording.Connect(obs_output_get_signal_handler(fileOutput),
|
||||
"stop", OBSStopRecording, this);
|
||||
stopRecording.Connect(obs_output_get_signal_handler(fileOutput), "stop",
|
||||
OBSStopRecording, this);
|
||||
recordStopping.Connect(obs_output_get_signal_handler(fileOutput),
|
||||
"stopping", OBSRecordStopping, this);
|
||||
}
|
||||
|
@ -416,15 +417,15 @@ void SimpleOutput::Update()
|
|||
obs_data_t *h264Settings = obs_data_create();
|
||||
obs_data_t *aacSettings = obs_data_create();
|
||||
|
||||
int videoBitrate = config_get_uint(main->Config(), "SimpleOutput",
|
||||
"VBitrate");
|
||||
int videoBitrate =
|
||||
config_get_uint(main->Config(), "SimpleOutput", "VBitrate");
|
||||
int audioBitrate = GetAudioBitrate();
|
||||
bool advanced = config_get_bool(main->Config(), "SimpleOutput",
|
||||
"UseAdvanced");
|
||||
bool advanced =
|
||||
config_get_bool(main->Config(), "SimpleOutput", "UseAdvanced");
|
||||
bool enforceBitrate = config_get_bool(main->Config(), "SimpleOutput",
|
||||
"EnforceBitrate");
|
||||
const char *custom = config_get_string(main->Config(),
|
||||
"SimpleOutput", "x264Settings");
|
||||
const char *custom = config_get_string(main->Config(), "SimpleOutput",
|
||||
"x264Settings");
|
||||
const char *encoder = config_get_string(main->Config(), "SimpleOutput",
|
||||
"StreamEncoder");
|
||||
const char *presetType;
|
||||
|
@ -457,8 +458,8 @@ void SimpleOutput::Update()
|
|||
obs_data_set_string(aacSettings, "rate_control", "CBR");
|
||||
obs_data_set_int(aacSettings, "bitrate", audioBitrate);
|
||||
|
||||
obs_service_apply_encoder_settings(main->GetService(),
|
||||
h264Settings, aacSettings);
|
||||
obs_service_apply_encoder_settings(main->GetService(), h264Settings,
|
||||
aacSettings);
|
||||
|
||||
if (advanced && !enforceBitrate) {
|
||||
obs_data_set_int(h264Settings, "bitrate", videoBitrate);
|
||||
|
@ -696,31 +697,33 @@ bool SimpleOutput::StartStreaming(obs_service_t *service)
|
|||
startStreaming.Disconnect();
|
||||
stopStreaming.Disconnect();
|
||||
|
||||
streamOutput = obs_output_create(type, "simple_stream",
|
||||
nullptr, nullptr);
|
||||
streamOutput = obs_output_create(type, "simple_stream", nullptr,
|
||||
nullptr);
|
||||
if (!streamOutput) {
|
||||
blog(LOG_WARNING, "Creation of stream output type '%s' "
|
||||
"failed!", type);
|
||||
blog(LOG_WARNING,
|
||||
"Creation of stream output type '%s' "
|
||||
"failed!",
|
||||
type);
|
||||
return false;
|
||||
}
|
||||
obs_output_release(streamOutput);
|
||||
|
||||
streamDelayStarting.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"starting", OBSStreamStarting, this);
|
||||
obs_output_get_signal_handler(streamOutput), "starting",
|
||||
OBSStreamStarting, this);
|
||||
streamStopping.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"stopping", OBSStreamStopping, this);
|
||||
obs_output_get_signal_handler(streamOutput), "stopping",
|
||||
OBSStreamStopping, this);
|
||||
|
||||
startStreaming.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"start", OBSStartStreaming, this);
|
||||
obs_output_get_signal_handler(streamOutput), "start",
|
||||
OBSStartStreaming, this);
|
||||
stopStreaming.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"stop", OBSStopStreaming, this);
|
||||
obs_output_get_signal_handler(streamOutput), "stop",
|
||||
OBSStopStreaming, this);
|
||||
|
||||
bool isEncoded = obs_output_get_flags(streamOutput)
|
||||
& OBS_OUTPUT_ENCODED;
|
||||
bool isEncoded = obs_output_get_flags(streamOutput) &
|
||||
OBS_OUTPUT_ENCODED;
|
||||
|
||||
if (isEncoded) {
|
||||
const char *codec =
|
||||
|
@ -732,15 +735,15 @@ bool SimpleOutput::StartStreaming(obs_service_t *service)
|
|||
}
|
||||
|
||||
if (strcmp(codec, "aac") != 0) {
|
||||
const char *id = FindAudioEncoderFromCodec(
|
||||
codec);
|
||||
const char *id =
|
||||
FindAudioEncoderFromCodec(codec);
|
||||
int audioBitrate = GetAudioBitrate();
|
||||
obs_data_t *settings = obs_data_create();
|
||||
obs_data_set_int(settings, "bitrate",
|
||||
audioBitrate);
|
||||
|
||||
aacStreaming = obs_audio_encoder_create(id,
|
||||
"alt_audio_enc", nullptr, 0,
|
||||
aacStreaming = obs_audio_encoder_create(
|
||||
id, "alt_audio_enc", nullptr, 0,
|
||||
nullptr);
|
||||
obs_encoder_release(aacStreaming);
|
||||
if (!aacStreaming)
|
||||
|
@ -763,24 +766,22 @@ bool SimpleOutput::StartStreaming(obs_service_t *service)
|
|||
|
||||
/* --------------------- */
|
||||
|
||||
bool reconnect = config_get_bool(main->Config(), "Output",
|
||||
"Reconnect");
|
||||
int retryDelay = config_get_uint(main->Config(), "Output",
|
||||
"RetryDelay");
|
||||
int maxRetries = config_get_uint(main->Config(), "Output",
|
||||
"MaxRetries");
|
||||
bool useDelay = config_get_bool(main->Config(), "Output",
|
||||
"DelayEnable");
|
||||
int delaySec = config_get_int(main->Config(), "Output",
|
||||
"DelaySec");
|
||||
bool preserveDelay = config_get_bool(main->Config(), "Output",
|
||||
"DelayPreserve");
|
||||
const char *bindIP = config_get_string(main->Config(), "Output",
|
||||
"BindIP");
|
||||
bool reconnect = config_get_bool(main->Config(), "Output", "Reconnect");
|
||||
int retryDelay =
|
||||
config_get_uint(main->Config(), "Output", "RetryDelay");
|
||||
int maxRetries =
|
||||
config_get_uint(main->Config(), "Output", "MaxRetries");
|
||||
bool useDelay =
|
||||
config_get_bool(main->Config(), "Output", "DelayEnable");
|
||||
int delaySec = config_get_int(main->Config(), "Output", "DelaySec");
|
||||
bool preserveDelay =
|
||||
config_get_bool(main->Config(), "Output", "DelayPreserve");
|
||||
const char *bindIP =
|
||||
config_get_string(main->Config(), "Output", "BindIP");
|
||||
bool enableNewSocketLoop = config_get_bool(main->Config(), "Output",
|
||||
"NewSocketLoopEnable");
|
||||
bool enableLowLatencyMode = config_get_bool(main->Config(), "Output",
|
||||
"LowLatencyEnable");
|
||||
bool enableLowLatencyMode =
|
||||
config_get_bool(main->Config(), "Output", "LowLatencyEnable");
|
||||
|
||||
obs_data_t *settings = obs_data_create();
|
||||
obs_data_set_string(settings, "bind_ip", bindIP);
|
||||
|
@ -797,8 +798,7 @@ bool SimpleOutput::StartStreaming(obs_service_t *service)
|
|||
obs_output_set_delay(streamOutput, useDelay ? delaySec : 0,
|
||||
preserveDelay ? OBS_OUTPUT_DELAY_PRESERVE : 0);
|
||||
|
||||
obs_output_set_reconnect_settings(streamOutput, maxRetries,
|
||||
retryDelay);
|
||||
obs_output_set_reconnect_settings(streamOutput, maxRetries, retryDelay);
|
||||
|
||||
if (obs_output_start(streamOutput)) {
|
||||
return true;
|
||||
|
@ -812,8 +812,7 @@ bool SimpleOutput::StartStreaming(obs_service_t *service)
|
|||
lastError = string();
|
||||
|
||||
blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type,
|
||||
hasLastError ? " Last Error: " : "",
|
||||
hasLastError ? error : "");
|
||||
hasLastError ? " Last Error: " : "", hasLastError ? error : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -871,26 +870,26 @@ void SimpleOutput::UpdateRecording()
|
|||
|
||||
bool SimpleOutput::ConfigureRecording(bool updateReplayBuffer)
|
||||
{
|
||||
const char *path = config_get_string(main->Config(),
|
||||
"SimpleOutput", "FilePath");
|
||||
const char *format = config_get_string(main->Config(),
|
||||
"SimpleOutput", "RecFormat");
|
||||
const char *path =
|
||||
config_get_string(main->Config(), "SimpleOutput", "FilePath");
|
||||
const char *format =
|
||||
config_get_string(main->Config(), "SimpleOutput", "RecFormat");
|
||||
const char *mux = config_get_string(main->Config(), "SimpleOutput",
|
||||
"MuxerCustom");
|
||||
bool noSpace = config_get_bool(main->Config(), "SimpleOutput",
|
||||
"FileNameWithoutSpace");
|
||||
const char *filenameFormat = config_get_string(main->Config(), "Output",
|
||||
"FilenameFormatting");
|
||||
bool overwriteIfExists = config_get_bool(main->Config(), "Output",
|
||||
"OverwriteIfExists");
|
||||
bool overwriteIfExists =
|
||||
config_get_bool(main->Config(), "Output", "OverwriteIfExists");
|
||||
const char *rbPrefix = config_get_string(main->Config(), "SimpleOutput",
|
||||
"RecRBPrefix");
|
||||
const char *rbSuffix = config_get_string(main->Config(), "SimpleOutput",
|
||||
"RecRBSuffix");
|
||||
int rbTime = config_get_int(main->Config(), "SimpleOutput",
|
||||
"RecRBTime");
|
||||
int rbSize = config_get_int(main->Config(), "SimpleOutput",
|
||||
"RecRBSize");
|
||||
int rbTime =
|
||||
config_get_int(main->Config(), "SimpleOutput", "RecRBTime");
|
||||
int rbSize =
|
||||
config_get_int(main->Config(), "SimpleOutput", "RecRBSize");
|
||||
|
||||
os_dir_t *dir = path && path[0] ? os_opendir(path) : nullptr;
|
||||
|
||||
|
@ -990,8 +989,7 @@ bool SimpleOutput::StartReplayBuffer()
|
|||
if (!ConfigureRecording(true))
|
||||
return false;
|
||||
if (!obs_output_start(replayBuffer)) {
|
||||
QMessageBox::critical(main,
|
||||
QTStr("Output.StartReplayFailed"),
|
||||
QMessageBox::critical(main, QTStr("Output.StartReplayFailed"),
|
||||
QTStr("Output.StartFailedGeneric"));
|
||||
return false;
|
||||
}
|
||||
|
@ -1111,15 +1109,16 @@ static void ApplyEncoderDefaults(OBSData &settings,
|
|||
|
||||
AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
||||
{
|
||||
const char *recType = config_get_string(main->Config(), "AdvOut",
|
||||
"RecType");
|
||||
const char *streamEncoder = config_get_string(main->Config(), "AdvOut",
|
||||
"Encoder");
|
||||
const char *recordEncoder = config_get_string(main->Config(), "AdvOut",
|
||||
"RecEncoder");
|
||||
const char *recType =
|
||||
config_get_string(main->Config(), "AdvOut", "RecType");
|
||||
const char *streamEncoder =
|
||||
config_get_string(main->Config(), "AdvOut", "Encoder");
|
||||
const char *recordEncoder =
|
||||
config_get_string(main->Config(), "AdvOut", "RecEncoder");
|
||||
|
||||
ffmpegOutput = astrcmpi(recType, "FFmpeg") == 0;
|
||||
ffmpegRecording = ffmpegOutput &&
|
||||
ffmpegRecording =
|
||||
ffmpegOutput &&
|
||||
config_get_bool(main->Config(), "AdvOut", "FFOutputToFile");
|
||||
useStreamEncoder = astrcmpi(recordEncoder, "none") == 0;
|
||||
|
||||
|
@ -1136,21 +1135,22 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
astrcmpi(rate_control, "ABR") == 0;
|
||||
|
||||
if (ffmpegOutput) {
|
||||
fileOutput = obs_output_create("ffmpeg_output",
|
||||
"adv_ffmpeg_output", nullptr, nullptr);
|
||||
fileOutput = obs_output_create(
|
||||
"ffmpeg_output", "adv_ffmpeg_output", nullptr, nullptr);
|
||||
if (!fileOutput)
|
||||
throw "Failed to create recording FFmpeg output "
|
||||
"(advanced output)";
|
||||
obs_output_release(fileOutput);
|
||||
} else {
|
||||
bool useReplayBuffer = config_get_bool(main->Config(),
|
||||
"AdvOut", "RecRB");
|
||||
bool useReplayBuffer =
|
||||
config_get_bool(main->Config(), "AdvOut", "RecRB");
|
||||
if (useReplayBuffer) {
|
||||
const char *str = config_get_string(main->Config(),
|
||||
"Hotkeys", "ReplayBuffer");
|
||||
const char *str = config_get_string(
|
||||
main->Config(), "Hotkeys", "ReplayBuffer");
|
||||
obs_data_t *hotkey = obs_data_create_from_json(str);
|
||||
replayBuffer = obs_output_create("replay_buffer",
|
||||
Str("ReplayBuffer"), nullptr, hotkey);
|
||||
Str("ReplayBuffer"),
|
||||
nullptr, hotkey);
|
||||
|
||||
obs_data_release(hotkey);
|
||||
if (!replayBuffer)
|
||||
|
@ -1159,28 +1159,28 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
obs_output_release(replayBuffer);
|
||||
|
||||
signal_handler_t *signal =
|
||||
obs_output_get_signal_handler(
|
||||
replayBuffer);
|
||||
obs_output_get_signal_handler(replayBuffer);
|
||||
|
||||
startReplayBuffer.Connect(signal, "start",
|
||||
OBSStartReplayBuffer, this);
|
||||
stopReplayBuffer.Connect(signal, "stop",
|
||||
OBSStopReplayBuffer, this);
|
||||
replayBufferStopping.Connect(signal, "stopping",
|
||||
OBSReplayBufferStopping, this);
|
||||
OBSReplayBufferStopping,
|
||||
this);
|
||||
}
|
||||
|
||||
fileOutput = obs_output_create("ffmpeg_muxer",
|
||||
"adv_file_output", nullptr, nullptr);
|
||||
fileOutput = obs_output_create(
|
||||
"ffmpeg_muxer", "adv_file_output", nullptr, nullptr);
|
||||
if (!fileOutput)
|
||||
throw "Failed to create recording output "
|
||||
"(advanced output)";
|
||||
obs_output_release(fileOutput);
|
||||
|
||||
if (!useStreamEncoder) {
|
||||
h264Recording = obs_video_encoder_create(recordEncoder,
|
||||
"recording_h264", recordEncSettings,
|
||||
nullptr);
|
||||
h264Recording = obs_video_encoder_create(
|
||||
recordEncoder, "recording_h264",
|
||||
recordEncSettings, nullptr);
|
||||
if (!h264Recording)
|
||||
throw "Failed to create recording h264 "
|
||||
"encoder (advanced output)";
|
||||
|
@ -1188,8 +1188,8 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
}
|
||||
}
|
||||
|
||||
h264Streaming = obs_video_encoder_create(streamEncoder,
|
||||
"streaming_h264", streamEncSettings, nullptr);
|
||||
h264Streaming = obs_video_encoder_create(
|
||||
streamEncoder, "streaming_h264", streamEncSettings, nullptr);
|
||||
if (!h264Streaming)
|
||||
throw "Failed to create streaming h264 encoder "
|
||||
"(advanced output)";
|
||||
|
@ -1207,8 +1207,8 @@ AdvancedOutput::AdvancedOutput(OBSBasic *main_) : BasicOutputHandler(main_)
|
|||
|
||||
startRecording.Connect(obs_output_get_signal_handler(fileOutput),
|
||||
"start", OBSStartRecording, this);
|
||||
stopRecording.Connect(obs_output_get_signal_handler(fileOutput),
|
||||
"stop", OBSStopRecording, this);
|
||||
stopRecording.Connect(obs_output_get_signal_handler(fileOutput), "stop",
|
||||
OBSStopRecording, this);
|
||||
recordStopping.Connect(obs_output_get_signal_handler(fileOutput),
|
||||
"stopping", OBSRecordStopping, this);
|
||||
}
|
||||
|
@ -1222,8 +1222,8 @@ void AdvancedOutput::UpdateStreamSettings()
|
|||
ApplyEncoderDefaults(settings, h264Streaming);
|
||||
|
||||
if (applyServiceSettings)
|
||||
obs_service_apply_encoder_settings(main->GetService(),
|
||||
settings, nullptr);
|
||||
obs_service_apply_encoder_settings(main->GetService(), settings,
|
||||
nullptr);
|
||||
|
||||
video_t *video = obs_get_video();
|
||||
enum video_format format = video_output_get_format(video);
|
||||
|
@ -1251,10 +1251,9 @@ void AdvancedOutput::Update()
|
|||
|
||||
inline void AdvancedOutput::SetupStreaming()
|
||||
{
|
||||
bool rescale = config_get_bool(main->Config(), "AdvOut",
|
||||
"Rescale");
|
||||
const char *rescaleRes = config_get_string(main->Config(), "AdvOut",
|
||||
"RescaleRes");
|
||||
bool rescale = config_get_bool(main->Config(), "AdvOut", "Rescale");
|
||||
const char *rescaleRes =
|
||||
config_get_string(main->Config(), "AdvOut", "RescaleRes");
|
||||
uint32_t caps = obs_encoder_get_caps(h264Streaming);
|
||||
unsigned int cx = 0;
|
||||
unsigned int cy = 0;
|
||||
|
@ -1276,14 +1275,13 @@ inline void AdvancedOutput::SetupStreaming()
|
|||
|
||||
inline void AdvancedOutput::SetupRecording()
|
||||
{
|
||||
const char *path = config_get_string(main->Config(), "AdvOut",
|
||||
"RecFilePath");
|
||||
const char *mux = config_get_string(main->Config(), "AdvOut",
|
||||
"RecMuxerCustom");
|
||||
bool rescale = config_get_bool(main->Config(), "AdvOut",
|
||||
"RecRescale");
|
||||
const char *rescaleRes = config_get_string(main->Config(), "AdvOut",
|
||||
"RecRescaleRes");
|
||||
const char *path =
|
||||
config_get_string(main->Config(), "AdvOut", "RecFilePath");
|
||||
const char *mux =
|
||||
config_get_string(main->Config(), "AdvOut", "RecMuxerCustom");
|
||||
bool rescale = config_get_bool(main->Config(), "AdvOut", "RecRescale");
|
||||
const char *rescaleRes =
|
||||
config_get_string(main->Config(), "AdvOut", "RecRescaleRes");
|
||||
int tracks = config_get_int(main->Config(), "AdvOut", "RecTracks");
|
||||
obs_data_t *settings = obs_data_create();
|
||||
unsigned int cx = 0;
|
||||
|
@ -1341,36 +1339,31 @@ inline void AdvancedOutput::SetupRecording()
|
|||
inline void AdvancedOutput::SetupFFmpeg()
|
||||
{
|
||||
const char *url = config_get_string(main->Config(), "AdvOut", "FFURL");
|
||||
int vBitrate = config_get_int(main->Config(), "AdvOut",
|
||||
"FFVBitrate");
|
||||
int gopSize = config_get_int(main->Config(), "AdvOut",
|
||||
"FFVGOPSize");
|
||||
bool rescale = config_get_bool(main->Config(), "AdvOut",
|
||||
"FFRescale");
|
||||
const char *rescaleRes = config_get_string(main->Config(), "AdvOut",
|
||||
"FFRescaleRes");
|
||||
const char *formatName = config_get_string(main->Config(), "AdvOut",
|
||||
"FFFormat");
|
||||
const char *mimeType = config_get_string(main->Config(), "AdvOut",
|
||||
"FFFormatMimeType");
|
||||
const char *muxCustom = config_get_string(main->Config(), "AdvOut",
|
||||
"FFMCustom");
|
||||
const char *vEncoder = config_get_string(main->Config(), "AdvOut",
|
||||
"FFVEncoder");
|
||||
int vEncoderId = config_get_int(main->Config(), "AdvOut",
|
||||
"FFVEncoderId");
|
||||
const char *vEncCustom = config_get_string(main->Config(), "AdvOut",
|
||||
"FFVCustom");
|
||||
int aBitrate = config_get_int(main->Config(), "AdvOut",
|
||||
"FFABitrate");
|
||||
int aMixes = config_get_int(main->Config(), "AdvOut",
|
||||
"FFAudioMixes");
|
||||
const char *aEncoder = config_get_string(main->Config(), "AdvOut",
|
||||
"FFAEncoder");
|
||||
int aEncoderId = config_get_int(main->Config(), "AdvOut",
|
||||
"FFAEncoderId");
|
||||
const char *aEncCustom = config_get_string(main->Config(), "AdvOut",
|
||||
"FFACustom");
|
||||
int vBitrate = config_get_int(main->Config(), "AdvOut", "FFVBitrate");
|
||||
int gopSize = config_get_int(main->Config(), "AdvOut", "FFVGOPSize");
|
||||
bool rescale = config_get_bool(main->Config(), "AdvOut", "FFRescale");
|
||||
const char *rescaleRes =
|
||||
config_get_string(main->Config(), "AdvOut", "FFRescaleRes");
|
||||
const char *formatName =
|
||||
config_get_string(main->Config(), "AdvOut", "FFFormat");
|
||||
const char *mimeType =
|
||||
config_get_string(main->Config(), "AdvOut", "FFFormatMimeType");
|
||||
const char *muxCustom =
|
||||
config_get_string(main->Config(), "AdvOut", "FFMCustom");
|
||||
const char *vEncoder =
|
||||
config_get_string(main->Config(), "AdvOut", "FFVEncoder");
|
||||
int vEncoderId =
|
||||
config_get_int(main->Config(), "AdvOut", "FFVEncoderId");
|
||||
const char *vEncCustom =
|
||||
config_get_string(main->Config(), "AdvOut", "FFVCustom");
|
||||
int aBitrate = config_get_int(main->Config(), "AdvOut", "FFABitrate");
|
||||
int aMixes = config_get_int(main->Config(), "AdvOut", "FFAudioMixes");
|
||||
const char *aEncoder =
|
||||
config_get_string(main->Config(), "AdvOut", "FFAEncoder");
|
||||
int aEncoderId =
|
||||
config_get_int(main->Config(), "AdvOut", "FFAEncoderId");
|
||||
const char *aEncCustom =
|
||||
config_get_string(main->Config(), "AdvOut", "FFACustom");
|
||||
obs_data_t *settings = obs_data_create();
|
||||
|
||||
obs_data_set_string(settings, "url", url);
|
||||
|
@ -1415,8 +1408,8 @@ inline void AdvancedOutput::UpdateAudioSettings()
|
|||
{
|
||||
bool applyServiceSettings = config_get_bool(main->Config(), "AdvOut",
|
||||
"ApplyServiceSettings");
|
||||
int streamTrackIndex = config_get_int(main->Config(), "AdvOut",
|
||||
"TrackIndex");
|
||||
int streamTrackIndex =
|
||||
config_get_int(main->Config(), "AdvOut", "TrackIndex");
|
||||
obs_data_t *settings[MAX_AUDIO_MIXES];
|
||||
|
||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||
|
@ -1438,8 +1431,8 @@ inline void AdvancedOutput::UpdateAudioSettings()
|
|||
|
||||
for (size_t i = 0; i < MAX_AUDIO_MIXES; i++) {
|
||||
if (applyServiceSettings && (int)(i + 1) == streamTrackIndex)
|
||||
obs_service_apply_encoder_settings(main->GetService(),
|
||||
nullptr, settings[i]);
|
||||
obs_service_apply_encoder_settings(
|
||||
main->GetService(), nullptr, settings[i]);
|
||||
|
||||
obs_encoder_update(aacTrack[i], settings[i]);
|
||||
obs_data_release(settings[i]);
|
||||
|
@ -1465,9 +1458,8 @@ void AdvancedOutput::SetupOutputs()
|
|||
int AdvancedOutput::GetAudioBitrate(size_t i) const
|
||||
{
|
||||
static const char *names[] = {
|
||||
"Track1Bitrate", "Track2Bitrate",
|
||||
"Track3Bitrate", "Track4Bitrate",
|
||||
"Track5Bitrate", "Track6Bitrate",
|
||||
"Track1Bitrate", "Track2Bitrate", "Track3Bitrate",
|
||||
"Track4Bitrate", "Track5Bitrate", "Track6Bitrate",
|
||||
};
|
||||
int bitrate = (int)config_get_uint(main->Config(), "AdvOut", names[i]);
|
||||
return FindClosestAvailableAACBitrate(bitrate);
|
||||
|
@ -1491,8 +1483,7 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
|||
|
||||
/* --------------------- */
|
||||
|
||||
int trackIndex = config_get_int(main->Config(), "AdvOut",
|
||||
"TrackIndex");
|
||||
int trackIndex = config_get_int(main->Config(), "AdvOut", "TrackIndex");
|
||||
|
||||
const char *type = obs_service_get_output_type(service);
|
||||
if (!type)
|
||||
|
@ -1505,31 +1496,33 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
|||
startStreaming.Disconnect();
|
||||
stopStreaming.Disconnect();
|
||||
|
||||
streamOutput = obs_output_create(type, "adv_stream",
|
||||
nullptr, nullptr);
|
||||
streamOutput =
|
||||
obs_output_create(type, "adv_stream", nullptr, nullptr);
|
||||
if (!streamOutput) {
|
||||
blog(LOG_WARNING, "Creation of stream output type '%s' "
|
||||
"failed!", type);
|
||||
blog(LOG_WARNING,
|
||||
"Creation of stream output type '%s' "
|
||||
"failed!",
|
||||
type);
|
||||
return false;
|
||||
}
|
||||
obs_output_release(streamOutput);
|
||||
|
||||
streamDelayStarting.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"starting", OBSStreamStarting, this);
|
||||
obs_output_get_signal_handler(streamOutput), "starting",
|
||||
OBSStreamStarting, this);
|
||||
streamStopping.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"stopping", OBSStreamStopping, this);
|
||||
obs_output_get_signal_handler(streamOutput), "stopping",
|
||||
OBSStreamStopping, this);
|
||||
|
||||
startStreaming.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"start", OBSStartStreaming, this);
|
||||
obs_output_get_signal_handler(streamOutput), "start",
|
||||
OBSStartStreaming, this);
|
||||
stopStreaming.Connect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"stop", OBSStopStreaming, this);
|
||||
obs_output_get_signal_handler(streamOutput), "stop",
|
||||
OBSStopStreaming, this);
|
||||
|
||||
bool isEncoded = obs_output_get_flags(streamOutput)
|
||||
& OBS_OUTPUT_ENCODED;
|
||||
bool isEncoded = obs_output_get_flags(streamOutput) &
|
||||
OBS_OUTPUT_ENCODED;
|
||||
|
||||
if (isEncoded) {
|
||||
const char *codec =
|
||||
|
@ -1551,8 +1544,8 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
|||
|
||||
obs_data_set_int(settings, "bitrate",
|
||||
audioBitrate);
|
||||
streamAudioEnc = obs_audio_encoder_create(id,
|
||||
"alt_audio_enc", nullptr,
|
||||
streamAudioEnc = obs_audio_encoder_create(
|
||||
id, "alt_audio_enc", nullptr,
|
||||
trackIndex - 1, nullptr);
|
||||
|
||||
if (!streamAudioEnc)
|
||||
|
@ -1579,18 +1572,17 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
|||
bool reconnect = config_get_bool(main->Config(), "Output", "Reconnect");
|
||||
int retryDelay = config_get_int(main->Config(), "Output", "RetryDelay");
|
||||
int maxRetries = config_get_int(main->Config(), "Output", "MaxRetries");
|
||||
bool useDelay = config_get_bool(main->Config(), "Output",
|
||||
"DelayEnable");
|
||||
int delaySec = config_get_int(main->Config(), "Output",
|
||||
"DelaySec");
|
||||
bool preserveDelay = config_get_bool(main->Config(), "Output",
|
||||
"DelayPreserve");
|
||||
const char *bindIP = config_get_string(main->Config(), "Output",
|
||||
"BindIP");
|
||||
bool useDelay =
|
||||
config_get_bool(main->Config(), "Output", "DelayEnable");
|
||||
int delaySec = config_get_int(main->Config(), "Output", "DelaySec");
|
||||
bool preserveDelay =
|
||||
config_get_bool(main->Config(), "Output", "DelayPreserve");
|
||||
const char *bindIP =
|
||||
config_get_string(main->Config(), "Output", "BindIP");
|
||||
bool enableNewSocketLoop = config_get_bool(main->Config(), "Output",
|
||||
"NewSocketLoopEnable");
|
||||
bool enableLowLatencyMode = config_get_bool(main->Config(), "Output",
|
||||
"LowLatencyEnable");
|
||||
bool enableLowLatencyMode =
|
||||
config_get_bool(main->Config(), "Output", "LowLatencyEnable");
|
||||
|
||||
obs_data_t *settings = obs_data_create();
|
||||
obs_data_set_string(settings, "bind_ip", bindIP);
|
||||
|
@ -1607,8 +1599,7 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
|||
obs_output_set_delay(streamOutput, useDelay ? delaySec : 0,
|
||||
preserveDelay ? OBS_OUTPUT_DELAY_PRESERVE : 0);
|
||||
|
||||
obs_output_set_reconnect_settings(streamOutput, maxRetries,
|
||||
retryDelay);
|
||||
obs_output_set_reconnect_settings(streamOutput, maxRetries, retryDelay);
|
||||
|
||||
if (obs_output_start(streamOutput)) {
|
||||
return true;
|
||||
|
@ -1622,8 +1613,7 @@ bool AdvancedOutput::StartStreaming(obs_service_t *service)
|
|||
lastError = string();
|
||||
|
||||
blog(LOG_WARNING, "Stream output type '%s' failed to start!%s%s", type,
|
||||
hasLastError ? " Last Error: " : "",
|
||||
hasLastError ? error : "");
|
||||
hasLastError ? " Last Error: " : "", hasLastError ? error : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1650,27 +1640,30 @@ bool AdvancedOutput::StartRecording()
|
|||
|
||||
if (!ffmpegOutput || ffmpegRecording) {
|
||||
path = config_get_string(main->Config(), "AdvOut",
|
||||
ffmpegRecording ? "FFFilePath" : "RecFilePath");
|
||||
ffmpegRecording ? "FFFilePath"
|
||||
: "RecFilePath");
|
||||
recFormat = config_get_string(main->Config(), "AdvOut",
|
||||
ffmpegRecording ? "FFExtension" : "RecFormat");
|
||||
ffmpegRecording ? "FFExtension"
|
||||
: "RecFormat");
|
||||
filenameFormat = config_get_string(main->Config(), "Output",
|
||||
"FilenameFormatting");
|
||||
overwriteIfExists = config_get_bool(main->Config(), "Output",
|
||||
"OverwriteIfExists");
|
||||
noSpace = config_get_bool(main->Config(), "AdvOut",
|
||||
ffmpegRecording ?
|
||||
"FFFileNameWithoutSpace" :
|
||||
"RecFileNameWithoutSpace");
|
||||
ffmpegRecording
|
||||
? "FFFileNameWithoutSpace"
|
||||
: "RecFileNameWithoutSpace");
|
||||
|
||||
os_dir_t *dir = path && path[0] ? os_opendir(path) : nullptr;
|
||||
|
||||
if (!dir) {
|
||||
if (main->isVisible())
|
||||
OBSMessageBox::warning(main,
|
||||
QTStr("Output.BadPath.Title"),
|
||||
OBSMessageBox::warning(
|
||||
main, QTStr("Output.BadPath.Title"),
|
||||
QTStr("Output.BadPath.Text"));
|
||||
else
|
||||
main->SysTrayNotify(QTStr("Output.BadPath.Text"),
|
||||
main->SysTrayNotify(
|
||||
QTStr("Output.BadPath.Text"),
|
||||
QSystemTrayIcon::Warning);
|
||||
return false;
|
||||
}
|
||||
|
@ -1691,8 +1684,7 @@ bool AdvancedOutput::StartRecording()
|
|||
FindBestFilename(strPath, noSpace);
|
||||
|
||||
obs_data_t *settings = obs_data_create();
|
||||
obs_data_set_string(settings,
|
||||
ffmpegRecording ? "url" : "path",
|
||||
obs_data_set_string(settings, ffmpegRecording ? "url" : "path",
|
||||
strPath.c_str());
|
||||
|
||||
obs_output_update(fileOutput, settings);
|
||||
|
@ -1742,35 +1734,36 @@ bool AdvancedOutput::StartReplayBuffer()
|
|||
|
||||
if (!ffmpegOutput || ffmpegRecording) {
|
||||
path = config_get_string(main->Config(), "AdvOut",
|
||||
ffmpegRecording ? "FFFilePath" : "RecFilePath");
|
||||
ffmpegRecording ? "FFFilePath"
|
||||
: "RecFilePath");
|
||||
recFormat = config_get_string(main->Config(), "AdvOut",
|
||||
ffmpegRecording ? "FFExtension" : "RecFormat");
|
||||
ffmpegRecording ? "FFExtension"
|
||||
: "RecFormat");
|
||||
filenameFormat = config_get_string(main->Config(), "Output",
|
||||
"FilenameFormatting");
|
||||
overwriteIfExists = config_get_bool(main->Config(), "Output",
|
||||
"OverwriteIfExists");
|
||||
noSpace = config_get_bool(main->Config(), "AdvOut",
|
||||
ffmpegRecording ?
|
||||
"FFFileNameWithoutSpace" :
|
||||
"RecFileNameWithoutSpace");
|
||||
ffmpegRecording
|
||||
? "FFFileNameWithoutSpace"
|
||||
: "RecFileNameWithoutSpace");
|
||||
rbPrefix = config_get_string(main->Config(), "SimpleOutput",
|
||||
"RecRBPrefix");
|
||||
rbSuffix = config_get_string(main->Config(), "SimpleOutput",
|
||||
"RecRBSuffix");
|
||||
rbTime = config_get_int(main->Config(), "AdvOut",
|
||||
"RecRBTime");
|
||||
rbSize = config_get_int(main->Config(), "AdvOut",
|
||||
"RecRBSize");
|
||||
rbTime = config_get_int(main->Config(), "AdvOut", "RecRBTime");
|
||||
rbSize = config_get_int(main->Config(), "AdvOut", "RecRBSize");
|
||||
|
||||
os_dir_t *dir = path && path[0] ? os_opendir(path) : nullptr;
|
||||
|
||||
if (!dir) {
|
||||
if (main->isVisible())
|
||||
OBSMessageBox::warning(main,
|
||||
QTStr("Output.BadPath.Title"),
|
||||
OBSMessageBox::warning(
|
||||
main, QTStr("Output.BadPath.Title"),
|
||||
QTStr("Output.BadPath.Text"));
|
||||
else
|
||||
main->SysTrayNotify(QTStr("Output.BadPath.Text"),
|
||||
main->SysTrayNotify(
|
||||
QTStr("Output.BadPath.Text"),
|
||||
QSystemTrayIcon::Warning);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -54,8 +54,7 @@ void EnumProfiles(std::function<bool (const char *, const char *)> &&cb)
|
|||
if (!glob->gl_pathv[i].directory)
|
||||
continue;
|
||||
|
||||
if (strcmp(dirName, ".") == 0 ||
|
||||
strcmp(dirName, "..") == 0)
|
||||
if (strcmp(dirName, ".") == 0 || strcmp(dirName, "..") == 0)
|
||||
continue;
|
||||
|
||||
std::string file = filePath;
|
||||
|
@ -80,8 +79,7 @@ void EnumProfiles(std::function<bool (const char *, const char *)> &&cb)
|
|||
static bool ProfileExists(const char *findName)
|
||||
{
|
||||
bool found = false;
|
||||
auto func = [&](const char *name, const char*)
|
||||
{
|
||||
auto func = [&](const char *name, const char *) {
|
||||
if (strcmp(name, findName) == 0) {
|
||||
found = true;
|
||||
return false;
|
||||
|
@ -94,15 +92,15 @@ static bool ProfileExists(const char *findName)
|
|||
}
|
||||
|
||||
static bool GetProfileName(QWidget *parent, std::string &name,
|
||||
std::string &file, const char *title, const char *text,
|
||||
const char *oldName = nullptr)
|
||||
std::string &file, const char *title,
|
||||
const char *text, const char *oldName = nullptr)
|
||||
{
|
||||
char path[512];
|
||||
int ret;
|
||||
|
||||
for (;;) {
|
||||
bool success = NameDialog::AskForName(parent, title, text,
|
||||
name, QT_UTF8(oldName));
|
||||
bool success = NameDialog::AskForName(parent, title, text, name,
|
||||
QT_UTF8(oldName));
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
@ -170,11 +168,12 @@ static bool CopyProfile(const char *fromPartial, const char *to)
|
|||
if (glob->gl_pathv[i].directory)
|
||||
continue;
|
||||
|
||||
ret = snprintf(path, sizeof(path), "%s/%s",
|
||||
to, strrchr(filePath, '/') + 1);
|
||||
ret = snprintf(path, sizeof(path), "%s/%s", to,
|
||||
strrchr(filePath, '/') + 1);
|
||||
if (ret > 0) {
|
||||
if (os_copyfile(filePath, path) != 0) {
|
||||
blog(LOG_WARNING, "CopyProfile: Failed to "
|
||||
blog(LOG_WARNING,
|
||||
"CopyProfile: Failed to "
|
||||
"copy file %s to %s",
|
||||
filePath, path);
|
||||
}
|
||||
|
@ -197,8 +196,8 @@ bool OBSBasic::AddProfile(bool create_new, const char *title, const char *text,
|
|||
if (!GetProfileName(this, newName, newDir, title, text, init_text))
|
||||
return false;
|
||||
|
||||
std::string curDir = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "ProfileDir");
|
||||
std::string curDir =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "ProfileDir");
|
||||
|
||||
char baseDir[512];
|
||||
int ret = GetConfigPath(baseDir, sizeof(baseDir),
|
||||
|
@ -312,8 +311,7 @@ void OBSBasic::DeleteProfile(const char *profileName, const char *profileDir)
|
|||
os_rmdir(profilePath);
|
||||
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
blog(LOG_INFO, "Removed profile '%s' (%s)",
|
||||
profileName, profileDir);
|
||||
blog(LOG_INFO, "Removed profile '%s' (%s)", profileName, profileDir);
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
}
|
||||
|
||||
|
@ -328,17 +326,16 @@ void OBSBasic::RefreshProfiles()
|
|||
delete menuActions[i];
|
||||
}
|
||||
|
||||
const char *curName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "Profile");
|
||||
const char *curName =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "Profile");
|
||||
|
||||
auto addProfile = [&](const char *name, const char *path)
|
||||
{
|
||||
auto addProfile = [&](const char *name, const char *path) {
|
||||
std::string file = strrchr(path, '/') + 1;
|
||||
|
||||
QAction *action = new QAction(QT_UTF8(name), this);
|
||||
action->setProperty("file_name", QT_UTF8(path));
|
||||
connect(action, &QAction::triggered,
|
||||
this, &OBSBasic::ChangeProfile);
|
||||
connect(action, &QAction::triggered, this,
|
||||
&OBSBasic::ChangeProfile);
|
||||
action->setCheckable(true);
|
||||
|
||||
action->setChecked(strcmp(name, curName) == 0);
|
||||
|
@ -364,10 +361,10 @@ void OBSBasic::ResetProfileData()
|
|||
|
||||
/* load audio monitoring */
|
||||
#if defined(_WIN32) || defined(__APPLE__) || HAVE_PULSEAUDIO
|
||||
const char *device_name = config_get_string(basicConfig, "Audio",
|
||||
"MonitoringDeviceName");
|
||||
const char *device_id = config_get_string(basicConfig, "Audio",
|
||||
"MonitoringDeviceId");
|
||||
const char *device_name =
|
||||
config_get_string(basicConfig, "Audio", "MonitoringDeviceName");
|
||||
const char *device_id =
|
||||
config_get_string(basicConfig, "Audio", "MonitoringDeviceId");
|
||||
|
||||
obs_set_audio_monitoring_device(device_name, device_id);
|
||||
|
||||
|
@ -388,14 +385,15 @@ void OBSBasic::on_actionDupProfile_triggered()
|
|||
|
||||
void OBSBasic::on_actionRenameProfile_triggered()
|
||||
{
|
||||
std::string curDir = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "ProfileDir");
|
||||
std::string curName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "Profile");
|
||||
std::string curDir =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "ProfileDir");
|
||||
std::string curName =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "Profile");
|
||||
|
||||
/* Duplicate and delete in case there are any issues in the process */
|
||||
bool success = AddProfile(false, Str("RenameProfile.Title"),
|
||||
Str("AddProfile.Text"), curName.c_str(), true);
|
||||
Str("AddProfile.Text"), curName.c_str(),
|
||||
true);
|
||||
if (success) {
|
||||
DeleteProfile(curName.c_str(), curDir.c_str());
|
||||
RefreshProfiles();
|
||||
|
@ -413,13 +411,12 @@ void OBSBasic::on_actionRemoveProfile_triggered()
|
|||
std::string newPath;
|
||||
ConfigFile config;
|
||||
|
||||
std::string oldDir = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "ProfileDir");
|
||||
std::string oldName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "Profile");
|
||||
std::string oldDir =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "ProfileDir");
|
||||
std::string oldName =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "Profile");
|
||||
|
||||
auto cb = [&](const char *name, const char *filePath)
|
||||
{
|
||||
auto cb = [&](const char *name, const char *filePath) {
|
||||
if (strcmp(oldName.c_str(), name) != 0) {
|
||||
newName = name;
|
||||
newPath = filePath;
|
||||
|
@ -438,8 +435,8 @@ void OBSBasic::on_actionRemoveProfile_triggered()
|
|||
QString text = QTStr("ConfirmRemove.Text");
|
||||
text.replace("$1", QT_UTF8(oldName.c_str()));
|
||||
|
||||
QMessageBox::StandardButton button = OBSMessageBox::question(this,
|
||||
QTStr("ConfirmRemove.Title"), text);
|
||||
QMessageBox::StandardButton button = OBSMessageBox::question(
|
||||
this, QTStr("ConfirmRemove.Title"), text);
|
||||
if (button == QMessageBox::No)
|
||||
return;
|
||||
|
||||
|
@ -458,8 +455,7 @@ void OBSBasic::on_actionRemoveProfile_triggered()
|
|||
|
||||
config_set_string(App()->GlobalConfig(), "Basic", "Profile",
|
||||
newName.c_str());
|
||||
config_set_string(App()->GlobalConfig(), "Basic", "ProfileDir",
|
||||
newDir);
|
||||
config_set_string(App()->GlobalConfig(), "Basic", "ProfileDir", newDir);
|
||||
|
||||
Auth::Save();
|
||||
auth.reset();
|
||||
|
@ -474,8 +470,8 @@ void OBSBasic::on_actionRemoveProfile_triggered()
|
|||
RefreshProfiles();
|
||||
config_save_safe(App()->GlobalConfig(), "tmp", nullptr);
|
||||
|
||||
blog(LOG_INFO, "Switched to profile '%s' (%s)",
|
||||
newName.c_str(), newDir);
|
||||
blog(LOG_INFO, "Switched to profile '%s' (%s)", newName.c_str(),
|
||||
newDir);
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
@ -501,11 +497,8 @@ void OBSBasic::on_actionImportProfile_triggered()
|
|||
}
|
||||
|
||||
QString dir = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
QTStr("Basic.MainMenu.Profile.Import"),
|
||||
home,
|
||||
QFileDialog::ShowDirsOnly |
|
||||
QFileDialog::DontResolveSymlinks);
|
||||
this, QTStr("Basic.MainMenu.Profile.Import"), home,
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
if (!dir.isEmpty() && !dir.isNull()) {
|
||||
QString inputPath = QString::fromUtf8(path);
|
||||
|
@ -526,8 +519,8 @@ void OBSBasic::on_actionImportProfile_triggered()
|
|||
profileDir + "/recordEncoder.json");
|
||||
RefreshProfiles();
|
||||
} else {
|
||||
OBSMessageBox::warning(this,
|
||||
QTStr("Basic.MainMenu.Profile.Import"),
|
||||
OBSMessageBox::warning(
|
||||
this, QTStr("Basic.MainMenu.Profile.Import"),
|
||||
QTStr("Basic.MainMenu.Profile.Exists"));
|
||||
}
|
||||
}
|
||||
|
@ -539,9 +532,8 @@ void OBSBasic::on_actionExportProfile_triggered()
|
|||
|
||||
QString home = QDir::homePath();
|
||||
|
||||
QString currentProfile =
|
||||
QString::fromUtf8(config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "ProfileDir"));
|
||||
QString currentProfile = QString::fromUtf8(config_get_string(
|
||||
App()->GlobalConfig(), "Basic", "ProfileDir"));
|
||||
|
||||
int ret = GetConfigPath(path, 512, "obs-studio/basic/profiles/");
|
||||
if (ret <= 0) {
|
||||
|
@ -550,11 +542,8 @@ void OBSBasic::on_actionExportProfile_triggered()
|
|||
}
|
||||
|
||||
QString dir = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
QTStr("Basic.MainMenu.Profile.Export"),
|
||||
home,
|
||||
QFileDialog::ShowDirsOnly |
|
||||
QFileDialog::DontResolveSymlinks);
|
||||
this, QTStr("Basic.MainMenu.Profile.Export"), home,
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
|
||||
if (!dir.isEmpty() && !dir.isNull()) {
|
||||
QString outputDir = dir + "/" + currentProfile;
|
||||
|
@ -571,10 +560,12 @@ void OBSBasic::on_actionExportProfile_triggered()
|
|||
QFile::remove(outputDir + "/service.json");
|
||||
|
||||
if (QFile::exists(outputDir + "/streamEncoder.json"))
|
||||
QFile::remove(outputDir + "/streamEncoder.json");
|
||||
QFile::remove(outputDir +
|
||||
"/streamEncoder.json");
|
||||
|
||||
if (QFile::exists(outputDir + "/recordEncoder.json"))
|
||||
QFile::remove(outputDir + "/recordEncoder.json");
|
||||
QFile::remove(outputDir +
|
||||
"/recordEncoder.json");
|
||||
}
|
||||
|
||||
QFile::copy(inputPath + currentProfile + "/basic.ini",
|
||||
|
@ -601,8 +592,8 @@ void OBSBasic::ChangeProfile()
|
|||
if (path.empty())
|
||||
return;
|
||||
|
||||
const char *oldName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "Profile");
|
||||
const char *oldName =
|
||||
config_get_string(App()->GlobalConfig(), "Basic", "Profile");
|
||||
if (action->text().compare(QT_UTF8(oldName)) == 0) {
|
||||
action->setChecked(true);
|
||||
return;
|
||||
|
@ -623,8 +614,7 @@ void OBSBasic::ChangeProfile()
|
|||
const char *newDir = strrchr(path.c_str(), '/') + 1;
|
||||
|
||||
config_set_string(App()->GlobalConfig(), "Basic", "Profile", newName);
|
||||
config_set_string(App()->GlobalConfig(), "Basic", "ProfileDir",
|
||||
newDir);
|
||||
config_set_string(App()->GlobalConfig(), "Basic", "ProfileDir", newDir);
|
||||
|
||||
Auth::Save();
|
||||
auth.reset();
|
||||
|
@ -642,8 +632,7 @@ void OBSBasic::ChangeProfile()
|
|||
|
||||
CheckForSimpleModeX264Fallback();
|
||||
|
||||
blog(LOG_INFO, "Switched to profile '%s' (%s)",
|
||||
newName, newDir);
|
||||
blog(LOG_INFO, "Switched to profile '%s' (%s)", newName, newDir);
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
if (api)
|
||||
|
@ -652,10 +641,10 @@ void OBSBasic::ChangeProfile()
|
|||
|
||||
void OBSBasic::CheckForSimpleModeX264Fallback()
|
||||
{
|
||||
const char *curStreamEncoder = config_get_string(basicConfig,
|
||||
"SimpleOutput", "StreamEncoder");
|
||||
const char *curRecEncoder = config_get_string(basicConfig,
|
||||
"SimpleOutput", "RecEncoder");
|
||||
const char *curStreamEncoder =
|
||||
config_get_string(basicConfig, "SimpleOutput", "StreamEncoder");
|
||||
const char *curRecEncoder =
|
||||
config_get_string(basicConfig, "SimpleOutput", "RecEncoder");
|
||||
bool qsv_supported = false;
|
||||
bool amd_supported = false;
|
||||
bool nve_supported = false;
|
||||
|
@ -672,8 +661,7 @@ void OBSBasic::CheckForSimpleModeX264Fallback()
|
|||
nve_supported = true;
|
||||
}
|
||||
|
||||
auto CheckEncoder = [&] (const char *&name)
|
||||
{
|
||||
auto CheckEncoder = [&](const char *&name) {
|
||||
if (strcmp(name, SIMPLE_ENCODER_QSV) == 0) {
|
||||
if (!qsv_supported) {
|
||||
changed = true;
|
||||
|
@ -698,12 +686,10 @@ void OBSBasic::CheckForSimpleModeX264Fallback()
|
|||
};
|
||||
|
||||
if (!CheckEncoder(curStreamEncoder))
|
||||
config_set_string(basicConfig,
|
||||
"SimpleOutput", "StreamEncoder",
|
||||
config_set_string(basicConfig, "SimpleOutput", "StreamEncoder",
|
||||
curStreamEncoder);
|
||||
if (!CheckEncoder(curRecEncoder))
|
||||
config_set_string(basicConfig,
|
||||
"SimpleOutput", "RecEncoder",
|
||||
config_set_string(basicConfig, "SimpleOutput", "RecEncoder",
|
||||
curRecEncoder);
|
||||
if (changed)
|
||||
config_save_safe(basicConfig, "tmp", nullptr);
|
||||
|
|
|
@ -52,8 +52,8 @@ void EnumSceneCollections(std::function<bool (const char *, const char *)> &&cb)
|
|||
if (glob->gl_pathv[i].directory)
|
||||
continue;
|
||||
|
||||
obs_data_t *data = obs_data_create_from_json_file_safe(filePath,
|
||||
"bak");
|
||||
obs_data_t *data =
|
||||
obs_data_create_from_json_file_safe(filePath, "bak");
|
||||
std::string name = obs_data_get_string(data, "name");
|
||||
|
||||
/* if no name found, use the file name as the name
|
||||
|
@ -75,8 +75,7 @@ void EnumSceneCollections(std::function<bool (const char *, const char *)> &&cb)
|
|||
static bool SceneCollectionExists(const char *findName)
|
||||
{
|
||||
bool found = false;
|
||||
auto func = [&](const char *name, const char*)
|
||||
{
|
||||
auto func = [&](const char *name, const char *) {
|
||||
if (strcmp(name, findName) == 0) {
|
||||
found = true;
|
||||
return false;
|
||||
|
@ -90,7 +89,8 @@ static bool SceneCollectionExists(const char *findName)
|
|||
}
|
||||
|
||||
static bool GetSceneCollectionName(QWidget *parent, std::string &name,
|
||||
std::string &file, const char *oldName = nullptr)
|
||||
std::string &file,
|
||||
const char *oldName = nullptr)
|
||||
{
|
||||
bool rename = oldName != nullptr;
|
||||
const char *title;
|
||||
|
@ -108,8 +108,8 @@ static bool GetSceneCollectionName(QWidget *parent, std::string &name,
|
|||
}
|
||||
|
||||
for (;;) {
|
||||
bool success = NameDialog::AskForName(parent, title, text,
|
||||
name, QT_UTF8(oldName));
|
||||
bool success = NameDialog::AskForName(parent, title, text, name,
|
||||
QT_UTF8(oldName));
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
|
@ -181,8 +181,7 @@ bool OBSBasic::AddSceneCollection(bool create_new, const QString &qname)
|
|||
RefreshSceneCollections();
|
||||
|
||||
blog(LOG_INFO, "Added scene collection '%s' (%s, %s.json)",
|
||||
name.c_str(), create_new ? "clean" : "duplicate",
|
||||
file.c_str());
|
||||
name.c_str(), create_new ? "clean" : "duplicate", file.c_str());
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
@ -206,18 +205,17 @@ void OBSBasic::RefreshSceneCollections()
|
|||
delete menuActions[i];
|
||||
}
|
||||
|
||||
const char *cur_name = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
const char *cur_name = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollection");
|
||||
|
||||
auto addCollection = [&](const char *name, const char *path)
|
||||
{
|
||||
auto addCollection = [&](const char *name, const char *path) {
|
||||
std::string file = strrchr(path, '/') + 1;
|
||||
file.erase(file.size() - 5, 5);
|
||||
|
||||
QAction *action = new QAction(QT_UTF8(name), this);
|
||||
action->setProperty("file_name", QT_UTF8(path));
|
||||
connect(action, &QAction::triggered,
|
||||
this, &OBSBasic::ChangeSceneCollection);
|
||||
connect(action, &QAction::triggered, this,
|
||||
&OBSBasic::ChangeSceneCollection);
|
||||
action->setCheckable(true);
|
||||
|
||||
action->setChecked(strcmp(name, cur_name) == 0);
|
||||
|
@ -265,10 +263,10 @@ void OBSBasic::on_actionRenameSceneCollection_triggered()
|
|||
std::string name;
|
||||
std::string file;
|
||||
|
||||
std::string oldFile = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollectionFile");
|
||||
const char *oldName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
std::string oldFile = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollectionFile");
|
||||
const char *oldName = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollection");
|
||||
|
||||
bool success = GetSceneCollectionName(this, name, file, oldName);
|
||||
if (!success)
|
||||
|
@ -312,13 +310,12 @@ void OBSBasic::on_actionRemoveSceneCollection_triggered()
|
|||
std::string newName;
|
||||
std::string newPath;
|
||||
|
||||
std::string oldFile = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollectionFile");
|
||||
std::string oldName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
std::string oldFile = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollectionFile");
|
||||
std::string oldName = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollection");
|
||||
|
||||
auto cb = [&](const char *name, const char *filePath)
|
||||
{
|
||||
auto cb = [&](const char *name, const char *filePath) {
|
||||
if (strcmp(oldName.c_str(), name) != 0) {
|
||||
newName = name;
|
||||
newPath = filePath;
|
||||
|
@ -337,8 +334,8 @@ void OBSBasic::on_actionRemoveSceneCollection_triggered()
|
|||
QString text = QTStr("ConfirmRemove.Text");
|
||||
text.replace("$1", QT_UTF8(oldName.c_str()));
|
||||
|
||||
QMessageBox::StandardButton button = OBSMessageBox::question(this,
|
||||
QTStr("ConfirmRemove.Title"), text);
|
||||
QMessageBox::StandardButton button = OBSMessageBox::question(
|
||||
this, QTStr("ConfirmRemove.Title"), text);
|
||||
if (button == QMessageBox::No)
|
||||
return;
|
||||
|
||||
|
@ -358,13 +355,13 @@ void OBSBasic::on_actionRemoveSceneCollection_triggered()
|
|||
Load(newPath.c_str());
|
||||
RefreshSceneCollections();
|
||||
|
||||
const char *newFile = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollectionFile");
|
||||
const char *newFile = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollectionFile");
|
||||
|
||||
blog(LOG_INFO, "Removed scene collection '%s' (%s.json), "
|
||||
blog(LOG_INFO,
|
||||
"Removed scene collection '%s' (%s.json), "
|
||||
"switched to '%s' (%s.json)",
|
||||
oldName.c_str(), oldFile.c_str(),
|
||||
newName.c_str(), newFile);
|
||||
oldName.c_str(), oldFile.c_str(), newName.c_str(), newFile);
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
@ -388,9 +385,7 @@ void OBSBasic::on_actionImportSceneCollection_triggered()
|
|||
}
|
||||
|
||||
QString qfilePath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QTStr("Basic.MainMenu.SceneCollection.Import"),
|
||||
qhome,
|
||||
this, QTStr("Basic.MainMenu.SceneCollection.Import"), qhome,
|
||||
"JSON Files (*.json)");
|
||||
|
||||
QFileInfo finfo(qfilePath);
|
||||
|
@ -416,7 +411,8 @@ void OBSBasic::on_actionImportSceneCollection_triggered()
|
|||
obs_data_set_string(scenedata, "name", name.c_str());
|
||||
|
||||
if (!GetFileSafeName(name.c_str(), file)) {
|
||||
blog(LOG_WARNING, "Failed to create "
|
||||
blog(LOG_WARNING,
|
||||
"Failed to create "
|
||||
"safe file name for '%s'",
|
||||
name.c_str());
|
||||
return;
|
||||
|
@ -425,14 +421,15 @@ void OBSBasic::on_actionImportSceneCollection_triggered()
|
|||
string filePath = path + file;
|
||||
|
||||
if (!GetClosestUnusedFileName(filePath, "json")) {
|
||||
blog(LOG_WARNING, "Failed to get "
|
||||
blog(LOG_WARNING,
|
||||
"Failed to get "
|
||||
"closest file name for %s",
|
||||
file.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
obs_data_save_json_safe(scenedata, filePath.c_str(),
|
||||
"tmp", "bak");
|
||||
obs_data_save_json_safe(scenedata, filePath.c_str(), "tmp",
|
||||
"bak");
|
||||
RefreshSceneCollections();
|
||||
}
|
||||
}
|
||||
|
@ -445,8 +442,8 @@ void OBSBasic::on_actionExportSceneCollection_triggered()
|
|||
|
||||
QString home = QDir::homePath();
|
||||
|
||||
QString currentFile = QT_UTF8(config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollectionFile"));
|
||||
QString currentFile = QT_UTF8(config_get_string(
|
||||
App()->GlobalConfig(), "Basic", "SceneCollectionFile"));
|
||||
|
||||
int ret = GetConfigPath(path, 512, "obs-studio/basic/scenes/");
|
||||
if (ret <= 0) {
|
||||
|
@ -455,10 +452,8 @@ void OBSBasic::on_actionExportSceneCollection_triggered()
|
|||
}
|
||||
|
||||
QString exportFile = QFileDialog::getSaveFileName(
|
||||
this,
|
||||
QTStr("Basic.MainMenu.SceneCollection.Export"),
|
||||
home + "/" + currentFile,
|
||||
"JSON Files (*.json)");
|
||||
this, QTStr("Basic.MainMenu.SceneCollection.Export"),
|
||||
home + "/" + currentFile, "JSON Files (*.json)");
|
||||
|
||||
string file = QT_TO_UTF8(exportFile);
|
||||
|
||||
|
@ -482,8 +477,8 @@ void OBSBasic::ChangeSceneCollection()
|
|||
if (fileName.empty())
|
||||
return;
|
||||
|
||||
const char *oldName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
const char *oldName = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollection");
|
||||
if (action->text().compare(QT_UTF8(oldName)) == 0) {
|
||||
action->setChecked(true);
|
||||
return;
|
||||
|
@ -494,13 +489,13 @@ void OBSBasic::ChangeSceneCollection()
|
|||
Load(fileName.c_str());
|
||||
RefreshSceneCollections();
|
||||
|
||||
const char *newName = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollection");
|
||||
const char *newFile = config_get_string(App()->GlobalConfig(),
|
||||
"Basic", "SceneCollectionFile");
|
||||
const char *newName = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollection");
|
||||
const char *newFile = config_get_string(App()->GlobalConfig(), "Basic",
|
||||
"SceneCollectionFile");
|
||||
|
||||
blog(LOG_INFO, "Switched to scene collection '%s' (%s.json)",
|
||||
newName, newFile);
|
||||
blog(LOG_INFO, "Switched to scene collection '%s' (%s.json)", newName,
|
||||
newFile);
|
||||
blog(LOG_INFO, "------------------------------------------------");
|
||||
|
||||
UpdateTitleBar();
|
||||
|
|
|
@ -54,8 +54,8 @@ void OBSBasic::InitDefaultTransitions()
|
|||
if (!obs_is_source_configurable(id)) {
|
||||
const char *name = obs_source_get_display_name(id);
|
||||
|
||||
obs_source_t *tr = obs_source_create_private(
|
||||
id, name, NULL);
|
||||
obs_source_t *tr =
|
||||
obs_source_create_private(id, name, NULL);
|
||||
InitTransition(tr);
|
||||
transitions.emplace_back(tr);
|
||||
|
||||
|
@ -82,8 +82,7 @@ void OBSBasic::AddQuickTransitionHotkey(QuickTransition *qt)
|
|||
.arg(MakeQuickTransitionText(qt));
|
||||
|
||||
auto quickTransition = [](void *data, obs_hotkey_id, obs_hotkey_t *,
|
||||
bool pressed)
|
||||
{
|
||||
bool pressed) {
|
||||
int id = (int)(uintptr_t)data;
|
||||
OBSBasic *main =
|
||||
reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
|
@ -96,7 +95,8 @@ void OBSBasic::AddQuickTransitionHotkey(QuickTransition *qt)
|
|||
};
|
||||
|
||||
qt->hotkey = obs_hotkey_register_frontend(hotkeyId->array,
|
||||
QT_TO_UTF8(hotkeyName), quickTransition,
|
||||
QT_TO_UTF8(hotkeyName),
|
||||
quickTransition,
|
||||
(void *)(uintptr_t)qt->id);
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,8 @@ void OBSBasic::InitTransition(obs_source_t *transition)
|
|||
signal_handler_t *handler = obs_source_get_signal_handler(transition);
|
||||
signal_handler_connect(handler, "transition_video_stop",
|
||||
onTransitionStop, this);
|
||||
signal_handler_connect(handler, "transition_stop",
|
||||
onTransitionFullStop, this);
|
||||
signal_handler_connect(handler, "transition_stop", onTransitionFullStop,
|
||||
this);
|
||||
}
|
||||
|
||||
static inline OBSSource GetTransitionComboItem(QComboBox *combo, int idx)
|
||||
|
@ -163,11 +163,11 @@ void OBSBasic::CreateDefaultQuickTransitions()
|
|||
{
|
||||
/* non-configurable transitions are always available, so add them
|
||||
* to the "default quick transitions" list */
|
||||
quickTransitions.emplace_back(
|
||||
GetTransitionComboItem(ui->transitions, 0),
|
||||
quickTransitions.emplace_back(GetTransitionComboItem(ui->transitions,
|
||||
0),
|
||||
300, quickTransitionIdCounter++);
|
||||
quickTransitions.emplace_back(
|
||||
GetTransitionComboItem(ui->transitions, 1),
|
||||
quickTransitions.emplace_back(GetTransitionComboItem(ui->transitions,
|
||||
1),
|
||||
300, quickTransitionIdCounter++);
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,8 @@ void OBSBasic::LoadQuickTransitions(obs_data_array_t *array)
|
|||
quickTransitionIdCounter = id + 1;
|
||||
|
||||
int idx = (int)quickTransitions.size() - 1;
|
||||
AddQuickTransitionHotkey(&quickTransitions[idx]);
|
||||
AddQuickTransitionHotkey(
|
||||
&quickTransitions[idx]);
|
||||
obs_hotkey_load(quickTransitions[idx].hotkey,
|
||||
hotkeys);
|
||||
}
|
||||
|
@ -231,8 +232,7 @@ obs_data_array_t *OBSBasic::SaveQuickTransitions()
|
|||
obs_source_t *OBSBasic::FindTransition(const char *name)
|
||||
{
|
||||
for (int i = 0; i < ui->transitions->count(); i++) {
|
||||
OBSSource tr = ui->transitions->itemData(i)
|
||||
.value<OBSSource>();
|
||||
OBSSource tr = ui->transitions->itemData(i).value<OBSSource>();
|
||||
|
||||
const char *trName = obs_source_get_name(tr);
|
||||
if (strcmp(trName, name) == 0)
|
||||
|
@ -317,10 +317,10 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force, bool direct,
|
|||
}
|
||||
|
||||
if (usingPreviewProgram && sceneDuplicationMode) {
|
||||
scene = obs_scene_duplicate(scene, NULL,
|
||||
editPropertiesMode ?
|
||||
OBS_SCENE_DUP_PRIVATE_COPY :
|
||||
OBS_SCENE_DUP_PRIVATE_REFS);
|
||||
scene = obs_scene_duplicate(
|
||||
scene, NULL,
|
||||
editPropertiesMode ? OBS_SCENE_DUP_PRIVATE_COPY
|
||||
: OBS_SCENE_DUP_PRIVATE_REFS);
|
||||
source = obs_scene_get_source(scene);
|
||||
}
|
||||
|
||||
|
@ -342,8 +342,8 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force, bool direct,
|
|||
OBSData data = obs_source_get_private_settings(source);
|
||||
obs_data_release(data);
|
||||
|
||||
const char *trOverrideName = obs_data_get_string(data,
|
||||
"transition");
|
||||
const char *trOverrideName =
|
||||
obs_data_get_string(data, "transition");
|
||||
int duration = ui->transitionDuration->value();
|
||||
|
||||
if (trOverrideName && *trOverrideName && !quickTransition) {
|
||||
|
@ -351,18 +351,18 @@ void OBSBasic::TransitionToScene(OBSSource source, bool force, bool direct,
|
|||
if (trOverride) {
|
||||
transition = trOverride;
|
||||
|
||||
obs_data_set_default_int(data,
|
||||
"transition_duration", 300);
|
||||
obs_data_set_default_int(
|
||||
data, "transition_duration", 300);
|
||||
|
||||
duration = (int)obs_data_get_int(data,
|
||||
"transition_duration");
|
||||
duration = (int)obs_data_get_int(
|
||||
data, "transition_duration");
|
||||
OverrideTransition(trOverride);
|
||||
overridingTransition = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool success = obs_transition_start(transition,
|
||||
OBS_TRANSITION_MODE_AUTO, duration, source);
|
||||
bool success = obs_transition_start(
|
||||
transition, OBS_TRANSITION_MODE_AUTO, duration, source);
|
||||
if (!success)
|
||||
TransitionFullyStopped();
|
||||
}
|
||||
|
@ -436,8 +436,8 @@ void OBSBasic::AddTransition()
|
|||
QString idStr = action->property("id").toString();
|
||||
|
||||
string name;
|
||||
QString placeHolderText = QT_UTF8(
|
||||
obs_source_get_display_name(QT_TO_UTF8(idStr)));
|
||||
QString placeHolderText =
|
||||
QT_UTF8(obs_source_get_display_name(QT_TO_UTF8(idStr)));
|
||||
QString format = placeHolderText + " (%1)";
|
||||
obs_source_t *source = nullptr;
|
||||
int i = 1;
|
||||
|
@ -462,8 +462,7 @@ void OBSBasic::AddTransition()
|
|||
|
||||
source = FindTransition(name.c_str());
|
||||
if (source) {
|
||||
OBSMessageBox::warning(this,
|
||||
QTStr("NameExists.Title"),
|
||||
OBSMessageBox::warning(this, QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
|
||||
AddTransition();
|
||||
|
@ -473,14 +472,16 @@ void OBSBasic::AddTransition()
|
|||
source = obs_source_create_private(QT_TO_UTF8(idStr),
|
||||
name.c_str(), NULL);
|
||||
InitTransition(source);
|
||||
ui->transitions->addItem(QT_UTF8(name.c_str()),
|
||||
ui->transitions->addItem(
|
||||
QT_UTF8(name.c_str()),
|
||||
QVariant::fromValue(OBSSource(source)));
|
||||
ui->transitions->setCurrentIndex(ui->transitions->count() - 1);
|
||||
CreatePropertiesWindow(source);
|
||||
obs_source_release(source);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
|
||||
api->on_event(
|
||||
OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
|
||||
|
||||
ClearQuickTransitionWidgets();
|
||||
RefreshQuickTransitions();
|
||||
|
@ -500,8 +501,8 @@ void OBSBasic::on_transitionAdd_clicked()
|
|||
QAction *action = new QAction(name, this);
|
||||
action->setProperty("id", id);
|
||||
|
||||
connect(action, SIGNAL(triggered()),
|
||||
this, SLOT(AddTransition()));
|
||||
connect(action, SIGNAL(triggered()), this,
|
||||
SLOT(AddTransition()));
|
||||
|
||||
menu.addAction(action);
|
||||
foundConfigurableTransitions = true;
|
||||
|
@ -529,7 +530,8 @@ void OBSBasic::on_transitionRemove_clicked()
|
|||
if (qt.button)
|
||||
qt.button->deleteLater();
|
||||
RemoveQuickTransitionHotkey(&qt);
|
||||
quickTransitions.erase(quickTransitions.begin() + i - 1);
|
||||
quickTransitions.erase(quickTransitions.begin() + i -
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,8 +570,7 @@ void OBSBasic::RenameTransition()
|
|||
|
||||
source = FindTransition(name.c_str());
|
||||
if (source) {
|
||||
OBSMessageBox::warning(this,
|
||||
QTStr("NameExists.Title"),
|
||||
OBSMessageBox::warning(this, QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
|
||||
RenameTransition();
|
||||
|
@ -579,10 +580,12 @@ void OBSBasic::RenameTransition()
|
|||
obs_source_set_name(transition, name.c_str());
|
||||
int idx = ui->transitions->findData(variant);
|
||||
if (idx != -1) {
|
||||
ui->transitions->setItemText(idx, QT_UTF8(name.c_str()));
|
||||
ui->transitions->setItemText(idx,
|
||||
QT_UTF8(name.c_str()));
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
|
||||
api->on_event(
|
||||
OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED);
|
||||
|
||||
ClearQuickTransitionWidgets();
|
||||
RefreshQuickTransitions();
|
||||
|
@ -597,9 +600,7 @@ void OBSBasic::on_transitionProps_clicked()
|
|||
if (!obs_source_configurable(source))
|
||||
return;
|
||||
|
||||
auto properties = [&] () {
|
||||
CreatePropertiesWindow(source);
|
||||
};
|
||||
auto properties = [&]() { CreatePropertiesWindow(source); };
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
|
@ -643,8 +644,7 @@ void OBSBasic::SetCurrentScene(obs_scene_t *scene, bool force, bool direct)
|
|||
SetCurrentScene(source, force, direct);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T GetOBSRef(QListWidgetItem *item)
|
||||
template<typename T> static T GetOBSRef(QListWidgetItem *item)
|
||||
{
|
||||
return item->data(static_cast<int>(QtDataRole::OBSRef)).value<T>();
|
||||
}
|
||||
|
@ -679,7 +679,8 @@ void OBSBasic::SetCurrentScene(OBSSource scene, bool force, bool direct)
|
|||
ui->scenes->setCurrentItem(item);
|
||||
ui->scenes->blockSignals(false);
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED);
|
||||
api->on_event(
|
||||
OBS_FRONTEND_EVENT_PREVIEW_SCENE_CHANGED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -698,8 +699,8 @@ void OBSBasic::CreateProgramDisplay()
|
|||
program = new OBSQTDisplay();
|
||||
|
||||
program->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(program.data(), &QWidget::customContextMenuRequested,
|
||||
this, &OBSBasic::on_program_customContextMenuRequested);
|
||||
connect(program.data(), &QWidget::customContextMenuRequested, this,
|
||||
&OBSBasic::on_program_customContextMenuRequested);
|
||||
|
||||
auto displayResize = [this]() {
|
||||
struct obs_video_info ovi;
|
||||
|
@ -708,11 +709,9 @@ void OBSBasic::CreateProgramDisplay()
|
|||
ResizeProgram(ovi.base_width, ovi.base_height);
|
||||
};
|
||||
|
||||
connect(program.data(), &OBSQTDisplay::DisplayResized,
|
||||
displayResize);
|
||||
connect(program.data(), &OBSQTDisplay::DisplayResized, displayResize);
|
||||
|
||||
auto addDisplay = [this] (OBSQTDisplay *window)
|
||||
{
|
||||
auto addDisplay = [this](OBSQTDisplay *window) {
|
||||
obs_display_add_draw_callback(window->GetDisplay(),
|
||||
OBSBasic::RenderProgram, this);
|
||||
|
||||
|
@ -723,8 +722,7 @@ void OBSBasic::CreateProgramDisplay()
|
|||
|
||||
connect(program.data(), &OBSQTDisplay::DisplayCreated, addDisplay);
|
||||
|
||||
program->setSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding);
|
||||
program->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
}
|
||||
|
||||
void OBSBasic::TransitionClicked()
|
||||
|
@ -806,14 +804,16 @@ void OBSBasic::CreateProgramOptions()
|
|||
&menu, menu.actionGeometry(act));
|
||||
};
|
||||
|
||||
action = menu.addAction(QTStr("QuickTransitions.DuplicateScene"));
|
||||
action = menu.addAction(
|
||||
QTStr("QuickTransitions.DuplicateScene"));
|
||||
action->setToolTip(QTStr("QuickTransitions.DuplicateSceneTT"));
|
||||
action->setCheckable(true);
|
||||
action->setChecked(sceneDuplicationMode);
|
||||
connect(action, &QAction::triggered, toggleSceneDuplication);
|
||||
connect(action, &QAction::hovered, showToolTip);
|
||||
|
||||
action = menu.addAction(QTStr("QuickTransitions.EditProperties"));
|
||||
action = menu.addAction(
|
||||
QTStr("QuickTransitions.EditProperties"));
|
||||
action->setToolTip(QTStr("QuickTransitions.EditPropertiesTT"));
|
||||
action->setCheckable(true);
|
||||
action->setChecked(editPropertiesMode);
|
||||
|
@ -831,8 +831,8 @@ void OBSBasic::CreateProgramOptions()
|
|||
menu.exec(QCursor::pos());
|
||||
};
|
||||
|
||||
connect(transitionButton.data(), &QAbstractButton::clicked,
|
||||
this, &OBSBasic::TransitionClicked);
|
||||
connect(transitionButton.data(), &QAbstractButton::clicked, this,
|
||||
&OBSBasic::TransitionClicked);
|
||||
connect(addQuickTransition, &QAbstractButton::clicked, onAdd);
|
||||
connect(configTransitions, &QAbstractButton::clicked, onConfig);
|
||||
}
|
||||
|
@ -868,8 +868,7 @@ QMenu *OBSBasic::CreatePerSceneTransitionMenu()
|
|||
duration->setSingleStep(50);
|
||||
duration->setValue(curDuration);
|
||||
|
||||
auto setTransition = [this] (QAction *action)
|
||||
{
|
||||
auto setTransition = [this](QAction *action) {
|
||||
int idx = action->property("transition_index").toInt();
|
||||
OBSSource scene = GetCurrentSceneSource();
|
||||
OBSData data = obs_source_get_private_settings(scene);
|
||||
|
@ -886,8 +885,7 @@ QMenu *OBSBasic::CreatePerSceneTransitionMenu()
|
|||
obs_data_set_string(data, "transition", name);
|
||||
};
|
||||
|
||||
auto setDuration = [this] (int duration)
|
||||
{
|
||||
auto setDuration = [this](int duration) {
|
||||
OBSSource scene = GetCurrentSceneSource();
|
||||
OBSData data = obs_source_get_private_settings(scene);
|
||||
obs_data_release(data);
|
||||
|
@ -937,8 +935,8 @@ QMenu *OBSBasic::CreateTransitionMenu(QWidget *parent, QuickTransition *qt)
|
|||
if (qt) {
|
||||
action = menu->addAction(QTStr("Remove"));
|
||||
action->setProperty("id", qt->id);
|
||||
connect(action, &QAction::triggered,
|
||||
this, &OBSBasic::QuickTransitionRemoveClicked);
|
||||
connect(action, &QAction::triggered, this,
|
||||
&OBSBasic::QuickTransitionRemoveClicked);
|
||||
|
||||
menu->addSeparator();
|
||||
}
|
||||
|
@ -953,7 +951,8 @@ QMenu *OBSBasic::CreateTransitionMenu(QWidget *parent, QuickTransition *qt)
|
|||
duration->setValue(qt ? qt->duration : 300);
|
||||
|
||||
if (qt) {
|
||||
connect(duration, (void (QSpinBox::*)(int))&QSpinBox::valueChanged,
|
||||
connect(duration,
|
||||
(void (QSpinBox::*)(int)) & QSpinBox::valueChanged,
|
||||
this, &OBSBasic::QuickTransitionChangeDuration);
|
||||
}
|
||||
|
||||
|
@ -968,7 +967,8 @@ QMenu *OBSBasic::CreateTransitionMenu(QWidget *parent, QuickTransition *qt)
|
|||
connect(action, &QAction::triggered, this,
|
||||
&OBSBasic::QuickTransitionChange);
|
||||
} else {
|
||||
action->setProperty("duration",
|
||||
action->setProperty(
|
||||
"duration",
|
||||
QVariant::fromValue<QWidget *>(duration));
|
||||
connect(action, &QAction::triggered, this,
|
||||
&OBSBasic::AddQuickTransition);
|
||||
|
@ -1004,8 +1004,8 @@ void OBSBasic::AddQuickTransitionId(int id)
|
|||
/* --------------------------------- */
|
||||
|
||||
button->setMenu(buttonMenu);
|
||||
connect(button, &QAbstractButton::clicked,
|
||||
this, &OBSBasic::QuickTransitionClicked);
|
||||
connect(button, &QAbstractButton::clicked, this,
|
||||
&OBSBasic::QuickTransitionClicked);
|
||||
|
||||
QVBoxLayout *programLayout =
|
||||
reinterpret_cast<QVBoxLayout *>(programOptions->layout());
|
||||
|
@ -1209,10 +1209,11 @@ void OBSBasic::SetPreviewProgramMode(bool enabled)
|
|||
|
||||
obs_scene_t *dup;
|
||||
if (sceneDuplicationMode) {
|
||||
dup = obs_scene_duplicate(curScene, nullptr,
|
||||
editPropertiesMode ?
|
||||
OBS_SCENE_DUP_PRIVATE_COPY :
|
||||
OBS_SCENE_DUP_PRIVATE_REFS);
|
||||
dup = obs_scene_duplicate(
|
||||
curScene, nullptr,
|
||||
editPropertiesMode
|
||||
? OBS_SCENE_DUP_PRIVATE_COPY
|
||||
: OBS_SCENE_DUP_PRIVATE_REFS);
|
||||
} else {
|
||||
dup = curScene;
|
||||
obs_scene_addref(dup);
|
||||
|
@ -1248,8 +1249,8 @@ void OBSBasic::SetPreviewProgramMode(bool enabled)
|
|||
programLayout->addWidget(programLabel);
|
||||
programLayout->addWidget(program);
|
||||
|
||||
bool labels = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "StudioModeLabels");
|
||||
bool labels = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"StudioModeLabels");
|
||||
|
||||
programLabel->setHidden(!labels);
|
||||
|
||||
|
@ -1257,7 +1258,8 @@ void OBSBasic::SetPreviewProgramMode(bool enabled)
|
|||
|
||||
ui->previewLayout->addWidget(programOptions);
|
||||
ui->previewLayout->addWidget(programWidget);
|
||||
ui->previewLayout->setAlignment(programOptions, Qt::AlignCenter);
|
||||
ui->previewLayout->setAlignment(programOptions,
|
||||
Qt::AlignCenter);
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_STUDIO_MODE_ENABLED);
|
||||
|
@ -1325,8 +1327,8 @@ void OBSBasic::RenderProgram(void *data, uint32_t cx, uint32_t cy)
|
|||
|
||||
gs_ortho(0.0f, float(ovi.base_width), 0.0f, float(ovi.base_height),
|
||||
-100.0f, 100.0f);
|
||||
gs_set_viewport(window->programX, window->programY,
|
||||
window->programCX, window->programCY);
|
||||
gs_set_viewport(window->programX, window->programY, window->programCX,
|
||||
window->programCY);
|
||||
|
||||
window->DrawBackdrop(float(ovi.base_width), float(ovi.base_height));
|
||||
|
||||
|
@ -1371,7 +1373,8 @@ obs_data_array_t *OBSBasic::SaveTransitions()
|
|||
obs_data_t *sourceData = obs_data_create();
|
||||
obs_data_t *settings = obs_source_get_settings(tr);
|
||||
|
||||
obs_data_set_string(sourceData, "name", obs_source_get_name(tr));
|
||||
obs_data_set_string(sourceData, "name",
|
||||
obs_source_get_name(tr));
|
||||
obs_data_set_string(sourceData, "id", obs_obj_get_id(tr));
|
||||
obs_data_set_obj(sourceData, "settings", settings);
|
||||
|
||||
|
@ -1394,11 +1397,12 @@ void OBSBasic::LoadTransitions(obs_data_array_t *transitions)
|
|||
const char *id = obs_data_get_string(item, "id");
|
||||
obs_data_t *settings = obs_data_get_obj(item, "settings");
|
||||
|
||||
obs_source_t *source = obs_source_create_private(id, name,
|
||||
settings);
|
||||
obs_source_t *source =
|
||||
obs_source_create_private(id, name, settings);
|
||||
if (!obs_obj_invalid(source)) {
|
||||
InitTransition(source);
|
||||
ui->transitions->addItem(QT_UTF8(name),
|
||||
ui->transitions->addItem(
|
||||
QT_UTF8(name),
|
||||
QVariant::fromValue(OBSSource(source)));
|
||||
ui->transitions->setCurrentIndex(
|
||||
ui->transitions->count() - 1);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -93,9 +93,10 @@ struct QuickTransition {
|
|||
duration(duration_),
|
||||
id(id_),
|
||||
renamedSignal(std::make_shared<OBSSignal>(
|
||||
obs_source_get_signal_handler(source),
|
||||
"rename", SourceRenamed, this))
|
||||
{}
|
||||
obs_source_get_signal_handler(source), "rename",
|
||||
SourceRenamed, this))
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
static void SourceRenamed(void *param, calldata_t *data);
|
||||
|
@ -124,19 +125,14 @@ class OBSBasic : public OBSMainWindow {
|
|||
friend class AutoConfigStreamPage;
|
||||
friend struct OBSStudioAPI;
|
||||
|
||||
enum class MoveDir {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right
|
||||
};
|
||||
enum class MoveDir { Up, Down, Left, Right };
|
||||
|
||||
enum DropType {
|
||||
DropType_RawText,
|
||||
DropType_Text,
|
||||
DropType_Image,
|
||||
DropType_Media,
|
||||
DropType_Html
|
||||
DropType_Html,
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -293,8 +289,8 @@ private:
|
|||
void ChangeSceneIndex(bool relative, int idx, int invalidIdx);
|
||||
|
||||
void TempFileOutput(const char *path, int vBitrate, int aBitrate);
|
||||
void TempStreamOutput(const char *url, const char *key,
|
||||
int vBitrate, int aBitrate);
|
||||
void TempStreamOutput(const char *url, const char *key, int vBitrate,
|
||||
int aBitrate);
|
||||
|
||||
void CloseDialogs();
|
||||
void ClearSceneData();
|
||||
|
@ -327,8 +323,8 @@ private:
|
|||
|
||||
int GetTopSelectedSourceItem();
|
||||
|
||||
obs_hotkey_pair_id streamingHotkeys, recordingHotkeys,
|
||||
replayBufHotkeys, togglePreviewHotkeys;
|
||||
obs_hotkey_pair_id streamingHotkeys, recordingHotkeys, replayBufHotkeys,
|
||||
togglePreviewHotkeys;
|
||||
obs_hotkey_id forceStreamingStopHotkey;
|
||||
|
||||
void InitDefaultTransitions();
|
||||
|
@ -459,12 +455,12 @@ public slots:
|
|||
void TransitionToScene(OBSScene scene, bool force = false,
|
||||
bool direct = false);
|
||||
void TransitionToScene(OBSSource scene, bool force = false,
|
||||
bool direct = false, bool quickTransition = false);
|
||||
bool direct = false,
|
||||
bool quickTransition = false);
|
||||
void SetCurrentScene(OBSSource scene, bool force = false,
|
||||
bool direct = false);
|
||||
|
||||
bool AddSceneCollection(
|
||||
bool create_new,
|
||||
bool AddSceneCollection(bool create_new,
|
||||
const QString &name = QString());
|
||||
|
||||
void UpdatePatronJson(const QString &text, const QString &error);
|
||||
|
@ -607,10 +603,7 @@ public:
|
|||
cy = previewCY;
|
||||
}
|
||||
|
||||
inline bool SavingDisabled() const
|
||||
{
|
||||
return disableSaving;
|
||||
}
|
||||
inline bool SavingDisabled() const { return disableSaving; }
|
||||
|
||||
inline double GetCPUUsage() const
|
||||
{
|
||||
|
@ -635,7 +628,8 @@ public:
|
|||
QMenu *AddDeinterlacingMenu(QMenu *menu, obs_source_t *source);
|
||||
QMenu *AddScaleFilteringMenu(QMenu *menu, obs_sceneitem_t *item);
|
||||
QMenu *AddBackgroundColorMenu(QMenu *menu, QWidgetAction *widgetAction,
|
||||
ColorSelect *select, obs_sceneitem_t *item);
|
||||
ColorSelect *select,
|
||||
obs_sceneitem_t *item);
|
||||
void CreateSourcePopupMenu(int idx, bool preview);
|
||||
|
||||
void UpdateTitleBar();
|
||||
|
@ -728,8 +722,8 @@ private slots:
|
|||
|
||||
void on_preview_customContextMenuRequested(const QPoint &pos);
|
||||
void on_program_customContextMenuRequested(const QPoint &pos);
|
||||
void on_previewDisabledLabel_customContextMenuRequested(
|
||||
const QPoint &pos);
|
||||
void
|
||||
on_previewDisabledLabel_customContextMenuRequested(const QPoint &pos);
|
||||
|
||||
void on_actionNewSceneCollection_triggered();
|
||||
void on_actionDupSceneCollection_triggered();
|
||||
|
@ -825,8 +819,8 @@ public:
|
|||
|
||||
virtual config_t *Config() const override;
|
||||
|
||||
virtual int GetProfilePath(char *path, size_t size, const char *file)
|
||||
const override;
|
||||
virtual int GetProfilePath(char *path, size_t size,
|
||||
const char *file) const override;
|
||||
|
||||
static void InitBrowserPanelSafeBlock();
|
||||
|
||||
|
@ -839,8 +833,8 @@ class SceneRenameDelegate : public QStyledItemDelegate {
|
|||
|
||||
public:
|
||||
SceneRenameDelegate(QObject *parent);
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index)
|
||||
const override;
|
||||
virtual void setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const override;
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *editor, QEvent *event) override;
|
||||
|
|
|
@ -65,9 +65,9 @@ struct SceneFindData {
|
|||
SceneFindData &operator=(SceneFindData &&) = delete;
|
||||
|
||||
inline SceneFindData(const vec2 &pos_, bool selectBelow_)
|
||||
: pos (pos_),
|
||||
selectBelow (selectBelow_)
|
||||
{}
|
||||
: pos(pos_), selectBelow(selectBelow_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static bool SceneItemHasVideo(obs_sceneitem_t *item)
|
||||
|
@ -153,48 +153,44 @@ vec3 OBSBasicPreview::GetSnapOffset(const vec3 &tl, const vec3 &br)
|
|||
|
||||
vec3_zero(&clampOffset);
|
||||
|
||||
const bool snap = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "SnappingEnabled");
|
||||
const bool snap = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"SnappingEnabled");
|
||||
if (snap == false)
|
||||
return clampOffset;
|
||||
|
||||
const bool screenSnap = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "ScreenSnapping");
|
||||
const bool centerSnap = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "CenterSnapping");
|
||||
const bool screenSnap = config_get_bool(
|
||||
GetGlobalConfig(), "BasicWindow", "ScreenSnapping");
|
||||
const bool centerSnap = config_get_bool(
|
||||
GetGlobalConfig(), "BasicWindow", "CenterSnapping");
|
||||
|
||||
const float clampDist = config_get_double(GetGlobalConfig(),
|
||||
"BasicWindow", "SnapDistance") / main->previewScale;
|
||||
"BasicWindow",
|
||||
"SnapDistance") /
|
||||
main->previewScale;
|
||||
const float centerX = br.x - (br.x - tl.x) / 2.0f;
|
||||
const float centerY = br.y - (br.y - tl.y) / 2.0f;
|
||||
|
||||
// Left screen edge.
|
||||
if (screenSnap &&
|
||||
fabsf(tl.x) < clampDist)
|
||||
if (screenSnap && fabsf(tl.x) < clampDist)
|
||||
clampOffset.x = -tl.x;
|
||||
// Right screen edge.
|
||||
if (screenSnap &&
|
||||
fabsf(clampOffset.x) < EPSILON &&
|
||||
if (screenSnap && fabsf(clampOffset.x) < EPSILON &&
|
||||
fabsf(screenSize.x - br.x) < clampDist)
|
||||
clampOffset.x = screenSize.x - br.x;
|
||||
// Horizontal center.
|
||||
if (centerSnap &&
|
||||
fabsf(screenSize.x - (br.x - tl.x)) > clampDist &&
|
||||
if (centerSnap && fabsf(screenSize.x - (br.x - tl.x)) > clampDist &&
|
||||
fabsf(screenSize.x / 2.0f - centerX) < clampDist)
|
||||
clampOffset.x = screenSize.x / 2.0f - centerX;
|
||||
|
||||
// Top screen edge.
|
||||
if (screenSnap &&
|
||||
fabsf(tl.y) < clampDist)
|
||||
if (screenSnap && fabsf(tl.y) < clampDist)
|
||||
clampOffset.y = -tl.y;
|
||||
// Bottom screen edge.
|
||||
if (screenSnap &&
|
||||
fabsf(clampOffset.y) < EPSILON &&
|
||||
if (screenSnap && fabsf(clampOffset.y) < EPSILON &&
|
||||
fabsf(screenSize.y - br.y) < clampDist)
|
||||
clampOffset.y = screenSize.y - br.y;
|
||||
// Vertical center.
|
||||
if (centerSnap &&
|
||||
fabsf(screenSize.y - (br.y - tl.y)) > clampDist &&
|
||||
if (centerSnap && fabsf(screenSize.y - (br.y - tl.y)) > clampDist &&
|
||||
fabsf(screenSize.y / 2.0f - centerY) < clampDist)
|
||||
clampOffset.y = screenSize.y / 2.0f - centerY;
|
||||
|
||||
|
@ -240,7 +236,8 @@ static bool CheckItemSelected(obs_scene_t *scene, obs_sceneitem_t *item,
|
|||
|
||||
if (data->group) {
|
||||
matrix4 parent_transform;
|
||||
obs_sceneitem_get_draw_transform(data->group, &parent_transform);
|
||||
obs_sceneitem_get_draw_transform(data->group,
|
||||
&parent_transform);
|
||||
matrix4_mul(&transform, &transform, &parent_transform);
|
||||
}
|
||||
|
||||
|
@ -286,8 +283,7 @@ struct HandleFindData {
|
|||
HandleFindData &operator=(HandleFindData &&) = delete;
|
||||
|
||||
inline HandleFindData(const vec2 &pos_, float scale)
|
||||
: pos (pos_),
|
||||
radius (HANDLE_SEL_RADIUS / scale)
|
||||
: pos(pos_), radius(HANDLE_SEL_RADIUS / scale)
|
||||
{
|
||||
matrix4_identity(&parent_xform);
|
||||
}
|
||||
|
@ -328,8 +324,7 @@ static bool FindHandleAtPos(obs_scene_t *scene, obs_sceneitem_t *item,
|
|||
|
||||
obs_sceneitem_get_box_transform(item, &transform);
|
||||
|
||||
auto TestHandle = [&] (float x, float y, ItemHandle handle)
|
||||
{
|
||||
auto TestHandle = [&](float x, float y, ItemHandle handle) {
|
||||
vec3 handlePos = GetTransformedPos(x, y, transform);
|
||||
vec3_transform(&handlePos, &handlePos, &data.parent_xform);
|
||||
|
||||
|
@ -370,10 +365,12 @@ static vec2 GetItemSize(obs_sceneitem_t *item)
|
|||
|
||||
obs_sceneitem_get_scale(item, &scale);
|
||||
obs_sceneitem_get_crop(item, &crop);
|
||||
size.x = float(obs_source_get_width(source) -
|
||||
crop.left - crop.right) * scale.x;
|
||||
size.y = float(obs_source_get_height(source) -
|
||||
crop.top - crop.bottom) * scale.y;
|
||||
size.x = float(obs_source_get_width(source) - crop.left -
|
||||
crop.right) *
|
||||
scale.x;
|
||||
size.y = float(obs_source_get_height(source) - crop.top -
|
||||
crop.bottom) *
|
||||
scale.y;
|
||||
}
|
||||
|
||||
return size;
|
||||
|
@ -413,16 +410,16 @@ void OBSBasicPreview::GetStretchHandleData(const vec2 &pos)
|
|||
|
||||
/* build the item space conversion matrices */
|
||||
matrix4_identity(&itemToScreen);
|
||||
matrix4_rotate_aa4f(&itemToScreen, &itemToScreen,
|
||||
0.0f, 0.0f, 1.0f, RAD(itemRot));
|
||||
matrix4_translate3f(&itemToScreen, &itemToScreen,
|
||||
itemUL.x, itemUL.y, 0.0f);
|
||||
matrix4_rotate_aa4f(&itemToScreen, &itemToScreen, 0.0f, 0.0f,
|
||||
1.0f, RAD(itemRot));
|
||||
matrix4_translate3f(&itemToScreen, &itemToScreen, itemUL.x,
|
||||
itemUL.y, 0.0f);
|
||||
|
||||
matrix4_identity(&screenToItem);
|
||||
matrix4_translate3f(&screenToItem, &screenToItem,
|
||||
-itemUL.x, -itemUL.y, 0.0f);
|
||||
matrix4_rotate_aa4f(&screenToItem, &screenToItem,
|
||||
0.0f, 0.0f, 1.0f, RAD(-itemRot));
|
||||
matrix4_translate3f(&screenToItem, &screenToItem, -itemUL.x,
|
||||
-itemUL.y, 0.0f);
|
||||
matrix4_rotate_aa4f(&screenToItem, &screenToItem, 0.0f, 0.0f,
|
||||
1.0f, RAD(-itemRot));
|
||||
|
||||
obs_sceneitem_get_crop(stretchItem, &startCrop);
|
||||
obs_sceneitem_get_pos(stretchItem, &startItemPos);
|
||||
|
@ -437,8 +434,7 @@ void OBSBasicPreview::GetStretchHandleData(const vec2 &pos)
|
|||
if (stretchGroup) {
|
||||
obs_sceneitem_get_draw_transform(stretchGroup,
|
||||
&invGroupTransform);
|
||||
matrix4_inv(&invGroupTransform,
|
||||
&invGroupTransform);
|
||||
matrix4_inv(&invGroupTransform, &invGroupTransform);
|
||||
obs_sceneitem_defer_group_resize_begin(stretchGroup);
|
||||
}
|
||||
}
|
||||
|
@ -480,8 +476,8 @@ void OBSBasicPreview::keyReleaseEvent(QKeyEvent *event)
|
|||
|
||||
void OBSBasicPreview::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (scrollMode && IsFixedScaling()
|
||||
&& event->orientation() == Qt::Vertical) {
|
||||
if (scrollMode && IsFixedScaling() &&
|
||||
event->orientation() == Qt::Vertical) {
|
||||
if (event->delta() > 0)
|
||||
SetScalingLevel(scalingLevel + 1);
|
||||
else if (event->delta() < 0)
|
||||
|
@ -628,11 +624,11 @@ struct SelectedItemBounds {
|
|||
static bool AddItemBounds(obs_scene_t *scene, obs_sceneitem_t *item,
|
||||
void *param)
|
||||
{
|
||||
SelectedItemBounds *data = reinterpret_cast<SelectedItemBounds*>(param);
|
||||
SelectedItemBounds *data =
|
||||
reinterpret_cast<SelectedItemBounds *>(param);
|
||||
vec3 t[4];
|
||||
|
||||
auto add_bounds = [data, &t] ()
|
||||
{
|
||||
auto add_bounds = [data, &t]() {
|
||||
for (const vec3 &v : t) {
|
||||
if (data->first) {
|
||||
vec3_copy(&data->tl, &v);
|
||||
|
@ -696,12 +692,10 @@ static bool GetSourceSnapOffset(obs_scene_t *scene, obs_sceneitem_t *item,
|
|||
matrix4 boxTransform;
|
||||
obs_sceneitem_get_box_transform(item, &boxTransform);
|
||||
|
||||
vec3 t[4] = {
|
||||
GetTransformedPos(0.0f, 0.0f, boxTransform),
|
||||
vec3 t[4] = {GetTransformedPos(0.0f, 0.0f, boxTransform),
|
||||
GetTransformedPos(1.0f, 0.0f, boxTransform),
|
||||
GetTransformedPos(0.0f, 1.0f, boxTransform),
|
||||
GetTransformedPos(1.0f, 1.0f, boxTransform)
|
||||
};
|
||||
GetTransformedPos(1.0f, 1.0f, boxTransform)};
|
||||
|
||||
bool first = true;
|
||||
vec3 tl, br;
|
||||
|
@ -723,10 +717,10 @@ static bool GetSourceSnapOffset(obs_scene_t *scene, obs_sceneitem_t *item,
|
|||
do { \
|
||||
double dist = fabsf(l.x - data->r.x); \
|
||||
if (dist < data->clampDist && \
|
||||
fabsf(data->offset.x) < EPSILON && \
|
||||
data->tl.y < br.y && \
|
||||
fabsf(data->offset.x) < EPSILON && data->tl.y < br.y && \
|
||||
data->br.y > tl.y && \
|
||||
(fabsf(data->offset.x) > dist || data->offset.x < EPSILON)) \
|
||||
(fabsf(data->offset.x) > dist || \
|
||||
data->offset.x < EPSILON)) \
|
||||
data->offset.x = l.x - data->r.x; \
|
||||
} while (false)
|
||||
|
||||
|
@ -755,10 +749,10 @@ void OBSBasicPreview::SnapItemMovement(vec2 &offset)
|
|||
|
||||
vec3 snapOffset = GetSnapOffset(data.tl, data.br);
|
||||
|
||||
const bool snap = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "SnappingEnabled");
|
||||
const bool sourcesSnap = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "SourceSnapping");
|
||||
const bool snap = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"SnappingEnabled");
|
||||
const bool sourcesSnap = config_get_bool(
|
||||
GetGlobalConfig(), "BasicWindow", "SourceSnapping");
|
||||
if (snap == false)
|
||||
return;
|
||||
if (sourcesSnap == false) {
|
||||
|
@ -768,7 +762,9 @@ void OBSBasicPreview::SnapItemMovement(vec2 &offset)
|
|||
}
|
||||
|
||||
const float clampDist = config_get_double(GetGlobalConfig(),
|
||||
"BasicWindow", "SnapDistance") / main->previewScale;
|
||||
"BasicWindow",
|
||||
"SnapDistance") /
|
||||
main->previewScale;
|
||||
|
||||
OffsetData offsetData;
|
||||
offsetData.clampDist = clampDist;
|
||||
|
@ -984,11 +980,9 @@ void OBSBasicPreview::CropItem(const vec2 &pos)
|
|||
vec2 max_tl;
|
||||
vec2 max_br;
|
||||
|
||||
vec2_set(&max_tl,
|
||||
float(-crop.left) * scale.x,
|
||||
vec2_set(&max_tl, float(-crop.left) * scale.x,
|
||||
float(-crop.top) * scale.y);
|
||||
vec2_set(&max_br,
|
||||
stretchItemSize.x + crop.right * scale.x,
|
||||
vec2_set(&max_br, stretchItemSize.x + crop.right * scale.x,
|
||||
stretchItemSize.y + crop.bottom * scale.y);
|
||||
|
||||
typedef std::function<float(float, float)> minmax_func_t;
|
||||
|
@ -1049,12 +1043,14 @@ void OBSBasicPreview::CropItem(const vec2 &pos)
|
|||
if (stretchFlags & ITEM_LEFT)
|
||||
crop.left += int(std::round(tl.x / scale.x));
|
||||
else if (stretchFlags & ITEM_RIGHT)
|
||||
crop.right += int(std::round((stretchItemSize.x - br.x) / scale.x));
|
||||
crop.right +=
|
||||
int(std::round((stretchItemSize.x - br.x) / scale.x));
|
||||
|
||||
if (stretchFlags & ITEM_TOP)
|
||||
crop.top += int(std::round(tl.y / scale.y));
|
||||
else if (stretchFlags & ITEM_BOTTOM)
|
||||
crop.bottom += int(std::round((stretchItemSize.y - br.y) / scale.y));
|
||||
crop.bottom +=
|
||||
int(std::round((stretchItemSize.y - br.y) / scale.y));
|
||||
|
||||
vec3_transform(&newPos, &newPos, &itemToScreen);
|
||||
newPos.x = std::round(newPos.x);
|
||||
|
@ -1109,8 +1105,7 @@ void OBSBasicPreview::StretchItem(const vec2 &pos)
|
|||
obs_source_t *source = obs_sceneitem_get_source(stretchItem);
|
||||
|
||||
vec2 baseSize;
|
||||
vec2_set(&baseSize,
|
||||
float(obs_source_get_width(source)),
|
||||
vec2_set(&baseSize, float(obs_source_get_width(source)),
|
||||
float(obs_source_get_height(source)));
|
||||
|
||||
vec2 size;
|
||||
|
@ -1120,8 +1115,10 @@ void OBSBasicPreview::StretchItem(const vec2 &pos)
|
|||
if (shiftDown)
|
||||
ClampAspect(tl, br, size, baseSize);
|
||||
|
||||
if (tl.x > br.x) std::swap(tl.x, br.x);
|
||||
if (tl.y > br.y) std::swap(tl.y, br.y);
|
||||
if (tl.x > br.x)
|
||||
std::swap(tl.x, br.x);
|
||||
if (tl.y > br.y)
|
||||
std::swap(tl.y, br.y);
|
||||
|
||||
vec2_abs(&size, &size);
|
||||
|
||||
|
@ -1180,8 +1177,8 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *event)
|
|||
OBSBasic *main = reinterpret_cast<OBSBasic *>(
|
||||
App()->GetMainWindow());
|
||||
OBSScene scene = main->GetCurrentScene();
|
||||
obs_sceneitem_t *group = obs_sceneitem_get_group(
|
||||
scene, stretchItem);
|
||||
obs_sceneitem_t *group =
|
||||
obs_sceneitem_get_group(scene, stretchItem);
|
||||
if (group) {
|
||||
vec3 group_pos;
|
||||
vec3_set(&group_pos, pos.x, pos.y, 0.0f);
|
||||
|
@ -1292,9 +1289,7 @@ static void DrawRect(float thickness, vec2 scale)
|
|||
|
||||
static inline bool crop_enabled(const obs_sceneitem_crop *crop)
|
||||
{
|
||||
return crop->left > 0 ||
|
||||
crop->top > 0 ||
|
||||
crop->right > 0 ||
|
||||
return crop->left > 0 || crop->top > 0 || crop->right > 0 ||
|
||||
crop->bottom > 0;
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1314,8 @@ bool OBSBasicPreview::DrawSelectedOverflow(obs_scene_t *scene,
|
|||
|
||||
gs_matrix_push();
|
||||
gs_matrix_mul(&mat);
|
||||
obs_sceneitem_group_enum_items(item, DrawSelectedOverflow, param);
|
||||
obs_sceneitem_group_enum_items(item, DrawSelectedOverflow,
|
||||
param);
|
||||
gs_matrix_pop();
|
||||
}
|
||||
|
||||
|
@ -1343,9 +1339,8 @@ bool OBSBasicPreview::DrawSelectedOverflow(obs_scene_t *scene,
|
|||
{{{1.f, 1.f, 0.f}}},
|
||||
};
|
||||
|
||||
bool visible = std::all_of(std::begin(bounds), std::end(bounds),
|
||||
[&](const vec3 &b)
|
||||
{
|
||||
bool visible = std::all_of(
|
||||
std::begin(bounds), std::end(bounds), [&](const vec3 &b) {
|
||||
vec3 pos;
|
||||
vec3_transform(&pos, &b, &boxTransform);
|
||||
vec3_transform(&pos, &pos, &invBoxTransform);
|
||||
|
@ -1437,9 +1432,8 @@ bool OBSBasicPreview::DrawSelectedItem(obs_scene_t *scene,
|
|||
vec4_set(&green, 0.0f, 1.0f, 0.0f, 1.0f);
|
||||
vec4_set(&blue, 0.0f, 0.5f, 1.0f, 1.0f);
|
||||
|
||||
bool visible = std::all_of(std::begin(bounds), std::end(bounds),
|
||||
[&](const vec3 &b)
|
||||
{
|
||||
bool visible = std::all_of(
|
||||
std::begin(bounds), std::end(bounds), [&](const vec3 &b) {
|
||||
vec3 pos;
|
||||
vec3_transform(&pos, &b, &boxTransform);
|
||||
vec3_transform(&pos, &pos, &invBoxTransform);
|
||||
|
@ -1592,13 +1586,16 @@ void OBSBasicPreview::ResetScrollingOffset()
|
|||
vec2_zero(&scrollingOffset);
|
||||
}
|
||||
|
||||
void OBSBasicPreview::SetScalingLevel(int32_t newScalingLevelVal) {
|
||||
float newScalingAmountVal = pow(ZOOM_SENSITIVITY, float(newScalingLevelVal));
|
||||
void OBSBasicPreview::SetScalingLevel(int32_t newScalingLevelVal)
|
||||
{
|
||||
float newScalingAmountVal =
|
||||
pow(ZOOM_SENSITIVITY, float(newScalingLevelVal));
|
||||
scalingLevel = newScalingLevelVal;
|
||||
SetScalingAmount(newScalingAmountVal);
|
||||
}
|
||||
|
||||
void OBSBasicPreview::SetScalingAmount(float newScalingAmountVal) {
|
||||
void OBSBasicPreview::SetScalingAmount(float newScalingAmountVal)
|
||||
{
|
||||
scrollingOffset.x *= newScalingAmountVal / scalingAmount;
|
||||
scrollingOffset.y *= newScalingAmountVal / scalingAmount;
|
||||
scalingAmount = newScalingAmountVal;
|
||||
|
|
|
@ -25,7 +25,7 @@ enum class ItemHandle : uint32_t {
|
|||
CenterRight = ITEM_RIGHT,
|
||||
BottomLeft = ITEM_BOTTOM | ITEM_LEFT,
|
||||
BottomCenter = ITEM_BOTTOM,
|
||||
BottomRight = ITEM_BOTTOM | ITEM_RIGHT
|
||||
BottomRight = ITEM_BOTTOM | ITEM_RIGHT,
|
||||
};
|
||||
|
||||
class OBSBasicPreview : public OBSQTDisplay {
|
||||
|
@ -114,7 +114,10 @@ public:
|
|||
inline void ToggleLocked() { locked = !locked; }
|
||||
inline bool Locked() const { return locked; }
|
||||
|
||||
inline void SetFixedScaling(bool newFixedScalingVal) { fixedScaling = newFixedScalingVal; }
|
||||
inline void SetFixedScaling(bool newFixedScalingVal)
|
||||
{
|
||||
fixedScaling = newFixedScalingVal;
|
||||
}
|
||||
inline bool IsFixedScaling() const { return fixedScaling; }
|
||||
|
||||
void SetScalingLevel(int32_t newScalingLevelVal);
|
||||
|
@ -123,7 +126,10 @@ public:
|
|||
inline float GetScalingAmount() const { return scalingAmount; }
|
||||
|
||||
void ResetScrollingOffset();
|
||||
inline void SetScrollingOffset(float x, float y) {vec2_set(&scrollingOffset, x, y);}
|
||||
inline void SetScrollingOffset(float x, float y)
|
||||
{
|
||||
vec2_set(&scrollingOffset, x, y);
|
||||
}
|
||||
inline float GetScrollX() const { return scrollingOffset.x; }
|
||||
inline float GetScrollY() const { return scrollingOffset.y; }
|
||||
|
||||
|
|
|
@ -37,12 +37,10 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
main(qobject_cast<OBSBasic *>(parent)),
|
||||
acceptClicked(false),
|
||||
source(source_),
|
||||
removedSignal (obs_source_get_signal_handler(source),
|
||||
"remove", OBSBasicProperties::SourceRemoved,
|
||||
this),
|
||||
renamedSignal (obs_source_get_signal_handler(source),
|
||||
"rename", OBSBasicProperties::SourceRenamed,
|
||||
this),
|
||||
removedSignal(obs_source_get_signal_handler(source), "remove",
|
||||
OBSBasicProperties::SourceRemoved, this),
|
||||
renamedSignal(obs_source_get_signal_handler(source), "rename",
|
||||
OBSBasicProperties::SourceRenamed, this),
|
||||
oldSettings(obs_data_create()),
|
||||
buttonBox(new QDialogButtonBox(this))
|
||||
{
|
||||
|
@ -60,8 +58,8 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
|
||||
buttonBox->button(QDialogButtonBox::Ok)->setText(QTStr("OK"));
|
||||
buttonBox->button(QDialogButtonBox::Cancel)->setText(QTStr("Cancel"));
|
||||
buttonBox->button(QDialogButtonBox::RestoreDefaults)->
|
||||
setText(QTStr("Defaults"));
|
||||
buttonBox->button(QDialogButtonBox::RestoreDefaults)
|
||||
->setText(QTStr("Defaults"));
|
||||
|
||||
if (cx > 400 && cy > 400)
|
||||
resize(cx, cy);
|
||||
|
@ -79,14 +77,15 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
obs_data_apply(oldSettings, settings);
|
||||
obs_data_release(settings);
|
||||
|
||||
view = new OBSPropertiesView(settings, source,
|
||||
view = new OBSPropertiesView(
|
||||
settings, source,
|
||||
(PropertiesReloadCallback)obs_source_properties,
|
||||
(PropertiesUpdateCallback)obs_source_update);
|
||||
view->setMinimumHeight(150);
|
||||
|
||||
preview->setMinimumSize(20, 150);
|
||||
preview->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,
|
||||
QSizePolicy::Expanding));
|
||||
preview->setSizePolicy(
|
||||
QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
|
||||
// Create a QSplitter to keep a unified workflow here.
|
||||
windowSplitter = new QSplitter(Qt::Orientation::Vertical, this);
|
||||
|
@ -102,8 +101,8 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
|
||||
if (type == OBS_SOURCE_TYPE_TRANSITION) {
|
||||
AddPreviewButton();
|
||||
connect(view, SIGNAL(PropertiesRefreshed()),
|
||||
this, SLOT(AddPreviewButton()));
|
||||
connect(view, SIGNAL(PropertiesRefreshed()), this,
|
||||
SLOT(AddPreviewButton()));
|
||||
}
|
||||
|
||||
layout()->addWidget(buttonBox);
|
||||
|
@ -122,14 +121,14 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
OBSBasicProperties::UpdateProperties,
|
||||
this);
|
||||
|
||||
auto addDrawCallback = [this] ()
|
||||
{
|
||||
auto addDrawCallback = [this]() {
|
||||
obs_display_add_draw_callback(preview->GetDisplay(),
|
||||
OBSBasicProperties::DrawPreview, this);
|
||||
OBSBasicProperties::DrawPreview,
|
||||
this);
|
||||
};
|
||||
auto addTransitionDrawCallback = [this] ()
|
||||
{
|
||||
obs_display_add_draw_callback(preview->GetDisplay(),
|
||||
auto addTransitionDrawCallback = [this]() {
|
||||
obs_display_add_draw_callback(
|
||||
preview->GetDisplay(),
|
||||
OBSBasicProperties::DrawTransitionPreview, this);
|
||||
};
|
||||
uint32_t caps = obs_source_get_output_flags(source);
|
||||
|
@ -143,10 +142,10 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
addDrawCallback);
|
||||
|
||||
} else if (type == OBS_SOURCE_TYPE_TRANSITION) {
|
||||
sourceA = obs_source_create_private("scene", "sourceA",
|
||||
nullptr);
|
||||
sourceB = obs_source_create_private("scene", "sourceB",
|
||||
nullptr);
|
||||
sourceA =
|
||||
obs_source_create_private("scene", "sourceA", nullptr);
|
||||
sourceB =
|
||||
obs_source_create_private("scene", "sourceB", nullptr);
|
||||
|
||||
obs_source_release(sourceA);
|
||||
obs_source_release(sourceB);
|
||||
|
@ -174,8 +173,7 @@ OBSBasicProperties::OBSBasicProperties(QWidget *parent, OBSSource source_)
|
|||
|
||||
obs_data_release(settings);
|
||||
|
||||
auto updateCallback = [=]()
|
||||
{
|
||||
auto updateCallback = [=]() {
|
||||
obs_data_t *settings = obs_source_get_settings(source);
|
||||
obs_source_update(sourceClone, settings);
|
||||
|
||||
|
@ -210,15 +208,14 @@ OBSBasicProperties::~OBSBasicProperties()
|
|||
|
||||
void OBSBasicProperties::AddPreviewButton()
|
||||
{
|
||||
QPushButton *playButton = new QPushButton(
|
||||
QTStr("PreviewTransition"), this);
|
||||
QPushButton *playButton =
|
||||
new QPushButton(QTStr("PreviewTransition"), this);
|
||||
VScrollArea *area = view;
|
||||
area->widget()->layout()->addWidget(playButton);
|
||||
|
||||
playButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
|
||||
auto play = [=] ()
|
||||
{
|
||||
auto play = [=]() {
|
||||
OBSSource start;
|
||||
OBSSource end;
|
||||
|
||||
|
@ -231,8 +228,7 @@ void OBSBasicProperties::AddPreviewButton()
|
|||
}
|
||||
|
||||
obs_transition_set(sourceClone, start);
|
||||
obs_transition_start(sourceClone,
|
||||
OBS_TRANSITION_MODE_AUTO,
|
||||
obs_transition_start(sourceClone, OBS_TRANSITION_MODE_AUTO,
|
||||
main->GetTransitionDuration(), end);
|
||||
direction = !direction;
|
||||
|
||||
|
@ -273,8 +269,8 @@ static obs_source_t *CreateLabel(const char *name, size_t h)
|
|||
const char *text_source_id = "text_ft2_source";
|
||||
#endif
|
||||
|
||||
obs_source_t *txtSource = obs_source_create_private(text_source_id,
|
||||
name, settings);
|
||||
obs_source_t *txtSource =
|
||||
obs_source_create_private(text_source_id, name, settings);
|
||||
|
||||
obs_data_release(font);
|
||||
obs_data_release(settings);
|
||||
|
@ -289,14 +285,14 @@ static void CreateTransitionScene(OBSSource scene, char *text, uint32_t color)
|
|||
obs_data_set_int(settings, "height", obs_source_get_height(scene));
|
||||
obs_data_set_int(settings, "color", color);
|
||||
|
||||
obs_source_t *colorBG = obs_source_create_private("color_source",
|
||||
"background", settings);
|
||||
obs_source_t *colorBG = obs_source_create_private(
|
||||
"color_source", "background", settings);
|
||||
|
||||
obs_scene_add(obs_scene_from_source(scene), colorBG);
|
||||
|
||||
obs_source_t *label = CreateLabel(text, obs_source_get_height(scene));
|
||||
obs_sceneitem_t *item = obs_scene_add(obs_scene_from_source(scene),
|
||||
label);
|
||||
obs_sceneitem_t *item =
|
||||
obs_scene_add(obs_scene_from_source(scene), label);
|
||||
|
||||
vec2 size;
|
||||
vec2_set(&size, obs_source_get_width(scene),
|
||||
|
@ -393,8 +389,7 @@ void OBSBasicProperties::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
|||
|
||||
gs_viewport_push();
|
||||
gs_projection_push();
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY),
|
||||
-100.0f, 100.0f);
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f);
|
||||
gs_set_viewport(x, y, newCX, newCY);
|
||||
|
||||
obs_source_video_render(window->source);
|
||||
|
@ -425,8 +420,7 @@ void OBSBasicProperties::DrawTransitionPreview(void *data, uint32_t cx,
|
|||
|
||||
gs_viewport_push();
|
||||
gs_projection_push();
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY),
|
||||
-100.0f, 100.0f);
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f);
|
||||
gs_set_viewport(x, y, newCX, newCY);
|
||||
|
||||
obs_source_video_render(window->sourceClone);
|
||||
|
@ -444,7 +438,8 @@ void OBSBasicProperties::Cleanup()
|
|||
|
||||
obs_display_remove_draw_callback(preview->GetDisplay(),
|
||||
OBSBasicProperties::DrawPreview, this);
|
||||
obs_display_remove_draw_callback(preview->GetDisplay(),
|
||||
obs_display_remove_draw_callback(
|
||||
preview->GetDisplay(),
|
||||
OBSBasicProperties::DrawTransitionPreview, this);
|
||||
}
|
||||
|
||||
|
@ -497,11 +492,10 @@ bool OBSBasicProperties::ConfirmQuit()
|
|||
{
|
||||
QMessageBox::StandardButton button;
|
||||
|
||||
button = OBSMessageBox::question(this,
|
||||
QTStr("Basic.PropertiesWindow.ConfirmTitle"),
|
||||
button = OBSMessageBox::question(
|
||||
this, QTStr("Basic.PropertiesWindow.ConfirmTitle"),
|
||||
QTStr("Basic.PropertiesWindow.Confirm"),
|
||||
QMessageBox::Save | QMessageBox::Discard |
|
||||
QMessageBox::Cancel);
|
||||
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||
|
||||
switch (button) {
|
||||
case QMessageBox::Save:
|
||||
|
|
|
@ -54,8 +54,7 @@ private:
|
|||
static void SourceRenamed(void *data, calldata_t *params);
|
||||
static void UpdateProperties(void *data, calldata_t *params);
|
||||
static void DrawPreview(void *data, uint32_t cx, uint32_t cy);
|
||||
static void DrawTransitionPreview(void *data, uint32_t cx,
|
||||
uint32_t cy);
|
||||
static void DrawTransitionPreview(void *data, uint32_t cx, uint32_t cy);
|
||||
void UpdateCallback(void *obj, obs_data_t *settings);
|
||||
bool ConfirmQuit();
|
||||
int CheckSettings();
|
||||
|
|
|
@ -54,10 +54,10 @@ void OBSBasicSettings::InitStreamPage()
|
|||
|
||||
LoadServices(false);
|
||||
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(UpdateServerList()));
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(UpdateKeyLink()));
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(UpdateServerList()));
|
||||
connect(ui->service, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(UpdateKeyLink()));
|
||||
}
|
||||
|
||||
void OBSBasicSettings::LoadStream1Settings()
|
||||
|
@ -78,8 +78,10 @@ void OBSBasicSettings::LoadStream1Settings()
|
|||
ui->customServer->setText(server);
|
||||
|
||||
bool use_auth = obs_data_get_bool(settings, "use_auth");
|
||||
const char *username = obs_data_get_string(settings, "username");
|
||||
const char *password = obs_data_get_string(settings, "password");
|
||||
const char *username =
|
||||
obs_data_get_string(settings, "username");
|
||||
const char *password =
|
||||
obs_data_get_string(settings, "password");
|
||||
ui->authUsername->setText(QT_UTF8(username));
|
||||
ui->authPw->setText(QT_UTF8(password));
|
||||
ui->useAuth->setChecked(use_auth);
|
||||
|
@ -126,9 +128,7 @@ void OBSBasicSettings::LoadStream1Settings()
|
|||
void OBSBasicSettings::SaveStream1Settings()
|
||||
{
|
||||
bool customServer = IsCustomService();
|
||||
const char *service_id = customServer
|
||||
? "rtmp_custom"
|
||||
: "rtmp_common";
|
||||
const char *service_id = customServer ? "rtmp_custom" : "rtmp_common";
|
||||
|
||||
obs_service_t *oldService = main->GetService();
|
||||
OBSData hotkeyData = obs_hotkeys_save_service(oldService);
|
||||
|
@ -140,7 +140,8 @@ void OBSBasicSettings::SaveStream1Settings()
|
|||
if (!customServer) {
|
||||
obs_data_set_string(settings, "service",
|
||||
QT_TO_UTF8(ui->service->currentText()));
|
||||
obs_data_set_string(settings, "server",
|
||||
obs_data_set_string(
|
||||
settings, "server",
|
||||
QT_TO_UTF8(ui->server->currentData().toString()));
|
||||
} else {
|
||||
obs_data_set_string(settings, "server",
|
||||
|
@ -148,18 +149,20 @@ void OBSBasicSettings::SaveStream1Settings()
|
|||
obs_data_set_bool(settings, "use_auth",
|
||||
ui->useAuth->isChecked());
|
||||
if (ui->useAuth->isChecked()) {
|
||||
obs_data_set_string(settings, "username",
|
||||
obs_data_set_string(
|
||||
settings, "username",
|
||||
QT_TO_UTF8(ui->authUsername->text()));
|
||||
obs_data_set_string(settings, "password",
|
||||
QT_TO_UTF8(ui->authPw->text()));
|
||||
}
|
||||
}
|
||||
|
||||
obs_data_set_bool(settings, "bwtest", ui->bandwidthTestEnable->isChecked());
|
||||
obs_data_set_bool(settings, "bwtest",
|
||||
ui->bandwidthTestEnable->isChecked());
|
||||
obs_data_set_string(settings, "key", QT_TO_UTF8(ui->key->text()));
|
||||
|
||||
OBSService newService = obs_service_create(service_id,
|
||||
"default_service", settings, hotkeyData);
|
||||
OBSService newService = obs_service_create(
|
||||
service_id, "default_service", settings, hotkeyData);
|
||||
obs_service_release(newService);
|
||||
|
||||
if (!newService)
|
||||
|
@ -185,13 +188,15 @@ void OBSBasicSettings::UpdateKeyLink()
|
|||
text += " <a href=\"https://";
|
||||
text += "www.twitch.tv/broadcast/dashboard/streamkey";
|
||||
text += "\">";
|
||||
text += QTStr("Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += QTStr(
|
||||
"Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += "</a>";
|
||||
} else if (serviceName == "YouTube / YouTube Gaming") {
|
||||
text += " <a href=\"https://";
|
||||
text += "www.youtube.com/live_dashboard";
|
||||
text += "\">";
|
||||
text += QTStr("Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += QTStr(
|
||||
"Basic.AutoConfig.StreamPage.StreamKey.LinkToSite");
|
||||
text += "</a>";
|
||||
}
|
||||
|
||||
|
@ -234,8 +239,8 @@ void OBSBasicSettings::LoadServices(bool showAll)
|
|||
QVariant((int)ListOpt::ShowAll));
|
||||
}
|
||||
|
||||
ui->service->insertItem(0,
|
||||
QTStr("Basic.AutoConfig.StreamPage.Service.Custom"),
|
||||
ui->service->insertItem(
|
||||
0, QTStr("Basic.AutoConfig.StreamPage.Service.Custom"),
|
||||
QVariant((int)ListOpt::Custom));
|
||||
|
||||
if (!lastService.isEmpty()) {
|
||||
|
@ -256,8 +261,8 @@ static inline bool is_auth_service(const std::string &service)
|
|||
|
||||
void OBSBasicSettings::on_service_currentIndexChanged(int)
|
||||
{
|
||||
bool showMore =
|
||||
ui->service->currentData().toInt() == (int)ListOpt::ShowAll;
|
||||
bool showMore = ui->service->currentData().toInt() ==
|
||||
(int)ListOpt::ShowAll;
|
||||
if (showMore)
|
||||
return;
|
||||
|
||||
|
@ -320,8 +325,8 @@ void OBSBasicSettings::on_service_currentIndexChanged(int)
|
|||
void OBSBasicSettings::UpdateServerList()
|
||||
{
|
||||
QString serviceName = ui->service->currentText();
|
||||
bool showMore =
|
||||
ui->service->currentData().toInt() == (int)ListOpt::ShowAll;
|
||||
bool showMore = ui->service->currentData().toInt() ==
|
||||
(int)ListOpt::ShowAll;
|
||||
|
||||
if (showMore) {
|
||||
LoadServices(true);
|
||||
|
@ -387,7 +392,8 @@ OBSService OBSBasicSettings::SpawnTempService()
|
|||
if (!custom) {
|
||||
obs_data_set_string(settings, "service",
|
||||
QT_TO_UTF8(ui->service->currentText()));
|
||||
obs_data_set_string(settings, "server",
|
||||
obs_data_set_string(
|
||||
settings, "server",
|
||||
QT_TO_UTF8(ui->server->currentData().toString()));
|
||||
} else {
|
||||
obs_data_set_string(settings, "server",
|
||||
|
@ -395,8 +401,8 @@ OBSService OBSBasicSettings::SpawnTempService()
|
|||
}
|
||||
obs_data_set_string(settings, "key", QT_TO_UTF8(ui->key->text()));
|
||||
|
||||
OBSService newService = obs_service_create(service_id,
|
||||
"temp_service", settings, nullptr);
|
||||
OBSService newService = obs_service_create(service_id, "temp_service",
|
||||
settings, nullptr);
|
||||
obs_service_release(newService);
|
||||
|
||||
return newService;
|
||||
|
@ -461,8 +467,7 @@ void OBSBasicSettings::on_disconnectAccount_clicked()
|
|||
{
|
||||
QMessageBox::StandardButton button;
|
||||
|
||||
button = OBSMessageBox::question(this,
|
||||
QTStr(DISCONNECT_COMFIRM_TITLE),
|
||||
button = OBSMessageBox::question(this, QTStr(DISCONNECT_COMFIRM_TITLE),
|
||||
QTStr(DISCONNECT_COMFIRM_TEXT));
|
||||
|
||||
if (button == QMessageBox::No) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -68,8 +68,7 @@ public slots:
|
|||
}
|
||||
};
|
||||
|
||||
class OBSFFDeleter
|
||||
{
|
||||
class OBSFFDeleter {
|
||||
public:
|
||||
void operator()(const ff_format_desc *format)
|
||||
{
|
||||
|
@ -80,27 +79,19 @@ public:
|
|||
ff_codec_desc_free(codec);
|
||||
}
|
||||
};
|
||||
using OBSFFCodecDesc = std::unique_ptr<const ff_codec_desc,
|
||||
OBSFFDeleter>;
|
||||
using OBSFFFormatDesc = std::unique_ptr<const ff_format_desc,
|
||||
OBSFFDeleter>;
|
||||
using OBSFFCodecDesc = std::unique_ptr<const ff_codec_desc, OBSFFDeleter>;
|
||||
using OBSFFFormatDesc = std::unique_ptr<const ff_format_desc, OBSFFDeleter>;
|
||||
|
||||
class OBSBasicSettings : public QDialog {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QIcon generalIcon WRITE SetGeneralIcon
|
||||
NOTIFY SetGeneralIcon)
|
||||
Q_PROPERTY(QIcon streamIcon WRITE SetStreamIcon
|
||||
NOTIFY SetStreamIcon)
|
||||
Q_PROPERTY(QIcon outputIcon WRITE SetOutputIcon
|
||||
NOTIFY SetOutputIcon)
|
||||
Q_PROPERTY(QIcon audioIcon WRITE SetAudioIcon
|
||||
NOTIFY SetAudioIcon)
|
||||
Q_PROPERTY(QIcon videoIcon WRITE SetVideoIcon
|
||||
NOTIFY SetVideoIcon)
|
||||
Q_PROPERTY(QIcon hotkeysIcon WRITE SetHotkeysIcon
|
||||
NOTIFY SetHotkeysIcon)
|
||||
Q_PROPERTY(QIcon advancedIcon WRITE SetAdvancedIcon
|
||||
NOTIFY SetAdvancedIcon)
|
||||
Q_PROPERTY(QIcon generalIcon WRITE SetGeneralIcon NOTIFY SetGeneralIcon)
|
||||
Q_PROPERTY(QIcon streamIcon WRITE SetStreamIcon NOTIFY SetStreamIcon)
|
||||
Q_PROPERTY(QIcon outputIcon WRITE SetOutputIcon NOTIFY SetOutputIcon)
|
||||
Q_PROPERTY(QIcon audioIcon WRITE SetAudioIcon NOTIFY SetAudioIcon)
|
||||
Q_PROPERTY(QIcon videoIcon WRITE SetVideoIcon NOTIFY SetVideoIcon)
|
||||
Q_PROPERTY(QIcon hotkeysIcon WRITE SetHotkeysIcon NOTIFY SetHotkeysIcon)
|
||||
Q_PROPERTY(
|
||||
QIcon advancedIcon WRITE SetAdvancedIcon NOTIFY SetAdvancedIcon)
|
||||
|
||||
private:
|
||||
OBSBasic *main;
|
||||
|
@ -141,9 +132,9 @@ private:
|
|||
QString curAdvRecordEncoder;
|
||||
|
||||
using AudioSource_t =
|
||||
std::tuple<OBSWeakSource,
|
||||
QPointer<QCheckBox>, QPointer<QSpinBox>,
|
||||
QPointer<QCheckBox>, QPointer<QSpinBox>>;
|
||||
std::tuple<OBSWeakSource, QPointer<QCheckBox>,
|
||||
QPointer<QSpinBox>, QPointer<QCheckBox>,
|
||||
QPointer<QSpinBox>>;
|
||||
std::vector<AudioSource_t> audioSources;
|
||||
std::vector<OBSSignal> audioSourceSignals;
|
||||
OBSSignal sourceCreated;
|
||||
|
@ -214,12 +205,14 @@ private:
|
|||
void LoadOutputSettings();
|
||||
void LoadAudioSettings();
|
||||
void LoadVideoSettings();
|
||||
void LoadHotkeySettings(obs_hotkey_id ignoreKey=OBS_INVALID_HOTKEY_ID);
|
||||
void
|
||||
LoadHotkeySettings(obs_hotkey_id ignoreKey = OBS_INVALID_HOTKEY_ID);
|
||||
void LoadAdvancedSettings();
|
||||
void LoadSettings(bool changedOnly);
|
||||
|
||||
OBSPropertiesView *CreateEncoderPropertyView(const char *encoder,
|
||||
const char *path, bool changed = false);
|
||||
const char *path,
|
||||
bool changed = false);
|
||||
|
||||
/* general */
|
||||
void LoadLanguageList();
|
||||
|
@ -241,8 +234,8 @@ private slots:
|
|||
void on_disconnectAccount_clicked();
|
||||
void on_useStreamKey_clicked();
|
||||
void on_useAuth_toggled();
|
||||
private:
|
||||
|
||||
private:
|
||||
/* output */
|
||||
void LoadSimpleOutputSettings();
|
||||
void LoadAdvOutputStreamingSettings();
|
||||
|
@ -251,8 +244,8 @@ private:
|
|||
void LoadAdvOutputRecordingEncoderProperties();
|
||||
void LoadAdvOutputFFmpegSettings();
|
||||
void LoadAdvOutputAudioSettings();
|
||||
void SetAdvOutputFFmpegEnablement(
|
||||
ff_codec_type encoderType, bool enabled,
|
||||
void SetAdvOutputFFmpegEnablement(ff_codec_type encoderType,
|
||||
bool enabled,
|
||||
bool enableEncode = false);
|
||||
|
||||
/* audio */
|
||||
|
|
|
@ -28,7 +28,8 @@ struct AddSourceData {
|
|||
|
||||
bool OBSBasicSourceSelect::EnumSources(void *data, obs_source_t *source)
|
||||
{
|
||||
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
||||
OBSBasicSourceSelect *window =
|
||||
static_cast<OBSBasicSourceSelect *>(data);
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *id = obs_source_get_id(source);
|
||||
|
||||
|
@ -40,13 +41,14 @@ bool OBSBasicSourceSelect::EnumSources(void *data, obs_source_t *source)
|
|||
|
||||
bool OBSBasicSourceSelect::EnumGroups(void *data, obs_source_t *source)
|
||||
{
|
||||
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
||||
OBSBasicSourceSelect *window =
|
||||
static_cast<OBSBasicSourceSelect *>(data);
|
||||
const char *name = obs_source_get_name(source);
|
||||
const char *id = obs_source_get_id(source);
|
||||
|
||||
if (strcmp(id, window->id) == 0) {
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic*>(
|
||||
App()->GetMainWindow());
|
||||
OBSBasic *main =
|
||||
reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
OBSScene scene = main->GetCurrentScene();
|
||||
|
||||
obs_sceneitem_t *existing = obs_scene_get_group(scene, name);
|
||||
|
@ -59,7 +61,8 @@ bool OBSBasicSourceSelect::EnumGroups(void *data, obs_source_t *source)
|
|||
|
||||
void OBSBasicSourceSelect::OBSSourceAdded(void *data, calldata_t *calldata)
|
||||
{
|
||||
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
||||
OBSBasicSourceSelect *window =
|
||||
static_cast<OBSBasicSourceSelect *>(data);
|
||||
obs_source_t *source = (obs_source_t *)calldata_ptr(calldata, "source");
|
||||
|
||||
QMetaObject::invokeMethod(window, "SourceAdded",
|
||||
|
@ -68,7 +71,8 @@ void OBSBasicSourceSelect::OBSSourceAdded(void *data, calldata_t *calldata)
|
|||
|
||||
void OBSBasicSourceSelect::OBSSourceRemoved(void *data, calldata_t *calldata)
|
||||
{
|
||||
OBSBasicSourceSelect *window = static_cast<OBSBasicSourceSelect*>(data);
|
||||
OBSBasicSourceSelect *window =
|
||||
static_cast<OBSBasicSourceSelect *>(data);
|
||||
obs_source_t *source = (obs_source_t *)calldata_ptr(calldata, "source");
|
||||
|
||||
QMetaObject::invokeMethod(window, "SourceRemoved",
|
||||
|
@ -120,8 +124,8 @@ static char *get_new_source_name(const char *name)
|
|||
dstr_copy(&new_name, name);
|
||||
|
||||
for (;;) {
|
||||
obs_source_t *existing_source = obs_get_source_by_name(
|
||||
new_name.array);
|
||||
obs_source_t *existing_source =
|
||||
obs_get_source_by_name(new_name.array);
|
||||
if (!existing_source)
|
||||
break;
|
||||
|
||||
|
@ -176,8 +180,7 @@ bool AddNew(QWidget *parent, const char *id, const char *name,
|
|||
|
||||
obs_source_t *source = obs_get_source_by_name(name);
|
||||
if (source) {
|
||||
OBSMessageBox::information(parent,
|
||||
QTStr("NameExists.Title"),
|
||||
OBSMessageBox::information(parent, QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
|
||||
} else {
|
||||
|
@ -243,16 +246,13 @@ static inline const char *GetSourceDisplayName(const char *id)
|
|||
|
||||
Q_DECLARE_METATYPE(OBSScene);
|
||||
|
||||
template <typename T>
|
||||
static inline T GetOBSRef(QListWidgetItem *item)
|
||||
template<typename T> static inline T GetOBSRef(QListWidgetItem *item)
|
||||
{
|
||||
return item->data(static_cast<int>(QtDataRole::OBSRef)).value<T>();
|
||||
}
|
||||
|
||||
OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
|
||||
: QDialog (parent),
|
||||
ui (new Ui::OBSBasicSourceSelect),
|
||||
id (id_)
|
||||
: QDialog(parent), ui(new Ui::OBSBasicSourceSelect), id(id_)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
|
@ -277,8 +277,8 @@ OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
|
|||
installEventFilter(CreateShortcutFilter());
|
||||
|
||||
if (strcmp(id_, "scene") == 0) {
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic*>(
|
||||
App()->GetMainWindow());
|
||||
OBSBasic *main =
|
||||
reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
OBSSource curSceneSource = main->GetCurrentSceneSource();
|
||||
|
||||
ui->selectExisting->setChecked(true);
|
||||
|
|
|
@ -58,15 +58,13 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
|
|||
|
||||
int row = 0;
|
||||
|
||||
auto newStatBare = [&] (QString name, QWidget *label, int col)
|
||||
{
|
||||
auto newStatBare = [&](QString name, QWidget *label, int col) {
|
||||
QLabel *typeLabel = new QLabel(name, this);
|
||||
topLayout->addWidget(typeLabel, row, col);
|
||||
topLayout->addWidget(label, row++, col + 1);
|
||||
};
|
||||
|
||||
auto newStat = [&] (const char *strLoc, QWidget *label, int col)
|
||||
{
|
||||
auto newStat = [&](const char *strLoc, QWidget *label, int col) {
|
||||
std::string str = "Basic.Stats.";
|
||||
str += strLoc;
|
||||
newStatBare(QTStr(str.c_str()), label, col);
|
||||
|
@ -109,8 +107,7 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
|
|||
/* --------------------------------------------- */
|
||||
|
||||
int col = 0;
|
||||
auto addOutputCol = [&] (const char *loc)
|
||||
{
|
||||
auto addOutputCol = [&](const char *loc) {
|
||||
QLabel *label = new QLabel(QTStr(loc), this);
|
||||
label->setStyleSheet("font-weight: bold");
|
||||
outputLayout->addWidget(label, 0, col++);
|
||||
|
@ -165,7 +162,8 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
|
|||
setWindowModality(Qt::NonModal);
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
QObject::connect(&timer, &QTimer::timeout, this, &OBSBasicStats::Update);
|
||||
QObject::connect(&timer, &QTimer::timeout, this,
|
||||
&OBSBasicStats::Update);
|
||||
timer.setInterval(TIMER_INTERVAL);
|
||||
|
||||
if (isVisible())
|
||||
|
@ -179,20 +177,19 @@ OBSBasicStats::OBSBasicStats(QWidget *parent, bool closeable)
|
|||
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
|
||||
const char *geometry = config_get_string(main->Config(),
|
||||
"Stats", "geometry");
|
||||
const char *geometry =
|
||||
config_get_string(main->Config(), "Stats", "geometry");
|
||||
if (geometry != NULL) {
|
||||
QByteArray byteArray = QByteArray::fromBase64(
|
||||
QByteArray(geometry));
|
||||
QByteArray byteArray =
|
||||
QByteArray::fromBase64(QByteArray(geometry));
|
||||
restoreGeometry(byteArray);
|
||||
|
||||
QRect windowGeometry = normalGeometry();
|
||||
if (!WindowPositionValid(windowGeometry)) {
|
||||
QRect rect = App()->desktop()->geometry();
|
||||
setGeometry(QStyle::alignedRect(
|
||||
Qt::LeftToRight,
|
||||
Qt::AlignCenter,
|
||||
size(), rect));
|
||||
setGeometry(QStyle::alignedRect(Qt::LeftToRight,
|
||||
Qt::AlignCenter, size(),
|
||||
rect));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,8 +200,7 @@ void OBSBasicStats::closeEvent(QCloseEvent *event)
|
|||
{
|
||||
OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
|
||||
if (isVisible()) {
|
||||
config_set_string(main->Config(),
|
||||
"Stats", "geometry",
|
||||
config_set_string(main->Config(), "Stats", "geometry",
|
||||
saveGeometry().toBase64().constData());
|
||||
config_save_safe(main->Config(), "tmp", nullptr);
|
||||
}
|
||||
|
@ -302,9 +298,12 @@ void OBSBasicStats::Update()
|
|||
/* ------------------ */
|
||||
|
||||
const char *mode = config_get_string(main->Config(), "Output", "Mode");
|
||||
const char *path = strcmp(mode, "Advanced") ?
|
||||
config_get_string(main->Config(), "SimpleOutput", "FilePath") :
|
||||
config_get_string(main->Config(), "AdvOut", "RecFilePath");
|
||||
const char *path = strcmp(mode, "Advanced")
|
||||
? config_get_string(main->Config(),
|
||||
"SimpleOutput",
|
||||
"FilePath")
|
||||
: config_get_string(main->Config(), "AdvOut",
|
||||
"RecFilePath");
|
||||
|
||||
#define MBYTE (1024ULL * 1024ULL)
|
||||
#define GBYTE (1024ULL * 1024ULL * 1024ULL)
|
||||
|
@ -374,8 +373,8 @@ void OBSBasicStats::Update()
|
|||
: 0.0l;
|
||||
num *= 100.0l;
|
||||
|
||||
str = QString("%1 / %2 (%3%)").arg(
|
||||
QString::number(total_skipped),
|
||||
str = QString("%1 / %2 (%3%)")
|
||||
.arg(QString::number(total_skipped),
|
||||
QString::number(total_encoded),
|
||||
QString::number(num, 'f', 1));
|
||||
skippedFrames->setText(str);
|
||||
|
@ -404,8 +403,8 @@ void OBSBasicStats::Update()
|
|||
: 0.0l;
|
||||
num *= 100.0l;
|
||||
|
||||
str = QString("%1 / %2 (%3%)").arg(
|
||||
QString::number(total_lagged),
|
||||
str = QString("%1 / %2 (%3%)")
|
||||
.arg(QString::number(total_lagged),
|
||||
QString::number(total_rendered),
|
||||
QString::number(num, 'f', 1));
|
||||
missedFrames->setText(str);
|
||||
|
@ -444,8 +443,8 @@ void OBSBasicStats::ResetRecTimeLeft()
|
|||
|
||||
void OBSBasicStats::RecordingTimeLeft()
|
||||
{
|
||||
long double averageBitrate = accumulate(bitrates.begin(),
|
||||
bitrates.end(), 0.0) /
|
||||
long double averageBitrate =
|
||||
accumulate(bitrates.begin(), bitrates.end(), 0.0) /
|
||||
(long double)bitrates.size();
|
||||
long double bytesPerSec = (averageBitrate / 8.0l) * 1000.0l;
|
||||
long double secondsUntilFull = (long double)num_bytes / bytesPerSec;
|
||||
|
@ -457,8 +456,8 @@ void OBSBasicStats::RecordingTimeLeft()
|
|||
int hours = totalMinutes / 60;
|
||||
|
||||
QString text;
|
||||
text.sprintf("%d %s, %d %s", hours, QT_TO_UTF8(QTStr("Hours")),
|
||||
minutes, QT_TO_UTF8(QTStr("Minutes")));
|
||||
text.sprintf("%d %s, %d %s", hours, QT_TO_UTF8(QTStr("Hours")), minutes,
|
||||
QT_TO_UTF8(QTStr("Minutes")));
|
||||
recordTimeLeft->setText(text);
|
||||
recordTimeLeft->setMinimumWidth(recordTimeLeft->width());
|
||||
}
|
||||
|
@ -494,8 +493,8 @@ void OBSBasicStats::OutputLabels::Update(obs_output_t *output, bool rec)
|
|||
lastBytesSent = 0;
|
||||
|
||||
uint64_t bitsBetween = (bytesSent - lastBytesSent) * 8;
|
||||
long double timePassed = (long double)(curTime - lastBytesSentTime) /
|
||||
1000000000.0l;
|
||||
long double timePassed =
|
||||
(long double)(curTime - lastBytesSentTime) / 1000000000.0l;
|
||||
kbps = (long double)bitsBetween / timePassed / 1000.0l;
|
||||
|
||||
if (timePassed < 0.01l)
|
||||
|
@ -509,8 +508,8 @@ void OBSBasicStats::OutputLabels::Update(obs_output_t *output, bool rec)
|
|||
str = QTStr("Basic.Stats.Status.Recording");
|
||||
} else {
|
||||
if (active) {
|
||||
bool reconnecting = output
|
||||
? obs_output_reconnecting(output)
|
||||
bool reconnecting =
|
||||
output ? obs_output_reconnecting(output)
|
||||
: false;
|
||||
|
||||
if (reconnecting) {
|
||||
|
@ -530,12 +529,12 @@ void OBSBasicStats::OutputLabels::Update(obs_output_t *output, bool rec)
|
|||
|
||||
megabytesSent->setText(
|
||||
QString("%1 MB").arg(QString::number(num, 'f', 1)));
|
||||
bitrate->setText(
|
||||
QString("%1 kb/s").arg(QString::number(kbps, 'f', 0)));
|
||||
bitrate->setText(QString("%1 kb/s").arg(QString::number(kbps, 'f', 0)));
|
||||
|
||||
if (!rec) {
|
||||
int total = output ? obs_output_get_total_frames(output) : 0;
|
||||
int dropped = output ? obs_output_get_frames_dropped(output) : 0;
|
||||
int dropped = output ? obs_output_get_frames_dropped(output)
|
||||
: 0;
|
||||
|
||||
if (total < first_total || dropped < first_dropped) {
|
||||
first_total = 0;
|
||||
|
@ -545,12 +544,11 @@ void OBSBasicStats::OutputLabels::Update(obs_output_t *output, bool rec)
|
|||
total -= first_total;
|
||||
dropped -= first_dropped;
|
||||
|
||||
num = total
|
||||
? (long double)dropped / (long double)total * 100.0l
|
||||
num = total ? (long double)dropped / (long double)total * 100.0l
|
||||
: 0.0l;
|
||||
|
||||
str = QString("%1 / %2 (%3%)").arg(
|
||||
QString::number(dropped),
|
||||
str = QString("%1 / %2 (%3%)")
|
||||
.arg(QString::number(dropped),
|
||||
QString::number(total),
|
||||
QString::number(num, 'f', 1));
|
||||
droppedFrames->setText(str);
|
||||
|
|
|
@ -74,8 +74,8 @@ void OBSBasicStatusBar::Activate()
|
|||
{
|
||||
if (!active) {
|
||||
refreshTimer = new QTimer(this);
|
||||
connect(refreshTimer, SIGNAL(timeout()),
|
||||
this, SLOT(UpdateStatusBar()));
|
||||
connect(refreshTimer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateStatusBar()));
|
||||
|
||||
int skipped = video_output_get_skipped_frames(obs_get_video());
|
||||
int total = video_output_get_total_frames(obs_get_video());
|
||||
|
@ -175,14 +175,13 @@ void OBSBasicStatusBar::UpdateBandwidth()
|
|||
|
||||
uint64_t bitsBetween = (bytesSent - lastBytesSent) * 8;
|
||||
|
||||
double timePassed = double(bytesSentTime - lastBytesSentTime) /
|
||||
1000000000.0;
|
||||
double timePassed =
|
||||
double(bytesSentTime - lastBytesSentTime) / 1000000000.0;
|
||||
|
||||
double kbitsPerSec = double(bitsBetween) / timePassed / 1000.0;
|
||||
|
||||
QString text;
|
||||
text += QString("kb/s: ") +
|
||||
QString::number(kbitsPerSec, 'f', 0);
|
||||
text += QString("kb/s: ") + QString::number(kbitsPerSec, 'f', 0);
|
||||
|
||||
kbps->setText(text);
|
||||
kbps->setMinimumWidth(kbps->width());
|
||||
|
@ -293,11 +292,13 @@ void OBSBasicStatusBar::UpdateDroppedFrames()
|
|||
QPixmap pixmap(20, 20);
|
||||
|
||||
float red = avgCongestion * 2.0f;
|
||||
if (red > 1.0f) red = 1.0f;
|
||||
if (red > 1.0f)
|
||||
red = 1.0f;
|
||||
red *= 255.0;
|
||||
|
||||
float green = (1.0f - avgCongestion) * 2.0f;
|
||||
if (green > 1.0f) green = 1.0f;
|
||||
if (green > 1.0f)
|
||||
green = 1.0f;
|
||||
green *= 255.0;
|
||||
|
||||
pixmap.fill(QColor(int(red), int(green), 0));
|
||||
|
@ -317,7 +318,8 @@ void OBSBasicStatusBar::OBSOutputReconnect(void *data, calldata_t *params)
|
|||
UNUSED_PARAMETER(params);
|
||||
}
|
||||
|
||||
void OBSBasicStatusBar::OBSOutputReconnectSuccess(void *data, calldata_t *params)
|
||||
void OBSBasicStatusBar::OBSOutputReconnectSuccess(void *data,
|
||||
calldata_t *params)
|
||||
{
|
||||
OBSBasicStatusBar *statusBar =
|
||||
reinterpret_cast<OBSBasicStatusBar *>(data);
|
||||
|
@ -432,7 +434,8 @@ void OBSBasicStatusBar::StreamStarted(obs_output_t *output)
|
|||
signal_handler_connect(obs_output_get_signal_handler(streamOutput),
|
||||
"reconnect", OBSOutputReconnect, this);
|
||||
signal_handler_connect(obs_output_get_signal_handler(streamOutput),
|
||||
"reconnect_success", OBSOutputReconnectSuccess, this);
|
||||
"reconnect_success", OBSOutputReconnectSuccess,
|
||||
this);
|
||||
|
||||
retries = 0;
|
||||
lastBytesSent = 0;
|
||||
|
@ -448,8 +451,7 @@ void OBSBasicStatusBar::StreamStopped()
|
|||
"reconnect", OBSOutputReconnect, this);
|
||||
signal_handler_disconnect(
|
||||
obs_output_get_signal_handler(streamOutput),
|
||||
"reconnect_success", OBSOutputReconnectSuccess,
|
||||
this);
|
||||
"reconnect_success", OBSOutputReconnectSuccess, this);
|
||||
|
||||
ReconnectClear();
|
||||
streamOutput = nullptr;
|
||||
|
|
|
@ -40,9 +40,7 @@ void OBSBasicTransform::HookWidget(QWidget *widget, const char *signal,
|
|||
#define DSCROLL_CHANGED SIGNAL(valueChanged(double))
|
||||
|
||||
OBSBasicTransform::OBSBasicTransform(OBSBasic *parent)
|
||||
: QDialog (parent),
|
||||
ui (new Ui::OBSBasicTransform),
|
||||
main (parent)
|
||||
: QDialog(parent), ui(new Ui::OBSBasicTransform), main(parent)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -88,14 +86,15 @@ void OBSBasicTransform::SetScene(OBSScene scene)
|
|||
|
||||
if (scene) {
|
||||
OBSSource source = obs_scene_get_source(scene);
|
||||
signal_handler_t *signal = obs_source_get_signal_handler(source);
|
||||
signal_handler_t *signal =
|
||||
obs_source_get_signal_handler(source);
|
||||
|
||||
transformSignal.Connect(signal, "item_transform",
|
||||
OBSSceneItemTransform, this);
|
||||
removeSignal.Connect(signal, "item_remove",
|
||||
OBSSceneItemRemoved, this);
|
||||
selectSignal.Connect(signal, "item_select",
|
||||
OBSSceneItemSelect, this);
|
||||
removeSignal.Connect(signal, "item_remove", OBSSceneItemRemoved,
|
||||
this);
|
||||
selectSignal.Connect(signal, "item_select", OBSSceneItemSelect,
|
||||
this);
|
||||
deselectSignal.Connect(signal, "item_deselect",
|
||||
OBSSceneItemDeselect, this);
|
||||
}
|
||||
|
@ -118,7 +117,8 @@ void OBSBasicTransform::SetItemQt(OBSSceneItem newItem)
|
|||
|
||||
void OBSBasicTransform::OBSChannelChanged(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
|
||||
OBSBasicTransform *window =
|
||||
reinterpret_cast<OBSBasicTransform *>(param);
|
||||
uint32_t channel = (uint32_t)calldata_int(data, "channel");
|
||||
OBSSource source = (obs_source_t *)calldata_ptr(data, "source");
|
||||
|
||||
|
@ -135,7 +135,8 @@ void OBSBasicTransform::OBSChannelChanged(void *param, calldata_t *data)
|
|||
|
||||
void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
|
||||
OBSBasicTransform *window =
|
||||
reinterpret_cast<OBSBasicTransform *>(param);
|
||||
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
if (item == window->item && !window->ignoreTransformSignal)
|
||||
|
@ -144,7 +145,8 @@ void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t *data)
|
|||
|
||||
void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
|
||||
OBSBasicTransform *window =
|
||||
reinterpret_cast<OBSBasicTransform *>(param);
|
||||
OBSScene scene = (obs_scene_t *)calldata_ptr(data, "scene");
|
||||
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
|
@ -154,7 +156,8 @@ void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
|
|||
|
||||
void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
|
||||
OBSBasicTransform *window =
|
||||
reinterpret_cast<OBSBasicTransform *>(param);
|
||||
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
if (item != window->item)
|
||||
|
@ -163,7 +166,8 @@ void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t *data)
|
|||
|
||||
void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
|
||||
OBSBasicTransform *window =
|
||||
reinterpret_cast<OBSBasicTransform *>(param);
|
||||
OBSScene scene = (obs_scene_t *)calldata_ptr(data, "scene");
|
||||
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
|
||||
|
||||
|
@ -171,8 +175,7 @@ void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t *data)
|
|||
window->SetItem(FindASelectedItem(scene));
|
||||
}
|
||||
|
||||
static const uint32_t listToAlign[] = {
|
||||
OBS_ALIGN_TOP | OBS_ALIGN_LEFT,
|
||||
static const uint32_t listToAlign[] = {OBS_ALIGN_TOP | OBS_ALIGN_LEFT,
|
||||
OBS_ALIGN_TOP,
|
||||
OBS_ALIGN_TOP | OBS_ALIGN_RIGHT,
|
||||
OBS_ALIGN_LEFT,
|
||||
|
@ -180,8 +183,7 @@ static const uint32_t listToAlign[] = {
|
|||
OBS_ALIGN_RIGHT,
|
||||
OBS_ALIGN_BOTTOM | OBS_ALIGN_LEFT,
|
||||
OBS_ALIGN_BOTTOM,
|
||||
OBS_ALIGN_BOTTOM | OBS_ALIGN_RIGHT
|
||||
};
|
||||
OBS_ALIGN_BOTTOM | OBS_ALIGN_RIGHT};
|
||||
|
||||
static int AlignToList(uint32_t align)
|
||||
{
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
void OBSDock::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
auto msgBox = [] ()
|
||||
{
|
||||
auto msgBox = []() {
|
||||
QMessageBox msgbox(App()->GetMainWindow());
|
||||
msgbox.setWindowTitle(QTStr("DockCloseWarning.Title"));
|
||||
msgbox.setText(QTStr("DockCloseWarning.Text"));
|
||||
|
@ -29,8 +28,7 @@ void OBSDock::closeEvent(QCloseEvent *event)
|
|||
bool warned = config_get_bool(App()->GlobalConfig(), "General",
|
||||
"WarnedAboutClosingDocks");
|
||||
if (!warned) {
|
||||
QMetaObject::invokeMethod(App(), "Exec",
|
||||
Qt::QueuedConnection,
|
||||
QMetaObject::invokeMethod(App(), "Exec", Qt::QueuedConnection,
|
||||
Q_ARG(VoidFunc, msgBox));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@
|
|||
#include "obs-app.hpp"
|
||||
|
||||
OBSLogReply::OBSLogReply(QWidget *parent, const QString &url)
|
||||
: QDialog (parent),
|
||||
ui (new Ui::OBSLogReply)
|
||||
: QDialog(parent), ui(new Ui::OBSLogReply)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->urlEdit->setText(url);
|
||||
|
|
|
@ -13,6 +13,6 @@ public:
|
|||
virtual config_t *Config() const = 0;
|
||||
virtual void OBSInit() = 0;
|
||||
|
||||
virtual int GetProfilePath(char *path, size_t size, const char *file)
|
||||
const=0;
|
||||
virtual int GetProfilePath(char *path, size_t size,
|
||||
const char *file) const = 0;
|
||||
};
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
using namespace std;
|
||||
|
||||
NameDialog::NameDialog(QWidget *parent)
|
||||
: QDialog (parent),
|
||||
ui (new Ui::NameDialog)
|
||||
: QDialog(parent), ui(new Ui::NameDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
|
@ -37,15 +36,16 @@ static bool IsWhitespace(char ch)
|
|||
}
|
||||
|
||||
bool NameDialog::AskForName(QWidget *parent, const QString &title,
|
||||
const QString &text, string &str, const QString &placeHolder,
|
||||
int maxSize)
|
||||
const QString &text, string &str,
|
||||
const QString &placeHolder, int maxSize)
|
||||
{
|
||||
if (maxSize <= 0 || maxSize > 32767)
|
||||
maxSize = 256;
|
||||
|
||||
NameDialog dialog(parent);
|
||||
dialog.setWindowTitle(title);
|
||||
dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
dialog.setWindowFlags(dialog.windowFlags() &
|
||||
~Qt::WindowContextHelpButtonHint);
|
||||
dialog.ui->label->setText(text);
|
||||
dialog.ui->userText->setMaxLength(maxSize);
|
||||
dialog.ui->userText->setText(placeHolder);
|
||||
|
|
|
@ -18,11 +18,10 @@ static size_t maxSrcs, numSrcs;
|
|||
|
||||
OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
||||
QString title, ProjectorType type_)
|
||||
: OBSQTDisplay (widget,
|
||||
Qt::Window),
|
||||
: OBSQTDisplay(widget, Qt::Window),
|
||||
source(source_),
|
||||
removedSignal (obs_source_get_signal_handler(source),
|
||||
"remove", OBSSourceRemoved, this)
|
||||
removedSignal(obs_source_get_signal_handler(source), "remove",
|
||||
OBSSourceRemoved, this)
|
||||
{
|
||||
projectorTitle = std::move(title);
|
||||
savedMonitor = monitor;
|
||||
|
@ -30,8 +29,8 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
|||
type = type_;
|
||||
|
||||
if (isWindow) {
|
||||
setWindowIcon(QIcon::fromTheme("obs",
|
||||
QIcon(":/res/images/obs.png")));
|
||||
setWindowIcon(
|
||||
QIcon::fromTheme("obs", QIcon(":/res/images/obs.png")));
|
||||
|
||||
UpdateProjectorTitle(projectorTitle);
|
||||
windowedProjectors.push_back(this);
|
||||
|
@ -51,8 +50,8 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
|||
SLOT(EscapeTriggered()));
|
||||
}
|
||||
|
||||
SetAlwaysOnTop(this, config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "ProjectorAlwaysOnTop"));
|
||||
SetAlwaysOnTop(this, config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"ProjectorAlwaysOnTop"));
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
||||
|
@ -61,19 +60,18 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
|||
|
||||
installEventFilter(CreateShortcutFilter());
|
||||
|
||||
auto addDrawCallback = [this] ()
|
||||
{
|
||||
auto addDrawCallback = [this]() {
|
||||
bool isMultiview = type == ProjectorType::Multiview;
|
||||
obs_display_add_draw_callback(GetDisplay(),
|
||||
isMultiview ? OBSRenderMultiview : OBSRender,
|
||||
this);
|
||||
obs_display_add_draw_callback(
|
||||
GetDisplay(),
|
||||
isMultiview ? OBSRenderMultiview : OBSRender, this);
|
||||
obs_display_set_background_color(GetDisplay(), 0x000000);
|
||||
};
|
||||
|
||||
connect(this, &OBSQTDisplay::DisplayCreated, addDrawCallback);
|
||||
|
||||
bool hideCursor = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "HideProjectorCursor");
|
||||
bool hideCursor = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"HideProjectorCursor");
|
||||
if (hideCursor && !isWindow && type != ProjectorType::Multiview) {
|
||||
QPixmap empty(16, 16);
|
||||
empty.fill(Qt::transparent);
|
||||
|
@ -107,8 +105,8 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
|||
gs_vertex2f(fourByThreeSafePercentage, graphicsSafePercentage);
|
||||
gs_vertex2f(1 - fourByThreeSafePercentage,
|
||||
graphicsSafePercentage);
|
||||
gs_vertex2f(1 - fourByThreeSafePercentage, 1 -
|
||||
graphicsSafePercentage);
|
||||
gs_vertex2f(1 - fourByThreeSafePercentage,
|
||||
1 - graphicsSafePercentage);
|
||||
gs_vertex2f(fourByThreeSafePercentage,
|
||||
1 - graphicsSafePercentage);
|
||||
gs_vertex2f(fourByThreeSafePercentage, graphicsSafePercentage);
|
||||
|
@ -155,8 +153,9 @@ OBSProjector::OBSProjector(QWidget *widget, obs_source_t *source_, int monitor,
|
|||
OBSProjector::~OBSProjector()
|
||||
{
|
||||
bool isMultiview = type == ProjectorType::Multiview;
|
||||
obs_display_remove_draw_callback(GetDisplay(),
|
||||
isMultiview ? OBSRenderMultiview : OBSRender, this);
|
||||
obs_display_remove_draw_callback(
|
||||
GetDisplay(), isMultiview ? OBSRenderMultiview : OBSRender,
|
||||
this);
|
||||
|
||||
if (source)
|
||||
obs_source_dec_showing(source);
|
||||
|
@ -217,8 +216,8 @@ static OBSSource CreateLabel(const char *name, size_t h)
|
|||
const char *text_source_id = "text_ft2_source";
|
||||
#endif
|
||||
|
||||
OBSSource txtSource = obs_source_create_private(text_source_id, name,
|
||||
settings);
|
||||
OBSSource txtSource =
|
||||
obs_source_create_private(text_source_id, name, settings);
|
||||
obs_source_release(txtSource);
|
||||
|
||||
obs_data_release(font);
|
||||
|
@ -282,8 +281,7 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
bool studioMode = main->IsPreviewProgramMode();
|
||||
|
||||
auto renderVB = [&](gs_vertbuffer_t *vb, int cx, int cy,
|
||||
uint32_t colorVal)
|
||||
{
|
||||
uint32_t colorVal) {
|
||||
if (!vb)
|
||||
return;
|
||||
|
||||
|
@ -304,16 +302,13 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
gs_matrix_pop();
|
||||
};
|
||||
|
||||
auto drawBox = [&](float cx, float cy, uint32_t colorVal)
|
||||
{
|
||||
auto drawBox = [&](float cx, float cy, uint32_t colorVal) {
|
||||
gs_effect_set_color(window->color, colorVal);
|
||||
while (gs_effect_loop(window->solid, "Solid"))
|
||||
gs_draw_sprite(nullptr, 0, (uint32_t)cx, (uint32_t)cy);
|
||||
};
|
||||
|
||||
auto setRegion = [&](float bx, float by, float cx,
|
||||
float cy)
|
||||
{
|
||||
auto setRegion = [&](float bx, float by, float cx, float cy) {
|
||||
float vX = int(x + bx * scale);
|
||||
float vY = int(y + by * scale);
|
||||
float vCX = int(cx * scale);
|
||||
|
@ -327,13 +322,12 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
startRegion(vX, vY, vCX, vCY, oL, oR, oT, oB);
|
||||
};
|
||||
|
||||
auto calcBaseSource = [&](size_t i)
|
||||
{
|
||||
auto calcBaseSource = [&](size_t i) {
|
||||
switch (multiviewLayout) {
|
||||
case MultiviewLayout::HORIZONTAL_TOP_24_SCENES:
|
||||
window->sourceX = (i % 6) * window->scenesCX;
|
||||
window->sourceY = window->pvwprgCY +
|
||||
(i / 6) * window->scenesCY;
|
||||
window->sourceY =
|
||||
window->pvwprgCY + (i / 6) * window->scenesCY;
|
||||
break;
|
||||
case MultiviewLayout::VERTICAL_LEFT_8_SCENES:
|
||||
window->sourceX = window->pvwprgCX;
|
||||
|
@ -352,8 +346,8 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
window->sourceX = (float(i) * window->scenesCX);
|
||||
window->sourceY = 0;
|
||||
} else {
|
||||
window->sourceX = (float(i - 4) *
|
||||
window->scenesCX);
|
||||
window->sourceX =
|
||||
(float(i - 4) * window->scenesCX);
|
||||
window->sourceY = window->scenesCY;
|
||||
}
|
||||
break;
|
||||
|
@ -362,22 +356,21 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
window->sourceX = (float(i) * window->scenesCX);
|
||||
window->sourceY = window->pvwprgCY;
|
||||
} else {
|
||||
window->sourceX = (float(i - 4) *
|
||||
window->scenesCX);
|
||||
window->sourceY = window->pvwprgCY +
|
||||
window->scenesCY;
|
||||
window->sourceX =
|
||||
(float(i - 4) * window->scenesCX);
|
||||
window->sourceY =
|
||||
window->pvwprgCY + window->scenesCY;
|
||||
}
|
||||
}
|
||||
window->siX = window->sourceX + window->thickness;
|
||||
window->siY = window->sourceY + window->thickness;
|
||||
};
|
||||
|
||||
auto calcPreviewProgram = [&](bool program)
|
||||
{
|
||||
auto calcPreviewProgram = [&](bool program) {
|
||||
switch (multiviewLayout) {
|
||||
case MultiviewLayout::HORIZONTAL_TOP_24_SCENES:
|
||||
window->sourceX = window->thickness +
|
||||
window->pvwprgCX / 2;
|
||||
window->sourceX =
|
||||
window->thickness + window->pvwprgCX / 2;
|
||||
window->sourceY = window->thickness;
|
||||
window->labelX = window->offset + window->pvwprgCX / 2;
|
||||
window->labelY = window->pvwprgCY * 0.85f;
|
||||
|
@ -429,8 +422,7 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
};
|
||||
|
||||
auto paintAreaWithColor = [&](float tx, float ty, float cx, float cy,
|
||||
uint32_t color)
|
||||
{
|
||||
uint32_t color) {
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(tx, ty, 0.0f);
|
||||
drawBox(cx, cy, color);
|
||||
|
@ -473,7 +465,8 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
|
||||
// Paint the background
|
||||
paintAreaWithColor(window->sourceX, window->sourceY,
|
||||
window->scenesCX, window->scenesCY, colorVal);
|
||||
window->scenesCX, window->scenesCY,
|
||||
colorVal);
|
||||
paintAreaWithColor(window->siX, window->siY, window->siCX,
|
||||
window->siCY, backgroundColor);
|
||||
|
||||
|
@ -501,13 +494,14 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
window->offset = labelOffset(label, window->scenesCX);
|
||||
|
||||
gs_matrix_push();
|
||||
gs_matrix_translate3f(window->sourceX + window->offset,
|
||||
(window->scenesCY * 0.85f) + window->sourceY,
|
||||
0.0f);
|
||||
gs_matrix_translate3f(
|
||||
window->sourceX + window->offset,
|
||||
(window->scenesCY * 0.85f) + window->sourceY, 0.0f);
|
||||
gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
|
||||
drawBox(obs_source_get_width(label),
|
||||
obs_source_get_height(label) +
|
||||
int(window->sourceY * 0.015f), labelColor);
|
||||
int(window->sourceY * 0.015f),
|
||||
labelColor);
|
||||
obs_source_video_render(label);
|
||||
gs_matrix_pop();
|
||||
}
|
||||
|
@ -556,7 +550,8 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
|
||||
drawBox(obs_source_get_width(previewLabel),
|
||||
obs_source_get_height(previewLabel) +
|
||||
int(window->pvwprgCX * 0.015f), labelColor);
|
||||
int(window->pvwprgCX * 0.015f),
|
||||
labelColor);
|
||||
obs_source_video_render(previewLabel);
|
||||
gs_matrix_pop();
|
||||
}
|
||||
|
@ -590,7 +585,8 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
gs_matrix_scale3f(window->ppiScaleX, window->ppiScaleY, 1.0f);
|
||||
drawBox(obs_source_get_width(programLabel),
|
||||
obs_source_get_height(programLabel) +
|
||||
int(window->pvwprgCX * 0.015f), labelColor);
|
||||
int(window->pvwprgCX * 0.015f),
|
||||
labelColor);
|
||||
obs_source_video_render(programLabel);
|
||||
gs_matrix_pop();
|
||||
}
|
||||
|
@ -599,10 +595,12 @@ void OBSProjector::OBSRenderMultiview(void *data, uint32_t cx, uint32_t cy)
|
|||
if (multiviewLayout == MultiviewLayout::HORIZONTAL_TOP_24_SCENES) {
|
||||
// Just paint the background for now
|
||||
paintAreaWithColor(window->thickness, window->thickness,
|
||||
window->siCX, window->siCY * 2 +
|
||||
window->thicknessx2, backgroundColor);
|
||||
paintAreaWithColor(window->thickness + 2.5 * (
|
||||
window->thicknessx2 + window->ppiCX),
|
||||
window->siCX,
|
||||
window->siCY * 2 + window->thicknessx2,
|
||||
backgroundColor);
|
||||
paintAreaWithColor(
|
||||
window->thickness +
|
||||
2.5 * (window->thicknessx2 + window->ppiCX),
|
||||
window->thickness, window->siCX,
|
||||
window->siCY * 2 + window->thicknessx2,
|
||||
backgroundColor);
|
||||
|
@ -863,16 +861,16 @@ void OBSProjector::UpdateMultiview()
|
|||
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));
|
||||
|
||||
multiviewLayout = static_cast<MultiviewLayout>(config_get_int(
|
||||
GetGlobalConfig(), "BasicWindow", "MultiviewLayout"));
|
||||
|
||||
drawLabel = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "MultiviewDrawNames");
|
||||
drawLabel = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"MultiviewDrawNames");
|
||||
|
||||
drawSafeArea = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"MultiviewDrawAreas");
|
||||
|
@ -880,8 +878,8 @@ void OBSProjector::UpdateMultiview()
|
|||
mouseSwitching = config_get_bool(GetGlobalConfig(), "BasicWindow",
|
||||
"MultiviewMouseSwitch");
|
||||
|
||||
transitionOnDoubleClick = config_get_bool(GetGlobalConfig(),
|
||||
"BasicWindow", "TransitionOnDoubleClick");
|
||||
transitionOnDoubleClick = config_get_bool(
|
||||
GetGlobalConfig(), "BasicWindow", "TransitionOnDoubleClick");
|
||||
|
||||
switch (multiviewLayout) {
|
||||
case MultiviewLayout::HORIZONTAL_TOP_24_SCENES:
|
||||
|
|
|
@ -8,7 +8,7 @@ enum class ProjectorType {
|
|||
Scene,
|
||||
Preview,
|
||||
StudioProgram,
|
||||
Multiview
|
||||
Multiview,
|
||||
};
|
||||
|
||||
class QMouseEvent;
|
||||
|
@ -18,7 +18,7 @@ enum class MultiviewLayout : uint8_t {
|
|||
HORIZONTAL_BOTTOM_8_SCENES = 1,
|
||||
VERTICAL_LEFT_8_SCENES = 2,
|
||||
VERTICAL_RIGHT_8_SCENES = 3,
|
||||
HORIZONTAL_TOP_24_SCENES = 4
|
||||
HORIZONTAL_TOP_24_SCENES = 4,
|
||||
};
|
||||
|
||||
class OBSProjector : public OBSQTDisplay {
|
||||
|
@ -51,10 +51,10 @@ private:
|
|||
gs_eparam_t *color = nullptr;
|
||||
// Multiview position helpers
|
||||
float thickness = 4;
|
||||
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;
|
||||
|
||||
float lineLength = 0.1f;
|
||||
// Rec. ITU-R BT.1848-1 / EBU R 95
|
||||
|
|
|
@ -48,28 +48,24 @@ enum RemuxEntryColumn {
|
|||
Count
|
||||
};
|
||||
|
||||
enum RemuxEntryRole {
|
||||
EntryStateRole = Qt::UserRole,
|
||||
NewPathsToProcessRole
|
||||
};
|
||||
enum RemuxEntryRole { EntryStateRole = Qt::UserRole, NewPathsToProcessRole };
|
||||
|
||||
/**********************************************************
|
||||
Delegate - Presents cells in the grid.
|
||||
**********************************************************/
|
||||
|
||||
RemuxEntryPathItemDelegate::RemuxEntryPathItemDelegate(bool isOutput,
|
||||
const QString &defaultPath)
|
||||
: QStyledItemDelegate(),
|
||||
isOutput(isOutput),
|
||||
defaultPath(defaultPath)
|
||||
RemuxEntryPathItemDelegate::RemuxEntryPathItemDelegate(
|
||||
bool isOutput, const QString &defaultPath)
|
||||
: QStyledItemDelegate(), isOutput(isOutput), defaultPath(defaultPath)
|
||||
{
|
||||
}
|
||||
|
||||
QWidget *RemuxEntryPathItemDelegate::createEditor(QWidget *parent,
|
||||
const QStyleOptionViewItem & /* option */,
|
||||
QWidget *RemuxEntryPathItemDelegate::createEditor(
|
||||
QWidget *parent, const QStyleOptionViewItem & /* option */,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
RemuxEntryState state = index.model()
|
||||
RemuxEntryState state =
|
||||
index.model()
|
||||
->index(index.row(), RemuxEntryColumn::State)
|
||||
.data(RemuxEntryRole::EntryStateRole)
|
||||
.value<RemuxEntryState>();
|
||||
|
@ -94,14 +90,12 @@ QWidget *RemuxEntryPathItemDelegate::createEditor(QWidget *parent,
|
|||
|
||||
QWidget *container = new QWidget(parent);
|
||||
|
||||
auto browseCallback = [this, container]()
|
||||
{
|
||||
auto browseCallback = [this, container]() {
|
||||
const_cast<RemuxEntryPathItemDelegate *>(this)
|
||||
->handleBrowse(container);
|
||||
};
|
||||
|
||||
auto clearCallback = [this, container]()
|
||||
{
|
||||
auto clearCallback = [this, container]() {
|
||||
const_cast<RemuxEntryPathItemDelegate *>(this)
|
||||
->handleClear(container);
|
||||
};
|
||||
|
@ -112,8 +106,8 @@ QWidget *RemuxEntryPathItemDelegate::createEditor(QWidget *parent,
|
|||
|
||||
QLineEdit *text = new QLineEdit();
|
||||
text->setObjectName(QStringLiteral("text"));
|
||||
text->setSizePolicy(QSizePolicy(
|
||||
QSizePolicy::Policy::Expanding,
|
||||
text->setSizePolicy(
|
||||
QSizePolicy(QSizePolicy::Policy::Expanding,
|
||||
QSizePolicy::Policy::Expanding,
|
||||
QSizePolicy::ControlType::LineEdit));
|
||||
layout->addWidget(text);
|
||||
|
@ -134,8 +128,7 @@ QWidget *RemuxEntryPathItemDelegate::createEditor(QWidget *parent,
|
|||
clearButton->setSizePolicy(buttonSizePolicy);
|
||||
layout->addWidget(clearButton);
|
||||
|
||||
container->connect(clearButton,
|
||||
&QToolButton::clicked,
|
||||
container->connect(clearButton, &QToolButton::clicked,
|
||||
clearCallback);
|
||||
}
|
||||
|
||||
|
@ -150,7 +143,8 @@ void RemuxEntryPathItemDelegate::setEditorData(QWidget *editor,
|
|||
{
|
||||
QLineEdit *text = editor->findChild<QLineEdit *>();
|
||||
text->setText(index.data().toString());
|
||||
QObject::connect(text, SIGNAL(textEdited(QString)), this, SLOT(updateText()));
|
||||
QObject::connect(text, SIGNAL(textEdited(QString)), this,
|
||||
SLOT(updateText()));
|
||||
editor->setProperty(PATH_LIST_PROP, QVariant());
|
||||
}
|
||||
|
||||
|
@ -167,8 +161,8 @@ void RemuxEntryPathItemDelegate::setModelData(QWidget *editor,
|
|||
// as normal text data in the default role.
|
||||
QVariant pathListProp = editor->property(PATH_LIST_PROP);
|
||||
if (pathListProp.isValid()) {
|
||||
QStringList list = editor->property(PATH_LIST_PROP)
|
||||
.toStringList();
|
||||
QStringList list =
|
||||
editor->property(PATH_LIST_PROP).toStringList();
|
||||
if (isOutput) {
|
||||
if (list.size() > 0)
|
||||
model->setData(index, list);
|
||||
|
@ -185,7 +179,8 @@ void RemuxEntryPathItemDelegate::paint(QPainter *painter,
|
|||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
RemuxEntryState state = index.model()
|
||||
RemuxEntryState state =
|
||||
index.model()
|
||||
->index(index.row(), RemuxEntryColumn::State)
|
||||
.data(RemuxEntryRole::EntryStateRole)
|
||||
.value<RemuxEntryState>();
|
||||
|
@ -195,8 +190,8 @@ void RemuxEntryPathItemDelegate::paint(QPainter *painter,
|
|||
|
||||
if (isOutput) {
|
||||
if (state != Ready) {
|
||||
QColor background = localOption.palette
|
||||
.color(QPalette::ColorGroup::Disabled,
|
||||
QColor background = localOption.palette.color(
|
||||
QPalette::ColorGroup::Disabled,
|
||||
QPalette::ColorRole::Background);
|
||||
|
||||
localOption.backgroundBrush = QBrush(background);
|
||||
|
@ -209,10 +204,8 @@ void RemuxEntryPathItemDelegate::paint(QPainter *painter,
|
|||
|
||||
void RemuxEntryPathItemDelegate::handleBrowse(QWidget *container)
|
||||
{
|
||||
QString OutputPattern =
|
||||
"(*.mp4 *.flv *.mov *.mkv *.ts *.m3u8)";
|
||||
QString InputPattern =
|
||||
"(*.flv *.mov *.mkv *.ts *.m3u8)";
|
||||
QString OutputPattern = "(*.mp4 *.flv *.mov *.mkv *.ts *.m3u8)";
|
||||
QString InputPattern = "(*.flv *.mov *.mkv *.ts *.m3u8)";
|
||||
|
||||
QLineEdit *text = container->findChild<QLineEdit *>();
|
||||
|
||||
|
@ -223,8 +216,8 @@ void RemuxEntryPathItemDelegate::handleBrowse(QWidget *container)
|
|||
bool isSet = false;
|
||||
if (isOutput) {
|
||||
QString newPath = QFileDialog::getSaveFileName(
|
||||
container, QTStr("Remux.SelectTarget"),
|
||||
currentPath, OutputPattern);
|
||||
container, QTStr("Remux.SelectTarget"), currentPath,
|
||||
OutputPattern);
|
||||
|
||||
if (!newPath.isEmpty()) {
|
||||
container->setProperty(PATH_LIST_PROP,
|
||||
|
@ -233,11 +226,9 @@ void RemuxEntryPathItemDelegate::handleBrowse(QWidget *container)
|
|||
}
|
||||
} else {
|
||||
QStringList paths = QFileDialog::getOpenFileNames(
|
||||
container,
|
||||
QTStr("Remux.SelectRecording"),
|
||||
currentPath,
|
||||
QTStr("Remux.OBSRecording")
|
||||
+ QString(" ") + InputPattern);
|
||||
container, QTStr("Remux.SelectRecording"), currentPath,
|
||||
QTStr("Remux.OBSRecording") + QString(" ") +
|
||||
InputPattern);
|
||||
|
||||
if (!paths.empty()) {
|
||||
container->setProperty(PATH_LIST_PROP, paths);
|
||||
|
@ -258,7 +249,8 @@ void RemuxEntryPathItemDelegate::handleClear(QWidget *container)
|
|||
emit commitData(container);
|
||||
}
|
||||
|
||||
void RemuxEntryPathItemDelegate::updateText() {
|
||||
void RemuxEntryPathItemDelegate::updateText()
|
||||
{
|
||||
QLineEdit *lineEdit = dynamic_cast<QLineEdit *>(sender());
|
||||
QWidget *editor = lineEdit->parentWidget();
|
||||
emit commitData(editor);
|
||||
|
@ -356,7 +348,8 @@ bool RemuxQueueModel::setData(const QModelIndex &index, const QVariant &value,
|
|||
endRemoveRows();
|
||||
}
|
||||
} else {
|
||||
if (pathList.size() > 1 && index.row() < queue.length()) {
|
||||
if (pathList.size() > 1 &&
|
||||
index.row() < queue.length()) {
|
||||
queue[index.row()].sourcePath = pathList[0];
|
||||
checkInputPath(index.row());
|
||||
|
||||
|
@ -414,12 +407,14 @@ bool RemuxQueueModel::setData(const QModelIndex &index, const QVariant &value,
|
|||
} else {
|
||||
switch (index.column()) {
|
||||
case RemuxEntryColumn::InputPath:
|
||||
queue[index.row()].sourcePath = value.toString();
|
||||
queue[index.row()].sourcePath =
|
||||
value.toString();
|
||||
checkInputPath(index.row());
|
||||
success = true;
|
||||
break;
|
||||
case RemuxEntryColumn::OutputPath:
|
||||
queue[index.row()].targetPath = value.toString();
|
||||
queue[index.row()].targetPath =
|
||||
value.toString();
|
||||
emit dataChanged(index, index);
|
||||
success = true;
|
||||
break;
|
||||
|
@ -437,23 +432,19 @@ QVariant RemuxQueueModel::getIcon(RemuxEntryState state)
|
|||
|
||||
switch (state) {
|
||||
case RemuxEntryState::Complete:
|
||||
icon = style->standardIcon(
|
||||
QStyle::SP_DialogApplyButton);
|
||||
icon = style->standardIcon(QStyle::SP_DialogApplyButton);
|
||||
break;
|
||||
|
||||
case RemuxEntryState::InProgress:
|
||||
icon = style->standardIcon(
|
||||
QStyle::SP_ArrowRight);
|
||||
icon = style->standardIcon(QStyle::SP_ArrowRight);
|
||||
break;
|
||||
|
||||
case RemuxEntryState::Error:
|
||||
icon = style->standardIcon(
|
||||
QStyle::SP_DialogCancelButton);
|
||||
icon = style->standardIcon(QStyle::SP_DialogCancelButton);
|
||||
break;
|
||||
|
||||
case RemuxEntryState::InvalidPath:
|
||||
icon = style->standardIcon(
|
||||
QStyle::SP_MessageBoxWarning);
|
||||
icon = style->standardIcon(QStyle::SP_MessageBoxWarning);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -477,8 +468,8 @@ void RemuxQueueModel::checkInputPath(int row)
|
|||
entry.state = RemuxEntryState::InvalidPath;
|
||||
|
||||
if (entry.state == RemuxEntryState::Ready)
|
||||
entry.targetPath = fileInfo.path() + QDir::separator()
|
||||
+ fileInfo.completeBaseName() + ".mp4";
|
||||
entry.targetPath = fileInfo.path() + QDir::separator() +
|
||||
fileInfo.completeBaseName() + ".mp4";
|
||||
}
|
||||
|
||||
if (entry.state == RemuxEntryState::Ready && isProcessing)
|
||||
|
@ -600,8 +591,8 @@ bool RemuxQueueModel::beginNextEntry(QString &inputPath, QString &outputPath)
|
|||
inputPath = entry.sourcePath;
|
||||
outputPath = entry.targetPath;
|
||||
|
||||
QModelIndex index = this->index(row,
|
||||
RemuxEntryColumn::State);
|
||||
QModelIndex index =
|
||||
this->index(row, RemuxEntryColumn::State);
|
||||
emit dataChanged(index, index);
|
||||
|
||||
anyStarted = true;
|
||||
|
@ -622,8 +613,8 @@ void RemuxQueueModel::finishEntry(bool success)
|
|||
else
|
||||
entry.state = RemuxEntryState::Error;
|
||||
|
||||
QModelIndex index = this->index(row,
|
||||
RemuxEntryColumn::State);
|
||||
QModelIndex index =
|
||||
this->index(row, RemuxEntryColumn::State);
|
||||
emit dataChanged(index, index);
|
||||
|
||||
break;
|
||||
|
@ -650,10 +641,9 @@ OBSRemux::OBSRemux(const char *path, QWidget *parent, bool autoRemux_)
|
|||
ui->setupUi(this);
|
||||
|
||||
ui->progressBar->setVisible(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
|
||||
setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)
|
||||
->setEnabled(false);
|
||||
|
||||
if (autoRemux) {
|
||||
resize(280, 40);
|
||||
|
@ -667,31 +657,31 @@ OBSRemux::OBSRemux(const char *path, QWidget *parent, bool autoRemux_)
|
|||
ui->progressBar->setValue(0);
|
||||
|
||||
ui->tableView->setModel(queueModel);
|
||||
ui->tableView->setItemDelegateForColumn(RemuxEntryColumn::InputPath,
|
||||
ui->tableView->setItemDelegateForColumn(
|
||||
RemuxEntryColumn::InputPath,
|
||||
new RemuxEntryPathItemDelegate(false, recPath));
|
||||
ui->tableView->setItemDelegateForColumn(RemuxEntryColumn::OutputPath,
|
||||
ui->tableView->setItemDelegateForColumn(
|
||||
RemuxEntryColumn::OutputPath,
|
||||
new RemuxEntryPathItemDelegate(true, recPath));
|
||||
ui->tableView->horizontalHeader()->setSectionResizeMode(
|
||||
QHeaderView::ResizeMode::Stretch);
|
||||
ui->tableView->horizontalHeader()->setSectionResizeMode(
|
||||
RemuxEntryColumn::State,
|
||||
QHeaderView::ResizeMode::Fixed);
|
||||
RemuxEntryColumn::State, QHeaderView::ResizeMode::Fixed);
|
||||
ui->tableView->setEditTriggers(
|
||||
QAbstractItemView::EditTrigger::CurrentChanged);
|
||||
|
||||
installEventFilter(CreateShortcutFilter());
|
||||
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setText(QTStr("Remux.Remux"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->
|
||||
setText(QTStr("Remux.ClearFinished"));
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
|
||||
setText(QTStr("Remux.ClearAll"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->
|
||||
setDisabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setText(QTStr("Remux.Remux"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)
|
||||
->setText(QTStr("Remux.ClearFinished"));
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)
|
||||
->setText(QTStr("Remux.ClearAll"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->setDisabled(true);
|
||||
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok),
|
||||
SIGNAL(clicked()), this, SLOT(beginRemux()));
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()),
|
||||
this, SLOT(beginRemux()));
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::Reset),
|
||||
SIGNAL(clicked()), this, SLOT(clearFinished()));
|
||||
connect(ui->buttonBox->button(QDialogButtonBox::RestoreDefaults),
|
||||
|
@ -704,28 +694,25 @@ OBSRemux::OBSRemux(const char *path, QWidget *parent, bool autoRemux_)
|
|||
|
||||
//gcc-4.8 can't use QPointer<RemuxWorker> below
|
||||
RemuxWorker *worker_ = worker;
|
||||
connect(worker_, &RemuxWorker::updateProgress,
|
||||
this, &OBSRemux::updateProgress);
|
||||
connect(worker_, &RemuxWorker::updateProgress, this,
|
||||
&OBSRemux::updateProgress);
|
||||
connect(&remuxer, &QThread::finished, worker_, &QObject::deleteLater);
|
||||
connect(worker_, &RemuxWorker::remuxFinished,
|
||||
this, &OBSRemux::remuxFinished);
|
||||
connect(worker_, &RemuxWorker::remuxFinished, this,
|
||||
&OBSRemux::remuxFinished);
|
||||
connect(this, &OBSRemux::remux, worker_, &RemuxWorker::remux);
|
||||
|
||||
// Guessing the GCC bug mentioned above would also affect
|
||||
// QPointer<RemuxQueueModel>? Unsure.
|
||||
RemuxQueueModel *queueModel_ = queueModel;
|
||||
connect(queueModel_,
|
||||
SIGNAL(rowsInserted(const QModelIndex &, int, int)),
|
||||
this,
|
||||
SLOT(rowCountChanged(const QModelIndex &, int, int)));
|
||||
connect(queueModel_,
|
||||
SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
|
||||
this,
|
||||
SIGNAL(rowsInserted(const QModelIndex &, int, int)), this,
|
||||
SLOT(rowCountChanged(const QModelIndex &, int, int)));
|
||||
connect(queueModel_, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
|
||||
this, SLOT(rowCountChanged(const QModelIndex &, int, int)));
|
||||
|
||||
QModelIndex index = queueModel->createIndex(0, 1);
|
||||
QMetaObject::invokeMethod(ui->tableView,
|
||||
"setCurrentIndex", Qt::QueuedConnection,
|
||||
QMetaObject::invokeMethod(ui->tableView, "setCurrentIndex",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(const QModelIndex &, index));
|
||||
}
|
||||
|
||||
|
@ -741,12 +728,10 @@ bool OBSRemux::stopRemux()
|
|||
|
||||
bool exit = false;
|
||||
|
||||
if (QMessageBox::critical(nullptr,
|
||||
QTStr("Remux.ExitUnfinishedTitle"),
|
||||
if (QMessageBox::critical(nullptr, QTStr("Remux.ExitUnfinishedTitle"),
|
||||
QTStr("Remux.ExitUnfinished"),
|
||||
QMessageBox::Yes | QMessageBox::No,
|
||||
QMessageBox::No) ==
|
||||
QMessageBox::Yes) {
|
||||
QMessageBox::No) == QMessageBox::Yes) {
|
||||
exit = true;
|
||||
}
|
||||
|
||||
|
@ -774,19 +759,17 @@ void OBSRemux::rowCountChanged(const QModelIndex &, int, int)
|
|||
// There must be more than one row, since there will always be
|
||||
// at least one row for the empty insertion point.
|
||||
if (queueModel->rowCount() > 1) {
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
|
||||
setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->
|
||||
setEnabled(queueModel->canClearFinished());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)
|
||||
->setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)
|
||||
->setEnabled(queueModel->canClearFinished());
|
||||
} else {
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
|
||||
setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->
|
||||
setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)
|
||||
->setEnabled(false);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)
|
||||
->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,13 +782,12 @@ void OBSRemux::dropEvent(QDropEvent *ev)
|
|||
|
||||
if (fileInfo.isDir()) {
|
||||
QStringList directoryFilter;
|
||||
directoryFilter <<
|
||||
"*.flv" <<
|
||||
"*.mp4" <<
|
||||
"*.mov" <<
|
||||
"*.mkv" <<
|
||||
"*.ts" <<
|
||||
"*.m3u8";
|
||||
directoryFilter << "*.flv"
|
||||
<< "*.mp4"
|
||||
<< "*.mov"
|
||||
<< "*.mkv"
|
||||
<< "*.ts"
|
||||
<< "*.m3u8";
|
||||
|
||||
QDirIterator dirIter(fileInfo.absoluteFilePath(),
|
||||
directoryFilter, QDir::Files,
|
||||
|
@ -822,10 +804,11 @@ void OBSRemux::dropEvent(QDropEvent *ev)
|
|||
if (urlList.empty()) {
|
||||
QMessageBox::information(nullptr,
|
||||
QTStr("Remux.NoFilesAddedTitle"),
|
||||
QTStr("Remux.NoFilesAdded"), QMessageBox::Ok);
|
||||
QTStr("Remux.NoFilesAdded"),
|
||||
QMessageBox::Ok);
|
||||
} else if (!autoRemux) {
|
||||
QModelIndex insertIndex = queueModel->index(
|
||||
queueModel->rowCount() - 1,
|
||||
QModelIndex insertIndex =
|
||||
queueModel->index(queueModel->rowCount() - 1,
|
||||
RemuxEntryColumn::InputPath);
|
||||
queueModel->setData(insertIndex, urlList,
|
||||
RemuxEntryRole::NewPathsToProcessRole);
|
||||
|
@ -856,8 +839,8 @@ void OBSRemux::beginRemux()
|
|||
message += fileInfo.canonicalFilePath() + "\n";
|
||||
|
||||
if (OBSMessageBox::question(this,
|
||||
QTStr("Remux.FileExistsTitle"), message)
|
||||
!= QMessageBox::Yes)
|
||||
QTStr("Remux.FileExistsTitle"),
|
||||
message) != QMessageBox::Yes)
|
||||
proceedWithRemux = false;
|
||||
}
|
||||
|
||||
|
@ -868,8 +851,8 @@ void OBSRemux::beginRemux()
|
|||
queueModel->beginProcessing();
|
||||
|
||||
ui->progressBar->setVisible(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setText(QTStr("Remux.Stop"));
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setText(QTStr("Remux.Stop"));
|
||||
setAcceptDrops(false);
|
||||
|
||||
remuxNextEntry();
|
||||
|
@ -895,20 +878,20 @@ void OBSRemux::remuxNextEntry()
|
|||
queueModel->endProcessing();
|
||||
|
||||
if (!autoRemux) {
|
||||
OBSMessageBox::information(this,
|
||||
QTStr("Remux.FinishedTitle"),
|
||||
OBSMessageBox::information(
|
||||
this, QTStr("Remux.FinishedTitle"),
|
||||
queueModel->checkForErrors()
|
||||
? QTStr("Remux.FinishedError")
|
||||
: QTStr("Remux.Finished"));
|
||||
}
|
||||
|
||||
ui->progressBar->setVisible(autoRemux);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setText(QTStr("Remux.Remux"));
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->
|
||||
setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)->
|
||||
setEnabled(queueModel->canClearFinished());
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)
|
||||
->setText(QTStr("Remux.Remux"));
|
||||
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)
|
||||
->setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Reset)
|
||||
->setEnabled(queueModel->canClearFinished());
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
}
|
||||
|
@ -936,8 +919,7 @@ void OBSRemux::updateProgress(float percent)
|
|||
|
||||
void OBSRemux::remuxFinished(bool success)
|
||||
{
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->
|
||||
setEnabled(true);
|
||||
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
|
||||
queueModel->finishEntry(success);
|
||||
|
||||
|
@ -976,8 +958,7 @@ void RemuxWorker::remux(const QString &source, const QString &target)
|
|||
{
|
||||
isWorking = true;
|
||||
|
||||
auto callback = [](void *data, float percent)
|
||||
{
|
||||
auto callback = [](void *data, float percent) {
|
||||
RemuxWorker *rw = static_cast<RemuxWorker *>(data);
|
||||
|
||||
QMutexLocker lock(&rw->updateMutex);
|
||||
|
@ -991,12 +972,10 @@ void RemuxWorker::remux(const QString &source, const QString &target)
|
|||
bool success = false;
|
||||
|
||||
media_remux_job_t mr_job = nullptr;
|
||||
if (media_remux_job_create(&mr_job,
|
||||
QT_TO_UTF8(source),
|
||||
if (media_remux_job_create(&mr_job, QT_TO_UTF8(source),
|
||||
QT_TO_UTF8(target))) {
|
||||
|
||||
success = media_remux_job_process(mr_job, callback,
|
||||
this);
|
||||
success = media_remux_job_process(mr_job, callback, this);
|
||||
|
||||
media_remux_job_destroy(mr_job);
|
||||
|
||||
|
|
|
@ -31,8 +31,7 @@
|
|||
class RemuxQueueModel;
|
||||
class RemuxWorker;
|
||||
|
||||
enum RemuxEntryState
|
||||
{
|
||||
enum RemuxEntryState {
|
||||
Empty,
|
||||
Ready,
|
||||
Pending,
|
||||
|
@ -97,8 +96,9 @@ class RemuxQueueModel : public QAbstractTableModel {
|
|||
|
||||
public:
|
||||
RemuxQueueModel(QObject *parent = 0)
|
||||
: QAbstractTableModel(parent)
|
||||
, isProcessing(false) {}
|
||||
: QAbstractTableModel(parent), isProcessing(false)
|
||||
{
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||
|
@ -106,8 +106,7 @@ public:
|
|||
QVariant headerData(int section, Qt::Orientation orientation,
|
||||
int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value,
|
||||
int role);
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
|
||||
QFileInfoList checkForOverwrites() const;
|
||||
bool checkForErrors() const;
|
||||
|
@ -122,8 +121,7 @@ public:
|
|||
bool autoRemux = false;
|
||||
|
||||
private:
|
||||
struct RemuxQueueEntry
|
||||
{
|
||||
struct RemuxQueueEntry {
|
||||
RemuxEntryState state;
|
||||
|
||||
QString sourcePath;
|
||||
|
@ -148,8 +146,7 @@ class RemuxWorker : public QObject {
|
|||
float lastProgress;
|
||||
void UpdateProgress(float percent);
|
||||
|
||||
explicit RemuxWorker()
|
||||
: isWorking(false) { }
|
||||
explicit RemuxWorker() : isWorking(false) {}
|
||||
virtual ~RemuxWorker(){};
|
||||
|
||||
private slots:
|
||||
|
@ -172,10 +169,9 @@ public:
|
|||
const QStyleOptionViewItem & /* option */,
|
||||
const QModelIndex &index) const override;
|
||||
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index)
|
||||
const override;
|
||||
virtual void setModelData(QWidget *editor,
|
||||
QAbstractItemModel *model,
|
||||
virtual void setEditorData(QWidget *editor,
|
||||
const QModelIndex &index) const override;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model,
|
||||
const QModelIndex &index) const override;
|
||||
virtual void paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
|
|
3
deps/blake2/.clang-format
vendored
Normal file
3
deps/blake2/.clang-format
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
Language: Cpp
|
||||
SortIncludes: false
|
||||
DisableFormat: true
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue