Add struct for playback streams.

This commit is contained in:
Zachary Hall 2024-04-14 13:25:49 -07:00
parent 7ff0d40da3
commit cb4b884f89
10 changed files with 65 additions and 31 deletions

View file

@ -38,7 +38,7 @@
<method name="Stop" /> <method name="Stop" />
<method name="TogglePause" /> <method name="TogglePause" />
<method name="GetStreams"> <method name="GetStreams">
<arg name="streams" type="as" direction="out" /> <arg name="streams" type="a(dsi)" direction="out" />
</method> </method>
<method name="PlayStream"> <method name="PlayStream">
<arg name="idx" type="u" direction="in" /> <arg name="idx" type="u" direction="in" />

View file

@ -152,7 +152,7 @@ private:
virtual void Quit() = 0; virtual void Quit() = 0;
virtual void Stop() = 0; virtual void Stop() = 0;
virtual void TogglePause() = 0; virtual void TogglePause() = 0;
virtual std::vector<std::string> GetStreams() = 0; virtual std::vector<sdbus::Struct<double, std::string, int32_t>> GetStreams() = 0;
virtual void PlayStream(const uint32_t& idx) = 0; virtual void PlayStream(const uint32_t& idx) = 0;
private: private:

View file

@ -136,9 +136,9 @@ public:
proxy_->callMethod("TogglePause").onInterface(INTERFACE_NAME); proxy_->callMethod("TogglePause").onInterface(INTERFACE_NAME);
} }
std::vector<std::string> GetStreams() std::vector<sdbus::Struct<double, std::string, int32_t>> GetStreams()
{ {
std::vector<std::string> result; std::vector<sdbus::Struct<double, std::string, int32_t>> result;
proxy_->callMethod("GetStreams").onInterface(INTERFACE_NAME).storeResultsTo(result); proxy_->callMethod("GetStreams").onInterface(INTERFACE_NAME).storeResultsTo(result);
return result; return result;
} }

View file

