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