looper/playback_process.hpp
2024-09-06 10:06:32 -07:00

114 lines
4.6 KiB
C++

#pragma once
#include <any>
#include <mutex>
#include <atomic>
#include <stdint.h>
#include <thread>
#include <string>
#include <vector>
#include "thirdparty/CRC.hpp"
#include "playback_backend.hpp"
#include <grpc/grpc.h>
#include <grpcpp/security/server_credentials.h>
#include <grpcpp/server.h>
#include <grpcpp/server_builder.h>
#include <grpcpp/server_context.h>
#include "rpc.hpp"
#include <google/protobuf/stubs/status.h>
#include "ipc/common.pb.h"
#include "ipc/internal.pb.h"
#include "ipc/internal.grpc.pb.h"
#include <log.hpp>
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<class T>
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;
bool is_playback_process = false;
bool done;
std::optional<IPCChannel<HostProcess, PlaybackProcessService>> host_channel;
std::optional<IPCChannel<PlaybackProcessService, HostProcess>> playback_process_channel;
inline std::unique_ptr<PlaybackProcessService::Stub> get_stub() {
return host_channel.value().get_stub();
}
std::string get_version_code();
PropertyData get_property(PropertyId id, std::optional<uint64_t> idx = {});
inline google::protobuf::Any get_property_value_any(PropertyId id, std::optional<uint64_t> idx = {}) {
PropertyData data = get_property(id, idx);
return data.value();
}
template<class T>
inline T *get_property_value(PropertyId id, std::optional<uint64_t> idx = {}) {
if constexpr (std::is_same_v<T, std::string>) {
auto *property = get_property_value<StringProperty>(id, idx);
std::string *tmp = new std::string(property->value());
delete property;
return tmp;
} else {
return resolve_any<T>(get_property_value_any(id, idx));
}
}
inline std::string get_property_string(PropertyId id, std::optional<uint64_t> idx = {}) {
auto *property = get_property_value<StringProperty>(id, idx);
std::string output = std::string(property->value());
delete property;
return output;
}
void set_property(PropertyId id, PropertyData data, std::optional<uint64_t> idx = {});
template<class T>
inline void set_property_value(PropertyId id, T *value, std::optional<uint64_t> idx = {}) {
PropertyData data;
data.mutable_value()->PackFrom(*value);
set_property(id, data, idx);
}
friend int looper_run_playback_process(std::vector<std::string> args);
PlaybackProcess(std::vector<std::string> 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<PlaybackStream> get_playback_streams();
AudioSpec *get_audio_spec();
size_t render(void *buf, size_t maxlen);
std::optional<google::protobuf::Any> get_property(std::string path);
bool set_property(std::string path, google::protobuf::Any value);
PlaybackProcess(std::string filename, int idx = 0);
~PlaybackProcess();
};