~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to gtk2_ardour/route_ui.cc

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
Import upstream version 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2002-2006 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
*/
 
19
 
 
20
#include <gtkmm2ext/gtk_ui.h>
 
21
#include <gtkmm2ext/choice.h>
 
22
#include <gtkmm2ext/doi.h>
 
23
#include <gtkmm2ext/bindable_button.h>
 
24
#include <gtkmm2ext/barcontroller.h>
 
25
#include <gtkmm2ext/gtk_ui.h>
 
26
 
 
27
#include "ardour/route_group.h"
 
28
#include "ardour/dB.h"
 
29
#include "pbd/memento_command.h"
 
30
#include "pbd/stacktrace.h"
 
31
#include "pbd/controllable.h"
 
32
#include "pbd/enumwriter.h"
 
33
 
 
34
#include "ardour_ui.h"
 
35
#include "editor.h"
 
36
#include "route_ui.h"
 
37
#include "ardour_button.h"
 
38
#include "keyboard.h"
 
39
#include "utils.h"
 
40
#include "prompter.h"
 
41
#include "gui_thread.h"
 
42
#include "ardour_dialog.h"
 
43
#include "latency_gui.h"
 
44
#include "mixer_strip.h"
 
45
#include "automation_time_axis.h"
 
46
#include "route_time_axis.h"
 
47
#include "group_tabs.h"
 
48
 
 
49
#include "ardour/audio_track.h"
 
50
#include "ardour/audioengine.h"
 
51
#include "ardour/filename_extensions.h"
 
52
#include "ardour/midi_track.h"
 
53
#include "ardour/route.h"
 
54
#include "ardour/session.h"
 
55
#include "ardour/template_utils.h"
 
56
 
 
57
#include "i18n.h"
 
58
using namespace Gtk;
 
59
using namespace Gtkmm2ext;
 
60
using namespace ARDOUR;
 
61
using namespace PBD;
 
62
 
 
63
uint32_t RouteUI::_max_invert_buttons = 3;
 
64
PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
 
65
boost::weak_ptr<Route> RouteUI::_showing_sends_to;
 
66
 
 
67
RouteUI::RouteUI (ARDOUR::Session* sess)
 
68
        : AxisView(sess)
 
69
        , mute_menu(0)
 
70
        , solo_menu(0)
 
71
        , sends_menu(0)
 
72
        , record_menu(0)
 
73
        , _invert_menu(0)
 
74
{
 
75
        if (sess) init ();
 
76
}
 
77
 
 
78
RouteUI::~RouteUI()
 
79
{
 
80
        _route.reset (); /* drop reference to route, so that it can be cleaned up */
 
81
        route_connections.drop_connections ();
 
82
 
 
83
        delete solo_menu;
 
84
        delete mute_menu;
 
85
        delete sends_menu;
 
86
        delete record_menu;
 
87
        delete _invert_menu;
 
88
}
 
89
 
 
90
void
 
91
RouteUI::init ()
 
92
{
 
93
        self_destruct = true;
 
94
        mute_menu = 0;
 
95
        solo_menu = 0;
 
96
        sends_menu = 0;
 
97
        record_menu = 0;
 
98
        _invert_menu = 0;
 
99
        pre_fader_mute_check = 0;
 
100
        post_fader_mute_check = 0;
 
101
        listen_mute_check = 0;
 
102
        main_mute_check = 0;
 
103
        solo_safe_check = 0;
 
104
        solo_isolated_check = 0;
 
105
        solo_isolated_led = 0;
 
106
        solo_safe_led = 0;
 
107
        _solo_release = 0;
 
108
        _mute_release = 0;
 
109
        denormal_menu_item = 0;
 
110
        step_edit_item = 0;
 
111
        multiple_mute_change = false;
 
112
        multiple_solo_change = false;
 
113
        _i_am_the_modifier = 0;
 
114
 
 
115
        setup_invert_buttons ();
 
116
 
 
117
        mute_button = manage (new ArdourButton);
 
118
        mute_button->set_name ("mute button");
 
119
        UI::instance()->set_tip (mute_button, _("Mute this track"), "");
 
120
 
 
121
        solo_button = manage (new ArdourButton);
 
122
        solo_button->set_name ("solo button");
 
123
        UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
 
124
        solo_button->set_no_show_all (true);
 
125
 
 
126
        rec_enable_button = manage (new ArdourButton);
 
127
        rec_enable_button->set_name ("record enable button");
 
128
        rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
 
129
        UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
 
130
 
 
131
        show_sends_button = manage (new ArdourButton);
 
132
        show_sends_button->set_name ("send alert button");
 
133
        UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
 
134
 
 
135
        monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
 
136
        monitor_input_button->set_name ("monitor button");
 
137
        monitor_input_button->set_text (_("In"));
 
138
        UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
 
139
        monitor_input_button->set_no_show_all (true);
 
140
        
 
141
        monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
 
142
        monitor_disk_button->set_name ("monitor button");
 
143
        monitor_disk_button->set_text (_("Disk"));
 
144
        UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
 
145
        monitor_disk_button->set_no_show_all (true);
 
146
 
 
147
        _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
 
148
        _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
 
149
        _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
 
150
 
 
151
        _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
 
152
        Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
 
153
 
 
154
        rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
 
155
        rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
 
156
 
 
157
        show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
 
158
        show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
 
159
 
 
160
        solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
 
161
        solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
 
162
        mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
 
163
        mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
 
164
        
 
165
        monitor_input_button->set_distinct_led_click (false);
 
166
        monitor_disk_button->set_distinct_led_click (false);
 
167
 
 
168
        monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
 
169
        monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
 
170
 
 
171
        monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
 
172
        monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
 
173
 
 
174
        BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
 
175
}
 
176
 
 
177
void
 
178
RouteUI::reset ()
 
179
{
 
180
        route_connections.drop_connections ();
 
181
 
 
182
        delete solo_menu;
 
183
        solo_menu = 0;
 
184
 
 
185
        delete mute_menu;
 
186
        mute_menu = 0;
 
187
 
 
188
        denormal_menu_item = 0;
 
189
}
 
190
 
 
191
void
 
192
RouteUI::self_delete ()
 
193
{
 
194
        delete this;
 
195
}
 
196
 
 
197
void
 
198
RouteUI::set_route (boost::shared_ptr<Route> rp)
 
199
{
 
200
        reset ();
 
201
 
 
202
        _route = rp;
 
203
 
 
204
        if (set_color_from_route()) {
 
205
                set_color (unique_random_color());
 
206
        }
 
207
 
 
208
        if (self_destruct) {
 
209
                rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
 
210
        }
 
211
 
 
212
        mute_button->set_controllable (_route->mute_control());
 
213
        solo_button->set_controllable (_route->solo_control());
 
214
 
 
215
        _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
 
216
        _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
 
217
 
 
218
        _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
 
219
        _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
 
220
        _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
 
221
        _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
 
222
 
 
223
        _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
 
224
        _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
 
225
 
 
226
        _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
 
227
        _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
 
228
 
 
229
        if (_session->writable() && is_track()) {
 
230
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
231
 
 
232
                t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
 
233
                
 
234
                rec_enable_button->show();
 
235
                rec_enable_button->set_controllable (t->rec_enable_control());
 
236
 
 
237
                if (is_midi_track()) {
 
238
                        midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
 
239
                                                                    boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
 
240
                }
 
241
 
 
242
        } 
 
243
 
 
244
        /* this will work for busses and tracks, and needs to be called to
 
245
           set up the name entry/name label display.
 
246
        */
 
247
 
 
248
        update_rec_display ();
 
249
 
 
250
        if (is_track()) {
 
251
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
252
                t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
 
253
 
 
254
                update_monitoring_display ();
 
255
        }
 
256
 
 
257
        mute_button->unset_flags (Gtk::CAN_FOCUS);
 
258
        solo_button->unset_flags (Gtk::CAN_FOCUS);
 
259
 
 
260
        mute_button->show();
 
261
 
 
262
        if (_route->is_monitor() || _route->is_master()) {
 
263
                solo_button->hide ();
 
264
        } else {
 
265
                solo_button->show();
 
266
        }
 
267
 
 
268
        map_frozen ();
 
269
 
 
270
        setup_invert_buttons ();
 
271
        set_invert_button_state ();
 
272
 
 
273
        boost::shared_ptr<Route> s = _showing_sends_to.lock ();
 
274
        bus_send_display_changed (s);
 
275
 
 
276
        update_mute_display ();
 
277
        update_solo_display ();
 
278
}
 
