1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2 
3 #include "smmorphlinear.hh"
4 #include "smmorphplan.hh"
5 #include "smleakdebugger.hh"
6 
7 #include <assert.h>
8 
9 using namespace SpectMorph;
10 
11 using std::string;
12 using std::vector;
13 
14 static LeakDebugger leak_debugger ("SpectMorph::MorphLinear");
15 
MorphLinear(MorphPlan * morph_plan)16 MorphLinear::MorphLinear (MorphPlan *morph_plan) :
17   MorphOperator (morph_plan)
18 {
19   connect (morph_plan->signal_operator_removed, this, &MorphLinear::on_operator_removed);
20 
21   m_left_op = NULL;
22   m_right_op = NULL;
23   m_control_op = NULL;
24   m_morphing = 0;
25   m_control_type = CONTROL_GUI;
26   m_db_linear = false;
27 
28   leak_debugger.add (this);
29 }
30 
~MorphLinear()31 MorphLinear::~MorphLinear()
32 {
33   leak_debugger.del (this);
34 }
35 
36 const char *
type()37 MorphLinear::type()
38 {
39   return "SpectMorph::MorphLinear";
40 }
41 
42 int
insert_order()43 MorphLinear::insert_order()
44 {
45   return 500;
46 }
47 
48 bool
save(OutFile & out_file)49 MorphLinear::save (OutFile& out_file)
50 {
51   write_operator (out_file, "left", m_left_op);
52   write_operator (out_file, "right", m_right_op);
53   write_operator (out_file, "control", m_control_op);
54   out_file.write_string ("left_smset", m_left_smset);
55   out_file.write_string ("right_smset", m_right_smset);
56   out_file.write_float ("morphing", m_morphing);
57   out_file.write_int ("control_type", m_control_type);
58   out_file.write_bool ("db_linear", m_db_linear);
59 
60   return true;
61 }
62 
63 bool
load(InFile & ifile)64 MorphLinear::load (InFile& ifile)
65 {
66   load_left    = "";
67   load_right   = "";
68   load_control = "";
69 
70   while (ifile.event() != InFile::END_OF_FILE)
71     {
72       if (ifile.event() == InFile::STRING)
73         {
74           if (ifile.event_name() == "left")
75             {
76               load_left = ifile.event_data();
77             }
78           else if (ifile.event_name() == "right")
79             {
80               load_right = ifile.event_data();
81             }
82           else if (ifile.event_name() == "control")
83             {
84               load_control = ifile.event_data();
85             }
86           else if (ifile.event_name() == "left_smset")
87             {
88               m_left_smset = ifile.event_data();
89             }
90           else if (ifile.event_name() == "right_smset")
91             {
92               m_right_smset = ifile.event_data();
93             }
94           else
95             {
96               g_printerr ("bad string\n");
97               return false;
98             }
99         }
100       else if (ifile.event() == InFile::FLOAT)
101         {
102           if (ifile.event_name() == "morphing")
103             {
104               m_morphing = ifile.event_float();
105             }
106           else
107             {
108               g_printerr ("bad float\n");
109               return false;
110             }
111         }
112       else if (ifile.event() == InFile::INT)
113         {
114           if (ifile.event_name() == "control_type")
115             {
116               m_control_type = static_cast<ControlType> (ifile.event_int());
117             }
118           else
119             {
120               g_printerr ("bad int\n");
121               return false;
122             }
123         }
124       else if (ifile.event() == InFile::BOOL)
125         {
126           if (ifile.event_name() == "db_linear")
127             {
128               m_db_linear = ifile.event_bool();
129             }
130           else if (ifile.event_name() == "use_lpc")
131             {
132               /* we need to skip this without error, as old files may contain this setting
133                * lpc is however no longer supported, so we always ignore the value
134                */
135             }
136           else
137             {
138               g_printerr ("bad bool\n");
139               return false;
140             }
141         }
142       else
143         {
144           g_printerr ("bad event\n");
145           return false;
146         }
147       ifile.next_event();
148     }
149   return true;
150 }
151 
152 void
post_load(OpNameMap & op_name_map)153 MorphLinear::post_load (OpNameMap& op_name_map)
154 {
155   m_left_op = op_name_map[load_left];
156   m_right_op = op_name_map[load_right];
157   m_control_op = op_name_map[load_control];
158 }
159 
160 MorphOperator::OutputType
output_type()161 MorphLinear::output_type()
162 {
163   return OUTPUT_AUDIO;
164 }
165 
166 void
on_operator_removed(MorphOperator * op)167 MorphLinear::on_operator_removed (MorphOperator *op)
168 {
169   // plan changed will be emitted automatically after remove, so we don't emit it here
170 
171   if (op == m_left_op)
172     m_left_op = nullptr;
173 
174   if (op == m_right_op)
175     m_right_op = nullptr;
176 
177   if (op == m_control_op)
178     {
179       m_control_op = nullptr;
180 
181       if (m_control_type == CONTROL_OP)
182         m_control_type = CONTROL_GUI;
183     }
184 }
185 
186 MorphOperator *
left_op()187 MorphLinear::left_op()
188 {
189   return m_left_op;
190 }
191 
192 MorphOperator *
right_op()193 MorphLinear::right_op()
194 {
195   return m_right_op;
196 }
197 
198 MorphOperator *
control_op()199 MorphLinear::control_op()
200 {
201   return m_control_op;
202 }
203 
204 void
set_left_op(MorphOperator * op)205 MorphLinear::set_left_op (MorphOperator *op)
206 {
207   m_left_op = op;
208 
209   m_morph_plan->emit_plan_changed();
210 }
211 
212 void
set_right_op(MorphOperator * op)213 MorphLinear::set_right_op (MorphOperator *op)
214 {
215   m_right_op = op;
216 
217   m_morph_plan->emit_plan_changed();
218 }
219 
220 void
set_control_op(MorphOperator * op)221 MorphLinear::set_control_op (MorphOperator *op)
222 {
223   m_control_op = op;
224 
225   m_morph_plan->emit_plan_changed();
226 }
227 
228 void
set_control_type_and_op(ControlType control_type,MorphOperator * op)229 MorphLinear::set_control_type_and_op (ControlType control_type, MorphOperator *op)
230 {
231   m_control_type = control_type;
232   m_control_op   = op;
233 
234   m_morph_plan->emit_plan_changed();
235 }
236 
237 string
left_smset()238 MorphLinear::left_smset()
239 {
240   return m_left_smset;
241 }
242 
243 string
right_smset()244 MorphLinear::right_smset()
245 {
246   return m_right_smset;
247 }
248 
249 void
set_left_smset(const string & smset)250 MorphLinear::set_left_smset (const string& smset)
251 {
252   m_left_smset = smset;
253 
254   m_morph_plan->emit_plan_changed();
255 }
256 
257 void
set_right_smset(const string & smset)258 MorphLinear::set_right_smset (const string& smset)
259 {
260   m_right_smset = smset;
261 
262   m_morph_plan->emit_plan_changed();
263 }
264 
265 double
morphing()266 MorphLinear::morphing()
267 {
268   return m_morphing;
269 }
270 
271 void
set_morphing(double new_morphing)272 MorphLinear::set_morphing (double new_morphing)
273 {
274   m_morphing = new_morphing;
275 
276   m_morph_plan->emit_plan_changed();
277 }
278 
279 MorphLinear::ControlType
control_type()280 MorphLinear::control_type()
281 {
282   return m_control_type;
283 }
284 
285 void
set_control_type(ControlType new_control_type)286 MorphLinear::set_control_type (ControlType new_control_type)
287 {
288   m_control_type = new_control_type;
289 
290   m_morph_plan->emit_plan_changed();
291 }
292 
293 bool
db_linear()294 MorphLinear::db_linear()
295 {
296   return m_db_linear;
297 }
298 
299 void
set_db_linear(bool dbl)300 MorphLinear::set_db_linear (bool dbl)
301 {
302   m_db_linear = dbl;
303 
304   m_morph_plan->emit_plan_changed();
305 }
306 
307 vector<MorphOperator *>
dependencies()308 MorphLinear::dependencies()
309 {
310   return { m_left_op, m_right_op, m_control_type == CONTROL_OP ? m_control_op : nullptr };
311 }
312