/[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 1261 - (show annotations) (download)
Thu Jul 5 17:12:20 2007 UTC (11 years, 11 months ago) by persson
File size: 9571 byte(s)
* a changed file is now marked with an asterisk in the window title
* added close confirmation dialog, shown if file is changed
* "save" means "save as" for new files
* enabled acceleration keys
* add .gig to filename in "save as" if it's not already there
* filename character encodings other than utf-8 supported

1 /*
2 * Copyright (C) 2006, 2007 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 "paramedit.h"
21
22 namespace {
23 const char* const controlChangeTexts[] = {
24 "none", "channelaftertouch", "velocity",
25 0,
26 "modwheel", // "Modulation Wheel or Lever",
27 "breath", // "Breath Controller",
28 0,
29 "foot", // "Foot Controller",
30 "portamentotime", // "Portamento Time",
31 0, 0, 0, 0, 0, 0,
32 "effect1", // "Effect Control 1",
33 "effect2", // "Effect Control 2",
34 0, 0,
35 "genpurpose1", // "General Purpose Controller 1",
36 "genpurpose2", // "General Purpose Controller 2",
37 "genpurpose3", // "General Purpose Controller 3",
38 "genpurpose4", // "General Purpose Controller 4",
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0,
42 "sustainpedal", // "Damper Pedal on/off (Sustain)",
43 "portamento", // "Portamento On/Off",
44 "sostenuto", // "Sustenuto On/Off",
45 "softpedal", // "Soft Pedal On/Off",
46 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 "genpurpose5", // "General Purpose Controller 5",
48 "genpurpose6", // "General Purpose Controller 6",
49 "genpurpose7", // "General Purpose Controller 7",
50 "genpurpose8", // "General Purpose Controller 8",
51 0, 0, 0, 0, 0, 0, 0,
52 "effect1depth", // "Effects 1 Depth",
53 "effect2depth", // "Effects 2 Depth",
54 "effect3depth", // "Effects 3 Depth",
55 "effect4depth", // "Effects 4 Depth",
56 "effect5depth", // "Effects 5 Depth"
57 };
58 }
59
60 LabelWidget::LabelWidget(const char* labelText, Gtk::Widget& widget) :
61 label(Glib::ustring(labelText) + ":"),
62 widget(widget)
63 {
64 label.set_alignment(Gtk::ALIGN_LEFT);
65 }
66
67 void LabelWidget::set_sensitive(bool sensitive)
68 {
69 label.set_sensitive(sensitive);
70 widget.set_sensitive(sensitive);
71 }
72
73 NumEntry::NumEntry(const char* labelText, double lower, double upper,
74 int decimals) :
75 adjust(lower, lower, upper, 1, 10),
76 scale(adjust),
77 spinbutton(adjust),
78 LabelWidget(labelText, box)
79 {
80 spinbutton.set_digits(decimals);
81 scale.set_draw_value(false);
82 box.pack_start(spinbutton, Gtk::PACK_SHRINK);
83 box.add(scale);
84 }
85
86 NumEntryGain::NumEntryGain(const char* labelText,
87 double lower, double upper,
88 int decimals, double coeff) :
89 NumEntry(labelText, lower, upper, decimals),
90 coeff(coeff)
91 {
92 spinbutton.signal_value_changed().connect(
93 sigc::mem_fun(*this, &NumEntryGain::value_changed));
94 }
95
96 void NumEntryGain::value_changed()
97 {
98 if (ptr) {
99 const double f = pow(10, spinbutton.get_digits());
100 int new_value = round_to_int(spinbutton.get_value() * f);
101
102 if (new_value != round_to_int(*ptr / coeff * f))
103 {
104 *ptr = round_to_int(new_value / f * coeff);
105 sig_changed();
106 }
107 }
108 }
109
110 void NumEntryGain::set_ptr(int32_t* ptr)
111 {
112 this->ptr = 0;
113 bool plus6 = *ptr < 0;
114 set_value(plus6 ? 0 : *ptr / coeff);
115 set_sensitive(!plus6);
116 this->ptr = ptr;
117 }
118
119
120 BoolEntryPlus6::BoolEntryPlus6(const char* labelText, NumEntryGain& eGain, int32_t plus6value) :
121 LabelWidget(labelText, checkbutton),
122 eGain(eGain),
123 plus6value(plus6value)
124 {
125 checkbutton.signal_toggled().connect(
126 sigc::mem_fun(*this, &BoolEntryPlus6::value_changed));
127 }
128
129 void BoolEntryPlus6::value_changed()
130 {
131 if (ptr) {
132 bool plus6 = checkbutton.get_active();
133 if (plus6) {
134 eGain.set_value(0);
135 *ptr = plus6value;
136 sig_changed();
137 } else {
138 if (*ptr < 0) {
139 *ptr = 0;
140 sig_changed();
141 }
142 }
143 eGain.set_sensitive(!plus6);
144 }
145 }
146
147 void BoolEntryPlus6::set_ptr(int32_t* ptr)
148 {
149 this->ptr = 0;
150 checkbutton.set_active(*ptr < 0);
151 this->ptr = ptr;
152 }
153
154 NumEntryPermille::NumEntryPermille(const char* labelText,
155 double lower, double upper, int decimals) :
156 NumEntry(labelText, lower, upper, decimals)
157 {
158 spinbutton.signal_value_changed().connect(
159 sigc::mem_fun(*this, &NumEntryPermille::value_changed));
160 }
161
162 void NumEntryPermille::value_changed()
163 {
164 if (ptr) {
165 uint16_t new_value = uint16_t(spinbutton.get_value() * 10 + 0.5);
166 if (new_value != *ptr) {
167 *ptr = uint16_t(spinbutton.get_value() * 10 + 0.5);
168 sig_changed();
169 }
170 }
171 }
172
173 void NumEntryPermille::set_ptr(uint16_t* ptr)
174 {
175 this->ptr = 0;
176 set_value(*ptr / 10.0);
177 this->ptr = ptr;
178 }
179
180
181 NoteEntry::NoteEntry(const char* labelText) :
182 NumEntryTemp<uint8_t>(labelText)
183 {
184 spinbutton.signal_input().connect(
185 sigc::mem_fun(*this, &NoteEntry::on_input));
186 spinbutton.signal_output().connect(
187 sigc::mem_fun(*this, &NoteEntry::on_output));
188 }
189
190 const char* notes[] = {
191 "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
192 };
193
194
195 // Convert the Entry text to a number
196 int NoteEntry::on_input(double* new_value)
197 {
198 const char* str = spinbutton.get_text().c_str();
199
200 int i;
201 for (i = 11 ; i >= 0 ; i--) {
202 if (strncmp(str, notes[i], strlen(notes[i])) == 0) break;
203 }
204 if (i >= 0) {
205 char* endptr;
206 long x = strtol(str + strlen(notes[i]), &endptr, 10);
207 if (endptr != str + strlen(notes[i])) {
208 *new_value = i + (x + 1) * 12;
209 return true;
210 }
211 }
212 return Gtk::INPUT_ERROR;
213 }
214
215 // Convert the Adjustment position to text
216 bool NoteEntry::on_output()
217 {
218 int x = int(spinbutton.get_adjustment()->get_value() + 0.5);
219 char buf[10];
220 sprintf(buf, "%s%d", notes[x % 12], x / 12 - 1);
221 spinbutton.set_text(buf);
222 return true;
223 }
224
225 ChoiceEntryLeverageCtrl::ChoiceEntryLeverageCtrl(const char* labelText) :
226 align(0, 0, 0, 0),
227 LabelWidget(labelText, align)
228 {
229 for (int i = 0 ; i < 99 ; i++) {
230 if (controlChangeTexts[i]) {
231 combobox.append_text(controlChangeTexts[i]);
232 }
233 }
234 combobox.signal_changed().connect(
235 sigc::mem_fun(*this, &ChoiceEntryLeverageCtrl::value_changed));
236 align.add(combobox);
237 }
238
239 void ChoiceEntryLeverageCtrl::value_changed()
240 {
241 if (ptr) {
242 int rowno = combobox.get_active_row_number();
243 switch (rowno)
244 {
245 case -1:
246 break;
247 case 0:
248 ptr->type = gig::leverage_ctrl_t::type_none;
249 break;
250 case 1:
251 ptr->type = gig::leverage_ctrl_t::type_channelaftertouch;
252 break;
253 case 2:
254 ptr->type = gig::leverage_ctrl_t::type_velocity;
255 break;
256 default:
257 ptr->type = gig::leverage_ctrl_t::type_controlchange;
258 int x = 3;
259 for (int cc = 0 ; cc < 96 ; cc++) {
260 if (controlChangeTexts[cc + 3]) {
261 if (rowno == x) {
262 ptr->controller_number = cc;
263 break;
264 }
265 x++;
266 }
267 }
268 break;
269 }
270 if (rowno >= 0) sig_changed();
271 }
272 }
273
274 void ChoiceEntryLeverageCtrl::set_ptr(gig::leverage_ctrl_t* ptr)
275 {
276 this->ptr = 0;
277 int x;
278 switch (ptr->type)
279 {
280 case gig::leverage_ctrl_t::type_none:
281 x = 0;
282 break;
283 case gig::leverage_ctrl_t::type_channelaftertouch:
284 x = 1;
285 break;
286 case gig::leverage_ctrl_t::type_velocity:
287 x = 2;
288 break;
289 case gig::leverage_ctrl_t::type_controlchange:
290 x = -1;
291 for (int cc = 0 ; cc < 96 ; cc++) {
292 if (controlChangeTexts[cc + 3]) {
293 x++;
294 if (ptr->controller_number == cc) {
295 x += 3;
296 break;
297 }
298 }
299 }
300 break;
301 default:
302 x = -1;
303 break;
304 }
305 combobox.set_active(x);
306 this->ptr = ptr;
307 }
308
309
310 BoolEntry::BoolEntry(const char* labelText) :
311 LabelWidget(labelText, checkbutton),
312 checkbutton(labelText),
313 ptr(0)
314 {
315 checkbutton.signal_toggled().connect(
316 sigc::mem_fun(*this, &BoolEntry::value_changed));
317 }
318
319 void BoolEntry::value_changed()
320 {
321 if (ptr) {
322 *ptr = checkbutton.get_active();
323 sig_changed();
324 }
325 }
326
327 void BoolEntry::set_ptr(bool* ptr)
328 {
329 this->ptr = 0;
330 checkbutton.set_active(*ptr);
331 this->ptr = ptr;
332 }
333
334
335 StringEntry::StringEntry(const char* labelText) :
336 LabelWidget(labelText, entry)
337 {
338 entry.signal_changed().connect(
339 sigc::mem_fun(*this, &StringEntry::value_changed));
340 }
341
342 void StringEntry::value_changed()
343 {
344 if (ptr) {
345 *ptr = entry.get_text();
346 sig_changed();
347 }
348 }
349
350 void StringEntry::set_ptr(gig::String* ptr)
351 {
352 this->ptr = 0;
353 entry.set_text(*ptr);
354 this->ptr = ptr;
355 }

  ViewVC Help
Powered by ViewVC