#pragma once #include #include #include #include #include #include #include #include #include #include #include #include "thirdparty/CRC.hpp" #include "playback_backend.hpp" #include "rpc.hpp" #include #include #include #include "options.hpp" #include "util.hpp" class PlaybackProcess; class PlaybackProcessServiceImpl { Lock cur_backend_lock; Lock render_ptr; public: PlaybackProcess *process; RenderResponseOrError Render(const RenderCommand *cmd); PropertyDataOrError Get(const GetProperty *request); MaybeError Set(const SetProperty *request); ResetResponse Reset(const ResetProperty *request); MaybeError Quit(const QuitCmd *request); MaybeError Init(const InitCommand *cmd); }; template inline T *resolve_any(google::protobuf::Any value) { T *output = new T(); value.UnpackTo(output); return output; } //#define DEBUG_PRINT_IPC void print_ipc_message(const google::protobuf::Message &msg, size_t level = 0); class PlaybackProcess { friend class HostProcessImpl; friend class PlaybackProcessServiceImpl; void threadfunc(); int send_fd; int recv_fd; bool multi_process = false; PlaybackProcess *other_process = nullptr; PlaybackProcessServiceImpl impl; int pid; bool init_failed = false; std::mutex start_mutex; std::condition_variable started; bool is_playback_process = false; std::atomic_bool done; RPCResponse handle_command(RPCCall &msg); RPCResponse SendCommand(RPCCall *msg); std::string get_version_code(); PropertyData get_property(PropertyId id, std::optional idx = {}); inline google::protobuf::Any get_property_value_any(PropertyId id, std::optional idx = {}) { PropertyData data = get_property(id, idx); return data.value(); } template inline T *get_property_value(PropertyId id, std::optional idx = {}) { if constexpr (std::is_same_v) { auto *property = get_property_value(id, idx); std::string *tmp = new std::string(property->value()); delete property; return tmp; } else { return resolve_any(get_property_value_any(id, idx)); } } inline double get_property_double(PropertyId id, std::optional idx = {}) { auto *property = get_property_value(id, idx); double output = double(property->value()); delete property; return output; } inline std::string get_property_string(PropertyId id, std::optional idx = {}) { auto *property = get_property_value(id, idx); std::string output = std::string(property->value()); delete property; return output; } void set_property(PropertyId id, PropertyData data, std::optional idx = {}); template inline void set_property_value(PropertyId id, T *value, std::optional idx = {}) { PropertyData data; data.mutable_value()->PackFrom(*value); set_property(id, data, idx); } inline void set_property_double(PropertyId id, double value, std::optional idx = {}) { PropertyData data; DoubleProperty property; property.set_value(value); data.mutable_value()->PackFrom(property); set_property(id, data, idx); } friend int looper_run_playback_process(std::vector args); PlaybackProcess(PlaybackProcess *parent); PlaybackProcess(std::vector args); void run_playback_process(); public: bool process_running(); double get_position(); double get_length(); void set_position(double pos); size_t get_stream_idx(); void set_stream_idx(size_t idx); std::string get_title(); std::string get_file_path(); std::string get_file_name(); std::string get_backend_id(); double get_cached_rate(); void set_rate(double value); std::string get_backend_name(); PlaybackStream get_playback_stream(size_t idx); std::vector get_playback_streams(); AudioSpec *get_audio_spec(); size_t render(void *buf, size_t maxlen); std::optional get_property(std::string path); bool set_property(std::string path, google::protobuf::Any value); PlaybackProcess(std::string filename, int idx = 0); ~PlaybackProcess(); };