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

« back to all changes in this revision

Viewing changes to libs/surfaces/mackie/mackie_control_protocol.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) 2006,2007 John Anderson
 
3
        Copyright (C) 2012 Paul Davis
 
4
 
 
5
        This program is free software; you can redistribute it and/or modify
 
6
        it under the terms of the GNU General Public License as published by
 
7
        the Free Software Foundation; either version 2 of the License, or
 
8
        (at your option) any later version.
 
9
 
 
10
        This program is distributed in the hope that it will be useful,
 
11
        but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
13
        GNU General Public License for more details.
 
14
 
 
15
        You should have received a copy of the GNU General Public License
 
16
        along with this program; if not, write to the Free Software
 
17
        Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
18
*/
 
19
 
 
20
#include <fcntl.h>
 
21
#include <iostream>
 
22
#include <algorithm>
 
23
#include <cmath>
 
24
#include <sstream>
 
25
#include <vector>
 
26
#include <iomanip>
 
27
 
 
28
#include <inttypes.h>
 
29
#include <float.h>
 
30
#include <sys/time.h>
 
31
#include <errno.h>
 
32
#include <poll.h>
 
33
 
 
34
#include <boost/shared_array.hpp>
 
35
 
 
36
#include "midi++/types.h"
 
37
#include "midi++/port.h"
 
38
#include "midi++/ipmidi_port.h"
 
39
#include "pbd/pthread_utils.h"
 
40
#include "pbd/error.h"
 
41
#include "pbd/memento_command.h"
 
42
#include "pbd/convert.h"
 
43
 
 
44
#include "ardour/automation_control.h"
 
45
#include "ardour/dB.h"
 
46
#include "ardour/debug.h"
 
47
#include "ardour/location.h"
 
48
#include "ardour/meter.h"
 
49
#include "ardour/panner.h"
 
50
#include "ardour/panner_shell.h"
 
51
#include "ardour/route.h"
 
52
#include "ardour/session.h"
 
53
#include "ardour/tempo.h"
 
54
#include "ardour/track.h"
 
55
#include "ardour/types.h"
 
56
#include "ardour/audioengine.h"
 
57
 
 
58
#include "mackie_control_protocol.h"
 
59
 
 
60
#include "midi_byte_array.h"
 
61
#include "mackie_control_exception.h"
 
62
#include "device_profile.h"
 
63
#include "surface_port.h"
 
64
#include "surface.h"
 
65
#include "strip.h"
 
66
#include "control_group.h"
 
67
#include "meter.h"
 
68
#include "button.h"
 
69
#include "fader.h"
 
70
#include "pot.h"
 
71
 
 
72
using namespace ARDOUR;
 
73
using namespace std;
 
74
using namespace Mackie;
 
75
using namespace PBD;
 
76
using namespace Glib;
 
77
 
 
78
#include "i18n.h"
 
79
 
 
80
#include "pbd/abstract_ui.cc" // instantiate template
 
81
 
 
82
const int MackieControlProtocol::MODIFIER_OPTION = 0x1;
 
83
const int MackieControlProtocol::MODIFIER_CONTROL = 0x2;
 
84
const int MackieControlProtocol::MODIFIER_SHIFT = 0x4;
 
85
const int MackieControlProtocol::MODIFIER_CMDALT = 0x8;
 
86
 
 
87
MackieControlProtocol* MackieControlProtocol::_instance = 0;
 
88
 
 
89
bool MackieControlProtocol::probe()
 
90
{
 
91
        return true;
 
92
}
 
93
 
 
94
MackieControlProtocol::MackieControlProtocol (Session& session)
 
95
        : ControlProtocol (session, X_("Mackie"))
 
96
        , AbstractUI<MackieControlUIRequest> ("mackie")
 
97
        , _current_initial_bank (0)
 
98
        , _timecode_type (ARDOUR::AnyTime::BBT)
 
99
        , _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
 
100
        , _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
 
101
        , _gui (0)
 
102
        , _zoom_mode (false)
 
103
        , _scrub_mode (false)
 
104
        , _flip_mode (Normal)
 
105
        , _view_mode (Mixer)
 
106
        , _current_selected_track (-1)
 
107
        , _modifier_state (0)
 
108
        , _ipmidi_base (MIDI::IPMIDIPort::lowest_ipmidi_port_default)
 
109
        , needs_ipmidi_restart (false)
 
110
        , _metering_active (true)
 
111
        , _initialized (false)
 
112
{
 
113
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
 
114
 
 
115
        DeviceInfo::reload_device_info ();
 
116
        DeviceProfile::reload_device_profiles ();
 
117
 
 
118
        TrackSelectionChanged.connect (gui_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::gui_track_selection_changed, this, _1, true), this);
 
119
 
 
120
        _instance = this;
 
121
 
 
122
        build_button_map ();
 
123
}
 
124
 
 
125
MackieControlProtocol::~MackieControlProtocol()
 
126
{
 
127
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol init\n");
 
128
        
 
129
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol drop_connections ()\n");
 
130
        drop_connections ();
 
131
 
 
132
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n");
 
133
        tear_down_gui ();
 
134
 
 
135
        _active = false;
 
136
 
 
137
        /* stop event loop */
 
138
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol BaseUI::quit ()\n");
 
139
        BaseUI::quit ();
 
140
 
 
141
        try {
 
142
                DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol close()\n");
 
143
                close();
 
144
        }
 
145
        catch (exception & e) {
 
146
                cout << "~MackieControlProtocol caught " << e.what() << endl;
 
147
        }
 
148
        catch (...) {
 
149
                cout << "~MackieControlProtocol caught unknown" << endl;
 
150
        }
 
151
 
 
152
        _instance = 0;
 
153
 
 
154
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol done\n");
 
155
}
 
156
 
 
157
void
 
158
MackieControlProtocol::thread_init ()
 
159
{
 
160
        struct sched_param rtparam;
 
161
 
 
162
        pthread_set_name (X_("MackieControl"));
 
163
 
 
164
        PBD::notify_gui_about_thread_creation (X_("gui"), pthread_self(), X_("MackieControl"), 2048);
 
165
        ARDOUR::SessionEvent::create_per_thread_pool (X_("MackieControl"), 128);
 
166
 
 
167
        memset (&rtparam, 0, sizeof (rtparam));
 
168
        rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
 
169
 
 
170
        if (pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam) != 0) {
 
171
                // do we care? not particularly.
 
172
        }
 
173
}
 
174
 
 
175
void
 
176
MackieControlProtocol::midi_connectivity_established ()
 
177
{
 
178
        for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
 
179
                (*si)->say_hello ();
 
180
        }
 
181
 
 
182
        if (_device_info.no_handshake()) {
 
183
                for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
 
184
                        (*si)->turn_it_on ();
 
185
                }
 
186
        }
 
187
}
 
188
 
 
189
// go to the previous track.
 
190
// Assume that get_sorted_routes().size() > route_table.size()
 
191
void 
 
192
MackieControlProtocol::prev_track()
 
193
{
 
194
        if (_current_initial_bank >= 1) {
 
195
                switch_banks (_current_initial_bank - 1);
 
196
        }
 
197
}
 
198
 
 
199
// go to the next track.
 
200
// Assume that get_sorted_routes().size() > route_table.size()
 
201
void 
 
202
MackieControlProtocol::next_track()
 
203
{
 
204
        Sorted sorted = get_sorted_routes();
 
205
        if (_current_initial_bank + n_strips() < sorted.size()) {
 
206
                switch_banks (_current_initial_bank + 1);
 
207
        }
 
208
}
 
209
 
 
210
bool
 
211
MackieControlProtocol::route_is_locked_to_strip (boost::shared_ptr<Route> r) const
 
212
{
 
213
        for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
 
214
                if ((*si)->route_is_locked_to_strip (r)) {
 
215
                        return true;
 
216
                }
 
217
        }
 
218
        return false;
 
219
}
 
220
 
 
221
// predicate for sort call in get_sorted_routes
 
222
struct RouteByRemoteId
 
223
{
 
224
        bool operator () (const boost::shared_ptr<Route> & a, const boost::shared_ptr<Route> & b) const
 
225
        {
 
226
                return a->remote_control_id() < b->remote_control_id();
 
227
        }
 
228
 
 
229
        bool operator () (const Route & a, const Route & b) const
 
230
        {
 
231
                return a.remote_control_id() < b.remote_control_id();
 
232
        }
 
233
 
 
234
        bool operator () (const Route * a, const Route * b) const
 
235
        {
 
236
                return a->remote_control_id() < b->remote_control_id();
 
237
        }
 
238
};
 
239
 
 
240
MackieControlProtocol::Sorted 
 
