Skip to content

Commit

Permalink
Merge pull request #23 from OPENSPHERE-Inc/patch-0.9.9
Browse files Browse the repository at this point in the history
Patch 0.9.9
  • Loading branch information
hanatyan128 authored Sep 23, 2024
2 parents a9ca28d + ca6aadc commit 360a325
Show file tree
Hide file tree
Showing 9 changed files with 338 additions and 194 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ More reliable and proper audio handling.
- Status dock to check the status and statistics of all Branch Output filters. Support for batch or individual activation and deactivation
- Can be interlinked with OBS Studio's streaming, recording, and virtual camera status

> **For studio mode: Branch Output ignore studio mode's program out and always outputs preview's one**
**[JP]**

Expand All @@ -43,6 +44,8 @@ More reliable and proper audio handling.
- ステータスドックで全 Branch Output フィルターの状態と統計を確認可能。一括ないし個別の有効化・無効化に対応。
- OBS Studio の配信・録画・仮想カメラの状態と連動可能

> **スタジオモード向け: Branch Output はスタジオモードのプログラム出力を無視し、常にプレビューを出力に使用します**
## Requirements

[OBS Studio](https://obsproject.com/) >= 30.1.0 (Qt6, x64/ARM64/AppleSilicon)
Expand Down
2 changes: 1 addition & 1 deletion buildspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
"name": "osi-branch-output",
"displayName": "Branch Output Plugin",
"version": "0.9.8",
"version": "0.9.9",
"author": "OPENSPHERE Inc.",
"website": "https://opensphere.co.jp/",
"email": "[email protected]",
Expand Down
88 changes: 58 additions & 30 deletions src/UI/output-status-dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,15 @@ BranchOutputStatusDock::BranchOutputStatusDock(QWidget *parent) : QFrame(parent)
this->setLayout(outputContainerLayout);

loadSettings();

obs_log(LOG_DEBUG, "BranchOutputStatusDock created");
}

BranchOutputStatusDock::~BranchOutputStatusDock()
{
saveSettings();

obs_log(LOG_DEBUG, "BranchOutputStatusDock destroyed");
}

void BranchOutputStatusDock::loadSettings()
Expand Down Expand Up @@ -171,31 +175,29 @@ void BranchOutputStatusDock::addFilter(BranchOutputFilter *filter)
auto parent = obs_filter_get_parent(filter->filterSource);
auto row = (int)outputTableRows.size();

OutputTableRow ol;
auto otr = new OutputTableRow(this);

ol.filter = filter;
ol.filterCell =
otr->filter = filter;
otr->filterCell =
new FilterCell(QString::fromUtf8(obs_source_get_name(filter->filterSource)), filter->filterSource, this);
ol.parentCell = new ParentCell(obs_source_get_name(parent), parent, this);
ol.status = new StatusCell(QTStr("Status.Inactive"), this);
ol.status->setIcon(QPixmap(":/branch-output/images/streaming.svg").scaled(16, 16));
ol.recording = new StatusCell(QTStr("Status.Inactive"), this);
ol.recording->setIcon(QPixmap(":/branch-output/images/recording.svg").scaled(16, 16));
ol.droppedFrames = new QLabel("", this);
ol.megabytesSent = new QLabel("", this);
ol.bitrate = new QLabel("", this);

outputTableRows.push_back(ol);
otr->parentCell = new ParentCell(obs_source_get_name(parent), parent, this);
otr->status = new StatusCell(QTStr("Status.Inactive"), this);
otr->status->setIcon(QPixmap(":/branch-output/images/streaming.svg").scaled(16, 16));
otr->recording = new StatusCell(QTStr("Status.Inactive"), this);
otr->recording->setIcon(QPixmap(":/branch-output/images/recording.svg").scaled(16, 16));
otr->droppedFrames = new QLabel("", this);
otr->megabytesSent = new QLabel("", this);
otr->bitrate = new QLabel("", this);

auto col = 0;
outputTable->setRowCount(row + 1);
outputTable->setCellWidget(row, col++, ol.filterCell);
outputTable->setCellWidget(row, col++, ol.parentCell);
outputTable->setCellWidget(row, col++, ol.status);
outputTable->setCellWidget(row, col++, ol.recording);
outputTable->setCellWidget(row, col++, ol.droppedFrames);
outputTable->setCellWidget(row, col++, ol.megabytesSent);
outputTable->setCellWidget(row, col++, ol.bitrate);
outputTable->setCellWidget(row, col++, otr->filterCell);
outputTable->setCellWidget(row, col++, otr->parentCell);
outputTable->setCellWidget(row, col++, otr->status);
outputTable->setCellWidget(row, col++, otr->recording);
outputTable->setCellWidget(row, col++, otr->droppedFrames);
outputTable->setCellWidget(row, col++, otr->megabytesSent);
outputTable->setCellWidget(row, col++, otr->bitrate);

outputTable->setRowHeight(row, 32);

Expand All @@ -206,29 +208,39 @@ void BranchOutputStatusDock::addFilter(BranchOutputFilter *filter)
resetButtonContainer->setLayout(resetButtonContainerLayout);

auto resetButton = new QPushButton(QTStr("Reset"), this);
connect(resetButton, &QPushButton::clicked, [this, row]() { outputTableRows[row].reset(); });
connect(resetButton, &QPushButton::clicked, [this, row]() { outputTableRows[row]->reset(); });
resetButton->setProperty("toolButton", true);
resetButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);

resetButtonContainerLayout->addWidget(resetButton);
outputTable->setCellWidget(row, col, resetButtonContainer);

outputTableRows.push_back(otr);
}

