/[svn]/gigedit/trunk/src/gigedit/dimregionedit.h
ViewVC logotype

Contents of /gigedit/trunk/src/gigedit/dimregionedit.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3619 - (show annotations) (download) (as text)
Tue Oct 1 16:21:28 2019 UTC (4 years, 5 months ago) by schoenebeck
File MIME type: text/x-c++hdr
File size: 17833 byte(s)
* Require C++11 compliant compiler.
* Draw LFO curves according to settings for each one of the 3 LFOs.
* Added 2 new tabs (a 3rd tab for "Amp" and a 3rd tab for "Filter").
* Shortened "Amplitude" -> "Amp" on tabs (to save space).
* Increased default window width 865px -> 960px.
* Bumped version (1.1.1.svn2).

1 /* -*- c++ -*-
2 * Copyright (C) 2006-2019 Andreas Persson
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2, or (at
7 * your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with program; see the file COPYING. If not, write to the Free
16 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17 * 02110-1301 USA.
18 */
19
20 #ifndef GIGEDIT_DIMREGIONEDIT_H
21 #define GIGEDIT_DIMREGIONEDIT_H
22
23 #ifdef LIBGIG_HEADER_FILE
24 # include LIBGIG_HEADER_FILE(gig.h)
25 #else
26 # include <gig.h>
27 #endif
28
29 #include "compat.h"
30
31 #include <cairomm/context.h>
32 #include <gtkmm/box.h>
33 #include <gtkmm/drawingarea.h>
34 #include <gtkmm/entry.h>
35 #include <gtkmm/label.h>
36 #include <gtkmm/notebook.h>
37 #if USE_GTKMM_GRID
38 # include <gtkmm/grid.h>
39 #else
40 # include <gtkmm/table.h>
41 #endif
42
43 #ifdef LIBLINUXSAMPLER_HEADER_FILE
44 # include LIBLINUXSAMPLER_HEADER_FILE(engines/LFO.h)
45 #else
46 # include <linuxsampler/engines/LFO.h>
47 #endif
48
49 #include <set>
50
51 #include "paramedit.h"
52 #include "global.h"
53
54 class VelocityCurve : public Gtk::DrawingArea {
55 public:
56 VelocityCurve(double (gig::DimensionRegion::*getter)(uint8_t));
57 void set_dim_region(gig::DimensionRegion* d) { dimreg = d; }
58
59 protected:
60 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
61 bool on_expose_event(GdkEventExpose* e);
62 #else
63 bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
64 #endif
65
66 private:
67 double (gig::DimensionRegion::* const getter)(uint8_t);
68 gig::DimensionRegion* dimreg;
69 };
70
71 class CrossfadeCurve : public Gtk::DrawingArea {
72 public:
73 CrossfadeCurve();
74 void set_dim_region(gig::DimensionRegion* d) { dimreg = d; }
75
76 protected:
77 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
78 bool on_expose_event(GdkEventExpose* e);
79 #else
80 bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
81 #endif
82
83 private:
84 gig::DimensionRegion* dimreg;
85 void draw_one_curve(const Cairo::RefPtr<Cairo::Context>& cr,
86 const gig::DimensionRegion* d,
87 bool sensitive);
88 };
89
90 class LFOGraph : public Gtk::DrawingArea {
91 public:
92 LFOGraph();
93 void set_dim_region(gig::DimensionRegion* d) { dimreg = d; }
94
95 protected:
96 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
97 bool on_expose_event(GdkEventExpose* e);
98 #else
99 bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr);
100 #endif
101
102 virtual float frequency() const = 0;
103 virtual uint internalDepth() const = 0;
104 virtual uint controllerDepth() const = 0;
105 virtual bool flipPolarity() const = 0;
106 virtual bool signedRange() const = 0;
107 virtual LinuxSampler::LFO::start_level_t startLevel() const = 0;
108 virtual bool hasControllerAssigned() const = 0;
109
110 gig::DimensionRegion* dimreg;
111 LinuxSampler::LFO lfo;
112 };
113
114 class LFO1Graph : public LFOGraph {
115 public:
116 float frequency() const OVERRIDE { return dimreg->LFO1Frequency; }
117 uint internalDepth() const OVERRIDE {
118 const gig::lfo1_ctrl_t ctrl = dimreg->LFO1Controller;
119 const bool hasInternalDepth = (
120 ctrl != gig::lfo1_ctrl_modwheel && ctrl != gig::lfo1_ctrl_breath
121 );
122 return (hasInternalDepth) ? dimreg->LFO1InternalDepth : 0;
123 }
124 uint controllerDepth() const OVERRIDE { return dimreg->LFO1ControlDepth; }
125 bool flipPolarity() const OVERRIDE { return dimreg->LFO1FlipPhase; }
126 bool signedRange() const OVERRIDE { return false; }
127 virtual LinuxSampler::LFO::start_level_t startLevel() const OVERRIDE { return LinuxSampler::LFO::start_level_mid; } // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
128 bool hasControllerAssigned() const OVERRIDE { return dimreg->LFO1Controller; }
129 };
130
131 class LFO2Graph : public LFOGraph {
132 public:
133 float frequency() const OVERRIDE { return dimreg->LFO2Frequency; }
134 uint internalDepth() const OVERRIDE {
135 const gig::lfo2_ctrl_t ctrl = dimreg->LFO2Controller;
136 const bool hasInternalDepth = (
137 ctrl != gig::lfo2_ctrl_modwheel && ctrl != gig::lfo2_ctrl_foot
138 );
139 return (hasInternalDepth) ? dimreg->LFO2InternalDepth : 0;
140 }
141 uint controllerDepth() const OVERRIDE { return dimreg->LFO2ControlDepth; }
142 bool flipPolarity() const OVERRIDE { return dimreg->LFO2FlipPhase; }
143 bool signedRange() const OVERRIDE { return false; }
144 virtual LinuxSampler::LFO::start_level_t startLevel() const OVERRIDE { return LinuxSampler::LFO::start_level_mid; } // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
145 bool hasControllerAssigned() const OVERRIDE { return dimreg->LFO2Controller; }
146 };
147
148 class LFO3Graph : public LFOGraph {
149 public:
150 float frequency() const OVERRIDE { return dimreg->LFO3Frequency; }
151 uint internalDepth() const OVERRIDE {
152 const gig::lfo3_ctrl_t ctrl = dimreg->LFO3Controller;
153 const bool hasInternalDepth = (
154 ctrl != gig::lfo3_ctrl_modwheel && ctrl != gig::lfo3_ctrl_aftertouch
155 );
156 return (hasInternalDepth) ? dimreg->LFO3InternalDepth : 0;
157 }
158 uint controllerDepth() const OVERRIDE { return dimreg->LFO3ControlDepth; }
159 bool flipPolarity() const OVERRIDE { return false; }
160 bool signedRange() const OVERRIDE { return true; }
161 virtual LinuxSampler::LFO::start_level_t startLevel() const OVERRIDE { return LinuxSampler::LFO::start_level_max; } // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
162 bool hasControllerAssigned() const OVERRIDE { return dimreg->LFO3Controller; }
163 };
164
165 class EGStateOptions : public HBox {
166 public:
167 Gtk::Label label;
168 BoolBox checkBoxAttack;
169 BoolBox checkBoxAttackHold;
170 BoolBox checkBoxDecay1;
171 BoolBox checkBoxDecay2;
172 BoolBox checkBoxRelease;
173
174 EGStateOptions();
175 void on_show_tooltips_changed();
176 };
177
178 class DimRegionEdit : public Gtk::Notebook
179 {
180 public:
181 DimRegionEdit();
182 virtual ~DimRegionEdit();
183 void set_dim_region(gig::DimensionRegion* d);
184 bool set_sample(gig::Sample* sample, bool copy_sample_unity, bool copy_sample_tune, bool copy_sample_loop);
185 bool set_sample(gig::DimensionRegion* dimreg, gig::Sample* sample, bool copy_sample_unity, bool copy_sample_tune, bool copy_sample_loop);
186 Gtk::Entry* wSample;
187 Gtk::Button* buttonNullSampleReference;
188 sigc::signal<void, gig::DimensionRegion*>& signal_dimreg_to_be_changed();
189 sigc::signal<void, gig::DimensionRegion*>& signal_dimreg_changed();
190 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/>& signal_sample_ref_changed();
191 sigc::signal<void, gig::Sample*>& signal_select_sample();
192
193 std::set<gig::DimensionRegion*> dimregs;
194
195 protected:
196 sigc::signal<void, gig::DimensionRegion*> dimreg_to_be_changed_signal;
197 sigc::signal<void, gig::DimensionRegion*> dimreg_changed_signal;
198 sigc::signal<void, gig::Sample*/*old*/, gig::Sample*/*new*/> sample_ref_changed_signal;
199 sigc::signal<void> instrument_changed;
200 sigc::signal<void, gig::Sample*> select_sample_signal;
201
202 /**
203 * Ensures that the 2 signals DimRegionEdit::dimreg_to_be_changed_signal and
204 * DimRegionEdit::dimreg_changed_signal are always triggered correctly as a
205 * pair. It behaves similar to a "mutex lock guard" design pattern.
206 */
207 class DimRegionChangeGuard : public SignalGuard<gig::DimensionRegion*> {
208 public:
209 DimRegionChangeGuard(DimRegionEdit* edit, gig::DimensionRegion* pDimReg) :
210 SignalGuard<gig::DimensionRegion*>(edit->dimreg_to_be_changed_signal, edit->dimreg_changed_signal, pDimReg)
211 {
212 }
213 };
214
215 gig::DimensionRegion* dimregion;
216
217 #ifdef OLD_TOOLTIPS
218 Gtk::Tooltips tooltips;
219 #endif
220
221 #if USE_GTKMM_GRID
222 Gtk::Grid* table[9];
223 #else
224 Gtk::Table* table[9];
225 #endif
226
227 Gtk::Label* lSample;
228
229 VelocityCurve velocity_curve;
230 VelocityCurve release_curve;
231 VelocityCurve cutoff_curve;
232 CrossfadeCurve crossfade_curve;
233 LFO1Graph lfo1Graph; ///< Graphic of Amplitude (Volume) LFO waveform.
234 LFO2Graph lfo2Graph; ///< Graphic of Filter Cutoff LFO waveform.
235 LFO3Graph lfo3Graph; ///< Graphic of Pitch LFO waveform.
236
237 NumEntryPermille eEG1PreAttack;
238 NumEntryTemp<double> eEG1Attack;
239 NumEntryTemp<double> eEG1Decay1;
240 NumEntryTemp<double> eEG1Decay2;
241 BoolEntry eEG1InfiniteSustain;
242 NumEntryPermille eEG1Sustain;
243 NumEntryTemp<double> eEG1Release;
244 BoolEntry eEG1Hold;
245 ChoiceEntryLeverageCtrl eEG1Controller;
246 BoolEntry eEG1ControllerInvert;
247 NumEntryTemp<uint8_t> eEG1ControllerAttackInfluence;
248 NumEntryTemp<uint8_t> eEG1ControllerDecayInfluence;
249 NumEntryTemp<uint8_t> eEG1ControllerReleaseInfluence;
250 EGStateOptions eEG1StateOptions;
251 NumEntryTemp<double> eLFO1Frequency;
252 NumEntryTemp<uint16_t> eLFO1InternalDepth;
253 NumEntryTemp<uint16_t> eLFO1ControlDepth;
254 ChoiceEntry<gig::lfo1_ctrl_t> eLFO1Controller;
255 BoolEntry eLFO1FlipPhase;
256 BoolEntry eLFO1Sync;
257 NumEntryPermille eEG2PreAttack;
258 NumEntryTemp<double> eEG2Attack;
259 NumEntryTemp<double> eEG2Decay1;
260 NumEntryTemp<double> eEG2Decay2;
261 BoolEntry eEG2InfiniteSustain;
262 NumEntryPermille eEG2Sustain;
263 NumEntryTemp<double> eEG2Release;
264 ChoiceEntryLeverageCtrl eEG2Controller;
265 BoolEntry eEG2ControllerInvert;
266 NumEntryTemp<uint8_t> eEG2ControllerAttackInfluence;
267 NumEntryTemp<uint8_t> eEG2ControllerDecayInfluence;
268 NumEntryTemp<uint8_t> eEG2ControllerReleaseInfluence;
269 EGStateOptions eEG2StateOptions;
270 NumEntryTemp<double> eLFO2Frequency;
271 NumEntryTemp<uint16_t> eLFO2InternalDepth;
272 NumEntryTemp<uint16_t> eLFO2ControlDepth;
273 ChoiceEntry<gig::lfo2_ctrl_t> eLFO2Controller;
274 BoolEntry eLFO2FlipPhase;
275 BoolEntry eLFO2Sync;
276 NumEntryTemp<double> eEG3Attack;
277 NumEntryTemp<int16_t> eEG3Depth;
278 NumEntryTemp<double> eLFO3Frequency;
279 NumEntryTemp<int16_t> eLFO3InternalDepth;
280 NumEntryTemp<int16_t> eLFO3ControlDepth;
281 ChoiceEntry<gig::lfo3_ctrl_t> eLFO3Controller;
282 BoolEntry eLFO3Sync;
283 BoolEntry eVCFEnabled;
284 ChoiceEntry<gig::vcf_type_t> eVCFType;
285 ChoiceEntry<gig::vcf_cutoff_ctrl_t> eVCFCutoffController;
286 BoolEntry eVCFCutoffControllerInvert;
287 NumEntryTemp<uint8_t> eVCFCutoff;
288 ChoiceEntry<gig::curve_type_t> eVCFVelocityCurve;
289 NumEntryTemp<uint8_t> eVCFVelocityScale;
290 NumEntryTemp<uint8_t> eVCFVelocityDynamicRange;
291 NumEntryTemp<uint8_t> eVCFResonance;
292 BoolEntry eVCFResonanceDynamic;
293 ChoiceEntry<gig::vcf_res_ctrl_t> eVCFResonanceController;
294 BoolEntry eVCFKeyboardTracking;
295 NumEntryTemp<uint8_t> eVCFKeyboardTrackingBreakpoint;
296 ChoiceEntry<gig::curve_type_t> eVelocityResponseCurve;
297 NumEntryTemp<uint8_t> eVelocityResponseDepth;
298 NumEntryTemp<uint8_t> eVelocityResponseCurveScaling;
299 ChoiceEntry<gig::curve_type_t> eReleaseVelocityResponseCurve;
300 NumEntryTemp<uint8_t> eReleaseVelocityResponseDepth;
301 NumEntryTemp<uint8_t> eReleaseTriggerDecay;
302 NumEntryTemp<uint8_t> eCrossfade_in_start;
303 NumEntryTemp<uint8_t> eCrossfade_in_end;
304 NumEntryTemp<uint8_t> eCrossfade_out_start;
305 NumEntryTemp<uint8_t> eCrossfade_out_end;
306 BoolEntry ePitchTrack;
307 ChoiceEntry<gig::sust_rel_trg_t> eSustainReleaseTrigger;
308 BoolEntry eNoNoteOffReleaseTrigger;
309 ChoiceEntry<gig::dim_bypass_ctrl_t> eDimensionBypass;
310 NumEntryTemp<int8_t> ePan;
311 BoolEntry eSelfMask;
312 ChoiceEntryLeverageCtrl eAttenuationController;
313 BoolEntry eInvertAttenuationController;
314 NumEntryTemp<uint8_t> eAttenuationControllerThreshold;
315 NumEntryTemp<uint8_t> eChannelOffset;
316 BoolEntry eSustainDefeat;
317 BoolEntry eMSDecode;
318 NumEntryTemp<uint16_t> eSampleStartOffset;
319 NoteEntry eUnityNote;
320 ReadOnlyLabelWidget eSampleGroup;
321 ReadOnlyLabelWidget eSampleFormatInfo;
322 ReadOnlyLabelWidget eSampleID;
323 ReadOnlyLabelWidget eChecksum;
324 NumEntryTemp<int16_t> eFineTune;
325 NumEntryGain eGain;
326 BoolEntryPlus6 eGainPlus6;
327 BoolEntry eSampleLoopEnabled;
328 NumEntryTemp<uint32_t> eSampleLoopStart;
329 NumEntryTemp<uint32_t> eSampleLoopLength;
330 ChoiceEntry<uint32_t> eSampleLoopType;
331 BoolEntry eSampleLoopInfinite;
332 NumEntryTemp<uint32_t> eSampleLoopPlayCount;
333 Gtk::Label* lEG2;
334 Gtk::Label* lLFO2;
335
336 Gtk::Button buttonSelectSample;
337
338 int rowno;
339 int pageno;
340 int firstRowInBlock;
341
342
343 void addProp(BoolEntry& boolentry);
344 void addProp(BoolEntryPlus6& boolentry);
345 void addProp(LabelWidget& labelwidget);
346 void addLine(HBox& line);
347 void addString(const char* labelText, Gtk::Label*& label,
348 Gtk::Entry*& widget);
349 void addString(const char* labelText, Gtk::Label*& label,
350 Gtk::Entry*& widget, Gtk::Button*& button);
351 Gtk::Label* addHeader(const char* text);
352 void addRightHandSide(Gtk::Widget& widget);
353 void nextPage();
354
355 void VCFEnabled_toggled();
356 void VCFCutoffController_changed();
357 void VCFResonanceController_changed();
358 void EG1InfiniteSustain_toggled();
359 void EG2InfiniteSustain_toggled();
360 void EG1Controller_changed();
361 void EG2Controller_changed();
362 void AttenuationController_changed();
363 void LFO1Controller_changed();
364 void LFO2Controller_changed();
365 void LFO3Controller_changed();
366 void crossfade1_changed();
367 void crossfade2_changed();
368 void crossfade3_changed();
369 void crossfade4_changed();
370 void update_loop_elements();
371 void loop_start_changed();
372 void loop_length_changed();
373 void loop_infinite_toggled();
374 void nullOutSampleReference();
375 void on_show_tooltips_changed();
376
377 int update_model;
378
379 // connect a widget to a setter function in DimRegionEdit
380 template<typename C, typename T>
381 void connect(C& widget,
382 void (DimRegionEdit::*setter)(gig::DimensionRegion&, T)) {
383 connect<C, T>(widget,
384 sigc::mem_fun(setter));
385 }
386
387 // connect a widget to a member variable in gig::DimensionRegion
388 template<typename C, typename T>
389 void connect(C& widget, T gig::DimensionRegion::* member) {
390 connect<C, T>(widget,
391 sigc::bind(sigc::mem_fun(&DimRegionEdit::set_member<T>), member));
392 }
393
394 // connect a widget to a member of a struct member in gig::DimensionRegion
395 template<typename C, typename T, typename S>
396 void connect(C& widget, S gig::DimensionRegion::* member, T S::* member2) {
397 connect<C, T>(widget,
398 sigc::bind(sigc::mem_fun(&DimRegionEdit::set_sub_member<T, S>), member, member2));
399 }
400
401 // connect a widget to a setter function in gig::DimensionRegion
402 template<typename C, typename T>
403 void connect(C& widget,
404 void (gig::DimensionRegion::*setter)(T)) {
405 connect<C, T>(widget,
406 sigc::hide<0>(sigc::mem_fun(setter)));
407 }
408
409 // helper function for the connect functions above
410 template<typename C, typename T>
411 void connect(C& widget,
412 sigc::slot<void, DimRegionEdit&, gig::DimensionRegion&, T> setter) {
413 widget.signal_value_changed().connect(
414 sigc::compose(sigc::bind(sigc::mem_fun(*this, &DimRegionEdit::set_many<T>), setter),
415 sigc::mem_fun(widget, &C::get_value)));
416 }
417
418 // loop through all dimregions being edited and set a value in
419 // each of them
420 template<typename T>
421 void set_many(T value,
422 sigc::slot<void, DimRegionEdit&, gig::DimensionRegion&, T> setter) {
423 if (update_model == 0) {
424 for (std::set<gig::DimensionRegion*>::iterator i = dimregs.begin() ;
425 i != dimregs.end() ; ++i)
426 {
427 DimRegionChangeGuard(this, *i);
428 setter(*this, **i, value);
429 }
430 }
431 }
432
433 // set a value of a member variable in the given dimregion
434 template<typename T>
435 void set_member(gig::DimensionRegion& d, T value,
436 T gig::DimensionRegion::* member) {
437 d.*member = value;
438 }
439
440 // set a value of a member of a struct member variable in the given dimregion
441 template<typename T, typename S>
442 void set_sub_member(gig::DimensionRegion& d, T value,
443 S gig::DimensionRegion::* member, T S::* member2) {
444 d.*member.*member2 = value;
445 }
446
447 // setters for specific dimregion parameters
448
449 void set_UnityNote(gig::DimensionRegion& d, uint8_t value);
450 void set_FineTune(gig::DimensionRegion& d, int16_t value);
451 void set_Crossfade_in_start(gig::DimensionRegion& d, uint8_t value);
452 void set_Crossfade_in_end(gig::DimensionRegion& d, uint8_t value);
453 void set_Crossfade_out_start(gig::DimensionRegion& d, uint8_t value);
454 void set_Crossfade_out_end(gig::DimensionRegion& d, uint8_t value);
455 void set_Gain(gig::DimensionRegion& d, int32_t value);
456 void set_LoopEnabled(gig::DimensionRegion& d, bool value);
457 void set_LoopType(gig::DimensionRegion& d, uint32_t value);
458 void set_LoopStart(gig::DimensionRegion& d, uint32_t value);
459 void set_LoopLength(gig::DimensionRegion& d, uint32_t value);
460 void set_LoopInfinite(gig::DimensionRegion& d, bool value);
461 void set_LoopPlayCount(gig::DimensionRegion& d, uint32_t value);
462
463 void onButtonSelectSamplePressed();
464 };
465
466 #endif

  ViewVC Help
Powered by ViewVC