35 Glib::RefPtr<Gtk::AccelGroup> accels,
int nchan) {
36 Glib::RefPtr<gx_gui::GxBuilder> bld = gx_gui::GxBuilder::create_from_file(
40 bld->find_widget(
"file_selector_box", w);
47 return new IRWindow(bld, jcp, icon, machine, accels, nchan);
54 void IRWindow::init_connect() {
55 builder->find_widget(
"iredit", wIredit);
57 &IRWindow::on_delay_changed));
59 &IRWindow::on_offset_changed));
61 &IRWindow::on_length_changed));
63 &IRWindow::on_max_scale_reached));
65 &IRWindow::on_min_scale_reached));
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);
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;
77 Gtk::TreeModelColumn<Glib::ustring> dname_col;
79 Glib::RefPtr<Gtk::ListStore> st = Gtk::ListStore::create(rec);
80 std::vector<gx_system::FileName> 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);
87 dircombo->set_model(st);
88 dircombo->signal_changed().connect(
89 sigc::mem_fun(*
this, &IRWindow::on_dircombo_changed));
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));
101 wLeft = wRight = wSum = 0;
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));
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));
129 builder->find_widget(
"delay_delta", wDelay_delta);
131 &IRWindow::on_delay_delta_format_value));
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));
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));
150 builder->find_widget(
"apply_button", wApply);
151 wApply->signal_clicked().connect(sigc::mem_fun(*
this,
152 &IRWindow::on_apply_button_clicked));
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));
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));
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);
174 builder->find_widget(
"channelbox", wChannelbox);
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));
183 builder->find_widget(
"preset_button", button);
184 button->signal_clicked().connect(
185 sigc::mem_fun(
this, &IRWindow::on_preset_popup_clicked));
187 gtk_window->signal_key_press_event().connect(
188 sigc::mem_fun(
this, &IRWindow::on_key_press_event));
193 Glib::RefPtr<Gtk::AccelGroup> accels,
int nchan_)
207 model(Gtk::TreeStore::create(columns)),
208 current_combo_dir() {
209 bld->get_toplevel(
"DisplayIR", gtk_window);
212 gtk_window->set_icon(icon);
213 gtk_window->add_accel_group(accels);
215 sigc::mem_fun(
this, &IRWindow::load_state));
217 sigc::mem_fun(
this, &IRWindow::on_enumerate));
220 file_changed(
"", 0, 0, 0,
"");
221 on_delay_changed(0, 0);
222 on_offset_changed(0, 0);
223 on_length_changed(0, 0);
226 IRWindow::~IRWindow() {
237 double value,
int fs) {
241 s2 = (value*1000.0)/fs;
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 =
"--";
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();
269 wSamples->set_text(s_length);
270 wSampleRate->set_text(s_rate);
271 wFormat->set_text(format);
272 wChan->set_text(s_channels);
274 wChannelbox->set_sensitive(channels >= 2);
276 wFilename->set_text(Glib::path_get_dirname(filename));
290 autogain_conn.block();
291 wGain_correction->set_active(jcs->
getGainCor());
292 autogain_conn.unblock();
294 reload_impresp_list();
297 Gainline IRWindow::gain0 = Gainline();
299 bool IRWindow::load_data(Glib::ustring f,
int offset,
int delay,
int length,
const Gainline& gain) {
301 int audio_type, audio_form, audio_rate;
303 if (!machine.
read_audio(filename, &audio_size, &audio_chan, &audio_type, &audio_form, &audio_rate, &buffer)) {
307 switch (audio_type) {
315 switch (audio_form) {
322 delete[] audio_buffer;
323 audio_buffer = buffer;
324 file_changed(filename, audio_rate, audio_size, audio_chan, enc);
328 wIredit->
set_state(audio_buffer, audio_chan, audio_size, audio_rate, offset, offset+length, delay-offset, gain);
330 wSum->set_active(
true);
332 wLog->set_active(
true);
336 double IRWindow::calc_normalized_gain(
int offset,
int length,
const Gainline& points) {
337 if (audio_chan == 0) {
341 unsigned int idx = 0;
342 double gp = 0.0, fct = 0.0;
344 while (points[idx].i < offset) {
346 assert(idx < points.size());
348 if (points[idx].i > offset) {
353 for (
int i = offset; i < offset+length; i++) {
354 if (idx+1 < points.size() && points[idx].i == i) {
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;
363 gain = sqrt(gain / audio_chan);
371 Gainline gainline = wIredit->
get_gain();
374 double gain = calc_normalized_gain(offset, length, gainline);
381 jc.
setGainCor(wGain_correction->get_active());
384 void IRWindow::save_state() {
394 void IRWindow::on_combo_changed() {
395 Gtk::TreeModel::iterator iter = wcombo->get_active();
397 Gtk::TreeModel::Row row = *iter;
399 std::string fname = row[columns.filename];
401 load_data(Glib::build_filename(current_combo_dir, fname));
408 void IRWindow::on_dircombo_changed() {
409 Gtk::TreeModel::iterator iter = dircombo->get_active();
412 iter->get_value(1, dir);
413 if (dir != current_combo_dir) {
419 void IRWindow::reload_impresp_list() {
422 path = getenv(
"HOME");
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);
438 void IRWindow::on_enumerate(
const std::string& path,
const std::vector<gx_system::FileName>& l) {
439 if (current_combo_dir == path) {
442 current_combo_dir = path;
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) {
456 model->set_sort_column(columns.displayname, Gtk::SORT_ASCENDING);
457 wcombo->set_model(model);
459 wcombo->set_active(j);
461 if (dircombo->is_visible()) {
462 Gtk::TreeNodeChildren ch = dircombo->get_model()->children();
463 for (Gtk::TreeIter di = ch.begin(); di != ch.end(); ++di) {
466 if (p == current_combo_dir) {
467 dircombo->set_active(di);
474 void IRWindow::on_linear() {
475 wIredit->
set_log(not wLinear->get_active());
478 void IRWindow::on_left() {
479 if (wLeft->get_active()) {
484 void IRWindow::on_right() {
485 if (wRight->get_active()) {
490 void IRWindow::on_sum() {
491 if (wSum->get_active()) {
496 void IRWindow::on_delay_changed(
int delay,
int fs) {
497 int d = static_cast<int>(round(set_val(wDelay, wDelay_ms, delay, fs)));
503 void IRWindow::on_offset_changed(
int offset,
int fs) {
504 set_val(wOffset, wOffset_ms, offset, fs);
507 void IRWindow::on_length_changed(
int length,
int fs) {
508 set_val(wLength, wLength_ms, length, fs);
511 void IRWindow::on_reset_clicked() {
518 jc.
setGain(calc_normalized_gain(0, audio_size, gain0));
521 const char *params[] = {
"jconv.balance",
"jconv.diff_delay",
"jconv.gain",
"jconv.wet_dry", 0};
522 for (
const char **p = params; *p; ++p) {
529 Glib::ustring IRWindow::on_delay_delta_format_value(
double v) {
530 Glib::ustring s =
"";
534 }
else if (v > 0.0) {
538 Glib::ustring fmt = (boost::format(
"%%.%df%%s") % wDelay_delta->property_digits()).str();
539 return (boost::format(fmt) % v % s).str();
542 void IRWindow::on_max_scale_reached(
bool v) {
543 wIncr->set_sensitive(not v);
546 void IRWindow::on_min_scale_reached(
bool v) {
547 wDecr->set_sensitive(not v);
550 void IRWindow::on_open() {
551 static Glib::ustring hostname =
"localhost";
553 hostname = Gio::Resolver::get_default()->lookup_by_address
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));
565 wav.set_name(
"WAV Files");
566 wav.add_mime_type(
"audio/x-wav");
567 wav.add_mime_type(
"audio/x-aiff");
569 Gtk::FileFilter audio;
570 audio.set_name(
"Audio Files");
571 audio.add_mime_type(
"audio/*");
574 all.add_pattern(
"*");
575 all.set_name(
"All Files");
577 if (!filename.empty()) {
578 d.set_uri(Glib::filename_to_uri (filename, hostname));
580 d.set_current_folder_uri(Glib::filename_to_uri (
string(getenv(
"HOME")) +
string(
"/"), hostname));
582 if (d.run() != Gtk::RESPONSE_OK) {
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);
594 reload_impresp_list();
597 void IRWindow::on_home() {
601 void IRWindow::on_jump_zoom_mark() {
605 void IRWindow::on_decr() {
609 void IRWindow::on_incr() {
613 void IRWindow::on_m_delay_changed() {
617 void IRWindow::on_ms_delay_changed() {
621 void IRWindow::on_m_offset_changed() {
625 void IRWindow::on_ms_offset_changed() {
629 void IRWindow::on_m_length_changed() {
633 void IRWindow::on_ms_length_changed() {
637 void IRWindow::on_apply_button_clicked() {
642 void IRWindow::destroy_self() {
646 void IRWindow::on_window_hide() {
647 Glib::signal_idle().connect(
648 sigc::bind_return(sigc::mem_fun(*
this, &IRWindow::destroy_self),
false));
651 void IRWindow::on_cancel_button_clicked() {
655 void IRWindow::on_ok_button_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) {
670 void IRWindow::on_help_clicked() {
674 void IRWindow::on_gain_button_toggled() {
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) {
687 if (gtk_window->get_visible() && !(gtk_window->get_window()->get_state() & Gdk::WINDOW_STATE_ICONIFIED)) {
691 gtk_window->present();