#pragma once #include #include #include #include #include #include #include #include #include #include "thirdparty/CRC.hpp" #include "playback_backend.hpp" #include #include #include #include #include #include "rpc.hpp" #include "ipc/common.pb.h" #include "ipc/internal.pb.h" #include "ipc/internal.grpc.pb.h" #include class PlaybackProcess; class PlaybackProcessServiceImpl : public PlaybackProcessService::Service { PlaybackBackend *cur_backend; public: PlaybackProcess *process; grpc::Status Init(grpc::ServerContext *ctx, const InitCommand *cmd, MaybeError *response) override; grpc::Status Render(grpc::ServerContext *context, const RenderCommand *cmd, RenderResponseOrError *response) override; grpc::Status Get(grpc::ServerContext *ctx, const GetProperty *request, PropertyDataOrError *response) override; grpc::Status Set(grpc::ServerContext *ctx, const SetProperty *request, MaybeError *err) override; grpc::Status Reset(grpc::ServerContext *ctx, const ResetProperty *request, ResetResponse *response) override; grpc::Status Quit(grpc::ServerContext *ctx, const QuitCmd *request, MaybeError *response) override; }; class HostProcessImpl : public HostProcess::Service { public: PlaybackProcess *process; grpc::Status WriteLog(grpc::ServerContext *ctx, const LogMessage *msg, SimpleAckResponse *response) override; grpc::Status SetAddress(grpc::ServerContext *ctx, const StringProperty *data, MaybeError *response) override; }; 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 pid; std::mutex start_mutex; std::condition_variable started; bool is_playback_process = false; std::atomic_bool done; std::optional> host_channel; std::optional> playback_process_channel; inline std::unique_ptr get_stub() { return host_channel.value().get_stub(); } 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 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); } friend int looper_run_playback_process(std::vector args); PlaybackProcess(std::vector args); void run_playback_process(); public: bool process_running(); double get_position(); 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(); 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(); };