1 /*
2 * Copyright (C) 2009, 2010, 2013 Hermann Meyer, James Warden, Andreas Degert
3 * Copyright (C) 2011 Pete Shorthose
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * --------------------------------------------------------------------------
19 */
20
21 #include "guitarix.h" // NOLINT
22
23 namespace gx_jconv {
24
25 /****************************************************************
26 ** Convolver Parameter Window
27 */
28
29 /*
30 ** static class variables and functions
31 */
32
create(const std::string & unit_id,Glib::RefPtr<Gdk::Pixbuf> icon,gx_engine::GxMachineBase & machine,Glib::RefPtr<Gtk::AccelGroup> accels,int nchan)33 IRWindow *IRWindow::create(const std::string& unit_id,
34 Glib::RefPtr<Gdk::Pixbuf> icon, gx_engine::GxMachineBase& machine,
35 Glib::RefPtr<Gtk::AccelGroup> accels, int nchan) {
36 Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
37 machine.get_options().get_builder_filepath(nchan == 1 ? "iredit_mono.glade" : "iredit.glade"), &machine);
38 Gtk::Widget *w;
39 if (!machine.get_jack()) {
40 bld->find_widget("file_selector_box", w);
41 //w->hide();
42 //bld->find_widget("dir_combo:rack_button", w);
43 //w->show();
44 }
45 gx_engine::JConvParameter *jcp = dynamic_cast<gx_engine::JConvParameter*>(&machine.get_parameter(unit_id+".convolver"));
46 assert(jcp);
47 return new IRWindow(bld, jcp, icon, machine, accels, nchan);
48 }
49
50 /*
51 ** Constructor
52 */
53
init_connect()54 void IRWindow::init_connect() {
55 builder->find_widget("iredit", wIredit);
56 wIredit->signal_delay_changed().connect(sigc::mem_fun(*this,
57 &IRWindow::on_delay_changed));
58 wIredit->signal_offset_changed().connect(sigc::mem_fun(*this,
59 &IRWindow::on_offset_changed));
60 wIredit->signal_length_changed().connect(sigc::mem_fun(*this,
61 &IRWindow::on_length_changed));
62 wIredit->signal_scale_max_reached().connect(sigc::mem_fun(*this,
63 &IRWindow::on_max_scale_reached));
64 wIredit->signal_scale_min_reached().connect(sigc::mem_fun(*this,
65 &IRWindow::on_min_scale_reached));
66
67 builder->find_widget("file_combo:rack_button", wcombo);
68 wcombo->signal_changed().connect(
69 sigc::mem_fun(*this, &IRWindow::on_combo_changed));
70 wcombo->set_model(model);
71
72 builder->find_widget("dir_combo:rack_button", dircombo);
73 if (dircombo->is_visible()) {
74 Gtk::TreeModelColumnRecord rec;
75 Gtk::TreeModelColumn<std::string> fname_col;
76 rec.add(fname_col);
77 Gtk::TreeModelColumn<Glib::ustring> dname_col;
78 rec.add(dname_col);
79 Glib::RefPtr<Gtk::ListStore> st = Gtk::ListStore::create(rec);
80 std::vector<gx_system::FileName> dirs;
81 machine.load_impresp_dirs(dirs);
82 for (std::vector<gx_system::FileName>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
83 Gtk::TreeIter j = st->append();
84 j->set_value(0, i->displayname);
85 j->set_value(1, i->filename);
86 }
87 dircombo->set_model(st);
88 dircombo->signal_changed().connect(
89 sigc::mem_fun(*this, &IRWindow::on_dircombo_changed));
90 }
91
92 if (nchan != 1) {
93 builder->find_widget("left", wLeft);
94 wLeft->signal_toggled().connect(sigc::mem_fun(*this, &IRWindow::on_left));
95 builder->find_widget("right", wRight);
96 wRight->signal_toggled().connect(sigc::mem_fun(*this, &IRWindow::on_right));
97 builder->find_widget("sum", wSum);
98 wSum->set_active(true);
99 wSum->signal_toggled().connect(sigc::mem_fun(*this, &IRWindow::on_sum));
100 } else {
101 wLeft = wRight = wSum = 0;
102 }
103
104 builder->find_widget("log", wLog);
105 wLog->set_active(true);
106 builder->find_widget("linear", wLinear);
107 wLinear->signal_toggled().connect(sigc::mem_fun(*this, &IRWindow::on_linear));
108
109 builder->find_widget("delay:show_always", wDelay);
110 wDelay->signal_value_changed().connect(sigc::mem_fun(*this,
111 &IRWindow::on_m_delay_changed));
112 builder->find_widget("offset:show_always", wOffset);
113 wOffset->signal_value_changed().connect(sigc::mem_fun(*this,
114 &IRWindow::on_m_offset_changed));
115 builder->find_widget("irlength:show_always", wLength);
116 wLength->signal_value_changed().connect(sigc::mem_fun(*this,
117 &IRWindow::on_m_length_changed));
118 builder->find_widget("delay_ms:show_always", wDelay_ms);
119 wDelay_ms->signal_value_changed().connect(sigc::mem_fun(*this,
120 &IRWindow::on_ms_delay_changed));
121 builder->find_widget("offset_ms:show_always", wOffset_ms);
122 wOffset_ms->signal_value_changed().connect(sigc::mem_fun(*this,
123 &IRWindow::on_ms_offset_changed));
124 builder->find_widget("irlength_ms:show_always", wLength_ms);
125 wLength_ms->signal_value_changed().connect(sigc::mem_fun(*this,
126 &IRWindow::on_ms_length_changed));
127
128 if (nchan != 1) {
129 builder->find_widget("delay_delta", wDelay_delta);
130 wDelay_delta->signal_format_value().connect(sigc::mem_fun(*this,
131 &IRWindow::on_delay_delta_format_value));
132 }
133
134 builder->find_widget("home", wHome);
135 wHome->signal_clicked().connect(sigc::mem_fun(*this, &IRWindow::on_home));
136 builder->find_widget("jump_zoom_mark", wJump_zoom_mark);
137 wJump_zoom_mark->signal_clicked().connect(sigc::mem_fun(*this,
138 &IRWindow::on_jump_zoom_mark));
139 builder->find_widget("incr", wIncr);
140 wIncr->signal_clicked().connect(sigc::mem_fun(*this, &IRWindow::on_incr));
141 builder->find_widget("decr", wDecr);
142 wDecr->signal_clicked().connect(sigc::mem_fun(*this, &IRWindow::on_decr));
143
144 builder->find_widget("reset_button", wReset);
145 wReset->signal_clicked().connect(sigc::mem_fun(*this, &IRWindow::on_reset_clicked));
146 builder->find_widget("open_button", wOpen);
147 if (!machine.get_jack()) wOpen->set_sensitive(false);
148 wOpen->signal_clicked().connect(sigc::mem_fun(*this, &IRWindow::on_open));
149
150 builder->find_widget("apply_button", wApply);
151 wApply->signal_clicked().connect(sigc::mem_fun(*this,
152 &IRWindow::on_apply_button_clicked));
153
154 builder->find_widget("cancel_button", wCancel);
155 wCancel->signal_clicked().connect(sigc::mem_fun(*this,
156 &IRWindow::on_cancel_button_clicked));
157 builder->find_widget("ok_button", wOk);
158 wOk->signal_clicked().connect(sigc::mem_fun(*this,
159 &IRWindow::on_ok_button_clicked));
160
161 builder->find_widget("gain_button", wGain_correction);
162 autogain_conn = wGain_correction->signal_toggled().connect(
163 sigc::mem_fun(*this, &IRWindow::on_gain_button_toggled));
164
165 builder->find_widget("length", wSamples);
166 builder->find_widget("samplerate", wSampleRate);
167 builder->find_widget("format", wFormat);
168 builder->find_widget("channels", wChan);
169 builder->find_widget("filename", wFilename);
170
171 if (nchan == 1) {
172 wChannelbox = 0;
173 } else {
174 builder->find_widget("channelbox", wChannelbox);
175 }
176 Gtk::Button* button;
177 builder->find_widget("help_button", button);
178 button->signal_clicked().connect(sigc::mem_fun(*this, &IRWindow::on_help_clicked));
179 builder->find_widget("HelpIR", wHelp);
180 builder->find_widget("close_irhelp", button);
181 button->signal_clicked().connect(sigc::mem_fun(wHelp, &Gtk::Widget::hide));
182
183 builder->find_widget("preset_button", button);
184 button->signal_clicked().connect(
185 sigc::mem_fun(this, &IRWindow::on_preset_popup_clicked));
186
187 gtk_window->signal_key_press_event().connect(
188 sigc::mem_fun(this, &IRWindow::on_key_press_event));
189 }
190
IRWindow(const Glib::RefPtr<gx_gui::GxBuilder> & bld,gx_engine::JConvParameter * jcp_,Glib::RefPtr<Gdk::Pixbuf> icon,gx_engine::GxMachineBase & machine_,Glib::RefPtr<Gtk::AccelGroup> accels,int nchan_)191 IRWindow::IRWindow(const Glib::RefPtr<gx_gui::GxBuilder>& bld, gx_engine::JConvParameter *jcp_,
192 Glib::RefPtr<Gdk::Pixbuf> icon, gx_engine::GxMachineBase& machine_,
193 Glib::RefPtr<Gtk::AccelGroup> accels, int nchan_)
194 : machine(machine_),
195 builder(bld),
196 filename(),
197 ms(0.0),
198 audio_buffer(0),
199 audio_size(0),
200 audio_chan(0),
201 jcp(jcp_),
202 gtk_window(0),
203 autogain_conn(),
204 nchan(nchan_),
205 //skipped all gtk widget pointers, will be set in init_connect()
206 columns(),
207 model(Gtk::TreeStore::create(columns)),
208 current_combo_dir() {
209 bld->get_toplevel("DisplayIR", gtk_window);
210
211 init_connect();
212 gtk_window->set_icon(icon);
213 gtk_window->add_accel_group(accels);
214 jcp->signal_changed().connect(
215 sigc::mem_fun(this, &IRWindow::load_state));
216 machine.signal_impresp_list().connect(
217 sigc::mem_fun(this, &IRWindow::on_enumerate));
218
219 // reset display
220 file_changed("", 0, 0, 0, "");
221 on_delay_changed(0, 0);
222 on_offset_changed(0, 0);
223 on_length_changed(0, 0);
224 }
225
~IRWindow()226 IRWindow::~IRWindow() {
227 delete gtk_window;
228 delete audio_buffer;
229 }
230
231 /*
232 ** helper functions
233 */
234
set_val(Gxw::ControlParameter * sample_display,Gxw::ControlParameter * ms_display,double value,int fs)235 int IRWindow::set_val(Gxw::ControlParameter *sample_display,
236 Gxw::ControlParameter *ms_display,
237 double value, int fs) {
238 double s1, s2;
239 if (fs) {
240 s1 = value;
241 s2 = (value*1000.0)/fs;
242 } else {
243 s1 = 0;
244 s2 = 0;
245 }
246 ms_display->cp_set_value(s2);
247 sample_display->cp_set_value(s1);
248 return sample_display->cp_get_int_value();
249 }
250
file_changed(Glib::ustring filename,int rate,int length,int channels,Glib::ustring format)251 void IRWindow::file_changed(Glib::ustring filename, int rate, int length,
252 int channels, Glib::ustring format) {
253 Glib::ustring s_rate, s_length, s_channels;
254 if (filename.empty()) {
255 filename = "no file selected";
256 s_length = s_rate = format = s_channels = "--";
257 } else {
258 ms = rate/1000.0;
259 wDelay->set_range(0, 5*rate);
260 wDelay_ms->set_range(0, 5*1000);
261 wOffset->set_range(0, length-1);
262 wOffset_ms->set_range(0, (length-1)*1000.0/rate);
263 wLength->set_range(0, length);
264 wLength_ms->set_range(0, (length)*1000.0/rate);
265 s_length = (boost::format("%1%") % length).str();
266 s_rate = (boost::format("%1%") % rate).str();
267 s_channels = (boost::format("%1%") % channels).str();
268 }
269 wSamples->set_text(s_length);
270 wSampleRate->set_text(s_rate);
271 wFormat->set_text(format);
272 wChan->set_text(s_channels);
273 if (nchan != 1) {
274 wChannelbox->set_sensitive(channels >= 2);
275 }
276 wFilename->set_text(Glib::path_get_dirname(filename));
277 }
278
load_state(const gx_engine::GxJConvSettings * jcs)279 void IRWindow::load_state(const gx_engine::GxJConvSettings* jcs) {
280 string path = jcs->getFullIRPath();
281 if (path.empty()) {
282 wIredit->set_ir_data(0, 0, 0, 0);
283 return;
284 }
285 gx_engine::GxJConvSettings jc;
286 make_state(jc);
287 if (jc == *jcs) {
288 return;
289 }
290 autogain_conn.block();
291 wGain_correction->set_active(jcs->getGainCor());
292 autogain_conn.unblock();
293 load_data(path, jcs->getOffset(), jcs->getDelay(), jcs->getLength(), jcs->getGainline());
294 reload_impresp_list();
295 }
296
297 Gainline IRWindow::gain0 = Gainline();
298
load_data(Glib::ustring f,int offset,int delay,int length,const Gainline & gain)299 bool IRWindow::load_data(Glib::ustring f, int offset, int delay, int length, const Gainline& gain) {
300 filename = f;
301 int audio_type, audio_form, audio_rate;
302 float *buffer;
303 if (!machine.read_audio(filename, &audio_size, &audio_chan, &audio_type, &audio_form, &audio_rate, &buffer)) {
304 return false;
305 }
306 Glib::ustring enc;
307 switch (audio_type) {
308 case gx_engine::Audiofile::TYPE_OTHER: enc = "???"; break;
309 case gx_engine::Audiofile::TYPE_CAF: enc = "CAF"; break;
310 case gx_engine::Audiofile::TYPE_WAV: enc = "WAV"; break;
311 case gx_engine::Audiofile::TYPE_AIFF: enc = "AIFF"; break;
312 case gx_engine::Audiofile::TYPE_AMB: enc = "AMB"; break;
313 }
314 enc += " ";
315 switch (audio_form) {
316 case gx_engine::Audiofile::FORM_OTHER: enc += "?"; break;
317 case gx_engine::Audiofile::FORM_16BIT: enc += "16 bit"; break;
318 case gx_engine::Audiofile::FORM_24BIT: enc += "24 bit"; break;
319 case gx_engine::Audiofile::FORM_32BIT: enc += "32 bit"; break;
320 case gx_engine::Audiofile::FORM_FLOAT: enc += "float"; break;
321 }
322 delete[] audio_buffer;
323 audio_buffer = buffer;
324 file_changed(filename, audio_rate, audio_size, audio_chan, enc);
325 if (!length) {
326 length = audio_size;
327 }
328 wIredit->set_state(audio_buffer, audio_chan, audio_size, audio_rate, offset, offset+length, delay-offset, gain);
329 if (wSum) {
330 wSum->set_active(true);
331 }
332 wLog->set_active(true);
333 return true;
334 }
335
calc_normalized_gain(int offset,int length,const Gainline & points)336 double IRWindow::calc_normalized_gain(int offset, int length, const Gainline& points) {
337 if (audio_chan == 0) {
338 return 1.0;
339 }
340 double gain = 0.0;
341 unsigned int idx = 0; // current index in gainline point array
342 double gp = 0.0, fct = 0.0; // calculated parameter of interpolation line
343 if (points.size()) {
344 while (points[idx].i < offset) {
345 idx++;
346 assert(idx < points.size());
347 }
348 if (points[idx].i > offset) {
349 idx--;
350 gx_engine::GxConvolver::compute_interpolation(fct, gp, idx, points, 0);
351 }
352 }
353 for (int i = offset; i < offset+length; i++) {
354 if (idx+1 < points.size() && points[idx].i == i) {
355 gx_engine::GxConvolver::compute_interpolation(fct, gp, idx, points, 0);
356 }
357 double g = pow(10, gp + i*fct);
358 for (int j = 0; j < audio_chan; j++) {
359 double v = audio_buffer[i*audio_chan+j] * g;
360 gain += v*v;
361 }
362 }
363 gain = sqrt(gain / audio_chan);
364 if (gain != 0.0) {
365 gain = 1 / gain;
366 }
367 return gain;
368 }
369
make_state(gx_engine::GxJConvSettings & jc)370 void IRWindow::make_state(gx_engine::GxJConvSettings& jc) {
371 Gainline gainline = wIredit->get_gain();
372 unsigned int offset = wIredit->get_offset();
373 unsigned int length = wIredit->get_length();
374 double gain = calc_normalized_gain(offset, length, gainline);
375 jc.setDelay(wIredit->get_delay());
376 jc.setOffset(offset);
377 jc.setLength(length);
378 jc.setFullIRPath(filename);
379 jc.setGainline(gainline);
380 jc.setGain(gain);
381 jc.setGainCor(wGain_correction->get_active());
382 }
383
save_state()384 void IRWindow::save_state() {
385 gx_engine::GxJConvSettings jc;
386 make_state(jc);
387 jcp->set(jc);
388 }
389
390 /**
391 ** signal functions
392 */
393
on_combo_changed()394 void IRWindow::on_combo_changed() {
395 Gtk::TreeModel::iterator iter = wcombo->get_active();
396 if (iter) {
397 Gtk::TreeModel::Row row = *iter;
398 if (row) {
399 std::string fname = row[columns.filename];
400 if (fname != jcp->get_value().getIRFile()) {
401 load_data(Glib::build_filename(current_combo_dir, fname));
402 save_state();
403 }
404 }
405 }
406 }
407
on_dircombo_changed()408 void IRWindow::on_dircombo_changed() {
409 Gtk::TreeModel::iterator iter = dircombo->get_active();
410 if (iter) {
411 std::string dir;
412 iter->get_value(1, dir);
413 if (dir != current_combo_dir) {
414 machine.reload_impresp_list(dir);
415 }
416 }
417 }
418
reload_impresp_list()419 void IRWindow::reload_impresp_list() {
420 std::string path = jcp->get_value().getIRDir();
421 if (path == "~/") { // cruft in old files
422 path = getenv("HOME");
423 }
424 string irfile = jcp->get_value().getIRFile();
425 if (current_combo_dir == path) {
426 Gtk::TreeNodeChildren ch = model->children();
427 for (Gtk::TreeIter i = ch.begin(); i != ch.end(); ++i) {
428 if (i->get_value(columns.filename) == irfile) {
429 wcombo->set_active(i);
430 }
431 }
432 return;
433 }
434 machine.reload_impresp_list(path);
435 }
436
437 // reload the treelist for the combobox
on_enumerate(const std::string & path,const std::vector<gx_system::FileName> & l)438 void IRWindow::on_enumerate(const std::string& path, const std::vector<gx_system::FileName>& l) {
439 if (current_combo_dir == path) {
440 return;
441 }
442 current_combo_dir = path;
443 string irfile = jcp->get_value().getIRFile();
444 model->clear();
445 Gtk::TreeIter j;
446 wcombo->unset_model();
447 model->set_sort_column(Gtk::TreeSortable::DEFAULT_UNSORTED_COLUMN_ID, Gtk::SORT_ASCENDING);
448 for (std::vector<gx_system::FileName>::const_iterator f = l.begin(); f != l.end(); ++f) {
449 Gtk::TreeIter i = model->append();
450 i->set_value(columns.displayname, f->displayname);
451 i->set_value(columns.filename, f->filename);
452 if (f->filename == irfile) {
453 j = i;
454 }
455 }
456 model->set_sort_column(columns.displayname, Gtk::SORT_ASCENDING);
457 wcombo->set_model(model);
458 if (j) {
459 wcombo->set_active(j);
460 }
461 if (dircombo->is_visible()) {
462 Gtk::TreeNodeChildren ch = dircombo->get_model()->children();
463 for (Gtk::TreeIter di = ch.begin(); di != ch.end(); ++di) {
464 std::string p;
465 di->get_value(1, p);
466 if (p == current_combo_dir) {
467 dircombo->set_active(di);
468 break;
469 }
470 }
471 }
472 }
473
on_linear()474 void IRWindow::on_linear() {
475 wIredit->set_log(not wLinear->get_active());
476 }
477
on_left()478 void IRWindow::on_left() {
479 if (wLeft->get_active()) {
480 wIredit->set_channel(0);
481 }
482 }
483
on_right()484 void IRWindow::on_right() {
485 if (wRight->get_active()) {
486 wIredit->set_channel(1);
487 }
488 }
489
on_sum()490 void IRWindow::on_sum() {
491 if (wSum->get_active()) {
492 wIredit->set_channel(-1);
493 }
494 }
495
on_delay_changed(int delay,int fs)496 void IRWindow::on_delay_changed(int delay, int fs) {
497 int d = static_cast<int>(round(set_val(wDelay, wDelay_ms, delay, fs)));
498 if (d != delay) {
499 wIredit->set_delay(d);
500 }
501 }
502
on_offset_changed(int offset,int fs)503 void IRWindow::on_offset_changed(int offset, int fs) {
504 set_val(wOffset, wOffset_ms, offset, fs);
505 }
506
on_length_changed(int length,int fs)507 void IRWindow::on_length_changed(int length, int fs) {
508 set_val(wLength, wLength_ms, length, fs);
509 }
510
on_reset_clicked()511 void IRWindow::on_reset_clicked() {
512 gx_engine::GxJConvSettings jc;
513 jc.setDelay(0);
514 jc.setOffset(0);
515 jc.setLength(audio_size);
516 jc.setFullIRPath(filename);
517 jc.setGainline(gain0);
518 jc.setGain(calc_normalized_gain(0, audio_size, gain0));
519 jc.setGainCor(true);
520 jcp->set(jc);
521 const char *params[] = {"jconv.balance", "jconv.diff_delay", "jconv.gain", "jconv.wet_dry", 0};
522 for (const char **p = params; *p; ++p) {
523 gx_engine::Parameter& pm = machine.get_parameter(*p);
524 pm.stdJSON_value();
525 pm.setJSON_value();
526 }
527 }
528
on_delay_delta_format_value(double v)529 Glib::ustring IRWindow::on_delay_delta_format_value(double v) {
530 Glib::ustring s = "";
531 if (v < 0.0) {
532 v = -v;
533 s = " R";
534 } else if (v > 0.0) {
535 s = " L";
536 }
537 // boost::format does not support "%*f"
538 Glib::ustring fmt = (boost::format("%%.%df%%s") % wDelay_delta->property_digits()).str();
539 return (boost::format(fmt) % v % s).str();
540 }
541
on_max_scale_reached(bool v)542 void IRWindow::on_max_scale_reached(bool v) {
543 wIncr->set_sensitive(not v);
544 }
545
on_min_scale_reached(bool v)546 void IRWindow::on_min_scale_reached(bool v) {
547 wDecr->set_sensitive(not v);
548 }
549
on_open()550 void IRWindow::on_open() {
551 static Glib::ustring hostname = "localhost";
552 if (! machine.get_jack()) {
553 hostname = Gio::Resolver::get_default()->lookup_by_address
554 (Gio::InetAddress::create( machine.get_options().get_rpcaddress()));
555 }
556 Glib::ustring title = hostname + ": Select Impulse Response";
557 Gtk::FileChooserDialog d(*gtk_window, title);
558 d.set_local_only(false);
559 d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
560 d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
561 d.add_shortcut_folder_uri(Glib::filename_to_uri(GX_SOUND_BPA_DIR, hostname));
562 d.add_shortcut_folder_uri(Glib::filename_to_uri(GX_SOUND_BPB_DIR, hostname));
563 d.add_shortcut_folder_uri(Glib::filename_to_uri(string(getenv("HOME")) + string("/.config/guitarix/IR"), hostname));
564 auto wav = Gtk::FileFilter::create();
565 wav->set_name("WAV Files");
566 wav->add_mime_type("audio/x-wav");
567 wav->add_mime_type("audio/x-aiff");
568 d.add_filter(wav);
569 auto audio = Gtk::FileFilter::create();
570 audio->set_name("Audio Files");
571 audio->add_mime_type("audio/*");
572 d.add_filter(audio);
573 auto all = Gtk::FileFilter::create();
574 all->add_pattern("*");
575 all->set_name("All Files");
576 d.add_filter(all);
577 if (!filename.empty()) {
578 d.set_uri(Glib::filename_to_uri (filename, hostname));
579 } else {
580 d.set_current_folder_uri(Glib::filename_to_uri (string(getenv("HOME")) + string("/"), hostname));
581 }
582 if (d.run() != Gtk::RESPONSE_OK) {
583 return;
584 }
585 filename = Glib::filename_from_uri(d.get_uri(), hostname);
586 Gtk::RecentManager::Data data;
587 bool result_uncertain;
588 data.mime_type = Gio::content_type_guess(filename, "", result_uncertain);
589 data.app_name = "guitarix";
590 data.groups.push_back("impulseresponse");
591 Gtk::RecentManager::get_default()->add_item(d.get_uri(), data);
592 load_data(filename);
593 save_state();
594 reload_impresp_list();
595 }
596
on_home()597 void IRWindow::on_home() {
598 wIredit->home();
599 }
600
on_jump_zoom_mark()601 void IRWindow::on_jump_zoom_mark() {
602 wIredit->jump_zoom_mark();
603 }
604
on_decr()605 void IRWindow::on_decr() {
606 wIredit->decr_scale(0.0);
607 }
608
on_incr()609 void IRWindow::on_incr() {
610 wIredit->incr_scale(0.0);
611 }
612
on_m_delay_changed()613 void IRWindow::on_m_delay_changed() {
614 wIredit->set_delay(wDelay->cp_get_int_value());
615 }
616
on_ms_delay_changed()617 void IRWindow::on_ms_delay_changed() {
618 wIredit->set_delay(get_ms(wDelay_ms));
619 }
620
on_m_offset_changed()621 void IRWindow::on_m_offset_changed() {
622 wIredit->set_offset(wOffset->cp_get_int_value());
623 }
624
on_ms_offset_changed()625 void IRWindow::on_ms_offset_changed() {
626 wIredit->set_offset(get_ms(wOffset_ms));
627 }
628
on_m_length_changed()629 void IRWindow::on_m_length_changed() {
630 wIredit->set_length(wLength->cp_get_int_value());
631 }
632
on_ms_length_changed()633 void IRWindow::on_ms_length_changed() {
634 wIredit->set_length(get_ms(wLength_ms));
635 }
636
on_apply_button_clicked()637 void IRWindow::on_apply_button_clicked() {
638 machine.pluginlist_lookup_plugin(jcp->group_id())->set_on_off(true);
639 save_state();
640 }
641
destroy_self()642 void IRWindow::destroy_self() {
643 delete this;
644 }
645
on_window_hide()646 void IRWindow::on_window_hide() {
647 Glib::signal_idle().connect(
648 sigc::bind_return(sigc::mem_fun(*this, &IRWindow::destroy_self), false));
649 }
650
on_cancel_button_clicked()651 void IRWindow::on_cancel_button_clicked() {
652 gtk_window->hide();
653 }
654
on_ok_button_clicked()655 void IRWindow::on_ok_button_clicked() {
656 save_state();
657 gtk_window->hide();
658 }
659
on_preset_popup_clicked()660 void IRWindow::on_preset_popup_clicked() {
661 Glib::ustring name = Glib::path_get_basename(filename);
662 Glib::ustring::size_type n = name.find_last_of('.');
663 if (n != Glib::ustring::npos) {
664 name.erase(n);
665 }
666 save_state();
667 new PluginPresetPopup(machine.pluginlist_lookup_plugin(jcp->group_id())->get_pdef(), machine, name);
668 }
669
on_help_clicked()670 void IRWindow::on_help_clicked() {
671 wHelp->show();
672 }
673
on_gain_button_toggled()674 void IRWindow::on_gain_button_toggled() {
675 save_state();
676 }
677
on_key_press_event(GdkEventKey * event)678 bool IRWindow::on_key_press_event(GdkEventKey *event) {
679 if (event->keyval == GDK_KEY_Escape && (event->state & Gtk::AccelGroup::get_default_mod_mask()) == 0) {
680 gtk_window->hide();
681 return true;
682 }
683 return false;
684 }
685
reload_and_show()686 void IRWindow::reload_and_show() {
687 if (gtk_window->get_visible() && !(gtk_window->get_window()->get_state() & Gdk::WINDOW_STATE_ICONIFIED)) {
688 gtk_window->hide();
689 } else {
690 load_state(&jcp->get_value());
691 gtk_window->present();
692 }
693 }
694
695 } // namespace gx_jconv
696