SpectMorph
smproject.hh
1 // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl-2.1.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 "smbuilderthread.hh"
10 #include "smmorphplan.hh"
11 #include "smuserinstrumentindex.hh"
12 #include "smnotifybuffer.hh"
13 
14 #include <thread>
15 #include <mutex>
16 
17 namespace SpectMorph
18 {
19 
20 class MidiSynth;
21 class SynthInterface;
22 class MorphWavSource;
23 
25 {
26 public:
27  virtual void run_rt (Project *project) = 0;
28  virtual
30  {
31  }
32 };
33 
34 struct InstFunc : public SynthControlEvent
35 {
36  std::function<void(Project *)> func;
37  std::function<void()> free_func;
38 public:
39  InstFunc (const std::function<void(Project *)>& func,
40  const std::function<void()>& free_func) :
41  func (func),
42  free_func (free_func)
43  {
44  }
45  ~InstFunc()
46  {
47  free_func();
48  }
49  void
50  run_rt (Project *project)
51  {
52  func (project);
53  }
54 };
55 
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  void destroy_all_events();
64 };
65 
66 class Project : public SignalReceiver
67 {
68 public:
69  enum class StorageModel {
70  COPY,
71  REFERENCE
72  };
73 
74  static constexpr size_t WAV_SETS_RESERVE = 256;
75 private:
76  std::vector<std::unique_ptr<WavSet>> wav_sets;
77 
78  std::unique_ptr<MidiSynth> m_midi_synth;
79  double m_mix_freq = 0;
80  double m_volume = -6;
81  MorphPlan m_morph_plan;
82  std::vector<unsigned char> m_last_plan_data;
83  bool m_state_changed_notify = false;
84  StorageModel m_storage_model = StorageModel::COPY;
85 
86  std::mutex m_synth_mutex;
87  ControlEventVector m_control_events; // protected by synth mutex
88  NotifyBuffer m_notify_buffer; // protected by synth mutex
89  bool m_state_changed = false; // protected by synth mutex
90 
91  std::unique_ptr<SynthInterface> m_synth_interface;
92 
93  UserInstrumentIndex m_user_instrument_index;
94  BuilderThread m_builder_thread;
95 
96  std::map<int, std::unique_ptr<Instrument>> instrument_map;
97 
98  std::vector<MorphWavSource *> list_wav_sources();
99 
100  Error load_internal (ZipReader& zip_reader, MorphPlan::ExtraParameters *params);
101  void post_load();
102 
103  void on_plan_changed();
104  void on_operator_added (MorphOperator *op);
105  void on_operator_removed (MorphOperator *op);
106 
107 public:
108  Project();
109 
110  Instrument *get_instrument (MorphWavSource *wav_source);
111 
112  void rebuild (MorphWavSource *wav_source);
113  void add_rebuild_result (int object_id, std::unique_ptr<WavSet>& wav_set);
114  void clear_wav_sets (std::vector<std::unique_ptr<WavSet>>& wav_sets);
115  bool rebuild_active (int object_id);
116 
117  WavSet *get_wav_set (int object_id);
118 
119  void synth_take_control_event (SynthControlEvent *event);
120 
121  std::mutex&
122  synth_mutex()
123  {
124  /* the synthesis thread will typically not block on synth_mutex
125  * instead, it tries locking it, and if that fails, continues
126  *
127  * the ui thread will block on the synth_mutex to enqueue events,
128  * parameter changes (in form of a new morph plan, volume, ...)
129  * and so on
130  *
131  * if the synthesis thread can obtain a lock, it will then be
132  * able to process these events to update its internal state
133  * and also send notifications back to the ui
134  */
135  return m_synth_mutex;
136  }
137  bool try_update_synth();
138  void set_mix_freq (double mix_freq);
139  void set_storage_model (StorageModel model);
140  void set_state_changed_notify (bool notify);
141  void state_changed();
142 
143  void set_volume (double new_volume);
144  double volume() const;
145 
146  NotifyBuffer *notify_buffer();
147  SynthInterface *synth_interface() const;
148  MidiSynth *midi_synth() const;
149  MorphPlan *morph_plan();
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
Definition: smbuilderthread.hh:19
Definition: smproject.hh:57
Definition: smutils.hh:102
Generic Input Stream.
Definition: smgenericin.hh:18
Definition: sminstrument.hh:83
Definition: smmidisynth.hh:27
Definition: smmorphoperator.hh:27
Definition: smmorphplan.hh:21
Definition: smmorphplan.hh:18
Definition: smmorphwavsource.hh:20
Definition: smnotifybuffer.hh:29
Definition: smproject.hh:67
Definition: smsignal.hh:35
Definition: smproject.hh:25
Definition: smsynthinterface.hh:14
Definition: smuserinstrumentindex.hh:12
Definition: smwavset.hh:29
Definition: smzip.hh:15
Definition: smzip.hh:34
Definition: smproject.hh:35