xybrid/xybrid/main.cpp

141 lines
4.0 KiB
C++

#include "mainwindow.h"
#include "audio/audioengine.h"
#include "config/pluginregistry.h"
#include "data/graph.h"
#include "fileops.h"
#include "util/mem.h"
#include <vector>
#include <QDebug>
#include <QApplication>
#include <QCommandLineParser>
#include <QLocalServer>
#include <QLocalSocket>
#include <QSurfaceFormat>
#include <QFontDatabase>
#include <QCborMap>
#include <QCborArray>
#include <QCborStreamReader>
#include <QCborStreamWriter>
#define qs QStringLiteral
int main(int argc, char *argv[]) {
qRegisterMetaType<Xybrid::Data::Port>();
// enable antialiasing on accelerated graphicsview
QSurfaceFormat fmt;
fmt.setSamples(10);
QSurfaceFormat::setDefaultFormat(fmt);
QApplication a(argc, argv);
QCommandLineParser cl;
cl.addHelpOption();
cl.addVersionOption();
cl.addPositionalArgument("[project...]", QApplication::translate("main", "Project file(s) to open."));
cl.process(a);
auto args = cl.positionalArguments();
QString userName = qEnvironmentVariable("USER");
if (userName.isEmpty()) userName = qEnvironmentVariable("USERNAME");
QString socketName = qs("xybrid-ipc-%1").arg(userName);
QLocalSocket tryc;
tryc.connectToServer(socketName);
tryc.waitForConnected(1000); // wait for connection attempt (can't hang on local)
if (tryc.isOpen()) { // if server already exists, give it the signal and exit
QCborArray root;
root << "open";
QCborArray lst;
for (auto& fn : args) {
QFileInfo fi(fn);
if (!fi.exists()) continue;
lst << fi.absoluteFilePath();
}
root << lst;
QCborStreamWriter csw(&tryc);
root.toCborValue().toCbor(csw);
tryc.waitForBytesWritten();
tryc.close();
return 0;
}
QLocalServer srv;
srv.setSocketOptions(QLocalServer::UserAccessOption);
srv.removeServer(socketName); // if it exists and we're here, previous instance probably crashed or was killed
srv.listen(socketName);
QObject::connect(&srv, &QLocalServer::newConnection, &srv, [&]() {
auto s = srv.nextPendingConnection();
s->waitForDisconnected();
QCborStreamReader csr(s);
auto root = QCborValue::fromCbor(csr).toArray();
s->deleteLater();
auto cmd = root.at(0).toString();
if (cmd == "open") {
auto lst = root.at(1).toArray();
if (lst.isEmpty()) {
auto w = new Xybrid::MainWindow(nullptr);
w->show();
}
for (auto e : lst) {
QFileInfo fi(e.toString());
if (!fi.exists()) continue;
auto fileName = fi.absoluteFilePath();
if (auto w = Xybrid::MainWindow::projectWindow(fileName); w) w->tryFocus();
else {
w = new Xybrid::MainWindow(nullptr, fileName);
if (w->getProject()) w->show();
else (w->deleteLater());
}
}
}
});
// make sure bundled fonts are loaded
QFontDatabase::addApplicationFont(":/fonts/iosevka-term-light.ttf");
QFontDatabase::addApplicationFont(":/fonts/Arcon-Rounded-Regular.otf");
Xybrid::FileOps::loadConfig();
Xybrid::FileOps::loadUIState();
Xybrid::Config::PluginRegistry::init();
Xybrid::Audio::AudioEngine::init();
Xybrid::Util::reserveInitialPool(); // reserve arena pool ahead of time
bool opn = false;
for (auto& fn : args) {
QFileInfo fi(fn);
if (!fi.exists()) continue;
auto fileName = fi.absoluteFilePath();
auto w = new Xybrid::MainWindow(nullptr, fileName);
if (w->getProject()) { w->show(); opn = true; }
else (w->deleteLater());
}
if (!opn) { // always show one window on launch
auto w = new Xybrid::MainWindow(nullptr);
w->show();
}
// hook up exit event
QObject::connect(&a, &QCoreApplication::aboutToQuit, [] {
Xybrid::FileOps::saveConfig();
});
return a.exec();
}