241
MackieControlProtocol::get_sorted_routes()
 
242
{
 
243
        Sorted sorted;
 
244
 
 
245
        // fetch all routes
 
246
        boost::shared_ptr<RouteList> routes = session->get_routes();
 
247
        set<uint32_t> remote_ids;
 
248
 
 
249
        // routes with remote_id 0 should never be added
 
250
        // TODO verify this with ardour devs
 
251
        // remote_ids.insert (0);
 
252
 
 
253
        // sort in remote_id order, and exclude master, control and hidden routes
 
254
        // and any routes that are already set.
 
255
 
 
256
        for (RouteList::iterator it = routes->begin(); it != routes->end(); ++it) {
 
257
 
 
258
                boost::shared_ptr<Route> route = *it;
 
259
 
 
260
                if (remote_ids.find (route->remote_control_id()) != remote_ids.end()) {
 
261
                        continue;
 
262
                }
 
263
 
 
264
                if (route->is_auditioner() || route->is_master() || route->is_monitor()) {
 
265
                        continue;
 
266
                }
 
267
 
 
268
                /* don't include locked routes */
 
269
 
 
270
                if (route_is_locked_to_strip(route)) {
 
271
                        continue;
 
272
                }
 
273
 
 
274
                switch (_view_mode) {
 
275
                case Mixer:
 
276
                        break;
 
277
                case AudioTracks:
 
278
                        break;
 
279
                case Busses:
 
280
                        break;
 
281
                case MidiTracks:
 
282
                        break;
 
283
                case Dynamics:
 
284
                        break;
 
285
                case EQ:
 
286
                        break;
 
287
                case Loop:
 
288
                        break;
 
289
                case Sends:
 
290
                        break;
 
291
                case Plugins:
 
292
                        break;
 
293
                }
 
294
 
 
295
                sorted.push_back (*it);
 
296
                remote_ids.insert (route->remote_control_id());
 
297
        }
 
298
 
 
299
        sort (sorted.begin(), sorted.end(), RouteByRemoteId());
 
300
        return sorted;
 
301
}
 
302
 
 
303
void 
 
304
MackieControlProtocol::refresh_current_bank()
 
305
{
 
306
        switch_banks (_current_initial_bank, true);
 
307
}
 
308
 
 
309
uint32_t
 
310
MackieControlProtocol::n_strips (bool with_locked_strips) const
 
311
{
 
312
        uint32_t strip_count = 0;
 
313
 
 
314
        for (Surfaces::const_iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
 
315
                strip_count += (*si)->n_strips (with_locked_strips);
 
316
        }
 
317
 
 
318
        return strip_count;
 
319
}
 
320
 
 
321
void 
 
322
MackieControlProtocol::switch_banks (uint32_t initial, bool force)
 
323
{
 
324
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch banking to start at %1 force ? %2 current = %3\n", initial, force, _current_initial_bank));
 
325
 
 
326
        if (initial == _current_initial_bank && !force) {
 
327
                return;
 
328
        }
 
329
 
 
330
        Sorted sorted = get_sorted_routes();
 
331
        uint32_t strip_cnt = n_strips (false); // do not include locked strips
 
332
                                               // in this count
 
333
 
 
334
        if (sorted.size() <= strip_cnt && _current_initial_bank == 0 && !force) {
 
335
                /* no banking - not enough routes to fill all strips and we're
 
336
                 * not at the first one.
 
337
                 */
 
338
                return;
 
339
        }
 
340
 
 
341
        _current_initial_bank = initial;
 
342
        _current_selected_track = -1;
 
343
 
 
344
        // Map current bank of routes onto each surface(+strip)
 
345
 
 
346
        if (_current_initial_bank <= sorted.size()) {
 
347
 
 
348
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("switch to %1, %2, available routes %3\n", _current_initial_bank, strip_cnt, sorted.size()));
 
349
 
 
350
                // link routes to strips
 
351
 
 
352
                Sorted::iterator r = sorted.begin() + _current_initial_bank;
 
353
                
 
354
                for (Surfaces::iterator si = surfaces.begin(); si != surfaces.end(); ++si) {
 
355
                        vector<boost::shared_ptr<Route> > routes;
 
356
                        uint32_t added = 0;
 
357
 
 
358
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface has %1 unlockedstrips\n", (*si)->n_strips (false)));
 
359
 
 
360
                        for (; r != sorted.end() && added < (*si)->n_strips (false); ++r, ++added) {
 
361
                                routes.push_back (*r);
 
362
                        }
 
363
 
 
364
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("give surface %1 routes\n", routes.size()));
 
365
 
 
366
                        (*si)->map_routes (routes);
 
367
                }
 
368
        }
 
369
 
 
370
        /* reset this to get the right display of view mode after the switch */
 
371
        set_view_mode (_view_mode);
 
372
 
 
373
        /* make sure selection is correct */
 
374
        
 
375
        _gui_track_selection_changed (&_last_selected_routes, false);
 
376
        
 
377
        /* current bank has not been saved */
 
378
        session->set_dirty();
 
379
}
 
380
 
 
381
int 
 
382
MackieControlProtocol::set_active (bool yn)
 
383
{
 
384
        DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn));
 
385
 
 
386
        if (yn == _active) {
 
387
                return 0;
 
388
        }
 
389
 
 
390
        if (yn) {
 
391
                
 
392
                /* start event loop */
 
393
                
 
394
                BaseUI::run ();
 
395
                
 
396
                create_surfaces ();
 
397
                connect_session_signals ();
 
398
                _active = true;
 
399
                update_surfaces ();
 
400
                
 
401
                /* set up periodic task for metering and automation
 
402
                 */
 
403
                
 
404
                Glib::RefPtr<Glib::TimeoutSource> periodic_timeout = Glib::TimeoutSource::create (100); // milliseconds
 
405
                periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &MackieControlProtocol::periodic));
 
406
                periodic_timeout->attach (main_loop()->get_context());
 
407
                
 
408
        } else {
 
409
 
 
410
                BaseUI::quit ();
 
411
                close ();
 
412
                _active = false;
 
413
 
 
414
        }
 
415
 
 
416
        DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn));
 
417
 
 
418
        return 0;
 
419
}
 
420
 
 
421
bool
 
422
MackieControlProtocol::periodic ()
 
423
{
 
424
        if (!_active) {
 
425
                return false;
 
426
        }
 
427
 
 
428
        if (needs_ipmidi_restart) {
 
429
                ipmidi_restart ();
 
430
                return true;
 
431
        }
 
432
        
 
433
        if (!_initialized) {
 
434
                initialize();
 
435
        }
 
436
 
 
437
        struct timeval now;
 
438
        uint64_t now_usecs;
 
439
        gettimeofday (&now, 0);
 
440
 
 
441
        now_usecs = (now.tv_sec * 1000000) + now.tv_usec;
 
442
 
 
443
        {
 
444
                Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
445
 
 
446
                for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
447
                        (*s)->periodic (now_usecs);
 
448
                }
 
449
        }
 
450
 
 
451
        update_timecode_display ();
 
452
        
 
453
        return true;
 
454
}
 
455
 
 
456
void 
 
457
MackieControlProtocol::update_timecode_beats_led()
 
458
{
 
459
        if (!_device_info.has_timecode_display()) {
 
460
                return;
 
461
        }
 
462
 
 
463
        DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::update_timecode_beats_led(): %1\n", _timecode_type));
 
464
        switch (_timecode_type) {
 
465
                case ARDOUR::AnyTime::BBT:
 
466
                        update_global_led (Led::Beats, on);
 
467
                        update_global_led (Led::Timecode, off);
 
468
                        break;
 
469
                case ARDOUR::AnyTime::Timecode:
 
470
                        update_global_led (Led::Timecode, on);
 
471
                        update_global_led (Led::Beats, off);
 
472
                        break;
 
473
                default:
 
474
                        ostringstream os;
 
475
                        os << "Unknown Anytime::Type " << _timecode_type;
 
476
                        throw runtime_error (os.str());
 
477
        }
 
478
}
 
479
 
 
480
void 
 
481
MackieControlProtocol::update_global_button (int id, LedState ls)
 
482
{
 
483
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
484
 
 
485
        if (!_device_info.has_global_controls()) {
 
486
                return;
 
487
        }
 
488
 
 
489
        boost::shared_ptr<Surface> surface = surfaces.front();
 
490
 
 
491
        map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (id);
 
492
        if (x != surface->controls_by_device_independent_id.end()) {
 
493
                Button * button = dynamic_cast<Button*> (x->second);
 
494
                surface->write (button->set_state (ls));
 
495
        } else {
 
496
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Button %1 not found\n", id));
 
497
        }
 
498
}
 
