summaryrefslogtreecommitdiff
path: root/libs/surfaces
diff options
context:
space:
mode:
authorJohn Anderson <ardour@semiosix.com>2008-01-05 12:00:52 +0000
committerJohn Anderson <ardour@semiosix.com>2008-01-05 12:00:52 +0000
commit8134233249158635f5a44c41f4f7d57b94526a46 (patch)
tree1eca9330fadb3bea4884bd5775e1f745bc3a9df8 /libs/surfaces
parent56d529290af04cd70e66b914cfbe67fdd00ebaa0 (diff)
Change MackiePort usage to SurfacePort. Add DummyPort for when the real port goes away. Do some checks to not use alsa/sequencer and device=ardour ports.
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2830 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/surfaces')
-rw-r--r--libs/surfaces/mackie/SConscript5
-rw-r--r--libs/surfaces/mackie/TODO16
-rw-r--r--libs/surfaces/mackie/bcf_surface.cc31
-rw-r--r--libs/surfaces/mackie/bcf_surface.h6
-rw-r--r--libs/surfaces/mackie/dummy_port.cc58
-rw-r--r--libs/surfaces/mackie/dummy_port.h60
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.cc211
-rw-r--r--libs/surfaces/mackie/mackie_control_protocol.h8
-rw-r--r--libs/surfaces/mackie/mackie_midi_builder.cc10
-rw-r--r--libs/surfaces/mackie/mackie_midi_builder.h20
-rw-r--r--libs/surfaces/mackie/mackie_port.cc1
-rw-r--r--libs/surfaces/mackie/mackie_surface.cc8
-rw-r--r--libs/surfaces/mackie/mackie_surface.h4
-rw-r--r--libs/surfaces/mackie/route_signal.h8
-rw-r--r--libs/surfaces/mackie/surface.h16
-rw-r--r--libs/surfaces/mackie/surface_port.cc10
-rw-r--r--libs/surfaces/mackie/surface_port.h16
17 files changed, 353 insertions, 135 deletions
diff --git a/libs/surfaces/mackie/SConscript b/libs/surfaces/mackie/SConscript
index bc834a9550..97e2b8c38b 100644
--- a/libs/surfaces/mackie/SConscript
+++ b/libs/surfaces/mackie/SConscript
@@ -28,12 +28,13 @@ mackie_files=Split("""
interface.cc
midi_byte_array.cc
controls.cc
+surface_port.cc
+dummy_port.cc
+mackie_port.cc
route_signal.cc
mackie_midi_builder.cc
mackie_button_handler.cc
mackie_control_protocol_poll.cc
-surface_port.cc
-mackie_port.cc
types.cc
surface.cc
mackie_control_protocol.cc
diff --git a/libs/surfaces/mackie/TODO b/libs/surfaces/mackie/TODO
index 84b75d1a9b..2573e0f05b 100644
--- a/libs/surfaces/mackie/TODO
+++ b/libs/surfaces/mackie/TODO
@@ -1,3 +1,4 @@
+* implement handle_port_inactive properly
* two bcf doesn't work
* remappable buttons (OSC or Surfax?)
* 7/1 configurable to 8
@@ -15,6 +16,19 @@ MCU
* metering on second line
* per-strip signal led
* midi bandwidth?
+* Zoom buttons, from Jean-Martin Barbut. In fact I'm a bit desappointed with those functions, because I was used
+ to use the 4 "N-E-S-W" buttons to zoom in and out with horizontal
+ buttons and zoom in/out on track height with vertical buttons. That is
+ with the zoom button in. with the zoom button off, it selects tracks
+ with vertical buttons and selects regions with horizontal buttons. This
+ was quite useful. The fact that the zoom button switches the wheel to
+ zoom is fine, but it would be great to also have the track/region
+ selection and the track height available from those buttons. I.e : you
+ select a track with the vertical arrows and you increase/decrease the
+ eight of the track with the zoom btn on. This combined with the region
+ selection allows to zoom in a region (vertical and horizontal zoom) very
+ easily.
+
Later
-----
@@ -50,3 +64,5 @@ Bugs
----
* when using alsa/sequencer, some midi events intended for mcu port end up being
read by the seq port.
+* MIDI::Port::type() returns _type, which is undefined. It might be in the descriptor
+* auditioner doesn't connect to master 1 and master 2 - it loses the spaces.
diff --git a/libs/surfaces/mackie/bcf_surface.cc b/libs/surfaces/mackie/bcf_surface.cc
index dae1f6d97f..0898e95ba1 100644
--- a/libs/surfaces/mackie/bcf_surface.cc
+++ b/libs/surfaces/mackie/bcf_surface.cc
@@ -1,9 +1,40 @@
#include "bcf_surface.h"
+#include "surface_port.h"
+#include "mackie_midi_builder.h"
#include <cmath>
using namespace Mackie;
+void BcfSurface::display_bank_start( SurfacePort & port, MackieMidiBuilder & builder, uint32_t current_bank )
+{
+ if ( current_bank == 0 )
+ {
+ // send Ar. to 2-char display on the master
+ port.write( builder.two_char_display( "Ar", ".." ) );
+ }
+ else
+ {
+ // write the current first remote_id to the 2-char display
+ port.write( builder.two_char_display( current_bank ) );
+ }
+}
+
+void BcfSurface::zero_all( SurfacePort & port, MackieMidiBuilder & builder )
+{
+ // clear 2-char display
+ port.write( builder.two_char_display( "LC" ) );
+
+ // and the led ring for the master strip
+ blank_jog_ring( port, builder );
+}
+
+void BcfSurface::blank_jog_ring( SurfacePort & port, MackieMidiBuilder & builder )
+{
+ Control & control = *controls_by_name["jog"];
+ port.write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
+}
+
float BcfSurface::scaled_delta( const ControlState & state, float current_speed )
{
return state.sign * ( std::pow( float(state.ticks + 1), 2 ) + current_speed ) / 100.0;
diff --git a/libs/surfaces/mackie/bcf_surface.h b/libs/surfaces/mackie/bcf_surface.h
index e6efa5ad1a..95bb27db01 100644
--- a/libs/surfaces/mackie/bcf_surface.h
+++ b/libs/surfaces/mackie/bcf_surface.h
@@ -21,8 +21,14 @@ public:
virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button );
virtual void init_controls();
+ virtual void display_bank_start( SurfacePort & port, MackieMidiBuilder & builder, uint32_t current_bank );
+ virtual void zero_all( SurfacePort & port, MackieMidiBuilder & builder );
+ virtual void blank_jog_ring( SurfacePort & port, MackieMidiBuilder & builder );
+ virtual bool has_timecode_display() const { return false; }
+
virtual float scrub_scaling_factor() { return 50.0; }
virtual float scaled_delta( const ControlState & state, float current_speed );
+
};
}
diff --git a/libs/surfaces/mackie/dummy_port.cc b/libs/surfaces/mackie/dummy_port.cc
new file mode 100644
index 0000000000..7654f8f987
--- /dev/null
+++ b/libs/surfaces/mackie/dummy_port.cc
@@ -0,0 +1,58 @@
+#include "dummy_port.h"
+
+#include "midi_byte_array.h"
+
+#include <midi++/port.h>
+#include <midi++/types.h>
+
+#include <iostream>
+
+using namespace Mackie;
+using namespace std;
+
+DummyPort::DummyPort()
+{
+}
+
+DummyPort::~DummyPort()
+{
+}
+
+
+void DummyPort::open()
+{
+ cout << "DummyPort::open" << endl;
+}
+
+
+void DummyPort::close()
+{
+ cout << "DummyPort::close" << endl;
+}
+
+
+MidiByteArray DummyPort::read()
+{
+ cout << "DummyPort::read" << endl;
+ return MidiByteArray();
+}
+
+
+void DummyPort::write( const MidiByteArray & mba )
+{
+ cout << "DummyPort::write " << mba << endl;
+}
+
+MidiByteArray empty_midi_byte_array;
+
+const MidiByteArray & DummyPort::sysex_hdr() const
+{
+ cout << "DummyPort::sysex_hdr" << endl;
+ return empty_midi_byte_array;
+}
+
+int DummyPort::strips() const
+{
+ cout << "DummyPort::strips" << endl;
+ return 0;
+}
diff --git a/libs/surfaces/mackie/dummy_port.h b/libs/surfaces/mackie/dummy_port.h
new file mode 100644
index 0000000000..4ed0a3043b
--- /dev/null
+++ b/libs/surfaces/mackie/dummy_port.h
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2008 John Anderson
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#ifndef dummy_port_h
+#define dummy_port_h
+
+#include "surface_port.h"
+
+#include "midi_byte_array.h"
+
+namespace MIDI {
+ class Port;
+}
+
+namespace Mackie
+{
+
+/**
+ A Dummy Port, to catch things that shouldn't be sent.
+*/
+class DummyPort : public SurfacePort
+{
+public:
+ DummyPort();
+ virtual ~DummyPort();
+
+ // when this is successful, active() should return true
+ virtual void open();
+
+ // subclasses should call this before doing their own close
+ virtual void close();
+
+ /// read bytes from the port. They'll either end up in the
+ /// parser, or if that's not active they'll be returned
+ virtual MidiByteArray read();
+
+ /// an easier way to output bytes via midi
+ virtual void write( const MidiByteArray & );
+
+ virtual const MidiByteArray & sysex_hdr() const;
+ virtual int strips() const;
+};
+
+}
+
+#endif
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index aac2a4a71e..39a1438f35 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -121,14 +121,28 @@ Mackie::Surface & MackieControlProtocol::surface()
return *_surface;
}
-const Mackie::MackiePort & MackieControlProtocol::mcu_port() const
+const Mackie::SurfacePort & MackieControlProtocol::mcu_port() const
{
- return dynamic_cast<const MackiePort &>( *_ports[0] );
+ if ( _ports.size() < 1 )
+ {
+ return _dummy_port;
+ }
+ else
+ {
+ return dynamic_cast<const MackiePort &>( *_ports[0] );
+ }
}
-Mackie::MackiePort & MackieControlProtocol::mcu_port()
+Mackie::SurfacePort & MackieControlProtocol::mcu_port()
{
- return dynamic_cast<const MackiePort &>( *_ports[0] );
+ if ( _ports.size() < 1 )
+ {
+ return _dummy_port;
+ }
+ else
+ {
+ return dynamic_cast<MackiePort &>( *_ports[0] );
+ }
}
// go to the previous track.
@@ -297,31 +311,13 @@ void MackieControlProtocol::switch_banks( int initial )
}
// display the current start bank.
- if ( mcu_port().emulation() == MackiePort::bcf2000 )
- {
- if ( _current_initial_bank == 0 )
- {
- // send Ar. to 2-char display on the master
- mcu_port().write( builder.two_char_display( "Ar", ".." ) );
- }
- else
- {
- // write the current first remote_id to the 2-char display
- mcu_port().write( builder.two_char_display( _current_initial_bank ) );
- }
- }
+ surface().display_bank_start( mcu_port(), builder, _current_initial_bank );
}
void MackieControlProtocol::zero_all()
{
// TODO turn off SMPTE displays
- if ( mcu_port().emulation() == MackiePort::bcf2000 )
- {
- // clear 2-char display
- mcu_port().write( builder.two_char_display( "LC" ) );
- }
-
// zero all strips
for ( Surface::Strips::iterator it = surface().strips.begin(); it != surface().strips.end(); ++it )
{
@@ -330,14 +326,7 @@ void MackieControlProtocol::zero_all()
}
// and the master strip
- mcu_port().write( builder.zero_strip( mcu_port(), master_strip() ) );
-
- // and the led ring for the master strip, in bcf mode
- if ( mcu_port().emulation() == MackiePort::bcf2000 )
- {
- Control & control = *surface().controls_by_name["jog"];
- mcu_port().write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
- }
+ mcu_port().write( builder.zero_strip( dynamic_cast<MackiePort&>( mcu_port() ), master_strip() ) );
// turn off global buttons and leds
// global buttons are only ever on mcu_port, so we don't have
@@ -350,6 +339,9 @@ void MackieControlProtocol::zero_all()
mcu_port().write( builder.zero_control( control ) );
}
}
+
+ // any hardware-specific stuff
+ surface().zero_all( mcu_port(), builder );
}
int MackieControlProtocol::set_active( bool yn )
@@ -472,7 +464,7 @@ void MackieControlProtocol::update_led( Mackie::Button & button, Mackie::LedStat
{
if ( ls != none )
{
- MackiePort * port = 0;
+ SurfacePort * port = 0;
if ( button.group().is_strip() )
{
if ( button.group().is_master() )
@@ -556,12 +548,8 @@ void MackieControlProtocol::update_surface()
// update strip from route
master_route_signal->notify_all();
- // turn off the led ring, for bcf emulation mode
- if ( mcu_port().emulation() == MackiePort::bcf2000 )
- {
- Control & control = *surface().controls_by_name["jog"];
- mcu_port().write( builder.build_led_ring( dynamic_cast<Pot &>( control ), off ) );
- }
+ // sometimes the jog wheel is a pot
+ surface().blank_jog_ring( mcu_port(), builder );
// update global buttons and displays
notify_record_state_changed();
@@ -595,34 +583,46 @@ void MackieControlProtocol::connect_session_signals()
void MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
{
#ifdef DEBUG
- cout << "add port " << midi_port.name() << ", " << midi_port.device() << endl;
+ cout << "add port " << midi_port.name() << ", " << midi_port.device() << ", " << midi_port.type() << endl;
+ cout << "MIDI::Port::ALSA_Sequencer " << MIDI::Port::ALSA_Sequencer << endl;
+ cout << "MIDI::Port::Unknown " << MIDI::Port::Unknown << endl;
#endif
-
- MackiePort * sport = new MackiePort( *this, midi_port, number );
- _ports.push_back( sport );
-
- connections_back = sport->init_event.connect(
- sigc::bind (
- mem_fun (*this, &MackieControlProtocol::handle_port_init)
- , sport
- )
- );
-
- connections_back = sport->active_event.connect(
- sigc::bind (
- mem_fun (*this, &MackieControlProtocol::handle_port_active)
- , sport
- )
- );
-
- connections_back = sport->inactive_event.connect(
- sigc::bind (
- mem_fun (*this, &MackieControlProtocol::handle_port_inactive)
- , sport
- )
- );
-
- _ports_changed = true;
+ if ( string( midi_port.device() ) == string( "ardour" ) )
+ {
+ throw MackieControlException( "The Mackie MCU driver will not use a port with device=ardour" );
+ }
+ else if ( midi_port.type() == MIDI::Port::ALSA_Sequencer )
+ {
+ throw MackieControlException( "alsa/sequencer ports don't work with the Mackie MCU driver right now" );
+ }
+ else
+ {
+ MackiePort * sport = new MackiePort( *this, midi_port, number );
+ _ports.push_back( sport );
+
+ connections_back = sport->init_event.connect(
+ sigc::bind (
+ mem_fun (*this, &MackieControlProtocol::handle_port_init)
+ , sport
+ )
+ );
+
+ connections_back = sport->active_event.connect(
+ sigc::bind (
+ mem_fun (*this, &MackieControlProtocol::handle_port_active)
+ , sport
+ )
+ );
+
+ connections_back = sport->inactive_event.connect(
+ sigc::bind (
+ mem_fun (*this, &MackieControlProtocol::handle_port_inactive)
+ , sport
+ )
+ );
+
+ _ports_changed = true;
+ }
}
void MackieControlProtocol::create_ports()
@@ -681,15 +681,23 @@ void MackieControlProtocol::initialize_surface()
set_route_table_size( strips );
- switch ( mcu_port().emulation() )
+ // TODO same as code in mackie_port.cc
+ string emulation = ARDOUR::Config->get_mackie_emulation();
+ if ( emulation == "bcf" )
{
- case MackiePort::bcf2000: _surface = new BcfSurface( strips ); break;
- case MackiePort::mackie: _surface = new MackieSurface( strips ); break;
- default:
- ostringstream os;
- os << "no Surface class found for emulation: " << mcu_port().emulation();
- throw MackieControlException( os.str() );
+ _surface = new BcfSurface( strips );
}
+ else if ( emulation == "mcu" )
+ {
+ _surface = new MackieSurface( strips );
+ }
+ else
+ {
+ ostringstream os;
+ os << "no Surface class found for emulation: " << emulation;
+ throw MackieControlException( os.str() );
+ }
+
_surface->init();
// Connect events. Must be after route table otherwise there will be trouble
@@ -1048,7 +1056,7 @@ void MackieControlProtocol::notify_name_changed( void *, RouteSignal * route_sig
line1 = PBD::short_version( fullname, 6 );
}
- MackiePort & port = route_signal->port();
+ SurfacePort & port = route_signal->port();
port.write( builder.strip_display( port, strip, 0, line1 ) );
port.write( builder.strip_display_blank( port, strip, 1 ) );
}
@@ -1157,30 +1165,33 @@ string MackieControlProtocol::format_smpte_timecode( nframes_t now_frame )
void MackieControlProtocol::update_timecode_display()
{
- // do assignment here so current_frame is fixed
- nframes_t current_frame = session->transport_frame();
- string timecode;
-
- switch ( _timecode_type )
- {
- case ARDOUR::AnyTime::BBT:
- timecode = format_bbt_timecode( current_frame );
- break;
- case ARDOUR::AnyTime::SMPTE:
- timecode = format_smpte_timecode( current_frame );
- break;
- default:
- ostringstream os;
- os << "Unknown timecode: " << _timecode_type;
- throw runtime_error( os.str() );
- }
-
- // only write the timecode string to the MCU if it's changed
- // since last time. This is to reduce midi bandwidth used.
- if ( timecode != _timecode_last )
+ if ( surface().has_timecode_display() )
{
- mcu_port().write( builder.timecode_display( mcu_port(), timecode, _timecode_last ) );
- _timecode_last = timecode;
+ // do assignment here so current_frame is fixed
+ nframes_t current_frame = session->transport_frame();
+ string timecode;
+
+ switch ( _timecode_type )
+ {
+ case ARDOUR::AnyTime::BBT:
+ timecode = format_bbt_timecode( current_frame );
+ break;
+ case ARDOUR::AnyTime::SMPTE:
+ timecode = format_smpte_timecode( current_frame );
+ break;
+ default:
+ ostringstream os;
+ os << "Unknown timecode: " << _timecode_type;
+ throw runtime_error( os.str() );
+ }
+
+ // only write the timecode string to the MCU if it's changed
+ // since last time. This is to reduce midi bandwidth used.
+ if ( timecode != _timecode_last )
+ {
+ surface().display_timecode( mcu_port(), builder, timecode, _timecode_last );
+ _timecode_last = timecode;
+ }
}
}
@@ -1200,11 +1211,7 @@ void MackieControlProtocol::poll_session_data()
update_automation( *master_route_signal );
}
- // and timecode display if it's a real mackie
- if ( mcu_port().emulation() == MackiePort::mackie )
- {
- update_timecode_display();
- }
+ update_timecode_display();
_automation_last.start();
}
@@ -1637,7 +1644,7 @@ LedState MackieControlProtocol::marker_release( Button & button )
return off;
}
-void jog_wheel_state_display( JogWheel::State state, MackiePort & port )
+void jog_wheel_state_display( JogWheel::State state, SurfacePort & port )
{
switch( state )
{
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 564a554a4b..d93f9c4c02 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -32,6 +32,7 @@
#include <control_protocol/control_protocol.h>
#include "midi_byte_array.h"
#include "controls.h"
+#include "dummy_port.h"
#include "route_signal.h"
#include "mackie_button_handler.h"
#include "mackie_port.h"
@@ -208,8 +209,8 @@ class MackieControlProtocol
/// This is the main MCU port, ie not an extender port
/// Only for use by JogWheel
- const Mackie::MackiePort & mcu_port() const;
- Mackie::MackiePort & mcu_port();
+ const Mackie::SurfacePort & mcu_port() const;
+ Mackie::SurfacePort & mcu_port();
ARDOUR::Session & get_session() { return *session; }
protected:
@@ -321,6 +322,9 @@ class MackieControlProtocol
typedef vector<Mackie::MackiePort*> MackiePorts;
MackiePorts _ports;
+ /// Sometimes the real port goes away, and we want to contain the breakage
+ Mackie::DummyPort _dummy_port;
+
// the thread that polls the ports for incoming midi data
pthread_t thread;
diff --git a/libs/surfaces/mackie/mackie_midi_builder.cc b/libs/surfaces/mackie/mackie_midi_builder.cc
index ce4eb1fda0..89a6ce7789 100644
--- a/libs/surfaces/mackie/mackie_midi_builder.cc
+++ b/libs/surfaces/mackie/mackie_midi_builder.cc
@@ -102,7 +102,7 @@ MidiByteArray MackieMidiBuilder::build_fader( const Fader & fader, float pos )
);
}
-MidiByteArray MackieMidiBuilder::zero_strip( MackiePort & port, const Strip & strip )
+MidiByteArray MackieMidiBuilder::zero_strip( SurfacePort & port, const Strip & strip )
{
Group::Controls::const_iterator it = strip.controls().begin();
MidiByteArray retval;
@@ -178,13 +178,13 @@ MidiByteArray MackieMidiBuilder::two_char_display( unsigned int value, const std
return two_char_display( os.str() );
}
-MidiByteArray MackieMidiBuilder::strip_display_blank( MackiePort & port, const Strip & strip, unsigned int line_number )
+MidiByteArray MackieMidiBuilder::strip_display_blank( SurfacePort & port, const Strip & strip, unsigned int line_number )
{
// 6 spaces, not 7 because strip_display adds a space where appropriate
return strip_display( port, strip, line_number, " " );
}
-MidiByteArray MackieMidiBuilder::strip_display( MackiePort & port, const Strip & strip, unsigned int line_number, const std::string & line )
+MidiByteArray MackieMidiBuilder::strip_display( SurfacePort & port, const Strip & strip, unsigned int line_number, const std::string & line )
{
if ( line_number > 1 )
{
@@ -227,7 +227,7 @@ MidiByteArray MackieMidiBuilder::strip_display( MackiePort & port, const Strip &
return retval;
}
-MidiByteArray MackieMidiBuilder::all_strips_display( MackiePort & port, std::vector<std::string> & lines1, std::vector<std::string> & lines2 )
+MidiByteArray MackieMidiBuilder::all_strips_display( SurfacePort & port, std::vector<std::string> & lines1, std::vector<std::string> & lines2 )
{
MidiByteArray retval;
retval << 0x12 << 0;
@@ -236,7 +236,7 @@ MidiByteArray MackieMidiBuilder::all_strips_display( MackiePort & port, std::vec
return retval;
}
-MidiByteArray MackieMidiBuilder::timecode_display( MackiePort & port, const std::string & timecode, const std::string & last_timecode )
+MidiByteArray MackieMidiBuilder::timecode_display( SurfacePort & port, const std::string & timecode, const std::string & last_timecode )
{
// if there's no change, send nothing, not even sysex header
if ( timecode == last_timecode ) return MidiByteArray();
diff --git a/libs/surfaces/mackie/mackie_midi_builder.h b/libs/surfaces/mackie/mackie_midi_builder.h
index 78bf4e5243..b5fc9f73c9 100644
--- a/libs/surfaces/mackie/mackie_midi_builder.h
+++ b/libs/surfaces/mackie/mackie_midi_builder.h
@@ -25,7 +25,7 @@
namespace Mackie
{
-class MackiePort;
+class SurfacePort;
/**
This knows how to build midi messages given a control and
@@ -64,8 +64,8 @@ public:
MidiByteArray build_fader( const Fader & fader, float pos );
/// return bytes that will reset all controls to their zero positions
- /// And blank the display for the strip. Pass MackiePort so we know which sysex header to use.
- MidiByteArray zero_strip( MackiePort &, const Strip & strip );
+ /// And blank the display for the strip. Pass SurfacePort so we know which sysex header to use.
+ MidiByteArray zero_strip( SurfacePort &, const Strip & strip );
// provide bytes to zero the given control
MidiByteArray zero_control( const Control & control );
@@ -81,19 +81,19 @@ public:
be encoded, to save midi bandwidth. If they're the same, an empty array will
be returned
*/
- MidiByteArray timecode_display( MackiePort &, const std::string & timecode, const std::string & last_timecode = "" );
+ MidiByteArray timecode_display( SurfacePort &, const std::string & timecode, const std::string & last_timecode = "" );
/**
for displaying characters on the strip LCD
- pass MackiePort so we know which sysex header to use
+ pass SurfacePort so we know which sysex header to use
*/
- MidiByteArray strip_display( MackiePort &, const Strip & strip, unsigned int line_number, const std::string & line );
+ MidiByteArray strip_display( SurfacePort &, const Strip & strip, unsigned int line_number, const std::string & line );
- /// blank the strip LCD, ie write all spaces. Pass MackiePort so we know which sysex header to use.
- MidiByteArray strip_display_blank( MackiePort &, const Strip & strip, unsigned int line_number );
+ /// blank the strip LCD, ie write all spaces. Pass SurfacePort so we know which sysex header to use.
+ MidiByteArray strip_display_blank( SurfacePort &, const Strip & strip, unsigned int line_number );
- /// for generating all strip names. Pass MackiePort so we know which sysex header to use.
- MidiByteArray all_strips_display( MackiePort &, std::vector<std::string> & lines1, std::vector<std::string> & lines2 );
+ /// for generating all strip names. Pass SurfacePort so we know which sysex header to use.
+ MidiByteArray all_strips_display( SurfacePort &, std::vector<std::string> & lines1, std::vector<std::string> & lines2 );
protected:
static MIDI::byte calculate_pot_value( midi_pot_mode mode, const ControlState & );
diff --git a/libs/surfaces/mackie/mackie_port.cc b/libs/surfaces/mackie/mackie_port.cc
index 080478d199..d9ced05da3 100644
--- a/libs/surfaces/mackie/mackie_port.cc
+++ b/libs/surfaces/mackie/mackie_port.cc
@@ -249,6 +249,7 @@ void MackiePort::finalise_init( bool yn )
// if an mcu and a bcf are needed to work as one surface
if ( _emulation == none )
{
+ // TODO same as code in mackie_control_protocol.cc
if ( ARDOUR::Config->get_mackie_emulation() == "bcf" )
{
_emulation = bcf2000;
diff --git a/libs/surfaces/mackie/mackie_surface.cc b/libs/surfaces/mackie/mackie_surface.cc
index 9745c79afc..dbba726062 100644
--- a/libs/surfaces/mackie/mackie_surface.cc
+++ b/libs/surfaces/mackie/mackie_surface.cc
@@ -1,9 +1,17 @@
#include "mackie_surface.h"
+#include "surface_port.h"
+#include "mackie_midi_builder.h"
#include <cmath>
+#include <string>
using namespace Mackie;
+void MackieSurface::display_timecode( SurfacePort & port, MackieMidiBuilder & builder, const std::string & timecode, const std::string & timecode_last )
+{
+ port.write( builder.timecode_display( port, timecode, timecode_last ) );
+}
+
float MackieSurface::scaled_delta( const ControlState & state, float current_speed )
{
return state.sign * ( std::pow( float(state.ticks + 1), 2 ) + current_speed ) / 100.0;
diff --git a/libs/surfaces/mackie/mackie_surface.h b/libs/surfaces/mackie/mackie_surface.h
index 6a7fb7bdf1..b3bfb3b6d4 100644
--- a/libs/surfaces/mackie/mackie_surface.h
+++ b/libs/surfaces/mackie/mackie_surface.h
@@ -10,7 +10,6 @@ namespace Mackie
{
class MackieButtonHandler;
-
class MackieSurface : public Surface
{
public:
@@ -21,6 +20,9 @@ public:
virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button );
virtual void init_controls();
+ virtual bool has_timecode_display() const { return true; }
+ virtual void display_timecode( SurfacePort &, MackieMidiBuilder &, const std::string & timecode, const std::string & timecode_last );
+
virtual float scrub_scaling_factor() { return 100.0; }
virtual float scaled_delta( const ControlState & state, float current_speed );
};
diff --git a/libs/surfaces/mackie/route_signal.h b/libs/surfaces/mackie/route_signal.h
index 6d79938ab0..01b3c97c16 100644
--- a/libs/surfaces/mackie/route_signal.h
+++ b/libs/surfaces/mackie/route_signal.h
@@ -34,7 +34,7 @@ namespace Mackie
{
class Strip;
-class MackiePort;
+class SurfacePort;
/**
This class is intended to easily create and destroy the set of
@@ -45,7 +45,7 @@ class MackiePort;
class RouteSignal
{
public:
- RouteSignal( ARDOUR::Route & route, MackieControlProtocol & mcp, Strip & strip, MackiePort & port )
+ RouteSignal( ARDOUR::Route & route, MackieControlProtocol & mcp, Strip & strip, SurfacePort & port )
: _route( route ), _mcp( mcp ), _strip( strip ), _port( port ), _last_gain_written(0.0)
{
connect();
@@ -64,7 +64,7 @@ public:
const ARDOUR::Route & route() const { return _route; }
Strip & strip() { return _strip; }
- MackiePort & port() { return _port; }
+ SurfacePort & port() { return _port; }
float last_gain_written() const { return _last_gain_written; }
void last_gain_written( float other ) { _last_gain_written = other; }
@@ -76,7 +76,7 @@ private:
ARDOUR::Route & _route;
MackieControlProtocol & _mcp;
Strip & _strip;
- MackiePort & _port;
+ SurfacePort & _port;
typedef std::vector<sigc::connection> Connections;
Connections _connections;
diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h
index 42ba6f907c..5305fe7eb8 100644
--- a/libs/surfaces/mackie/surface.h
+++ b/libs/surfaces/mackie/surface.h
@@ -9,6 +9,8 @@ namespace Mackie
{
class MackieButtonHandler;
+class SurfacePort;
+class MackieMidiBuilder;
/**
This represents an entire control surface, made up of Groups,
@@ -83,6 +85,20 @@ public:
virtual void handle_button( MackieButtonHandler & mbh, ButtonState bs, Button & button ) = 0;
public:
+ /// display an indicator of the first switched-in Route. Do nothing by default.
+ virtual void display_bank_start( SurfacePort &, MackieMidiBuilder &, uint32_t current_bank ) {};
+
+ /// called from MackieControlPRotocol::zero_all to turn things off
+ virtual void zero_all( SurfacePort &, MackieMidiBuilder & ) {};
+
+ /// turn off leds around the jog wheel. This is for surfaces that use a pot
+ /// pretending to be a jog wheel.
+ virtual void blank_jog_ring( SurfacePort &, MackieMidiBuilder & ) {};
+
+ virtual bool has_timecode_display() const = 0;
+ virtual void display_timecode( SurfacePort &, MackieMidiBuilder &, const std::string & timecode, const std::string & timecode_last ) {};
+
+public:
/**
This is used to calculate the clicks per second that define
a transport speed of 1.0 for the jog wheel. 100.0 is 10 clicks
diff --git a/libs/surfaces/mackie/surface_port.cc b/libs/surfaces/mackie/surface_port.cc
index 448fbb40c8..4d1fbc254b 100644
--- a/libs/surfaces/mackie/surface_port.cc
+++ b/libs/surfaces/mackie/surface_port.cc
@@ -35,8 +35,13 @@
using namespace std;
using namespace Mackie;
+SurfacePort::SurfacePort()
+: _port( 0 ), _number( 0 ), _active( false )
+{
+}
+
SurfacePort::SurfacePort( MIDI::Port & port, int number )
-: _port( port ), _number( number ), _active( false )
+: _port( &port ), _number( number ), _active( false )
{
}
@@ -142,9 +147,8 @@ void SurfacePort::write( const MidiByteArray & mba )
os << "Surface: couldn't write to port " << port().name();
os << ", error: " << fetch_errmsg( errno ) << "(" << errno << ")";
- cout << os.str();
+ cout << os.str() << endl;
inactive_event();
- throw MackieControlException( os.str() );
}
}
#ifdef PORT_DEBUG
diff --git a/libs/surfaces/mackie/surface_port.h b/libs/surfaces/mackie/surface_port.h
index 87419f1bcd..421446df68 100644
--- a/libs/surfaces/mackie/surface_port.h
+++ b/libs/surfaces/mackie/surface_port.h
@@ -48,20 +48,20 @@ public:
/// read bytes from the port. They'll either end up in the
/// parser, or if that's not active they'll be returned
- MidiByteArray read();
+ virtual MidiByteArray read();
/// an easier way to output bytes via midi
- void write( const MidiByteArray & );
+ virtual void write( const MidiByteArray & );
/// write a sysex message
void write_sysex( const MidiByteArray & mba );
void write_sysex( MIDI::byte msg );
- // return the correct sysex header for this port
+ /// return the correct sysex header for this port
virtual const MidiByteArray & sysex_hdr() const = 0;
- MIDI::Port & port() { return _port; }
- const MIDI::Port & port() const { return _port; }
+ MIDI::Port & port() { return *_port; }
+ const MIDI::Port & port() const { return *_port; }
// all control notofications are sent from here
sigc::signal<void, SurfacePort &, Control &, const ControlState &> control_event;
@@ -85,8 +85,12 @@ public:
virtual bool active() const { return _active; }
virtual void active( bool yn ) { _active = yn; }
+protected:
+ /// Only for use by DummyPort
+ SurfacePort();
+
private:
- MIDI::Port & _port;
+ MIDI::Port * _port;
int _number;
bool _active;