#include "mainwindow.h" #include "audio/audioengine.h" #include "config/pluginregistry.h" #include "data/graph.h" #include "fileops.h" #include "util/mem.h" #include #include #include #include #include #include #include #include #include #include #include #include #define qs QStringLiteral int main(int argc, char *argv[]) { qRegisterMetaType(); // 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(); }