279
 
 
280
void
 
281
RouteUI::polarity_changed ()
 
282
{
 
283
        if (!_route) {
 
284
                return;
 
285
        }
 
286
 
 
287
        set_invert_button_state ();
 
288
}
 
289
 
 
290
bool
 
291
RouteUI::mute_press (GdkEventButton* ev)
 
292
{
 
293
        if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
 
294
                return true;
 
295
        }
 
296
 
 
297
        multiple_mute_change = false;
 
298
 
 
299
        if (!_i_am_the_modifier) {
 
300
 
 
301
                if (Keyboard::is_context_menu_event (ev)) {
 
302
 
 
303
                        if (mute_menu == 0){
 
304
                                build_mute_menu();
 
305
                        }
 
306
 
 
307
                        mute_menu->popup(0,ev->time);
 
308
 
 
309
                } else {
 
310
 
 
311
                        if (Keyboard::is_button2_event (ev)) {
 
312
                                // Primary-button2 click is the midi binding click
 
313
                                // button2-click is "momentary"
 
314
 
 
315
 
 
316
                                if (mute_button->on_button_press_event (ev)) {
 
317
                                        return true;
 
318
                                }
 
319
 
 
320
                                _mute_release = new SoloMuteRelease (_route->muted ());
 
321
                        }
 
322
 
 
323
                        if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
 
324
 
 
325
                                if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
326
 
 
327
                                        /* toggle mute on everything (but
 
328
                                         * exclude the master and monitor)
 
329
                                         *
 
330
                                         * because we are going to erase
 
331
                                         * elements of the list we need to work
 
332
                                         * on a copy.
 
333
                                         */
 
334
                                        
 
335
                                        boost::shared_ptr<RouteList> copy (new RouteList);
 
336
 
 
337
                                        *copy = *_session->get_routes ();
 
338
 
 
339
                                        for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
 
340
                                                if ((*i)->is_master() || (*i)->is_monitor()) {
 
341
                                                        i = copy->erase (i);
 
342
                                                } else {
 
343
                                                        ++i;
 
344
                                                }
 
345
                                        }
 
346
 
 
347
                                        if (_mute_release) {
 
348
                                                _mute_release->routes = copy;
 
349
                                        }
 
350
 
 
351
                                        _session->set_mute (copy, !_route->muted());
 
352
 
 
353
                                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
354
 
 
355
                                        /* Primary-button1 applies change to the mix group even if it is not active
 
356
                                           NOTE: Primary-button2 is MIDI learn.
 
357
                                        */
 
358
 
 
359
                                        boost::shared_ptr<RouteList> rl;
 
360
 
 
361
                                        if (ev->button == 1) { 
 
362
 
 
363
                                                if (_route->route_group()) {
 
364
                                                        
 
365
                                                        rl = _route->route_group()->route_list();
 
366
                                                        
 
367
                                                        if (_mute_release) {
 
368
                                                                _mute_release->routes = rl;
 
369
                                                        }
 
370
                                                } else {
 
371
                                                        rl.reset (new RouteList);
 
372
                                                        rl->push_back (_route);
 
373
                                                }
 
374
 
 
375
                                                _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
 
376
                                        }
 
377
 
 
378
                                } else {
 
379
 
 
380
                                        /* plain click applies change to this route */
 
381
 
 
382
                                        boost::shared_ptr<RouteList> rl (new RouteList);
 
383
                                        rl->push_back (_route);
 
384
                                        
 
385
                                        if (_mute_release) {
 
386
                                                _mute_release->routes = rl;
 
387
                                        }
 
388
 
 
389
                                        _session->set_mute (rl, !_route->muted());
 
390
 
 
391
                                }
 
392
                        }
 
393
                }
 
394
 
 
395
        }
 
396
 
 
397
        return true;
 
398
}
 
399
 
 
400
bool
 
401
RouteUI::mute_release (GdkEventButton*)
 
402
{
 
403
        if (!_i_am_the_modifier) {
 
404
                if (_mute_release){
 
405
                        _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
 
406
                        delete _mute_release;
 
407
                        _mute_release = 0;
 
408
                }
 
409
        }
 
410
 
 
411
        return true;
 
412
}
 
413
 
 
414
bool
 
415
RouteUI::solo_press(GdkEventButton* ev)
 
416
{
 
417
        /* ignore double/triple clicks */
 
418
 
 
419
        if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
 
420
                return true;
 
421
        }
 
422
 
 
423
        multiple_solo_change = false;
 
424
 
 
425
        if (!_i_am_the_modifier) {
 
426
 
 
427
                if (Keyboard::is_context_menu_event (ev)) {
 
428
 
 
429
                        if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
 
430
                            ! (solo_safe_led && solo_safe_led->is_visible())) {
 
431
 
 
432
                                if (solo_menu == 0) {
 
433
                                        build_solo_menu ();
 
434
                                }
 
435
 
 
436
                                solo_menu->popup (1, ev->time);
 
437
                        }
 
438
 
 
439
                } else {
 
440
 
 
441
                        if (Keyboard::is_button2_event (ev)) {
 
442
 
 
443
                                // Primary-button2 click is the midi binding click
 
444
                                // button2-click is "momentary"
 
445
 
 
446
                                if (solo_button->on_button_press_event (ev)) {
 
447
                                        return true;
 
448
                                }
 
449
 
 
450
                                _solo_release = new SoloMuteRelease (_route->self_soloed());
 
451
                        }
 
452
 
 
453
                        if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
 
454
 
 
455
                                if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
456
 
 
457
                                        /* Primary-Tertiary-click applies change to all routes */
 
458
 
 
459
                                        if (_solo_release) {
 
460
                                                _solo_release->routes = _session->get_routes ();
 
461
                                        }
 
462
 
 
463
                                        if (Config->get_solo_control_is_listen_control()) {
 
464
                                                _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
 
465
                                        } else {
 
466
                                                _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, true);
 
467
                                        }
 
468
 
 
469
                                } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
 
470
 
 
471
                                        // Primary-Secondary-click: exclusively solo this track
 
472
 
 
473
                                        if (_solo_release) {
 
474
                                                _solo_release->exclusive = true;
 
475
 
 
476
                                                boost::shared_ptr<RouteList> routes = _session->get_routes();
 
477
 
 
478
                                                for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
 
479
                                                        if ((*i)->soloed ()) {
 
480
                                                                _solo_release->routes_on->push_back (*i);
 
481
                                                        } else {
 
482
                                                                _solo_release->routes_off->push_back (*i);
 
483
                                                        }
 
484
                                                }
 
485
                                        }
 
486
 
 
487
                                        if (Config->get_solo_control_is_listen_control()) {
 
488
                                                /* ??? we need a just_one_listen() method */
 
489
                                        } else {
 
490
                                                _session->set_just_one_solo (_route, true);
 
491
                                        }
 
492
 
 
493
                                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
 
494
 
 
495
                                        // shift-click: toggle solo isolated status
 
496
 
 
497
                                        _route->set_solo_isolated (!_route->solo_isolated(), this);
 
498
                                        delete _solo_release;
 
499
                                        _solo_release = 0;
 
500
 
 
501
                                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
502
 
 
503
                                        /* Primary-button1: solo mix group.
 
504
                                           NOTE: Primary-button2 is MIDI learn.
 
505
                                        */
 
506
 
 
507
                                        /* Primary-button1 applies change to the mix group even if it is not active
 
508
                                           NOTE: Primary-button2 is MIDI learn.
 
509
                                        */
 
510
 
 
511
                                        boost::shared_ptr<RouteList> rl;
 
