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

Diff of /gigedit/trunk/src/gigedit/dimregionedit.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2536 by schoenebeck, Mon Apr 21 17:49:17 2014 UTC revision 3619 by schoenebeck, Tue Oct 1 16:21:28 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006-2014 Andreas Persson   * Copyright (C) 2006-2019 Andreas Persson
3   *   *
4   * This program is free software; you can redistribute it and/or   * This program is free software; you can redistribute it and/or
5   * modify it under the terms of the GNU General Public License as   * modify it under the terms of the GNU General Public License as
# Line 17  Line 17 
17   * 02110-1301 USA.   * 02110-1301 USA.
18   */   */
19    
20    #include "global.h"
21  #include "dimregionedit.h"  #include "dimregionedit.h"
22    
 #include "global.h"  
23  #include "compat.h"  #include "compat.h"
24    
25    #if USE_GTKMM_GRID
26    # include <gtkmm/grid.h>
27    #else
28    # include <gtkmm/table.h>
29    #endif
30    
31    #include "Settings.h"
32    
33  VelocityCurve::VelocityCurve(double (gig::DimensionRegion::*getter)(uint8_t)) :  VelocityCurve::VelocityCurve(double (gig::DimensionRegion::*getter)(uint8_t)) :
34      getter(getter), dimreg(0) {      getter(getter), dimreg(0) {
35      set_size_request(80, 80);      set_size_request(80, 80);
# Line 31  VelocityCurve::VelocityCurve(double (gig Line 39  VelocityCurve::VelocityCurve(double (gig
39  bool VelocityCurve::on_expose_event(GdkEventExpose* e) {  bool VelocityCurve::on_expose_event(GdkEventExpose* e) {
40      const Cairo::RefPtr<Cairo::Context>& cr =      const Cairo::RefPtr<Cairo::Context>& cr =
41          get_window()->create_cairo_context();          get_window()->create_cairo_context();
 #if 0  
 }  
 #endif  
42  #else  #else
43  bool VelocityCurve::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {  bool VelocityCurve::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
44  #endif  #endif
# Line 76  CrossfadeCurve::CrossfadeCurve() : dimre Line 81  CrossfadeCurve::CrossfadeCurve() : dimre
81  bool CrossfadeCurve::on_expose_event(GdkEventExpose* e) {  bool CrossfadeCurve::on_expose_event(GdkEventExpose* e) {
82      const Cairo::RefPtr<Cairo::Context>& cr =      const Cairo::RefPtr<Cairo::Context>& cr =
83          get_window()->create_cairo_context();          get_window()->create_cairo_context();
 #if 0  
 }  
 #endif  
84  #else  #else
85  bool CrossfadeCurve::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {  bool CrossfadeCurve::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
86  #endif  #endif
# Line 147  void CrossfadeCurve::draw_one_curve(cons Line 149  void CrossfadeCurve::draw_one_curve(cons
149  }  }
150    
151    
152    LFOGraph::LFOGraph() : dimreg(0) {
153        set_size_request(500, 100);
154    }
155    
156    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
157    bool LFOGraph::on_expose_event(GdkEventExpose* e) {
158        const Cairo::RefPtr<Cairo::Context>& cr =
159            get_window()->create_cairo_context();
160    #else
161    bool LFOGraph::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) {
162    #endif
163        if (dimreg) {
164            const int w = get_width();
165            const int h = get_height();
166            const bool sensitive = is_sensitive();
167            const bool signedRange = this->signedRange();
168            const float visiblePeriods = 5.f; // such that minimum LFO frequency 0.1 Hz draws exactly a half period
169    
170            // short-hand functions for setting colors
171            auto setGrayColor = [&] {
172                cr->set_source_rgba(0.88, 0.88, 0.88, sensitive ? 1.0 : 0.3);
173            };
174            auto setBlackColor = [&] {
175                cr->set_source_rgba(0, 0, 0, sensitive ? 1.0 : 0.3);
176            };
177            auto setGreenColor = [&] {
178                cr->set_source_rgba(94/255.f, 219/255.f, 80/255.f, sensitive ? 1.0 : 0.3);
179            };
180            auto setRedColor = [&] {
181                cr->set_source_rgba(255.f, 44/255.f, 44/255.f, sensitive ? 1.0 : 0.3);
182            };
183            /*auto setBlueColor = [&] {
184                cr->set_source_rgba(53/255.f, 167/255.f, 255.f, sensitive ? 1.0 : 0.3);
185            };*/
186            auto setOrangeColor = [&] {
187                cr->set_source_rgba(255.f, 177/255.f, 82/255.f, sensitive ? 1.0 : 0.3);
188            };
189    
190            // draw horizontal center line (dashed gray) if LFO range is signed
191            if (signedRange) {
192                cr->move_to(0, h/2);
193                cr->line_to(w, h/2);
194                cr->set_line_width(2);
195                setGrayColor();
196                cr->set_dash(std::vector<double>{ 7, 5 }, 0 /*offset*/);
197                cr->stroke();
198            }
199    
200            // draw a vertical line for each second
201            for (int period = 1; period < visiblePeriods; ++period) {
202                int x = float(w) / float(visiblePeriods) * period;
203                cr->move_to(x, 0);
204                cr->line_to(x, h);
205                cr->set_line_width(2);
206                setGrayColor();
207                cr->set_dash(std::vector<double>{ 5, 3 }, 0 /*offset*/);
208                cr->stroke();
209            }
210    
211            // how many curves shall we draw, two or one?
212            const int runs = (hasControllerAssigned()) ? 2 : 1;
213            // only draw the two curves in dashed style if they're very close to each other
214            const bool dashedCurves = (runs == 2 && controllerDepth() < 63);
215            // draw the required amount of curves
216            for (int run = 0; run < runs; ++run) {
217                // setup the LFO generator with the relevant parameters
218                lfo.setup({
219                    .waveType = LinuxSampler::LFO::wave_sine, // see https://sourceforge.net/p/linuxsampler/mailman/linuxsampler-devel/thread/2189307.cNP0Xbctxq%40silver/#msg36774029
220                    .rangeType = (signedRange) ? LinuxSampler::LFO::range_signed : LinuxSampler::LFO::range_unsigned,
221                    .frequency = frequency(),
222                    //.phase = TODO
223                    .startLevel = startLevel(),
224                    .internalDepth = internalDepth(),
225                    .midiControllerDepth = controllerDepth(),
226                    .flipPolarity = flipPolarity(),
227                    .samplerate = w / visiblePeriods,
228                    .maxValue = (signedRange) ? h/2 : h,
229                });
230                // 1st curve reflects min. CC value, 2nd curve max. CC value
231                lfo.setMIDICtrlValue( (run == 0) ? 0 : 127 );
232    
233                // the actual render/draw loop
234                for (int x = 0; x < w ; ++x) {
235                    const float y =
236                        (signedRange) ?
237                            h/2 - lfo.render() :
238                            h   - lfo.render();
239                    if (x == 0)
240                        cr->move_to(x, y);
241                    else
242                        cr->line_to(x, y);
243                }
244                cr->set_line_width( (frequency() <= 4.f) ? 2 : 1 );
245                if (runs == 1)
246                    setOrangeColor();
247                else if (run == 0)
248                    setGreenColor();
249                else
250                    setRedColor();
251                if (dashedCurves)
252                    cr->set_dash(std::vector<double>{ 3, 3 }, (run == 0) ? 0 : 3 /*offset*/);
253                else
254                    cr->set_dash(std::vector<double>(), 0 /*offset*/);
255                cr->stroke();
256            }
257    
258            // draw text legend
259            if (runs == 2) {
260                setRedColor();
261                cr->move_to(2, 10);
262                cr->show_text("CC Max.");
263    
264                setGreenColor();
265                cr->move_to(2, 23);
266                cr->show_text("CC Min.");
267            } else { // no controller assigned, internal depth only ...
268                setOrangeColor();
269                cr->move_to(2, 10);
270                cr->show_text("Const. Depth");
271            }
272            // draw text legend for each second ("1s", "2s", ...)
273            for (int period = 1; period < visiblePeriods; ++period) {
274                int x = float(w) / float(visiblePeriods) * period;
275                setBlackColor();
276                cr->move_to(x - 13, h - 3);
277                cr->show_text(ToString(period) + "s");
278            }
279        }
280        return true;
281    }
282    
283    
284    EGStateOptions::EGStateOptions() : HBox(),
285        label(_("May be cancelled: ")),
286        checkBoxAttack(_("Attack")),
287        checkBoxAttackHold(_("Attack Hold")),
288        checkBoxDecay1(_("Decay 1")),
289        checkBoxDecay2(_("Decay 2")),
290        checkBoxRelease(_("Release"))
291    {
292        set_spacing(6);
293    
294        pack_start(label);
295        pack_start(checkBoxAttack, Gtk::PACK_SHRINK);
296        pack_start(checkBoxAttackHold, Gtk::PACK_SHRINK);
297        pack_start(checkBoxDecay1, Gtk::PACK_SHRINK);
298        pack_start(checkBoxDecay2, Gtk::PACK_SHRINK);
299        pack_start(checkBoxRelease, Gtk::PACK_SHRINK);
300    
301        checkBoxAttack.set_tooltip_text(_(
302            "If checked: a note-off aborts the 'attack' stage."
303        ));
304        checkBoxAttackHold.set_tooltip_text(_(
305            "If checked: a note-off aborts the 'attack hold' stage."
306        ));
307        checkBoxDecay1.set_tooltip_text(_(
308            "If checked: a note-off aborts the 'decay 1' stage."
309        ));
310        checkBoxDecay2.set_tooltip_text(_(
311            "If checked: a note-off aborts the 'decay 2' stage."
312        ));
313        checkBoxRelease.set_tooltip_text(_(
314            "If checked: a note-on reverts back from the 'release' stage."
315        ));
316    }
317    
318    void EGStateOptions::on_show_tooltips_changed() {
319        const bool b = Settings::singleton()->showTooltips;
320    
321        checkBoxAttack.set_has_tooltip(b);
322        checkBoxAttackHold.set_has_tooltip(b);
323        checkBoxDecay1.set_has_tooltip(b);
324        checkBoxDecay2.set_has_tooltip(b);
325        checkBoxRelease.set_has_tooltip(b);
326    }
327    
328    
329  DimRegionEdit::DimRegionEdit() :  DimRegionEdit::DimRegionEdit() :
330      velocity_curve(&gig::DimensionRegion::GetVelocityAttenuation),      velocity_curve(&gig::DimensionRegion::GetVelocityAttenuation),
331      release_curve(&gig::DimensionRegion::GetVelocityRelease),      release_curve(&gig::DimensionRegion::GetVelocityRelease),
332      cutoff_curve(&gig::DimensionRegion::GetVelocityCutoff),      cutoff_curve(&gig::DimensionRegion::GetVelocityCutoff),
333      eEG1PreAttack(_("Pre-attack"), 0, 100, 2),      eEG1PreAttack(_("Pre-attack Level (%)"), 0, 100, 2),
334      eEG1Attack(_("Attack"), 0, 60, 3),      eEG1Attack(_("Attack Time (seconds)"), 0, 60, 3),
335      eEG1Decay1(_("Decay 1"), 0.005, 60, 3),      eEG1Decay1(_("Decay 1 Time (seconds)"), 0.005, 60, 3),
336      eEG1Decay2(_("Decay 2"), 0, 60, 3),      eEG1Decay2(_("Decay 2 Time (seconds)"), 0, 60, 3),
337      eEG1InfiniteSustain(_("Infinite sustain")),      eEG1InfiniteSustain(_("Infinite sustain")),
338      eEG1Sustain(_("Sustain"), 0, 100, 2),      eEG1Sustain(_("Sustain Level (%)"), 0, 100, 2),
339      eEG1Release(_("Release"), 0, 60, 3),      eEG1Release(_("Release Time (seconds)"), 0, 60, 3),
340      eEG1Hold(_("Hold")),      eEG1Hold(_("Hold Attack Stage until Loop End")),
341      eEG1Controller(_("Controller")),      eEG1Controller(_("Controller")),
342      eEG1ControllerInvert(_("Controller invert")),      eEG1ControllerInvert(_("Controller invert")),
343      eEG1ControllerAttackInfluence(_("Controller attack influence"), 0, 3),      eEG1ControllerAttackInfluence(_("Controller attack influence"), 0, 3),
# Line 170  DimRegionEdit::DimRegionEdit() : Line 349  DimRegionEdit::DimRegionEdit() :
349      eLFO1Controller(_("Controller")),      eLFO1Controller(_("Controller")),
350      eLFO1FlipPhase(_("Flip phase")),      eLFO1FlipPhase(_("Flip phase")),
351      eLFO1Sync(_("Sync")),      eLFO1Sync(_("Sync")),
352      eEG2PreAttack(_("Pre-attack"), 0, 100, 2),      eEG2PreAttack(_("Pre-attack Level (%)"), 0, 100, 2),
353      eEG2Attack(_("Attack"), 0, 60, 3),      eEG2Attack(_("Attack Time (seconds)"), 0, 60, 3),
354      eEG2Decay1(_("Decay 1"), 0.005, 60, 3),      eEG2Decay1(_("Decay 1 Time (seconds)"), 0.005, 60, 3),
355      eEG2Decay2(_("Decay 2"), 0, 60, 3),      eEG2Decay2(_("Decay 2 Time (seconds)"), 0, 60, 3),
356      eEG2InfiniteSustain(_("Infinite sustain")),      eEG2InfiniteSustain(_("Infinite sustain")),
357      eEG2Sustain(_("Sustain"), 0, 100, 2),      eEG2Sustain(_("Sustain Level (%)"), 0, 100, 2),
358      eEG2Release(_("Release"), 0, 60, 3),      eEG2Release(_("Release Time (seconds)"), 0, 60, 3),
359      eEG2Controller(_("Controller")),      eEG2Controller(_("Controller")),
360      eEG2ControllerInvert(_("Controller invert")),      eEG2ControllerInvert(_("Controller invert")),
361      eEG2ControllerAttackInfluence(_("Controller attack influence"), 0, 3),      eEG2ControllerAttackInfluence(_("Controller attack influence"), 0, 3),
# Line 219  DimRegionEdit::DimRegionEdit() : Line 398  DimRegionEdit::DimRegionEdit() :
398      eCrossfade_out_start(_("Crossfade-out start")),      eCrossfade_out_start(_("Crossfade-out start")),
399      eCrossfade_out_end(_("Crossfade-out end")),      eCrossfade_out_end(_("Crossfade-out end")),
400      ePitchTrack(_("Pitch track")),      ePitchTrack(_("Pitch track")),
401        eSustainReleaseTrigger(_("Sustain Release Trigger")),
402        eNoNoteOffReleaseTrigger(_("No note-off release trigger")),
403      eDimensionBypass(_("Dimension bypass")),      eDimensionBypass(_("Dimension bypass")),
404      ePan(_("Pan"), -64, 63),      ePan(_("Pan"), -64, 63),
405      eSelfMask(_("One note/voice per key (a.k.a \"Self mask\")")),      eSelfMask(_("Kill lower velocity voices (a.k.a \"Self mask\")")),
406      eAttenuationController(_("Attenuation controller")),      eAttenuationController(_("Attenuation controller")),
407      eInvertAttenuationController(_("Invert attenuation controller")),      eInvertAttenuationController(_("Invert attenuation controller")),
408      eAttenuationControllerThreshold(_("Attenuation controller threshold")),      eAttenuationControllerThreshold(_("Attenuation controller threshold")),
409      eChannelOffset(_("Channel offset"), 0, 9),      eChannelOffset(_("Channel offset"), 0, 9),
410      eSustainDefeat(_("Ignore Hold Pedal (a.k.a. \"Sustain defeat\")")),      eSustainDefeat(_("Ignore Hold Pedal (a.k.a. \"Sustain defeat\")")),
411      eMSDecode(_("MS decode")),      eMSDecode(_("Decode Mid/Side Recordings")),
412      eSampleStartOffset(_("Sample start offset"), 0, 2000),      eSampleStartOffset(_("Sample start offset"), 0, 2000),
413      eUnityNote(_("Unity note")),      eUnityNote(_("Unity note")),
414        eSampleGroup(_("Sample Group")),
415        eSampleFormatInfo(_("Sample Format")),
416        eSampleID("Sample ID"),
417        eChecksum("Wave Data CRC-32"),
418      eFineTune(_("Fine tune"), -49, 50),      eFineTune(_("Fine tune"), -49, 50),
419      eGain(_("Gain"), -96, 0, 2, -655360),      eGain(_("Gain"), -96, 0, 2, -655360),
420      eGainPlus6(_("Gain +6dB"), eGain, 6 * -655360),      eGainPlus6(_("Gain +6dB"), eGain, 6 * -655360),
421      eSampleLoopEnabled(_("Enabled")),      eSampleLoopEnabled(_("Enabled")),
422      eSampleLoopStart(_("Loop start positon")),      eSampleLoopStart(_("Loop start position")),
423      eSampleLoopLength(_("Loop size")),      eSampleLoopLength(_("Loop size")),
424      eSampleLoopType(_("Loop type")),      eSampleLoopType(_("Loop type")),
425      eSampleLoopInfinite(_("Infinite loop")),      eSampleLoopInfinite(_("Infinite loop")),
426      eSampleLoopPlayCount(_("Playback count"), 1),      eSampleLoopPlayCount(_("Playback count"), 1),
427        buttonSelectSample(UNICODE_LEFT_ARROW + "  " + _("Select Sample")),
428      update_model(0)      update_model(0)
429  {  {
430        // make synthesis parameter page tabs scrollable
431        // (workaround for GTK3: default theme uses huge tabs which breaks layout)
432        set_scrollable();
433    
434      connect(eEG1PreAttack, &gig::DimensionRegion::EG1PreAttack);      connect(eEG1PreAttack, &gig::DimensionRegion::EG1PreAttack);
435      connect(eEG1Attack, &gig::DimensionRegion::EG1Attack);      connect(eEG1Attack, &gig::DimensionRegion::EG1Attack);
436      connect(eEG1Decay1, &gig::DimensionRegion::EG1Decay1);      connect(eEG1Decay1, &gig::DimensionRegion::EG1Decay1);
# Line 257  DimRegionEdit::DimRegionEdit() : Line 447  DimRegionEdit::DimRegionEdit() :
447              &gig::DimensionRegion::EG1ControllerDecayInfluence);              &gig::DimensionRegion::EG1ControllerDecayInfluence);
448      connect(eEG1ControllerReleaseInfluence,      connect(eEG1ControllerReleaseInfluence,
449              &gig::DimensionRegion::EG1ControllerReleaseInfluence);              &gig::DimensionRegion::EG1ControllerReleaseInfluence);
450        connect(eEG1StateOptions.checkBoxAttack, &gig::DimensionRegion::EG1Options,
451                &gig::eg_opt_t::AttackCancel);
452        connect(eEG1StateOptions.checkBoxAttackHold, &gig::DimensionRegion::EG1Options,
453                &gig::eg_opt_t::AttackHoldCancel);
454        connect(eEG1StateOptions.checkBoxDecay1, &gig::DimensionRegion::EG1Options,
455                &gig::eg_opt_t::Decay1Cancel);
456        connect(eEG1StateOptions.checkBoxDecay2, &gig::DimensionRegion::EG1Options,
457                &gig::eg_opt_t::Decay2Cancel);
458        connect(eEG1StateOptions.checkBoxRelease, &gig::DimensionRegion::EG1Options,
459                &gig::eg_opt_t::ReleaseCancel);
460      connect(eLFO1Frequency, &gig::DimensionRegion::LFO1Frequency);      connect(eLFO1Frequency, &gig::DimensionRegion::LFO1Frequency);
461      connect(eLFO1InternalDepth, &gig::DimensionRegion::LFO1InternalDepth);      connect(eLFO1InternalDepth, &gig::DimensionRegion::LFO1InternalDepth);
462      connect(eLFO1ControlDepth, &gig::DimensionRegion::LFO1ControlDepth);      connect(eLFO1ControlDepth, &gig::DimensionRegion::LFO1ControlDepth);
# Line 278  DimRegionEdit::DimRegionEdit() : Line 478  DimRegionEdit::DimRegionEdit() :
478              &gig::DimensionRegion::EG2ControllerDecayInfluence);              &gig::DimensionRegion::EG2ControllerDecayInfluence);
479      connect(eEG2ControllerReleaseInfluence,      connect(eEG2ControllerReleaseInfluence,
480              &gig::DimensionRegion::EG2ControllerReleaseInfluence);              &gig::DimensionRegion::EG2ControllerReleaseInfluence);
481        connect(eEG2StateOptions.checkBoxAttack, &gig::DimensionRegion::EG2Options,
482                &gig::eg_opt_t::AttackCancel);
483        connect(eEG2StateOptions.checkBoxAttackHold, &gig::DimensionRegion::EG2Options,
484                &gig::eg_opt_t::AttackHoldCancel);
485        connect(eEG2StateOptions.checkBoxDecay1, &gig::DimensionRegion::EG2Options,
486                &gig::eg_opt_t::Decay1Cancel);
487        connect(eEG2StateOptions.checkBoxDecay2, &gig::DimensionRegion::EG2Options,
488                &gig::eg_opt_t::Decay2Cancel);
489        connect(eEG2StateOptions.checkBoxRelease, &gig::DimensionRegion::EG2Options,
490                &gig::eg_opt_t::ReleaseCancel);
491      connect(eLFO2Frequency, &gig::DimensionRegion::LFO2Frequency);      connect(eLFO2Frequency, &gig::DimensionRegion::LFO2Frequency);
492      connect(eLFO2InternalDepth, &gig::DimensionRegion::LFO2InternalDepth);      connect(eLFO2InternalDepth, &gig::DimensionRegion::LFO2InternalDepth);
493      connect(eLFO2ControlDepth, &gig::DimensionRegion::LFO2ControlDepth);      connect(eLFO2ControlDepth, &gig::DimensionRegion::LFO2ControlDepth);
# Line 325  DimRegionEdit::DimRegionEdit() : Line 535  DimRegionEdit::DimRegionEdit() :
535      connect(eCrossfade_out_start, &DimRegionEdit::set_Crossfade_out_start);      connect(eCrossfade_out_start, &DimRegionEdit::set_Crossfade_out_start);
536      connect(eCrossfade_out_end, &DimRegionEdit::set_Crossfade_out_end);      connect(eCrossfade_out_end, &DimRegionEdit::set_Crossfade_out_end);
537      connect(ePitchTrack, &gig::DimensionRegion::PitchTrack);      connect(ePitchTrack, &gig::DimensionRegion::PitchTrack);
538        connect(eSustainReleaseTrigger, &gig::DimensionRegion::SustainReleaseTrigger);
539        connect(eNoNoteOffReleaseTrigger, &gig::DimensionRegion::NoNoteOffReleaseTrigger);
540      connect(eDimensionBypass, &gig::DimensionRegion::DimensionBypass);      connect(eDimensionBypass, &gig::DimensionRegion::DimensionBypass);
541      connect(ePan, &gig::DimensionRegion::Pan);      connect(ePan, &gig::DimensionRegion::Pan);
542      connect(eSelfMask, &gig::DimensionRegion::SelfMask);      connect(eSelfMask, &gig::DimensionRegion::SelfMask);
# Line 348  DimRegionEdit::DimRegionEdit() : Line 560  DimRegionEdit::DimRegionEdit() :
560      connect(eSampleLoopLength, &DimRegionEdit::set_LoopLength);      connect(eSampleLoopLength, &DimRegionEdit::set_LoopLength);
561      connect(eSampleLoopInfinite, &DimRegionEdit::set_LoopInfinite);      connect(eSampleLoopInfinite, &DimRegionEdit::set_LoopInfinite);
562      connect(eSampleLoopPlayCount, &DimRegionEdit::set_LoopPlayCount);      connect(eSampleLoopPlayCount, &DimRegionEdit::set_LoopPlayCount);
563        buttonSelectSample.signal_clicked().connect(
564            sigc::mem_fun(*this, &DimRegionEdit::onButtonSelectSamplePressed)
565        );
566    
567      for (int i = 0 ; i < 7 ; i++) {      for (int i = 0 ; i < 9 ; i++) {
568    #if USE_GTKMM_GRID
569            table[i] = new Gtk::Grid;
570            table[i]->set_column_spacing(7);
571    #else
572          table[i] = new Gtk::Table(3, 1);          table[i] = new Gtk::Table(3, 1);
573          table[i]->set_col_spacings(7);          table[i]->set_col_spacings(7);
574    #endif
575    
576    // on Gtk 3 there is absolutely no margin by default
577    #if GTKMM_MAJOR_VERSION >= 3
578    # if GTKMM_MAJOR_VERSION == 3 && GTKMM_MINOR_VERSION < 12
579            table[i]->set_margin_left(12);
580            table[i]->set_margin_right(12);
581    # else
582            table[i]->set_margin_start(12);
583            table[i]->set_margin_end(12);
584    # endif
585    #endif
586      }      }
587    
588      // set tooltips      // set tooltips
589      eUnityNote.set_tip(      eUnityNote.set_tip(
590          _("Note this sample is associated with (a.k.a. 'root note')")          _("Note this sample is associated with (a.k.a. 'root note')")
591      );      );
592        buttonSelectSample.set_tooltip_text(
593            _("Selects the sample of this dimension region on the left hand side's sample tree view.")
594        );
595      eSampleStartOffset.set_tip(_("Sample position at which playback should be started"));      eSampleStartOffset.set_tip(_("Sample position at which playback should be started"));
596      ePan.set_tip(_("Stereo balance (left/right)"));      ePan.set_tip(_("Stereo balance (left/right)"));
597      eChannelOffset.set_tip(      eChannelOffset.set_tip(
# Line 388  DimRegionEdit::DimRegionEdit() : Line 622  DimRegionEdit::DimRegionEdit() :
622            "Caution: this setting is stored on Sample side, thus is shared "            "Caution: this setting is stored on Sample side, thus is shared "
623            "among all dimension regions that use this sample!")            "among all dimension regions that use this sample!")
624      );      );
625        
626        eEG1PreAttack.set_tip(
627            "Very first level this EG starts with. It rises then in Attack Time "
628            "seconds from this initial level to 100%."
629        );
630        eEG1Attack.set_tip(
631            "Duration of the EG's Attack stage, which raises its level from "
632            "Pre-Attack Level to 100%."
633        );
634        eEG1Hold.set_tip(
635           "On looped sounds, enabling this will cause the Decay 1 stage not to "
636           "enter before the loop has been passed one time."
637        );
638        eAttenuationController.set_tip(_(
639            "If you are not using the 'Layer' dimension, then this controller "
640            "simply alters the volume. If you are using the 'Layer' dimension, "
641            "then this controller is controlling the crossfade between Layers in "
642            "real-time."
643        ));
644    
645        eLFO1Sync.set_tip(
646            "If not checked, every voice will use its own LFO instance, which "
647            "causes voices triggered at different points in time to have different "
648            "LFO levels. By enabling 'Sync' here the voices will instead use and "
649            "share one single LFO, causing all voices to have the same LFO level, "
650            "no matter when the individual notes have been triggered."
651        );
652        eLFO2Sync.set_tip(
653            "If not checked, every voice will use its own LFO instance, which "
654            "causes voices triggered at different points in time to have different "
655            "LFO levels. By enabling 'Sync' here the voices will instead use and "
656            "share one single LFO, causing all voices to have the same LFO level, "
657            "no matter when the individual notes have been triggered."
658        );
659        eLFO3Sync.set_tip(
660            "If not checked, every voice will use its own LFO instance, which "
661            "causes voices triggered at different points in time to have different "
662            "LFO levels. By enabling 'Sync' here the voices will instead use and "
663            "share one single LFO, causing all voices to have the same LFO level, "
664            "no matter when the individual notes have been triggered."
665        );
666        eLFO1FlipPhase.set_tip(
667           "Inverts the LFO's generated wave vertically."
668        );
669        eLFO2FlipPhase.set_tip(
670           "Inverts the LFO's generated wave vertically."
671        );
672    
673      pageno = 0;      pageno = 0;
674      rowno = 0;      rowno = 0;
675      firstRowInBlock = 0;      firstRowInBlock = 0;
676    
677      addHeader(_("Mandatory Settings"));      addHeader(_("Mandatory Settings"));
678      addString(_("Sample"), lSample, wSample);      addString(_("Sample"), lSample, wSample, buttonNullSampleReference);
679        buttonNullSampleReference->set_label("X");
680        buttonNullSampleReference->set_tooltip_text(_("Remove current sample reference (NULL reference). This can be used to define a \"silent\" case where no sample shall be played."));
681        buttonNullSampleReference->signal_clicked().connect(
682            sigc::mem_fun(*this, &DimRegionEdit::nullOutSampleReference)
683        );
684      //TODO: the following would break drag&drop:   wSample->property_editable().set_value(false);  or this:    wSample->set_editable(false);      //TODO: the following would break drag&drop:   wSample->property_editable().set_value(false);  or this:    wSample->set_editable(false);
685  #ifdef OLD_TOOLTIPS  #ifdef OLD_TOOLTIPS
686      tooltips.set_tip(*wSample, _("Drag & drop a sample here"));      tooltips.set_tip(*wSample, _("Drag & drop a sample here"));
# Line 402  DimRegionEdit::DimRegionEdit() : Line 688  DimRegionEdit::DimRegionEdit() :
688      wSample->set_tooltip_text(_("Drag & drop a sample here"));      wSample->set_tooltip_text(_("Drag & drop a sample here"));
689  #endif  #endif
690      addProp(eUnityNote);      addProp(eUnityNote);
691        addProp(eSampleGroup);
692        addProp(eSampleFormatInfo);
693        addProp(eSampleID);
694        addProp(eChecksum);
695        addRightHandSide(buttonSelectSample);
696      addHeader(_("Optional Settings"));      addHeader(_("Optional Settings"));
697      addProp(eSampleStartOffset);      addProp(eSampleStartOffset);
698      addProp(eChannelOffset);      addProp(eChannelOffset);
# Line 431  DimRegionEdit::DimRegionEdit() : Line 722  DimRegionEdit::DimRegionEdit() :
722      addHeader(_("Amplitude Envelope (EG1)"));      addHeader(_("Amplitude Envelope (EG1)"));
723      addProp(eEG1PreAttack);      addProp(eEG1PreAttack);
724      addProp(eEG1Attack);      addProp(eEG1Attack);
725        addProp(eEG1Hold);
726      addProp(eEG1Decay1);      addProp(eEG1Decay1);
727      addProp(eEG1Decay2);      addProp(eEG1Decay2);
728      addProp(eEG1InfiniteSustain);      addProp(eEG1InfiniteSustain);
729      addProp(eEG1Sustain);      addProp(eEG1Sustain);
730      addProp(eEG1Release);      addProp(eEG1Release);
     addProp(eEG1Hold);  
