From cd694d06b76bcbcf88d209877bfcc1e05ac7a866 Mon Sep 17 00:00:00 2001 From: Nanako <469449812@qq.com> Date: Tue, 4 Jun 2024 13:52:39 +0800 Subject: [PATCH] =?UTF-8?q?mixer=5Ftrack=E6=95=88=E6=9E=9C=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Arona/src/widget/main_window.cpp | 1 + Arona/src/widget/main_window.h | 3 +- Arona/src/widget/misc/w_audio_buffer_bar.cpp | 3 +- Arona/src/widget/misc/w_volume_bar.h | 7 ++- Arona/src/widget/mixer/w_effect_item.cpp | 53 +++++++++++++++++ Arona/src/widget/mixer/w_effect_item.h | 54 +++++++++++++++++ Arona/src/widget/mixer/w_effect_list.cpp | 62 ++++++++++++++++++++ Arona/src/widget/mixer/w_effect_list.h | 43 ++++++++++++++ Arona/src/widget/mixer/w_mixer_list.cpp | 31 +++++----- Arona/src/widget/mixer/w_mixer_list.h | 14 +++-- AronaCore | 2 +- 11 files changed, 247 insertions(+), 26 deletions(-) create mode 100644 Arona/src/widget/mixer/w_effect_item.cpp create mode 100644 Arona/src/widget/mixer/w_effect_item.h create mode 100644 Arona/src/widget/mixer/w_effect_list.cpp create mode 100644 Arona/src/widget/mixer/w_effect_list.h diff --git a/Arona/src/widget/main_window.cpp b/Arona/src/widget/main_window.cpp index ed8a30d..adaf59c 100644 --- a/Arona/src/widget/main_window.cpp +++ b/Arona/src/widget/main_window.cpp @@ -12,5 +12,6 @@ void main_window::on_click() { bool main_window::on_close_request() { get_arona_application()->shutdown(); + connection_.empty(); return Window::on_close_request(); } diff --git a/Arona/src/widget/main_window.h b/Arona/src/widget/main_window.h index 07e8b49..f3d85b1 100644 --- a/Arona/src/widget/main_window.h +++ b/Arona/src/widget/main_window.h @@ -7,7 +7,7 @@ public: main_window() { box_ = Gtk::Box(Gtk::Orientation::VERTICAL); button_ = Gtk::Button("Hello, World!"); - button_.signal_clicked().connect(mem_fun(*this, &main_window::on_click)); + connection_ = button_.signal_clicked().connect(mem_fun(*this, &main_window::on_click)); box_.append(button_); box_.append(mixer_list_); @@ -23,4 +23,5 @@ private: Gtk::Box box_; Gtk::Button button_; w_mixer_list mixer_list_; + sigc::connection connection_; }; diff --git a/Arona/src/widget/misc/w_audio_buffer_bar.cpp b/Arona/src/widget/misc/w_audio_buffer_bar.cpp index d0e43e8..c233c37 100644 --- a/Arona/src/widget/misc/w_audio_buffer_bar.cpp +++ b/Arona/src/widget/misc/w_audio_buffer_bar.cpp @@ -7,7 +7,8 @@ #include "tool/delta_timer.h" w_audio_buffer_bar::w_audio_buffer_bar() { - timer_ = std::make_shared<delta_timer>(mem_fun(*this, &w_audio_buffer_bar::on_timer), 1000.f / get_arona_application()->get_screen_refresh_rate()); + float Interval = 1000.f / get_arona_application()->get_screen_refresh_rate(); + timer_ = std::make_shared<delta_timer>(mem_fun(*this, &w_audio_buffer_bar::on_timer), Interval); } void w_audio_buffer_bar::set_buffers(weak_buffer in_buffers) { diff --git a/Arona/src/widget/misc/w_volume_bar.h b/Arona/src/widget/misc/w_volume_bar.h index 253bc45..15d84f2 100644 --- a/Arona/src/widget/misc/w_volume_bar.h +++ b/Arona/src/widget/misc/w_volume_bar.h @@ -1,15 +1,18 @@ #pragma once #include "gtkmm/drawingarea.h" +#include "extern.h" class w_volume_bar : public Gtk::DrawingArea { public: explicit w_volume_bar(bool vertical = false); - void set_value(double value) { + void set_value(sample_t value) { + if (value_ == value) + return; value_ = value; queue_draw(); } const bool is_vertical; private: void on_draw(const Cairo::RefPtr<Cairo::Context>& cr, int width, int height); - double value_ = 0.; + sample_t value_ = 0.; }; diff --git a/Arona/src/widget/mixer/w_effect_item.cpp b/Arona/src/widget/mixer/w_effect_item.cpp new file mode 100644 index 0000000..f855125 --- /dev/null +++ b/Arona/src/widget/mixer/w_effect_item.cpp @@ -0,0 +1,53 @@ +#include "w_effect_item.h" +#include "audio/plugin_host/plugin_host.h" + +void w_effect_item::set_effect(plugin_host* in_effect) { + effect_ = in_effect; + effect_name_.set_label(effect_->name); + data_model_->remove_all(); + uint32_t param_count = in_effect->get_param_count(); + for (int i = 0; i < param_count; ++i) { + auto model_data = effect_value_model::create(in_effect, i); + if (model_data->is_valid()) + data_model_->append(model_data); + } +} + +w_effect_item::w_effect_item() : Gtk::Box(Gtk::Orientation::VERTICAL) { + data_model_ = Gio::ListStore<effect_value_model>::create(); + selection_model_ = Gtk::SingleSelection::create(data_model_); + selection_model_->set_autoselect(true); + + factory_ = Gtk::SignalListItemFactory::create(); + factory_->signal_setup().connect(mem_fun(*this, &w_effect_item::on_setup_value_widget)); + factory_->signal_bind().connect(mem_fun(*this, &w_effect_item::on_bind_value_widget)); + + list_view_.set_model(selection_model_); + list_view_.set_factory(factory_); + list_view_.set_orientation(Gtk::Orientation::VERTICAL); + + append(effect_name_); + append(list_view_); +} + +void w_effect_item::on_setup_value_widget(const Glib::RefPtr<Gtk::ListItem>& item) { + const auto widget = Gtk::make_managed<w_effect_value>(); + item->set_child(*widget); +} + +void w_effect_item::on_bind_value_widget(const Glib::RefPtr<Gtk::ListItem>& item) { + const auto index = item->get_position(); + if (auto* widget = dynamic_cast<w_effect_value*>(item->get_child())) { + auto data = data_model_->get_item(index); + widget->set_value(data); + } +} + +void w_effect_value::set_value(const Glib::RefPtr<effect_value_model>& in_param) { + param_ = in_param; + param_name_.set_label(in_param->get_name()); +} + +w_effect_value::w_effect_value() : Gtk::Box(Gtk::Orientation::HORIZONTAL) { + append(param_name_); +} diff --git a/Arona/src/widget/mixer/w_effect_item.h b/Arona/src/widget/mixer/w_effect_item.h new file mode 100644 index 0000000..f304453 --- /dev/null +++ b/Arona/src/widget/mixer/w_effect_item.h @@ -0,0 +1,54 @@ +#pragma once +#include <gtkmm/box.h> +#include <gtkmm/listview.h> +#include <giomm/liststore.h> +#include <gtkmm/singleselection.h> +#include <gtkmm/signallistitemfactory.h> +#include <gtkmm/label.h> +#include "audio/plugin_host/host_param.h" + +class plugin_host; + +class effect_value_model : public Glib::Object { +public: + host_param param; + bool is_valid() const { + return param.is_valid(); + } + const std::string& get_name() const { + return param.get_name(); + } + static Glib::RefPtr<effect_value_model> create(plugin_host* in_effect, int32_t index) { + return Glib::make_refptr_for_instance(new effect_value_model(in_effect, index)); + } +private: + explicit effect_value_model(plugin_host* in_effect, int32_t index) : param(in_effect, index) {} +}; + +class w_effect_value : public Gtk::Box { +public: + w_effect_value(); + void set_value(const Glib::RefPtr<effect_value_model>& in_param); +private: + Glib::RefPtr<effect_value_model> param_; + + Gtk::Label param_name_; +}; + +class w_effect_item : public Gtk::Box { +public: + w_effect_item(); + void set_effect(plugin_host* in_effect); +protected: + void on_setup_value_widget(const Glib::RefPtr<Gtk::ListItem>& item); + void on_bind_value_widget(const Glib::RefPtr<Gtk::ListItem>& item); +private: + plugin_host* effect_; + + Glib::RefPtr<Gio::ListStore<effect_value_model>> data_model_; + Glib::RefPtr<Gtk::SingleSelection> selection_model_; + Glib::RefPtr<Gtk::SignalListItemFactory> factory_; + + Gtk::Label effect_name_; + Gtk::ListView list_view_; +}; diff --git a/Arona/src/widget/mixer/w_effect_list.cpp b/Arona/src/widget/mixer/w_effect_list.cpp new file mode 100644 index 0000000..ac245f5 --- /dev/null +++ b/Arona/src/widget/mixer/w_effect_list.cpp @@ -0,0 +1,62 @@ +#include "w_effect_list.h" +#include "audio/mixer/mixer_track.h" +#include "w_effect_item.h" +#include "audio/plugin_host/plugin_host_manager.h" + +w_effect_list::w_effect_list() : Gtk::Box(Gtk::Orientation::HORIZONTAL), mixer_track_(nullptr) { + { + add_effect_.set_label("add_new_effect"); + add_effect_.signal_clicked().connect(mem_fun(*this, &w_effect_list::add_new_effect)); + } + + data_model_ = Gio::ListStore<mixer_effect_model>::create(); + selection_model_ = Gtk::SingleSelection::create(data_model_); + selection_model_->set_autoselect(true); + + factory_ = Gtk::SignalListItemFactory::create(); + factory_->signal_setup().connect(mem_fun(*this, &w_effect_list::on_setup_effect_widget)); + factory_->signal_bind().connect(mem_fun(*this, &w_effect_list::on_bind_effect_widget)); + + list_view_.set_model(selection_model_); + list_view_.set_factory(factory_); + list_view_.set_orientation(Gtk::Orientation::HORIZONTAL); + + append(list_view_); + append(add_effect_); +} + +void w_effect_list::set_track(mixer_track* in_mixer_track) { + if (mixer_track_) { + mixer_track_->on_add_effect.remove_object(this); + } + mixer_track_ = in_mixer_track; + mixer_track_->on_add_effect.add_raw(this, &w_effect_list::on_add_effect); + data_model_->remove_all(); + for (auto effect : mixer_track_->effects) { + on_add_effect(effect); + } +} + +void w_effect_list::on_setup_effect_widget(const Glib::RefPtr<Gtk::ListItem>& item) { + const auto widget = Gtk::make_managed<w_effect_item>(); + item->set_child(*widget); +} + +void w_effect_list::on_bind_effect_widget(const Glib::RefPtr<Gtk::ListItem>& item) { + const auto index = item->get_position(); + if (auto* widget = dynamic_cast<w_effect_item*>(item->get_child())) { + auto data = data_model_->get_item(index); + widget->set_effect(data->effect); + } +} + +void w_effect_list::add_new_effect() { + if (!mixer_track_) + return; + auto* host = get_plugin_host_manager()->create_effect_plugin_host(R"(F:\VST\VST64\OTT_x64.dll)"); + mixer_track_->add_effect(host); +} + +void w_effect_list::on_add_effect(plugin_host* in_effect) { + data_model_->append(mixer_effect_model::create(in_effect)); +} diff --git a/Arona/src/widget/mixer/w_effect_list.h b/Arona/src/widget/mixer/w_effect_list.h new file mode 100644 index 0000000..5ed2a9c --- /dev/null +++ b/Arona/src/widget/mixer/w_effect_list.h @@ -0,0 +1,43 @@ +#pragma once +#include <gtkmm/box.h> +#include <gtkmm/listview.h> +#include <giomm/liststore.h> +#include <gtkmm/singleselection.h> +#include <gtkmm/signallistitemfactory.h> +#include <gtkmm/button.h> + +class mixer_track; +class plugin_host; + +class mixer_effect_model : public Glib::Object { +public: + plugin_host* effect; + static Glib::RefPtr<mixer_effect_model> create(plugin_host* in_effect) { + return Glib::make_refptr_for_instance(new mixer_effect_model(in_effect)); + } +protected: + explicit mixer_effect_model(plugin_host* in_effect) : effect(in_effect) { + + } +}; + +class w_effect_list : public Gtk::Box { +public: + w_effect_list(); + + void set_track(mixer_track* in_mixer_track); + mixer_track* get_track() const { return mixer_track_; } +private: + void add_new_effect(); + void on_setup_effect_widget(const Glib::RefPtr<Gtk::ListItem>& item); + void on_bind_effect_widget(const Glib::RefPtr<Gtk::ListItem>& item); + void on_add_effect(plugin_host* in_effect); + Gtk::ListView list_view_; + + Glib::RefPtr<Gio::ListStore<mixer_effect_model>> data_model_; + Glib::RefPtr<Gtk::SingleSelection> selection_model_; + Glib::RefPtr<Gtk::SignalListItemFactory> factory_; + + mixer_track* mixer_track_; + Gtk::Button add_effect_; +}; diff --git a/Arona/src/widget/mixer/w_mixer_list.cpp b/Arona/src/widget/mixer/w_mixer_list.cpp index 706b708..c2b4a5c 100644 --- a/Arona/src/widget/mixer/w_mixer_list.cpp +++ b/Arona/src/widget/mixer/w_mixer_list.cpp @@ -4,7 +4,7 @@ #include "audio/mixer/mixer.h" #include "thread_message/thread_message_hubs.h" -w_mixer_list::w_mixer_list() { +w_mixer_list::w_mixer_list() : Gtk::Box(Gtk::Orientation::VERTICAL) { mixer* mixer = get_mixer(); { @@ -20,6 +20,7 @@ w_mixer_list::w_mixer_list() { data_model_ = Gio::ListStore<mixer_list_model>::create(); selection_model_ = Gtk::SingleSelection::create(data_model_); selection_model_->set_autoselect(true); + selection_model_->signal_selection_changed().connect(mem_fun(*this, &w_mixer_list::on_selection_changed)); factory_ = Gtk::SignalListItemFactory::create(); factory_->signal_setup().connect(mem_fun(*this, &w_mixer_list::on_setup_track_widget)); @@ -30,6 +31,7 @@ w_mixer_list::w_mixer_list() { list_view_.set_orientation(Gtk::Orientation::HORIZONTAL); append(list_view_); + append(effect_list_); } w_mixer_list::~w_mixer_list() { @@ -38,13 +40,15 @@ w_mixer_list::~w_mixer_list() { mixer->on_remove_track.remove_object(this); } -void w_mixer_list::on_add_track(mixer_track* mixer_track) { - data_model_->append(mixer_list_model::create(mixer_track)); +void w_mixer_list::on_add_track(mixer_track* track) { + data_model_->append(mixer_list_model::create(track)); + if (!effect_list_.get_track()) + effect_list_.set_track(track); } -void w_mixer_list::on_remove_track(mixer_track* mixer_track) { +void w_mixer_list::on_remove_track(mixer_track* track) { for (int i = 0; i < data_model_->get_n_items(); ++i) { - if (data_model_->get_item(i)->mixer == mixer_track) { + if (data_model_->get_item(i)->mixer == track) { data_model_->remove(i); return; } @@ -57,22 +61,19 @@ void w_mixer_list::on_setup_track_widget(const Glib::RefPtr<Gtk::ListItem>& item } void w_mixer_list::on_bind_track_widget(const Glib::RefPtr<Gtk::ListItem>& item) { - const auto index = item->get_position() + 1; // 0 is master track + const auto index = item->get_position(); if (auto* widget = dynamic_cast<w_mixer_track*>(item->get_child())) { - const std::vector<mixer_track*>& tracks = get_mixer()->get_tracks(); - if (index >= tracks.size()) { - return; - } - widget->set_mixer_track(tracks[index]); + auto data = data_model_->get_item(index); + widget->set_mixer_track(data->mixer); } } -void w_mixer_list::on_selection_changed() { - const guint selected = selection_model_->get_selected(); - const Glib::RefPtr<mixer_list_model>& selected_model = data_model_->get_item(selected); +void w_mixer_list::on_selection_changed(uint32_t position, uint32_t count) { + const Glib::RefPtr<mixer_list_model>& selected_model = data_model_->get_item(selection_model_->get_selected()); if (!selection_model_) { return; } - const mixer_track* track = selected_model->mixer; + mixer_track* track = selected_model->mixer; spdlog::info("Selected track: {}", track->get_name()); + effect_list_.set_track(track); } diff --git a/Arona/src/widget/mixer/w_mixer_list.h b/Arona/src/widget/mixer/w_mixer_list.h index 926090a..aba0a43 100644 --- a/Arona/src/widget/mixer/w_mixer_list.h +++ b/Arona/src/widget/mixer/w_mixer_list.h @@ -7,15 +7,16 @@ #include "w_mixer_track.h" #include "audio/mixer/mixer_track.h" +#include "w_effect_list.h" class mixer_list_model : public Glib::Object { public: mixer_track* mixer; - static Glib::RefPtr<mixer_list_model> create(mixer_track* mixer) { - return Glib::make_refptr_for_instance(new mixer_list_model(mixer)); + static Glib::RefPtr<mixer_list_model> create(mixer_track* in_mixer) { + return Glib::make_refptr_for_instance(new mixer_list_model(in_mixer)); } protected: - explicit mixer_list_model(mixer_track* mixer) : mixer(mixer) {} + explicit mixer_list_model(mixer_track* in_mixer) : mixer(in_mixer) {} }; class w_mixer_list : public Gtk::Box { @@ -23,12 +24,12 @@ public: w_mixer_list(); ~w_mixer_list() override; private: - void on_add_track(mixer_track* mixer_track); - void on_remove_track(mixer_track* mixer_track); + void on_add_track(mixer_track* track); + void on_remove_track(mixer_track* track); void on_setup_track_widget(const Glib::RefPtr<Gtk::ListItem>& item); void on_bind_track_widget(const Glib::RefPtr<Gtk::ListItem>& item); - void on_selection_changed(); + void on_selection_changed(uint32_t position, uint32_t count); Glib::RefPtr<Gio::ListStore<mixer_list_model>> data_model_; Glib::RefPtr<Gtk::SingleSelection> selection_model_; Glib::RefPtr<Gtk::SignalListItemFactory> factory_; @@ -36,4 +37,5 @@ private: Gtk::ListView list_view_; w_mixer_track* master_track_; + w_effect_list effect_list_; }; diff --git a/AronaCore b/AronaCore index 03353ac..1b4ee22 160000 --- a/AronaCore +++ b/AronaCore @@ -1 +1 @@ -Subproject commit 03353ac2c928069792734091f78ef5e32732ac8b +Subproject commit 1b4ee22c9502b55cd063d96fa1c9f82a03cd33fd