111 lines
No EOL
3.6 KiB
C++
111 lines
No EOL
3.6 KiB
C++
#pragma once
|
|
#include <vector>
|
|
#include <string>
|
|
#include <map>
|
|
#include <optional>
|
|
#include <atomic>
|
|
#include "playback.h"
|
|
#include "dbus.hpp"
|
|
class UIBackend {
|
|
protected:
|
|
std::vector<std::string> args;
|
|
Playback *playback;
|
|
std::atomic_bool exit_flag = false;
|
|
double new_speed = 1.0;
|
|
double new_tempo = 1.0;
|
|
double new_pitch = 1.0;
|
|
bool speed_set = false;
|
|
bool tempo_set = false;
|
|
bool pitch_set = false;
|
|
bool multi_instance = false;
|
|
bool daemon_found = false;
|
|
public:
|
|
DBusAPI *dbus_api;
|
|
inline virtual bool allow_multi_instance() {
|
|
return true;
|
|
}
|
|
virtual std::string get_id();
|
|
virtual std::string get_name();
|
|
UIBackend() = default;
|
|
/// @brief A hook to add any licenses of software packages used by the UI backend.
|
|
inline virtual void add_licenses() {
|
|
// Don't add any here, but leave this specified. That way, licenses specific to UI frontends are only added per UI frontend.
|
|
}
|
|
void init_libportal();
|
|
void init_playback();
|
|
void setup_playback_args();
|
|
void init_dbus();
|
|
bool parse_args(std::vector<std::string> realArgs, int argc, char **argv);
|
|
/// @brief The main loop of the UI. Be sure to call @ref UIBackend::run and be prepared for it to throw an integer exit code that needs to escape your implementation.
|
|
virtual int run(std::vector<std::string> realArgs, int argc, char **argv);
|
|
/// @brief A hook that is called when the D-Bus API receives a request to exit the program.
|
|
inline virtual void QuitHandler() {
|
|
// Set a flag for loops managed by the UI backend.
|
|
exit_flag.store(true);
|
|
}
|
|
static std::map<std::string, UIBackend*> backends;
|
|
template<class T>
|
|
static inline std::string get_backend_id() {
|
|
UIBackend *backend = new T();
|
|
auto output = backend->get_id();
|
|
delete backend;
|
|
return output;
|
|
}
|
|
static inline UIBackend* get_first_backend() {
|
|
if (backends.empty()) {
|
|
return nullptr;
|
|
}
|
|
return (*backends.begin()).second;
|
|
}
|
|
static void register_backend(UIBackend *backend) {
|
|
std::string backend_id = backend->get_id();
|
|
if (backends.contains(backend_id)) { // Guard against potential memory leak due to reassigning a new pointer without deallocating the previous one
|
|
delete backend;
|
|
return;
|
|
}
|
|
backends[backend_id] = backend;
|
|
}
|
|
template<class T>
|
|
static void register_backend() {
|
|
UIBackend *backend = new T();
|
|
backend->register_self();
|
|
}
|
|
static inline void unregister_backend(std::string id) {
|
|
if (backends.contains(id)) {
|
|
auto backend = backends[id];
|
|
delete backend;
|
|
backends.erase(id);
|
|
}
|
|
}
|
|
inline void unregister_self() {
|
|
UIBackend::unregister_backend(get_id());
|
|
}
|
|
inline void register_self() {
|
|
UIBackend::register_backend(this);
|
|
}
|
|
template<class T>
|
|
static void unregister_backend() {
|
|
unregister_backend(get_backend_id<T>());
|
|
}
|
|
static void deinit_backends();
|
|
static inline std::optional<UIBackend*> get_backend(std::string id) {
|
|
if (backends.contains(id)) {
|
|
return backends[id];
|
|
} else {
|
|
return {};
|
|
}
|
|
}
|
|
template<class T>
|
|
static inline std::optional<T*> get_backend() {
|
|
auto id = get_backend_id<T>();
|
|
auto output = get_backend(id);
|
|
if (output.has_value()) {
|
|
return (T*)output.value();
|
|
} else {
|
|
return {};
|
|
}
|
|
}
|
|
static UIBackend *running_ui_backend;
|
|
virtual ~UIBackend();
|
|
};
|
|
void init_backends(); |