499
 
 
500
void 
 
501
MackieControlProtocol::update_global_led (int id, LedState ls)
 
502
{
 
503
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
504
 
 
505
        if (!_device_info.has_global_controls()) {
 
506
                return;
 
507
        }
 
508
 
 
509
        boost::shared_ptr<Surface> surface = surfaces.front();
 
510
 
 
511
        map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (id);
 
512
 
 
513
        if (x != surface->controls_by_device_independent_id.end()) {
 
514
                Led * led = dynamic_cast<Led*> (x->second);
 
515
                DEBUG_TRACE (DEBUG::MackieControl, "Writing LedState\n");
 
516
                surface->write (led->set_state (ls));
 
517
        } else {
 
518
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Led %1 not found\n", id));
 
519
        }
 
520
}
 
521
 
 
522
// send messages to surface to set controls to correct values
 
523
void 
 
524
MackieControlProtocol::update_surfaces()
 
525
{
 
526
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n");
 
527
        if (!_active) {
 
528
                return;
 
529
        }
 
530
 
 
531
        // do the initial bank switch to connect signals
 
532
        // _current_initial_bank is initialised by set_state
 
533
        switch_banks (_current_initial_bank, true);
 
534
        
 
535
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() finished\n");
 
536
}
 
537
 
 
538
void
 
539
MackieControlProtocol::initialize()
 
540
{
 
541
        {
 
542
                Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
543
                
 
544
                if (surfaces.empty()) {
 
545
                        return;
 
546
                }
 
547
                
 
548
                if (!surfaces.front()->active ()) {
 
549
                        return;
 
550
                }
 
551
                
 
552
                // sometimes the jog wheel is a pot
 
553
                if (_device_info.has_jog_wheel()) {
 
554
                        surfaces.front()->blank_jog_ring ();
 
555
                }
 
556
        }
 
557
 
 
558
        // update global buttons and displays
 
559
 
 
560
        notify_record_state_changed();
 
561
        notify_transport_state_changed();
 
562
        update_timecode_beats_led();
 
563
        
 
564
        _initialized = true;
 
565
}
 
566
 
 
567
void 
 
568
MackieControlProtocol::connect_session_signals()
 
569
{
 
570
        // receive routes added
 
571
        session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_route_added, this, _1), this);
 
572
        // receive record state toggled
 
573
        session->RecordStateChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_record_state_changed, this), this);
 
574
        // receive transport state changed
 
575
        session->TransportStateChange.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_transport_state_changed, this), this);
 
576
        session->TransportLooped.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_loop_state_changed, this), this);
 
577
        // receive punch-in and punch-out
 
578
        Config->ParameterChanged.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
 
579
        session->config.ParameterChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_parameter_changed, this, _1), this);
 
580
        // receive rude solo changed
 
581
        session->SoloActive.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_solo_active_changed, this, _1), this);
 
582
 
 
583
        // make sure remote id changed signals reach here
 
584
        // see also notify_route_added
 
585
        Sorted sorted = get_sorted_routes();
 
586
 
 
587
        for (Sorted::iterator it = sorted.begin(); it != sorted.end(); ++it) {
 
588
                (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
 
589
        }
 
590
}
 
591
 
 
592
void
 
593
MackieControlProtocol::set_profile (const string& profile_name)
 
594
{
 
595
        if (profile_name == "default") {
 
596
                /* reset to default */
 
597
                _device_profile = DeviceProfile (profile_name);
 
598
        }
 
599
 
 
600
        map<string,DeviceProfile>::iterator d = DeviceProfile::device_profiles.find (profile_name);
 
601
 
 
602
        if (d == DeviceProfile::device_profiles.end()) {
 
603
                return;
 
604
        }
 
605
        
 
606
        _device_profile = d->second;
 
607
}       
 
608
 
 
609
void
 
610
MackieControlProtocol::set_device (const string& device_name, bool allow_activation)
 
611
{
 
612
        map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name);
 
613
 
 
614
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1, activation allowed ? %2\n",
 
615
                                                           device_name, allow_activation));
 
616
 
 
617
        if (d == DeviceInfo::device_info.end()) {
 
618
                return;
 
619
        }
 
620
        
 
621
        if (_active) {
 
622
                clear_ports ();
 
623
                clear_surfaces ();
 
624
        }
 
625
 
 
626
        _device_info = d->second;
 
627
 
 
628
        if (allow_activation) {
 
629
                set_active (true);
 
630
        } else {
 
631
                if (_active) {
 
632
                        create_surfaces ();
 
633
                        switch_banks (0, true);
 
634
                }
 
635
        }
 
636
}
 
637
 
 
638
void 
 
639
MackieControlProtocol::create_surfaces ()
 
640
{
 
641
        string device_name;
 
642
        surface_type_t stype = mcu;
 
643
        char buf[128];
 
644
 
 
645
        if (_device_info.extenders() == 0) {
 
646
                device_name = X_("mackie control");
 
647
        } else {
 
648
                device_name = X_("mackie control #1");
 
649
        }
 
650
 
 
651
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Create %1 surfaces\n", 1 + _device_info.extenders()));
 
652
 
 
653
        for (uint32_t n = 0; n < 1 + _device_info.extenders(); ++n) {
 
654
 
 
655
                boost::shared_ptr<Surface> surface (new Surface (*this, device_name, n, stype));
 
656
 
 
657
                {
 
658
                        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
659
                        surfaces.push_back (surface);
 
660
                }
 
661
 
 
662
                /* next device will be an extender */
 
663
                
 
664
                if (_device_info.extenders() < 2) {
 
665
                        device_name = X_("mackie control #2");
 
666
                } else {
 
667
                        snprintf (buf, sizeof (buf), X_("mackie control #%d"), n+2);
 
668
                        device_name = buf;
 
669
                }
 
670
                stype = ext;
 
671
 
 
672
                if (!_device_info.uses_ipmidi()) {
 
673
                        _input_bundle->add_channel (
 
674
                                surface->port().input_port().name(),
 
675
                                ARDOUR::DataType::MIDI,
 
676
                                session->engine().make_port_name_non_relative (surface->port().input_port().name())
 
677
                                );
 
678
                        
 
679
                        _output_bundle->add_channel (
 
680
                                surface->port().output_port().name(),
 
681
                                ARDOUR::DataType::MIDI,
 
682
                                session->engine().make_port_name_non_relative (surface->port().output_port().name())
 
683
                                );
 
684
                }
 
685
 
 
686
                int fd;
 
687
                MIDI::Port& input_port (surface->port().input_port());
 
688
 
 
689
                if ((fd = input_port.selectable ()) >= 0) {
 
690
                        Glib::RefPtr<IOSource> psrc = IOSource::create (fd, IO_IN|IO_HUP|IO_ERR);
 
691
 
 
692
                        psrc->connect (sigc::bind (sigc::mem_fun (this, &MackieControlProtocol::midi_input_handler), &input_port));
 
693
                        psrc->attach (main_loop()->get_context());
 
694
                        
 
695
                        // glibmm hack: for now, store only the GSource*
 
696
 
 
697
                        port_sources.push_back (psrc->gobj());
 
698
                        g_source_ref (psrc->gobj());
 
699
                }
 
700
        }
 
701
}
 
702
 
 
703
void 
 
704
MackieControlProtocol::close()
 
705
{
 
706
        clear_ports ();
 
707
 
 
708
        port_connections.drop_connections ();
 
709
        session_connections.drop_connections ();
 
710
        route_connections.drop_connections ();
 
711
        periodic_connection.disconnect ();
 
712
 
 
713
        clear_surfaces();
 
714
}
 
715
 
 
716
XMLNode& 
 
717
MackieControlProtocol::get_state()
 
718
{
 
719
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n");
 
720
        char buf[16];
 
721
 
 
722
        // add name of protocol
 
723
        XMLNode* node = new XMLNode (X_("Protocol"));
 
724
        node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
 
725
 
 
726
        // add current bank
 
727
        snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
 
728
        node->add_property (X_("bank"), buf);
 
729
 
 
730
        // ipMIDI base port (possibly not used)
 
731
        snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
 
732
        node->add_property (X_("ipmidi-base"), buf);
 
733
 
 
734
        node->add_property (X_("device-profile"), _device_profile.name());
 
735
        node->add_property (X_("device-name"), _device_info.name());
 
736
 
 
737
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n");
 
738
 
 
739
        return *node;
 
740
}
 
741
 
 
742
int 
 
743
MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
 