512
 
 
513
                                        if (ev->button == 1) { 
 
514
 
 
515
                                                if (_route->route_group()) {
 
516
                                                        
 
517
                                                        rl = _route->route_group()->route_list();
 
518
                                                        
 
519
                                                        if (_solo_release) {
 
520
                                                                _solo_release->routes = rl;
 
521
                                                        }
 
522
                                                } else {
 
523
                                                        rl.reset (new RouteList);
 
524
                                                        rl->push_back (_route);
 
525
                                                }
 
526
 
 
527
                                                if (Config->get_solo_control_is_listen_control()) {
 
528
                                                        _session->set_listen (rl, !_route->listening_via_monitor(),  Session::rt_cleanup, true);
 
529
                                                } else {
 
530
                                                        _session->set_solo (rl, !_route->self_soloed(),  Session::rt_cleanup, true);
 
531
                                                }
 
532
                                        }
 
533
 
 
534
                                } else {
 
535
 
 
536
                                        /* click: solo this route */
 
537
 
 
538
                                        boost::shared_ptr<RouteList> rl (new RouteList);
 
539
                                        rl->push_back (route());
 
540
 
 
541
                                        if (_solo_release) {
 
542
                                                _solo_release->routes = rl;
 
543
                                        }
 
544
 
 
545
                                        if (Config->get_solo_control_is_listen_control()) {
 
546
                                                _session->set_listen (rl, !_route->listening_via_monitor());
 
547
                                        } else {
 
548
                                                _session->set_solo (rl, !_route->self_soloed());
 
549
                                        }
 
550
                                }
 
551
                        }
 
552
                }
 
553
        }
 
554
 
 
555
        return true;
 
556
}
 
557
 
 
558
bool
 
559
RouteUI::solo_release (GdkEventButton*)
 
560
{
 
561
        if (!_i_am_the_modifier) {
 
562
 
 
563
                if (_solo_release) {
 
564
 
 
565
                        if (_solo_release->exclusive) {
 
566
 
 
567
                        } else {
 
568
                                if (Config->get_solo_control_is_listen_control()) {
 
569
                                        _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
 
570
                                } else {
 
571
                                        _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
 
572
                                }
 
573
                        }
 
574
 
 
575
                        delete _solo_release;
 
576
                        _solo_release = 0;
 
577
                }
 
578
        }
 
579
 
 
580
        return true;
 
581
}
 
582
 
 
583
bool
 
584
RouteUI::rec_enable_press(GdkEventButton* ev)
 
585
{
 
586
        if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
 
587
                return true;
 
588
        }
 
589
 
 
590
        if (!_session->engine().connected()) {
 
591
                MessageDialog msg (_("Not connected to JACK - cannot engage record"));
 
592
                msg.run ();
 
593
                return true;
 
594
        }
 
595
 
 
596
        if (is_midi_track()) {
 
597
 
 
598
                /* rec-enable button exits from step editing */
 
599
 
 
600
                if (midi_track()->step_editing()) {
 
601
                        midi_track()->set_step_editing (false);
 
602
                        return true;
 
603
                }
 
604
        }
 
605
 
 
606
        if (!_i_am_the_modifier && is_track() && rec_enable_button) {
 
607
 
 
608
                if (Keyboard::is_button2_event (ev)) {
 
609
 
 
610
                        // do nothing on midi sigc::bind event
 
611
                        return rec_enable_button->on_button_press_event (ev);
 
612
 
 
613
                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
614
 
 
615
                        _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
 
616
 
 
617
                } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
618
 
 
619
                        /* Primary-button1 applies change to the route group (even if it is not active)
 
620
                           NOTE: Primary-button2 is MIDI learn.
 
621
                        */
 
622
 
 
623
                        if (ev->button == 1) {
 
624
 
 
625
                                boost::shared_ptr<RouteList> rl;
 
626
                                
 
627
                                if (_route->route_group()) {
 
628
                                        
 
629
                                        rl = _route->route_group()->route_list();
 
630
                                        
 
631
                                } else {
 
632
                                        rl.reset (new RouteList);
 
633
                                        rl->push_back (_route);
 
634
                                }
 
635
                                
 
636
                                _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
 
637
                        }
 
638
 
 
639
                } else if (Keyboard::is_context_menu_event (ev)) {
 
640
 
 
641
                        /* do this on release */
 
642
 
 
643
                } else {
 
644
 
 
645
                        boost::shared_ptr<RouteList> rl (new RouteList);
 
646
                        rl->push_back (route());
 
647
                        _session->set_record_enabled (rl, !rec_enable_button->active_state());
 
648
                }
 
649
        }
 
650
 
 
651
        return true;
 
652
}
 
653
 
 
654
void
 
655
RouteUI::monitoring_changed ()
 
656
{
 
657
        update_monitoring_display ();
 
658
}
 
659
 
 
660
void
 
661
RouteUI::update_monitoring_display ()
 
662
{
 
663
        if (!_route) {
 
664
                return;
 
665
        }
 
666
 
 
667
        boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
668
 
 
669
        if (!t) {
 
670
                return;
 
671
        }
 
672
 
 
673
        MonitorState ms = t->monitoring_state();
 
674
 
 
675
        if (t->monitoring_choice() & MonitorInput) {
 
676
                monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
 
677
        } else {
 
678
                if (ms & MonitoringInput) {
 
679
                        monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
 
680
                } else {
 
681
                        monitor_input_button->unset_active_state ();
 
682
                }
 
683
        }
 
684
 
 
685
        if (t->monitoring_choice() & MonitorDisk) {
 
686
                monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
 
687
        } else {
 
688
                if (ms & MonitoringDisk) {
 
689
                        monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
 
690
                } else {
 
691
                        monitor_disk_button->unset_active_state ();
 
692
                }
 
693
        }
 
694
}
 
695
 
 
696
bool
 
697
RouteUI::monitor_input_press(GdkEventButton*)
 
698
{
 
699
        return true;
 
700
}
 
701
 
 
702
bool
 
703
RouteUI::monitor_input_release(GdkEventButton* ev)
 
704
{
 
705
        return monitor_release (ev, MonitorInput);
 
706
}
 
707
 
 
708
bool
 
709
RouteUI::monitor_disk_press (GdkEventButton*)
 
710
{
 
711
        return true;
 
712
}
 
713
 
 
714
bool
 
715
RouteUI::monitor_disk_release (GdkEventButton* ev)
 
716
{
 
717
        return monitor_release (ev, MonitorDisk);
 
718
}
 
719
 
 
720
bool
 
721
RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
 
722
{       
 
723
        if (ev->button != 1) {
 
724
                return false;
 
725
        }
 
726
 
 
727
        boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
728
 
 
729
        if (!t) {
 
730
                return true;
 
731
        }
 
732
 
 
733
        MonitorChoice mc;
 
734
        boost::shared_ptr<RouteList> rl;
 
735
        
 
736
        /* XXX for now, monitoring choices are orthogonal. cue monitoring 
 
737
           will follow in 3.X but requires mixing the input and playback (disk)
 
738
           signal together, which requires yet more buffers.
 
739
        */
 
740
 
 
741
        if (t->monitoring_choice() & monitor_choice) {
 
742
                mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
 
743
        } else {
 
744
                /* this line will change when the options are non-orthogonal */
 
745
                // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
 
746
                mc = monitor_choice;
 
747
        }
 
748
 
 
749
        if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {       
 
750
                rl = _session->get_routes ();
 
751
 
 
752
        } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
753
                if (_route->route_group() && _route->route_group()->is_monitoring()) {
 
754
                        rl = _route->route_group()->route_list();
 
755
                } else {
 
756
                        rl.reset (new RouteList);
 
757
                        rl->push_back (route());
 
758
                }
 
759
        } else {
 
760
                rl.reset (new RouteList);
 
761
                rl->push_back (route());
 
762
        }
 
763
 
 
764
        _session->set_monitoring (rl, mc, Session::rt_cleanup, true);           
 
765
 
 
766
        return true;
 
767
}
 
768
 
 
769
void
 
770
RouteUI::build_record_menu ()
 
771
{
 
772
        if (record_menu) {
 
773
                return;
 
774
        }
 
775
 
 
776
        /* no rec-button context menu for non-MIDI tracks
 
777
         */
 
778
 
 
779
        if (is_midi_track()) {
 
780
                record_menu = new Menu;
 
781
                record_menu->set_name ("ArdourContextMenu");
 
782
 
 
783
                using namespace Menu_Helpers;
 
784
                MenuList& items = record_menu->items();
 
785
 
 
786
                items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
 
787
                step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
 
788
 
 
789
                if (_route->record_enabled()) {
 
790
                        step_edit_item->set_sensitive (false);
 
791
                }
 
792
 
 
793
                step_edit_item->set_active (midi_track()->step_editing());
 
794
        }
 
795
}
 
