176 lines
4.7 KiB
C++
176 lines
4.7 KiB
C++
#include <warppipe/warppipe.hpp>
|
|
|
|
#include "GraphEditorWidget.h"
|
|
|
|
#include <QAction>
|
|
#include <QApplication>
|
|
#include <QCommandLineParser>
|
|
#include <QDateTime>
|
|
#include <QDir>
|
|
#include <QKeySequence>
|
|
#include <QLabel>
|
|
#include <QMainWindow>
|
|
#include <QPixmap>
|
|
#include <QScreen>
|
|
#include <QStandardPaths>
|
|
#include <QStatusBar>
|
|
#include <QTimer>
|
|
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
static int captureWindow(QMainWindow *window, const QString &path) {
|
|
QPixmap pixmap = window->grab();
|
|
if (pixmap.isNull()) {
|
|
QScreen *screen = window->screen();
|
|
if (screen) {
|
|
pixmap = screen->grabWindow(window->winId());
|
|
}
|
|
}
|
|
if (pixmap.isNull()) {
|
|
std::cerr << "warppipe: screenshot capture failed\n";
|
|
return 3;
|
|
}
|
|
|
|
QFileInfo fi(path);
|
|
QDir dir = fi.absoluteDir();
|
|
if (!dir.exists()) {
|
|
dir.mkpath(".");
|
|
}
|
|
|
|
if (!pixmap.save(path)) {
|
|
std::cerr << "warppipe: failed to write screenshot to "
|
|
<< path.toStdString() << "\n";
|
|
return 3;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
for (int i = 1; i < argc; ++i) {
|
|
if (std::strcmp(argv[i], "--offscreen") == 0) {
|
|
qputenv("QT_QPA_PLATFORM", "offscreen");
|
|
}
|
|
}
|
|
|
|
QApplication app(argc, argv);
|
|
QCoreApplication::setApplicationName("Warppipe");
|
|
QCoreApplication::setApplicationVersion("0.1.0");
|
|
|
|
QCommandLineParser parser;
|
|
parser.setApplicationDescription("Warppipe — PipeWire Audio Router GUI");
|
|
parser.addHelpOption();
|
|
parser.addVersionOption();
|
|
|
|
QCommandLineOption screenshotOpt(
|
|
QStringList() << "s" << "screenshot",
|
|
"Capture window to PNG and exit.", "path");
|
|
QCommandLineOption delayOpt(
|
|
"screenshot-delay",
|
|
"Delay in ms before capture (default 800).", "ms", "800");
|
|
QCommandLineOption debugDirOpt(
|
|
"debug-screenshot-dir",
|
|
"Save timestamped screenshot on every graph state change.", "dir");
|
|
QCommandLineOption offscreenOpt(
|
|
"offscreen",
|
|
"Run with QT_QPA_PLATFORM=offscreen (headless).");
|
|
|
|
parser.addOption(screenshotOpt);
|
|
parser.addOption(delayOpt);
|
|
parser.addOption(debugDirOpt);
|
|
parser.addOption(offscreenOpt);
|
|
parser.process(app);
|
|
|
|
warppipe::ConnectionOptions opts;
|
|
opts.application_name = "warppipe-gui";
|
|
|
|
auto result = warppipe::Client::Create(opts);
|
|
if (!result.ok()) {
|
|
std::cerr << "warppipe: failed to connect: " << result.status.message
|
|
<< "\n";
|
|
return 1;
|
|
}
|
|
|
|
auto &client = result.value;
|
|
|
|
QMainWindow window;
|
|
window.setWindowTitle("Warppipe \u2014 Audio Router");
|
|
|
|
auto *editor = new GraphEditorWidget(client.get(), &window);
|
|
window.setCentralWidget(editor);
|
|
window.resize(1280, 720);
|
|
|
|
auto *statusLabel = new QLabel(&window);
|
|
window.statusBar()->addWidget(statusLabel);
|
|
|
|
auto *statusTimer = new QTimer(&window);
|
|
QObject::connect(statusTimer, &QTimer::timeout, [&]() {
|
|
int nodes = editor->nodeCount();
|
|
int links = editor->linkCount();
|
|
statusLabel->setText(
|
|
QString("PipeWire connected | %1 nodes | %2 links")
|
|
.arg(nodes)
|
|
.arg(links));
|
|
});
|
|
statusTimer->start(500);
|
|
|
|
if (parser.isSet(debugDirOpt)) {
|
|
editor->setDebugScreenshotDir(parser.value(debugDirOpt));
|
|
}
|
|
|
|
if (parser.isSet(screenshotOpt)) {
|
|
QString screenshotPath = parser.value(screenshotOpt);
|
|
int delay = parser.value(delayOpt).toInt();
|
|
if (delay <= 0) {
|
|
delay = 800;
|
|
}
|
|
|
|
bool captured = false;
|
|
auto doCapture = [&]() {
|
|
if (captured) return;
|
|
captured = true;
|
|
QTimer::singleShot(100, [&]() {
|
|
int code = captureWindow(&window, screenshotPath);
|
|
app.exit(code);
|
|
});
|
|
};
|
|
|
|
auto *fallbackTimer = new QTimer(&window);
|
|
fallbackTimer->setSingleShot(true);
|
|
QObject::connect(fallbackTimer, &QTimer::timeout, doCapture);
|
|
|
|
QObject::connect(editor, &GraphEditorWidget::graphReady, [&]() {
|
|
fallbackTimer->stop();
|
|
doCapture();
|
|
});
|
|
|
|
fallbackTimer->start(delay);
|
|
}
|
|
|
|
auto *f12Action = new QAction(&window);
|
|
f12Action->setShortcut(Qt::Key_F12);
|
|
QObject::connect(f12Action, &QAction::triggered, [&]() {
|
|
QString picDir =
|
|
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) +
|
|
"/warppipe";
|
|
QDir().mkpath(picDir);
|
|
QString timestamp =
|
|
QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss");
|
|
QString path = picDir + "/warppipe_" + timestamp + ".png";
|
|
int code = captureWindow(&window, path);
|
|
if (code == 0) {
|
|
window.statusBar()->showMessage("Screenshot saved: " + path, 3000);
|
|
}
|
|
});
|
|
window.addAction(f12Action);
|
|
|
|
auto *closeAction = new QAction(&window);
|
|
closeAction->setShortcut(QKeySequence::Quit);
|
|
QObject::connect(closeAction, &QAction::triggered, &window,
|
|
&QMainWindow::close);
|
|
window.addAction(closeAction);
|
|
|
|
window.show();
|
|
|
|
return app.exec();
|
|
}
|