744
{
 
745
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
 
746
 
 
747
        int retval = 0;
 
748
        const XMLProperty* prop;
 
749
        uint32_t bank = 0;
 
750
        bool active = _active;
 
751
 
 
752
        if ((prop = node.property (X_("ipmidi-base"))) != 0) {
 
753
                set_ipmidi_base (atoi (prop->value()));
 
754
        }
 
755
 
 
756
        // fetch current bank
 
757
        if ((prop = node.property (X_("bank"))) != 0) {
 
758
                bank = atoi (prop->value());
 
759
        }
 
760
        
 
761
        if ((prop = node.property (X_("active"))) != 0) {
 
762
                active = string_is_affirmative (prop->value());
 
763
        }
 
764
 
 
765
        if ((prop = node.property (X_("device-name"))) != 0) {
 
766
                set_device (prop->value(), false);
 
767
        }
 
768
 
 
769
        if ((prop = node.property (X_("device-profile"))) != 0) {
 
770
                set_profile (prop->value());
 
771
        }
 
772
 
 
773
        set_active (active);
 
774
 
 
775
        if (_active) {
 
776
                switch_banks (bank, true);
 
777
        }
 
778
 
 
779
        DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n");
 
780
 
 
781
        return retval;
 
782
}
 
783
 
 
784
string 
 
785
MackieControlProtocol::format_bbt_timecode (framepos_t now_frame)
 
786
{
 
787
        Timecode::BBT_Time bbt_time;
 
788
 
 
789
        session->bbt_time (now_frame, bbt_time);
 
790
 
 
791
        // The Mackie protocol spec is built around a BBT time display of
 
792
        //
 
793
        // digits:     888/88/88/888
 
794
        // semantics:  BBB/bb/ss/ttt
 
795
        //
 
796
        // The third field is "subdivisions" which is a concept found in Logic
 
797
        // but not present in Ardour. Instead Ardour displays a 4 digit tick
 
798
        // count, which we need to spread across the 5 digits of ss/ttt.
 
799
 
 
800
        ostringstream os;
 
801
 
 
802
        os << setw(3) << setfill('0') << bbt_time.bars;
 
803
        os << setw(2) << setfill('0') << bbt_time.beats;
 
804
        os << ' ';
 
805
        os << setw(1) << setfill('0') << bbt_time.ticks / 1000;
 
806
        os << setw(3) << setfill('0') << bbt_time.ticks % 1000;
 
807
 
 
808
        return os.str();
 
809
}
 
810
 
 
811
string 
 
812
MackieControlProtocol::format_timecode_timecode (framepos_t now_frame)
 
813
{
 
814
        Timecode::Time timecode;
 
815
        session->timecode_time (now_frame, timecode);
 
816
 
 
817
        // According to the Logic docs
 
818
        // digits: 888/88/88/888
 
819
        // Timecode mode: Hours/Minutes/Seconds/Frames
 
820
        ostringstream os;
 
821
        os << setw(2) << setfill('0') << timecode.hours;
 
822
        os << ' ';
 
823
        os << setw(2) << setfill('0') << timecode.minutes;
 
824
        os << setw(2) << setfill('0') << timecode.seconds;
 
825
        os << ' ';
 
826
        os << setw(2) << setfill('0') << timecode.frames;
 
827
 
 
828
        return os.str();
 
829
}
 
830
 
 
831
void 
 
832
MackieControlProtocol::update_timecode_display()
 
833
{
 
834
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
835
 
 
836
        if (surfaces.empty()) {
 
837
                return;
 
838
        }
 
839
 
 
840
        boost::shared_ptr<Surface> surface = surfaces.front();
 
841
 
 
842
        if (surface->type() != mcu || !_device_info.has_timecode_display() || !surface->active ()) {
 
843
                return;
 
844
        }
 
845
 
 
846
        // do assignment here so current_frame is fixed
 
847
        framepos_t current_frame = session->transport_frame();
 
848
        string timecode;
 
849
 
 
850
        switch (_timecode_type) {
 
851
        case ARDOUR::AnyTime::BBT:
 
852
                timecode = format_bbt_timecode (current_frame);
 
853
                break;
 
854
        case ARDOUR::AnyTime::Timecode:
 
855
                timecode = format_timecode_timecode (current_frame);
 
856
                break;
 
857
        default:
 
858
                return;
 
859
        }
 
860
        
 
861
        // only write the timecode string to the MCU if it's changed
 
862
        // since last time. This is to reduce midi bandwidth used.
 
863
        if (timecode != _timecode_last) {
 
864
                surface->display_timecode (timecode, _timecode_last);
 
865
                _timecode_last = timecode;
 
866
        }
 
867
}
 
868
 
 
869
///////////////////////////////////////////
 
870
// Session signals
 
871
///////////////////////////////////////////
 
872
 
 
873
void MackieControlProtocol::notify_parameter_changed (std::string const & p)
 
874
{
 
875
        if (p == "punch-in") {
 
876
                update_global_button (Button::PunchIn, session->config.get_punch_in());
 
877
        } else if (p == "punch-out") {
 
878
                update_global_button (Button::PunchOut, session->config.get_punch_out());
 
879
        } else if (p == "clicking") {
 
880
                // update_global_button (Button::RelayClick, Config->get_clicking());
 
881
        } else {
 
882
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("parameter changed: %1\n", p));
 
883
        }
 
884
}
 
885
 
 
886
// RouteList is the set of routes that have just been added
 
887
void 
 
888
MackieControlProtocol::notify_route_added (ARDOUR::RouteList & rl)
 
889
{
 
890
        // currently assigned banks are less than the full set of
 
891
        // strips, so activate the new strip now.
 
892
 
 
893
        refresh_current_bank();
 
894
 
 
895
        // otherwise route added, but current bank needs no updating
 
896
 
 
897
        // make sure remote id changes in the new route are handled
 
898
        typedef ARDOUR::RouteList ARS;
 
899
 
 
900
        for (ARS::iterator it = rl.begin(); it != rl.end(); ++it) {
 
901
                (*it)->RemoteControlIDChanged.connect (route_connections, MISSING_INVALIDATOR, boost::bind (&MackieControlProtocol::notify_remote_id_changed, this), this);
 
902
        }
 
903
}
 
904
 
 
905
void 
 
906
MackieControlProtocol::notify_solo_active_changed (bool active)
 
907
{
 
908
        boost::shared_ptr<Surface> surface;
 
909
 
 
910
        {
 
911
                Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
912
                surface = surfaces.front ();
 
913
        }
 
914
        
 
915
        map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Led::RudeSolo);
 
916
        if (x != surface->controls_by_device_independent_id.end()) {
 
917
                Led* rude_solo = dynamic_cast<Led*> (x->second);
 
918
                if (rude_solo) {
 
919
                        surface->write (rude_solo->set_state (active ? flashing : off));
 
920
                }
 
921
        }
 
922
}
 
923
 
 
924
void 
 
925
MackieControlProtocol::notify_remote_id_changed()
 
926
{
 
927
        Sorted sorted = get_sorted_routes();
 
928
        uint32_t sz = n_strips();
 
929
 
 
930
        // if a remote id has been moved off the end, we need to shift
 
931
        // the current bank backwards.
 
932
 
 
933
        if (sorted.size() - _current_initial_bank < sz) {
 
934
                // but don't shift backwards past the zeroth channel
 
935
                switch_banks (max((Sorted::size_type) 0, sorted.size() - sz));
 
936
        } else {
 
937
                // Otherwise just refresh the current bank
 
938
                refresh_current_bank();
 
939
        }
 
940
}
 
941
 
 
942
///////////////////////////////////////////
 
943
// Transport signals
 
944
///////////////////////////////////////////
 
945
 
 
946
void 
 
947
MackieControlProtocol::notify_loop_state_changed()
 
948
{
 
949
        update_global_button (Button::Loop, session->get_play_loop());
 
950
}
 
951
 
 
952
void 
 
953
MackieControlProtocol::notify_transport_state_changed()
 
954
{
 
955
        if (!_device_info.has_global_controls()) {
 
956
                return;
 
957
        }
 
958
 
 
959
        // switch various play and stop buttons on / off
 
960
        update_global_button (Button::Loop, session->get_play_loop());
 
961
        update_global_button (Button::Play, session->transport_speed() == 1.0);
 
962
        update_global_button (Button::Stop, session->transport_stopped ());
 
963
        update_global_button (Button::Rewind, session->transport_speed() < 0.0);
 
964
        update_global_button (Button::Ffwd, session->transport_speed() > 1.0);
 
965
 
 
966
        notify_metering_state_changed ();
 
967
}
 
968
 
 
969
void 
 
970
MackieControlProtocol::notify_metering_state_changed()
 
