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