@ -40,14 +40,13 @@ void MainWindow::update_file(optional<std::string> new_file) {
length_label.set_text("00:00"); length_label.set_text("00:00");
seek_bar.set_value(0.0); seek_bar.set_value(0.0);
} }
int i = 0;
for (auto row : stream_selection_box.get_children()) { for (auto row : stream_selection_box.get_children()) {
row->remove_data(Glib::Quark("id")); row->remove_data(Glib::Quark("id"));
} }
stream_selection_box.remove_all(); stream_selection_box.remove_all();
for (auto &stream : playback->get_streams()) { for (auto &stream : playback->get_streams()) {
int id = i++; int id = stream.id;
Glib::ustring name(stream.c_str()); Glib::ustring name(stream.name.c_str());
Gtk::Label idLabel; Gtk::Label idLabel;
idLabel.set_text(Glib::ustring(std::format("{}", id).c_str())); idLabel.set_text(Glib::ustring(std::format("{}", id).c_str()));
Gtk::Label nameLabel; Gtk::Label nameLabel;

View file

@ -168,16 +168,17 @@ void MainLoop::GuiFunction() {
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
for (int i = 0; i < streams.size(); i++) { for (int i = 0; i < streams.size(); i++) {
auto &stream = streams[i]; auto &stream = streams[i];
if (stream == "") { if (stream.name == "" && stream.length == 0) {
continue; continue;
} }
if (stream.starts_with(filter)) { if (stream.name.starts_with(filter)) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0); ImGui::TableSetColumnIndex(0);
ImGui::Text("%i", i); ImGui::Text("%i", stream.id);
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
const bool is_selected = playback->get_current_stream() == i; const bool is_selected = playback->get_current_stream() == i;
if (ImGui::Selectable(stream.c_str(), is_selected, 0)) { if (ImGui::Selectable(stream.name.c_str(), is_selected, 0)) {
length = stream.length;
playback->play_stream(i); playback->play_stream(i);
} }
if (is_selected) { if (is_selected) {

View file

@ -53,7 +53,7 @@ class MainLoop : public RendererBackend {
UIBackend *cur_backend; UIBackend *cur_backend;
friend class ImGuiUIBackend; friend class ImGuiUIBackend;
std::atomic_bool exit_flag; std::atomic_bool exit_flag;
std::vector<std::string> streams; std::vector<PlaybackStream> streams;
public: public:
Playback *playback; Playback *playback;
vector<std::string> args; vector<std::string> args;

View file

@ -405,8 +405,14 @@ std::vector<std::string> DBusAPI::GetAllAndClear(const std::string &handle) {
uint32_t DBusAPI::StreamIdx() { uint32_t DBusAPI::StreamIdx() {
return playback->get_current_stream(); return playback->get_current_stream();
} }
std::vector<std::string> DBusAPI::GetStreams() { std::vector<sdbus::Struct<double, std::string, int32_t>> DBusAPI::GetStreams() {
return playback->get_streams(); std::vector<sdbus::Struct<double, std::string, int32_t>> output;
auto streams = playback->get_streams();
for (auto stream : streams) {
sdbus::Struct<double, std::string, int32_t> tmp(stream.length, stream.name, stream.id);
output.push_back(tmp);
}
return output;
} }
void DBusAPI::PlayStream(const uint32_t &idx) { void DBusAPI::PlayStream(const uint32_t &idx) {
playback->play_stream((int)idx); playback->play_stream((int)idx);
@ -487,8 +493,17 @@ void DBusAPISender::Load(std::string filePath) {
int DBusAPISender::get_current_stream() { int DBusAPISender::get_current_stream() {
return (int)ProxyInterfaces::StreamIdx(); return (int)ProxyInterfaces::StreamIdx();
} }
std::vector<std::string> DBusAPISender::get_streams() { std::vector<PlaybackStream> DBusAPISender::get_streams() {
return ProxyInterfaces::GetStreams(); std::vector<PlaybackStream> output;
auto input = ProxyInterfaces::GetStreams();
for (auto stream : input) {
PlaybackStream tmp;
tmp.length = stream.get<0>();
tmp.name = stream.get<1>();
tmp.id = stream.get<2>();
output.push_back(tmp);
}
return output;
} }
bool DBusAPISender::IsPaused() { bool DBusAPISender::IsPaused() {
return ProxyInterfaces::Paused(); return ProxyInterfaces::Paused();

View file

@ -161,7 +161,7 @@ class DBusAPI : public sdbus::AdaptorInterfaces<com::complecwaft::Looper_adaptor
bool IsDaemon() override; bool IsDaemon() override;
void Quit() override; void Quit() override;
uint32_t StreamIdx() override; uint32_t StreamIdx() override;
std::vector<std::string> GetStreams() override; std::vector<sdbus::Struct<double, std::string, int32_t>> GetStreams() override;
void PlayStream(const uint32_t &idx) override; void PlayStream(const uint32_t &idx) override;
// API // API
@ -229,7 +229,7 @@ class DBusAPISender : public Playback, public sdbus::ProxyInterfaces<com::comple
float GetVolume() override; float GetVolume() override;
int get_current_stream() override; int get_current_stream() override;
void Load(std::string filePath) override; void Load(std::string filePath) override;
std::vector<std::string> get_streams() override; std::vector<PlaybackStream> get_streams() override;
// Constructors and destructors. // Constructors and destructors.
// The constructor is protected because there is a different API that should be used for creation. // The constructor is protected because there is a different API that should be used for creation.
protected: protected:

View file

@ -183,23 +183,37 @@ VGMSTREAM *PlaybackInstance::LoadVgm(const char *file, int idx) {
close_vgmstream(output); close_vgmstream(output);
stream_list_mutex.lock(); stream_list_mutex.lock();
streams.clear(); streams.clear();
streams.push_back("Default"); PlaybackStream defaultStream;
for (int i = 1; i <= stream_count; i++) { defaultStream.id = 0;
defaultStream.name = "Default";
streams.push_back(defaultStream);
for (int i = 0; i <= stream_count; i++) {
PlaybackStream stream;
stream.id = i;
stream.length = 0;
stream.name = "";
if (!sf) { if (!sf) {
streams.push_back(""); streams.push_back(stream);
continue; continue;
} }
sf->stream_index = i; sf->stream_index = i;
auto *tmp = init_vgmstream_from_STREAMFILE(sf); auto *tmp = init_vgmstream_from_STREAMFILE(sf);
if (!tmp) { if (!tmp) {
streams.push_back(""); streams.push_back(stream);
continue; continue;
} }
reset_vgmstream(tmp); reset_vgmstream(tmp);
stream.length = (double)tmp->num_samples / (double)tmp->sample_rate;
char *buf = (char*)malloc(STREAM_NAME_SIZE + 1); char *buf = (char*)malloc(STREAM_NAME_SIZE + 1);
memset(buf, 0, STREAM_NAME_SIZE + 1); memset(buf, 0, STREAM_NAME_SIZE + 1);
strncpy(buf, tmp->stream_name, STREAM_NAME_SIZE); strncpy(buf, tmp->stream_name, STREAM_NAME_SIZE);
streams.push_back(buf);
if (i == 0) {
stream.name = std::format("Default ({})", buf);
} else {
stream.name = buf;
}
free(buf); free(buf);
close_vgmstream(tmp); close_vgmstream(tmp);
} }
@ -222,7 +236,7 @@ VGMSTREAM *PlaybackInstance::LoadVgm(const char *file, int idx) {
vgmstream_spec.channels = output->channels; vgmstream_spec.channels = output->channels;
vgmstream_spec.freq = output->sample_rate; vgmstream_spec.freq = output->sample_rate;
length = (double)output->num_samples / (double)output->sample_rate; length = streams[idx].length;
update.store(true); update.store(true);
current_file_mutex.lock(); current_file_mutex.lock();
current_file = std::string(file); current_file = std::string(file);
@ -379,7 +393,7 @@ void PlaybackInstance::ThreadFunc() {
} }
if (stream_changed.exchange(false)) { if (stream_changed.exchange(false)) {
std::string file = current_file.value(); std::string file = current_file.value();
if (streams[current_stream] == "" || current_stream < 0 || current_stream >= streams.size()) { if (streams[current_stream].name == "" || streams[current_stream].length <= 0 || current_stream < 0 || current_stream >= streams.size()) {
if (stream != nullptr) { if (stream != nullptr) {
current_stream = stream->stream_index; current_stream = stream->stream_index;
} else { } else {
@ -718,8 +732,8 @@ Playback *Playback::Create(bool *daemon_found, bool daemon) {
DEBUG.writeln("Creating new playback instance."); DEBUG.writeln("Creating new playback instance.");
return new PlaybackInstance(); return new PlaybackInstance();
} }
std::vector<std::string> PlaybackInstance::get_streams() { std::vector<PlaybackStream> PlaybackInstance::get_streams() {
std::vector<std::string> output; std::vector<PlaybackStream> output;
for (auto stream : streams) { for (auto stream : streams) {
output.push_back(stream); output.push_back(stream);
} }

View file

@ -46,6 +46,11 @@ enum {
/// @brief Playback has started. If @ref PlaybackSignalStopped has also been signalled, call @ref Playback::IsStopped to find out if playback is currently playing. /// @brief Playback has started. If @ref PlaybackSignalStopped has also been signalled, call @ref Playback::IsStopped to find out if playback is currently playing.
PlaybackSignalStarted = 1 << 9 PlaybackSignalStarted = 1 << 9
}; };
struct PlaybackStream {
double length;
std::string name;
int id;
};
/// @brief Playback handler base class. /// @brief Playback handler base class.
class Playback { class Playback {
protected: protected:
@ -83,8 +88,8 @@ class Playback {
inline virtual int get_current_stream() { inline virtual int get_current_stream() {
return 0; return 0;
} }
inline virtual std::vector<std::string> get_streams() { inline virtual std::vector<PlaybackStream> get_streams() {
std::vector<std::string> output; std::vector<PlaybackStream> output;
return output; return output;
} }
inline virtual void play_stream(int idx) {} inline virtual void play_stream(int idx) {}
@ -222,7 +227,7 @@ private:
void UnloadMix(Mix_Music* music); void UnloadMix(Mix_Music* music);
void UnloadVgm(VGMSTREAM *stream); void UnloadVgm(VGMSTREAM *stream);
VGMSTREAM *stream; VGMSTREAM *stream;
std::vector<std::string> streams; std::vector<PlaybackStream> streams;
std::mutex stream_list_mutex; std::mutex stream_list_mutex;
double real_volume = 1.0; double real_volume = 1.0;
void ThreadFunc(); void ThreadFunc();
@ -244,7 +249,7 @@ public:
inline bool is_proxy() override { inline bool is_proxy() override {
return false; return false;
} }
std::vector<std::string> get_streams() override; std::vector<PlaybackStream> get_streams() override;
void play_stream(int idx) override; void play_stream(int idx) override;
void Load(std::string filePath) override; void Load(std::string filePath) override;
double GetPosition() override; double GetPosition() override;