971
{
 
972
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
973
 
 
974
        for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
975
                (*s)->notify_metering_state_changed ();
 
976
        }       
 
977
}
 
978
 
 
979
void
 
980
MackieControlProtocol::notify_record_state_changed ()
 
981
{
 
982
        if (!_device_info.has_global_controls()) {
 
983
                return;
 
984
        }
 
985
 
 
986
        boost::shared_ptr<Surface> surface;
 
987
 
 
988
        {
 
989
                Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
990
                surface = surfaces.front();
 
991
        }
 
992
                
 
993
        /* rec is a tristate */
 
994
 
 
995
        map<int,Control*>::iterator x = surface->controls_by_device_independent_id.find (Button::Record);
 
996
        if (x != surface->controls_by_device_independent_id.end()) {
 
997
                Button * rec = dynamic_cast<Button*> (x->second);
 
998
                if (rec) {
 
999
                        LedState ls;
 
1000
                        
 
1001
                        switch (session->record_status()) {
 
1002
                        case Session::Disabled:
 
1003
                                DEBUG_TRACE (DEBUG::MackieControl, "record state changed to disabled, LED off\n");
 
1004
                                ls = off;
 
1005
                                break;
 
1006
                        case Session::Recording:
 
1007
                                DEBUG_TRACE (DEBUG::MackieControl, "record state changed to recording, LED on\n");
 
1008
                                ls = on;
 
1009
                                break;
 
1010
                        case Session::Enabled:
 
1011
                                DEBUG_TRACE (DEBUG::MackieControl, "record state changed to enabled, LED flashing\n");
 
1012
                                ls = flashing;
 
1013
                                break;
 
1014
                        }
 
1015
 
 
1016
                        surface->write (rec->set_state (ls));
 
1017
                }
 
1018
        }
 
1019
}
 
1020
 
 
1021
list<boost::shared_ptr<ARDOUR::Bundle> >
 
1022
MackieControlProtocol::bundles ()
 
1023
{
 
1024
        list<boost::shared_ptr<ARDOUR::Bundle> > b;
 
1025
        b.push_back (_input_bundle);
 
1026
        b.push_back (_output_bundle);
 
1027
        return b;
 
1028
}
 
1029
 
 
1030
void
 
1031
MackieControlProtocol::do_request (MackieControlUIRequest* req)
 
1032
{
 
1033
        if (req->type == CallSlot) {
 
1034
 
 
1035
                call_slot (MISSING_INVALIDATOR, req->the_slot);
 
1036
 
 
1037
        } else if (req->type == Quit) {
 
1038
 
 
1039
                stop ();
 
1040
        }
 
1041
}
 
1042
 
 
1043
int
 
1044
MackieControlProtocol::stop ()
 
1045
{
 
1046
        BaseUI::quit ();
 
1047
 
 
1048
        return 0;
 
1049
}
 
1050
 
 
1051
void 
 
1052
MackieControlProtocol::update_led (Surface& surface, Button& button, Mackie::LedState ls)
 
1053
{
 
1054
        if (ls != none) {
 
1055
                surface.port().write (button.set_state (ls));
 
1056
        }
 
1057
}
 
1058
 
 
1059
void
 
1060
MackieControlProtocol::build_button_map ()
 
