|
@@ -0,0 +1,228 @@
|
|
|
+/******************************************************************************
|
|
|
+ Copyright (C) 2014 by Ruwen Hahn <[email protected]>
|
|
|
+
|
|
|
+ This program is free software: you can redistribute it and/or modify
|
|
|
+ it under the terms of the GNU General Public License as published by
|
|
|
+ the Free Software Foundation, either version 2 of the License, or
|
|
|
+ (at your option) any later version.
|
|
|
+
|
|
|
+ This program is distributed in the hope that it will be useful,
|
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ GNU General Public License for more details.
|
|
|
+
|
|
|
+ You should have received a copy of the GNU General Public License
|
|
|
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+******************************************************************************/
|
|
|
+
|
|
|
+#include "window-remux.hpp"
|
|
|
+
|
|
|
+#include "obs-app.hpp"
|
|
|
+
|
|
|
+#include <QCloseEvent>
|
|
|
+#include <QFileDialog>
|
|
|
+#include <QFileInfo>
|
|
|
+#include <QMessageBox>
|
|
|
+
|
|
|
+#include "qt-wrappers.hpp"
|
|
|
+
|
|
|
+#include <memory>
|
|
|
+#include <cmath>
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+
|
|
|
+OBSRemux::OBSRemux(const char *path, QWidget *parent)
|
|
|
+ : QDialog (parent),
|
|
|
+ worker (new RemuxWorker),
|
|
|
+ ui (new Ui::OBSRemux),
|
|
|
+ recPath (path)
|
|
|
+{
|
|
|
+ ui->setupUi(this);
|
|
|
+
|
|
|
+ ui->progressBar->setVisible(false);
|
|
|
+ ui->remux->setEnabled(false);
|
|
|
+ ui->targetFile->setEnabled(false);
|
|
|
+ ui->browseTarget->setEnabled(false);
|
|
|
+
|
|
|
+ ui->progressBar->setMinimum(0);
|
|
|
+ ui->progressBar->setMaximum(1000);
|
|
|
+ ui->progressBar->setValue(0);
|
|
|
+
|
|
|
+ connect(ui->browseSource, &QPushButton::clicked,
|
|
|
+ [&]() { BrowseInput(); });
|
|
|
+ connect(ui->browseTarget, &QPushButton::clicked,
|
|
|
+ [&]() { BrowseOutput(); });
|
|
|
+ connect(ui->remux, &QPushButton::clicked, [&]() { Remux(); });
|
|
|
+
|
|
|
+ connect(ui->sourceFile, &QLineEdit::textChanged,
|
|
|
+ this, &OBSRemux::inputChanged);
|
|
|
+
|
|
|
+ worker->moveToThread(&remuxer);
|
|
|
+
|
|
|
+ //gcc-4.8 can't use QPointer<RemuxWorker> below
|
|
|
+ RemuxWorker *worker_ = worker;
|
|
|
+ connect(worker_, &RemuxWorker::updateProgress,
|
|
|
+ this, &OBSRemux::updateProgress);
|
|
|
+ connect(&remuxer, &QThread::finished, worker_, &QObject::deleteLater);
|
|
|
+ connect(worker_, &RemuxWorker::remuxFinished,
|
|
|
+ this, &OBSRemux::remuxFinished);
|
|
|
+ connect(this, &OBSRemux::remux, worker_, &RemuxWorker::remux);
|
|
|
+}
|
|
|
+
|
|
|
+bool OBSRemux::Stop()
|
|
|
+{
|
|
|
+ if (!worker->job)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ if (QMessageBox::critical(nullptr,
|
|
|
+ QTStr("Remux.ExitUnfinishedTitle"),
|
|
|
+ QTStr("Remux.ExitUnfinished"),
|
|
|
+ QMessageBox::Yes | QMessageBox::No,
|
|
|
+ QMessageBox::No) ==
|
|
|
+ QMessageBox::Yes) {
|
|
|
+ os_event_signal(worker->stop);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+OBSRemux::~OBSRemux()
|
|
|
+{
|
|
|
+ Stop();
|
|
|
+ remuxer.quit();
|
|
|
+ remuxer.wait();
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::BrowseInput()
|
|
|
+{
|
|
|
+ QString path = ui->sourceFile->text();
|
|
|
+ if (path.isEmpty())
|
|
|
+ path = recPath;
|
|
|
+
|
|
|
+ path = QFileDialog::getOpenFileName(this,
|
|
|
+ QTStr("Remux.SelectRecording"), path,
|
|
|
+ QTStr("Remux.RecordingPattern"));
|
|
|
+
|
|
|
+ inputChanged(path);
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::inputChanged(const QString &path)
|
|
|
+{
|
|
|
+ if (!QFileInfo::exists(path)) {
|
|
|
+ ui->remux->setEnabled(false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ui->sourceFile->setText(path);
|
|
|
+ ui->remux->setEnabled(true);
|
|
|
+
|
|
|
+ QFileInfo fi(path);
|
|
|
+ QString mp4 = fi.path() + "/" + fi.baseName() + ".mp4";
|
|
|
+ ui->targetFile->setText(mp4);
|
|
|
+
|
|
|
+ ui->targetFile->setEnabled(true);
|
|
|
+ ui->browseTarget->setEnabled(true);
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::BrowseOutput()
|
|
|
+{
|
|
|
+ QString path(ui->targetFile->text());
|
|
|
+ path = QFileDialog::getSaveFileName(this, QTStr("Remux.SelectTarget"),
|
|
|
+ path, "(*.mp4)");
|
|
|
+
|
|
|
+ if (path.isEmpty())
|
|
|
+ return;
|
|
|
+
|
|
|
+ ui->targetFile->setText(path);
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::Remux()
|
|
|
+{
|
|
|
+ if (QFileInfo::exists(ui->targetFile->text()))
|
|
|
+ if (QMessageBox::question(this, QTStr("Remux.FileExistsTitle"),
|
|
|
+ QTStr("Remux.FileExists"),
|
|
|
+ QMessageBox::Yes | QMessageBox::No) !=
|
|
|
+ QMessageBox::Yes)
|
|
|
+ return;
|
|
|
+
|
|
|
+ media_remux_job_t mr_job = nullptr;
|
|
|
+ if (!media_remux_job_create(&mr_job, QT_TO_UTF8(ui->sourceFile->text()),
|
|
|
+ QT_TO_UTF8(ui->targetFile->text())))
|
|
|
+ return;
|
|
|
+
|
|
|
+ worker->job = job_t(mr_job, media_remux_job_destroy);
|
|
|
+ worker->lastProgress = 0.f;
|
|
|
+
|
|
|
+ ui->progressBar->setVisible(true);
|
|
|
+ ui->remux->setEnabled(false);
|
|
|
+
|
|
|
+ if (!remuxer.isRunning())
|
|
|
+ remuxer.start();
|
|
|
+ emit remux();
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::closeEvent(QCloseEvent *event)
|
|
|
+{
|
|
|
+ if (!Stop())
|
|
|
+ event->ignore();
|
|
|
+ else
|
|
|
+ QDialog::closeEvent(event);
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::reject()
|
|
|
+{
|
|
|
+ if (!Stop())
|
|
|
+ return;
|
|
|
+
|
|
|
+ QDialog::reject();
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::updateProgress(float percent)
|
|
|
+{
|
|
|
+ ui->progressBar->setValue(percent * 10);
|
|
|
+}
|
|
|
+
|
|
|
+void OBSRemux::remuxFinished(bool success)
|
|
|
+{
|
|
|
+ QMessageBox::information(this, QTStr("Remux.FinishedTitle"),
|
|
|
+ success ?
|
|
|
+ QTStr("Remux.Finished") : QTStr("Remux.FinishedError"));
|
|
|
+
|
|
|
+ worker->job.reset();
|
|
|
+ ui->progressBar->setVisible(false);
|
|
|
+ ui->remux->setEnabled(true);
|
|
|
+}
|
|
|
+
|
|
|
+RemuxWorker::RemuxWorker()
|
|
|
+{
|
|
|
+ os_event_init(&stop, OS_EVENT_TYPE_MANUAL);
|
|
|
+}
|
|
|
+
|
|
|
+RemuxWorker::~RemuxWorker()
|
|
|
+{
|
|
|
+ os_event_destroy(stop);
|
|
|
+}
|
|
|
+
|
|
|
+void RemuxWorker::UpdateProgress(float percent)
|
|
|
+{
|
|
|
+ if (abs(lastProgress - percent) < 0.1f)
|
|
|
+ return;
|
|
|
+
|
|
|
+ emit updateProgress(percent);
|
|
|
+ lastProgress = percent;
|
|
|
+}
|
|
|
+
|
|
|
+void RemuxWorker::remux()
|
|
|
+{
|
|
|
+ auto callback = [](void *data, float percent)
|
|
|
+ {
|
|
|
+ auto rw = static_cast<RemuxWorker*>(data);
|
|
|
+ rw->UpdateProgress(percent);
|
|
|
+ return !!os_event_try(rw->stop);
|
|
|
+ };
|
|
|
+
|
|
|
+ bool success = media_remux_job_process(job.get(), callback, this);
|
|
|
+
|
|
|
+ emit remuxFinished(os_event_try(stop) && success);
|
|
|
+}
|