Initial commit: pwweb - PipeWire WebUI
C++ backend with SSE streaming (reuses qpwgraph PipeWire callbacks). Svelte frontend with custom SVG canvas for port-level connections. Features: - Live PipeWire graph via SSE - Drag output->input port to connect - Double-click or select+Delete to disconnect - Node positions saved to localStorage - Pan (drag bg) and zoom (scroll) - Port type coloring (audio=green, midi=red, video=blue)
This commit is contained in:
131
src/graph_engine.h
Normal file
131
src/graph_engine.h
Normal file
@@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#include "graph_types.h"
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
|
||||
#include <pipewire/utils.h> // pw_thread_loop, etc.
|
||||
#include <spa/utils/list.h> // spa_list
|
||||
#include <spa/utils/hook.h> // spa_hook
|
||||
|
||||
struct pw_thread_loop;
|
||||
struct pw_context;
|
||||
struct pw_core;
|
||||
struct pw_registry;
|
||||
|
||||
namespace pwgraph {
|
||||
|
||||
class GraphEngine {
|
||||
public:
|
||||
using ChangeCallback = std::function<void()>;
|
||||
|
||||
GraphEngine();
|
||||
~GraphEngine();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
|
||||
// Set callback invoked when graph changes
|
||||
void setOnChange(ChangeCallback cb);
|
||||
|
||||
// Thread-safe snapshot of the current graph state
|
||||
struct Snapshot {
|
||||
std::vector<Node> nodes;
|
||||
std::vector<Port> ports;
|
||||
std::vector<Link> links;
|
||||
};
|
||||
Snapshot snapshot() const;
|
||||
|
||||
// Connect/disconnect two ports (thread-safe, blocks until done)
|
||||
bool connectPorts(uint32_t output_port_id, uint32_t input_port_id);
|
||||
bool disconnectPorts(uint32_t output_port_id, uint32_t input_port_id);
|
||||
|
||||
// PipeWire internal data (exposed for C callbacks)
|
||||
struct PwData {
|
||||
pw_thread_loop *loop;
|
||||
pw_context *context;
|
||||
pw_core *core;
|
||||
spa_hook core_listener;
|
||||
pw_registry *registry;
|
||||
spa_hook registry_listener;
|
||||
int pending_seq;
|
||||
spa_list pending; // doubly-linked list head for pending syncs
|
||||
int last_seq;
|
||||
int last_res;
|
||||
bool error;
|
||||
};
|
||||
|
||||
PwData& pwData() { return m_pw; }
|
||||
|
||||
// Object management (called from C callbacks)
|
||||
struct Object {
|
||||
enum Type { ObjNode, ObjPort, ObjLink };
|
||||
uint32_t id;
|
||||
Type type;
|
||||
void *proxy;
|
||||
void *info;
|
||||
void (*destroy_info)(void*);
|
||||
spa_hook proxy_listener;
|
||||
spa_hook object_listener;
|
||||
int pending_seq;
|
||||
spa_list pending_link;
|
||||
|
||||
Object(uint32_t id, Type type);
|
||||
virtual ~Object();
|
||||
};
|
||||
|
||||
struct NodeObj : Object {
|
||||
NodeObj(uint32_t id) : Object(id, ObjNode) {}
|
||||
Node node;
|
||||
};
|
||||
|
||||
struct PortObj : Object {
|
||||
PortObj(uint32_t id) : Object(id, ObjPort) {}
|
||||
Port port;
|
||||
};
|
||||
|
||||
struct LinkObj : Object {
|
||||
LinkObj(uint32_t id) : Object(id, ObjLink) {}
|
||||
Link link;
|
||||
};
|
||||
|
||||
void addObject(uint32_t id, Object *obj);
|
||||
Object *findObject(uint32_t id) const;
|
||||
void removeObject(uint32_t id);
|
||||
void clearObjects();
|
||||
|
||||
NodeObj *findNode(uint32_t node_id) const;
|
||||
PortObj *findPort(uint32_t port_id) const;
|
||||
LinkObj *findLink(uint32_t link_id) const;
|
||||
|
||||
void notifyChanged();
|
||||
|
||||
private:
|
||||
PwData m_pw;
|
||||
|
||||
mutable std::mutex m_mutex; // protects m_objects and graph data
|
||||
std::unordered_map<uint32_t, Object*> m_objects_by_id;
|
||||
std::vector<Object*> m_objects;
|
||||
|
||||
ChangeCallback m_on_change;
|
||||
std::atomic<bool> m_running;
|
||||
|
||||
// Port type hashes
|
||||
uint32_t m_audio_type;
|
||||
uint32_t m_midi_type;
|
||||
uint32_t m_midi2_type;
|
||||
uint32_t m_video_type;
|
||||
uint32_t m_other_type;
|
||||
|
||||
public:
|
||||
uint32_t audioPortType() const { return m_audio_type; }
|
||||
uint32_t midiPortType() const { return m_midi_type; }
|
||||
uint32_t videoPortType() const { return m_video_type; }
|
||||
uint32_t otherPortType() const { return m_other_type; }
|
||||
};
|
||||
|
||||
} // namespace pwgraph
|
||||
Reference in New Issue
Block a user