move ownership of LTC I/O ports to Session, and manage as IO objects
[ardour.git] / libs / ardour / midi_diskstream.cc
index fd6e1707dbe3ae8a0af96ffad6ccf705407ed2d1..64f02b0ad9c59a520c0d4c973c179d26f7ed4964 100644 (file)
 
 #include "pbd/error.h"
 #include "pbd/basename.h"
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include "pbd/xml++.h"
 #include "pbd/memento_command.h"
 #include "pbd/enumwriter.h"
 #include "pbd/stateful_diff_command.h"
 #include "pbd/stacktrace.h"
 
-#include "ardour/ardour.h"
 #include "ardour/audioengine.h"
 #include "ardour/butler.h"
-#include "ardour/configuration.h"
-#include "ardour/cycle_timer.h"
 #include "ardour/debug.h"
 #include "ardour/io.h"
 #include "ardour/midi_diskstream.h"
 #include "ardour/midi_region.h"
 #include "ardour/playlist_factory.h"
 #include "ardour/region_factory.h"
-#include "ardour/route.h"
-#include "ardour/send.h"
 #include "ardour/session.h"
 #include "ardour/session_playlists.h"
 #include "ardour/smf_source.h"
+#include "ardour/types.h"
 #include "ardour/utils.h"
 
 #include "midi++/types.h"
@@ -135,7 +131,7 @@ MidiDiskstream::init ()
 
 MidiDiskstream::~MidiDiskstream ()
 {
-       Glib::Mutex::Lock lm (state_lock);
+       Glib::Threads::Mutex::Lock lm (state_lock);
 }
 
 
