a005d3637ec85965825769eb1c6a60e3ec3729fa
[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
632         input_menu.popup (1, ev->time);
633
634         return TRUE;
635 }
636
637 void
638 MixerStrip::connection_input_chosen (ARDOUR::Connection *c)
639 {
640         if (!ignore_toggle) {
641
642                 try { 
643                         _route.use_input_connection (*c, this);
644                 }
645
646                 catch (AudioEngine::PortRegistrationFailure& err) {
647                         error << _("could not register new ports required for that connection")
648                               << endmsg;
649                 }
650         }
651 }
652
653 void
654 MixerStrip::connection_output_chosen (ARDOUR::Connection *c)
655 {
656         if (!ignore_toggle) {
657
658                 try { 
659                         _route.use_output_connection (*c, this);
660                 }
661
662                 catch (AudioEngine::PortRegistrationFailure& err) {
663                         error << _("could not register new ports required for that connection")
664                               << endmsg;
665                 }
666         }
667 }
668
669 void
670 MixerStrip::add_connection_to_input_menu (ARDOUR::Connection* c)
671 {
672         using namespace Menu_Helpers;
673
674         if (dynamic_cast<InputConnection *> (c) == 0) {
675                 return;
676         }
677
678         MenuList& citems = input_menu.items();
679         
680         if (c->nports() == _route.n_inputs()) {
681
682                 citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_input_chosen), c)));
683                 
684                 ARDOUR::Connection *current = _route.input_connection();
685                 
686                 if (current == c) {
687                         ignore_toggle = true;
688                         dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
689                         ignore_toggle = false;
690                 }
691         }
692 }
693
694 void
695 MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c)
696 {
697         using namespace Menu_Helpers;
698
699         if (dynamic_cast<OutputConnection *> (c) == 0) {
700                 return;
701         }
702
703         if (c->nports() == _route.n_outputs()) {
704
705                 MenuList& citems = output_menu.items();
706                 citems.push_back (CheckMenuElem (c->name(), bind (mem_fun(*this, &MixerStrip::connection_output_chosen), c)));
707                 
708                 ARDOUR::Connection *current = _route.output_connection();
709                 
710                 if (current == c) {
711                         ignore_toggle = true;
712                         dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
713                         ignore_toggle = false;
714                 }
715         }
716 }
717
718 void
719 MixerStrip::select_stream_input ()
720 {
721         using namespace Menu_Helpers;
722
723         Menu *stream_menu = manage (new Menu);
724         MenuList& items = stream_menu->items();
725         stream_menu->set_name ("ArdourContextMenu");
726         
727         Session::DiskStreamList streams = _session.disk_streams();
728
729         for (Session::DiskStreamList::iterator i = streams.begin(); i != streams.end(); ++i) {
730
731                 if (!(*i)->hidden()) {
732
733                         items.push_back (CheckMenuElem ((*i)->name(), bind (mem_fun(*this, &MixerStrip::stream_input_chosen), *i)));
734                         
735                         if (get_diskstream() == *i) {
736                                 ignore_toggle = true;
737                                 static_cast<CheckMenuItem *> (&items.back())->set_active (true);
738                                 ignore_toggle = false;
739                         } 
740                 }
741         }
742         
743         stream_menu->popup (1, 0);
744 }
745
746 void
747 MixerStrip::stream_input_chosen (DiskStream *stream)
748 {
749         if (is_audio_track()) {
750                 audio_track()->set_diskstream (*stream, this);
751         }
752 }
753
754 void
755 MixerStrip::update_diskstream_display ()
756 {
757         if (is_audio_track()) {
758
759                 map_frozen ();
760
761                 update_input_display ();
762
763                 if (input_selector) {
764                         input_selector->hide_all ();
765                 }
766
767                 show_route_color ();
768
769         } else {
770
771                 map_frozen ();
772
773                 update_input_display ();
774                 show_passthru_color ();
775         }
776 }
777
778 void
779 MixerStrip::connect_to_pan ()
780 {
781         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::connect_to_pan));
782         
783         panstate_connection.disconnect ();
784         panstyle_connection.disconnect ();
785
786         if (!_route.panner().empty()) {
787                 StreamPanner* sp = _route.panner().front();
788
789                 panstate_connection = sp->automation().automation_state_changed.connect (mem_fun(*this, &MixerStrip::pan_automation_state_changed));
790                 panstyle_connection = sp->automation().automation_style_changed.connect (mem_fun(*this, &MixerStrip::pan_automation_style_changed));
791         }
792
793         panners.pan_changed (this);
794 }
795
796 void
797 MixerStrip::update_input_display ()
798 {
799         ARDOUR::Connection *c;
800
801         if ((c = _route.input_connection()) != 0) {
802                 input_label.set_text (c->name());
803         } else {
804                 switch (_width) {
805                 case Wide:
806                         input_label.set_text (_("INPUT"));
807                         break;
808                 case Narrow:
809                         input_label.set_text (_("IN"));
810                         break;
811                 }
812         }
813
814         panners.setup_pan ();
815 }
816
817 void
818 MixerStrip::update_output_display ()
819 {
820         ARDOUR::Connection *c;
821
822         if ((c = _route.output_connection()) != 0) {
823                 output_label.set_text (c->name());
824         } else {
825                 switch (_width) {
826                 case Wide:
827                         output_label.set_text (_("OUTPUT"));
828                         break;
829                 case Narrow:
830                         output_label.set_text (_("OUT"));
831                         break;
832                 }
833         }
834
835         gpm.setup_meters ();
836         panners.setup_pan ();
837 }
838
839 void
840 MixerStrip::update ()
841 {
842         gpm.update_meters ();
843 }
844
845 void
846 MixerStrip::fast_update ()
847 {
848         if (_session.meter_falloff() > 0.0f) {
849                 gpm.update_meters_falloff ();
850         }
851 }
852
853 gint
854 MixerStrip::gain_automation_state_button_event (GdkEventButton *ev)
855 {
856         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
857                 return TRUE;
858         }
859         
860         switch (ev->button) {
861         case 1:
862                 switch (ev->button) {
863                 case 1:
864                         gain_astate_menu.popup (1, ev->time);
865                         break;
866                 default:
867                         break;
868                 }
869         }
870
871         return TRUE;
872 }
873
874 gint
875 MixerStrip::gain_automation_style_button_event (GdkEventButton *ev)
876 {
877         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
878                 return TRUE;
879         }
880
881         switch (ev->button) {
882         case 1:
883                 gain_astyle_menu.popup (1, ev->time);
884                 break;
885         default:
886                 break;
887         }
888         return TRUE;
889 }
890
891 gint
892 MixerStrip::pan_automation_state_button_event (GdkEventButton *ev)
893 {
894         using namespace Menu_Helpers;
895
896         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
897                 return TRUE;
898         }
899
900         switch (ev->button) {
901         case 1:
902                 pan_astate_menu.popup (1, ev->time);
903                 break;
904         default:
905                 break;
906         }
907
908         return TRUE;
909 }
910
911 gint
912 MixerStrip::pan_automation_style_button_event (GdkEventButton *ev)
913 {
914         switch (ev->button) {
915         case 1:
916                 pan_astyle_menu.popup (1, ev->time);
917                 break;
918         default:
919                 break;
920         }
921         return TRUE;
922 }
923
924 string
925 MixerStrip::astate_string (AutoState state)
926 {
927         return _astate_string (state, false);
928 }
929
930 string
931 MixerStrip::short_astate_string (AutoState state)
932 {
933         return _astate_string (state, true);
934 }
935
936 string
937 MixerStrip::_astate_string (AutoState state, bool shrt)
938 {
939         string sstr;
940
941         switch (state) {
942         case Off:
943                 sstr = (shrt ? "--" : _("off"));
944                 break;
945         case Play:
946                 sstr = (shrt ? "P" : _("aplay"));
947                 break;
948         case Touch:
949                 sstr = (shrt ? "T" : _("touch"));
950                 break;
951         case Write:
952                 sstr = (shrt ? "W" : _("awrite"));
953                 break;
954         }
955
956         return sstr;
957 }
958
959 string
960 MixerStrip::astyle_string (AutoStyle style)
961 {
962         return _astyle_string (style, false);
963 }
964
965 string
966 MixerStrip::short_astyle_string (AutoStyle style)
967 {
968         return _astyle_string (style, true);
969 }
970
971 string
972 MixerStrip::_astyle_string (AutoStyle style, bool shrt)
973 {
974         if (style & Trim) {
975                 return _("trim");
976         } else {
977                 /* XXX it might different in different languages */
978
979                 return (shrt ? _("abs") : _("abs"));
980         }
981 }
982
983 void
984 MixerStrip::diskstream_changed (void *src)
985 {
986         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_diskstream_display));
987 }       
988
989 void
990 MixerStrip::gain_automation_style_changed ()
991 {
992         switch (_width) {
993         case Wide:
994                 static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style()));
995                 break;
996         case Narrow:
997                 static_cast<Gtk::Label*> (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style()));
998                 break;
999         }
1000 }
1001
1002 void
1003 MixerStrip::gain_automation_state_changed ()
1004 {
1005         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::gain_automation_state_changed));
1006         
1007         bool x;
1008
1009         switch (_width) {
1010         case Wide:
1011                 static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state()));
1012                 break;
1013         case Narrow:
1014                 static_cast<Gtk::Label*> (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state()));
1015                 break;
1016         }
1017
1018         x = (_route.gain_automation_state() != Off);
1019         
1020         if (gain_automation_state_button.get_active() != x) {
1021                 ignore_toggle = true;
1022                 gain_automation_state_button.set_active (x);
1023                 ignore_toggle = false;
1024         }
1025
1026         gpm.update_gain_sensitive ();
1027         
1028         /* start watching automation so that things move */
1029         
1030         gain_watching.disconnect();
1031
1032         if (x) {
1033                 gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (gpm, &GainMeter::effective_gain_display));
1034         }
1035 }
1036
1037 void
1038 MixerStrip::pan_automation_style_changed ()
1039 {
1040         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::pan_automation_style_changed));
1041         
1042         switch (_width) {
1043         case Wide:
1044                 static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style()));
1045                 break;
1046         case Narrow:
1047                 static_cast<Gtk::Label*> (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style()));
1048                 break;
1049         }
1050 }
1051
1052 void
1053 MixerStrip::pan_automation_state_changed ()
1054 {
1055         ENSURE_GUI_THREAD(mem_fun(*this, &MixerStrip::pan_automation_state_changed));
1056         
1057         bool x;
1058
1059         switch (_width) {
1060         case Wide:
1061                 static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state()));
1062                 break;
1063         case Narrow:
1064                 static_cast<Gtk::Label*> (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state()));
1065                 break;
1066         }
1067
1068         /* when creating a new session, we get to create busses (and
1069            sometimes tracks) with no outputs by the time they get
1070            here.
1071         */
1072
1073         if (_route.panner().empty()) {
1074                 return;
1075         }
1076
1077         x = (_route.panner().front()->automation().automation_state() != Off);
1078
1079         if (pan_automation_state_button.get_active() != x) {
1080                 ignore_toggle = true;
1081                 pan_automation_state_button.set_active (x);
1082                 ignore_toggle = false;
1083         }
1084
1085         panners.update_pan_sensitive ();
1086         
1087         /* start watching automation so that things move */
1088         
1089         pan_watching.disconnect();
1090
1091         if (x) {
1092                 pan_watching = ARDOUR_UI::RapidScreenUpdate.connect (mem_fun (panners, &PannerUI::effective_pan_display));
1093         }
1094 }
1095
1096 void
1097 MixerStrip::input_changed (IOChange change, void *src)
1098 {
1099         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_input_display));
1100 }
1101
1102 void
1103 MixerStrip::output_changed (IOChange change, void *src)
1104 {
1105         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_output_display));
1106 }
1107
1108 void
1109 MixerStrip::comment_button_clicked ()
1110 {
1111         if (comment_window == 0) {
1112                 setup_comment_editor ();
1113         }
1114
1115         if (comment_window->is_visible()) {
1116                 comment_window->hide ();
1117                 return;
1118         } 
1119
1120         comment_window->set_position (Gtk::WIN_POS_MOUSE);
1121         comment_window->show_all ();
1122         comment_window->present();
1123         
1124         ResponseType response = (ResponseType) comment_window->run();
1125         comment_window->hide ();
1126
1127         switch (response) {
1128         case RESPONSE_ACCEPT:
1129                 break;
1130         default:
1131                 return;
1132         }
1133
1134         string str =  comment_area->get_buffer()->get_text();
1135         _route.set_comment (str, this);
1136         ARDOUR_UI::instance()->tooltips().set_tip (comment_button, 
1137                                                    str.empty() ? _("click to add/edit comments") : str);
1138 }
1139
1140 void
1141 MixerStrip::setup_comment_editor ()
1142 {
1143         string title;
1144         title = _route.name();
1145         title += _(": comment editor");
1146
1147         comment_window = new ArdourDialog (title, false);
1148         comment_area = manage (new TextView());
1149
1150         comment_area->set_name ("MixerTrackCommentArea");
1151         comment_area->set_editable (true);
1152         comment_area->get_buffer()->set_text (_route.comment());
1153         comment_area->set_size_request (200,100);
1154         comment_area->show ();
1155
1156         comment_window->get_vbox()->pack_start (*comment_area);
1157         comment_window->add_button (Stock::CANCEL, RESPONSE_CANCEL);
1158         comment_window->add_button (Stock::OK, RESPONSE_ACCEPT);
1159 }
1160
1161 void
1162 MixerStrip::comment_changed (void *src)
1163 {
1164         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::comment_changed), src));
1165         
1166         if (src != this) {
1167                 ignore_comment_edit = true;
1168                 if (comment_area) {
1169                         comment_area->get_buffer()->set_text (_route.comment());
1170                 }
1171                 ignore_comment_edit = false;
1172         }
1173 }
1174
1175 void
1176 MixerStrip::set_mix_group (RouteGroup *rg)
1177
1178 {
1179         _route.set_mix_group (rg, this);
1180         delete group_menu;
1181         group_menu = 0;
1182 }
1183
1184 void
1185 MixerStrip::add_mix_group_to_menu (RouteGroup *rg)
1186 {
1187         using namespace Menu_Helpers;
1188
1189         MenuList& items = group_menu->items();
1190         items.push_back (MenuElem (rg->name(), bind (mem_fun(*this, &MixerStrip::set_mix_group), rg)));
1191 }
1192
1193 gint
1194 MixerStrip::select_mix_group (GdkEventButton *ev)
1195 {
1196         using namespace Menu_Helpers;
1197
1198         group_menu = new Menu;
1199         group_menu->set_name ("ArdourContextMenu");
1200         MenuList& items = group_menu->items();
1201
1202         items.push_back (MenuElem (_("no group"), bind (mem_fun(*this, &MixerStrip::set_mix_group), (RouteGroup *) 0)));
1203         _session.foreach_mix_group (this, &MixerStrip::add_mix_group_to_menu);
1204
1205         group_menu->popup (ev->button, 0);
1206         return stop_signal (group_button, "button_press_event");
1207 }       
1208
1209 void
1210 MixerStrip::mix_group_changed (void *ignored)
1211 {
1212         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::mix_group_changed), ignored));
1213         
1214         RouteGroup *rg = _route.mix_group();
1215         
1216         if (rg) {
1217                 group_label.set_text (rg->name());
1218         } else {
1219                 switch (_width) {
1220                 case Wide:
1221                         group_label.set_text (_("no group"));
1222                         break;
1223                 case Narrow:
1224                         group_label.set_text (_("~G"));
1225                         break;
1226                 }
1227         }
1228 }
1229
1230 void
1231 MixerStrip::polarity_toggled ()
1232 {
1233         bool x;
1234
1235         if ((x = polarity_button.get_active()) != _route.phase_invert()) {
1236                 _route.set_phase_invert (x, this);
1237         }
1238 }
1239
1240
1241 void 
1242 MixerStrip::route_gui_changed (string what_changed, void* ignored)
1243 {
1244         ENSURE_GUI_THREAD(bind (mem_fun(*this, &MixerStrip::route_gui_changed), what_changed, ignored));
1245         
1246         if (what_changed == "color") {
1247                 if (set_color_from_route () == 0) {
1248                         show_route_color ();
1249                 }
1250         }
1251 }
1252
1253 void
1254 MixerStrip::show_route_color ()
1255 {
1256         name_button.ensure_style ();
1257         Glib::RefPtr<Gtk::Style> style = name_button.get_style()->copy();
1258         style->set_bg (Gtk::STATE_NORMAL, color());
1259         name_button.set_style (style);
1260
1261         route_active_changed ();
1262 }
1263
1264 void
1265 MixerStrip::show_passthru_color ()
1266 {
1267         route_active_changed ();
1268 }
1269
1270 void
1271 MixerStrip::build_route_ops_menu ()
1272 {
1273         using namespace Menu_Helpers;
1274
1275         route_ops_menu = new Menu;
1276         route_ops_menu->set_name ("ArdourContextMenu");
1277
1278         MenuList& items = route_ops_menu->items();
1279         
1280         items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RouteUI::route_rename)));
1281         items.push_back (SeparatorElem());
1282         items.push_back (CheckMenuElem (_("Active"), mem_fun(*this, &RouteUI::toggle_route_active)));
1283         route_active_menu_item = dynamic_cast<CheckMenuItem *> (&items.back());
1284         route_active_menu_item->set_active (_route.active());
1285
1286         items.push_back (SeparatorElem());
1287         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
1288 }
1289
1290 gint
1291 MixerStrip::name_button_button_release (GdkEventButton* ev)
1292 {
1293         if (ev->button == 3) {
1294                 list_route_operations ();
1295         }
1296         return FALSE;
1297 }
1298
1299 void
1300 MixerStrip::list_route_operations ()
1301 {
1302         if (route_ops_menu == 0) {
1303                 build_route_ops_menu ();
1304         }
1305
1306         route_ops_menu->popup (1, 0);
1307 }
1308
1309
1310 void
1311 MixerStrip::speed_adjustment_changed ()
1312 {
1313         /* since there is a usable speed adjustment, there has to be a diskstream */
1314         if (!ignore_speed_adjustment) {
1315                 get_diskstream()->set_speed (speed_adjustment.get_value());
1316         }
1317 }
1318
1319 void
1320 MixerStrip::speed_changed ()
1321 {
1322         Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_speed_display));
1323 }
1324
1325 void
1326 MixerStrip::update_speed_display ()
1327 {
1328         float val;
1329         
1330         val = get_diskstream()->speed();
1331
1332         if (val != 1.0) {
1333                 speed_spinner.set_name ("MixerStripSpeedBaseNotOne");
1334         } else {
1335                 speed_spinner.set_name ("MixerStripSpeedBase");
1336         }
1337
1338         if (speed_adjustment.get_value() != val) {
1339                 ignore_speed_adjustment = true;
1340                 speed_adjustment.set_value (val);
1341                 ignore_speed_adjustment = false;
1342         }
1343 }                       
1344
1345
1346 void
1347 MixerStrip::set_selected (bool yn)
1348 {
1349         AxisView::set_selected (yn);
1350         if (_selected) {
1351                 global_frame.set_shadow_type (Gtk::SHADOW_ETCHED_OUT);
1352                 global_frame.set_name ("MixerStripSelectedFrame");
1353         } else {
1354                 global_frame.set_shadow_type (Gtk::SHADOW_IN);
1355                 global_frame.set_name ("MixerStripFrame");
1356         }
1357         global_frame.queue_draw ();
1358 }
1359
1360 void
1361 MixerStrip::name_changed (void *src)
1362 {
1363         switch (_width) {
1364         case Wide:
1365                 RouteUI::name_changed (src);
1366                 break;
1367         case Narrow:
1368                 name_label.set_text (short_version (_route.name(), 5));
1369                 break;
1370         }
1371 }
1372
1373 void
1374 MixerStrip::width_clicked ()
1375 {
1376         switch (_width) {
1377         case Wide:
1378                 set_width (Narrow);
1379                 break;
1380         case Narrow:
1381                 set_width (Wide);
1382                 break;
1383         }
1384 }
1385
1386 void
1387 MixerStrip::hide_clicked ()
1388 {
1389         if (_embedded) {
1390                  Hiding(); /* EMIT_SIGNAL */
1391         } else {
1392                 _mixer.unselect_strip_in_display (this);
1393         }
1394 }
1395
1396 void
1397 MixerStrip::set_embedded (bool yn)
1398 {
1399         _embedded = yn;
1400 }
1401
1402 void
1403 MixerStrip::map_frozen ()
1404 {
1405         ENSURE_GUI_THREAD (mem_fun(*this, &MixerStrip::map_frozen));
1406
1407         AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
1408
1409         if (at) {
1410                 switch (at->freeze_state()) {
1411                 case AudioTrack::Frozen:
1412                         pre_redirect_box.set_sensitive (false);
1413                         post_redirect_box.set_sensitive (false);
1414                         speed_spinner.set_sensitive (false);
1415                         break;
1416                 default:
1417                         pre_redirect_box.set_sensitive (true);
1418                         post_redirect_box.set_sensitive (true);
1419                         speed_spinner.set_sensitive (true);
1420                         break;
1421                 }
1422         }
1423         _route.foreach_redirect (this, &MixerStrip::hide_redirect_editor);
1424 }
1425
1426 void
1427 MixerStrip::hide_redirect_editor (Redirect* redirect)
1428 {
1429         void* gui = redirect->get_gui ();
1430         
1431         if (gui) {
1432                 static_cast<Gtk::Widget*>(gui)->hide ();
1433         }
1434 }
1435
1436 void
1437 MixerStrip::route_active_changed ()
1438 {
1439         RouteUI::route_active_changed ();
1440
1441         if (is_audio_track()) {
1442                 if (_route.active()) {
1443                         set_name ("AudioTrackStripBase");
1444                         gpm.set_meter_strip_name ("AudioTrackStripBase");
1445                 } else {
1446                         set_name ("AudioTrackStripBaseInactive");
1447                         gpm.set_meter_strip_name ("AudioTrackStripBaseInactive");
1448                 }
1449                 gpm.set_fader_name ("AudioTrackFader");
1450         } else {
1451                 if (_route.active()) {
1452                         set_name ("AudioBusStripBase");
1453                         gpm.set_meter_strip_name ("AudioBusStripBase");
1454                 } else {
1455                         set_name ("AudioBusStripBaseInactive");
1456                         gpm.set_meter_strip_name ("AudioBusStripBaseInactive");
1457                 }
1458                 gpm.set_fader_name ("AudioBusFader");
1459         }
1460 }