#include "graph_engine.h" #include "web_server.h" #include #include #include #include #include static std::atomic g_running(true); static void signal_handler(int sig) { g_running = false; fprintf(stderr, "\npwweb: caught signal %d, shutting down...\n", sig); } int main(int argc, char *argv[]) { int port = 9876; // Parse optional port argument if (argc > 1) { port = atoi(argv[1]); if (port <= 0 || port > 65535) { fprintf(stderr, "usage: pwweb [port]\n"); return 1; } } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); pwgraph::GraphEngine engine; fprintf(stderr, "pwweb: connecting to PipeWire...\n"); if (!engine.open()) { fprintf(stderr, "pwweb: failed to connect to PipeWire.\n"); fprintf(stderr, " Make sure XDG_RUNTIME_DIR is set: export XDG_RUNTIME_DIR=/run/user/$(id -u)\n"); return 1; } pwgraph::WebServer server(engine, port); // Wire change notifications to broadcast engine.setOnChange([&server]() { server.broadcastGraph(); }); if (!server.start()) { fprintf(stderr, "pwweb: failed to start web server on port %d\n", port); engine.close(); return 1; } fprintf(stderr, "pwweb: server running at http://localhost:%d\n", port); fprintf(stderr, "pwweb: API at http://localhost:%d/api/graph\n", port); fprintf(stderr, "pwweb: press Ctrl+C to stop\n"); // Main loop — just wait for shutdown signal while (g_running) { std::this_thread::sleep_for(std::chrono::milliseconds(200)); } fprintf(stderr, "pwweb: shutting down...\n"); server.stop(); engine.close(); fprintf(stderr, "pwweb: goodbye.\n"); return 0; }