@@ -153,7 +149,7 @@ void
 MidiDiskstream::non_realtime_input_change ()
 {
        {
-               Glib::Mutex::Lock lm (state_lock);
+               Glib::Threads::Mutex::Lock lm (state_lock);
 
                if (input_change_pending.type == IOChange::NoChange) {
                        return;
@@ -305,175 +301,6 @@ MidiDiskstream::set_note_mode (NoteMode m)
                _write_source->model()->set_note_mode(m);
 }
 
-#if 0
-static void
-trace_midi (ostream& o, MIDI::byte *msg, size_t len)
-{
-       using namespace MIDI;
-       eventType type;
-       const char trace_prefix = ':';
-
-       type = (eventType) (msg[0]&0xF0);
-
-       switch (type) {
-       case off:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  << " NoteOff NoteNum "
-                  << (int) msg[1]
-                  << " Vel "
-                  << (int) msg[2]
-                  << endl;
-               break;
-
-       case on:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  << " NoteOn NoteNum "
-                  << (int) msg[1]
-                  << " Vel "
-                  << (int) msg[2]
-                  << endl;
-               break;
-
-       case polypress:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  << " PolyPressure"
-                  << (int) msg[1]
-                  << endl;
-               break;
-
-       case MIDI::controller:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  << " Controller "
-                  << (int) msg[1]
-                  << " Value "
-                  << (int) msg[2]
-                  << endl;
-               break;
-
-       case program:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  <<  " Program Change ProgNum "
-                  << (int) msg[1]
-                  << endl;
-               break;
-
-       case chanpress:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  << " Channel Pressure "
-                  << (int) msg[1]
-                  << endl;
-               break;
-
-       case MIDI::pitchbend:
-               o << trace_prefix
-                  << "Channel "
-                  << (msg[0]&0xF)+1
-                  << " Pitch Bend "
-                  << ((msg[2]<<7)|msg[1])
-                  << endl;
-               break;
-
-       case MIDI::sysex:
-               if (len == 1) {
-                       switch (msg[0]) {
-                       case 0xf8:
-                               o << trace_prefix
-                                  << "Clock"
-                                  << endl;
-                               break;
-                       case 0xfa:
-                               o << trace_prefix
-                                  << "Start"
-                                  << endl;
-                               break;
-                       case 0xfb:
-                               o << trace_prefix
-                                  << "Continue"
-                                  << endl;
-                               break;
-                       case 0xfc:
-                               o << trace_prefix
-                                  << "Stop"
-                                  << endl;
-                               break;
-                       case 0xfe:
-                               o << trace_prefix
-                                  << "Active Sense"
-                                  << endl;
-                               break;
-                       case 0xff:
-                               o << trace_prefix
-                                  << "System Reset"
-                                  << endl;
-                               break;
-                       default:
-                               o << trace_prefix
-                                  << "System Exclusive (1 byte : " << hex << (int) *msg << dec << ')'
-                                  << endl;
-                               break;
-                       }
-               } else {
-                       o << trace_prefix
-                          << "System Exclusive (" << len << ") = [ " << hex;
-                       for (unsigned int i = 0; i < len; ++i) {
-                               o << (int) msg[i] << ' ';
-                       }
-                       o << dec << ']' << endl;
-
-               }
-               break;
-
-       case MIDI::song:
-               o << trace_prefix << "Song" << endl;
-               break;
-
-       case MIDI::tune:
-               o << trace_prefix << "Tune" << endl;
-               break;
-
-       case MIDI::eox:
-               o << trace_prefix << "End-of-System Exclusive" << endl;
-               break;
-
-       case MIDI::timing:
-               o << trace_prefix << "Timing" << endl;
-               break;
-
-       case MIDI::start:
-               o << trace_prefix << "Start" << endl;
-               break;
-
-       case MIDI::stop:
-               o << trace_prefix << "Stop" << endl;
-               break;
-
-       case MIDI::contineu:
-               o << trace_prefix << "Continue" << endl;
-               break;
-
-       case active:
-               o << trace_prefix << "Active Sense" << endl;
-               break;
-
-       default:
-               o << trace_prefix << "Unrecognized MIDI message" << endl;
-               break;
-       }
-}
-#endif
-
 int
 MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, framecnt_t& playback_distance)
 {
@@ -499,7 +326,7 @@ MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, framecnt
                return 1;
        }
 
-       Glib::Mutex::Lock sm (state_lock, Glib::TRY_LOCK);
+       Glib::Threads::Mutex::Lock sm (state_lock, Glib::Threads::TRY_LOCK);
 
        if (!sm.locked()) {
                return 1;
@@ -508,7 +335,7 @@ MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, framecnt
        adjust_capture_position = 0;
 
        if (nominally_recording || (re && was_recording && _session.get_record_enabled() && _session.config.get_punch_in())) {
-               OverlapType ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
+               Evoral::OverlapType ot = Evoral::coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
 
                calculate_record_range(ot, transport_frame, nframes, rec_nframes, rec_offset);
 
@@ -549,7 +376,7 @@ MidiDiskstream::process (framepos_t transport_frame, pframes_t nframes, framecnt
                }
 
                if (buf.size() != 0) {
-                       Glib::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::TRY_LOCK);
+                       Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK);
 
                        if (lm.locked ()) {
                                /* Copy this data into our GUI feed buffer and tell the GUI
@@ -623,13 +450,26 @@ MidiDiskstream::commit (framecnt_t playback_distance)
 
        uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
        uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
-       if ((frames_written - frames_read) + playback_distance < midi_readahead) {
-               need_butler = true;
+
+       /*
+         cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read <<
+         " = " << frames_written - frames_read
+         << " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl;
+       */
+
+       /* frames_read will generally be less than frames_written, but
+        * immediately after an overwrite, we can end up having read some data
+        * before we've written any. we don't need to trip an assert() on this,
+        * but we do need to check so that the decision on whether or not we
+        * need the butler is done correctly.
+        */
+       
+       if (frames_read <= frames_written) {
+               if ((frames_written - frames_read) + playback_distance < midi_readahead) {
+                       need_butler = true;
+               }
        }
 
-       /*cerr << "MDS written: " << frames_written << " - read: " << frames_read <<
-               " = " << frames_written - frames_read
-               << " + " << nframes << " < " << midi_readahead << " = " << need_butler << ")" << endl;*/
 
        return need_butler;
 }
@@ -663,9 +503,17 @@ MidiDiskstream::overwrite_existing_buffers ()
 int
 MidiDiskstream::seek (framepos_t frame, bool complete_refill)
 {
-       Glib::Mutex::Lock lm (state_lock);
+       Glib::Threads::Mutex::Lock lm (state_lock);
        int ret = -1;
 
+       if (g_atomic_int_get (&_frames_read_from_ringbuffer) == 0) {
+               /* we haven't read anything since the last seek,
+                  so flush all note trackers to prevent
+                  wierdness
+               */
+               reset_tracker ();
+       }
+
        _playback_buf->reset();
        _capture_buf->reset();
        g_atomic_int_set(&_frames_read_from_ringbuffer, 0);
@@ -766,7 +614,7 @@ MidiDiskstream::read (framepos_t& start, framecnt_t dur, bool reversed)
                        return -1;
                }
 
-               g_atomic_int_add(&_frames_written_to_ringbuffer, this_read);
+               g_atomic_int_add (&_frames_written_to_ringbuffer, this_read);
 
                if (reversed) {
 
@@ -941,7 +789,7 @@ MidiDiskstream::transport_stopped_wallclock (struct tm& /*when*/, time_t /*twhen
        }
 
        /* XXX is there anything we can do if err != 0 ? */
-       Glib::Mutex::Lock lm (capture_info_lock);
+       Glib::Threads::Mutex::Lock lm (capture_info_lock);
 
        if (capture_info.empty()) {
                goto no_capture_stuff_to_do;
@@ -1429,6 +1277,13 @@ MidiDiskstream::use_pending_capture_data (XMLNode& /*node*/)
        return 0;
 }
 
+void
+MidiDiskstream::flush_playback (framepos_t start, framepos_t end)
+{
+       _playback_buf->flush (start, end);
+       g_atomic_int_add (&_frames_read_from_ringbuffer, end - start);
+}
+
 /** Writes playback events from playback_sample for nframes to dst, translating time stamps
  *  so that an event at playback_sample has time = 0
  */
@@ -1475,7 +1330,7 @@ MidiDiskstream::get_gui_feed_buffer () const
 {
        boost::shared_ptr<MidiBuffer> b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)));
        
-       Glib::Mutex::Lock lm (_gui_feed_buffer_mutex);
+       Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex);
        b->copy (_gui_feed_buffer);
        return b;
 }