1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #ifndef SPECTMORPH_PROJECT_HH
4 #define SPECTMORPH_PROJECT_HH
5 
6 #include "sminstrument.hh"
7 #include "smwavset.hh"
8 #include "smwavsetbuilder.hh"
9 #include "smobject.hh"
10 #include "smbuilderthread.hh"
11 #include "smmorphplan.hh"
12 #include "smuserinstrumentindex.hh"
13 
14 #include <thread>
15 #include <mutex>
16 
17 namespace SpectMorph
18 {
19 
20 class MidiSynth;
21 class SynthInterface;
22 class MorphWavSource;
23 
24 class SynthControlEvent
25 {
26 public:
27   virtual void run_rt (Project *project) = 0;
28   virtual
~SynthControlEvent()29   ~SynthControlEvent()
30   {
31   }
32 };
33 
34 struct InstFunc : public SynthControlEvent
35 {
36   std::function<void(Project *)> func;
37   std::function<void()>          free_func;
38 public:
InstFuncSpectMorph::InstFunc39   InstFunc (const std::function<void(Project *)>& func,
40             const std::function<void()>& free_func) :
41     func (func),
42     free_func (free_func)
43   {
44   }
~InstFuncSpectMorph::InstFunc45   ~InstFunc()
46   {
47     free_func();
48   }
49   void
run_rtSpectMorph::InstFunc50   run_rt (Project *project)
51   {
52     func (project);
53   }
54 };
55 
56 class ControlEventVector
57 {
58   std::vector<std::unique_ptr<SynthControlEvent>> events;
59   bool clear = false;
60 public:
61   void take (SynthControlEvent *ev);
62   void run_rt (Project *project);
63 };
64 
65 class Project : public SignalReceiver
66 {
67 public:
68   enum class StorageModel {
69     COPY,
70     REFERENCE
71   };
72 
73 private:
74   std::vector<std::shared_ptr<WavSet>> wav_sets;
75 
76   std::unique_ptr<MidiSynth>  m_midi_synth;
77   double                      m_mix_freq = 0;
78   double                      m_volume = -6;
79   RefPtr<MorphPlan>           m_morph_plan;
80   std::vector<unsigned char>  m_last_plan_data;
81   bool                        m_state_changed_notify = false;
82   StorageModel                m_storage_model = StorageModel::COPY;
83 
84   std::mutex                  m_synth_mutex;
85   ControlEventVector          m_control_events;          // protected by synth mutex
86   std::vector<std::string>    m_out_events;              // protected by synth mutex
87   bool                        m_voices_active = false;   // protected by synth mutex
88   bool                        m_state_changed = false;   // protected by synth mutex
89 
90   std::unique_ptr<SynthInterface> m_synth_interface;
91 
92   UserInstrumentIndex         m_user_instrument_index;
93   BuilderThread               m_builder_thread;
94 
95   std::map<int, std::unique_ptr<Instrument>> instrument_map;
96 
97   std::vector<MorphWavSource *> list_wav_sources();
98 
99   Error load_internal (ZipReader& zip_reader, MorphPlan::ExtraParameters *params);
100   void  post_load();
101 
102   void on_plan_changed();
103   void on_operator_added (MorphOperator *op);
104   void on_operator_removed (MorphOperator *op);
105 
106 public:
107   Project();
108 
109   Instrument *get_instrument (MorphWavSource *wav_source);
110 
111   void rebuild (MorphWavSource *wav_source);
112   void add_rebuild_result (int object_id, WavSet *wav_set);
113   void clear_wav_sets();
114   bool rebuild_active (int object_id);
115 
116   std::shared_ptr<WavSet> get_wav_set (int object_id);
117 
118   void synth_take_control_event (SynthControlEvent *event);
119 
120   std::mutex&
synth_mutex()121   synth_mutex()
122   {
123     /* the synthesis thread will typically not block on synth_mutex
124      * instead, it tries locking it, and if that fails, continues
125      *
126      * the ui thread will block on the synth_mutex to enqueue events,
127      * parameter changes (in form of a new morph plan, volume, ...)
128      * and so on
129      *
130      * if the synthesis thread can obtain a lock, it will then be
131      * able to process these events to update its internal state
132      * and also send notifications back to the ui
133      */
134     return m_synth_mutex;
135   }
136   bool try_update_synth();
137   void set_mix_freq (double mix_freq);
138   void set_storage_model (StorageModel model);
139   void set_state_changed_notify (bool notify);
140   void state_changed();
141   bool voices_active();
142 
143   void set_volume (double new_volume);
144   double volume() const;
145 
146   std::vector<std::string> notify_take_events();
147   SynthInterface *synth_interface() const;
148   MidiSynth *midi_synth() const;
149   MorphPlanPtr morph_plan() const;
150   UserInstrumentIndex *user_instrument_index();
151 
152   Error save (const std::string& filename);
153   Error save (ZipWriter& zip_writer, MorphPlan::ExtraParameters *params);
154   Error load (const std::string& filename);
155   Error load (ZipReader& zip_reader, MorphPlan::ExtraParameters *params);
156   Error load_compat (GenericIn *in, MorphPlan::ExtraParameters *params);
157 
158   std::string save_plan_lv2 (std::function<std::string(std::string)> abstract_path);
159   void        load_plan_lv2 (std::function<std::string(std::string)> absolute_path, const std::string& plan);
160   void        clear_lv2_filenames();
161 
162   Signal<double> signal_volume_changed;
163 };
164 
165 }
166 
167 #endif
168