796
 
 
797
void
 
798
RouteUI::toggle_step_edit ()
 
799
{
 
800
        if (!is_midi_track() || _route->record_enabled()) {
 
801
                return;
 
802
        }
 
803
 
 
804
        midi_track()->set_step_editing (step_edit_item->get_active());
 
805
}
 
806
 
 
807
void
 
808
RouteUI::step_edit_changed (bool yn)
 
809
{
 
810
        if (yn) {
 
811
                if (rec_enable_button) {
 
812
                        rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
 
813
                }
 
814
 
 
815
                start_step_editing ();
 
816
 
 
817
                if (step_edit_item) {
 
818
                        step_edit_item->set_active (true);
 
819
                }
 
820
 
 
821
        } else {
 
822
 
 
823
                if (rec_enable_button) {
 
824
                        rec_enable_button->unset_active_state ();
 
825
                }
 
826
 
 
827
                stop_step_editing ();
 
828
 
 
829
                if (step_edit_item) {
 
830
                        step_edit_item->set_active (false);
 
831
                }
 
832
        }
 
833
}
 
834
 
 
835
bool
 
836
RouteUI::rec_enable_release (GdkEventButton* ev)
 
837
{
 
838
        if (Keyboard::is_context_menu_event (ev)) {
 
839
                build_record_menu ();
 
840
                if (record_menu) {
 
841
                        record_menu->popup (1, ev->time);
 
842
                }
 
843
                return true;
 
844
        }
 
845
 
 
846
        return true;
 
847
}
 
848
 
 
849
void
 
850
RouteUI::build_sends_menu ()
 
851
{
 
852
        using namespace Menu_Helpers;
 
853
 
 
854
        sends_menu = new Menu;
 
855
        sends_menu->set_name ("ArdourContextMenu");
 
856
        MenuList& items = sends_menu->items();
 
857
 
 
858
        items.push_back (
 
859
                MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
 
860
                );
 
861
 
 
862
        items.push_back (
 
863
                MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
 
864
                );
 
865
 
 
866
        items.push_back (
 
867
                MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
 
868
                );
 
869
 
 
870
        items.push_back (
 
871
                MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
 
872
                );
 
873
 
 
874
        items.push_back (
 
875
                MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
 
876
                );
 
877
 
 
878
        items.push_back (
 
879
                MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
 
880
 
 
881
        items.push_back (
 
882
                MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
 
883
                );
 
884
 
 
885
        items.push_back (
 
886
                MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
 
887
                );
 
888
 
 
889
        items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
 
890
        items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
 
891
        items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
 
892
 
 
893
}
 
894
 
 
895
void
 
896
RouteUI::create_sends (Placement p, bool include_buses)
 
897
{
 
898
        _session->globally_add_internal_sends (_route, p, include_buses);
 
899
}
 
900
 
 
901
void
 
902
RouteUI::create_selected_sends (Placement p, bool include_buses)
 
903
{
 
904
        boost::shared_ptr<RouteList> rlist (new RouteList);
 
905
        TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
 
906
 
 
907
        for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
 
908
                RouteTimeAxisView* rtv;
 
909
                RouteUI* rui;
 
910
                if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
 
911
                        if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
 
912
                                if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
 
913
                                        rlist->push_back (rui->route());
 
914
                                }
 
915
                        }
 
916
                }
 
917
        }
 
918
 
 
919
        _session->add_internal_sends (_route, p, rlist);
 
920
}
 
921
 
 
922
void
 
923
RouteUI::set_sends_gain_from_track ()
 
924
{
 
925
        _session->globally_set_send_gains_from_track (_route);
 
926
}
 
927
 
 
928
void
 
929
RouteUI::set_sends_gain_to_zero ()
 
930
{
 
931
        _session->globally_set_send_gains_to_zero (_route);
 
932
}
 
933
 
 
934
void
 
935
RouteUI::set_sends_gain_to_unity ()
 
936
{
 
937
        _session->globally_set_send_gains_to_unity (_route);
 
938
}
 
939
 
 
940
bool
 
941
RouteUI::show_sends_press(GdkEventButton* ev)
 
942
{
 
943
        if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
 
944
                return true;
 
945
        }
 
946
 
 
947
        if (!_i_am_the_modifier && !is_track() && show_sends_button) {
 
948
 
 
949
                if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
 
950
 
 
951
                        // do nothing on midi sigc::bind event
 
952
                        return false;
 
953
 
 
954
                } else if (Keyboard::is_context_menu_event (ev)) {
 
955
 
 
956
                        if (sends_menu == 0) {
 
957
                                build_sends_menu ();
 
958
                        }
 
959
 
 
960
                        sends_menu->popup (0, ev->time);
 
961
 
 
962
                } else {
 
963
 
 
964
                        boost::shared_ptr<Route> s = _showing_sends_to.lock ();
 
965
 
 
966
                        if (s == _route) {
 
967
                                set_showing_sends_to (boost::shared_ptr<Route> ());
 
968
                        } else {
 
969
                                set_showing_sends_to (_route);
 
970
                        }
 
971
                }
 
972
        }
 
973
 
 
974
        return true;
 
975
}
 
976
 
 
977
bool
 
978
RouteUI::show_sends_release (GdkEventButton*)
 
979
{
 
980
        return true;
 
981
}
 
982
 
 
983
void
 
984
RouteUI::send_blink (bool onoff)
 
985
{
 
986
        if (!show_sends_button) {
 
987
                return;
 
988
        }
 
989
 
 
990
        if (onoff) {
 
991
                show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
 
992
        } else {
 
993
                show_sends_button->unset_active_state ();
 
994
        }
 
995
}
 
996
 
 
997
Gtkmm2ext::ActiveState
 
998
RouteUI::solo_active_state (boost::shared_ptr<Route> r)
 
999
{
 
1000
        if (r->is_master() || r->is_monitor()) {
 
1001
                return Gtkmm2ext::Off;
 
1002
        }
 
1003
 
 
1004
        if (Config->get_solo_control_is_listen_control()) {
 
1005
 
 
1006
                if (r->listening_via_monitor()) {
 
1007
                        return Gtkmm2ext::ExplicitActive;
 
1008
                } else {
 
1009
                        return Gtkmm2ext::Off;
 
1010
                }
 
1011
 
 
1012
        }
 
1013
 
 
1014
        if (r->soloed()) {
 
1015
                if (!r->self_soloed()) {
 
1016
                        return Gtkmm2ext::ImplicitActive;
 
1017
                } else {
 
1018
                        return Gtkmm2ext::ExplicitActive;
 
1019
                }
 
1020
        } else {
 
1021
                return Gtkmm2ext::Off;
 
1022
        }
 
1023
}
 
1024
 
 
1025
Gtkmm2ext::ActiveState
 
1026
RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
 
1027
{
 
1028
        if (r->is_master() || r->is_monitor()) {
 
1029
                return Gtkmm2ext::Off;
 
1030
        }
 
1031
 
 
1032
        if (r->solo_isolated()) {
 
1033
                return Gtkmm2ext::ExplicitActive;
 
1034
        } else {
 
1035
                return Gtkmm2ext::Off;
 
1036
        }
 
1037
}
 
1038
 
 
1039
Gtkmm2ext::ActiveState
 
1040
RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
 
1041
{
 
1042
        if (r->is_master() || r->is_monitor()) {
 
1043
                return Gtkmm2ext::Off;
 
1044
        }
 
1045
 
 
1046
        if (r->solo_safe()) {
 
1047
                return Gtkmm2ext::ExplicitActive;
 
1048
        } else {
 
1049
                return Gtkmm2ext::Off;
 
1050
        }
 
1051
}
 
1052
 
 
1053
void
 
1054
RouteUI::update_solo_display ()
 
1055
{
 
1056
        bool yn = _route->solo_safe ();
 
1057
 
 
1058
        if (solo_safe_check && solo_safe_check->get_active() != yn) {
 
1059
                solo_safe_check->set_active (yn);
 
1060
        }
 
1061
 
 
1062
        yn = _route->solo_isolated ();
 
1063
 
 
1064
        if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
 
1065
                solo_isolated_check->set_active (yn);
 
1066
        }
 
