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