void BranchOutputStatusDock::removeFilter(BranchOutputFilter *filter)
{
// DO NOT access filter resources at this time (It may be already deleted)
for (int i = 0; i < outputTableRows.size(); i++) {
if (outputTableRows[i].filter == filter) {
outputTableRows.removeAt(i);
auto otr = outputTableRows[i];
if (otr->filter == filter) {
outputTable->removeRow(i);
outputTableRows.removeAt(i);
otr->deleteLater();
break;
}
}
}

void BranchOutputStatusDock::update()
{
for (int i = 0; i < outputTableRows.size(); i++) {
outputTableRows[i].update();
foreach (auto row, outputTableRows) {
if (!sourceInFrontend(obs_filter_get_parent(row->filter->filterSource))) {
// Remove filter that no longer exists in the frontend
removeFilter(row->filter);
continue;
}
row->update();
}
}

Expand All @@ -244,15 +256,30 @@ void BranchOutputStatusDock::hideEvent(QHideEvent *)

void BranchOutputStatusDock::setEabnleAll(bool enabled)
{
foreach (auto &row, outputTableRows) {
obs_source_set_enabled(row.filter->filterSource, enabled);
foreach (auto row, outputTableRows) {
obs_source_set_enabled(row->filter->filterSource, enabled);
}
}

//--- BranchOutputStatusDock::OutputTableRow structure ---//
BranchOutputFilter *BranchOutputStatusDock::findFilter(const QString &parentName, const QString &filterName)
{
for (auto row : outputTableRows) {
if (filterName == obs_source_get_name(row->filter->filterSource) &&
parentName == obs_source_get_name(obs_filter_get_parent(row->filter->filterSource))) {
return row->filter;
}
}
return nullptr;
}

//--- OutputTableRow class ---//

OutputTableRow::OutputTableRow(QObject *parent) : QObject(parent) {}

OutputTableRow::~OutputTableRow() {}

// Imitate UI/window-basic-stats.cpp
void BranchOutputStatusDock::OutputTableRow::update()
void OutputTableRow::update()
{
auto output = filter->streamOutput ? filter->streamOutput : filter->recordingOutput;
uint64_t totalBytes = output ? obs_output_get_total_bytes(output) : 0;
Expand Down Expand Up @@ -353,7 +380,7 @@ void BranchOutputStatusDock::OutputTableRow::update()
lastBytesSentTime = curTime;
}

void BranchOutputStatusDock::OutputTableRow::reset()
void OutputTableRow::reset()
{
auto output = filter->streamOutput ? filter->streamOutput : filter->recordingOutput;
if (!output) {
Expand Down Expand Up @@ -453,6 +480,7 @@ void ParentCell::setSourceName(const QString &text)
void ParentCell::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
obs_log(LOG_DEBUG, "uuid=%s", obs_source_get_uuid(source));
obs_frontend_open_source_filters(source);
}
}
Expand Down
58 changes: 35 additions & 23 deletions src/UI/output-status-dock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class QString;
class QCheckBox;
class QPushButton;
struct BranchOutputFilter;
class OutputTableRow;

class FilterCell : public QWidget {
Q_OBJECT
Expand Down Expand Up @@ -93,35 +94,14 @@ class StatusCell : public QWidget {
class BranchOutputStatusDock : public QFrame {
Q_OBJECT

struct OutputTableRow {
BranchOutputFilter *filter;
FilterCell *filterCell;
ParentCell *parentCell;
StatusCell *status;
StatusCell *recording;
QLabel *droppedFrames;
QLabel *megabytesSent;
QLabel *bitrate;

uint64_t lastBytesSent = 0;
uint64_t lastBytesSentTime = 0;

int first_total = 0;
int first_dropped = 0;

void update();
void reset();

long double kbps = 0.0l;
};

QTimer timer;
QTableWidget *outputTable = nullptr;
QList<OutputTableRow> outputTableRows;
QList<OutputTableRow *> outputTableRows;
QPushButton *enableAllButton = nullptr;
QPushButton *disableAllButton = nullptr;
QLabel *interlockLabel = nullptr;
QComboBox *interlockComboBox = nullptr;
OBSSignal sourceAddedSignal;

void update();
void saveSettings();
Expand All @@ -135,9 +115,41 @@ class BranchOutputStatusDock : public QFrame {
explicit BranchOutputStatusDock(QWidget *parent = (QWidget *)nullptr);
~BranchOutputStatusDock();

public slots:
void addFilter(BranchOutputFilter *filter);
void removeFilter(BranchOutputFilter *filter);
BranchOutputFilter *findFilter(const QString &parentName, const QString &filterName);
void setEabnleAll(bool enabled);

inline int getInterlockType() const { return interlockComboBox->currentData().toInt(); };
};

class OutputTableRow : public QObject {
Q_OBJECT

friend class BranchOutputStatusDock;

BranchOutputFilter *filter;
FilterCell *filterCell;
ParentCell *parentCell;
StatusCell *status;
StatusCell *recording;
QLabel *droppedFrames;
QLabel *megabytesSent;
QLabel *bitrate;

uint64_t lastBytesSent = 0;
uint64_t lastBytesSentTime = 0;

int first_total = 0;
int first_dropped = 0;

void update();
void reset();

long double kbps = 0.0l;

public:
explicit OutputTableRow(QObject *parent = (QObject *)nullptr);
~OutputTableRow();
};
2 changes: 2 additions & 0 deletions src/plugin-audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ void masterAudioCallback(void *param, size_t, audio_data *audioData)
pushAudioToBuffer(filter, &filterAudioData);
}

//--- OBS Plugin Callbacks ---//

// Callback from audio output
bool audioInputCallback(
void *param, uint64_t startTsIn, uint64_t, uint64_t *outTs, uint32_t mixers, audio_output_data *mixes
Expand Down
Loading

0 comments on commit 360a325

Please sign in to comment.