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

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

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

revision 1225 by schoenebeck, Sun Jun 10 10:56:11 2007 UTC revision 2507 by persson, Sun Jan 12 19:37:55 2014 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (C) 2006, 2007 Andreas Persson   * Copyright (C) 2006-2014 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 <cstring>
21    
22  #include "paramedit.h"  #include "paramedit.h"
23    
24  bool update_gui;  #include "global.h"
25    #include "compat.h"
26    
27    std::string gig_encoding("CP1252");
28    
29    Glib::ustring gig_to_utf8(const gig::String& gig_string) {
30        return Glib::convert_with_fallback(gig_string, "UTF-8", gig_encoding, "?");
31    }
32    
33    gig::String gig_from_utf8(const Glib::ustring& utf8_string) {
34        return Glib::convert_with_fallback(utf8_string, gig_encoding, "UTF-8", "?");
35    }
36    
37    
38  namespace {  namespace {
39      const char* const controlChangeTexts[] = {      const char* const controlChangeTexts[] = {
40          "none", "channelaftertouch", "velocity",          _("none"), _("channelaftertouch"), _("velocity"),
41          0,          0,
42          "modwheel", // "Modulation Wheel or Lever",          _("modwheel"), // "Modulation Wheel or Lever",
43          "breath", // "Breath Controller",          _("breath"), // "Breath Controller",
44          0,          0,
45          "foot", // "Foot Controller",          _("foot"), // "Foot Controller",
46          "portamentotime", // "Portamento Time",          _("portamentotime"), // "Portamento Time",
47          0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0,
48          "effect1", // "Effect Control 1",          _("effect1"), // "Effect Control 1",
49          "effect2", // "Effect Control 2",          _("effect2"), // "Effect Control 2",
50          0, 0,          0, 0,
51          "genpurpose1", // "General Purpose Controller 1",          _("genpurpose1"), // "General Purpose Controller 1",
52          "genpurpose2", // "General Purpose Controller 2",          _("genpurpose2"), // "General Purpose Controller 2",
53          "genpurpose3", // "General Purpose Controller 3",          _("genpurpose3"), // "General Purpose Controller 3",
54          "genpurpose4", // "General Purpose Controller 4",          _("genpurpose4"), // "General Purpose Controller 4",
55          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57          0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0,
58          "sustainpedal", // "Damper Pedal on/off (Sustain)",          _("sustainpedal"), // "Damper Pedal on/off (Sustain)",
59          "portamento", // "Portamento On/Off",          _("portamento"), // "Portamento On/Off",
60          "sostenuto", // "Sustenuto On/Off",          _("sostenuto"), // "Sustenuto On/Off",
61          "softpedal", // "Soft Pedal On/Off",          _("softpedal"), // "Soft Pedal On/Off",
62          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63          "genpurpose5", // "General Purpose Controller 5",          _("genpurpose5"), // "General Purpose Controller 5",
64          "genpurpose6", // "General Purpose Controller 6",          _("genpurpose6"), // "General Purpose Controller 6",
65          "genpurpose7", // "General Purpose Controller 7",          _("genpurpose7"), // "General Purpose Controller 7",
66          "genpurpose8", // "General Purpose Controller 8",          _("genpurpose8"), // "General Purpose Controller 8",
67          0, 0, 0, 0, 0, 0, 0,          0, 0, 0, 0, 0, 0, 0,
68          "effect1depth", // "Effects 1 Depth",          _("effect1depth"), // "Effects 1 Depth",
69          "effect2depth", // "Effects 2 Depth",          _("effect2depth"), // "Effects 2 Depth",
70          "effect3depth", // "Effects 3 Depth",          _("effect3depth"), // "Effects 3 Depth",
71          "effect4depth", // "Effects 4 Depth",          _("effect4depth"), // "Effects 4 Depth",
72          "effect5depth", // "Effects 5 Depth"          _("effect5depth"), // "Effects 5 Depth"
73      };      };
74  }  }
75    
# Line 63  LabelWidget::LabelWidget(const char* lab Line 77  LabelWidget::LabelWidget(const char* lab
77      label(Glib::ustring(labelText) + ":"),      label(Glib::ustring(labelText) + ":"),
78      widget(widget)      widget(widget)
79  {  {
80      label.set_alignment(Gtk::ALIGN_LEFT);      label.set_alignment(Gtk::ALIGN_START);
81  }  }
82    
83  void LabelWidget::set_sensitive(bool sensitive)  void LabelWidget::set_sensitive(bool sensitive)
# Line 74  void LabelWidget::set_sensitive(bool sen Line 88  void LabelWidget::set_sensitive(bool sen
88    
89  NumEntry::NumEntry(const char* labelText, double lower, double upper,  NumEntry::NumEntry(const char* labelText, double lower, double upper,
90                     int decimals) :                     int decimals) :
91        LabelWidget(labelText, box),
92    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
93      adjust(lower, lower, upper, 1, 10),      adjust(lower, lower, upper, 1, 10),
94    #else
95        adjust(Gtk::Adjustment::create(lower, lower, upper, 1, 10)),
96    #endif
97      scale(adjust),      scale(adjust),
98      spinbutton(adjust),      spinbutton(adjust)
     LabelWidget(labelText, box)  
