Line data Source code
1 : #pragma once
2 :
3 : #include "audio/effects/effect.h"
4 : #include <functional>
5 : #include <stdexcept>
6 : #include <unordered_map>
7 : #include <string>
8 :
9 : namespace Amplitron {
10 :
11 : /**
12 : * Registry-based effect factory.
13 : * Replaces the if-chain in PresetManager::create_effect().
14 : * All effect types self-register via EffectRegistrar.
15 : */
16 : class EffectFactory {
17 : public:
18 : using Creator = std::function<std::shared_ptr<Effect>()>;
19 :
20 684 : static EffectFactory& instance() {
21 687 : static EffectFactory factory;
22 684 : return factory;
23 : }
24 :
25 111 : void register_effect(const std::string& type_name, Creator creator) {
26 111 : if (creators_.count(type_name) > 0) {
27 4 : throw std::runtime_error("Duplicate effect registration: " + type_name);
28 : }
29 108 : creators_.emplace(type_name, std::move(creator));
30 109 : }
31 :
32 564 : std::shared_ptr<Effect> create(const std::string& type_name) const {
33 564 : auto it = creators_.find(type_name);
34 564 : if (it != creators_.end()) {
35 474 : return it->second();
36 : }
37 90 : return nullptr;
38 188 : }
39 :
40 9 : std::vector<std::string> registered_types() const {
41 9 : std::vector<std::string> types;
42 9 : types.reserve(creators_.size());
43 171 : for (auto& [name, _] : creators_) {
44 162 : types.push_back(name);
45 : }
46 9 : return types;
47 3 : }
48 :
49 57 : std::shared_ptr<Effect> create_from_type(const std::string& type_name) const {
50 57 : return create(type_name);
51 : }
52 :
53 6 : std::vector<std::string> get_all_type_names() const {
54 6 : return registered_types();
55 : }
56 :
57 : private:
58 8 : EffectFactory() = default;
59 : std::unordered_map<std::string, Creator> creators_;
60 : };
61 :
62 : /**
63 : * RAII helper that registers an effect type at static-init time.
64 : * Usage (in .cpp file):
65 : * static EffectRegistrar<MyEffect> reg("My Effect");
66 : */
67 : template <typename T>
68 : struct EffectRegistrar {
69 144 : explicit EffectRegistrar(const std::string& type_name) {
70 424 : EffectFactory::instance().register_effect(type_name, []() {
71 316 : return std::make_shared<T>();
72 : });
73 144 : }
74 : };
75 :
76 9 : inline std::shared_ptr<Effect> Effect::clone() const {
77 12 : auto new_effect = EffectFactory::instance().create(type_id());
78 9 : if (new_effect) {
79 6 : new_effect->set_params(get_params());
80 6 : new_effect->set_enabled(enabled_);
81 6 : new_effect->set_mix(mix_);
82 2 : }
83 9 : return new_effect;
84 3 : }
85 :
86 : } // namespace Amplitron
|