diff --git a/buildspec.json b/buildspec.json
index 49280c7..16de67b 100644
--- a/buildspec.json
+++ b/buildspec.json
@@ -38,7 +38,7 @@
},
"name": "osi-branch-output",
"displayName": "Branch Output Plugin",
- "version": "0.9.5",
+ "version": "0.9.6",
"author": "OPENSPHERE Inc.",
"website": "https://opensphere.co.jp/",
"email": "info@opensphere.co.jp",
diff --git a/data/locale/ca-ES.ini b/data/locale/ca-ES.ini
index 6a1e536..ee41577 100644
--- a/data/locale/ca-ES.ini
+++ b/data/locale/ca-ES.ini
@@ -27,3 +27,5 @@ Status.Reconnecting="Tornant a connectar"
Status.Inactive="Inactiu"
Status.Active="Actiu"
Reset="Restableix"
+EnableAll="Activa-ho tot"
+DisableAll="Desactiva-ho tot"
diff --git a/data/locale/de-DE.ini b/data/locale/de-DE.ini
index 27b2ede..15e7ccd 100644
--- a/data/locale/de-DE.ini
+++ b/data/locale/de-DE.ini
@@ -26,4 +26,6 @@ Status.Live="Live"
Status.Reconnecting="Wiederverbindung"
Status.Inactive="Inaktiv"
Status.Active="Aktiv"
-Reset="Zurücksetzen"
\ No newline at end of file
+Reset="Zurücksetzen"
+EnableAll="Alle aktivieren"
+DisableAll="Alle deaktivieren"
\ No newline at end of file
diff --git a/data/locale/en-US.ini b/data/locale/en-US.ini
index 0477952..c1e4550 100644
--- a/data/locale/en-US.ini
+++ b/data/locale/en-US.ini
@@ -26,4 +26,6 @@ Status.Live="Live"
Status.Reconnecting="Reconnecting"
Status.Inactive="Inactive"
Status.Active="Active"
-Reset="Reset"
\ No newline at end of file
+Reset="Reset"
+EnableAll="Activate All"
+DisableAll="Deactivate All"
diff --git a/data/locale/fr-FR.ini b/data/locale/fr-FR.ini
index 80d5e52..930488c 100644
--- a/data/locale/fr-FR.ini
+++ b/data/locale/fr-FR.ini
@@ -26,4 +26,6 @@ Status.Live="En direct"
Status.Reconnecting="Reconnexion"
Status.Inactive="Inactif"
Status.Active="Actif"
-Reset="Réinitialiser"
\ No newline at end of file
+Reset="Réinitialiser"
+EnableAll="Activer tout"
+DisableAll="Désactiver tout"
\ No newline at end of file
diff --git a/data/locale/ja-JP.ini b/data/locale/ja-JP.ini
index 045f2a0..3b1f851 100644
--- a/data/locale/ja-JP.ini
+++ b/data/locale/ja-JP.ini
@@ -26,4 +26,6 @@ Status.Live="配信中"
Status.Reconnecting="再接続中"
Status.Inactive="非アクティブ"
Status.Active="アクティブ"
-Reset="リセット"
\ No newline at end of file
+Reset="リセット"
+EnableAll="全て有効化"
+DisableAll="全て無効化"
diff --git a/data/locale/ko-KR.ini b/data/locale/ko-KR.ini
index 90a1e98..04e9228 100644
--- a/data/locale/ko-KR.ini
+++ b/data/locale/ko-KR.ini
@@ -26,4 +26,6 @@ Status.Live="살다"
Status.Reconnecting="다시 연결"
Status.Inactive="비활성"
Status.Active="활동적인"
-Reset="리셋"
\ No newline at end of file
+Reset="리셋"
+EnableAll="모두 활성화"
+DisableAll="모두 무효화"
diff --git a/data/locale/ro-RO.ini b/data/locale/ro-RO.ini
index 52ab61f..8b7e48b 100644
--- a/data/locale/ro-RO.ini
+++ b/data/locale/ro-RO.ini
@@ -26,4 +26,6 @@ Status.Live="Trăi"
Status.Reconnecting="Reconectare"
Status.Inactive="Inactiv"
Status.Active="Activ"
-Reset="Resetați"
\ No newline at end of file
+Reset="Resetați"
+EnableAll="Activați toate"
+DisableAll="Dezactivați toate"
\ No newline at end of file
diff --git a/data/locale/ru-RU.ini b/data/locale/ru-RU.ini
index 5b81ff7..4461079 100644
--- a/data/locale/ru-RU.ini
+++ b/data/locale/ru-RU.ini
@@ -26,4 +26,6 @@ Status.Live="Жить"
Status.Reconnecting="Повторное подключение"
Status.Inactive="Неактивный"
Status.Active="Активный"
-Reset="Перезагрузить"
\ No newline at end of file
+Reset="Перезагрузить"
+EnableAll="Активировать все"
+DisableAll="Деактивировать все"
\ No newline at end of file
diff --git a/data/locale/uk-UA.ini b/data/locale/uk-UA.ini
index 28eb0f2..8eabbce 100644
--- a/data/locale/uk-UA.ini
+++ b/data/locale/uk-UA.ini
@@ -26,4 +26,6 @@ Status.Live="Жити"
Status.Reconnecting="Повторне підключення"
Status.Inactive="Неактивний"
Status.Active="Активний"
-Reset="Скидання"
\ No newline at end of file
+Reset="Скидання"
+EnableAll="Активувати всі"
+DisableAll="Деактивувати всі"
\ No newline at end of file
diff --git a/data/locale/zh-CN.ini b/data/locale/zh-CN.ini
index 6ee6fe8..77afca0 100644
--- a/data/locale/zh-CN.ini
+++ b/data/locale/zh-CN.ini
@@ -26,4 +26,6 @@ Status.Live="活的"
Status.Reconnecting="重新连接"
Status.Inactive="不活跃"
Status.Active="积极的"
-Reset="重置"
\ No newline at end of file
+Reset="重置"
+EnableAll="全部启用"
+DisableAll="全部停用"
diff --git a/src/dock/output-status.cpp b/src/dock/output-status.cpp
index 549e5b5..3643bcd 100644
--- a/src/dock/output-status.cpp
+++ b/src/dock/output-status.cpp
@@ -26,6 +26,8 @@ with this program. If not, see
#include
#include
#include
+#include
+#include
#include
#include "output-status.hpp"
@@ -53,13 +55,13 @@ BranchOutputStatus::BranchOutputStatus(QWidget *parent) : QFrame(parent), timer(
outputTable->setColumnCount(7);
int col = 0;
- outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("SourceName")));
outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("FilterName")));
+ outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("SourceName")));
outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("Status")));
outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("DropFrames")));
outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("SentDataSize")));
outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("BitRate")));
- outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QTStr("")));
+ outputTable->setHorizontalHeaderItem(col++, new QTableWidgetItem(QString::fromUtf8("")));
QObject::connect(&timer, &QTimer::timeout, this, &BranchOutputStatus::Update);
@@ -68,45 +70,79 @@ BranchOutputStatus::BranchOutputStatus(QWidget *parent) : QFrame(parent), timer(
timer.start();
}
+ // Tool buttons
+ auto enableAllButton = new QPushButton(QTStr("EnableAll"));
+ connect(enableAllButton, &QPushButton::clicked, [this]() { SetEabnleAll(true); });
+
+ auto disableAllButton = new QPushButton(QTStr("DisableAll"));
+ connect(disableAllButton, &QPushButton::clicked, [this]() { SetEabnleAll(false); });
+
+ auto buttonsContainerLayout = new QHBoxLayout();
+ buttonsContainerLayout->addWidget(enableAllButton);
+ buttonsContainerLayout->addWidget(disableAllButton);
+ buttonsContainerLayout->addStretch();
+
QVBoxLayout *outputContainerLayout = new QVBoxLayout();
outputContainerLayout->addWidget(outputTable);
-
+ outputContainerLayout->addLayout(buttonsContainerLayout);
this->setLayout(outputContainerLayout);
}
BranchOutputStatus::~BranchOutputStatus() {}
-void BranchOutputStatus::AddOutputLabels(QString parentName, filter_t *filter)
+void BranchOutputStatus::AddOutputLabels(filter_t *filter)
{
+ auto parent = obs_filter_get_parent(filter->source);
OutputLabels ol;
ol.filter = filter;
- ol.parentName = new QTableWidgetItem(parentName);
- ol.name = new QTableWidgetItem(QTStr(obs_source_get_name(filter->source)));
- ol.status = new QLabel(QTStr("Status.Inactive"));
- ol.droppedFrames = new QLabel(QTStr(""));
- ol.megabytesSent = new QLabel(QTStr(""));
- ol.bitrate = new QLabel(QTStr(""));
+ ol.filterItem = new FilterItem(QString::fromUtf8(obs_source_get_name(filter->source)), filter->source, this);
+ ol.parentName = new QTableWidgetItem(QString::fromUtf8(obs_source_get_name(parent)));
+ ol.status = new QLabel(QTStr("Status.Inactive"), this);
+ ol.droppedFrames = new QLabel(QString::fromUtf8(""), this);
+ ol.megabytesSent = new QLabel(QString::fromUtf8(""), this);
+ ol.bitrate = new QLabel(QString::fromUtf8(""), this);
auto col = 0;
auto row = (int)outputLabels.size();
outputTable->setRowCount(row + 1);
+ outputTable->setCellWidget(row, col++, ol.filterItem);
outputTable->setItem(row, col++, ol.parentName);
- outputTable->setItem(row, col++, ol.name);
outputTable->setCellWidget(row, col++, ol.status);
outputTable->setCellWidget(row, col++, ol.droppedFrames);
outputTable->setCellWidget(row, col++, ol.megabytesSent);
outputTable->setCellWidget(row, col++, ol.bitrate);
+ outputTable->setRowHeight(row, 32);
+
outputLabels.push_back(ol);
// Setup reset button
+ auto resetButtonContainer = new QWidget(this);
+ auto resetButtonLayout = new QHBoxLayout();
+ resetButtonLayout->setContentsMargins(0, 0, 0, 0);
+ resetButtonContainer->setLayout(resetButtonLayout);
+
auto resetButton = new QPushButton(QTStr("Reset"), this);
connect(resetButton, &QPushButton::clicked, [this, row]() { outputLabels[row].Reset(); });
+ resetButton->setProperty("toolButton", true);
resetButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
- resetButton->setMinimumHeight(27);
- outputTable->setCellWidget(row, col, resetButton);
+
+ resetButtonLayout->addWidget(resetButton);
+ outputTable->setCellWidget(row, col, resetButtonContainer);
+
+ // Listen signal for filter update
+ signal_handler_connect(
+ obs_source_get_signal_handler(filter->source), "rename", BranchOutputStatus::OutputLabels::FilterRenamed,
+ outputLabels[row].filterItem
+ );
+
+ // Listen signal for parent update
+ signal_handler_connect(
+ obs_source_get_signal_handler(parent), "rename", BranchOutputStatus::OutputLabels::ParentRenamed,
+ outputLabels[row].parentName
+ );
}
void BranchOutputStatus::RemoveOutputLabels(filter_t *filter)
@@ -115,6 +151,17 @@ void BranchOutputStatus::RemoveOutputLabels(filter_t *filter)
if (outputLabels[i].filter == filter) {
outputLabels.removeAt(i);
outputTable->removeRow(i);
+
+ signal_handler_disconnect(
+ obs_source_get_signal_handler(filter->source), "rename",
+ BranchOutputStatus::OutputLabels::FilterRenamed, outputLabels[i].filterItem
+ );
+
+ signal_handler_disconnect(
+ obs_source_get_signal_handler(obs_filter_get_parent(filter->source)), "rename",
+ BranchOutputStatus::OutputLabels::ParentRenamed, outputLabels[i].parentName
+ );
+
break;
}
}
@@ -137,6 +184,13 @@ void BranchOutputStatus::hideEvent(QHideEvent *)
timer.stop();
}
+void BranchOutputStatus::SetEabnleAll(bool enabled)
+{
+ for (int i = 0; i < outputLabels.size(); i++) {
+ obs_source_set_enabled(outputLabels[i].filter->source, enabled);
+ }
+}
+
// Imitate UI/window-basic-stats.cpp
void setThemeID(QWidget *widget, const QString &themeID)
{
@@ -150,6 +204,8 @@ void setThemeID(QWidget *widget, const QString &themeID)
}
}
+// BranchOutputStatus::OutputLabels structure
+
// Imitate UI/window-basic-stats.cpp
void BranchOutputStatus::OutputLabels::Update(bool rec)
{
@@ -257,3 +313,60 @@ void BranchOutputStatus::OutputLabels::Reset()
megabytesSent->setText(QString("0 MiB"));
bitrate->setText(QString("0 kb/s"));
}
+
+void BranchOutputStatus::OutputLabels::FilterRenamed(void *data, calldata_t *cd)
+{
+ auto item = (FilterItem *)data;
+ auto newName = calldata_string(cd, "new_name");
+ item->SetText(QString::fromUtf8(newName));
+}
+
+void BranchOutputStatus::OutputLabels::ParentRenamed(void *data, calldata_t *cd)
+{
+ auto label = (QTableWidgetItem *)data;
+ auto newName = calldata_string(cd, "new_name");
+ label->setText(QString::fromUtf8(newName));
+}
+
+// FilterItem class
+
+FilterItem::FilterItem(QString text, obs_source_t *_source, QWidget *parent) : QWidget(parent)
+{
+ setMinimumHeight(27);
+ source = _source;
+
+ visibilityCheckbox = new QCheckBox(this);
+ visibilityCheckbox->setProperty("visibilityCheckBox", true);
+ visibilityCheckbox->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+ visibilityCheckbox->setChecked(obs_source_enabled(source));
+
+ connect(visibilityCheckbox, &QCheckBox::clicked, [this](bool visible) { obs_source_set_enabled(source, visible); });
+
+ name = new QLabel(text, this);
+
+ auto checkboxLayout = new QHBoxLayout();
+ checkboxLayout->setContentsMargins(0, 0, 0, 0);
+ checkboxLayout->addWidget(visibilityCheckbox);
+ checkboxLayout->addWidget(name);
+ setLayout(checkboxLayout);
+
+ // Listen signal for filter enabled/disabled
+ signal_handler_connect(obs_source_get_signal_handler(source), "enable", FilterItem::VisibilityChanged, this);
+}
+
+FilterItem::~FilterItem()
+{
+ signal_handler_disconnect(obs_source_get_signal_handler(source), "enable", FilterItem::VisibilityChanged, this);
+}
+
+void FilterItem::SetText(QString text)
+{
+ name->setText(text);
+}
+
+void FilterItem::VisibilityChanged(void *data, calldata_t *cd)
+{
+ auto item = (FilterItem *)data;
+ auto enabled = calldata_bool(cd, "enabled");
+ item->visibilityCheckbox->setChecked(enabled);
+}
diff --git a/src/dock/output-status.hpp b/src/dock/output-status.hpp
index 30e6580..f94bdff 100644
--- a/src/dock/output-status.hpp
+++ b/src/dock/output-status.hpp
@@ -28,15 +28,33 @@ class QTableWidget;
class QTableWidgetItem;
class QLabel;
class QString;
+class QCheckBox;
struct filter_t;
+class FilterItem : public QWidget {
+ Q_OBJECT
+
+ obs_source_t *source;
+
+ QCheckBox *visibilityCheckbox;
+ QLabel *name;
+
+public:
+ FilterItem(QString text, obs_source_t *_source, QWidget *parent = (QWidget *)nullptr);
+ ~FilterItem();
+
+ void SetText(QString text);
+
+ static void VisibilityChanged(void *data, calldata_t *cd);
+};
+
class BranchOutputStatus : public QFrame {
Q_OBJECT
struct OutputLabels {
filter_t *filter;
+ FilterItem *filterItem;
QTableWidgetItem *parentName;
- QTableWidgetItem *name;
QLabel *status;
QLabel *droppedFrames;
QLabel *megabytesSent;
@@ -51,6 +69,9 @@ class BranchOutputStatus : public QFrame {
void Update(bool rec);
void Reset();
+ static void FilterRenamed(void *data, calldata_t *cd);
+ static void ParentRenamed(void *data, calldata_t *cd);
+
long double kbps = 0.0l;
};
@@ -64,8 +85,9 @@ class BranchOutputStatus : public QFrame {
BranchOutputStatus(QWidget *parent = (QWidget *)nullptr);
~BranchOutputStatus();
- void AddOutputLabels(QString parentName, filter_t *filter);
+ void AddOutputLabels(filter_t *filter);
void RemoveOutputLabels(filter_t *filter);
+ void SetEabnleAll(bool enabled);
protected:
virtual void showEvent(QShowEvent *event) override;
diff --git a/src/plugin-main.cpp b/src/plugin-main.cpp
index 51fb33f..459b41b 100644
--- a/src/plugin-main.cpp
+++ b/src/plugin-main.cpp
@@ -513,11 +513,11 @@ void video_tick(void *data, float)
BranchOutputStatus *status_dock = nullptr;
-void filter_add(void *data, obs_source_t *parent)
+void filter_add(void *data, obs_source_t *)
{
// Register to output status dock
auto filter = (filter_t *)data;
- status_dock->AddOutputLabels(QTStr(obs_source_get_name(parent)), filter);
+ status_dock->AddOutputLabels(filter);
}
void filter_remove(void *data, obs_source_t *)