1061
{
 
1062
        /* this maps our device-independent button codes to the methods that handle them.
 
1063
         */
 
1064
 
 
1065
#define DEFINE_BUTTON_HANDLER(b,p,r) button_map.insert (pair<Button::ID,ButtonHandlers> ((b), ButtonHandlers ((p),(r))));
 
1066
 
 
1067
        DEFINE_BUTTON_HANDLER (Button::IO, &MackieControlProtocol::io_press, &MackieControlProtocol::io_release);
 
1068
        DEFINE_BUTTON_HANDLER (Button::Sends, &MackieControlProtocol::sends_press, &MackieControlProtocol::sends_release);
 
1069
        DEFINE_BUTTON_HANDLER (Button::Pan, &MackieControlProtocol::pan_press, &MackieControlProtocol::pan_release);
 
1070
        DEFINE_BUTTON_HANDLER (Button::Plugin, &MackieControlProtocol::plugin_press, &MackieControlProtocol::plugin_release);
 
1071
        DEFINE_BUTTON_HANDLER (Button::Eq, &MackieControlProtocol::eq_press, &MackieControlProtocol::eq_release);
 
1072
        DEFINE_BUTTON_HANDLER (Button::Dyn, &MackieControlProtocol::dyn_press, &MackieControlProtocol::dyn_release);
 
1073
        DEFINE_BUTTON_HANDLER (Button::Left, &MackieControlProtocol::left_press, &MackieControlProtocol::left_release);
 
1074
        DEFINE_BUTTON_HANDLER (Button::Right, &MackieControlProtocol::right_press, &MackieControlProtocol::right_release);
 
1075
        DEFINE_BUTTON_HANDLER (Button::ChannelLeft, &MackieControlProtocol::channel_left_press, &MackieControlProtocol::channel_left_release);
 
1076
        DEFINE_BUTTON_HANDLER (Button::ChannelRight, &MackieControlProtocol::channel_right_press, &MackieControlProtocol::channel_right_release);
 
1077
        DEFINE_BUTTON_HANDLER (Button::Flip, &MackieControlProtocol::flip_press, &MackieControlProtocol::flip_release);
 
1078
        DEFINE_BUTTON_HANDLER (Button::Edit, &MackieControlProtocol::edit_press, &MackieControlProtocol::edit_release);
 
1079
        DEFINE_BUTTON_HANDLER (Button::NameValue, &MackieControlProtocol::name_value_press, &MackieControlProtocol::name_value_release);
 
1080
        DEFINE_BUTTON_HANDLER (Button::TimecodeBeats, &MackieControlProtocol::timecode_beats_press, &MackieControlProtocol::timecode_beats_release);
 
1081
        DEFINE_BUTTON_HANDLER (Button::F1, &MackieControlProtocol::F1_press, &MackieControlProtocol::F1_release);
 
1082
        DEFINE_BUTTON_HANDLER (Button::F2, &MackieControlProtocol::F2_press, &MackieControlProtocol::F2_release);
 
1083
        DEFINE_BUTTON_HANDLER (Button::F3, &MackieControlProtocol::F3_press, &MackieControlProtocol::F3_release);
 
1084
        DEFINE_BUTTON_HANDLER (Button::F4, &MackieControlProtocol::F4_press, &MackieControlProtocol::F4_release);
 
1085
        DEFINE_BUTTON_HANDLER (Button::F5, &MackieControlProtocol::F5_press, &MackieControlProtocol::F5_release);
 
1086
        DEFINE_BUTTON_HANDLER (Button::F6, &MackieControlProtocol::F6_press, &MackieControlProtocol::F6_release);
 
1087
        DEFINE_BUTTON_HANDLER (Button::F7, &MackieControlProtocol::F7_press, &MackieControlProtocol::F7_release);
 
1088
        DEFINE_BUTTON_HANDLER (Button::F8, &MackieControlProtocol::F8_press, &MackieControlProtocol::F8_release);
 
1089
        DEFINE_BUTTON_HANDLER (Button::F9, &MackieControlProtocol::F9_press, &MackieControlProtocol::F9_release);
 
1090
        DEFINE_BUTTON_HANDLER (Button::F10, &MackieControlProtocol::F10_press, &MackieControlProtocol::F10_release);
 
1091
        DEFINE_BUTTON_HANDLER (Button::F11, &MackieControlProtocol::F11_press, &MackieControlProtocol::F11_release);
 
1092
        DEFINE_BUTTON_HANDLER (Button::F12, &MackieControlProtocol::F12_press, &MackieControlProtocol::F12_release);
 
1093
        DEFINE_BUTTON_HANDLER (Button::F13, &MackieControlProtocol::F13_press, &MackieControlProtocol::F13_release);
 
1094
        DEFINE_BUTTON_HANDLER (Button::F14, &MackieControlProtocol::F14_press, &MackieControlProtocol::F14_release);
 
1095
        DEFINE_BUTTON_HANDLER (Button::F15, &MackieControlProtocol::F15_press, &MackieControlProtocol::F15_release);
 
1096
        DEFINE_BUTTON_HANDLER (Button::F16, &MackieControlProtocol::F16_press, &MackieControlProtocol::F16_release);
 
1097
        DEFINE_BUTTON_HANDLER (Button::Shift, &MackieControlProtocol::shift_press, &MackieControlProtocol::shift_release);
 
1098
        DEFINE_BUTTON_HANDLER (Button::Option, &MackieControlProtocol::option_press, &MackieControlProtocol::option_release);
 
1099
        DEFINE_BUTTON_HANDLER (Button::Ctrl, &MackieControlProtocol::control_press, &MackieControlProtocol::control_release);
 
1100
        DEFINE_BUTTON_HANDLER (Button::CmdAlt, &MackieControlProtocol::cmd_alt_press, &MackieControlProtocol::cmd_alt_release);
 
1101
        DEFINE_BUTTON_HANDLER (Button::On, &MackieControlProtocol::on_press, &MackieControlProtocol::on_release);
 
1102
        DEFINE_BUTTON_HANDLER (Button::RecReady, &MackieControlProtocol::rec_ready_press, &MackieControlProtocol::rec_ready_release);
 
1103
        DEFINE_BUTTON_HANDLER (Button::Undo, &MackieControlProtocol::undo_press, &MackieControlProtocol::undo_release);
 
1104
        DEFINE_BUTTON_HANDLER (Button::Save, &MackieControlProtocol::save_press, &MackieControlProtocol::save_release);
 
1105
        DEFINE_BUTTON_HANDLER (Button::Touch, &MackieControlProtocol::touch_press, &MackieControlProtocol::touch_release);
 
1106
        DEFINE_BUTTON_HANDLER (Button::Redo, &MackieControlProtocol::redo_press, &MackieControlProtocol::redo_release);
 
1107
        DEFINE_BUTTON_HANDLER (Button::Marker, &MackieControlProtocol::marker_press, &MackieControlProtocol::marker_release);
 
1108
        DEFINE_BUTTON_HANDLER (Button::Enter, &MackieControlProtocol::enter_press, &MackieControlProtocol::enter_release);
 
1109
        DEFINE_BUTTON_HANDLER (Button::Cancel, &MackieControlProtocol::cancel_press, &MackieControlProtocol::cancel_release);
 
1110
        DEFINE_BUTTON_HANDLER (Button::Mixer, &MackieControlProtocol::mixer_press, &MackieControlProtocol::mixer_release);
 
1111
        DEFINE_BUTTON_HANDLER (Button::FrmLeft, &MackieControlProtocol::frm_left_press, &MackieControlProtocol::frm_left_release);
 
1112
        DEFINE_BUTTON_HANDLER (Button::FrmRight, &MackieControlProtocol::frm_right_press, &MackieControlProtocol::frm_right_release);
 
1113
        DEFINE_BUTTON_HANDLER (Button::Loop, &MackieControlProtocol::loop_press, &MackieControlProtocol::loop_release);
 
1114
        DEFINE_BUTTON_HANDLER (Button::PunchIn, &MackieControlProtocol::punch_in_press, &MackieControlProtocol::punch_in_release);
 
1115
        DEFINE_BUTTON_HANDLER (Button::PunchOut, &MackieControlProtocol::punch_out_press, &MackieControlProtocol::punch_out_release);
 
1116
        DEFINE_BUTTON_HANDLER (Button::Home, &MackieControlProtocol::home_press, &MackieControlProtocol::home_release);
 
1117
        DEFINE_BUTTON_HANDLER (Button::End, &MackieControlProtocol::end_press, &MackieControlProtocol::end_release);
 
1118
        DEFINE_BUTTON_HANDLER (Button::Rewind, &MackieControlProtocol::rewind_press, &MackieControlProtocol::rewind_release);
 
1119
        DEFINE_BUTTON_HANDLER (Button::Ffwd, &MackieControlProtocol::ffwd_press, &MackieControlProtocol::ffwd_release);
 
1120
        DEFINE_BUTTON_HANDLER (Button::Stop, &MackieControlProtocol::stop_press, &MackieControlProtocol::stop_release);
 
1121
        DEFINE_BUTTON_HANDLER (Button::Play, &MackieControlProtocol::play_press, &MackieControlProtocol::play_release);
 
1122
        DEFINE_BUTTON_HANDLER (Button::Record, &MackieControlProtocol::record_press, &MackieControlProtocol::record_release);
 
1123
        DEFINE_BUTTON_HANDLER (Button::CursorUp, &MackieControlProtocol::cursor_up_press, &MackieControlProtocol::cursor_up_release);
 
1124
        DEFINE_BUTTON_HANDLER (Button::CursorDown, &MackieControlProtocol::cursor_down_press, &MackieControlProtocol::cursor_down_release);
 
1125
        DEFINE_BUTTON_HANDLER (Button::CursorLeft, &MackieControlProtocol::cursor_left_press, &MackieControlProtocol::cursor_left_release);
 
1126
        DEFINE_BUTTON_HANDLER (Button::CursorRight, &MackieControlProtocol::cursor_right_press, &MackieControlProtocol::cursor_right_release);
 
1127
        DEFINE_BUTTON_HANDLER (Button::Zoom, &MackieControlProtocol::zoom_press, &MackieControlProtocol::zoom_release);
 
1128
        DEFINE_BUTTON_HANDLER (Button::Scrub, &MackieControlProtocol::scrub_press, &MackieControlProtocol::scrub_release);
 
1129
        DEFINE_BUTTON_HANDLER (Button::UserA, &MackieControlProtocol::user_a_press, &MackieControlProtocol::user_a_release);
 
1130
        DEFINE_BUTTON_HANDLER (Button::UserB, &MackieControlProtocol::user_b_press, &MackieControlProtocol::user_b_release);
 
1131
        DEFINE_BUTTON_HANDLER (Button::MasterFaderTouch, &MackieControlProtocol::master_fader_touch_press, &MackieControlProtocol::master_fader_touch_release);
 
1132
 
 
1133
        DEFINE_BUTTON_HANDLER (Button::Snapshot, &MackieControlProtocol::snapshot_press, &MackieControlProtocol::snapshot_release);
 
1134
        DEFINE_BUTTON_HANDLER (Button::Read, &MackieControlProtocol::read_press, &MackieControlProtocol::read_release);
 
1135
        DEFINE_BUTTON_HANDLER (Button::Write, &MackieControlProtocol::write_press, &MackieControlProtocol::write_release);
 
1136
        DEFINE_BUTTON_HANDLER (Button::FdrGroup, &MackieControlProtocol::fdrgroup_press, &MackieControlProtocol::fdrgroup_release);
 
1137
        DEFINE_BUTTON_HANDLER (Button::ClearSolo, &MackieControlProtocol::clearsolo_press, &MackieControlProtocol::clearsolo_release);
 
1138
        DEFINE_BUTTON_HANDLER (Button::Track, &MackieControlProtocol::track_press, &MackieControlProtocol::track_release);
 
1139
        DEFINE_BUTTON_HANDLER (Button::Send, &MackieControlProtocol::send_press, &MackieControlProtocol::send_release);
 
1140
        DEFINE_BUTTON_HANDLER (Button::MidiTracks, &MackieControlProtocol::miditracks_press, &MackieControlProtocol::miditracks_release);
 
1141
        DEFINE_BUTTON_HANDLER (Button::Inputs, &MackieControlProtocol::inputs_press, &MackieControlProtocol::inputs_release);
 
1142
        DEFINE_BUTTON_HANDLER (Button::AudioTracks, &MackieControlProtocol::audiotracks_press, &MackieControlProtocol::audiotracks_release);
 
1143
        DEFINE_BUTTON_HANDLER (Button::AudioInstruments, &MackieControlProtocol::audioinstruments_press, &MackieControlProtocol::audioinstruments_release);
 
1144
        DEFINE_BUTTON_HANDLER (Button::Aux, &MackieControlProtocol::aux_press, &MackieControlProtocol::aux_release);
 
1145
        DEFINE_BUTTON_HANDLER (Button::Busses, &MackieControlProtocol::busses_press, &MackieControlProtocol::busses_release);
 
1146
        DEFINE_BUTTON_HANDLER (Button::Outputs, &MackieControlProtocol::outputs_press, &MackieControlProtocol::outputs_release);
 
1147
        DEFINE_BUTTON_HANDLER (Button::User, &MackieControlProtocol::user_press, &MackieControlProtocol::user_release);
 
1148
        DEFINE_BUTTON_HANDLER (Button::Trim, &MackieControlProtocol::trim_press, &MackieControlProtocol::trim_release);
 
1149
        DEFINE_BUTTON_HANDLER (Button::Latch, &MackieControlProtocol::latch_press, &MackieControlProtocol::latch_release);
 
1150
        DEFINE_BUTTON_HANDLER (Button::Grp, &MackieControlProtocol::grp_press, &MackieControlProtocol::grp_release);
 
1151
        DEFINE_BUTTON_HANDLER (Button::Nudge, &MackieControlProtocol::nudge_press, &MackieControlProtocol::nudge_release);
 
1152
        DEFINE_BUTTON_HANDLER (Button::Drop, &MackieControlProtocol::drop_press, &MackieControlProtocol::drop_release);
 
1153
        DEFINE_BUTTON_HANDLER (Button::Replace, &MackieControlProtocol::replace_press, &MackieControlProtocol::replace_release);
 
1154
        DEFINE_BUTTON_HANDLER (Button::Click, &MackieControlProtocol::click_press, &MackieControlProtocol::click_release);
 
1155
        DEFINE_BUTTON_HANDLER (Button::View, &MackieControlProtocol::view_press, &MackieControlProtocol::view_release);
 
1156
}
 