99  {  {
100        scale.set_size_request(70);
101      spinbutton.set_digits(decimals);      spinbutton.set_digits(decimals);
102        spinbutton.set_value(0);
103        spinbutton.set_numeric();
104      scale.set_draw_value(false);      scale.set_draw_value(false);
105      box.pack_start(spinbutton, Gtk::PACK_SHRINK);      box.pack_start(spinbutton, Gtk::PACK_SHRINK);
106      box.add(scale);      box.add(scale);
# Line 89  NumEntryGain::NumEntryGain(const char* l Line 110  NumEntryGain::NumEntryGain(const char* l
110                             double lower, double upper,                             double lower, double upper,
111                             int decimals, double coeff) :                             int decimals, double coeff) :
112      NumEntry(labelText, lower, upper, decimals),      NumEntry(labelText, lower, upper, decimals),
113      coeff(coeff)      value(0),
114        coeff(coeff),
115        connected(true)
116  {  {
117      spinbutton.signal_value_changed().connect(      spinbutton.signal_value_changed().connect(
118          sigc::mem_fun(*this, &NumEntryGain::value_changed));          sigc::mem_fun(*this, &NumEntryGain::value_changed));
# Line 97  NumEntryGain::NumEntryGain(const char* l Line 120  NumEntryGain::NumEntryGain(const char* l
120    
121  void NumEntryGain::value_changed()  void NumEntryGain::value_changed()
122  {  {
123      if (ptr && update_gui) {      if (!connected) return;
124          *ptr = int32_t(spinbutton.get_value() * coeff);  
125        const double f = pow(10, spinbutton.get_digits());
126        int new_value = round_to_int(spinbutton.get_value() * f);
127        if (new_value != round_to_int(value / coeff * f)) {
128            value = round_to_int(new_value / f * coeff);
129            sig_changed();
130      }      }
131  }  }
132    
133  void NumEntryGain::set_ptr(int32_t* ptr)  void NumEntryGain::set_value(int32_t value)
134  {  {
135      this->ptr = 0;      if (value != this->value) {
136      bool plus6 = *ptr < 0;          this->value = value;
137      set_value(plus6 ? 0 : *ptr / coeff);  
138      set_sensitive(!plus6);          connected = false;
139      this->ptr = ptr;          bool plus6 = value < 0;
140            spinbutton.set_value(plus6 ? 0 : value / coeff);
141            set_sensitive(!plus6);
142            connected = true;
143    
144            sig_changed();
145        }
146  }  }
147    
148    
149  BoolEntryPlus6::BoolEntryPlus6(const char* labelText, NumEntryGain& eGain, int32_t plus6value) :  BoolEntryPlus6::BoolEntryPlus6(const char* labelText, NumEntryGain& eGain, int32_t plus6value) :
150      LabelWidget(labelText, checkbutton),      LabelWidget(labelText, checkbutton),
151        checkbutton(labelText),
152      eGain(eGain),      eGain(eGain),
153      plus6value(plus6value)      plus6value(plus6value)
154  {  {
# Line 123  BoolEntryPlus6::BoolEntryPlus6(const cha Line 158  BoolEntryPlus6::BoolEntryPlus6(const cha
158    
159  void BoolEntryPlus6::value_changed()  void BoolEntryPlus6::value_changed()
160  {  {
161      if (ptr && update_gui) {      if (checkbutton.get_active()) eGain.set_value(plus6value);
162          bool plus6 = checkbutton.get_active();      else if (eGain.get_value() < 0) eGain.set_value(0);
163          if (plus6) {  }
164              eGain.set_value(0);  
165              *ptr = plus6value;  int32_t BoolEntryPlus6::get_value() const
166          } else {  {
167              if (*ptr < 0) {      return eGain.get_value();
                 *ptr = 0;  
             }  
         }  
         eGain.set_sensitive(!plus6);  
     }  
168  }  }
169    
170  void BoolEntryPlus6::set_ptr(int32_t* ptr)  void BoolEntryPlus6::set_value(int32_t value)
171  {  {
172      this->ptr = 0;      checkbutton.set_active(value < 0);
     checkbutton.set_active(*ptr < 0);  
     this->ptr = ptr;  
173  }  }
174    
175  NumEntryPermille::NumEntryPermille(const char* labelText,  NumEntryPermille::NumEntryPermille(const char* labelText,
176                                     double lower, double upper, int decimals) :                                     double lower, double upper, int decimals) :
177      NumEntry(labelText, lower, upper, decimals)      NumEntry(labelText, lower, upper, decimals),
178        value(0)
179  {  {
180      spinbutton.signal_value_changed().connect(      spinbutton.signal_value_changed().connect(
181          sigc::mem_fun(*this, &NumEntryPermille::value_changed));          sigc::mem_fun(*this, &NumEntryPermille::value_changed));
# Line 154  NumEntryPermille::NumEntryPermille(const Line 183  NumEntryPermille::NumEntryPermille(const
183    
184  void NumEntryPermille::value_changed()  void NumEntryPermille::value_changed()
185  {  {
186      if (ptr && update_gui) {      uint16_t new_value = uint16_t(spinbutton.get_value() * 10 + 0.5);
187          *ptr = uint16_t(spinbutton.get_value() * 10 + 0.5);      if (new_value != value) {
188            value = uint16_t(spinbutton.get_value() * 10 + 0.5);
189            sig_changed();
190      }      }
191  }  }
192    
193  void NumEntryPermille::set_ptr(uint16_t* ptr)  void NumEntryPermille::set_value(uint16_t value)
194  {  {
195      this->ptr = 0;      if (value != this->value) {
196      set_value(*ptr / 10.0);          spinbutton.set_value(value / 10.0);
197      this->ptr = ptr;      }
198  }  }
199    
200    
201  NoteEntry::NoteEntry(const char* labelText) :  NoteEntry::NoteEntry(const char* labelText) :
202      NumEntryTemp<uint8_t>(labelText)      NumEntryTemp<uint8_t>(labelText)
203  {  {
204      spinbutton.signal_input().connect(      spin_button_show_notes(spinbutton);
         sigc::mem_fun(*this, &NoteEntry::on_input));  
     spinbutton.signal_output().connect(  
         sigc::mem_fun(*this, &NoteEntry::on_output));  
205  }  }
206    
207  const char* notes[] = {  namespace {
208      "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"      const char* notes[] = {
209  };          _("C"), _("C#"), _("D"), _("D#"), _("E"), _("F"),_("F#"),
210            _("G"), _("G#"), _("A"), _("A#"), _("B")
211        };
212    
213        int note_value(const Glib::ustring& note, double* value)
214        {
215            const char* str = note.c_str();
216    
217            int i;
218            for (i = 11 ; i >= 0 ; i--) {
219                if (strncasecmp(str, notes[i], strlen(notes[i])) == 0) break;
220            }
221            if (i >= 0) {
222                char* endptr;
223                long x = strtol(str + strlen(notes[i]), &endptr, 10);
224                if (endptr != str + strlen(notes[i])) {
225                    *value = std::max(0L, std::min(i + (x + 1) * 12, 127L));
226                    return true;
227                }
228            } else {
229                char* endptr;
230                long x = strtol(str, &endptr, 10);
231                if (endptr != str) {
232                    *value = std::max(0L, std::min(x, 127L));
233                    return true;
234                }
235            }
236            return Gtk::INPUT_ERROR;
237        }
238    }
239    
240    int note_value(const Glib::ustring& note)
241    {
242        double value = 0;
243        note_value(note, &value);
244        return value;
245    }
246    
247  // Convert the Entry text to a number  Glib::ustring note_str(int note)
 int NoteEntry::on_input(double* new_value)  
248  {  {
249      const char* str = spinbutton.get_text().c_str();      char buf[10];
250        sprintf(buf, "%s%d", notes[note % 12], note / 12 - 1);
251        return buf;
252    }
253    
254      int i;  namespace {
255      for (i = 11 ; i >= 0 ; i--) {      // Convert the Entry text to a number
256          if (strncmp(str, notes[i], strlen(notes[i])) == 0) break;      int on_input(double* new_value, Gtk::SpinButton* spinbutton) {
257            return note_value(spinbutton->get_text(), new_value);
258      }      }
259      if (i >= 0) {  
260          char* endptr;      // Convert the Adjustment position to text
261          long x = strtol(str + strlen(notes[i]), &endptr, 10);      bool on_output(Gtk::SpinButton* spinbutton) {
262          if (endptr != str + strlen(notes[i])) {          spinbutton->set_text(
263              *new_value = i + (x + 1) * 12;              note_str(spinbutton->get_adjustment()->get_value() + 0.5));
264              return true;          return true;
         }  
265      }      }
     return Gtk::INPUT_ERROR;  
266  }  }
267    
268  // Convert the Adjustment position to text  // Make a SpinButton show notes instead of numbers
269  bool NoteEntry::on_output()  void spin_button_show_notes(Gtk::SpinButton& spin_button)
270  {  {
271      int x = int(spinbutton.get_adjustment()->get_value());      spin_button.set_numeric(false);
272      char buf[10];      spin_button.set_width_chars(4);
273      sprintf(buf, "%s%d", notes[x % 12], x / 12 - 1);      spin_button.signal_input().connect(
274      spinbutton.set_text(buf);          sigc::bind(sigc::ptr_fun(&on_input), &spin_button));
275      return true;      spin_button.signal_output().connect(
276            sigc::bind(sigc::ptr_fun(&on_output), &spin_button));
277  }  }
278    
279  ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(const char* labelText) :  ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(const char* labelText) :
280      align(0, 0, 0, 0),      LabelWidget(labelText, align),
281      LabelWidget(labelText, align)      align(0, 0, 0, 0)
282  {  {
283      for (int i = 0 ; i < 99 ; i++) {      for (int i = 0 ; i < 99 ; i++) {
284          if (controlChangeTexts[i]) {          if (controlChangeTexts[i]) {
285    #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 24) || GTKMM_MAJOR_VERSION < 2
286              combobox.append_text(controlChangeTexts[i]);              combobox.append_text(controlChangeTexts[i]);
287    #else
288                combobox.append(controlChangeTexts[i]);
289    #endif
290          }          }
291      }      }
292      combobox.signal_changed().connect(      combobox.signal_changed().connect(
293          sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));          sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));
294      align.add(combobox);      align.add(combobox);
295        value.type = gig::leverage_ctrl_t::type_none;
296        value.controller_number = 0;
297  }  }
298    
299  void ChoiceEntryLeverageCtrl::value_changed()  void ChoiceEntryLeverageCtrl::value_changed()
300  {  {
301      if (ptr && update_gui) {      int rowno = combobox.get_active_row_number();
302          int rowno = combobox.get_active_row_number();      switch (rowno)
303          switch (rowno)      {
304          {      case -1:
305          case -1:          break;
306              break;      case 0:
307          case 0:          value.type = gig::leverage_ctrl_t::type_none;
308              ptr->type = gig::leverage_ctrl_t::type_none;          break;
309              break;      case 1:
310          case 1:          value.type = gig::leverage_ctrl_t::type_channelaftertouch;
311              ptr->type = gig::leverage_ctrl_t::type_channelaftertouch;          break;
312              break;      case 2:
313          case 2:          value.type = gig::leverage_ctrl_t::type_velocity;
314              ptr->type = gig::leverage_ctrl_t::type_velocity;          break;
315              break;      default:
316          default:          value.type = gig::leverage_ctrl_t::type_controlchange;
317              ptr->type = gig::leverage_ctrl_t::type_controlchange;          int x = 3;
318              int x = 3;          for (uint cc = 0 ; cc < 96 ; cc++) {
319              for (int cc = 0 ; cc < 96 ; cc++) {              if (controlChangeTexts[cc + 3]) {
320                  if (controlChangeTexts[cc + 3]) {                  if (rowno == x) {
321                      if (rowno == x) {                      value.controller_number = cc;
322                          ptr->controller_number = cc;                      break;
                         break;  
                     }  
                     x++;  
323                  }                  }
324                    x++;
325              }              }
             break;  
326          }          }
327            break;
328      }      }
329        if (rowno >= 0) sig_changed();
330  }  }
331    
332  void ChoiceEntryLeverageCtrl::set_ptr(gig::leverage_ctrl_t* ptr)  void ChoiceEntryLeverageCtrl::set_value(gig::leverage_ctrl_t value)
333  {  {
     this->ptr = 0;  
334      int x;      int x;
335      switch (ptr->type)      switch (value.type)
336      {      {
337      case gig::leverage_ctrl_t::type_none:      case gig::leverage_ctrl_t::type_none:
338          x = 0;          x = 0;
# Line 276  void ChoiceEntryLeverageCtrl::set_ptr(gi Line 345  void ChoiceEntryLeverageCtrl::set_ptr(gi
345          break;          break;
346      case gig::leverage_ctrl_t::type_controlchange:      case gig::leverage_ctrl_t::type_controlchange:
347          x = -1;          x = -1;
348          for (int cc = 0 ; cc < 96 ; cc++) {          for (uint cc = 0 ; cc < 96 ; cc++) {
349              if (controlChangeTexts[cc + 3]) {              if (controlChangeTexts[cc + 3]) {
350                  x++;                  x++;
351                  if (ptr->controller_number == cc) {                  if (value.controller_number == cc) {
352                      x += 3;                      x += 3;
353                      break;                      break;
354                  }                  }
# Line 291  void ChoiceEntryLeverageCtrl::set_ptr(gi Line 360  void ChoiceEntryLeverageCtrl::set_ptr(gi
360          break;          break;
361      }      }
362      combobox.set_active(x);      combobox.set_active(x);
     this->ptr = ptr;  
363  }  }
364    
365    
366  BoolEntry::BoolEntry(const char* labelText) :  BoolEntry::BoolEntry(const char* labelText) :
367      LabelWidget(labelText, checkbutton),      LabelWidget(labelText, checkbutton),
368      checkbutton(labelText),      checkbutton(labelText)
     ptr(0)  
369  {  {
370      checkbutton.signal_toggled().connect(      checkbutton.signal_toggled().connect(sig_changed.make_slot());
371          sigc::mem_fun(*this, &BoolEntry::value_changed));  }
372    
373    
374    StringEntry::StringEntry(const char* labelText) :
375        LabelWidget(labelText, entry)
376    {
377        entry.signal_changed().connect(sig_changed.make_slot());
378  }  }
379    
380  void BoolEntry::value_changed()  gig::String StringEntry::get_value() const
381  {  {
382      if (ptr && update_gui) {      return gig_from_utf8(entry.get_text());
383          *ptr = checkbutton.get_active();  }
384      }  
385    void StringEntry::set_value(const gig::String& value) {
386        entry.set_text(gig_to_utf8(value));
387    }
388    
389    
390    StringEntryMultiLine::StringEntryMultiLine(const char* labelText) :
391        LabelWidget(labelText, frame)
392    {
393        text_buffer = text_view.get_buffer();
394        frame.set_shadow_type(Gtk::SHADOW_IN);
395        frame.add(text_view);
396        text_buffer->signal_changed().connect(sig_changed.make_slot());
397  }  }
398    
399  void BoolEntry::set_ptr(bool* ptr)  gig::String StringEntryMultiLine::get_value() const
400  {  {
401      this->ptr = 0;      Glib::ustring value = text_buffer->get_text();
402      checkbutton.set_active(*ptr);      for (int i = 0 ; (i = value.find("\x0a", i)) >= 0 ; i += 2)
403      this->ptr = ptr;          value.replace(i, 1, "\x0d\x0a");
404        return gig_from_utf8(value);
405  }  }
406    
407    void StringEntryMultiLine::set_value(const gig::String& value)
408    {
409        Glib::ustring text = gig_to_utf8(value);
410        for (int i = 0 ; (i = text.find("\x0d\x0a", i, 2)) >= 0 ; i++)
411            text.replace(i, 2, "\x0a");
412        text_buffer->set_text(text);
413    }
414    
415  StringEntry::StringEntry(const char* labelText) :  
416      LabelWidget(labelText, entry)  Table::Table(int x, int y) : Gtk::Table(x, y), rowno(0) {  }
417    
418    void Table::add(BoolEntry& boolentry)
419  {  {
420      entry.signal_changed().connect(      attach(boolentry.widget, 0, 2, rowno, rowno + 1,
421          sigc::mem_fun(*this, &StringEntry::value_changed));             Gtk::FILL, Gtk::SHRINK);
422        rowno++;
423  }  }
424    
425  void StringEntry::value_changed()  void Table::add(BoolEntryPlus6& boolentry)
426  {  {
427      if (ptr && update_gui) {      attach(boolentry.widget, 0, 2, rowno, rowno + 1,
428          *ptr = entry.get_text();             Gtk::FILL, Gtk::SHRINK);
429      }      rowno++;
430  }  }
431    
432  void StringEntry::set_ptr(gig::String* ptr)  void Table::add(LabelWidget& prop)
433  {  {
434      this->ptr = 0;      attach(prop.label, 1, 2, rowno, rowno + 1,
435      entry.set_text(*ptr);             Gtk::FILL, Gtk::SHRINK);
436      this->ptr = ptr;      attach(prop.widget, 2, 3, rowno, rowno + 1,
437               Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
438        rowno++;
439  }  }

Legend:
Removed from v.1225  
changed lines
  Added in v.2507

  ViewVC Help
Powered by ViewVC