731      addProp(eEG1Controller);      addProp(eEG1Controller);
732      addProp(eEG1ControllerInvert);      addProp(eEG1ControllerInvert);
733      addProp(eEG1ControllerAttackInfluence);      addProp(eEG1ControllerAttackInfluence);
734      addProp(eEG1ControllerDecayInfluence);      addProp(eEG1ControllerDecayInfluence);
735      addProp(eEG1ControllerReleaseInfluence);      addProp(eEG1ControllerReleaseInfluence);
736        addLine(eEG1StateOptions);
737    
738      nextPage();      nextPage();
739    
# Line 464  DimRegionEdit::DimRegionEdit() : Line 756  DimRegionEdit::DimRegionEdit() :
756      addProp(eLFO1Controller);      addProp(eLFO1Controller);
757      addProp(eLFO1FlipPhase);      addProp(eLFO1FlipPhase);
758      addProp(eLFO1Sync);      addProp(eLFO1Sync);
759        {
760            Gtk::Frame* frame = new Gtk::Frame;
761            frame->add(lfo1Graph);
762            // on Gtk 3 there is no margin at all by default
763    #if GTKMM_MAJOR_VERSION >= 3
764            frame->set_margin_top(12);
765            frame->set_margin_bottom(12);
766    #endif
767    #if USE_GTKMM_GRID
768            table[pageno]->attach(*frame, 1, rowno, 2);
769    #else
770            table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
771                                  Gtk::SHRINK, Gtk::SHRINK);
772    #endif
773            rowno++;
774        }
775        eLFO1FlipPhase.signal_value_changed().connect(
776            sigc::mem_fun(lfo1Graph, &LFOGraph::queue_draw)
777        );
778    
779        nextPage();
780    
781      addHeader(_("Crossfade"));      addHeader(_("Crossfade"));
782      addProp(eAttenuationController);      addProp(eAttenuationController);
783      addProp(eInvertAttenuationController);      addProp(eInvertAttenuationController);
# Line 475  DimRegionEdit::DimRegionEdit() : Line 789  DimRegionEdit::DimRegionEdit() :
789    
790      Gtk::Frame* frame = new Gtk::Frame;      Gtk::Frame* frame = new Gtk::Frame;
791      frame->add(crossfade_curve);      frame->add(crossfade_curve);
792        // on Gtk 3 there is no margin at all by default
793    #if GTKMM_MAJOR_VERSION >= 3
794        frame->set_margin_top(12);
795        frame->set_margin_bottom(12);
796    #endif
797    #if USE_GTKMM_GRID
798        table[pageno]->attach(*frame, 1, rowno, 2);
799    #else
800      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
801                            Gtk::SHRINK, Gtk::SHRINK);                            Gtk::SHRINK, Gtk::SHRINK);
802    #endif
803      rowno++;      rowno++;
804    
805      eCrossfade_in_start.signal_value_changed().connect(      eCrossfade_in_start.signal_value_changed().connect(
# Line 550  DimRegionEdit::DimRegionEdit() : Line 873  DimRegionEdit::DimRegionEdit() :
873    
874      frame = new Gtk::Frame;      frame = new Gtk::Frame;
875      frame->add(cutoff_curve);      frame->add(cutoff_curve);
876        // on Gtk 3 there is no margin at all by default
877    #if GTKMM_MAJOR_VERSION >= 3
878        frame->set_margin_top(12);
879        frame->set_margin_bottom(12);
880    #endif
881    #if USE_GTKMM_GRID
882        table[pageno]->attach(*frame, 1, rowno, 2);
883    #else
884      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
885                            Gtk::SHRINK, Gtk::SHRINK);                            Gtk::SHRINK, Gtk::SHRINK);
886    #endif
887      rowno++;      rowno++;
888    
889      addProp(eVCFResonance);      addProp(eVCFResonance);
# Line 587  DimRegionEdit::DimRegionEdit() : Line 919  DimRegionEdit::DimRegionEdit() :
919      addProp(eEG2ControllerAttackInfluence);      addProp(eEG2ControllerAttackInfluence);
920      addProp(eEG2ControllerDecayInfluence);      addProp(eEG2ControllerDecayInfluence);
921      addProp(eEG2ControllerReleaseInfluence);      addProp(eEG2ControllerReleaseInfluence);
922        addLine(eEG2StateOptions);
923    
924        nextPage();
925    
926      lLFO2 = addHeader(_("Filter Cutoff Oscillator (LFO2)"));      lLFO2 = addHeader(_("Filter Cutoff Oscillator (LFO2)"));
927      addProp(eLFO2Frequency);      addProp(eLFO2Frequency);
928      addProp(eLFO2InternalDepth);      addProp(eLFO2InternalDepth);
# Line 606  DimRegionEdit::DimRegionEdit() : Line 942  DimRegionEdit::DimRegionEdit() :
942      addProp(eLFO2Controller);      addProp(eLFO2Controller);
943      addProp(eLFO2FlipPhase);      addProp(eLFO2FlipPhase);
944      addProp(eLFO2Sync);      addProp(eLFO2Sync);
945        {
946            Gtk::Frame* frame = new Gtk::Frame;
947            frame->add(lfo2Graph);
948            // on Gtk 3 there is no margin at all by default
949    #if GTKMM_MAJOR_VERSION >= 3
950            frame->set_margin_top(12);
951            frame->set_margin_bottom(12);
952    #endif
953    #if USE_GTKMM_GRID
954            table[pageno]->attach(*frame, 1, rowno, 2);
955    #else
956            table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
957                                  Gtk::SHRINK, Gtk::SHRINK);
958    #endif
959            rowno++;
960        }
961        eLFO2FlipPhase.signal_value_changed().connect(
962            sigc::mem_fun(lfo2Graph, &LFOGraph::queue_draw)
963        );
964    
965      nextPage();      nextPage();
966    
# Line 633  DimRegionEdit::DimRegionEdit() : Line 988  DimRegionEdit::DimRegionEdit() :
988      }      }
989      addProp(eLFO3Controller);      addProp(eLFO3Controller);
990      addProp(eLFO3Sync);      addProp(eLFO3Sync);
991        {
992            Gtk::Frame* frame = new Gtk::Frame;
993            frame->add(lfo3Graph);
994            // on Gtk 3 there is no margin at all by default
995    #if GTKMM_MAJOR_VERSION >= 3
996            frame->set_margin_top(12);
997            frame->set_margin_bottom(12);
998    #endif
999    #if USE_GTKMM_GRID
1000            table[pageno]->attach(*frame, 1, rowno, 2);
1001    #else
1002            table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
1003                                  Gtk::SHRINK, Gtk::SHRINK);
1004    #endif
1005            rowno++;
1006        }
1007    
1008      nextPage();      nextPage();
1009    
1010      addHeader(_("Velocity Reponse"));      addHeader(_("Velocity Response"));
1011      eVelocityResponseCurve.set_choices(curve_type_texts, curve_type_values);      eVelocityResponseCurve.set_choices(curve_type_texts, curve_type_values);
1012      addProp(eVelocityResponseCurve);      addProp(eVelocityResponseCurve);
1013      addProp(eVelocityResponseDepth);      addProp(eVelocityResponseDepth);
# Line 651  DimRegionEdit::DimRegionEdit() : Line 1022  DimRegionEdit::DimRegionEdit() :
1022    
1023      frame = new Gtk::Frame;      frame = new Gtk::Frame;
1024      frame->add(velocity_curve);      frame->add(velocity_curve);
1025        // on Gtk 3 there is no margin at all by default
1026    #if GTKMM_MAJOR_VERSION >= 3
1027        frame->set_margin_top(12);
1028        frame->set_margin_bottom(12);
1029    #endif
1030    #if USE_GTKMM_GRID
1031        table[pageno]->attach(*frame, 1, rowno, 2);
1032    #else
1033      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
1034                            Gtk::SHRINK, Gtk::SHRINK);                            Gtk::SHRINK, Gtk::SHRINK);
1035    #endif
1036      rowno++;      rowno++;
1037    
1038      addHeader(_("Release Velocity Reponse"));      addHeader(_("Release Velocity Response"));
1039      eReleaseVelocityResponseCurve.set_choices(curve_type_texts,      eReleaseVelocityResponseCurve.set_choices(curve_type_texts,
1040                                                curve_type_values);                                                curve_type_values);
1041      addProp(eReleaseVelocityResponseCurve);      addProp(eReleaseVelocityResponseCurve);
# Line 667  DimRegionEdit::DimRegionEdit() : Line 1047  DimRegionEdit::DimRegionEdit() :
1047          sigc::mem_fun(release_curve, &VelocityCurve::queue_draw));          sigc::mem_fun(release_curve, &VelocityCurve::queue_draw));
1048      frame = new Gtk::Frame;      frame = new Gtk::Frame;
1049      frame->add(release_curve);      frame->add(release_curve);
1050        // on Gtk 3 there is no margin at all by default
1051    #if GTKMM_MAJOR_VERSION >= 3
1052        frame->set_margin_top(12);
1053        frame->set_margin_bottom(12);
1054    #endif
1055    #if USE_GTKMM_GRID
1056        table[pageno]->attach(*frame, 1, rowno, 2);
1057    #else
1058      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,      table[pageno]->attach(*frame, 1, 3, rowno, rowno + 1,
1059                            Gtk::SHRINK, Gtk::SHRINK);                            Gtk::SHRINK, Gtk::SHRINK);
1060    #endif
1061      rowno++;      rowno++;
1062    
1063      addProp(eReleaseTriggerDecay);      addProp(eReleaseTriggerDecay);
1064      {      {
1065            const char* choices[] = { _("off"), _("on (max. velocity)"), _("on (key velocity)"), 0 };
1066            static const gig::sust_rel_trg_t values[] = {
1067                gig::sust_rel_trg_none,
1068                gig::sust_rel_trg_maxvelocity,
1069                gig::sust_rel_trg_keyvelocity
1070            };
1071            eSustainReleaseTrigger.set_choices(choices, values);
1072        }
1073        eSustainReleaseTrigger.set_tip(_(
1074            "By default release trigger samples are played on note-off events only. "
1075            "This option allows to play release trigger sample on sustain pedal up "
1076            "events as well. NOTE: This is a format extension!"
1077        ));
1078        addProp(eSustainReleaseTrigger);
1079        {
1080          const char* choices[] = { _("none"), _("effect4depth"), _("effect5depth"), 0 };          const char* choices[] = { _("none"), _("effect4depth"), _("effect5depth"), 0 };
1081          static const gig::dim_bypass_ctrl_t values[] = {          static const gig::dim_bypass_ctrl_t values[] = {
1082              gig::dim_bypass_ctrl_none,              gig::dim_bypass_ctrl_none,
# Line 681  DimRegionEdit::DimRegionEdit() : Line 1085  DimRegionEdit::DimRegionEdit() :
1085          };          };
1086          eDimensionBypass.set_choices(choices, values);          eDimensionBypass.set_choices(choices, values);
1087      }      }
1088        eNoNoteOffReleaseTrigger.set_tip(_(
1089            "By default release trigger samples are played on note-off events only. "
1090            "If this option is checked, then no release trigger sample is played "
1091            "when releasing a note. NOTE: This is a format extension!"
1092        ));
1093        addProp(eNoNoteOffReleaseTrigger);
1094      addProp(eDimensionBypass);      addProp(eDimensionBypass);
1095      eSelfMask.widget.set_tooltip_text(_("If enabled: high velocity notes will stop low velocity notes at the same note, that way you can save voices that wouldn't be audible anyway."));      eSelfMask.widget.set_tooltip_text(_(
1096            "If enabled: new notes with higher velocity value will stop older "
1097            "notes with lower velocity values, that way you can save voices that "
1098            "would barely be audible. This is also useful for certain drum sounds."
1099        ));
1100      addProp(eSelfMask);      addProp(eSelfMask);
1101      eSustainDefeat.widget.set_tooltip_text(_("If enabled: sustain pedal will not hold a note."));      eSustainDefeat.widget.set_tooltip_text(_(
1102            "If enabled: sustain pedal will not hold a note. This way you can use "
1103            "the sustain pedal for other purposes, for example to switch among "
1104            "dimension regions."
1105        ));
1106      addProp(eSustainDefeat);      addProp(eSustainDefeat);
1107      eMSDecode.widget.set_tooltip_text(_("Gigastudio specific flag: defines if Mid Side Recordings should be decoded."));      eMSDecode.widget.set_tooltip_text(_(
1108            "Defines if Mid/Side Recordings should be decoded. Mid/Side Recordings "
1109            "are an alternative way to record sounds in stereo. The sampler needs "
1110            "to decode such samples to actually make use of them. Note: this "
1111            "feature is currently not supported by LinuxSampler."
1112        ));
1113      addProp(eMSDecode);      addProp(eMSDecode);
1114    
1115      nextPage();      nextPage();
# Line 734  DimRegionEdit::DimRegionEdit() : Line 1157  DimRegionEdit::DimRegionEdit() :
1157          sigc::mem_fun(*this, &DimRegionEdit::loop_infinite_toggled));          sigc::mem_fun(*this, &DimRegionEdit::loop_infinite_toggled));
1158    
1159      append_page(*table[0], _("Sample"));      append_page(*table[0], _("Sample"));
1160      append_page(*table[1], _("Amplitude (1)"));      append_page(*table[1], _("Amp (1)"));
1161      append_page(*table[2], _("Amplitude (2)"));      append_page(*table[2], _("Amp (2)"));
1162      append_page(*table[3], _("Filter (1)"));      append_page(*table[3], _("Amp (3)"));
1163      append_page(*table[4], _("Filter (2)"));      append_page(*table[4], _("Filter (1)"));
1164      append_page(*table[5], _("Pitch"));      append_page(*table[5], _("Filter (2)"));
1165      append_page(*table[6], _("Misc"));      append_page(*table[6], _("Filter (3)"));
1166        append_page(*table[7], _("Pitch"));
1167        append_page(*table[8], _("Misc"));
1168    
1169        Settings::singleton()->showTooltips.get_proxy().signal_changed().connect(
1170            sigc::mem_fun(*this, &DimRegionEdit::on_show_tooltips_changed)
1171        );
1172    
1173        on_show_tooltips_changed();
1174  }  }
1175    
1176  DimRegionEdit::~DimRegionEdit()  DimRegionEdit::~DimRegionEdit()
# Line 750  void DimRegionEdit::addString(const char Line 1181  void DimRegionEdit::addString(const char
1181                                Gtk::Entry*& widget)                                Gtk::Entry*& widget)
1182  {  {
1183      label = new Gtk::Label(Glib::ustring(labelText) + ":");      label = new Gtk::Label(Glib::ustring(labelText) + ":");
1184    #if HAS_GTKMM_ALIGNMENT
1185      label->set_alignment(Gtk::ALIGN_START);      label->set_alignment(Gtk::ALIGN_START);
1186    #else
1187        label->set_halign(Gtk::Align::START);
1188    #endif
1189    
1190    #if USE_GTKMM_GRID
1191        table[pageno]->attach(*label, 1, rowno);
1192    #else
1193      table[pageno]->attach(*label, 1, 2, rowno, rowno + 1,      table[pageno]->attach(*label, 1, 2, rowno, rowno + 1,
1194                            Gtk::FILL, Gtk::SHRINK);                            Gtk::FILL, Gtk::SHRINK);
1195    #endif
1196    
1197      widget = new Gtk::Entry();      widget = new Gtk::Entry();
1198    
1199    #if USE_GTKMM_GRID
1200        table[pageno]->attach(*widget, 2, rowno);
1201    #else
1202      table[pageno]->attach(*widget, 2, 3, rowno, rowno + 1,      table[pageno]->attach(*widget, 2, 3, rowno, rowno + 1,
1203                            Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);                            Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
1204    #endif
1205    
1206        rowno++;
1207    }
1208    
1209    void DimRegionEdit::addString(const char* labelText, Gtk::Label*& label,
1210                                  Gtk::Entry*& widget, Gtk::Button*& button)
1211    {
1212        label = new Gtk::Label(Glib::ustring(labelText) + ":");
1213    #if HAS_GTKMM_ALIGNMENT
1214        label->set_alignment(Gtk::ALIGN_START);
1215    #else
1216        label->set_halign(Gtk::Align::START);
1217    #endif
1218    
1219    #if USE_GTKMM_GRID
1220        table[pageno]->attach(*label, 1, rowno);
1221    #else
1222        table[pageno]->attach(*label, 1, 2, rowno, rowno + 1,
1223                              Gtk::FILL, Gtk::SHRINK);
1224    #endif
1225    
1226        widget = new Gtk::Entry();
1227        button = new Gtk::Button();
1228    
1229        HBox* hbox = new HBox;
1230        hbox->pack_start(*widget);
1231        hbox->pack_start(*button, Gtk::PACK_SHRINK);
1232    
1233    #if USE_GTKMM_GRID
1234        table[pageno]->attach(*hbox, 2, rowno);
1235    #else
1236        table[pageno]->attach(*hbox, 2, 3, rowno, rowno + 1,
1237                              Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
1238    #endif
1239    
1240      rowno++;      rowno++;
1241  }  }
# Line 768  Gtk::Label* DimRegionEdit::addHeader(con Line 1245  Gtk::Label* DimRegionEdit::addHeader(con
1245      if (firstRowInBlock < rowno - 1)      if (firstRowInBlock < rowno - 1)
1246      {      {
1247          Gtk::Label* filler = new Gtk::Label("    ");          Gtk::Label* filler = new Gtk::Label("    ");
1248    #if USE_GTKMM_GRID
1249            table[pageno]->attach(*filler, 0, firstRowInBlock);
1250    #else
1251          table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,          table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,
1252                                Gtk::FILL, Gtk::SHRINK);                                Gtk::FILL, Gtk::SHRINK);
1253    #endif
1254      }      }
1255      Glib::ustring str = "<b>";      Glib::ustring str = "<b>";
1256      str += text;      str += text;
1257      str += "</b>";      str += "</b>";
1258      Gtk::Label* label = new Gtk::Label(str);      Gtk::Label* label = new Gtk::Label(str);
1259      label->set_use_markup();      label->set_use_markup();
1260    #if HAS_GTKMM_ALIGNMENT
1261      label->set_alignment(Gtk::ALIGN_START);      label->set_alignment(Gtk::ALIGN_START);
1262    #else
1263        label->set_halign(Gtk::Align::START);
1264    #endif
1265        // on GTKMM 3 there is absolutely no margin by default
1266    #if GTKMM_MAJOR_VERSION >= 3
1267        label->set_margin_top(18);
1268        label->set_margin_bottom(13);
1269    #endif
1270    #if USE_GTKMM_GRID
1271        table[pageno]->attach(*label, 0, rowno, 3);
1272    #else
1273      table[pageno]->attach(*label, 0, 3, rowno, rowno + 1,      table[pageno]->attach(*label, 0, 3, rowno, rowno + 1,
1274                            Gtk::FILL, Gtk::SHRINK);                            Gtk::FILL, Gtk::SHRINK);
1275    #endif
1276      rowno++;      rowno++;
1277      firstRowInBlock = rowno;      firstRowInBlock = rowno;
1278      return label;      return label;
1279  }  }
1280    
1281    void DimRegionEdit::on_show_tooltips_changed() {
1282        const bool b = Settings::singleton()->showTooltips;
1283    
1284        buttonSelectSample.set_has_tooltip(b);
1285        buttonNullSampleReference->set_has_tooltip(b);
1286        wSample->set_has_tooltip(b);
1287    
1288        eEG1StateOptions.on_show_tooltips_changed();
1289        eEG2StateOptions.on_show_tooltips_changed();
1290    
1291        set_has_tooltip(b);
1292    }
1293    
1294  void DimRegionEdit::nextPage()  void DimRegionEdit::nextPage()
1295  {  {
1296      if (firstRowInBlock < rowno - 1)      if (firstRowInBlock < rowno - 1)
1297      {      {
1298          Gtk::Label* filler = new Gtk::Label("    ");          Gtk::Label* filler = new Gtk::Label("    ");
1299    #if USE_GTKMM_GRID
1300            table[pageno]->attach(*filler, 0, firstRowInBlock);
1301    #else
1302          table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,          table[pageno]->attach(*filler, 0, 1, firstRowInBlock, rowno,
1303                                Gtk::FILL, Gtk::SHRINK);                                Gtk::FILL, Gtk::SHRINK);
1304    #endif
1305      }      }
1306      pageno++;      pageno++;
1307      rowno = 0;      rowno = 0;
# Line 799  void DimRegionEdit::nextPage() Line 1310  void DimRegionEdit::nextPage()
1310    
1311  void DimRegionEdit::addProp(BoolEntry& boolentry)  void DimRegionEdit::addProp(BoolEntry& boolentry)
1312  {  {
1313    #if USE_GTKMM_GRID
1314        table[pageno]->attach(boolentry.widget, 1, rowno, 2);
1315    #else
1316      table[pageno]->attach(boolentry.widget, 1, 3, rowno, rowno + 1,      table[pageno]->attach(boolentry.widget, 1, 3, rowno, rowno + 1,
1317                            Gtk::FILL, Gtk::SHRINK);                            Gtk::FILL, Gtk::SHRINK);
1318    #endif
1319      rowno++;      rowno++;
1320  }  }
1321    
1322  void DimRegionEdit::addProp(BoolEntryPlus6& boolentry)  void DimRegionEdit::addProp(BoolEntryPlus6& boolentry)
1323  {  {
1324    #if USE_GTKMM_GRID
1325        table[pageno]->attach(boolentry.widget, 1, rowno, 2);
1326    #else
1327      table[pageno]->attach(boolentry.widget, 1, 3, rowno, rowno + 1,      table[pageno]->attach(boolentry.widget, 1, 3, rowno, rowno + 1,
1328                            Gtk::FILL, Gtk::SHRINK);                            Gtk::FILL, Gtk::SHRINK);
1329    #endif
1330      rowno++;      rowno++;
1331  }  }
1332    
1333  void DimRegionEdit::addProp(LabelWidget& prop)  void DimRegionEdit::addProp(LabelWidget& prop)
1334  {  {
1335    #if USE_GTKMM_GRID
1336        table[pageno]->attach(prop.label, 1, rowno);
1337        table[pageno]->attach(prop.widget, 2, rowno);
1338    #else
1339      table[pageno]->attach(prop.label, 1, 2, rowno, rowno + 1,      table[pageno]->attach(prop.label, 1, 2, rowno, rowno + 1,
1340                            Gtk::FILL, Gtk::SHRINK);                            Gtk::FILL, Gtk::SHRINK);
1341      table[pageno]->attach(prop.widget, 2, 3, rowno, rowno + 1,      table[pageno]->attach(prop.widget, 2, 3, rowno, rowno + 1,
1342                            Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);                            Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
1343    #endif
1344      rowno++;      rowno++;
1345  }  }
1346    
1347    void DimRegionEdit::addLine(HBox& line)
1348    {
1349    #if USE_GTKMM_GRID
1350        table[pageno]->attach(line, 1, rowno, 2);
1351    #else
1352        table[pageno]->attach(line, 1, 3, rowno, rowno + 1,
1353                              Gtk::FILL, Gtk::SHRINK);
1354    #endif
1355        rowno++;
1356    }
1357    
1358    void DimRegionEdit::addRightHandSide(Gtk::Widget& widget)
1359    {
1360    #if USE_GTKMM_GRID
1361        table[pageno]->attach(widget, 2, rowno);
1362    #else
1363        table[pageno]->attach(widget, 2, 3, rowno, rowno + 1,
1364                              Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
1365    #endif
1366        rowno++;
1367    }
1368    
1369  void DimRegionEdit::set_dim_region(gig::DimensionRegion* d)  void DimRegionEdit::set_dim_region(gig::DimensionRegion* d)
1370  {  {
# Line 828  void DimRegionEdit::set_dim_region(gig:: Line 1373  void DimRegionEdit::set_dim_region(gig::
1373      release_curve.set_dim_region(d);      release_curve.set_dim_region(d);
1374      cutoff_curve.set_dim_region(d);      cutoff_curve.set_dim_region(d);
1375      crossfade_curve.set_dim_region(d);      crossfade_curve.set_dim_region(d);
1376        lfo1Graph.set_dim_region(d);
1377        lfo2Graph.set_dim_region(d);
1378        lfo3Graph.set_dim_region(d);
1379    
1380      set_sensitive(d);      set_sensitive(d);
1381      if (!d) return;      if (!d) return;
# Line 846  void DimRegionEdit::set_dim_region(gig:: Line 1394  void DimRegionEdit::set_dim_region(gig::
1394      eEG1ControllerAttackInfluence.set_value(d->EG1ControllerAttackInfluence);      eEG1ControllerAttackInfluence.set_value(d->EG1ControllerAttackInfluence);
1395      eEG1ControllerDecayInfluence.set_value(d->EG1ControllerDecayInfluence);      eEG1ControllerDecayInfluence.set_value(d->EG1ControllerDecayInfluence);
1396      eEG1ControllerReleaseInfluence.set_value(d->EG1ControllerReleaseInfluence);      eEG1ControllerReleaseInfluence.set_value(d->EG1ControllerReleaseInfluence);
1397        eEG1StateOptions.checkBoxAttack.set_value(d->EG1Options.AttackCancel);
1398        eEG1StateOptions.checkBoxAttackHold.set_value(d->EG1Options.AttackHoldCancel);
1399        eEG1StateOptions.checkBoxDecay1.set_value(d->EG1Options.Decay1Cancel);
1400        eEG1StateOptions.checkBoxDecay2.set_value(d->EG1Options.Decay2Cancel);
1401        eEG1StateOptions.checkBoxRelease.set_value(d->EG1Options.ReleaseCancel);
1402      eLFO1Frequency.set_value(d->LFO1Frequency);      eLFO1Frequency.set_value(d->LFO1Frequency);
1403      eLFO1InternalDepth.set_value(d->LFO1InternalDepth);      eLFO1InternalDepth.set_value(d->LFO1InternalDepth);
1404      eLFO1ControlDepth.set_value(d->LFO1ControlDepth);      eLFO1ControlDepth.set_value(d->LFO1ControlDepth);
# Line 864  void DimRegionEdit::set_dim_region(gig:: Line 1417  void DimRegionEdit::set_dim_region(gig::
1417      eEG2ControllerAttackInfluence.set_value(d->EG2ControllerAttackInfluence);      eEG2ControllerAttackInfluence.set_value(d->EG2ControllerAttackInfluence);
1418      eEG2ControllerDecayInfluence.set_value(d->EG2ControllerDecayInfluence);      eEG2ControllerDecayInfluence.set_value(d->EG2ControllerDecayInfluence);
1419      eEG2ControllerReleaseInfluence.set_value(d->EG2ControllerReleaseInfluence);      eEG2ControllerReleaseInfluence.set_value(d->EG2ControllerReleaseInfluence);
1420        eEG2StateOptions.checkBoxAttack.set_value(d->EG2Options.AttackCancel);
1421        eEG2StateOptions.checkBoxAttackHold.set_value(d->EG2Options.AttackHoldCancel);
1422        eEG2StateOptions.checkBoxDecay1.set_value(d->EG2Options.Decay1Cancel);
1423        eEG2StateOptions.checkBoxDecay2.set_value(d->EG2Options.Decay2Cancel);
1424        eEG2StateOptions.checkBoxRelease.set_value(d->EG2Options.ReleaseCancel);
1425      eLFO2Frequency.set_value(d->LFO2Frequency);      eLFO2Frequency.set_value(d->LFO2Frequency);
1426      eLFO2InternalDepth.set_value(d->LFO2InternalDepth);      eLFO2InternalDepth.set_value(d->LFO2InternalDepth);
1427      eLFO2ControlDepth.set_value(d->LFO2ControlDepth);      eLFO2ControlDepth.set_value(d->LFO2ControlDepth);
# Line 901  void DimRegionEdit::set_dim_region(gig:: Line 1459  void DimRegionEdit::set_dim_region(gig::
1459      eCrossfade_out_start.set_value(d->Crossfade.out_start);      eCrossfade_out_start.set_value(d->Crossfade.out_start);
1460      eCrossfade_out_end.set_value(d->Crossfade.out_end);      eCrossfade_out_end.set_value(d->Crossfade.out_end);
1461      ePitchTrack.set_value(d->PitchTrack);      ePitchTrack.set_value(d->PitchTrack);
1462        eSustainReleaseTrigger.set_value(d->SustainReleaseTrigger);
1463        eNoNoteOffReleaseTrigger.set_value(d->NoNoteOffReleaseTrigger);
1464      eDimensionBypass.set_value(d->DimensionBypass);      eDimensionBypass.set_value(d->DimensionBypass);
1465      ePan.set_value(d->Pan);      ePan.set_value(d->Pan);
1466      eSelfMask.set_value(d->SelfMask);      eSelfMask.set_value(d->SelfMask);
# Line 912  void DimRegionEdit::set_dim_region(gig:: Line 1472  void DimRegionEdit::set_dim_region(gig::
1472      eMSDecode.set_value(d->MSDecode);      eMSDecode.set_value(d->MSDecode);
1473      eSampleStartOffset.set_value(d->SampleStartOffset);      eSampleStartOffset.set_value(d->SampleStartOffset);
1474      eUnityNote.set_value(d->UnityNote);      eUnityNote.set_value(d->UnityNote);
1475        // show sample group name
1476        {
1477            Glib::ustring s = "---";
1478            if (d->pSample && d->pSample->GetGroup())
1479                s = d->pSample->GetGroup()->Name;
1480            eSampleGroup.text.set_text(s);
1481        }
1482        // assemble sample format info string
1483        {
1484            Glib::ustring s;
1485            if (d->pSample) {
1486                switch (d->pSample->Channels) {
1487                    case 1: s = _("Mono"); break;
1488                    case 2: s = _("Stereo"); break;
1489                    default:
1490                        s = ToString(d->pSample->Channels) + _(" audio channels");
1491                        break;
1492                }
1493                s += " " + ToString(d->pSample->BitDepth) + " Bits";
1494                s += " " + ToString(d->pSample->SamplesPerSecond/1000) + "."
1495                          + ToString((d->pSample->SamplesPerSecond%1000)/100) + " kHz";
1496            } else {
1497                s = _("No sample assigned to this dimension region.");
1498            }
1499            eSampleFormatInfo.text.set_text(s);
1500        }
1501        // generate sample's memory address pointer string
1502        {
1503            Glib::ustring s;
1504            if (d->pSample) {
1505                char buf[64] = {};
1506                snprintf(buf, sizeof(buf), "%p", d->pSample);
1507                s = buf;
1508            } else {
1509                s = "---";
1510            }
1511            eSampleID.text.set_text(s);
1512        }
1513        // generate raw wave form data CRC-32 checksum string
1514        {
1515            Glib::ustring s = "---";
1516            if (d->pSample) {
1517                char buf[64] = {};
1518                snprintf(buf, sizeof(buf), "%x", d->pSample->GetWaveDataCRC32Checksum());
1519                s = buf;
1520            }
1521            eChecksum.text.set_text(s);
1522        }
1523        buttonSelectSample.set_sensitive(d && d->pSample);
1524      eFineTune.set_value(d->FineTune);      eFineTune.set_value(d->FineTune);
1525      eGain.set_value(d->Gain);      eGain.set_value(d->Gain);
1526      eGainPlus6.set_value(d->Gain);      eGainPlus6.set_value(d->Gain);
# Line 960  void DimRegionEdit::VCFEnabled_toggled() Line 1569  void DimRegionEdit::VCFEnabled_toggled()
1569      eEG2ControllerAttackInfluence.set_sensitive(sensitive);      eEG2ControllerAttackInfluence.set_sensitive(sensitive);
1570      eEG2ControllerDecayInfluence.set_sensitive(sensitive);      eEG2ControllerDecayInfluence.set_sensitive(sensitive);
1571      eEG2ControllerReleaseInfluence.set_sensitive(sensitive);      eEG2ControllerReleaseInfluence.set_sensitive(sensitive);
1572        eEG2StateOptions.set_sensitive(sensitive);
1573      lLFO2->set_sensitive(sensitive);      lLFO2->set_sensitive(sensitive);
1574      eLFO2Frequency.set_sensitive(sensitive);      eLFO2Frequency.set_sensitive(sensitive);
1575      eLFO2InternalDepth.set_sensitive(sensitive);      eLFO2InternalDepth.set_sensitive(sensitive);
# Line 967  void DimRegionEdit::VCFEnabled_toggled() Line 1577  void DimRegionEdit::VCFEnabled_toggled()
1577      eLFO2Controller.set_sensitive(sensitive);      eLFO2Controller.set_sensitive(sensitive);
1578      eLFO2FlipPhase.set_sensitive(sensitive);      eLFO2FlipPhase.set_sensitive(sensitive);
1579      eLFO2Sync.set_sensitive(sensitive);      eLFO2Sync.set_sensitive(sensitive);
1580        lfo2Graph.set_sensitive(sensitive);
1581      if (sensitive) {      if (sensitive) {
1582          VCFCutoffController_changed();          VCFCutoffController_changed();
1583          VCFResonanceController_changed();          VCFResonanceController_changed();
# Line 1153  void DimRegionEdit::loop_infinite_toggle Line 1764  void DimRegionEdit::loop_infinite_toggle
1764    
1765  bool DimRegionEdit::set_sample(gig::Sample* sample, bool copy_sample_unity, bool copy_sample_tune, bool copy_sample_loop)  bool DimRegionEdit::set_sample(gig::Sample* sample, bool copy_sample_unity, bool copy_sample_tune, bool copy_sample_loop)
1766  {  {
1767      if (dimregion) {      bool result = false;
1768        for (std::set<gig::DimensionRegion*>::iterator itDimReg = dimregs.begin();
1769             itDimReg != dimregs.end(); ++itDimReg)
1770        {
1771            result |= set_sample(*itDimReg, sample, copy_sample_unity, copy_sample_tune, copy_sample_loop);
1772        }
1773        return result;
1774    }
1775    
1776    bool DimRegionEdit::set_sample(gig::DimensionRegion* dimreg, gig::Sample* sample, bool copy_sample_unity, bool copy_sample_tune, bool copy_sample_loop)
1777    {
1778        if (dimreg) {
1779          //TODO: we should better move the code from MainWindow::on_sample_label_drop_drag_data_received() here          //TODO: we should better move the code from MainWindow::on_sample_label_drop_drag_data_received() here
1780    
1781          // currently commented because we're sending a similar signal in MainWindow::on_sample_label_drop_drag_data_received()          // currently commented because we're sending a similar signal in MainWindow::on_sample_label_drop_drag_data_received()
1782          //dimreg_to_be_changed_signal.emit(dimregion);          //DimRegionChangeGuard(this, dimregion);
1783    
1784          // make sure stereo samples always are the same in both          // make sure stereo samples always are the same in both
1785          // dimregs in the samplechannel dimension          // dimregs in the samplechannel dimension
1786          int nbDimregs = 1;          int nbDimregs = 1;
1787          gig::DimensionRegion* d[2] = { dimregion, 0 };          gig::DimensionRegion* d[2] = { dimreg, 0 };
1788          if (sample->Channels == 2) {          if (sample->Channels == 2) {
1789              gig::Region* region = dimregion->GetParent();              gig::Region* region = dimreg->GetParent();
1790    
1791              int bitcount = 0;              int bitcount = 0;
1792              int stereo_bit = 0;              int stereo_bit = 0;
# Line 1179  bool DimRegionEdit::set_sample(gig::Samp Line 1801  bool DimRegionEdit::set_sample(gig::Samp
1801              if (stereo_bit) {              if (stereo_bit) {
1802                  int dimregno;                  int dimregno;
1803                  for (dimregno = 0 ; dimregno < region->DimensionRegions ; dimregno++) {                  for (dimregno = 0 ; dimregno < region->DimensionRegions ; dimregno++) {
1804                      if (region->pDimensionRegions[dimregno] == dimregion) {                      if (region->pDimensionRegions[dimregno] == dimreg) {
1805                          break;                          break;
1806                      }                      }
1807                  }                  }
# Line 1189  bool DimRegionEdit::set_sample(gig::Samp Line 1811  bool DimRegionEdit::set_sample(gig::Samp
1811              }              }
1812          }          }
1813    
1814          gig::Sample* oldref = dimregion->pSample;          gig::Sample* oldref = dimreg->pSample;
1815    
1816          for (int i = 0 ; i < nbDimregs ; i++) {          for (int i = 0 ; i < nbDimregs ; i++) {
1817              d[i]->pSample = sample;              d[i]->pSample = sample;
# Line 1219  bool DimRegionEdit::set_sample(gig::Samp Line 1841  bool DimRegionEdit::set_sample(gig::Samp
1841    
1842          // update ui          // update ui
1843          update_model++;          update_model++;
1844          wSample->set_text(gig_to_utf8(dimregion->pSample->pInfo->Name));          wSample->set_text(gig_to_utf8(dimreg->pSample->pInfo->Name));
1845          eUnityNote.set_value(dimregion->UnityNote);          eUnityNote.set_value(dimreg->UnityNote);
1846          eFineTune.set_value(dimregion->FineTune);          eFineTune.set_value(dimreg->FineTune);
1847          eSampleLoopEnabled.set_value(dimregion->SampleLoops);          eSampleLoopEnabled.set_value(dimreg->SampleLoops);
1848          update_loop_elements();          update_loop_elements();
1849          update_model--;          update_model--;
1850    
1851          sample_ref_changed_signal.emit(oldref, sample);          sample_ref_changed_signal.emit(oldref, sample);
         // currently commented because we're sending a similar signal in MainWindow::on_sample_label_drop_drag_data_received()  
         //dimreg_changed_signal.emit(dimregion);  
1852          return true;          return true;
1853      }      }
1854      return false;      return false;
# Line 1247  sigc::signal<void, gig::Sample*/*old*/, Line 1867  sigc::signal<void, gig::Sample*/*old*/,
1867  }  }
1868    
1869    
1870  void DimRegionEdit::set_UnityNote(gig::DimensionRegion* d, uint8_t value)  void DimRegionEdit::set_UnityNote(gig::DimensionRegion& d, uint8_t value)
1871  {  {
1872      d->UnityNote = value;      d.UnityNote = value;
1873  }  }
1874    
1875  void DimRegionEdit::set_FineTune(gig::DimensionRegion* d, int16_t value)  void DimRegionEdit::set_FineTune(gig::DimensionRegion& d, int16_t value)
1876  {  {
1877      d->FineTune = value;      d.FineTune = value;
1878  }  }
1879    
1880  void DimRegionEdit::set_Crossfade_in_start(gig::DimensionRegion* d,  void DimRegionEdit::set_Crossfade_in_start(gig::DimensionRegion& d,
1881                                             uint8_t value)                                             uint8_t value)
1882  {  {
1883      d->Crossfade.in_start = value;      d.Crossfade.in_start = value;
1884      if (d->Crossfade.in_end < value) set_Crossfade_in_end(d, value);      if (d.Crossfade.in_end < value) set_Crossfade_in_end(d, value);
1885  }  }
1886    
1887  void DimRegionEdit::set_Crossfade_in_end(gig::DimensionRegion* d,  void DimRegionEdit::set_Crossfade_in_end(gig::DimensionRegion& d,
1888                                           uint8_t value)                                           uint8_t value)
1889  {  {
1890      d->Crossfade.in_end = value;      d.Crossfade.in_end = value;
1891      if (value < d->Crossfade.in_start) set_Crossfade_in_start(d, value);      if (value < d.Crossfade.in_start) set_Crossfade_in_start(d, value);
1892      if (value > d->Crossfade.out_start) set_Crossfade_out_start(d, value);      if (value > d.Crossfade.out_start) set_Crossfade_out_start(d, value);
1893  }  }
1894    
1895  void DimRegionEdit::set_Crossfade_out_start(gig::DimensionRegion* d,  void DimRegionEdit::set_Crossfade_out_start(gig::DimensionRegion& d,
1896                                              uint8_t value)                                              uint8_t value)
1897  {  {
1898      d->Crossfade.out_start = value;      d.Crossfade.out_start = value;
1899      if (value < d->Crossfade.in_end) set_Crossfade_in_end(d, value);      if (value < d.Crossfade.in_end) set_Crossfade_in_end(d, value);
1900      if (value > d->Crossfade.out_end) set_Crossfade_out_end(d, value);      if (value > d.Crossfade.out_end) set_Crossfade_out_end(d, value);
1901  }  }
1902    
1903  void DimRegionEdit::set_Crossfade_out_end(gig::DimensionRegion* d,  void DimRegionEdit::set_Crossfade_out_end(gig::DimensionRegion& d,
1904                                            uint8_t value)                                            uint8_t value)
1905  {  {
1906      d->Crossfade.out_end = value;      d.Crossfade.out_end = value;
1907      if (value < d->Crossfade.out_start) set_Crossfade_out_start(d, value);      if (value < d.Crossfade.out_start) set_Crossfade_out_start(d, value);
1908  }  }
1909    
1910  void DimRegionEdit::set_Gain(gig::DimensionRegion* d, int32_t value)  void DimRegionEdit::set_Gain(gig::DimensionRegion& d, int32_t value)
1911  {  {
1912      d->SetGain(value);      d.SetGain(value);
1913  }  }
1914    
1915  void DimRegionEdit::set_LoopEnabled(gig::DimensionRegion* d, bool value)  void DimRegionEdit::set_LoopEnabled(gig::DimensionRegion& d, bool value)
1916  {  {
1917      if (value) {      if (value) {
1918          // create a new sample loop in case there is none yet          // create a new sample loop in case there is none yet
1919          if (!d->SampleLoops) {          if (!d.SampleLoops) {
1920                DimRegionChangeGuard(this, &d);
1921    
1922              DLS::sample_loop_t loop;              DLS::sample_loop_t loop;
1923              loop.LoopType = gig::loop_type_normal;              loop.LoopType = gig::loop_type_normal;
1924              // loop the whole sample by default              // loop the whole sample by default
1925              loop.LoopStart  = 0;              loop.LoopStart  = 0;
1926              loop.LoopLength =              loop.LoopLength =
1927                  (d->pSample) ? d->pSample->SamplesTotal : 0;                  (d.pSample) ? d.pSample->SamplesTotal : 0;
1928              dimreg_to_be_changed_signal.emit(d);              d.AddSampleLoop(&loop);
             d->AddSampleLoop(&loop);  
             dimreg_changed_signal.emit(d);  
1929          }          }
1930      } else {      } else {
1931          if (d->SampleLoops) {          if (d.SampleLoops) {
1932              dimreg_to_be_changed_signal.emit(d);              DimRegionChangeGuard(this, &d);
1933    
1934              // delete ALL existing sample loops              // delete ALL existing sample loops
1935              while (d->SampleLoops) {              while (d.SampleLoops) {
1936                  d->DeleteSampleLoop(&d->pSampleLoops[0]);                  d.DeleteSampleLoop(&d.pSampleLoops[0]);
1937              }              }
             dimreg_changed_signal.emit(d);  
1938          }          }
1939      }      }
1940  }  }
1941    
1942  void DimRegionEdit::set_LoopType(gig::DimensionRegion* d, uint32_t value)  void DimRegionEdit::set_LoopType(gig::DimensionRegion& d, uint32_t value)
1943  {  {
1944      if (d->SampleLoops) d->pSampleLoops[0].LoopType = value;      if (d.SampleLoops) d.pSampleLoops[0].LoopType = value;
1945  }  }
1946    
1947  void DimRegionEdit::set_LoopStart(gig::DimensionRegion* d, uint32_t value)  void DimRegionEdit::set_LoopStart(gig::DimensionRegion& d, uint32_t value)
1948  {  {
1949      if (d->SampleLoops) {      if (d.SampleLoops) {
1950          d->pSampleLoops[0].LoopStart =          d.pSampleLoops[0].LoopStart =
1951              d->pSample ?              d.pSample ?
1952              std::min(value, uint32_t(d->pSample->SamplesTotal -              std::min(value, uint32_t(d.pSample->SamplesTotal -
1953                                       d->pSampleLoops[0].LoopLength)) :                                       d.pSampleLoops[0].LoopLength)) :
1954              0;              0;
1955      }      }
1956  }  }
1957    
1958  void DimRegionEdit::set_LoopLength(gig::DimensionRegion* d, uint32_t value)  void DimRegionEdit::set_LoopLength(gig::DimensionRegion& d, uint32_t value)
1959  {  {
1960      if (d->SampleLoops) {      if (d.SampleLoops) {
1961          d->pSampleLoops[0].LoopLength =          d.pSampleLoops[0].LoopLength =
1962              d->pSample ?              d.pSample ?
1963              std::min(value, uint32_t(d->pSample->SamplesTotal -              std::min(value, uint32_t(d.pSample->SamplesTotal -
1964                                       d->pSampleLoops[0].LoopStart)) :                                       d.pSampleLoops[0].LoopStart)) :
1965              0;              0;
1966      }      }
1967  }  }
1968    
1969  void DimRegionEdit::set_LoopInfinite(gig::DimensionRegion* d, bool value)  void DimRegionEdit::set_LoopInfinite(gig::DimensionRegion& d, bool value)
1970  {  {
1971      if (d->pSample) {      if (d.pSample) {
1972          if (value) d->pSample->LoopPlayCount = 0;          if (value) d.pSample->LoopPlayCount = 0;
1973          else if (d->pSample->LoopPlayCount == 0) d->pSample->LoopPlayCount = 1;          else if (d.pSample->LoopPlayCount == 0) d.pSample->LoopPlayCount = 1;
1974      }      }
1975  }  }
1976    
1977  void DimRegionEdit::set_LoopPlayCount(gig::DimensionRegion* d, uint32_t value)  void DimRegionEdit::set_LoopPlayCount(gig::DimensionRegion& d, uint32_t value)
1978  {  {
1979      if (d->pSample) d->pSample->LoopPlayCount = value;      if (d.pSample) d.pSample->LoopPlayCount = value;
1980    }
1981    
1982    void DimRegionEdit::nullOutSampleReference() {
1983        if (!dimregion) return;
1984        gig::Sample* oldref = dimregion->pSample;
1985        if (!oldref) return;
1986    
1987        DimRegionChangeGuard(this, dimregion);
1988    
1989        // in case currently assigned sample is a stereo one, then remove both
1990        // references (expected to be due to a "stereo dimension")
1991        gig::DimensionRegion* d[2] = { dimregion, NULL };
1992        if (oldref->Channels == 2) {
1993            gig::Region* region = dimregion->GetParent();
1994            {
1995                int stereo_bit = 0;
1996                int bitcount = 0;
1997                for (int dim = 0 ; dim < region->Dimensions ; dim++) {
1998                    if (region->pDimensionDefinitions[dim].dimension == gig::dimension_samplechannel) {
1999                        stereo_bit = 1 << bitcount;
2000                        break;
2001                    }
2002                    bitcount += region->pDimensionDefinitions[dim].bits;
2003                }
2004    
2005                if (stereo_bit) {
2006                    int dimregno;
2007                    for (dimregno = 0 ; dimregno < region->DimensionRegions ; dimregno++) {
2008                        if (region->pDimensionRegions[dimregno] == dimregion) {
2009                            break;
2010                        }
2011                    }
2012                    d[0] = region->pDimensionRegions[dimregno & ~stereo_bit];
2013                    d[1] = region->pDimensionRegions[dimregno | stereo_bit];
2014                }
2015            }
2016        }
2017    
2018        if (d[0]) d[0]->pSample = NULL;
2019        if (d[1]) d[1]->pSample = NULL;
2020    
2021        // update UI elements
2022        set_dim_region(dimregion);
2023    
2024        sample_ref_changed_signal.emit(oldref, NULL);
2025    }
2026    
2027    void DimRegionEdit::onButtonSelectSamplePressed() {
2028        if (!dimregion) return;
2029        if (!dimregion->pSample) return;
2030        select_sample_signal.emit(dimregion->pSample);
2031    }
2032    
2033    sigc::signal<void, gig::Sample*>& DimRegionEdit::signal_select_sample() {
2034        return select_sample_signal;
2035  }  }

Legend:
Removed from v.2536  
changed lines
  Added in v.3619

  ViewVC Help
Powered by ViewVC