#pragma once #include "graph_types.h" #include #include #include #include #include #include #include // pw_thread_loop, etc. #include // spa_list #include // spa_hook struct pw_thread_loop; struct pw_context; struct pw_core; struct pw_registry; namespace pwgraph { class GraphEngine { public: using ChangeCallback = std::function; 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 nodes; std::vector ports; std::vector 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); // Volume control bool setNodeVolume(uint32_t node_id, float volume); bool setNodeMute(uint32_t node_id, bool mute); // Module loading (virtual devices) uint32_t loadModule(const char *name, const char *args); bool unloadModule(uint32_t module_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; GraphEngine *engine_ref; // back-pointer set in create_proxy_for_object 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 m_objects_by_id; std::vector m_objects; ChangeCallback m_on_change; std::atomic 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