Add Aitum Vertical support

This commit is contained in:
Exeldro 2024-07-11 13:54:58 +02:00
parent f1a31a90bf
commit ff0f22a1d0
No known key found for this signature in database
GPG Key ID: 97269A83FC715751
4 changed files with 207 additions and 31 deletions

View File

@ -61,10 +61,9 @@ OBSBasicSettings::OBSBasicSettings(QMainWindow *parent) : QDialog(parent)
listwidgetitem->setIcon(QIcon(QString::fromUtf8(":/settings/images/settings/stream.svg"))); listwidgetitem->setIcon(QIcon(QString::fromUtf8(":/settings/images/settings/stream.svg")));
listwidgetitem->setText(QString::fromUtf8(obs_module_text("MainCanvas"))); listwidgetitem->setText(QString::fromUtf8(obs_module_text("MainCanvas")));
//listwidgetitem = new QListWidgetItem(listWidget); listwidgetitem = new QListWidgetItem(listWidget);
//listwidgetitem->setIcon(QIcon(QString::fromUtf8(":/settings/images/settings/stream.svg"))); listwidgetitem->setIcon(QIcon(QString::fromUtf8(":/settings/images/settings/stream.svg")));
//listwidgetitem->setIcon(main_window->property("defaultIcon").value<QIcon>()); listwidgetitem->setText(QString::fromUtf8(obs_module_text("VerticalCanvas")));
//listwidgetitem->setText(QString::fromUtf8(obs_module_text("Vertical outputs")));
listwidgetitem = new QListWidgetItem(listWidget); listwidgetitem = new QListWidgetItem(listWidget);
listwidgetitem->setIcon(main_window->property("defaultIcon").value<QIcon>()); listwidgetitem->setIcon(main_window->property("defaultIcon").value<QIcon>());
@ -102,14 +101,17 @@ OBSBasicSettings::OBSBasicSettings(QMainWindow *parent) : QDialog(parent)
scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setFrameShape(QFrame::NoFrame);
settingsPages->addWidget(scrollArea); settingsPages->addWidget(scrollArea);
/* auto verticalOutputsPage = new QGroupBox;
auto verticalOutputsPage = new QWidget; verticalOutputsPage->setProperty("customTitle", QVariant(true));
verticalOutputsPage->setStyleSheet(QString("QGroupBox[customTitle=\"true\"]{ padding-top: 4px;}"));
verticalOutputsPage->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
scrollArea = new QScrollArea; scrollArea = new QScrollArea;
scrollArea->setWidget(verticalOutputsPage); scrollArea->setWidget(verticalOutputsPage);
scrollArea->setWidgetResizable(true); scrollArea->setWidgetResizable(true);
scrollArea->setLineWidth(0); scrollArea->setLineWidth(0);
scrollArea->setFrameShape(QFrame::NoFrame); scrollArea->setFrameShape(QFrame::NoFrame);
settingsPages->addWidget(scrollArea);*/ settingsPages->addWidget(scrollArea);
troubleshooterText = new QTextEdit; troubleshooterText = new QTextEdit;
troubleshooterText->setReadOnly(true); troubleshooterText->setReadOnly(true);
@ -185,6 +187,35 @@ OBSBasicSettings::OBSBasicSettings(QMainWindow *parent) : QDialog(parent)
mainOutputsPage->setLayout(mainOutputsLayout); mainOutputsPage->setLayout(mainOutputsLayout);
verticalOutputsLayout = new QFormLayout;
verticalOutputsLayout->setContentsMargins(9, 2, 9, 9);
verticalOutputsLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
verticalOutputsLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
streaming_title_layout = new QHBoxLayout;
streaming_title = new QLabel(QString::fromUtf8(obs_module_text("VerticalCanvas")));
streaming_title->setStyleSheet(QString::fromUtf8("font-weight: bold;"));
streaming_title_layout->addWidget(streaming_title, 0, Qt::AlignLeft);
//auto guide_link = new QLabel(QString::fromUtf8("<a href=\"https://l.aitum.tv/vh-streaming-settings\">") + QString::fromUtf8(obs_module_text("ViewGuide")) + QString::fromUtf8("</a>"));
//guide_link->setOpenExternalLinks(true);
addButton = new QPushButton(QIcon(":/res/images/plus.svg"), QString::fromUtf8(obs_module_text("AddOutput")));
addButton->setProperty("themeID", QVariant(QString::fromUtf8("addIconSmall")));
connect(addButton, &QPushButton::clicked, [this] {
if (!vertical_outputs)
return;
auto s = obs_data_create();
obs_data_set_string(s, "name", obs_module_text("Unnamed"));
obs_data_array_push_back(vertical_outputs, s);
AddServer(verticalOutputsLayout, s);
obs_data_release(s);
});
streaming_title_layout->addWidget(addButton, 0, Qt::AlignRight);
verticalOutputsLayout->addRow(streaming_title_layout);
verticalOutputsPage->setLayout(verticalOutputsLayout);
const auto version = const auto version =
new QLabel(QString::fromUtf8(obs_module_text("Version")) + " " + QString::fromUtf8(PROJECT_VERSION) + " " + new QLabel(QString::fromUtf8(obs_module_text("Version")) + " " + QString::fromUtf8(PROJECT_VERSION) + " " +
QString::fromUtf8(obs_module_text("MadeBy")) + " <a href=\"https://aitum.tv\">Aitum</a>"); QString::fromUtf8(obs_module_text("MadeBy")) + " <a href=\"https://aitum.tv\">Aitum</a>");
@ -226,6 +257,8 @@ OBSBasicSettings::OBSBasicSettings(QMainWindow *parent) : QDialog(parent)
OBSBasicSettings::~OBSBasicSettings() OBSBasicSettings::~OBSBasicSettings()
{ {
if (vertical_outputs)
obs_data_array_release(vertical_outputs);
for (auto it = encoder_properties.begin(); it != encoder_properties.end(); it++) for (auto it = encoder_properties.begin(); it != encoder_properties.end(); it++)
obs_properties_destroy(it->second); obs_properties_destroy(it->second);
} }
@ -278,7 +311,7 @@ void OBSBasicSettings::SetGeneralIcon(const QIcon &icon)
void OBSBasicSettings::SetStreamIcon(const QIcon &icon) void OBSBasicSettings::SetStreamIcon(const QIcon &icon)
{ {
listWidget->item(1)->setIcon(icon); listWidget->item(1)->setIcon(icon);
//listWidget->item(2)->setIcon(icon); listWidget->item(2)->setIcon(icon);
} }
void OBSBasicSettings::SetOutputIcon(const QIcon &icon) void OBSBasicSettings::SetOutputIcon(const QIcon &icon)
@ -579,17 +612,17 @@ void OBSBasicSettings::AddServer(QFormLayout *outputsLayout, obs_data_t *setting
server->addItem("rtmps://b.rtmps.youtube.com:443/live2?backup=1"); server->addItem("rtmps://b.rtmps.youtube.com:443/live2?backup=1");
server->addItem("rtmp://a.rtmp.youtube.com/live2"); server->addItem("rtmp://a.rtmp.youtube.com/live2");
server->addItem("rtmp://b.rtmp.youtube.com/live2?backup=1"); server->addItem("rtmp://b.rtmp.youtube.com/live2?backup=1");
server->setCurrentText(QString::fromUtf8(obs_data_get_string(settings, "server"))); server->setCurrentText(QString::fromUtf8(obs_data_get_string(settings, "stream_server")));
connect(server, &QComboBox::currentTextChanged, connect(server, &QComboBox::currentTextChanged,
[server, settings] { obs_data_set_string(settings, "server", server->currentText().toUtf8().constData()); }); [server, settings] { obs_data_set_string(settings, "stream_server", server->currentText().toUtf8().constData()); });
serverLayout->addRow(QString::fromUtf8(obs_module_text("Server")), server); serverLayout->addRow(QString::fromUtf8(obs_module_text("Server")), server);
QLayout *subLayout = new QHBoxLayout(); QLayout *subLayout = new QHBoxLayout();
auto key = new QLineEdit; auto key = new QLineEdit;
key->setEchoMode(QLineEdit::Password); key->setEchoMode(QLineEdit::Password);
key->setText(QString::fromUtf8(obs_data_get_string(settings, "key"))); key->setText(QString::fromUtf8(obs_data_get_string(settings, "stream_key")));
connect(key, &QLineEdit::textChanged, connect(key, &QLineEdit::textChanged,
[key, settings] { obs_data_set_string(settings, "key", key->text().toUtf8().constData()); }); [key, settings] { obs_data_set_string(settings, "stream_key", key->text().toUtf8().constData()); });
QPushButton *show = new QPushButton(); QPushButton *show = new QPushButton();
show->setText(QString::fromUtf8(obs_frontend_get_locale_string("Show"))); show->setText(QString::fromUtf8(obs_frontend_get_locale_string("Show")));
@ -610,6 +643,46 @@ void OBSBasicSettings::AddServer(QFormLayout *outputsLayout, obs_data_t *setting
outputsLayout->addRow(serverGroup); outputsLayout->addRow(serverGroup);
} }
void OBSBasicSettings::LoadVerticalSettings()
{
while (verticalOutputsLayout->rowCount() > 1) {
auto i = verticalOutputsLayout->takeRow(1).fieldItem;
RemoveLayoutItem(i);
verticalOutputsLayout->removeRow(1);
}
auto ph = obs_get_proc_handler();
struct calldata cd;
calldata_init(&cd);
if (!proc_handler_call(ph, "aitum_vertical_get_stream_settings", &cd)) {
calldata_free(&cd);
return;
}
if (vertical_outputs)
obs_data_array_release(vertical_outputs);
vertical_outputs = (obs_data_array_t *)calldata_ptr(&cd, "outputs");
obs_data_array_enum(
vertical_outputs,
[](obs_data_t *data, void *param) {
auto d = (OBSBasicSettings *)param;
d->AddServer(d->verticalOutputsLayout, data);
},
this);
calldata_free(&cd);
}
void OBSBasicSettings::SaveVerticalSettings()
{
if (!vertical_outputs)
return;
auto ph = obs_get_proc_handler();
struct calldata cd;
calldata_init(&cd);
calldata_set_ptr(&cd, "outputs", vertical_outputs);
proc_handler_call(ph, "aitum_vertical_set_stream_settings", &cd);
calldata_free(&cd);
}
void OBSBasicSettings::LoadSettings(obs_data_t *settings) void OBSBasicSettings::LoadSettings(obs_data_t *settings)
{ {
while (mainOutputsLayout->rowCount() > 2) { while (mainOutputsLayout->rowCount() > 2) {

View File

@ -39,7 +39,8 @@ private:
void AddProperty(obs_properties_t *properties, obs_property_t *property, obs_data_t *settings, QFormLayout *layout); void AddProperty(obs_properties_t *properties, obs_property_t *property, obs_data_t *settings, QFormLayout *layout);
void RefreshProperties(obs_properties_t *properties, QFormLayout *layout); void RefreshProperties(obs_properties_t *properties, QFormLayout *layout);
obs_data_t *settings; obs_data_t *settings = nullptr;
obs_data_array_t *vertical_outputs = nullptr;
std::map<obs_property_t *, QWidget *> encoder_property_widgets; std::map<obs_property_t *, QWidget *> encoder_property_widgets;
std::map<QWidget *, obs_properties_t *> encoder_properties; std::map<QWidget *, obs_properties_t *> encoder_properties;
@ -65,6 +66,8 @@ public:
~OBSBasicSettings(); ~OBSBasicSettings();
void LoadSettings(obs_data_t *settings); void LoadSettings(obs_data_t *settings);
void LoadVerticalSettings();
void SaveVerticalSettings();
void LoadOutputStats(); void LoadOutputStats();
void SetNewerVersion(QString newer_version_available); void SetNewerVersion(QString newer_version_available);
public slots: public slots:

View File

@ -65,6 +65,11 @@ bool obs_module_load(void)
return true; return true;
} }
void obs_module_post_load()
{
multistream_dock->LoadVerticalOutputs();
}
void obs_module_unload() void obs_module_unload()
{ {
update_info_destroy(version_update_info); update_info_destroy(version_update_info);
@ -153,9 +158,13 @@ MultistreamDock::MultistreamDock(QWidget *parent) : QFrame(parent)
mainCanvasGroup->setLayout(mainCanvasLayout); mainCanvasGroup->setLayout(mainCanvasLayout);
tl->addWidget(mainCanvasGroup); tl->addWidget(mainCanvasGroup);
tl->addStretch(1);
//auto verticalCanvasGroup = new QGroupBox(QString::fromUtf8(obs_module_text("VerticalCanvas"))); auto verticalCanvasGroup = new QGroupBox(QString::fromUtf8(obs_module_text("VerticalCanvas")));
verticalCanvasLayout = new QVBoxLayout;
verticalCanvasGroup->setLayout(verticalCanvasLayout);
tl->addWidget(verticalCanvasGroup);
tl->addStretch(1);
//tl->addWidget(verticalCanvasGroup); //tl->addWidget(verticalCanvasGroup);
QScrollArea *scrollArea = new QScrollArea; QScrollArea *scrollArea = new QScrollArea;
@ -183,6 +192,7 @@ MultistreamDock::MultistreamDock(QWidget *parent) : QFrame(parent)
if (current_config) if (current_config)
obs_data_apply(settings, current_config); obs_data_apply(settings, current_config);
configDialog->LoadSettings(settings); configDialog->LoadSettings(settings);
configDialog->LoadVerticalSettings();
configDialog->LoadOutputStats(); configDialog->LoadOutputStats();
configDialog->SetNewerVersion(newer_version_available); configDialog->SetNewerVersion(newer_version_available);
configDialog->setResult(QDialog::Rejected); configDialog->setResult(QDialog::Rejected);
@ -192,6 +202,8 @@ MultistreamDock::MultistreamDock(QWidget *parent) : QFrame(parent)
obs_data_release(settings); obs_data_release(settings);
SaveSettings(); SaveSettings();
LoadSettings(); LoadSettings();
configDialog->SaveVerticalSettings();
LoadVerticalOutputs();
} else { } else {
current_config = settings; current_config = settings;
} }
@ -316,13 +328,13 @@ void MultistreamDock::LoadSettings()
outputs, outputs,
[](obs_data_t *data, void *param) { [](obs_data_t *data, void *param) {
auto d = (MultistreamDock *)param; auto d = (MultistreamDock *)param;
d->LoadOutput(data); d->LoadOutput(data, false);
}, },
this); this);
obs_data_array_release(outputs); obs_data_array_release(outputs);
} }
void MultistreamDock::LoadOutput(obs_data_t *data) void MultistreamDock::LoadOutput(obs_data_t *data, bool vertical)
{ {
auto name = QString::fromUtf8(obs_data_get_string(data, "name")); auto name = QString::fromUtf8(obs_data_get_string(data, "name"));
for (int i = 1; i < mainCanvasLayout->count(); i++) { for (int i = 1; i < mainCanvasLayout->count(); i++) {
@ -346,15 +358,42 @@ void MultistreamDock::LoadOutput(obs_data_t *data)
streamButton->setIcon(streamInactiveIcon); streamButton->setIcon(streamInactiveIcon);
streamButton->setCheckable(true); streamButton->setCheckable(true);
streamButton->setChecked(false); streamButton->setChecked(false);
connect(streamButton, &QPushButton::clicked, [this, streamButton, data] { if (vertical) {
if (streamButton->isChecked()) { connect(streamButton, &QPushButton::clicked, [this, streamButton, data] {
if (!StartOutput(data, streamButton)) auto ph = obs_get_proc_handler();
streamButton->setChecked(false); struct calldata cd;
} else { calldata_init(&cd);
} calldata_set_string(&cd, "name", obs_data_get_string(data, "name"));
streamButton->setStyleSheet(QString::fromUtf8(streamButton->isChecked() ? "background: rgb(0,210,153);" : "")); if (streamButton->isChecked()) {
streamButton->setIcon(streamButton->isChecked() ? streamActiveIcon : streamInactiveIcon); if (!proc_handler_call(ph, "aitum_vertical_start_stream_output", &cd))
}); streamButton->setChecked(false);
} else {
proc_handler_call(ph, "aitum_vertical_stop_stream_output", &cd);
}
calldata_free(&cd);
streamButton->setStyleSheet(
QString::fromUtf8(streamButton->isChecked() ? "background: rgb(0,210,153);" : ""));
streamButton->setIcon(streamButton->isChecked() ? streamActiveIcon : streamInactiveIcon);
});
} else {
connect(streamButton, &QPushButton::clicked, [this, streamButton, data] {
if (streamButton->isChecked()) {
if (!StartOutput(data, streamButton))
streamButton->setChecked(false);
} else {
const char *name = obs_data_get_string(data, "name");
auto it = outputs.find(name);
if (it != outputs.end()) {
obs_output_stop(it->second);
obs_output_release(it->second);
outputs.erase(it);
}
}
streamButton->setStyleSheet(
QString::fromUtf8(streamButton->isChecked() ? "background: rgb(0,210,153);" : ""));
streamButton->setIcon(streamButton->isChecked() ? streamActiveIcon : streamInactiveIcon);
});
}
//streamButton->setSizePolicy(sp2); //streamButton->setSizePolicy(sp2);
streamButton->setToolTip(QString::fromUtf8(obs_module_text("Stream"))); streamButton->setToolTip(QString::fromUtf8(obs_module_text("Stream")));
l2->addWidget(streamButton); l2->addWidget(streamButton);
@ -362,7 +401,10 @@ void MultistreamDock::LoadOutput(obs_data_t *data)
streamGroup->setLayout(streamLayout); streamGroup->setLayout(streamLayout);
mainCanvasLayout->addWidget(streamGroup); if (vertical)
verticalCanvasLayout->addWidget(streamGroup);
else
mainCanvasLayout->addWidget(streamGroup);
} }
static void ensure_directory(char *path) static void ensure_directory(char *path)
@ -441,6 +483,8 @@ void MultistreamDock::SaveSettings()
bool MultistreamDock::StartOutput(obs_data_t *settings, QPushButton *streamButton) bool MultistreamDock::StartOutput(obs_data_t *settings, QPushButton *streamButton)
{ {
if (!settings)
return false;
const char *name = obs_data_get_string(settings, "name"); const char *name = obs_data_get_string(settings, "name");
auto old = outputs.find(name); auto old = outputs.find(name);
if (old != outputs.end()) { if (old != outputs.end()) {
@ -535,14 +579,25 @@ bool MultistreamDock::StartOutput(obs_data_t *settings, QPushButton *streamButto
if (!aenc || !venc) { if (!aenc || !venc) {
return false; return false;
} }
auto server = obs_data_get_string(settings, "server"); auto server = obs_data_get_string(settings, "stream_server");
if (!server || !strlen(server)) {
server = obs_data_get_string(settings, "server");
if (server && strlen(server))
obs_data_set_string(settings, "stream_server", server);
}
bool whip = strstr(server, "whip") != nullptr; bool whip = strstr(server, "whip") != nullptr;
auto s = obs_data_create(); auto s = obs_data_create();
obs_data_set_string(s, "server", server); obs_data_set_string(s, "server", server);
auto key = obs_data_get_string(settings, "stream_key");
if (!key || !strlen(key)) {
key = obs_data_get_string(settings, "key");
if (key && strlen(key))
obs_data_set_string(settings, "stream_key", key);
}
if (whip) { if (whip) {
obs_data_set_string(s, "bearer_token", obs_data_get_string(settings, "key")); obs_data_set_string(s, "bearer_token", key);
} else { } else {
obs_data_set_string(s, "key", obs_data_get_string(settings, "key")); obs_data_set_string(s, "key", key);
} }
//use_auth //use_auth
//username //username
@ -621,3 +676,46 @@ void MultistreamDock::NewerVersionAvailable(QString version)
newer_version_available = version; newer_version_available = version;
configButton->setStyleSheet(QString::fromUtf8("background: rgb(192,128,0);")); configButton->setStyleSheet(QString::fromUtf8("background: rgb(192,128,0);"));
} }
void MultistreamDock::LoadVerticalOutputs()
{
auto ph = obs_get_proc_handler();
struct calldata cd;
calldata_init(&cd);
if (!proc_handler_call(ph, "aitum_vertical_get_stream_settings", &cd)) {
calldata_free(&cd);
return;
}
auto outputs = (obs_data_array_t *)calldata_ptr(&cd, "outputs");
calldata_free(&cd);
auto count = obs_data_array_count(outputs);
int idx = 1;
while (auto item = verticalCanvasLayout->itemAt(idx)) {
auto streamGroup = item->widget();
auto name = streamGroup->objectName();
bool found = false;
for (size_t i = 0; i < count; i++) {
auto item = obs_data_array_item(outputs, i);
if (QString::fromUtf8(obs_data_get_string(item, "name")) == name) {
found = true;
}
obs_data_release(item);
}
if (!found) {
verticalCanvasLayout->removeWidget(streamGroup);
RemoveWidget(streamGroup);
} else {
idx++;
}
}
obs_data_array_enum(
outputs,
[](obs_data_t *data, void *param) {
auto d = (MultistreamDock *)param;
d->LoadOutput(data, true);
},
this);
obs_data_array_release(outputs);
}

View File

@ -18,6 +18,7 @@ private:
obs_data_t *current_config = nullptr; obs_data_t *current_config = nullptr;
QVBoxLayout *mainCanvasLayout = nullptr; QVBoxLayout *mainCanvasLayout = nullptr;
QVBoxLayout *verticalCanvasLayout = nullptr;
QPushButton *mainStreamButton = nullptr; QPushButton *mainStreamButton = nullptr;
QPushButton *configButton = nullptr; QPushButton *configButton = nullptr;
@ -27,7 +28,7 @@ private:
void LoadSettingsFile(); void LoadSettingsFile();
void LoadSettings(); void LoadSettings();
void LoadOutput(obs_data_t *data); void LoadOutput(obs_data_t *data, bool vertical);
void SaveSettings(); void SaveSettings();
bool StartOutput(obs_data_t *settings, QPushButton *streamButton); bool StartOutput(obs_data_t *settings, QPushButton *streamButton);
@ -46,4 +47,5 @@ private slots:
public: public:
MultistreamDock(QWidget *parent = nullptr); MultistreamDock(QWidget *parent = nullptr);
~MultistreamDock(); ~MultistreamDock();
void LoadVerticalOutputs();
}; };