1067
 
 
1068
        set_button_names ();
 
1069
 
 
1070
        if (solo_isolated_led) {
 
1071
                if (_route->solo_isolated()) {
 
1072
                        solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
 
1073
                } else {
 
1074
                        solo_isolated_led->unset_active_state ();
 
1075
                }
 
1076
        }
 
1077
 
 
1078
        if (solo_safe_led) {
 
1079
                if (_route->solo_safe()) {
 
1080
                        solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
 
1081
                } else {
 
1082
                        solo_safe_led->unset_active_state ();
 
1083
                }
 
1084
        }
 
1085
 
 
1086
        solo_button->set_active_state (solo_active_state (_route));
 
1087
 
 
1088
        /* some changes to solo status can affect mute display, so catch up
 
1089
         */
 
1090
 
 
1091
        update_mute_display ();
 
1092
}
 
1093
 
 
1094
void
 
1095
RouteUI::solo_changed_so_update_mute ()
 
1096
{
 
1097
        update_mute_display ();
 
1098
}
 
1099
 
 
1100
void
 
1101
RouteUI::mute_changed(void* /*src*/)
 
1102
{
 
1103
        update_mute_display ();
 
1104
}
 
1105
 
 
1106
ActiveState
 
1107
RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
 
1108
{
 
1109
        if (r->is_monitor()) {
 
1110
                return ActiveState(0);
 
1111
        }
 
1112
 
 
1113
 
 
1114
        if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
 
1115
 
 
1116
                if (r->muted ()) {
 
1117
                        /* full mute */
 
1118
                        return Gtkmm2ext::ExplicitActive;
 
1119
                } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
 
1120
                        /* master is NEVER muted by others */
 
1121
                        return Gtkmm2ext::ImplicitActive;
 
1122
                } else {
 
1123
                        /* no mute at all */
 
1124
                        return Gtkmm2ext::Off;
 
1125
                }
 
1126
 
 
1127
        } else {
 
1128
 
 
1129
                if (r->muted()) {
 
1130
                        /* full mute */
 
1131
                        return Gtkmm2ext::ExplicitActive;
 
1132
                } else {
 
1133
                        /* no mute at all */
 
1134
                        return Gtkmm2ext::Off;
 
1135
                }
 
1136
        }
 
1137
 
 
1138
        return ActiveState(0);
 
1139
}
 
1140
 
 
1141
void
 
1142
RouteUI::update_mute_display ()
 
1143
{
 
1144
        if (!_route) {
 
1145
                return;
 
1146
        }
 
1147
 
 
1148
        mute_button->set_active_state (mute_active_state (_session, _route));
 
1149
}
 
1150
 
 
1151
void
 
1152
RouteUI::route_rec_enable_changed ()
 
1153
{
 
1154
        update_rec_display ();
 
1155
        update_monitoring_display ();
 
1156
}
 
1157
 
 
1158
void
 
1159
RouteUI::session_rec_enable_changed ()
 
1160
{
 
1161
        update_rec_display ();
 
1162
        update_monitoring_display ();
 
1163
}
 
1164
 
 
1165
void
 
1166
RouteUI::update_rec_display ()
 
1167
{
 
1168
        if (!rec_enable_button || !_route) {
 
1169
                return;
 
1170
        }
 
1171
 
 
1172
        if (_route->record_enabled()) {
 
1173
                switch (_session->record_status ()) {
 
1174
                case Session::Recording:
 
1175
                        rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
 
1176
                        break;
 
1177
 
 
1178
                case Session::Disabled:
 
1179
                case Session::Enabled:
 
1180
                        rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
 
1181
                        break;
 
1182
 
 
1183
                }
 
1184
 
 
1185
                if (step_edit_item) {
 
1186
                        step_edit_item->set_sensitive (false);
 
1187
                }
 
1188
 
 
1189
        } else {
 
1190
                rec_enable_button->unset_active_state ();
 
1191
 
 
1192
                if (step_edit_item) {
 
1193
                        step_edit_item->set_sensitive (true);
 
1194
                }
 
1195
        }
 
1196
 
 
1197
 
 
1198
        check_rec_enable_sensitivity ();
 
1199
}
 
1200
 
 
1201
void
 
1202
RouteUI::build_solo_menu (void)
 
1203
{
 
1204
        using namespace Menu_Helpers;
 
1205
 
 
1206
        solo_menu = new Menu;
 
1207
        solo_menu->set_name ("ArdourContextMenu");
 
1208
        MenuList& items = solo_menu->items();
 
1209
        CheckMenuItem* check;
 
1210
 
 
1211
        check = new CheckMenuItem(_("Solo Isolate"));
 
1212
        check->set_active (_route->solo_isolated());
 
1213
        check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
 
1214
        items.push_back (CheckMenuElem(*check));
 
1215
        solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
 
1216
        check->show_all();
 
1217
 
 
1218
        check = new CheckMenuItem(_("Solo Safe"));
 
1219
        check->set_active (_route->solo_safe());
 
1220
        check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
 
1221
        items.push_back (CheckMenuElem(*check));
 
1222
        solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
 
1223
        check->show_all();
 
1224
 
 
1225
        //items.push_back (SeparatorElem());
 
1226
        // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
 
1227
 
 
1228
}
 
1229
 
 
1230
void
 
1231
RouteUI::build_mute_menu(void)
 
1232
{
 
1233
        using namespace Menu_Helpers;
 
1234
 
 
1235
        mute_menu = new Menu;
 
1236
        mute_menu->set_name ("ArdourContextMenu");
 
1237
 
 
1238
        MenuList& items = mute_menu->items();
 
1239
 
 
1240
        pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
 
1241
        init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
 
1242
        pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
 
1243
        items.push_back (CheckMenuElem(*pre_fader_mute_check));
 
1244
        pre_fader_mute_check->show_all();
 
1245
 
 
1246
        post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
 
1247
        init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
 
1248
        post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
 
1249
        items.push_back (CheckMenuElem(*post_fader_mute_check));
 
1250
        post_fader_mute_check->show_all();
 
1251
 
 
1252
        listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
 
1253
        init_mute_menu(MuteMaster::Listen, listen_mute_check);
 
1254
        listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
 
1255
        items.push_back (CheckMenuElem(*listen_mute_check));
 
1256
        listen_mute_check->show_all();
 
1257
 
 
1258
        main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
 
1259
        init_mute_menu(MuteMaster::Main, main_mute_check);
 
1260
        main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
 
1261
        items.push_back (CheckMenuElem(*main_mute_check));
 
1262
        main_mute_check->show_all();
 
1263
 
 
1264
        //items.push_back (SeparatorElem());
 
1265
        // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
 
1266
 
 
1267
        _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
 
1268
}
 
1269
 
 
1270
void
 
1271
RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
 
1272
{
 
1273
        check->set_active (_route->mute_points() & mp);
 
1274
}
 
1275
 
 
1276
void
 
1277
RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
 
1278
{
 
1279
        if (check->get_active()) {
 
1280
                _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
 
1281
        } else {
 
1282
                _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
 
1283
        }
 
1284
}
 
1285
 
 
1286
void
 
1287
RouteUI::muting_change ()
 
1288
{
 
1289
        ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
 
1290
 
 
1291
        bool yn;
 
1292
        MuteMaster::MutePoint current = _route->mute_points ();
 
1293
 
 
1294
        yn = (current & MuteMaster::PreFader);
 
1295
 
 
1296
        if (pre_fader_mute_check->get_active() != yn) {
 
1297
                pre_fader_mute_check->set_active (yn);
 
1298
        }
 
1299
 
 
1300
        yn = (current & MuteMaster::PostFader);
 
1301
 
 
1302
        if (post_fader_mute_check->get_active() != yn) {
 
1303
                post_fader_mute_check->set_active (yn);
 
1304
        }
 
1305
 
 
1306
        yn = (current & MuteMaster::Listen);
 
1307
 
 
1308
        if (listen_mute_check->get_active() != yn) {
 
1309
                listen_mute_check->set_active (yn);
 
1310
        }
 
1311
 
 
1312
        yn = (current & MuteMaster::Main);
 
1313
 
 
1314
        if (main_mute_check->get_active() != yn) {
 
1315
                main_mute_check->set_active (yn);
 
1316
        }
 
1317
}
 
