diff options
Diffstat (limited to 'libs/surfaces/mackie')
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.cc | 91 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol.h | 11 | ||||
-rw-r--r-- | libs/surfaces/mackie/mackie_control_protocol_poll.cc | 5 |
3 files changed, 100 insertions, 7 deletions
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 502cea581f..f7886e078f 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -1030,9 +1030,9 @@ void MackieControlProtocol::update_automation( RouteSignal & rs ) } } -void MackieControlProtocol::poll_automation() +void MackieControlProtocol::poll_automation () { - if ( _active ) + if ( _active && _automation_last.elapsed() >= 20 ) { // do all currently mapped routes for( RouteSignals::iterator it = route_signals.begin(); it != route_signals.end(); ++it ) @@ -1041,7 +1041,92 @@ void MackieControlProtocol::poll_automation() } // and the master strip - if ( master_route_signal != 0 ) update_automation( *master_route_signal ); + if ( master_route_signal != 0 ) + { + update_automation( *master_route_signal ); + } + + update_timecode_display(); + + _automation_last.start(); + } +} + +string MackieControlProtocol::format_bbt_timecode( nframes_t now_frame ) +{ + BBT_Time bbt_time; + session->bbt_time( now_frame, bbt_time ); + + // According to the Logic docs + // digits: 888/88/88/888 + // BBT mode: Bars/Beats/Subdivisions/Ticks + ostringstream os; + os << setw(3) << setfill('0') << bbt_time.bars; + os << setw(2) << setfill('0') << bbt_time.beats; + + // figure out subdivisions per beat + const Meter & meter = session->tempo_map().meter_at( now_frame ); + int subdiv = 2; + if ( meter.note_divisor() == 8 && (meter.beats_per_bar() == 12.0 || meter.beats_per_bar() == 9.0 || meter.beats_per_bar() == 6.0) ) + { + subdiv = 3; + } + + uint32_t subdivisions = bbt_time.ticks / uint32_t( Meter::ticks_per_beat / subdiv ); + uint32_t ticks = bbt_time.ticks % uint32_t( Meter::ticks_per_beat / subdiv ); + + os << setw(2) << setfill('0') << subdivisions + 1; + os << setw(3) << setfill('0') << ticks; + + return os.str(); +} + +string MackieControlProtocol::format_smpte_timecode( nframes_t now_frame ) +{ + SMPTE::Time smpte; + session->smpte_time( now_frame, smpte ); + + // According to the Logic docs + // digits: 888/88/88/888 + // SMPTE mode: Hours/Minutes/Seconds/Frames + ostringstream os; + os << setw(3) << setfill('0') << smpte.hours; + os << setw(2) << setfill('0') << smpte.minutes; + os << setw(2) << setfill('0') << smpte.seconds; + os << setw(3) << setfill('0') << smpte.frames; + + return os.str(); +} + +void MackieControlProtocol::update_timecode_display() +{ + if ( surface().has_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 ) + { + surface().display_timecode( mcu_port(), builder, timecode, _timecode_last ); + _timecode_last = timecode; + } } } diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index 0ff7fbd9d4..735a2c88bd 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -255,12 +255,19 @@ class MackieControlProtocol void add_port( MIDI::Port &, int number ); - /// read automation data from the currently active routes and send to surface - void poll_automation(); + /** + Read session data and send to surface. Includes + automation from the currently active routes and + timecode displays. + */ + void poll_automation (); // called from poll_automation to figure out which automations need to be sent void update_automation( Mackie::RouteSignal & ); + // also called from poll_automation to update timecode display + void update_timecode_display(); + /** notification that the port is about to start it's init sequence. We must make sure that before this exits, the port is being polled diff --git a/libs/surfaces/mackie/mackie_control_protocol_poll.cc b/libs/surfaces/mackie/mackie_control_protocol_poll.cc index cf72c35678..cd95551f70 100644 --- a/libs/surfaces/mackie/mackie_control_protocol_poll.cc +++ b/libs/surfaces/mackie/mackie_control_protocol_poll.cc @@ -33,8 +33,7 @@ bool MackieControlProtocol::probe() void * MackieControlProtocol::monitor_work() { - // What does ThreadCreatedWithRequestSize do? - PBD::ThreadCreated (pthread_self(), X_("Mackie")); + PBD::notify_gui_about_thread_creation (pthread_self(), X_("Mackie")); pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0); pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); @@ -105,6 +104,8 @@ void MackieControlProtocol::read_ports() for ( int p = 0; p < nfds; ++p ) { // this will cause handle_midi_any in the MackiePort to be triggered + // for alsa/raw ports + // alsa/sequencer ports trigger the midi parser off poll if ( (pfd[p].revents & POLLIN) > 0 ) { // avoid deadlocking? |