1157
 
 
1158
void 
 
1159
MackieControlProtocol::handle_button_event (Surface& surface, Button& button, ButtonState bs)
 
1160
{
 
1161
        if  (bs != press && bs != release) {
 
1162
                update_led (surface, button, none);
 
1163
                return;
 
1164
        }
 
1165
        
 
1166
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Handling %1 for button %2 (%3)\n", (bs == press ? "press" : "release"), button.id(),
 
1167
                                                           Button::id_to_name (button.bid())));
 
1168
 
 
1169
        /* check profile first */
 
1170
        
 
1171
        string action = _device_profile.get_button_action (button.bid(), _modifier_state);
 
1172
        
 
1173
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("Looked up action for button %1 with modifier %2, got [%3]\n",
 
1174
                                                           button.bid(), _modifier_state, action));
 
1175
 
 
1176
        if (!action.empty()) {
 
1177
                /* if there is a bound action for this button, and this is a press event,
 
1178
                   carry out the action. If its a release event, do nothing since we 
 
1179
                   don't bind to them at all but don't want any other handling to 
 
1180
                   occur either.
 
1181
                */
 
1182
                if (bs == press) {
 
1183
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("executing action %1\n", action));
 
1184
                        access_action (action);
 
1185
                }
 
1186
                return;
 
1187
        }
 
1188
 
 
1189
        /* lookup using the device-INDEPENDENT button ID */
 
1190
 
 
1191
        ButtonMap::iterator b = button_map.find (button.bid());
 
1192
 
 
1193
        if (b != button_map.end()) {
 
1194
 
 
1195
                ButtonHandlers& bh (b->second);
 
1196
 
 
1197
                switch  (bs) {
 
1198
                case press: 
 
1199
                        surface.write (button.set_state ((this->*(bh.press)) (button)));
 
1200
                        break;
 
1201
                case release: 
 
1202
                        surface.write (button.set_state ((this->*(bh.release)) (button)));
 
1203
                        break;
 
1204
                default:
 
1205
                        break;
 
1206
                }
 
1207
        } else {
 
1208
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("no button handlers for button ID %1 (device ID %2)\n", 
 
1209
                                                                   button.bid(), button.id()));
 
1210
                error << string_compose ("no button handlers for button ID %1 (device ID %2)\n", 
 
1211
                                         button.bid(), button.id()) << endmsg;
 
1212
        }
 
1213
}
 
1214
 
 
1215
bool
 
1216
MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
 
1217
{
 
1218
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("something happend on  %1\n", port->name()));
 
1219
 
 
1220
        if (ioc & ~IO_IN) {
 
1221
                return false;
 
1222
        }
 
1223
 
 
1224
        if (ioc & IO_IN) {
 
1225
 
 
1226
                /* Devices using regular JACK MIDI ports will need to have
 
1227
                   the x-thread FIFO drained to avoid burning endless CPU.
 
1228
 
 
1229
                   Devices using ipMIDI have port->selectable() as the same
 
1230
                   file descriptor that data arrives on, so doing this
 
1231
                   for them will simply throw all incoming data away.
 
1232
                */
 
1233
 
 
1234
                if (!_device_info.uses_ipmidi()) {
 
1235
                        CrossThreadChannel::drain (port->selectable());
 
1236
                }
 
1237
 
 
1238
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("data available on %1\n", port->name()));
 
1239
                framepos_t now = session->engine().frame_time();
 
1240
                port->parse (now);
 
1241
        }
 
1242
 
 
1243
        return true;
 
1244
}
 
1245
 
 
1246
void
 
1247
MackieControlProtocol::clear_ports ()
 
1248
{
 
1249
        _input_bundle->remove_channels ();
 
1250
        _output_bundle->remove_channels ();
 
1251
 
 
1252
        for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
 
1253
                g_source_destroy (*i);
 
1254
                g_source_unref (*i);
 
1255
        }
 
1256
 
 
1257
        port_sources.clear ();
 
1258
}
 
1259
 
 
1260
void
 
1261
MackieControlProtocol::set_view_mode (ViewMode m)
 
1262
{
 
1263
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
1264
 
 
1265
        _view_mode = m;
 
1266
 
 
1267
        for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
1268
                (*s)->update_view_mode_display ();
 
1269
        }
 
1270
        
 
1271
}
 
1272
 
 
1273
void
 
1274
MackieControlProtocol::set_flip_mode (FlipMode fm)
 
1275
{
 
1276
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
1277
 
 
1278
        _flip_mode = fm;
 
1279
        
 
1280
        for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
1281
                (*s)->update_flip_mode_display ();
 
1282
        }
 
1283
}
 
1284
        
 
1285
void
 
1286
MackieControlProtocol::set_master_on_surface_strip (uint32_t surface, uint32_t strip_number)
 
1287
{
 
1288
        force_special_route_to_strip (session->master_out(), surface, strip_number);
 
1289
}
 
1290
 
 
1291
void
 
1292
MackieControlProtocol::set_monitor_on_surface_strip (uint32_t surface, uint32_t strip_number)
 
1293
{
 
1294
        force_special_route_to_strip (session->monitor_out(), surface, strip_number);
 
1295
}
 
1296
 
 
1297
void
 
1298
MackieControlProtocol::force_special_route_to_strip (boost::shared_ptr<Route> r, uint32_t surface, uint32_t strip_number)
 
1299
{
 
1300
        if (!r) {
 
1301
                return;
 
1302
        }
 
1303
 
 
1304
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
1305
 
 
1306
        for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
1307
                if ((*s)->number() == surface) {
 
1308
                        Strip* strip = (*s)->nth_strip (strip_number);
 
1309
                        if (strip) {
 
1310
                                strip->set_route (session->master_out());
 
1311
                                strip->lock_controls ();
 
1312
                        }
 
1313
                }
 
1314
        }
 
1315
}
 
1316
 
 
1317
void
 
1318
MackieControlProtocol::gui_track_selection_changed (ARDOUR::RouteNotificationListPtr rl, bool save_list)
 
1319
{
 
1320
        _gui_track_selection_changed (rl.get(), save_list);
 
1321
}
 
1322
 
 
1323
void
 
1324
MackieControlProtocol::_gui_track_selection_changed (ARDOUR::RouteNotificationList* rl, bool save_list)
 
1325
{
 
1326
        /* We need to keep a list of the most recently selected routes around,
 
1327
           but we are not allowed to keep shared_ptr<Route> unless we want to
 
1328
           handle the complexities of route deletion. So instead, the GUI sends
 
1329
           us a notification using weak_ptr<Route>, which we keep a copy
 
1330
           of. For efficiency's sake, however, we convert the weak_ptr's into
 
1331
           shared_ptr<Route> before passing them to however many surfaces (and
 
1332
           thus strips) that we have.
 
1333
        */
 
1334
 
 
1335
        StrongRouteNotificationList srl;
 
1336
 
 
1337
        for (ARDOUR::RouteNotificationList::const_iterator i = rl->begin(); i != rl->end(); ++i) {
 
1338
                boost::shared_ptr<ARDOUR::Route> r = (*i).lock();
 
1339
                if (r) {
 
1340
                        srl.push_back (r);
 
1341
                }
 
1342
        }
 
1343
 
 
1344
        {
 
1345
                Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
1346
                
 
1347
                for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
1348
                        (*s)->gui_selection_changed (srl);
 
1349
                }
 
1350
        }
 
1351
        
 
1352
        if (save_list) {
 
1353
                _last_selected_routes = *rl;
 
1354
        }
 
1355
}
 
1356
 
 
1357
framepos_t
 
1358
MackieControlProtocol::transport_frame() const
 
1359
{
 
1360
        return session->transport_frame();
 
1361
}
 
1362
 
 
1363
void
 
1364
MackieControlProtocol::add_down_select_button (int surface, int strip)
 
1365
{
 
1366
        _down_select_buttons.insert ((surface<<8)|(strip&0xf));
 
1367
}
 
1368
 
 
1369
void
 
1370
MackieControlProtocol::remove_down_select_button (int surface, int strip)
 