1318
 
 
1319
bool
 
1320
RouteUI::solo_isolate_button_release (GdkEventButton* ev)
 
1321
{
 
1322
        if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
 
1323
                return true;
 
1324
        }
 
1325
 
 
1326
        bool view = solo_isolated_led->active_state();
 
1327
        bool model = _route->solo_isolated();
 
1328
 
 
1329
        /* called BEFORE the view has changed */
 
1330
 
 
1331
        if (ev->button == 1) {
 
1332
                if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
 
1333
 
 
1334
                        if (model) {
 
1335
                                /* disable isolate for all routes */
 
1336
                                _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
 
1337
                        }
 
1338
 
 
1339
                } else {
 
1340
                        if (model == view) {
 
1341
 
 
1342
                                /* flip just this route */
 
1343
 
 
1344
                                boost::shared_ptr<RouteList> rl (new RouteList);
 
1345
                                rl->push_back (_route);
 
1346
                                _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
 
1347
                        }
 
1348
                }
 
1349
        }
 
1350
 
 
1351
        return true;
 
1352
}
 
1353
 
 
1354
bool
 
1355
RouteUI::solo_safe_button_release (GdkEventButton* ev)
 
1356
{
 
1357
        if (ev->button == 1) {
 
1358
                _route->set_solo_safe (!solo_safe_led->active_state(), this);
 
1359
                return true;
 
1360
        }
 
1361
        return false;
 
1362
}
 
1363
 
 
1364
void
 
1365
RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
 
1366
{
 
1367
        bool view = check->get_active();
 
1368
        bool model = _route->solo_isolated();
 
1369
 
 
1370
        /* called AFTER the view has changed */
 
1371
 
 
1372
        if (model != view) {
 
1373
                _route->set_solo_isolated (view, this);
 
1374
        }
 
1375
}
 
1376
 
 
1377
void
 
1378
RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
 
1379
{
 
1380
        _route->set_solo_safe (check->get_active(), this);
 
1381
}
 
1382
 
 
1383
/** Ask the user to choose a colour, and then set all selected tracks
 
1384
 *  to that colour.
 
1385
 */
 
1386
void
 
1387
RouteUI::choose_color ()
 
1388
{
 
1389
        bool picked;
 
1390
        Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
 
1391
 
 
1392
        if (picked) {
 
1393
                ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
 
1394
                        boost::bind (&RouteUI::set_color, _1, color)
 
1395
                        );
 
1396
        }
 
1397
}
 
1398
 
 
1399
/** Set the route's own color.  This may not be used for display if
 
1400
 *  the route is in a group which shares its color with its routes.
 
1401
 */
 
1402
void
 
1403
RouteUI::set_color (const Gdk::Color & c)
 
1404
{
 
1405
        /* leave _color alone in the group case so that tracks can retain their
 
1406
         * own pre-group colors.
 
1407
         */
 
1408
 
 
1409
        char buf[64];
 
1410
        _color = c;
 
1411
        snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
 
1412
        
 
1413
        /* note: we use the route state ID here so that color is the same for both
 
1414
           the time axis view and the mixer strip
 
1415
        */
 
1416
        
 
1417
        gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
 
1418
        _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
 
1419
}
 
1420
 
 
1421
/** @return GUI state ID for things that are common to the route in all its representations */
 
1422
string
 
1423
RouteUI::route_state_id () const
 
1424
{
 
1425
        return string_compose (X_("route %1"), _route->id().to_s());
 
1426
}
 
1427
 
 
1428
int
 
1429
RouteUI::set_color_from_route ()
 
1430
{
 
1431
        const string str = gui_object_state().get_string (route_state_id(), X_("color"));
 
1432
 
 
1433
        if (str.empty()) {
 
1434
                return 1;
 
1435
        }
 
1436
 
 
1437
        int r, g, b;
 
1438
 
 
1439
        sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
 
1440
 
 
1441
        _color.set_red (r);
 
1442
        _color.set_green (g);
 
1443
        _color.set_blue (b);
 
1444
 
 
1445
        return 0;
 
1446
}
 
1447
 
 
1448
void
 
1449
RouteUI::remove_this_route (bool apply_to_selection)
 
