undo forgotten debug code
[ardour.git] / gtk2_ardour / mixer_strip.cc
1 /*
2     Copyright (C) 2000-2002 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <cmath>
22 #include <glib.h>
23
24 #include <sigc++/bind.h>
25
26 #include <gtkmm2ext/gtk_ui.h>
27 #include <gtkmm2ext/utils.h>
28 #include <gtkmm2ext/choice.h>
29 #include <gtkmm2ext/slider_controller.h>
30 #include <gtkmm2ext/stop_signal.h>
31 #include <gtkmm2ext/bindable_button.h>
32 #include <gtkmm2ext/doi.h>
33
34 #include <ardour/ardour.h>
35 #include <ardour/session.h>
36 #include <ardour/audioengine.h>
37 #include <ardour/route.h>
38 #include <ardour/audio_track.h>
39 #include <ardour/diskstream.h>
40 #include <ardour/panner.h>
41 #include <ardour/send.h>
42 #include <ardour/insert.h>
43 #include <ardour/ladspa_plugin.h>
44 #include <ardour/connection.h>
45 #include <ardour/session_connection.h>
46
47 #include "ardour_ui.h"
48 #include "ardour_dialog.h"
49 #include "ardour_message.h"
50 #include "mixer_strip.h"
51 #include "mixer_ui.h"
52 #include "keyboard.h"
53 #include "plugin_selector.h"
54 #include "public_editor.h"
55
56 #include "plugin_ui.h"
57 #include "send_ui.h"
58 #include "io_selector.h"
59 #include "utils.h"
60 #include "gui_thread.h"
61
62 #include "i18n.h"
63
64 using namespace sigc;
65 using namespace ARDOUR;
66 using namespace Gtk;
67 using namespace Gtkmm2ext;
68
69 /* XPM */
70 static const gchar * small_x_xpm[] = {
71 "11 11 2 1",
72 "       c None",
73 ".      c #cccc99",
74 "           ",
75 "           ",
76 "  .     .  ",
77 "   .   .   ",
78 "    . .    ",
79 "     .     ",
80 "    . .    ",
81 "   .   .   ",
82 "  .     .  ",
83 "           ",
84 "           "};
85
86 /* XPM */
87 static const gchar * lr_xpm[] = {
88 "11 11 2 1",
89 "       c None",
90 ".      c #cccc99",
91 "           ",
92 "           ",
93 "   .   .   ",
94 "  .     .  ",
95 " .       . ",
96 "...........",
97 " .       . ",
98 "  .     .  ",
99 "   .   .   ",
100 "           ",
101 "           "};
102
103 static void 
104 speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg)
105 {
106         float val = adj.get_value ();
107
108         if (val == 1.0) {
109                 strcpy (buf, "1");
110         } else {
111                 snprintf (buf, 32, "%.3f", val);
112         }
113 }
114
115 MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer)
116         : AxisView(sess),
117           RouteUI (rt, sess, _("mute"), _("solo"), _("RECORD")),
118           _mixer(mx),
119           pre_redirect_box (PreFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer),
120           post_redirect_box (PostFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer),
121           gpm (_route, sess),
122           panners (_route, sess),
123           button_table (8, 2),
124           gain_automation_style_button (""),
125           gain_automation_state_button (""),
126           pan_automation_style_button (""),
127           pan_automation_state_button (""),
128           polarity_button (_("polarity")),
129           comment_button (_("comments")),
130           speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1),
131           speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
132
133 {
134         if (set_color_from_route()) {
135                 set_color (unique_random_color());
136         }
137
138         input_selector = 0;
139         output_selector = 0;
140         group_menu = 0;
141         _marked_for_display = false;
142         route_ops_menu = 0;
143         ignore_comment_edit = false;
144         ignore_toggle = false;
145         ignore_speed_adjustment = false;
146         comment_window = 0;
147         comment_area = 0;
148
149         width_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(lr_xpm)))));
150         hide_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(small_x_xpm)))));
151
152
153         input_label.set_text (_("INPUT"));
154         input_button.add (input_label);
155         input_button.set_name ("MixerIOButton");
156         input_label.set_name ("MixerIOButtonLabel");
157
158         output_label.set_text (_("OUTPUT"));
159         output_button.add (output_label);
160         output_button.set_name ("MixerIOButton");
161         output_label.set_name ("MixerIOButtonLabel");
162
163         rec_enable_button->set_name ("MixerRecordEnableButton");
164         rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
165
166         solo_button->set_name ("MixerSoloButton");
167         mute_button->set_name ("MixerMuteButton");
168         gain_automation_style_button.set_name ("MixerAutomationModeButton");
169         gain_automation_state_button.set_name ("MixerAutomationPlaybackButton");
170         pan_automation_style_button.set_name ("MixerAutomationModeButton");
171         pan_automation_state_button.set_name ("MixerAutomationPlaybackButton");
172         polarity_button.set_name ("MixerPhaseInvertButton");
173
174         ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("Pan automation mode"));
175         ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("Gain automation mode"));
176
177         ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("Pan automation type"));
178         ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("Gain automation type"));
179
180         hide_button.set_events (hide_button.get_events() & ~(Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK));
181
182         width_button.unset_flags (Gtk::CAN_FOCUS);
183         hide_button.unset_flags (Gtk::CAN_FOCUS);
184         input_button.unset_flags (Gtk::CAN_FOCUS);
185         output_button.unset_flags (Gtk::CAN_FOCUS);
186         solo_button->unset_flags (Gtk::CAN_FOCUS);
187         mute_button->unset_flags (Gtk::CAN_FOCUS);
188         gain_automation_style_button.unset_flags (Gtk::CAN_FOCUS);
189         gain_automation_state_button.unset_flags (Gtk::CAN_FOCUS);
190         pan_automation_style_button.unset_flags (Gtk::CAN_FOCUS);
191         pan_automation_state_button.unset_flags (Gtk::CAN_FOCUS);
192         polarity_button.unset_flags (Gtk::CAN_FOCUS);
193
194         button_table.set_homogeneous (true);
195
196         button_table.attach (name_button, 0, 2, 0, 1);
197         button_table.attach (group_button, 0, 2, 1, 2);
198         button_table.attach (input_button, 0, 2, 2, 3);
199
200         button_table.attach (polarity_button, 0, 2, 3, 4);
201
202         button_table.attach (*solo_button, 0, 1, 4, 5);
203         button_table.attach (*mute_button, 1, 2, 4, 5);
204
205         // button_table.attach (gain_automation_style_button, 0, 1, 5, 6);
206         button_table.attach (gain_automation_state_button, 0, 1, 5, 6);
207         // button_table.attach (pan_automation_style_button, 0, 1, 6, 7);
208         button_table.attach (pan_automation_state_button, 1, 2, 5, 6);
209
210         using namespace Menu_Helpers;
211         
212         gain_astate_menu.items().push_back (MenuElem (_("off"), 
213                                                       bind (mem_fun (_route, &IO::set_gain_automation_state), (AutoState) Off)));
214         gain_astate_menu.items().push_back (MenuElem (_("play"),
215                                                       bind (mem_fun (_route, &IO::set_gain_automation_state), (AutoState) Play)));
216         gain_astate_menu.items().push_back (MenuElem (_("write"),
217                                                       bind (mem_fun (_route, &IO::set_gain_automation_state), (AutoState) Write)));
218         gain_astate_menu.items().push_back (MenuElem (_("touch"),
219                                                       bind (mem_fun (_route, &IO::set_gain_automation_state), (AutoState) Touch)));
220         
221         gain_astyle_menu.items().push_back (MenuElem (_("trim")));
222         gain_astyle_menu.items().push_back (MenuElem (_("abs")));
223
224         pan_astate_menu.items().push_back (MenuElem (_("off"), 
225                                                      bind (mem_fun (_route.panner(), &Panner::set_automation_state), (AutoState) Off)));
226         pan_astate_menu.items().push_back (MenuElem (_("play"),
227                                                      bind (mem_fun (_route.panner(), &Panner::set_automation_state), (AutoState) Play)));
228         pan_astate_menu.items().push_back (MenuElem (_("write"),
229                                                      bind (mem_fun (_route.panner(), &Panner::set_automation_state), (AutoState) Write)));
230         pan_astate_menu.items().push_back (MenuElem (_("touch"),
231                                                      bind (mem_fun (_route.panner(), &Panner::set_automation_state), (AutoState) Touch)));
232
233         pan_astyle_menu.items().push_back (MenuElem (_("trim")));
234         pan_astyle_menu.items().push_back (MenuElem (_("abs")));
235         
236         gain_astate_menu.set_name ("ArdourContextMenu");
237         gain_astyle_menu.set_name ("ArdourContextMenu");
238         pan_astate_menu.set_name ("ArdourContextMenu");
239         pan_astyle_menu.set_name ("ArdourContextMenu");
240
241         ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("gain automation mode"));
242         ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("pan automation mode"));
243         ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("gain automation state"));
244         ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("pan automation state"));
245
246         if (is_audio_track()) {
247                 
248                 AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
249
250                 at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen));
251
252                 speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed));
253                 
254                 speed_frame.set_name ("BaseFrame");
255                 speed_frame.set_shadow_type (Gtk::SHADOW_IN);
256                 speed_frame.add (speed_spinner);
257                 
258                 speed_spinner.set_print_func (speed_printer, 0);
259
260                 ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("varispeed"));
261
262                 speed_spinner.show ();
263                 speed_frame.show  ();
264
265                 button_table.attach (speed_frame, 0, 2, 6, 7);
266                 button_table.attach (*rec_enable_button, 0, 2, 7, 8);
267         }
268         
269         name_button.add (name_label);
270         name_button.set_name ("MixerNameButton");
271         Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
272
273         name_label.set_name ("MixerNameButtonLabel");
274         name_label.set_text (_route.name());
275
276         group_button.add (group_label);
277         group_button.set_name ("MixerGroupButton");
278         group_label.set_name ("MixerGroupButtonLabel");
279
280         comment_button.set_name ("MixerCommentButton");
281         ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route.comment()=="" ?
282                                                         _("click to add/edit comments"):
283                                                         _route.comment());
284         comment_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::comment_button_clicked));
285         
286         global_vpacker.set_border_width (4);
287         global_vpacker.set_spacing (4);
288
289         Gtk::VBox *whvbox = manage (new Gtk::VBox);
290
291         width_button.set_name ("MixerWidthButton");
292         hide_button.set_name ("MixerHideButton");
293
294         width_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::width_clicked));
295         hide_button.signal_clicked().connect (mem_fun(*this, &MixerStrip::hide_clicked));
296
297         width_hide_box.pack_start (width_button, false, true);
298         width_hide_box.pack_end (hide_button, false, true);
299
300         whvbox->pack_start (width_hide_box, true, true);
301
302         global_vpacker.pack_start (*whvbox, false, false);
303         global_vpacker.pack_start (button_table, false, false);
304         global_vpacker.pack_start (pre_redirect_box, true, true);
305         global_vpacker.pack_start (gpm, false, false);
306         global_vpacker.pack_start (post_redirect_box, true, true);
307         global_vpacker.pack_start (panners, false, false);
308         global_vpacker.pack_start (output_button, false, false);
309         global_vpacker.pack_start (comment_button, false, false);
310
311         global_frame.add (global_vpacker);
312         global_frame.set_shadow_type (Gtk::SHADOW_IN);
313         global_frame.set_name ("BaseFrame");
314
315         add (global_frame);
316
317         /* force setting of visible selected status */
318
319         _selected = true;
320         set_selected (false);
321
322         whvbox->show_all ();
323         name_label.show ();
324         group_label.show();
325         input_label.show ();
326         output_label.show ();
327         pre_redirect_box.show_all ();
328         post_redirect_box.show_all ();
329         button_table.show ();
330         comment_button.show ();
331         name_button.show ();
332         input_button.show ();
333         group_button.show ();
334         output_button.show ();
335         rec_enable_button->show ();
336         solo_button->show ();
337         mute_button->show ();
338         gain_automation_style_button.show ();
339         gain_automation_state_button.show ();
340         pan_automation_style_button.show ();
341         pan_automation_state_button.show ();
342         polarity_button.show ();
343         global_vpacker.show ();
344         global_frame.show ();
345
346         _packed = false;
347         _embedded = false;
348
349         _route.input_changed.connect (mem_fun(*this, &MixerStrip::input_changed));
350         _route.output_changed.connect (mem_fun(*this, &MixerStrip::output_changed));
351         _route.mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
352         _route.solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
353         _route.solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
354         _route.mix_group_changed.connect (mem_fun(*this, &MixerStrip::mix_group_changed));
355         _route.gain_automation_curve().automation_state_changed.connect (mem_fun(*this, &MixerStrip::gain_automation_state_changed));
356         _route.gain_automation_curve().automation_style_changed.connect (mem_fun(*this, &MixerStrip::gain_automation_style_changed));
357         _route.panner().Changed.connect (mem_fun(*this, &MixerStrip::connect_to_pan));
358
359         if (is_audio_track()) {
360                 audio_track()->diskstream_changed.connect (mem_fun(*this, &MixerStrip::diskstream_changed));
361                 get_diskstream()->speed_changed.connect (mem_fun(*this, &MixerStrip::speed_changed));
362         }
363
364         _route.name_changed.connect (mem_fun(*this, &RouteUI::name_changed));
365         _route.comment_changed.connect (mem_fun(*this, &MixerStrip::comment_changed));
366         _route.gui_changed.connect (mem_fun(*this, &MixerStrip::route_gui_changed));
367
368         input_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::input_press));
369         output_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::output_press));
370
371         rec_enable_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::rec_enable_press));
372         solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press));
373         solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release));
374         mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press));
375         mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release));
376
377         gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::gain_automation_style_button_event));
378         gain_automation_style_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::gain_automation_style_button_event));
379         pan_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::pan_automation_style_button_event));
380         pan_automation_style_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::pan_automation_style_button_event));
381
382         gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::gain_automation_state_button_event));
383         gain_automation_state_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::gain_automation_state_button_event));
384         pan_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::pan_automation_state_button_event));
385         pan_automation_state_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::pan_automation_state_button_event));
386
387         polarity_button.signal_toggled().connect (mem_fun(*this, &MixerStrip::polarity_toggled));
388
389         name_button.signal_button_release_event().connect (mem_fun(*this, &MixerStrip::name_button_button_release));
390
391         group_button.signal_button_press_event().connect (mem_fun(*this, &MixerStrip::select_mix_group));
392
393         _width = (Width) -1;
394         set_stuff_from_route ();
395
396         /* start off as a passthru strip. we'll correct this, if necessary,
397            in update_diskstream_display().
398         */
399
400         set_name ("AudioTrackStripBase");
401
402         /* now force an update of all the various elements */
403
404         pre_redirect_box.update();
405         post_redirect_box.update();
406         mute_changed (0);
407         solo_changed (0);
408         name_changed (0);
409         comment_changed (0);
410         mix_group_changed (0);
411         gain_automation_state_changed ();
412         pan_automation_state_changed ();
413         connect_to_pan ();
414
415         panners.setup_pan ();
416
417         if (is_audio_track()) {
418                 speed_changed ();
419         }
420
421         /* XXX hack: no phase invert changed signal */
422
423         polarity_button.set_active (_route.phase_invert());
424
425         update_diskstream_display ();
426         update_input_display ();
427         update_output_display ();
428
429         add_events (Gdk::BUTTON_RELEASE_MASK);
430 }
431
432 MixerStrip::~MixerStrip ()
433 {
434         GoingAway(); /* EMIT_SIGNAL */
435
436         if (input_selector) {
437                 delete input_selector;
438         }
439
440         if (output_selector) {
441                 delete output_selector;
442         }
443 }
444
445 void
446 MixerStrip::set_stuff_from_route ()
447 {
448         XMLProperty *prop;
449         
450         ensure_xml_node ();
451
452         if ((prop = xml_node->property ("strip_width")) != 0) {
453                 if (prop->value() == "wide") {
454                         set_width (Wide);
455                 } else if (prop->value() == "narrow") {
456                         set_width (Narrow);
457                 }
458                 else {
459                         error << string_compose(_("unknown strip width \"%1\" in XML GUI information"), prop->value()) << endmsg;
460                         set_width (Wide);
461                 }
462         }
463         else {
464                 set_width (Wide);
465         }
466
467         if ((prop = xml_node->property ("shown_mixer")) != 0) {
468                 if (prop->value() == "no") {
469                         _marked_for_display = false;
470                 } else {
471                         _marked_for_display = true;
472                 }
473         }
474         else {
475                 /* backwards compatibility */
476                 _marked_for_display = true;
477         }
478 }
479
480 void
481 MixerStrip::set_width (Width w)
482 {
483         /* always set the gpm width again, things may be hidden */
484         gpm.set_width (w);
485         panners.set_width (w);
486         pre_redirect_box.set_width (w);
487         post_redirect_box.set_width (w);
488         
489         if (_width == w) {
490                 return;
491         }
492
493         ensure_xml_node ();
494         
495         _width = w;
496
497         switch (w) {
498         case Wide:
499                 set_size_request (-1, -1);
500                 xml_node->add_property ("strip_width", "wide");
501
502                 static_cast<Gtk::Label*> (rec_enable_button->get_child())->set_text (_("RECORD"));
503                 static_cast<Gtk::Label*> (mute_button->get_child())->set_text (_("mute"));
504                 static_cast<Gtk::Label*> (solo_button->get_child())->set_text (_("solo"));
505                 static_cast<Gtk::Label*> (comment_button.get_child())->set_text (_("comments"));
506                 static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style()));
507                 static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state()));
508                 static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style()));
509                 static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state()));
510                 static_cast<Gtk::Label*> (polarity_button.get_child())->set_text (_("polarity"));
511                 Gtkmm2ext::set_size_request_to_display_given_text (name_button, "long", 2, 2);
512                 break;
513
514         case Narrow:
515                 set_size_request (50, -1);
516                 xml_node->add_property ("strip_width", "narrow");
517
518                 static_cast<Gtk::Label*> (rec_enable_button->get_child())->set_text (_("REC"));
519                 static_cast<Gtk::Label*> (mute_button->get_child())->set_text (_("m"));
520                 static_cast<Gtk::Label*> (solo_button->get_child())->set_text (_("s"));
521                 static_cast<Gtk::Label*> (comment_button.get_child())->set_text (_("cmt"));
522                 static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style()));
523                 static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state()));
524                 static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style()));
525                 static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state()));
526                 static_cast<Gtk::Label*> (polarity_button.get_child())->set_text (_("pol"));
527                 Gtkmm2ext::set_size_request_to_display_given_text (name_button, "longest label", 2, 2);
528                 break;
529         }
530
531         update_input_display ();
532         update_output_display ();
533         mix_group_changed (0);
534         name_changed (0);
535 }
536
537 void
538 MixerStrip::set_packed (bool yn)
539 {
540         _packed = yn;
541
542         ensure_xml_node ();
543
544         if (_packed) {
545                 xml_node->add_property ("shown_mixer", "yes");
546         } else {
547                 xml_node->add_property ("shown_mixer", "no");
548         }
549 }
550
551
552 gint
553 MixerStrip::output_press (GdkEventButton *ev)
554 {
555         using namespace Menu_Helpers;
556
557         if (!_session.engine().connected()) {
558                 ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
559                 return TRUE;
560         }
561
562         MenuList& citems = output_menu.items();
563         output_menu.set_name ("ArdourContextMenu");
564         citems.clear();
565
566         citems.push_back (MenuElem (_("Edit"), mem_fun(*this, &MixerStrip::edit_output_configuration)));
567         citems.push_back (SeparatorElem());
568         citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_output)));
569         citems.push_back (SeparatorElem());
570
571         _session.foreach_connection (this, &MixerStrip::add_connection_to_output_menu);
572
573         output_menu.popup (1, ev->time);
574
575         return TRUE;
576 }
577
578 void
579 MixerStrip::edit_output_configuration ()
580 {
581         if (output_selector == 0) {
582                 output_selector = new IOSelectorWindow (_session, _route, false);
583         } 
584
585         if (output_selector->is_visible()) {
586                 output_selector->get_toplevel()->get_window()->raise();
587         } else {
588                 output_selector->show_all ();
589         }
590 }
591
592 void
593 MixerStrip::edit_input_configuration ()
594 {
595         if (input_selector == 0) {
596                 input_selector = new IOSelectorWindow (_session, _route, true);
597         } 
598
599         if (input_selector->is_visible()) {
600                 input_selector->get_toplevel()->get_window()->raise();
601         } else {
602                 input_selector->show_all ();
603         }
604 }
605
606 gint
607 MixerStrip::input_press (GdkEventButton *ev)
608 {
609         using namespace Menu_Helpers;
610
611         MenuList& citems = input_menu.items();
612         input_menu.set_name ("ArdourContextMenu");
613         citems.clear();
614
615         if (!_session.engine().connected()) {
616                 ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible"));
617                 return TRUE;
618         }
619
620 #if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY
621         if (is_audio_track()) {
622                 citems.push_back (MenuElem (_("Track"), mem_fun(*this, &MixerStrip::select_stream_input)));
623         }
624 #endif
625         citems.push_back (MenuElem (_("Edit"), mem_fun(*this, &MixerStrip::edit_input_configuration)));
626         citems.push_back (SeparatorElem());
627         citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
628         citems.push_back (SeparatorElem());
629
630         _session.foreach_connection (this, &MixerStrip::add_connection_to_input_menu);
631         input_menu.popup (1, ev->time);
632
633         return TRUE;
634 }
635
636 void
637 MixerStrip::connection_input_chosen (ARDOUR::Connection *c)
638 {
639         if (!ignore_toggle) {
640
641                 try { 
642                         _route.use_input_connection (*c, this);
643                 }
644
645                 catch (AudioEngine::PortRegistrationFailure& err) {
646                         error << _("could not register new ports required for that connection")
647                               << endmsg;
648                 }
649         }
650 }
651
652 void
653 MixerStrip::connection_output_chosen (ARDOUR::Connection *c)
654 {
655         if (!ignore_toggle) {
656
657                 try { 
658                         _route.use_output_connection (*c, this);
659                 }
660
661                 catch (AudioEngine::PortRegistrationFailure& err) {
662                         error << _("could not register new ports required for that connection")
663                               << endmsg;
664                 }
665         }
666 }
667
668 void
669 MixerStrip::add_connection_to_input_menu (ARDOUR::Connection* c)
670 {
671         using namespace Menu_Helpers;
672
673         if (dynamic_cast<InputConnection *> (c) == 0) {
674                 return;
675         }
676
677         MenuList& citems = input_menu.items();
678         
679         if (c->nports() == _route.n_inputs()) {
680
681                 citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_input_chosen), c)));
682                 
683                 ARDOUR::Connection *current = _route.input_connection();
684                 
685                 if (current == c) {
686                         ignore_toggle = true;
687                         dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
688                         ignore_toggle = false;
689                 }
690         }
691 }
692
693 void
694 MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
695 {
696         using namespace Menu_Helpers;
697
698         if (dynamic_cast<OutputConnection *> (c) == 0) {
699                 return;
700         }
701
702         if (c->nports() == _route.n_outputs()) {
703
704                 MenuList& citems = output_menu.items();
705                 citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_output_chosen), c)));
706                 
707                 ARDOUR::Connection *current = _route.output_connection();
708                 
709                 if (current == c) {
710                         ignore_toggle = true;
711                         dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
712                         ignore_toggle = false;
713                 }
714         }
715 }
716
717 void
718 MixerStrip::select_stream_input ()
719 {
720         using namespace Menu_Helpers;
721
722         Menu *stream_menu = manage (new Menu);
723         MenuList& items = stream_menu->items();
724         stream_menu->set_name ("ArdourContextMenu");
725         
726         Session::DiskStreamList streams = _session.disk_streams();
727
728         for (Session::DiskStreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
729
730                 if (!(*i)->hidden()) {
731
732                         items.push_back (CheckMenuElem ((*i)->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), *i)));
733                         
734                         if (get_diskstream() == *i) {
735                                 ignore_toggle = true;
736                                 static_cast<CheckMenuItem *> (&items.back())->set_active (true);
737                                 ignore_toggle = false;
738                         } 
739                 }
740         }
741         
742         stream_menu->popup (1, 0);
743 }
744
745 void
746 MixerStrip::stream_input_chosen (DiskStream *stream)
747 {
748         if (is_audio_track()) {
749                 audio_track()->set_diskstream (*stream, this);
750         }
751 }
752
753 void
754 MixerStrip::update_diskstream_display ()
755 {
756         if (is_audio_track()) {
757
758                 map_frozen ();
759
760                 update_input_display ();
761
762                 if (input_selector) {
763                         input_selector->hide_all ();
764                 }
765
766                 show_route_color ();
767
768         } else {
769
770                 map_frozen ();
771
772                 update_input_display ();
773                 show_passthru_color ();
774         }
775 }
776
777 void
778 MixerStrip::connect_to_pan ()
779 {
780         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::connect_to_pan));
781         
782         panstate_connection.disconnect ();
783         panstyle_connection.disconnect ();
784
785         if (!_route.panner().empty()) {
786                 StreamPanner* sp = _route.panner().front();
787
788                 panstate_connection = sp->automation().automation_state_changed.connect (mem_fun(*this, &MixerStrip::pan_automation_state_changed));
789                 panstyle_connection = sp->automation().automation_style_changed.connect (mem_fun(*this, &MixerStrip::pan_automation_style_changed));
790         }
791
792         panners.pan_changed (this);
793 }
794
795 void
796 MixerStrip::update_input_display ()
797 {
798         ARDOUR::Connection *c;
799
800         if ((c = _route.input_connection()) != 0) {
801                 input_label.set_text (c->name());
802         } else {
803                 switch (_width) {
804                 case Wide:
805                         input_label.set_text (_("INPUT"));
806                         break;
807                 case Narrow:
808                         input_label.set_text (_("IN"));
809                         break;
810                 }
811         }
812
813         panners.setup_pan ();
814 }
815
816 void
817 MixerStrip::update_output_display ()
818 {
819         ARDOUR::Connection *c;
820
821         if ((c = _route.output_connection()) != 0) {
822                 output_label.set_text (c->name());
823         } else {
824                 switch (_width) {
825                 case Wide:
826                         output_label.set_text (_("OUTPUT"));
827                         break;
828                 case Narrow:
829                         output_label.set_text (_("OUT"));
830                         break;
831                 }
832         }
833
834         gpm.setup_meters ();
835         panners.setup_pan ();
836 }
837
838 void
839 MixerStrip::update ()
840 {
841         gpm.update_meters ();
842 }
843
844 void
845 MixerStrip::fast_update ()
846 {
847         if (_session.meter_falloff() > 0.0f) {
848                 gpm.update_meters_falloff ();
849         }
850 }
851
852 gint
853 MixerStrip::gain_automation_state_button_event (GdkEventButton *ev)
854 {
855         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
856                 return TRUE;
857         }
858         
859         switch (ev->button) {
860         case 1:
861                 switch (ev->button) {
862                 case 1:
863                         gain_astate_menu.popup (1, ev->time);
864                         break;
865                 default:
866                         break;
867                 }
868         }
869
870         return TRUE;
871 }
872
873 gint
874 MixerStrip::gain_automation_style_button_event (GdkEventButton *ev)
875 {
876         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
877                 return TRUE;
878         }
879
880         switch (ev->button) {
881         case 1:
882                 gain_astyle_menu.popup (1, ev->time);
883                 break;
884         default:
885                 break;
886         }
887         return TRUE;
888 }
889
890 gint
891 MixerStrip::pan_automation_state_button_event (GdkEventButton *ev)
892 {
893         using namespace Menu_Helpers;
894
895         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
896                 return TRUE;
897         }
898
899         switch (ev->button) {
900         case 1:
901                 pan_astate_menu.popup (1, ev->time);
902                 break;
903         default:
904                 break;
905         }
906
907         return TRUE;
908 }
909
910 gint
911 MixerStrip::pan_automation_style_button_event (GdkEventButton *ev)
912 {
913         switch (ev->button) {
914         case 1:
915                 pan_astyle_menu.popup (1, ev->time);
916                 break;
917         default:
918                 break;
919         }
920         return TRUE;
921 }
922
923 string
924 MixerStrip::astate_string (AutoState state)
925 {
926         return _astate_string (state, false);
927 }
928
929 string
930 MixerStrip::short_astate_string (AutoState state)
931 {
932         return _astate_string (state, true);
933 }
934
935 string
936 MixerStrip::_astate_string (AutoState state, bool shrt)
937 {
938         string sstr;
939
940         switch (state) {
941         case Off:
942                 sstr = (shrt ? "--" : _("off"));
943                 break;
944         case Play:
945                 sstr = (shrt ? "P" : _("aplay"));
946                 break;
947         case Touch:
948                 sstr = (shrt ? "T" : _("touch"));
949                 break;
950         case Write:
951                 sstr = (shrt ? "W" : _("awrite"));
952                 break;
953         }
954
955         return sstr;
956 }
957
958 string
959 MixerStrip::astyle_string (AutoStyle style)
960 {
961         return _astyle_string (style, false);
962 }
963
964 string
965 MixerStrip::short_astyle_string (AutoStyle style)
966 {
967         return _astyle_string (style, true);
968 }
969
970 string
971 MixerStrip::_astyle_string (AutoStyle style, bool shrt)
972 {
973         if (style & Trim) {
974                 return _("trim");
975         } else {
976                 /* XXX it might different in different languages */
977
978                 return (shrt ? _("abs") : _("abs"));
979         }
980 }
981
982 void
983 MixerStrip::diskstream_changed (void *src)
984 {
985         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_diskstream_display));
986 }       
987
988 void
989 MixerStrip::gain_automation_style_changed ()
990 {
991         switch (_width) {
992         case Wide:
993                 static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style()));
994                 break;
995         case Narrow:
996                 static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style()));
997                 break;
998         }
999 }
1000
1001 void
1002 MixerStrip::gain_automation_state_changed ()
1003 {
1004         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::gain_automation_state_changed));
1005         
1006         bool x;
1007
1008         switch (_width) {
1009         case Wide:
1010                 static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state()));
1011                 break;
1012         case Narrow:
1013                 static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state()));
1014                 break;
1015         }
1016
1017         x = (_route.gain_automation_state() != Off);
1018         
1019         if (gain_automation_state_button.get_active() != x) {
1020                 ignore_toggle = true;
1021                 gain_automation_state_button.set_active (x);
1022                 ignore_toggle = false;
1023         }
1024
1025         gpm.update_gain_sensitive ();
1026         
1027         /* start watching automation so that things move */
1028         
1029         gain_watching.disconnect();
1030
1031         if (x) {
1032                 gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (gpm, &GainMeter::effective_gain_display));
1033         }
1034 }
1035
1036 void
1037 MixerStrip::pan_automation_style_changed ()
1038 {
1039         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::pan_automation_style_changed));
1040         
1041         switch (_width) {
1042         case Wide:
1043                 static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style()));
1044                 break;
1045         case Narrow:
1046                 static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style()));
1047                 break;
1048         }
1049 }
1050
1051 void
1052 MixerStrip::pan_automation_state_changed ()
1053 {
1054         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::pan_automation_state_changed));
1055         
1056         bool x;
1057
1058         switch (_width) {
1059         case Wide:
1060                 static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state()));
1061                 break;
1062         case Narrow:
1063                 static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state()));
1064                 break;
1065         }
1066
1067         /* when creating a new session, we get to create busses (and
1068            sometimes tracks) with no outputs by the time they get
1069            here.
1070         */
1071
1072         if (_route.panner().empty()) {
1073                 return;
1074         }
1075
1076         x = (_route.panner().front()->automation().automation_state() != Off);
1077
1078         if (pan_automation_state_button.get_active() != x) {
1079                 ignore_toggle = true;
1080                 pan_automation_state_button.set_active (x);
1081                 ignore_toggle = false;
1082         }
1083
1084         panners.update_pan_sensitive ();
1085         
1086         /* start watching automation so that things move */
1087         
1088         pan_watching.disconnect();
1089
1090         if (x) {
1091                 pan_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (panners, &PannerUI::effective_pan_display));
1092         }
1093 }
1094
1095 void
1096 MixerStrip::input_changed (IOChange change, void *src)
1097 {
1098         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_input_display));
1099 }
1100
1101 void
1102 MixerStrip::output_changed (IOChange change, void *src)
1103 {
1104         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_output_display));
1105 }
1106
1107 void
1108 MixerStrip::comment_button_clicked ()
1109 {
1110         if (comment_window == 0) {
1111                 setup_comment_editor ();
1112         }
1113
1114         if (comment_window->is_visible()) {
1115                 comment_window->hide ();
1116                 return;
1117         } 
1118
1119         comment_window->set_position (Gtk::WIN_POS_MOUSE);
1120         comment_window->show_all ();
1121         comment_window->present();
1122         
1123         ResponseType response = (ResponseType) comment_window->run();
1124         comment_window->hide ();
1125
1126         switch (response) {
1127         case RESPONSE_ACCEPT:
1128                 break;
1129         default:
1130                 return;
1131         }
1132
1133         string str =  comment_area->get_buffer()->get_text();
1134         _route.set_comment (str, this);
1135         ARDOUR_UI::instance()->tooltips().set_tip (comment_button, 
1136                                                    str.empty() ? _("click to add/edit comments") : str);
1137 }
1138
1139 void
1140 MixerStrip::setup_comment_editor ()
1141 {
1142         string title;
1143         title = _route.name();
1144         title += _(": comment editor");
1145
1146         comment_window = new ArdourDialog (title, false);
1147         comment_area = manage (new TextView());
1148
1149         comment_area->set_name ("MixerTrackCommentArea");
1150         comment_area->set_editable (true);
1151         comment_area->get_buffer()->set_text (_route.comment());
1152         comment_area->set_size_request (200,100);
1153         comment_area->show ();
1154
1155         comment_window->get_vbox()->pack_start (*comment_area);
1156         comment_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1157         comment_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1158 }
1159
1160 void
1161 MixerStrip::comment_changed (void *src)
1162 {
1163         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::comment_changed), src));
1164         
1165         if (src != this) {
1166                 ignore_comment_edit = true;
1167                 if (comment_area) {
1168                         comment_area->get_buffer()->set_text (_route.comment());
1169                 }
1170                 ignore_comment_edit = false;
1171         }
1172 }
1173
1174 void
1175 MixerStrip::set_mix_group (RouteGroup *rg)
1176
1177 {
1178         _route.set_mix_group (rg, this);
1179         delete group_menu;
1180         group_menu = 0;
1181 }
1182
1183 void
1184 MixerStrip::add_mix_group_to_menu (RouteGroup *rg)
1185 {
1186         using namespace Menu_Helpers;
1187
1188         MenuList& items = group_menu->items();
1189         items.push_back (MenuElem (rg->name(), bind (mem_fun(*this, &MixerStrip::set_mix_group), rg)));
1190 }
1191
1192 gint
1193 MixerStrip::select_mix_group (GdkEventButton *ev)
1194 {
1195         using namespace Menu_Helpers;
1196
1197         group_menu = new Menu;
1198         group_menu->set_name ("ArdourContextMenu");
1199         MenuList& items = group_menu->items();
1200
1201         items.push_back (MenuElem (_("no group"), bind (mem_fun(*this, &MixerStrip::set_mix_group), (RouteGroup *) 0)));
1202         _session.foreach_mix_group (this, &MixerStrip::add_mix_group_to_menu);
1203
1204         group_menu->popup (ev->button, 0);
1205         return stop_signal (group_button, "button_press_event");
1206 }       
1207
1208 void
1209 MixerStrip::mix_group_changed (void *ignored)
1210 {
1211         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::mix_group_changed), ignored));
1212         
1213         RouteGroup *rg = _route.mix_group();
1214         
1215         if (rg) {
1216                 group_label.set_text (rg->name());
1217         } else {
1218                 switch (_width) {
1219                 case Wide:
1220                         group_label.set_text (_("no group"));
1221                         break;
1222                 case Narrow:
1223                         group_label.set_text (_("~G"));
1224                         break;
1225                 }
1226         }
1227 }
1228
1229 void
1230 MixerStrip::polarity_toggled ()
1231 {
1232         bool x;
1233
1234         if ((x = polarity_button.get_active()) != _route.phase_invert()) {
1235                 _route.set_phase_invert (x, this);
1236         }
1237 }
1238
1239
1240 void 
1241 MixerStrip::route_gui_changed (string what_changed, void* ignored)
1242 {
1243         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::route_gui_changed), what_changed, ignored));
1244         
1245         if (what_changed == "color") {
1246                 if (set_color_from_route () == 0) {
1247                         show_route_color ();
1248                 }
1249         }
1250 }
1251
1252 void
1253 MixerStrip::show_route_color ()
1254 {
1255         name_button.ensure_style ();
1256         Glib::RefPtr<Gtk::Style> style = name_button.get_style()->copy();
1257         style->set_bg (Gtk::STATE_NORMAL, color());
1258         name_button.set_style (style);
1259
1260         route_active_changed ();
1261 }
1262
1263 void
1264 MixerStrip::show_passthru_color ()
1265 {
1266         route_active_changed ();
1267 }
1268
1269 void
1270 MixerStrip::build_route_ops_menu ()
1271 {
1272         using namespace Menu_Helpers;
1273
1274         route_ops_menu = new Menu;
1275         route_ops_menu->set_name ("ArdourContextMenu");
1276
1277         MenuList& items = route_ops_menu->items();
1278         
1279         items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RouteUI::route_rename)));
1280         items.push_back (SeparatorElem());
1281         items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active)));
1282         route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
1283         route_active_menu_item->set_active (_route.active());
1284
1285         items.push_back (SeparatorElem());
1286         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
1287 }
1288
1289 gint
1290 MixerStrip::name_button_button_release (GdkEventButton* ev)
1291 {
1292         if (ev->button == 3) {
1293                 list_route_operations ();
1294         }
1295         return FALSE;
1296 }
1297
1298 void
1299 MixerStrip::list_route_operations ()
1300 {
1301         if (route_ops_menu == 0) {
1302                 build_route_ops_menu ();
1303         }
1304
1305         route_ops_menu->popup (1, 0);
1306 }
1307
1308
1309 void
1310 MixerStrip::speed_adjustment_changed ()
1311 {
1312         /* since there is a usable speed adjustment, there has to be a diskstream */
1313         if (!ignore_speed_adjustment) {
1314                 get_diskstream()->set_speed (speed_adjustment.get_value());
1315         }
1316 }
1317
1318 void
1319 MixerStrip::speed_changed ()
1320 {
1321         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_speed_display));
1322 }
1323
1324 void
1325 MixerStrip::update_speed_display ()
1326 {
1327         float val;
1328         
1329         val = get_diskstream()->speed();
1330
1331         if (val != 1.0) {
1332                 speed_spinner.set_name ("MixerStripSpeedBaseNotOne");
1333         } else {
1334                 speed_spinner.set_name ("MixerStripSpeedBase");
1335         }
1336
1337         if (speed_adjustment.get_value() != val) {
1338                 ignore_speed_adjustment = true;
1339                 speed_adjustment.set_value (val);
1340                 ignore_speed_adjustment = false;
1341         }
1342 }                       
1343
1344
1345 void
1346 MixerStrip::set_selected (bool yn)
1347 {
1348         AxisView::set_selected (yn);
1349         if (_selected) {
1350                 global_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
1351                 global_frame.set_name ("MixerStripSelectedFrame");
1352         } else {
1353                 global_frame.set_shadow_type (Gtk::SHADOW_IN);
1354                 global_frame.set_name ("MixerStripFrame");
1355         }
1356         global_frame.queue_draw ();
1357 }
1358
1359 void
1360 MixerStrip::name_changed (void *src)
1361 {
1362         switch (_width) {
1363         case Wide:
1364                 RouteUI::name_changed (src);
1365                 break;
1366         case Narrow:
1367                 name_label.set_text (short_version (_route.name(), 5));
1368                 break;
1369         }
1370 }
1371
1372 void
1373 MixerStrip::width_clicked ()
1374 {
1375         switch (_width) {
1376         case Wide:
1377                 set_width (Narrow);
1378                 break;
1379         case Narrow:
1380                 set_width (Wide);
1381                 break;
1382         }
1383 }
1384
1385 void
1386 MixerStrip::hide_clicked ()
1387 {
1388         if (_embedded) {
1389                  Hiding(); /* EMIT_SIGNAL */
1390         } else {
1391                 _mixer.unselect_strip_in_display (this);
1392         }
1393 }
1394
1395 void
1396 MixerStrip::set_embedded (bool yn)
1397 {
1398         _embedded = yn;
1399 }
1400
1401 void
1402 MixerStrip::map_frozen ()
1403 {
1404         ENSURE_GUI_THREAD (mem_fun(*this, &MixerStrip::map_frozen));
1405
1406         AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
1407
1408         if (at) {
1409                 switch (at->freeze_state()) {
1410                 case AudioTrack::Frozen:
1411                         pre_redirect_box.set_sensitive (false);
1412                         post_redirect_box.set_sensitive (false);
1413                         speed_spinner.set_sensitive (false);
1414                         break;
1415                 default:
1416                         pre_redirect_box.set_sensitive (true);
1417                         post_redirect_box.set_sensitive (true);
1418                         speed_spinner.set_sensitive (true);
1419                         break;
1420                 }
1421         }
1422         _route.foreach_redirect (this, &MixerStrip::hide_redirect_editor);
1423 }
1424
1425 void
1426 MixerStrip::hide_redirect_editor (Redirect* redirect)
1427 {
1428         void* gui = redirect->get_gui ();
1429         
1430         if (gui) {
1431                 static_cast<Gtk::Widget*>(gui)->hide ();
1432         }
1433 }
1434
1435 void
1436 MixerStrip::route_active_changed ()
1437 {
1438         RouteUI::route_active_changed ();
1439
1440         if (is_audio_track()) {
1441                 if (_route.active()) {
1442                         set_name ("AudioTrackStripBase");
1443                         gpm.set_meter_strip_name ("AudioTrackStripBase");
1444                 } else {
1445                         set_name ("AudioTrackStripBaseInactive");
1446                         gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
1447                 }
1448                 gpm.set_fader_name ("AudioTrackFader");
1449         } else {
1450                 if (_route.active()) {
1451                         set_name ("AudioBusStripBase");
1452                         gpm.set_meter_strip_name ("AudioBusStripBase");
1453                 } else {
1454                         set_name ("AudioBusStripBaseInactive");
1455                         gpm.set_meter_strip_name ("AudioBusStripBaseInactive");
1456                 }
1457                 gpm.set_fader_name ("AudioBusFader");
1458         }
1459 }