diff options
author | John Anderson <ardour@semiosix.com> | 2008-01-05 12:00:52 +0000 |
---|---|---|
committer | John Anderson <ardour@semiosix.com> | 2008-01-05 12:00:52 +0000 |
commit | 8134233249158635f5a44c41f4f7d57b94526a46 (patch) | |
tree | 1eca9330fadb3bea4884bd5775e1f745bc3a9df8 /libs/surfaces | |
parent | 56d529290af04cd70e66b914cfbe67fdd00ebaa0 (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/SConscript | 5 | ||||
-rw-r--r-- | libs/surfaces/mackie/TODO | 16 | ||||
-rw-r--r-- | libs/surfaces/mackie/bcf_surface.cc | 31 | ||||
-rw-r--r-- | libs/surfaces/mackie/bcf_surface.h | 6 | ||||
-rw-r--r-- | libs/surfaces/mackie/dummy_port.cc | 58 | ||||
-rw-r--r-- | libs/surfaces/mackie/dummy_port.h | 60 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.cc | 211 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.h | 8 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_midi_builder.cc | 10 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_midi_builder.h | 20 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_port.cc | 1 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_surface.cc | 8 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_surface.h | 4 | ||||
-rw-r--r-- | libs/surfaces/mackie/route_signal.h | 8 | ||||
-rw-r--r-- | libs/surfaces/mackie/surface.h | 16 | ||||
-rw-r--r-- | libs/surfaces/mackie/surface_port.cc | 10 | ||||
-rw-r--r-- | libs/surfaces/mackie/surface_port.h | 16 |
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; |