1450
{
 
1451
        if (apply_to_selection) {
 
1452
                ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
 
1453
        } else {
 
1454
                if ((route()->is_master() || route()->is_monitor()) &&
 
1455
                    !Config->get_allow_special_bus_removal()) {
 
1456
                        MessageDialog msg (_("That would be bad news ...."),
 
1457
                                           false,
 
1458
                                           Gtk::MESSAGE_INFO,
 
1459
                                   Gtk::BUTTONS_OK);
 
1460
                        msg.set_secondary_text (string_compose (_(
 
1461
"Removing the master or monitor bus is such a bad idea\n\
 
1462
that %1 is not going to allow it.\n\
 
1463
\n\
 
1464
If you really want to do this sort of thing\n\
 
1465
edit your ardour.rc file to set the\n\
 
1466
\"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
 
1467
 
 
1468
                        msg.present ();
 
1469
                        msg.run ();
 
1470
                        return;
 
1471
                }
 
1472
 
 
1473
                vector<string> choices;
 
1474
                string prompt;
 
1475
 
 
1476
                if (is_track()) {
 
1477
                        prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
 
1478
                } else {
 
1479
                        prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
 
1480
                }
 
1481
 
 
1482
                choices.push_back (_("No, do nothing."));
 
1483
                choices.push_back (_("Yes, remove it."));
 
1484
 
 
1485
                string title;
 
1486
                if (is_track()) {
 
1487
                        title = _("Remove track");
 
1488
                } else {
 
1489
                        title = _("Remove bus");
 
1490
                }
 
1491
 
 
1492
                Choice prompter (title, prompt, choices);
 
1493
 
 
1494
                if (prompter.run () == 1) {
 
1495
                        Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
 
1496
                }
 
1497
        }
 
1498
}
 
1499
 
 
1500
gint
 
1501
RouteUI::idle_remove_this_route (RouteUI *rui)
 
1502
{
 
1503
        rui->_session->remove_route (rui->route());
 
1504
        return false;
 
1505
}
 
1506
 
 
1507
/** @return true if this name should be used for the route, otherwise false */
 
1508
bool
 
1509
RouteUI::verify_new_route_name (const std::string& name)
 
1510
{
 
1511
        if (name.find (':') == string::npos) {
 
1512
                return true;
 
1513
        }
 
1514
        
 
1515
        MessageDialog colon_msg (
 
1516
                _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
 
1517
                false, MESSAGE_QUESTION, BUTTONS_NONE
 
1518
                );
 
1519
        
 
1520
        colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
 
1521
        colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
 
1522
 
 
1523
        return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
 
1524
}
 
1525
 
 
1526
void
 
1527
RouteUI::route_rename ()
 
1528
{
 
1529
        ArdourPrompter name_prompter (true);
 
1530
        string result;
 
1531
        bool done = false;
 
1532
 
 
1533
        if (is_track()) {
 
1534
                name_prompter.set_title (_("Rename Track"));
 
1535
        } else {
 
1536
                name_prompter.set_title (_("Rename Bus"));
 
1537
        }
 
1538
        name_prompter.set_prompt (_("New name:"));
 
1539
        name_prompter.set_initial_text (_route->name());
 
1540
        name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
 
1541
        name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
 
1542
        name_prompter.show_all ();
 
1543
 
 
1544
        while (!done) {
 
1545
                switch (name_prompter.run ()) {
 
1546
                case Gtk::RESPONSE_ACCEPT:
 
1547
                        name_prompter.get_result (result);
 
1548
                        name_prompter.hide ();
 
1549
                        if (result.length()) {
 
1550
                                if (verify_new_route_name (result)) {
 
1551
                                        _route->set_name (result);
 
1552
                                        done = true;
 
1553
                                } else {
 
1554
                                        /* back to name prompter */
 
1555
                                }
 
1556
 
 
1557
                        } else {
 
1558
                                /* nothing entered, just get out of here */
 
1559
                                done = true;
 
1560
                        }
 
1561
                        break;
 
1562
                default:
 
1563
                        done = true;
 
1564
                        break;
 
1565
                }
 
1566
        }
 
1567
 
 
1568
        return;
 
1569
 
 
1570
}
 
1571
 
 
1572
void
 
1573
RouteUI::property_changed (const PropertyChange& what_changed)
 
1574
{
 
1575
        if (what_changed.contains (ARDOUR::Properties::name)) {
 
1576
                name_label.set_text (_route->name());
 
1577
        }
 
1578
}
 
1579
 
 
1580
void
 
1581
RouteUI::set_route_active (bool a, bool apply_to_selection)
 
1582
{
 
1583
        if (apply_to_selection) {
 
1584
                ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
 
1585
        } else {
 
1586
                _route->set_active (a, this);
 
1587
        }
 
1588
}
 
1589
 
 
1590
void
 
1591
RouteUI::toggle_denormal_protection ()
 
1592
{
 
1593
        if (denormal_menu_item) {
 
1594
 
 
1595
                bool x;
 
1596
 
 
1597
                ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
 
1598
 
 
1599
                if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
 
1600
                        _route->set_denormal_protection (x);
 
1601
                }
 
1602
        }
 
1603
}
 
1604
 
 
1605
void
 
1606
RouteUI::denormal_protection_changed ()
 
1607
{
 
1608
        if (denormal_menu_item) {
 
1609
                denormal_menu_item->set_active (_route->denormal_protection());
 
1610
        }
 
1611
}
 
1612
 
 
1613
void
 
1614
RouteUI::disconnect_input ()
 
1615
{
 
1616
        _route->input()->disconnect (this);
 
1617
}
 
1618
 
 
1619
void
 
1620
RouteUI::disconnect_output ()
 
1621
{
 
1622
        _route->output()->disconnect (this);
 
1623
}
 
1624
 
 
1625
bool
 
1626
RouteUI::is_track () const
 
1627
{
 
1628
        return boost::dynamic_pointer_cast<Track>(_route) != 0;
 
1629
}
 
1630
 
 
1631
boost::shared_ptr<Track>
 
1632
RouteUI::track() const
 
1633
{
 
1634
        return boost::dynamic_pointer_cast<Track>(_route);
 
1635
}
 
1636
 
 
1637
bool
 
1638
RouteUI::is_audio_track () const
 
1639
{
 
1640
        return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
 
1641
}
 
1642
 
 
1643
boost::shared_ptr<AudioTrack>
 
1644
RouteUI::audio_track() const
 
1645
{
 
1646
        return boost::dynamic_pointer_cast<AudioTrack>(_route);
 
1647
}
 
1648
 
 
1649
bool
 
1650
RouteUI::is_midi_track () const
 
1651
{
 
1652
        return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
 
1653
}
 
1654
 
 
1655
boost::shared_ptr<MidiTrack>
 
1656
RouteUI::midi_track() const
 
1657
{
 
1658
        return boost::dynamic_pointer_cast<MidiTrack>(_route);
 
1659
}
 
1660
 
 
1661
bool
 
1662
RouteUI::has_audio_outputs () const
 
1663
{
 
1664
        return (_route->n_outputs().n_audio() > 0);
 
1665
}
 
1666
 
 
1667
string
 
1668
RouteUI::name() const
 
1669
{
 
1670
        return _route->name();
 
1671
}
 
1672
 
 
1673
void
 
1674
RouteUI::map_frozen ()
 
1675
{
 
1676
        ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
 
1677
 
 
1678
        AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
 
1679
 
 
1680
        if (at) {
 
1681
                switch (at->freeze_state()) {
 
1682
                case AudioTrack::Frozen:
 
1683
                        rec_enable_button->set_sensitive (false);
 
1684
                        break;
 
1685
                default:
 
1686
                        rec_enable_button->set_sensitive (true);
 
1687
                        break;
 
1688
                }
 
1689
        }
 
1690
}
 
1691
 
 
1692
void
 
1693
RouteUI::adjust_latency ()
 
1694
{
 
1695
        LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
 
1696
}
 
1697
 
 
1698
void
 
1699
RouteUI::save_as_template ()
 
1700
{
 
1701
        std::string path;
 
1702
        std::string safe_name;
 
1703
        string name;
 
1704
 
 
1705
        path = ARDOUR::user_route_template_directory ();
 
1706
 
 
1707
        if (g_mkdir_with_parents (path.c_str(), 0755)) {
 
1708
                error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
 
1709
                return;
 
1710
        }
 
1711
 
 
1712
        Prompter p (true); // modal
 
1713
 
 
1714
        p.set_title (_("Save As Template"));
 
1715
        p.set_prompt (_("Template name:"));
 
1716
        p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
 
1717
        switch (p.run()) {
 
1718
        case RESPONSE_ACCEPT:
 
1719
                break;
 
1720
        default:
 
1721
                return;
 
1722
        }
 
1723
 
 
1724
        p.hide ();
 
1725
        p.get_result (name, true);
 
1726
 
 
1727
        safe_name = legalize_for_path (name);
 
1728
        safe_name += template_suffix;
 
1729
 
 
1730
        path = Glib::build_filename (path, safe_name);
 
1731
 
 
1732
        _route->save_as_template (path, name);
 
1733
}
 
1734
 
 
1735
void
 
1736
RouteUI::check_rec_enable_sensitivity ()
 
1737
{
 
1738
        if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
 
1739
                rec_enable_button->set_sensitive (false);
 
1740
        } else {
 
1741
                rec_enable_button->set_sensitive (true);
 
1742
        }
 
1743
 
 
1744
        update_monitoring_display ();
 
1745
}
 
1746
 
 
1747
void
 
1748
RouteUI::parameter_changed (string const & p)
 
1749
{
 
1750
        /* this handles RC and per-session parameter changes */
 
1751
 
 
1752
        if (p == "disable-disarm-during-roll") {
 
1753
                check_rec_enable_sensitivity ();
 
1754
        } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
 
1755
                set_button_names ();
 
1756
        } else if (p == "auto-input") {
 
1757
                update_monitoring_display ();
 
1758
        }
 
1759
}
 
1760
 
 
1761
void
 
1762
RouteUI::step_gain_up ()
 
1763
{
 
1764
        _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
 
1765
}
 
1766
 
 
1767
void
 
1768
RouteUI::page_gain_up ()
 
1769
{
 
1770
        _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
 
1771
}
 
1772
 
 
1773
void
 
1774
RouteUI::step_gain_down ()
 
1775
{
 
1776
        _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
 
1777
}
 
1778
 
 
1779
void
 
1780
RouteUI::page_gain_down ()
 
1781
{
 
1782
        _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
 
1783
}
 
1784
 
 
1785
void
 
1786
RouteUI::open_remote_control_id_dialog ()
 
1787
{
 
1788
        ArdourDialog dialog (_("Remote Control ID"));
 
1789
        SpinButton* spin = 0;
 
1790
 
 
1791
        dialog.get_vbox()->set_border_width (18);
 
1792
 
 
1793
        if (Config->get_remote_model() == UserOrdered) {
 
1794
                uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
 
1795
                
 
1796
                HBox* hbox = manage (new HBox);
 
1797
                hbox->set_spacing (6);
 
1798
                hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
 
1799
                spin = manage (new SpinButton);
 
1800
                spin->set_digits (0);
 
1801
                spin->set_increments (1, 10);
 
1802
                spin->set_range (0, limit);
 
1803
                spin->set_value (_route->remote_control_id());
 
1804
                hbox->pack_start (*spin);
 
1805
                dialog.get_vbox()->pack_start (*hbox);
 
1806
                
 
1807
                dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
 
1808
                dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
 
1809
        } else {
 
1810
                Label* l = manage (new Label());
 
1811
                if (_route->is_master() || _route->is_monitor()) {
 
1812
                        l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
 
1813
                                                         "The remote control ID of %3 cannot be changed."),
 
1814
                                                       Glib::Markup::escape_text (_route->name()),
 
1815
                                                       _route->remote_control_id(),
 
1816
                                                       (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
 
1817
                } else {
 
1818
                        l->set_markup (string_compose (_("The remote control ID of %6 is: %3\n\n\n"
 
1819
                                                         "Remote Control IDs are currently determined by track/bus ordering in %1\n\n"
 
1820
                                                         "%4Use the User Interaction tab of the Preferences window if you want to change this%5"),
 
1821
                                                       (Config->get_remote_model() == MixerOrdered ? _("the mixer") : _("the editor")),
 
1822
                                                       (is_track() ? _("track") : _("bus")),
 
1823
                                                       _route->remote_control_id(),
 
1824
                                                       "<span size=\"small\" style=\"italic\">",
 
1825
                                                       "</span>",
 
1826
                                                       Glib::Markup::escape_text (_route->name())));
 
1827
                }
 
1828
                dialog.get_vbox()->pack_start (*l);
 
1829
                dialog.add_button (Stock::OK, RESPONSE_CANCEL);
 
1830
        }
 
1831
 
 
1832
        dialog.show_all ();
 
1833
        int const r = dialog.run ();
 
1834
 
 
1835
        if (r == RESPONSE_ACCEPT && spin) {
 
1836
                _route->set_remote_control_id (spin->get_value_as_int ());
 
1837
        }
 
1838
}
 
