Unconditionally save instant.xml on session-close
[ardour.git] / gtk2_ardour / port_insert_ui.cc
1 /*
2  * Copyright (C) 2010-2011 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2010-2017 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2011-2012 David Robillard <d@drobilla.net>
5  * Copyright (C) 2013-2017 Robin Gareus <robin@gareus.org>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <glibmm/objectbase.h>
23
24 #include <gtkmm/messagedialog.h>
25 #include <gtkmm/stock.h>
26
27 #include "ardour/audioengine.h"
28 #include "ardour/mtdm.h"
29 #include "ardour/port_insert.h"
30 #include "ardour/session.h"
31
32 #include "gtkmm2ext/doi.h"
33
34 #include "port_insert_ui.h"
35 #include "gui_thread.h"
36 #include "pbd/i18n.h"
37
38 using namespace ARDOUR;
39 using namespace Gtk;
40
41 PortInsertUI::PortInsertUI (Gtk::Window* parent, ARDOUR::Session* sess, boost::shared_ptr<ARDOUR::PortInsert> pi)
42         : _pi (pi)
43         , latency_button (_("Measure Latency"))
44         , input_selector (parent, sess, pi->input())
45         , output_selector (parent, sess, pi->output())
46 {
47         latency_hbox.pack_start (latency_button, false, false);
48         latency_hbox.pack_start (latency_display, false, false);
49         latency_hbox.set_spacing (4);
50
51         output_selector.set_min_height_divisor (2);
52         input_selector.set_min_height_divisor (2);
53
54         notebook.append_page (output_selector, _("Send/Output"));
55         notebook.append_page (input_selector, _("Return/Input"));
56
57         notebook.set_current_page (0);
58
59         set_spacing (12);
60         pack_start (notebook, true, true);
61         pack_start (latency_hbox, false, false);
62
63         update_latency_display ();
64
65         latency_button.signal_toggled().connect (mem_fun (*this, &PortInsertUI::latency_button_toggled));
66         latency_button.set_name (X_("MeasureLatencyButton"));
67 }
68
69 void
70 PortInsertUI::update_latency_display ()
71 {
72         samplecnt_t const sample_rate = AudioEngine::instance()->sample_rate();
73         if (sample_rate == 0) {
74                 latency_display.set_text (_("Disconnected from audio engine"));
75         } else {
76                 char buf[64];
77                 snprintf (buf, sizeof (buf), "%10.3lf samples %10.3lf ms",
78                           (float)_pi->latency(), (float)_pi->latency() * 1000.0f/sample_rate);
79                 latency_display.set_text(buf);
80         }
81 }
82
83 bool
84 PortInsertUI::check_latency_measurement ()
85 {
86         MTDM* mtdm = _pi->mtdm ();
87
88         if (mtdm->resolve () < 0) {
89                 latency_display.set_text (_("No signal detected"));
90                 return true;
91         }
92
93         if (mtdm->err () > 0.3) {
94                 mtdm->invert ();
95                 mtdm->resolve ();
96         }
97
98         char buf[128];
99         samplecnt_t const sample_rate = AudioEngine::instance()->sample_rate();
100
101         if (sample_rate == 0) {
102                 latency_display.set_text (_("Disconnected from audio engine"));
103                 _pi->stop_latency_detection ();
104                 return false;
105         }
106
107         snprintf (buf, sizeof (buf), "%10.3lf samples %10.3lf ms", mtdm->del (), mtdm->del () * 1000.0f/sample_rate);
108
109         bool solid = true;
110
111         if (mtdm->err () > 0.2) {
112                 strcat (buf, " ??");
113                 solid = false;
114         }
115
116         if (mtdm->inv ()) {
117                 strcat (buf, " (Inv)");
118                 solid = false;
119         }
120
121         if (solid) {
122                 _pi->set_measured_latency (rint (mtdm->del()));
123                 latency_button.set_active (false);
124                 strcat (buf, " (set)");
125         }
126
127         latency_display.set_text (buf);
128
129         return true;
130 }
131
132 void
133 PortInsertUI::latency_button_toggled ()
134 {
135         if (latency_button.get_active ()) {
136
137                 _pi->start_latency_detection ();
138                 latency_display.set_text (_("Detecting ..."));
139                 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &PortInsertUI::check_latency_measurement), 250);
140
141         } else {
142                 _pi->stop_latency_detection ();
143                 latency_timeout.disconnect ();
144                 update_latency_display ();
145         }
146 }
147
148 void
149 PortInsertUI::redisplay ()
150 {
151         input_selector.setup_ports (input_selector.other());
152         output_selector.setup_ports (output_selector.other());
153 }
154
155 void
156 PortInsertUI::finished (IOSelector::Result r)
157 {
158         input_selector.Finished (r);
159         output_selector.Finished (r);
160 }
161
162
163 PortInsertWindow::PortInsertWindow (ARDOUR::Session* sess, boost::shared_ptr<ARDOUR::PortInsert> pi)
164         : ArdourDialog ("port insert dialog"),
165           _portinsertui (this, sess, pi)
166 {
167
168         set_name ("IOSelectorWindow");
169         std::string title = _("Port Insert ");
170         title += pi->name();
171         set_title (title);
172
173         get_vbox()->pack_start (_portinsertui);
174
175         Gtk::Button* cancel_but = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
176         Gtk::Button* ok_but = add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
177
178         cancel_but->signal_clicked().connect (sigc::mem_fun (*this, &PortInsertWindow::cancel));
179         ok_but->signal_clicked().connect (sigc::mem_fun (*this, &PortInsertWindow::accept));
180
181         signal_delete_event().connect (sigc::mem_fun (*this, &PortInsertWindow::wm_delete), false);
182 }
183
184 bool
185 PortInsertWindow::wm_delete (GdkEventAny* /*event*/)
186 {
187         accept ();
188         return false;
189 }
190
191 void
192 PortInsertWindow::on_map ()
193 {
194         _portinsertui.redisplay ();
195         Window::on_map ();
196 }
197
198
199 void
200 PortInsertWindow::cancel ()
201 {
202         _portinsertui.finished (IOSelector::Cancelled);
203         hide ();
204 }
205
206 void
207 PortInsertWindow::accept ()
208 {
209         _portinsertui.finished (IOSelector::Accepted);
210         hide ();
211 }
212