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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2423 - (hide annotations) (download)
Sun Feb 24 15:19:39 2013 UTC (11 years, 2 months ago) by persson
File size: 10823 byte(s)
* code refactoring: created a PropEdit class for property editor
  windows, moved Table class from mainwindow to paramedit
* minor gui tweaks: made note entry fields a bit wider, set a minimum
  width for scales
* bug fix: avoid stale information in the instrument properties window
  when a new file is loaded or the instrument is removed

1 schoenebeck 1225 /*
2 persson 2423 * Copyright (C) 2006-2013 Andreas Persson
3 schoenebeck 1225 *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License as
6     * published by the Free Software Foundation; either version 2, or (at
7     * your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful, but
10     * WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12     * General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with program; see the file COPYING. If not, write to the Free
16     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17     * 02110-1301 USA.
18     */
19    
20 persson 1714 #include <cstring>
21    
22 schoenebeck 1225 #include "paramedit.h"
23    
24 persson 1831 #include "global.h"
25 persson 2169 #include "compat.h"
26 persson 1831
27 schoenebeck 1225 namespace {
28     const char* const controlChangeTexts[] = {
29 persson 1831 _("none"), _("channelaftertouch"), _("velocity"),
30 schoenebeck 1225 0,
31 persson 1831 _("modwheel"), // "Modulation Wheel or Lever",
32     _("breath"), // "Breath Controller",
33 schoenebeck 1225 0,
34 persson 1831 _("foot"), // "Foot Controller",
35     _("portamentotime"), // "Portamento Time",
36 schoenebeck 1225 0, 0, 0, 0, 0, 0,
37 persson 1831 _("effect1"), // "Effect Control 1",
38     _("effect2"), // "Effect Control 2",
39 schoenebeck 1225 0, 0,
40 persson 1831 _("genpurpose1"), // "General Purpose Controller 1",
41     _("genpurpose2"), // "General Purpose Controller 2",
42     _("genpurpose3"), // "General Purpose Controller 3",
43     _("genpurpose4"), // "General Purpose Controller 4",
44 schoenebeck 1225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
46     0, 0, 0, 0, 0, 0,
47 persson 1831 _("sustainpedal"), // "Damper Pedal on/off (Sustain)",
48     _("portamento"), // "Portamento On/Off",
49     _("sostenuto"), // "Sustenuto On/Off",
50     _("softpedal"), // "Soft Pedal On/Off",
51 schoenebeck 1225 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 persson 1831 _("genpurpose5"), // "General Purpose Controller 5",
53     _("genpurpose6"), // "General Purpose Controller 6",
54     _("genpurpose7"), // "General Purpose Controller 7",
55     _("genpurpose8"), // "General Purpose Controller 8",
56 schoenebeck 1225 0, 0, 0, 0, 0, 0, 0,
57 persson 1831 _("effect1depth"), // "Effects 1 Depth",
58     _("effect2depth"), // "Effects 2 Depth",
59     _("effect3depth"), // "Effects 3 Depth",
60     _("effect4depth"), // "Effects 4 Depth",
61     _("effect5depth"), // "Effects 5 Depth"
62 schoenebeck 1225 };
63     }
64    
65     LabelWidget::LabelWidget(const char* labelText, Gtk::Widget& widget) :
66     label(Glib::ustring(labelText) + ":"),
67     widget(widget)
68     {
69 persson 2169 label.set_alignment(Gtk::ALIGN_START);
70 schoenebeck 1225 }
71    
72     void LabelWidget::set_sensitive(bool sensitive)
73     {
74     label.set_sensitive(sensitive);
75     widget.set_sensitive(sensitive);
76     }
77    
78     NumEntry::NumEntry(const char* labelText, double lower, double upper,
79     int decimals) :
80 persson 2151 LabelWidget(labelText, box),
81 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
82 schoenebeck 1225 adjust(lower, lower, upper, 1, 10),
83 persson 2169 #else
84     adjust(Gtk::Adjustment::create(lower, lower, upper, 1, 10)),
85     #endif
86 schoenebeck 1225 scale(adjust),
87 persson 2151 spinbutton(adjust)
88 schoenebeck 1225 {
89 persson 2423 scale.set_size_request(70);
90 schoenebeck 1225 spinbutton.set_digits(decimals);
91 persson 1460 spinbutton.set_value(0);
92 schoenebeck 1225 scale.set_draw_value(false);
93     box.pack_start(spinbutton, Gtk::PACK_SHRINK);
94     box.add(scale);
95     }
96    
97     NumEntryGain::NumEntryGain(const char* labelText,
98     double lower, double upper,
99     int decimals, double coeff) :
100     NumEntry(labelText, lower, upper, decimals),
101 persson 2151 value(0),
102 persson 1460 coeff(coeff),
103     connected(true)
104 schoenebeck 1225 {
105     spinbutton.signal_value_changed().connect(
106     sigc::mem_fun(*this, &NumEntryGain::value_changed));
107     }
108    
109     void NumEntryGain::value_changed()
110     {
111 persson 1460 if (!connected) return;
112    
113 schoenebeck 1359 const double f = pow(10, spinbutton.get_digits());
114     int new_value = round_to_int(spinbutton.get_value() * f);
115 persson 1460 if (new_value != round_to_int(value / coeff * f)) {
116     value = round_to_int(new_value / f * coeff);
117     sig_changed();
118 schoenebeck 1225 }
119     }
120    
121 persson 1460 void NumEntryGain::set_value(int32_t value)
122 schoenebeck 1225 {
123 persson 1460 if (value != this->value) {
124     this->value = value;
125    
126     connected = false;
127     bool plus6 = value < 0;
128     spinbutton.set_value(plus6 ? 0 : value / coeff);
129     set_sensitive(!plus6);
130     connected = true;
131    
132     sig_changed();
133     }
134 schoenebeck 1225 }
135    
136    
137     BoolEntryPlus6::BoolEntryPlus6(const char* labelText, NumEntryGain& eGain, int32_t plus6value) :
138     LabelWidget(labelText, checkbutton),
139 persson 1262 checkbutton(labelText),
140 schoenebeck 1225 eGain(eGain),
141     plus6value(plus6value)
142     {
143     checkbutton.signal_toggled().connect(
144     sigc::mem_fun(*this, &BoolEntryPlus6::value_changed));
145     }
146    
147     void BoolEntryPlus6::value_changed()
148     {
149 persson 1460 if (checkbutton.get_active()) eGain.set_value(plus6value);
150     else if (eGain.get_value() < 0) eGain.set_value(0);
151 schoenebeck 1225 }
152    
153 persson 1460 int32_t BoolEntryPlus6::get_value() const
154 schoenebeck 1225 {
155 persson 1460 return eGain.get_value();
156 schoenebeck 1225 }
157    
158 persson 1460 void BoolEntryPlus6::set_value(int32_t value)
159     {
160     checkbutton.set_active(value < 0);
161     }
162    
163 schoenebeck 1225 NumEntryPermille::NumEntryPermille(const char* labelText,
164     double lower, double upper, int decimals) :
165 persson 1460 NumEntry(labelText, lower, upper, decimals),
166     value(0)
167 schoenebeck 1225 {
168     spinbutton.signal_value_changed().connect(
169     sigc::mem_fun(*this, &NumEntryPermille::value_changed));
170     }
171    
172     void NumEntryPermille::value_changed()
173     {
174 persson 1460 uint16_t new_value = uint16_t(spinbutton.get_value() * 10 + 0.5);
175     if (new_value != value) {
176     value = uint16_t(spinbutton.get_value() * 10 + 0.5);
177     sig_changed();
178 schoenebeck 1225 }
179     }
180    
181 persson 1460 void NumEntryPermille::set_value(uint16_t value)
182 schoenebeck 1225 {
183 persson 1460 if (value != this->value) {
184     spinbutton.set_value(value / 10.0);
185     }
186 schoenebeck 1225 }
187    
188    
189     NoteEntry::NoteEntry(const char* labelText) :
190     NumEntryTemp<uint8_t>(labelText)
191     {
192 persson 2423 spinbutton.set_width_chars(4);
193 schoenebeck 1225 spinbutton.signal_input().connect(
194     sigc::mem_fun(*this, &NoteEntry::on_input));
195     spinbutton.signal_output().connect(
196     sigc::mem_fun(*this, &NoteEntry::on_output));
197     }
198    
199     const char* notes[] = {
200 persson 1831 _("C"), _("C#"), _("D"), _("D#"), _("E"), _("F"),_("F#"),
201     _("G"), _("G#"), _("A"), _("A#"), _("B")
202 schoenebeck 1225 };
203    
204    
205     // Convert the Entry text to a number
206     int NoteEntry::on_input(double* new_value)
207     {
208     const char* str = spinbutton.get_text().c_str();
209    
210     int i;
211     for (i = 11 ; i >= 0 ; i--) {
212     if (strncmp(str, notes[i], strlen(notes[i])) == 0) break;
213     }
214     if (i >= 0) {
215     char* endptr;
216     long x = strtol(str + strlen(notes[i]), &endptr, 10);
217     if (endptr != str + strlen(notes[i])) {
218     *new_value = i + (x + 1) * 12;
219     return true;
220     }
221     }
222     return Gtk::INPUT_ERROR;
223     }
224    
225     // Convert the Adjustment position to text
226     bool NoteEntry::on_output()
227     {
228 persson 1261 int x = int(spinbutton.get_adjustment()->get_value() + 0.5);
229 schoenebeck 1225 char buf[10];
230     sprintf(buf, "%s%d", notes[x % 12], x / 12 - 1);
231     spinbutton.set_text(buf);
232     return true;
233     }
234    
235     ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(const char* labelText) :
236 persson 2151 LabelWidget(labelText, align),
237     align(0, 0, 0, 0)
238 schoenebeck 1225 {
239     for (int i = 0 ; i < 99 ; i++) {
240     if (controlChangeTexts[i]) {
241 persson 2169 #if (GTKMM_MAJOR_VERSION == 2 && GTKMM_MINOR_VERSION < 90) || GTKMM_MAJOR_VERSION < 2
242 schoenebeck 1225 combobox.append_text(controlChangeTexts[i]);
243 persson 2169 #else
244     combobox.append(controlChangeTexts[i]);
245     #endif
246 schoenebeck 1225 }
247     }
248     combobox.signal_changed().connect(
249     sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));
250     align.add(combobox);
251 persson 1460 value.type = gig::leverage_ctrl_t::type_none;
252     value.controller_number = 0;
253 schoenebeck 1225 }
254    
255     void ChoiceEntryLeverageCtrl::value_changed()
256     {
257 persson 1460 int rowno = combobox.get_active_row_number();
258     switch (rowno)
259     {
260     case -1:
261     break;
262     case 0:
263     value.type = gig::leverage_ctrl_t::type_none;
264     break;
265     case 1:
266     value.type = gig::leverage_ctrl_t::type_channelaftertouch;
267     break;
268     case 2:
269     value.type = gig::leverage_ctrl_t::type_velocity;
270     break;
271     default:
272     value.type = gig::leverage_ctrl_t::type_controlchange;
273     int x = 3;
274 persson 2151 for (uint cc = 0 ; cc < 96 ; cc++) {
275 persson 1460 if (controlChangeTexts[cc + 3]) {
276     if (rowno == x) {
277     value.controller_number = cc;
278     break;
279 schoenebeck 1225 }
280 persson 1460 x++;
281 schoenebeck 1225 }
282     }
283 persson 1460 break;
284 schoenebeck 1225 }
285 persson 1460 if (rowno >= 0) sig_changed();
286 schoenebeck 1225 }
287    
288 persson 1460 void ChoiceEntryLeverageCtrl::set_value(gig::leverage_ctrl_t value)
289 schoenebeck 1225 {
290     int x;
291 persson 1460 switch (value.type)
292 schoenebeck 1225 {
293     case gig::leverage_ctrl_t::type_none:
294     x = 0;
295     break;
296     case gig::leverage_ctrl_t::type_channelaftertouch:
297     x = 1;
298     break;
299     case gig::leverage_ctrl_t::type_velocity:
300     x = 2;
301     break;
302     case gig::leverage_ctrl_t::type_controlchange:
303     x = -1;
304 persson 2151 for (uint cc = 0 ; cc < 96 ; cc++) {
305 schoenebeck 1225 if (controlChangeTexts[cc + 3]) {
306     x++;
307 persson 1460 if (value.controller_number == cc) {
308 schoenebeck 1225 x += 3;
309     break;
310     }
311     }
312     }
313     break;
314     default:
315     x = -1;
316     break;
317     }
318     combobox.set_active(x);
319     }
320    
321    
322     BoolEntry::BoolEntry(const char* labelText) :
323     LabelWidget(labelText, checkbutton),
324 persson 1460 checkbutton(labelText)
325 schoenebeck 1225 {
326 persson 1460 checkbutton.signal_toggled().connect(sig_changed.make_slot());
327 schoenebeck 1225 }
328    
329    
330     StringEntry::StringEntry(const char* labelText) :
331     LabelWidget(labelText, entry)
332     {
333 persson 1582 entry.signal_changed().connect(sig_changed.make_slot());
334 schoenebeck 1225 }
335    
336 persson 1582 StringEntryMultiLine::StringEntryMultiLine(const char* labelText) :
337     LabelWidget(labelText, frame)
338 schoenebeck 1225 {
339 persson 1582 text_buffer = text_view.get_buffer();
340     frame.set_shadow_type(Gtk::SHADOW_IN);
341     frame.add(text_view);
342     text_buffer->signal_changed().connect(sig_changed.make_slot());
343 schoenebeck 1225 }
344    
345 persson 1582 gig::String StringEntryMultiLine::get_value() const
346 schoenebeck 1225 {
347 persson 1582 Glib::ustring value = text_buffer->get_text();
348     for (int i = 0 ; (i = value.find("\x0a", i)) >= 0 ; i += 2)
349     value.replace(i, 1, "\x0d\x0a");
350     return value;
351 schoenebeck 1225 }
352 persson 1582
353     void StringEntryMultiLine::set_value(gig::String value)
354     {
355     for (int i = 0 ; (i = value.find("\x0d\x0a", i, 2)) >= 0 ; i++)
356     value.replace(i, 2, "\x0a");
357     text_buffer->set_text(value);
358     }
359 persson 2423
360    
361     Table::Table(int x, int y) : Gtk::Table(x, y), rowno(0) { }
362    
363     void Table::add(BoolEntry& boolentry)
364     {
365     attach(boolentry.widget, 0, 2, rowno, rowno + 1,
366     Gtk::FILL, Gtk::SHRINK);
367     rowno++;
368     }
369    
370     void Table::add(BoolEntryPlus6& boolentry)
371     {
372     attach(boolentry.widget, 0, 2, rowno, rowno + 1,
373     Gtk::FILL, Gtk::SHRINK);
374     rowno++;
375     }
376    
377     void Table::add(LabelWidget& prop)
378     {
379     attach(prop.label, 1, 2, rowno, rowno + 1,
380     Gtk::FILL, Gtk::SHRINK);
381     attach(prop.widget, 2, 3, rowno, rowno + 1,
382     Gtk::EXPAND | Gtk::FILL, Gtk::SHRINK);
383     rowno++;
384     }

  ViewVC Help
Powered by ViewVC