1371
{
 
1372
        DownButtonList::iterator x = find (_down_select_buttons.begin(), _down_select_buttons.end(), (surface<<8)|(strip&0xf));
 
1373
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down select buttons\n", surface, strip));
 
1374
        if (x != _down_select_buttons.end()) {
 
1375
                _down_select_buttons.erase (x);
 
1376
        } else {
 
1377
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 not found in down select buttons\n",
 
1378
                                                                   surface, strip));
 
1379
        }
 
1380
}
 
1381
 
 
1382
void
 
1383
MackieControlProtocol::select_range ()
 
1384
{
 
1385
        RouteList routes;
 
1386
 
 
1387
        pull_route_range (_down_select_buttons, routes);
 
1388
 
 
1389
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("select range: found %1 routes\n", routes.size()));
 
1390
 
 
1391
        if (!routes.empty()) {
 
1392
                for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
 
1393
 
 
1394
                        if (_modifier_state == MODIFIER_CONTROL) {
 
1395
                                ToggleRouteSelection ((*r)->remote_control_id ());
 
1396
                        } else {
 
1397
                                if (r == routes.begin()) {
 
1398
                                        SetRouteSelection ((*r)->remote_control_id());
 
1399
                                } else {
 
1400
                                        AddRouteToSelection ((*r)->remote_control_id());
 
1401
                                }
 
1402
                        }
 
1403
                }
 
1404
        }
 
1405
}
 
1406
 
 
1407
void
 
1408
MackieControlProtocol::add_down_button (AutomationType a, int surface, int strip)
 
1409
{
 
1410
        DownButtonMap::iterator m = _down_buttons.find (a);
 
1411
 
 
1412
        if (m == _down_buttons.end()) {
 
1413
                _down_buttons[a] = DownButtonList();
 
1414
        }
 
1415
 
 
1416
        _down_buttons[a].insert ((surface<<8)|(strip&0xf));
 
1417
}
 
1418
 
 
1419
void
 
1420
MackieControlProtocol::remove_down_button (AutomationType a, int surface, int strip)
 
1421
{
 
1422
        DownButtonMap::iterator m = _down_buttons.find (a);
 
1423
 
 
1424
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("removing surface %1 strip %2 from down buttons for %3\n", surface, strip, (int) a));
 
1425
 
 
1426
        if (m == _down_buttons.end()) {
 
1427
                return;
 
1428
        }
 
1429
 
 
1430
        DownButtonList& l (m->second);
 
1431
        DownButtonList::iterator x = find (l.begin(), l.end(), (surface<<8)|(strip&0xf));
 
1432
 
 
1433
        if (x != l.end()) {
 
1434
                l.erase (x);
 
1435
        } else {
 
1436
                DEBUG_TRACE (DEBUG::MackieControl, string_compose ("surface %1 strip %2 not found in down buttons for %3\n",
 
1437
                                                                   surface, strip, (int) a));
 
1438
        }
 
1439
}
 
1440
 
 
1441
MackieControlProtocol::ControlList
 
1442
MackieControlProtocol::down_controls (AutomationType p)
 
1443
{
 
1444
        ControlList controls;
 
1445
        RouteList routes;
 
1446
 
 
1447
        DownButtonMap::iterator m = _down_buttons.find (p);
 
1448
 
 
1449
        if (m == _down_buttons.end()) {
 
1450
                return controls;
 
1451
        }
 
1452
        
 
1453
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("looking for down buttons for %1, got %2\n",
 
1454
                                                           p, m->second.size()));
 
1455
 
 
1456
        pull_route_range (m->second, routes);
 
1457
        
 
1458
        switch (p) {
 
1459
        case GainAutomation:
 
1460
                for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
 
1461
                        controls.push_back ((*r)->gain_control());
 
1462
                }
 
1463
                break;
 
1464
        case SoloAutomation:
 
1465
                for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
 
1466
                        controls.push_back ((*r)->solo_control());
 
1467
                }
 
1468
                break;
 
1469
        case MuteAutomation:
 
1470
                for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
 
1471
                        controls.push_back ((*r)->mute_control());
 
1472
                }
 
1473
                break;
 
1474
        case RecEnableAutomation:
 
1475
                for (RouteList::iterator r = routes.begin(); r != routes.end(); ++r) {
 
1476
                        boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
 
1477
                        if (trk) {
 
1478
                                controls.push_back (trk->rec_enable_control());
 
1479
                        }
 
1480
                }
 
1481
                break;
 
1482
        default:
 
1483
                break;
 
1484
        }
 
1485
 
 
1486
        return controls;
 
1487
 
 
1488
}
 
1489
        
 
1490
struct ButtonRangeSorter {
 
1491
    bool operator() (const uint32_t& a, const uint32_t& b) {
 
1492
            return (a>>8) < (b>>8) // a.surface < b.surface
 
1493
                    ||
 
1494
                    ((a>>8) == (b>>8) && (a&0xf) < (b&0xf)); // a.surface == b.surface && a.strip < b.strip
 
1495
    }
 
1496
};
 
1497
 
 
1498
void
 
1499
MackieControlProtocol::pull_route_range (DownButtonList& down, RouteList& selected)
 
1500
{
 
1501
        ButtonRangeSorter cmp;
 
1502
 
 
1503
        if (down.empty()) {
 
1504
                return;
 
1505
        }
 
1506
 
 
1507
        list<uint32_t> ldown;
 
1508
        ldown.insert (ldown.end(), down.begin(), down.end());
 
1509
        ldown.sort (cmp);
 
1510
 
 
1511
        uint32_t first = ldown.front();
 
1512
        uint32_t last = ldown.back ();
 
1513
        
 
1514
        uint32_t first_surface = first>>8;
 
1515
        uint32_t first_strip = first&0xf;
 
1516
 
 
1517
        uint32_t last_surface = last>>8;
 
1518
        uint32_t last_strip = last&0xf;
 
1519
 
 
1520
        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("PRR %5 in list %1.%2 - %3.%4\n", first_surface, first_strip, last_surface, last_strip,
 
1521
                                                           down.size()));
 
1522
        
 
1523
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
1524
 
 
1525
        for (Surfaces::const_iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
 
1526
                
 
1527
                if ((*s)->number() >= first_surface && (*s)->number() <= last_surface) {
 
1528
 
 
1529
                        uint32_t fs;
 
1530
                        uint32_t ls;
 
1531
 
 
1532
                        if ((*s)->number() == first_surface) {
 
1533
                                fs = first_strip;
 
1534
                        } else {
 
1535
                                fs = 0;
 
1536
                        }
 
1537
 
 
1538
                        if ((*s)->number() == last_surface) {
 
1539
                                ls = last_strip;
 
1540
                                ls += 1;
 
1541
                        } else {
 
1542
                                ls = (*s)->n_strips ();
 
1543
                        }
 
1544
 
 
1545
                        DEBUG_TRACE (DEBUG::MackieControl, string_compose ("adding strips for surface %1 (%2 .. %3)\n",
 
1546
                                                                           (*s)->number(), fs, ls));
 
1547
 
 
1548
                        for (uint32_t n = fs; n < ls; ++n) {
 
1549
                                boost::shared_ptr<Route> r = (*s)->nth_strip (n)->route();
 
1550
                                if (r) {
 
1551
                                        selected.push_back (r);
 
1552
                                }
 
1553
                        }
 
1554
                }
 
1555
        }
 
1556
}
 
1557
 
 
1558
void
 
1559
MackieControlProtocol::set_ipmidi_base (int16_t portnum)
 
1560
{
 
1561
        /* this will not be saved without a session save, so .. */
 
1562
 
 
1563
        session->set_dirty ();
 
1564
 
 
1565
        _ipmidi_base = portnum;
 
1566
 
 
1567
        /* if the current device uses ipMIDI we need
 
1568
           to restart.
 
1569
        */
 
1570
 
 
1571
        if (_active && _device_info.uses_ipmidi()) {
 
1572
                needs_ipmidi_restart = true;
 
1573
        }
 
1574
}
 
1575
 
 
1576
void
 
1577
MackieControlProtocol::ipmidi_restart ()
 
1578
{
 
1579
        clear_ports ();
 
1580
        clear_surfaces ();
 
1581
        create_surfaces ();
 
1582
        switch_banks (_current_initial_bank, true);
 
1583
        needs_ipmidi_restart = false;
 
1584
}
 
1585
 
 
1586
void
 
1587
MackieControlProtocol::clear_surfaces ()
 
1588
{
 
1589
        Glib::Threads::Mutex::Lock lm (surfaces_lock);
 
1590
        surfaces.clear ();      
 
1591
}