mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-08 12:24:09 +00:00
UI: Use main video on the virtual camera if program
This change allows the virtual camera to really output what is in the program view, some plugin interract with this view but their changes does not appear on the virtual camera.
This commit is contained in:
parent
2be0550e9a
commit
7cd7ca80f8
|
@ -740,9 +740,9 @@ Basic.Main.VirtualCamConfig="Configure Virtual Camera"
|
|||
Basic.VCam.VirtualCamera="Virtual Camera"
|
||||
Basic.VCam.OutputType="Output Type"
|
||||
Basic.VCam.OutputSelection="Output Selection"
|
||||
Basic.VCam.Internal="Internal"
|
||||
Basic.VCam.InternalDefault="Program Output (Default)"
|
||||
Basic.VCam.InternalPreview="Preview Output"
|
||||
Basic.VCam.OutputType.Program="Program (Default)"
|
||||
Basic.VCam.OutputSelection.NoSelection="No selection for this output type"
|
||||
Basic.VCam.RestartWarning="The virtual camera will be restarted to apply this change"
|
||||
|
||||
# basic mode file menu
|
||||
Basic.MainMenu.File="&File"
|
||||
|
|
|
@ -22,23 +22,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="outputType">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Basic.VCam.Internal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Basic.Scene</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Basic.Main.Source</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QComboBox" name="outputType"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="outputSelectionLabel">
|
||||
|
@ -50,6 +34,16 @@
|
|||
<item>
|
||||
<widget class="QComboBox" name="outputSelection"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="warningLabel">
|
||||
<property name="text">
|
||||
<string>Basic.VCam.RestartWarning</string>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -301,13 +301,17 @@ bool BasicOutputHandler::StartVirtualCam()
|
|||
if (!main->vcamEnabled)
|
||||
return false;
|
||||
|
||||
if (!virtualCamView)
|
||||
bool typeIsProgram = main->vcamConfig.type ==
|
||||
VCamOutputType::ProgramView;
|
||||
|
||||
if (!virtualCamView && !typeIsProgram)
|
||||
virtualCamView = obs_view_create();
|
||||
|
||||
UpdateVirtualCamOutputSource();
|
||||
|
||||
if (!virtualCamVideo) {
|
||||
virtualCamVideo = obs_view_add(virtualCamView);
|
||||
virtualCamVideo = typeIsProgram ? obs_get_video()
|
||||
: obs_view_add(virtualCamView);
|
||||
|
||||
if (!virtualCamVideo)
|
||||
return false;
|
||||
|
@ -361,19 +365,17 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource()
|
|||
OBSSourceAutoRelease source;
|
||||
|
||||
switch (main->vcamConfig.type) {
|
||||
case VCamOutputType::InternalOutput:
|
||||
case VCamOutputType::Invalid:
|
||||
case VCamOutputType::ProgramView:
|
||||
DestroyVirtualCameraScene();
|
||||
switch (main->vcamConfig.internal) {
|
||||
case VCamInternalType::Default:
|
||||
source = obs_get_output_source(0);
|
||||
break;
|
||||
case VCamInternalType::Preview:
|
||||
OBSSource s = main->GetCurrentSceneSource();
|
||||
obs_source_get_ref(s);
|
||||
source = s.Get();
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case VCamOutputType::PreviewOutput: {
|
||||
DestroyVirtualCameraScene();
|
||||
OBSSource s = main->GetCurrentSceneSource();
|
||||
obs_source_get_ref(s);
|
||||
source = s.Get();
|
||||
break;
|
||||
}
|
||||
case VCamOutputType::SceneOutput:
|
||||
DestroyVirtualCameraScene();
|
||||
source = obs_get_source_by_name(main->vcamConfig.scene.c_str());
|
||||
|
@ -418,6 +420,11 @@ void BasicOutputHandler::UpdateVirtualCamOutputSource()
|
|||
|
||||
void BasicOutputHandler::DestroyVirtualCamView()
|
||||
{
|
||||
if (main->vcamConfig.type == VCamOutputType::ProgramView) {
|
||||
virtualCamVideo = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
obs_view_remove(virtualCamView);
|
||||
obs_view_set_source(virtualCamView, 0, nullptr);
|
||||
virtualCamVideo = nullptr;
|
||||
|
|
|
@ -283,10 +283,6 @@ void OBSBasic::OverrideTransition(OBSSource transition)
|
|||
obs_transition_swap_begin(transition, oldTransition);
|
||||
obs_set_output_source(0, transition);
|
||||
obs_transition_swap_end(transition, oldTransition);
|
||||
|
||||
// Transition overrides don't raise an event so we need to call update directly
|
||||
if (vcamEnabled)
|
||||
outputHandler->UpdateVirtualCamOutputSource();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,10 +422,6 @@ void OBSBasic::SetTransition(OBSSource transition)
|
|||
ui->transitionRemove->setEnabled(configurable);
|
||||
ui->transitionProps->setEnabled(configurable);
|
||||
|
||||
if (vcamEnabled && vcamConfig.type == VCamOutputType::InternalOutput &&
|
||||
vcamConfig.internal == VCamInternalType::Default)
|
||||
outputHandler->UpdateVirtualCamOutputSource();
|
||||
|
||||
if (api)
|
||||
api->on_event(OBS_FRONTEND_EVENT_TRANSITION_CHANGED);
|
||||
}
|
||||
|
@ -697,8 +689,8 @@ void OBSBasic::SetCurrentScene(OBSSource scene, bool force)
|
|||
ui->scenes->blockSignals(false);
|
||||
|
||||
if (vcamEnabled &&
|
||||
vcamConfig.internal ==
|
||||
VCamInternalType::Preview)
|
||||
vcamConfig.type ==
|
||||
VCamOutputType::PreviewOutput)
|
||||
outputHandler
|
||||
->UpdateVirtualCamOutputSource();
|
||||
|
||||
|
|
|
@ -795,11 +795,11 @@ void OBSBasic::Save(const char *file)
|
|||
if (vcamEnabled) {
|
||||
OBSDataAutoRelease obj = obs_data_create();
|
||||
|
||||
obs_data_set_int(obj, "type", (int)vcamConfig.type);
|
||||
obs_data_set_int(obj, "type2", (int)vcamConfig.type);
|
||||
switch (vcamConfig.type) {
|
||||
case VCamOutputType::InternalOutput:
|
||||
obs_data_set_int(obj, "internal",
|
||||
(int)vcamConfig.internal);
|
||||
case VCamOutputType::Invalid:
|
||||
case VCamOutputType::ProgramView:
|
||||
case VCamOutputType::PreviewOutput:
|
||||
break;
|
||||
case VCamOutputType::SceneOutput:
|
||||
obs_data_set_string(obj, "scene",
|
||||
|
@ -1239,9 +1239,26 @@ retryScene:
|
|||
OBSDataAutoRelease obj =
|
||||
obs_data_get_obj(data, "virtual-camera");
|
||||
|
||||
vcamConfig.type = (VCamOutputType)obs_data_get_int(obj, "type");
|
||||
vcamConfig.internal =
|
||||
(VCamInternalType)obs_data_get_int(obj, "internal");
|
||||
vcamConfig.type =
|
||||
(VCamOutputType)obs_data_get_int(obj, "type2");
|
||||
if (vcamConfig.type == VCamOutputType::Invalid)
|
||||
vcamConfig.type =
|
||||
(VCamOutputType)obs_data_get_int(obj, "type");
|
||||
|
||||
if (vcamConfig.type == VCamOutputType::Invalid) {
|
||||
VCamInternalType internal =
|
||||
(VCamInternalType)obs_data_get_int(obj,
|
||||
"internal");
|
||||
|
||||
switch (internal) {
|
||||
case VCamInternalType::Default:
|
||||
vcamConfig.type = VCamOutputType::ProgramView;
|
||||
break;
|
||||
case VCamInternalType::Preview:
|
||||
vcamConfig.type = VCamOutputType::PreviewOutput;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vcamConfig.scene = obs_data_get_string(obj, "scene");
|
||||
vcamConfig.source = obs_data_get_string(obj, "source");
|
||||
}
|
||||
|
@ -4873,8 +4890,7 @@ void OBSBasic::ClearSceneData()
|
|||
/* Reset VCam to default to clear its private scene and any references
|
||||
* it holds. It will be reconfigured during loading. */
|
||||
if (vcamEnabled) {
|
||||
vcamConfig.type = VCamOutputType::InternalOutput;
|
||||
vcamConfig.internal = VCamInternalType::Default;
|
||||
vcamConfig.type = VCamOutputType::ProgramView;
|
||||
outputHandler->UpdateVirtualCamOutputSource();
|
||||
}
|
||||
|
||||
|
@ -5300,8 +5316,7 @@ void OBSBasic::on_scenes_currentItemChanged(QListWidgetItem *current,
|
|||
|
||||
SetCurrentScene(source);
|
||||
|
||||
if (vcamEnabled && vcamConfig.type == VCamOutputType::InternalOutput &&
|
||||
vcamConfig.internal == VCamInternalType::Preview)
|
||||
if (vcamEnabled && vcamConfig.type == VCamOutputType::PreviewOutput)
|
||||
outputHandler->UpdateVirtualCamOutputSource();
|
||||
|
||||
if (api)
|
||||
|
@ -7935,6 +7950,13 @@ void OBSBasic::OnVirtualCamStop(int)
|
|||
blog(LOG_INFO, VIRTUAL_CAM_STOP);
|
||||
|
||||
OnDeactivate();
|
||||
|
||||
if (!restartingVCam)
|
||||
return;
|
||||
|
||||
/* Restarting needs to be delayed to make sure that the virtual camera
|
||||
* implementation is stopped and avoid race condition. */
|
||||
QTimer::singleShot(100, this, &OBSBasic::RestartingVirtualCam);
|
||||
}
|
||||
|
||||
void OBSBasic::on_streamButton_clicked()
|
||||
|
@ -8089,10 +8111,13 @@ void OBSBasic::VCamButtonClicked()
|
|||
|
||||
void OBSBasic::VCamConfigButtonClicked()
|
||||
{
|
||||
OBSBasicVCamConfig dialog(vcamConfig, this);
|
||||
OBSBasicVCamConfig dialog(vcamConfig, outputHandler->VirtualCamActive(),
|
||||
this);
|
||||
|
||||
connect(&dialog, &OBSBasicVCamConfig::Accepted, this,
|
||||
&OBSBasic::UpdateVirtualCamConfig);
|
||||
connect(&dialog, &OBSBasicVCamConfig::AcceptedAndRestart, this,
|
||||
&OBSBasic::RestartVirtualCam);
|
||||
|
||||
dialog.exec();
|
||||
}
|
||||
|
@ -8104,6 +8129,25 @@ void OBSBasic::UpdateVirtualCamConfig(const VCamConfig &config)
|
|||
outputHandler->UpdateVirtualCamOutputSource();
|
||||
}
|
||||
|
||||
void OBSBasic::RestartVirtualCam(const VCamConfig &config)
|
||||
{
|
||||
restartingVCam = true;
|
||||
|
||||
StopVirtualCam();
|
||||
|
||||
vcamConfig = config;
|
||||
}
|
||||
|
||||
void OBSBasic::RestartingVirtualCam()
|
||||
{
|
||||
if (!restartingVCam)
|
||||
return;
|
||||
|
||||
outputHandler->UpdateVirtualCamOutputSource();
|
||||
StartVirtualCam();
|
||||
restartingVCam = false;
|
||||
}
|
||||
|
||||
void OBSBasic::on_settingsButton_clicked()
|
||||
{
|
||||
on_action_Settings_triggered();
|
||||
|
|
|
@ -656,6 +656,8 @@ private:
|
|||
|
||||
void UpdatePreviewOverflowSettings();
|
||||
|
||||
bool restartingVCam = false;
|
||||
|
||||
public slots:
|
||||
void DeferSaveBegin();
|
||||
void DeferSaveEnd();
|
||||
|
@ -830,6 +832,8 @@ private slots:
|
|||
void ResetProxyStyleSliders();
|
||||
|
||||
void UpdateVirtualCamConfig(const VCamConfig &config);
|
||||
void RestartVirtualCam(const VCamConfig &config);
|
||||
void RestartingVirtualCam();
|
||||
|
||||
private:
|
||||
/* OBS Callbacks */
|
||||
|
|
|
@ -5,35 +5,55 @@
|
|||
#include <util/util.hpp>
|
||||
#include <util/platform.h>
|
||||
|
||||
#include <QStandardItem>
|
||||
|
||||
OBSBasicVCamConfig::OBSBasicVCamConfig(const VCamConfig &_config,
|
||||
QWidget *parent)
|
||||
: config(_config), QDialog(parent), ui(new Ui::OBSBasicVCamConfig)
|
||||
bool _vcamActive, QWidget *parent)
|
||||
: config(_config),
|
||||
vcamActive(_vcamActive),
|
||||
activeType(_config.type),
|
||||
QDialog(parent),
|
||||
ui(new Ui::OBSBasicVCamConfig)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->outputType->setCurrentIndex(config.type);
|
||||
OutputTypeChanged(config.type);
|
||||
ui->outputType->addItem(QTStr("Basic.VCam.OutputType.Program"),
|
||||
(int)VCamOutputType::ProgramView);
|
||||
ui->outputType->addItem(QTStr("Preview"),
|
||||
(int)VCamOutputType::PreviewOutput);
|
||||
ui->outputType->addItem(QTStr("Basic.Scene"),
|
||||
(int)VCamOutputType::SceneOutput);
|
||||
ui->outputType->addItem(QTStr("Basic.Main.Source"),
|
||||
(int)VCamOutputType::SourceOutput);
|
||||
|
||||
ui->outputType->setCurrentIndex(
|
||||
ui->outputType->findData((int)config.type));
|
||||
OutputTypeChanged();
|
||||
connect(ui->outputType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(OutputTypeChanged(int)));
|
||||
SLOT(OutputTypeChanged()));
|
||||
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
|
||||
&OBSBasicVCamConfig::UpdateConfig);
|
||||
}
|
||||
|
||||
void OBSBasicVCamConfig::OutputTypeChanged(int type)
|
||||
void OBSBasicVCamConfig::OutputTypeChanged()
|
||||
{
|
||||
VCamOutputType type =
|
||||
(VCamOutputType)ui->outputType->currentData().toInt();
|
||||
ui->outputSelection->setDisabled(false);
|
||||
|
||||
auto list = ui->outputSelection;
|
||||
list->clear();
|
||||
|
||||
switch ((VCamOutputType)type) {
|
||||
case VCamOutputType::InternalOutput:
|
||||
list->addItem(QTStr("Basic.VCam.InternalDefault"));
|
||||
list->addItem(QTStr("Basic.VCam.InternalPreview"));
|
||||
list->setCurrentIndex(config.internal);
|
||||
switch (type) {
|
||||
case VCamOutputType::Invalid:
|
||||
case VCamOutputType::ProgramView:
|
||||
case VCamOutputType::PreviewOutput:
|
||||
ui->outputSelection->setDisabled(true);
|
||||
list->addItem(QTStr("Basic.VCam.OutputSelection.NoSelection"));
|
||||
break;
|
||||
|
||||
case VCamOutputType::SceneOutput: {
|
||||
// Scenes in default order
|
||||
BPtr<char *> scenes = obs_frontend_get_scene_names();
|
||||
|
@ -45,7 +65,6 @@ void OBSBasicVCamConfig::OutputTypeChanged(int type)
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VCamOutputType::SourceOutput: {
|
||||
// Sources in alphabetical order
|
||||
std::vector<std::string> sources;
|
||||
|
@ -81,15 +100,25 @@ void OBSBasicVCamConfig::OutputTypeChanged(int type)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!vcamActive)
|
||||
return;
|
||||
|
||||
requireRestart = (activeType == VCamOutputType::ProgramView &&
|
||||
type != VCamOutputType::ProgramView) ||
|
||||
(activeType != VCamOutputType::ProgramView &&
|
||||
type == VCamOutputType::ProgramView);
|
||||
|
||||
ui->warningLabel->setVisible(requireRestart);
|
||||
}
|
||||
|
||||
void OBSBasicVCamConfig::UpdateConfig()
|
||||
{
|
||||
VCamOutputType type = (VCamOutputType)ui->outputType->currentIndex();
|
||||
VCamOutputType type =
|
||||
(VCamOutputType)ui->outputType->currentData().toInt();
|
||||
switch (type) {
|
||||
case VCamOutputType::InternalOutput:
|
||||
config.internal =
|
||||
(VCamInternalType)ui->outputSelection->currentIndex();
|
||||
case VCamOutputType::ProgramView:
|
||||
case VCamOutputType::PreviewOutput:
|
||||
break;
|
||||
case VCamOutputType::SceneOutput:
|
||||
config.scene = ui->outputSelection->currentText().toStdString();
|
||||
|
@ -105,5 +134,9 @@ void OBSBasicVCamConfig::UpdateConfig()
|
|||
|
||||
config.type = type;
|
||||
|
||||
emit Accepted(config);
|
||||
if (requireRestart) {
|
||||
emit AcceptedAndRestart(config);
|
||||
} else {
|
||||
emit Accepted(config);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,12 +15,16 @@ class OBSBasicVCamConfig : public QDialog {
|
|||
|
||||
VCamConfig config;
|
||||
|
||||
bool vcamActive;
|
||||
VCamOutputType activeType;
|
||||
bool requireRestart;
|
||||
|
||||
public:
|
||||
explicit OBSBasicVCamConfig(const VCamConfig &config,
|
||||
explicit OBSBasicVCamConfig(const VCamConfig &config, bool VCamActive,
|
||||
QWidget *parent = 0);
|
||||
|
||||
private slots:
|
||||
void OutputTypeChanged(int type);
|
||||
void OutputTypeChanged();
|
||||
void UpdateConfig();
|
||||
|
||||
private:
|
||||
|
@ -28,4 +32,5 @@ private:
|
|||
|
||||
signals:
|
||||
void Accepted(const VCamConfig &config);
|
||||
void AcceptedAndRestart(const VCamConfig &config);
|
||||
};
|
||||
|
|
|
@ -3,19 +3,21 @@
|
|||
#include <string>
|
||||
|
||||
enum VCamOutputType {
|
||||
InternalOutput,
|
||||
Invalid,
|
||||
SceneOutput,
|
||||
SourceOutput,
|
||||
ProgramView,
|
||||
PreviewOutput,
|
||||
};
|
||||
|
||||
// Kept for config upgrade
|
||||
enum VCamInternalType {
|
||||
Default,
|
||||
Preview,
|
||||
};
|
||||
|
||||
struct VCamConfig {
|
||||
VCamOutputType type = VCamOutputType::InternalOutput;
|
||||
VCamInternalType internal = VCamInternalType::Default;
|
||||
VCamOutputType type = VCamOutputType::ProgramView;
|
||||
std::string scene;
|
||||
std::string source;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue