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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2446 - (show annotations) (download)
Sun Apr 28 15:40:43 2013 UTC (10 years, 11 months ago) by persson
File size: 11405 byte(s)
* use character encoding Windows-1252 for all strings in gig files

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

  ViewVC Help
Powered by ViewVC