1839
 
 
1840
void
 
1841
RouteUI::setup_invert_buttons ()
 
1842
{
 
1843
        /* remove old invert buttons */
 
1844
        for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
 
1845
                _invert_button_box.remove (**i);
 
1846
        }
 
1847
 
 
1848
        _invert_buttons.clear ();
 
1849
 
 
1850
        if (!_route || !_route->input()) {
 
1851
                return;
 
1852
        }
 
1853
 
 
1854
        uint32_t const N = _route->input()->n_ports().n_audio ();
 
1855
 
 
1856
        uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
 
1857
 
 
1858
        for (uint32_t i = 0; i < to_add; ++i) {
 
1859
                ArdourButton* b = manage (new ArdourButton);
 
1860
                b->set_size_request(20,20);
 
1861
                b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
 
1862
                b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
 
1863
 
 
1864
                b->set_name (X_("invert button"));
 
1865
                if (to_add == 1) {
 
1866
                        if (N > 1) {
 
1867
                                b->set_text (string_compose (X_("Ø (%1)"), N));
 
1868
                        } else {
 
1869
                                b->set_text (X_("Ø"));
 
1870
                        }
 
1871
                } else {
 
1872
                        b->set_text (string_compose (X_("Ø%1"), i + 1));
 
1873
                }
 
1874
 
 
1875
                if (N <= _max_invert_buttons) {
 
1876
                        UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) channel %1 of this track.  Right-click to show menu."), i + 1));
 
1877
                } else {
 
1878
                        UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
 
1879
                }
 
1880
 
 
1881
                _invert_buttons.push_back (b);
 
1882
                _invert_button_box.pack_start (*b);
 
1883
        }
 
1884
 
 
1885
        _invert_button_box.set_spacing (1);
 
1886
        _invert_button_box.show_all ();
 
1887
}
 
1888
 
 
1889
void
 
1890
RouteUI::set_invert_button_state ()
 
1891
{
 
1892
        ++_i_am_the_modifier;
 
1893
 
 
1894
        uint32_t const N = _route->input()->n_ports().n_audio();
 
1895
        if (N > _max_invert_buttons) {
 
1896
 
 
1897
                /* One button for many channels; explicit active if all channels are inverted,
 
1898
                   implicit active if some are, off if none are.
 
1899
                */
 
1900
 
 
1901
                ArdourButton* b = _invert_buttons.front ();
 
1902
                
 
1903
                if (_route->phase_invert().count() == _route->phase_invert().size()) {
 
1904
                        b->set_active_state (Gtkmm2ext::ExplicitActive);
 
1905
                } else if (_route->phase_invert().any()) {
 
1906
                        b->set_active_state (Gtkmm2ext::ImplicitActive);
 
1907
                } else {
 
1908
                        b->set_active_state (Gtkmm2ext::Off);
 
1909
                }
 
1910
 
 
1911
        } else {
 
1912
 
 
1913
                /* One button per channel; just set active */
 
1914
 
 
1915
                int j = 0;
 
1916
                for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
 
1917
                        (*i)->set_active (_route->phase_invert (j));
 
1918
                }
 
1919
                
 
1920
        }
 
1921
 
 
1922
        --_i_am_the_modifier;
 
1923
}
 
1924
 
 
1925
bool
 
1926
RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
 
1927
{
 
1928
        if (ev->button == 1 && i < _invert_buttons.size()) {
 
1929
                uint32_t const N = _route->input()->n_ports().n_audio ();
 
1930
                if (N <= _max_invert_buttons) {
 
1931
                        /* left-click inverts phase so long as we have a button per channel */
 
1932
                        _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
 
1933
                        return true;
 
1934
                }
 
1935
        }
 
1936
        return false;
 
1937
}
 
1938
 
 
1939
 
 
1940
bool
 
1941
RouteUI::invert_press (GdkEventButton* ev)
 
1942
{
 
1943
        using namespace Menu_Helpers;
 
1944
 
 
1945
        uint32_t const N = _route->input()->n_ports().n_audio();
 
1946
        if (N <= _max_invert_buttons && ev->button != 3) {
 
1947
                /* If we have an invert button per channel, we only pop
 
1948
                   up a menu on right-click; left click is handled
 
1949
                   on release.
 
1950
                */
 
1951
                return true;
 
1952
        }
 
1953
        
 
1954
        delete _invert_menu;
 
1955
        _invert_menu = new Menu;
 
1956
        _invert_menu->set_name ("ArdourContextMenu");
 
1957
        MenuList& items = _invert_menu->items ();
 
1958
 
 
1959
        for (uint32_t i = 0; i < N; ++i) {
 
1960
                items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
 
1961
                CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
 
1962
                ++_i_am_the_modifier;
 
1963
                e->set_active (_route->phase_invert (i));
 
1964
                --_i_am_the_modifier;
 
1965
        }
 
1966
 
 
1967
        _invert_menu->popup (0, ev->time);
 
1968
 
 
1969
        return false;
 
1970
}
 
1971
 
 
1972
void
 
1973
RouteUI::invert_menu_toggled (uint32_t c)
 
1974
{
 
1975
        if (_i_am_the_modifier) {
 
1976
                return;
 
1977
        }
 
1978
 
 
1979
        _route->set_phase_invert (c, !_route->phase_invert (c));
 
1980
}
 
1981
 
 
1982
void
 
1983
RouteUI::set_invert_sensitive (bool yn)
 
1984
{
 
1985
        for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
 
1986
                (*b)->set_sensitive (yn);
 
1987
        }
 
1988
}
 
1989
 
 
1990
void
 
1991
RouteUI::request_redraw ()
 
1992
{
 
1993
        if (_route) {
 
1994
                _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
 
1995
        }
 
1996
}
 
1997
 
 
1998
/** The Route's gui_changed signal has been emitted */
 
1999
void
 
2000
RouteUI::route_gui_changed (string what_changed)
 
2001
{
 
2002
        if (what_changed == "color") {
 
2003
                if (set_color_from_route () == 0) {
 
2004
                        route_color_changed ();
 
2005
                }
 
2006
        }
 
2007
}
 
2008
 
 
2009
/** @return the color that this route should use; it maybe its own,
 
2010
    or it maybe that of its route group.
 
2011
*/
 
2012
Gdk::Color
 
2013
RouteUI::color () const
 
2014
{
 
2015
        RouteGroup* g = _route->route_group ();
 
2016
        
 
2017
        if (g && g->is_color()) {
 
2018
                return GroupTabs::group_color (g);
 
2019
        }
 
2020
 
 
2021
        return _color;
 
2022
}
 
2023
 
 
2024
void
 
2025
RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
 
2026
{
 
2027
        _showing_sends_to = send_to;
 
2028
        BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
 
2029
}
 
2030
 
 
2031
void
 
2032
RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
 
2033
{
 
2034
        if (_route == send_to) {
 
2035
                show_sends_button->set_active (true);
 
2036
                send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
 
2037
        } else {
 
2038
                show_sends_button->set_active (false);
 
2039
                send_blink_connection.disconnect ();
 
2040
        }
 
2041
}
 
2042
 
 
2043
RouteGroup*
 
2044
RouteUI::route_group() const
 
2045
{
 
2046
        return _route->route_group();
 
2047
}