Removed excessive debug printing, added missing files for SMPTE namespace and Jack...
authorDavid Robillard <d@drobilla.net>
Fri, 9 Jun 2006 01:48:38 +0000 (01:48 +0000)
committerDavid Robillard <d@drobilla.net>
Fri, 9 Jun 2006 01:48:38 +0000 (01:48 +0000)
git-svn-id: svn://localhost/ardour2/branches/midi@577 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/ardour/ardour/smpte.h [new file with mode: 0644]
libs/ardour/session_midi.cc
libs/ardour/session_process.cc
libs/ardour/smpte.cc [new file with mode: 0644]
libs/midi++2/jack_midiport.cc [new file with mode: 0644]
libs/midi++2/midi++/jack.h [new file with mode: 0644]

diff --git a/libs/ardour/ardour/smpte.h b/libs/ardour/ardour/smpte.h
new file mode 100644 (file)
index 0000000..6a7684c
--- /dev/null
@@ -0,0 +1,76 @@
+/*  Copyright (C) 2006 Paul Davis 
+
+    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.,
+    51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef __ardour_smpte_h__
+#define __ardour_smpte_h__
+
+#include <inttypes.h>
+
+namespace SMPTE {
+
+enum Wrap {
+       NONE = 0,
+       FRAMES,
+       SECONDS,
+       MINUTES,
+       HOURS
+};
+
+// FIXME: make this a float
+enum FPS {
+    MTC_24_FPS = 0,
+    MTC_25_FPS = 1,
+    MTC_30_FPS_DROP = 2,
+    MTC_30_FPS = 3
+};
+
+struct Time {
+       bool       negative;
+       uint32_t   hours;
+       uint32_t   minutes;
+       uint32_t   seconds;
+       uint32_t   frames;       ///< SMPTE frames (not audio samples)
+       uint32_t   subframes;    ///< Typically unused
+       FPS        rate;         ///< Frame rate of this Time
+       static FPS default_rate; ///< Rate to use for default constructor
+
+       Time(FPS a_rate = default_rate) {
+               negative = false;
+               hours = 0;
+               minutes = 0;
+               seconds = 0;
+               frames = 0;
+               subframes = 0;
+               rate = a_rate;
+       }
+};
+
+Wrap increment( Time& smpte );
+Wrap decrement( Time& smpte );
+Wrap increment_subframes( Time& smpte );
+Wrap decrement_subframes( Time& smpte );
+Wrap increment_seconds( Time& smpte );
+Wrap increment_minutes( Time& smpte );
+Wrap increment_hours( Time& smpte );
+void frames_floor( Time& smpte );
+void seconds_floor( Time& smpte );
+void minutes_floor( Time& smpte );
+void hours_floor( Time& smpte );
+
+} // namespace SMPTE
+
+#endif  // __ardour_smpte_h__
index 95d6d02f39cc052682e0fa29d38fc927d0acc5c8..bb3c0018df9c68d2babc01b53b1e1e98c2c6083b 100644 (file)
@@ -22,6 +22,7 @@
 #include <string>
 #include <cmath>
 #include <cerrno>
+#include <cassert>
 #include <unistd.h>
 #include <fcntl.h>
 #include <poll.h>
index bbd35a9055d799515c55a8554f59e25f204fcc35..2f35bbfee2d6ffdcbdac83e2de15aea70dffadca 100644 (file)
@@ -49,7 +49,7 @@ using namespace std;
 void
 Session::process (jack_nframes_t nframes)
 {
-       cerr << "CYCLE START " << _transport_frame << "-------------------" << endl;
+       //cerr << "CYCLE START " << _transport_frame << "-------------------" << endl;
        
        MIDI::Manager::instance()->cycle_start(nframes);
 
@@ -69,7 +69,7 @@ Session::process (jack_nframes_t nframes)
        
        MIDI::Manager::instance()->cycle_end();
        
-       cerr << "CYCLE END " << _transport_frame << "-----------------------" << endl;
+       //cerr << "CYCLE END " << _transport_frame << "-----------------------" << endl;
 }
 
 void
@@ -87,8 +87,6 @@ Session::no_roll (jack_nframes_t nframes, jack_nframes_t offset)
        int ret = 0;
        bool declick = get_transport_declick_required();
 
-       cerr << "[DR] no_roll\n";
-
        if (_click_io) {
                _click_io->silence (nframes, offset);
        }
@@ -261,8 +259,6 @@ Session::process_with_events (jack_nframes_t nframes)
        long           frames_moved;
        bool           session_needs_butler = false;
 
-       cerr << "[DR] with events" << endl;
-
        if (auditioner) {
                auditioner->silence (nframes, 0);
        }
@@ -741,8 +737,6 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
 void
 Session::process_without_events (jack_nframes_t nframes)
 {
-       cerr << "[DR] without events" << endl;
-
        bool session_needs_butler = false;
        jack_nframes_t stop_limit;
        long frames_moved;
diff --git a/libs/ardour/smpte.cc b/libs/ardour/smpte.cc
new file mode 100644 (file)
index 0000000..17e5a6b
--- /dev/null
@@ -0,0 +1,406 @@
+/*  Copyright (C) 2006 Paul Davis 
+
+    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.,
+    51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#define SMPTE_IS_AROUND_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours)
+#define SMPTE_IS_ZERO( sm ) (!(sm).frames && !(sm).seconds && !(sm).minutes && !(sm).hours && !(sm.subframes))
+
+#include <ardour/smpte.h>
+
+namespace SMPTE {
+
+FPS Time::default_rate = MTC_30_FPS;
+
+
+/** Increment @a smpte by exactly one frame (keep subframes value).
+ * Realtime safe.
+ * @return true if seconds wrap.
+ */
+Wrap
+increment( Time& smpte )
+{
+       //Wrap wrap = NONE;
+       Wrap wrap = NONE;
+
+       if (smpte.negative) {
+               if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) {
+                       // We have a zero transition involving only subframes
+                       smpte.subframes = 80 - smpte.subframes;
+                       smpte.negative = false;
+                       return SECONDS;
+               }
+    
+               smpte.negative = false;
+               wrap = decrement( smpte );
+               if (!SMPTE_IS_ZERO( smpte )) {
+                       smpte.negative = true;
+               }
+               return wrap;
+       }
+  
+       switch (smpte.rate) {
+       case MTC_24_FPS:
+               if (smpte.frames == 23) {
+                       smpte.frames = 0;
+                       wrap = SECONDS;
+               }
+               break;
+       case MTC_25_FPS:
+               if (smpte.frames == 24) {
+                       smpte.frames = 0;
+                       wrap = SECONDS;
+               }
+               break;
+       case MTC_30_FPS_DROP:
+               if (smpte.frames == 29) {
+                       if ( ((smpte.minutes + 1) % 10) && (smpte.seconds == 59) ) {
+                               smpte.frames = 2;
+                       }
+                       else {
+                               smpte.frames = 0;
+                       }
+                       wrap = SECONDS;
+               }
+               break;
+       case MTC_30_FPS:
+               if (smpte.frames == 29) {
+                       smpte.frames = 0;
+                       wrap = SECONDS;
+               }
+               break;
+       }
+  
+       if (wrap == SECONDS) {
+               if (smpte.seconds == 59) {
+                       smpte.seconds = 0;
+                       wrap = MINUTES;
+                       if (smpte.minutes == 59) {
+                               smpte.minutes = 0;
+                               wrap = HOURS;
+                               smpte.hours++;
+                       } else {
+                               smpte.minutes++;
+                       }
+               } else {
+                       smpte.seconds++;
+               }
+       } else {
+               smpte.frames++;
+       }
+  
+       return wrap;
+}
+
+
+/** Decrement @a smpte by exactly one frame (keep subframes value)
+ * Realtime safe.
+ * @return true if seconds wrap. */
+Wrap
+decrement( Time& smpte )
+{
+       Wrap wrap = NONE;
+  
+  
+       if (smpte.negative || SMPTE_IS_ZERO(smpte)) {
+               smpte.negative = false;
+               wrap = increment( smpte );
+               smpte.negative = true;
+               return wrap;
+       } else if (SMPTE_IS_AROUND_ZERO(smpte) && smpte.subframes) {
+               // We have a zero transition involving only subframes
+               smpte.subframes = 80 - smpte.subframes;
+               smpte.negative = true;
+               return SECONDS;
+       }
+  
+       switch (smpte.rate) {
+       case MTC_24_FPS:
+               if (smpte.frames == 0) {
+                       smpte.frames = 23;
+                       wrap = SECONDS;
+               }
+               break;
+       case MTC_25_FPS:
+               if (smpte.frames == 0) {
+                       smpte.frames = 24;
+                       wrap = SECONDS;
+               }
+               break;
+       case MTC_30_FPS_DROP:
+               if ((smpte.minutes % 10) && (smpte.seconds == 0)) {
+                       if (smpte.frames <= 2) {
+                               smpte.frames = 29;
+                               wrap = SECONDS;
+                       }
+               } else if (smpte.frames == 0) {
+                       smpte.frames = 29;
+                       wrap = SECONDS;
+               }
+               break;
+       case MTC_30_FPS:
+               if (smpte.frames == 0) {
+                       smpte.frames = 29;
+                       wrap = SECONDS;
+               }
+               break;
+       }
+  
+       if (wrap == SECONDS) {
+               if (smpte.seconds == 0) {
+                       smpte.seconds = 59;
+                       wrap = MINUTES;
+                       if (smpte.minutes == 0) {
+                               smpte.minutes = 59;
+                               wrap = HOURS;
+                               smpte.hours--;
+                       }
+                       else {
+                               smpte.minutes--;
+                       }
+               } else {
+                       smpte.seconds--;
+               }
+       } else {
+               smpte.frames--;
+       }
+  
+       if (SMPTE_IS_ZERO( smpte )) {
+               smpte.negative = false;
+       }
+  
+       return wrap;
+}
+
+
+/** Go to lowest absolute subframe value in this frame (set to 0 :-) ) */
+void
+frames_floor( Time& smpte )
+{
+       smpte.subframes = 0;
+       if (SMPTE_IS_ZERO(smpte)) {
+               smpte.negative = false;
+       }
+}
+
+
+/** Increment @a smpte by one subframe */
+Wrap
+increment_subframes( Time& smpte )
+{
+       Wrap wrap = NONE;
+  
+       if (smpte.negative) {
+               smpte.negative = false;
+               wrap = decrement_subframes( smpte );
+               if (!SMPTE_IS_ZERO(smpte)) {
+                       smpte.negative = true;
+               }
+               return wrap;
+       }
+  
+       smpte.subframes++;
+       if (smpte.subframes >= 80) {
+               smpte.subframes = 0;
+               increment( smpte );
+               return FRAMES;
+       }
+       return NONE;
+}
+
+
+/** Decrement @a smpte by one subframe */
+Wrap
+decrement_subframes( Time& smpte )
+{
+       Wrap wrap = NONE;
+  
+       if (smpte.negative) {
+               smpte.negative = false;
+               wrap = increment_subframes( smpte );
+               smpte.negative = true;
+               return wrap;
+       }
+  
+       if (smpte.subframes <= 0) {
+               smpte.subframes = 0;
+               if (SMPTE_IS_ZERO(smpte)) {
+                       smpte.negative = true;
+                       smpte.subframes = 1;
+                       return FRAMES;
+               } else {
+                       decrement( smpte );
+                       smpte.subframes = 79;
+                       return FRAMES;
+               }
+       } else {
+               smpte.subframes--;
+               if (SMPTE_IS_ZERO(smpte)) {
+                       smpte.negative = false;
+               }
+               return NONE;
+       }
+}
+
+
+/** Go to next whole second (frames == 0 or frames == 2) */
+Wrap
+increment_seconds( Time& smpte )
+{
+       Wrap wrap = NONE;
+  
+       // Clear subframes
+       frames_floor( smpte );
+  
+       if (smpte.negative) {
+               // Wrap second if on second boundary
+               wrap = increment(smpte);
+               // Go to lowest absolute frame value
+               seconds_floor( smpte );
+               if (SMPTE_IS_ZERO(smpte)) {
+                       smpte.negative = false;
+               }
+       } else {
+               // Go to highest possible frame in this second
+               switch (smpte.rate) {
+               case MTC_24_FPS:
+                       smpte.frames = 23;
+                       break;
+               case MTC_25_FPS:
+                       smpte.frames = 24;
+                       break;
+               case MTC_30_FPS_DROP:
+               case MTC_30_FPS:
+                       smpte.frames = 29;
+                       break;
+               }
+    
+               // Increment by one frame
+               wrap = increment( smpte );
+       }
+  
+       return wrap;
+}
+
+
+/** Go to lowest (absolute) frame value in this second
+ * Doesn't care about positive/negative */
+void
+seconds_floor( Time& smpte )
+{
+       // Clear subframes
+       frames_floor( smpte );
+  
+       // Go to lowest possible frame in this second
+       switch (smpte.rate) {
+       case MTC_24_FPS:
+       case MTC_25_FPS:
+       case MTC_30_FPS:
+               smpte.frames = 0;
+               break;
+       case MTC_30_FPS_DROP:
+               if ((smpte.minutes % 10) && (smpte.seconds == 0)) {
+                       smpte.frames = 2;
+               } else {
+                       smpte.frames = 0;
+               }
+               break;
+       }
+  
+       if (SMPTE_IS_ZERO(smpte)) {
+               smpte.negative = false;
+       }
+}
+
+
+/** Go to next whole minute (seconds == 0, frames == 0 or frames == 2) */
+Wrap
+increment_minutes( Time& smpte )
+{
+       Wrap wrap = NONE;
+  
+       // Clear subframes
+       frames_floor( smpte );
+  
+       if (smpte.negative) {
+               // Wrap if on minute boundary
+               wrap = increment_seconds( smpte );
+               // Go to lowest possible value in this minute
+               minutes_floor( smpte );
+       } else {
+               // Go to highest possible second
+               smpte.seconds = 59;
+               // Wrap minute by incrementing second
+               wrap = increment_seconds( smpte );
+       }
+  
+       return wrap;
+}
+
+
+/** Go to lowest absolute value in this minute */
+void
+minutes_floor( Time& smpte )
+{
+       // Go to lowest possible second
+       smpte.seconds = 0;
+       // Go to lowest possible frame
+       seconds_floor( smpte );
+
+       if (SMPTE_IS_ZERO(smpte)) {
+               smpte.negative = false;
+       }
+}
+
+
+/** Go to next whole hour (minute = 0, second = 0, frame = 0) */
+Wrap
+increment_hours( Time& smpte )
+{
+       Wrap wrap = NONE;
+  
+       // Clear subframes
+       frames_floor(smpte);
+  
+       if (smpte.negative) {
+               // Wrap if on hour boundary
+               wrap = increment_minutes( smpte );
+               // Go to lowest possible value in this hour
+               hours_floor( smpte );
+       } else {
+               smpte.minutes = 59;
+               wrap = increment_minutes( smpte );
+       }
+  
+       return wrap;
+}
+
+
+/** Go to lowest absolute value in this hour */
+void
+hours_floor( Time& smpte )
+{
+       smpte.minutes = 0;
+       smpte.seconds = 0;
+       smpte.frames = 0;
+       smpte.subframes = 0;
+  
+       if (SMPTE_IS_ZERO(smpte)) {
+               smpte.negative = false;
+       }
+}
+
+
+} // namespace SMPTE
diff --git a/libs/midi++2/jack_midiport.cc b/libs/midi++2/jack_midiport.cc
new file mode 100644 (file)
index 0000000..4fc24e8
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+  Copyright (C) 2006 Paul Davis 
+  Written by Dave Robillard
+  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.
+  $Id: alsa_sequencer_midiport.cc 244 2006-01-06 04:59:17Z essej $
+*/
+
+#include <fcntl.h>
+#include <cerrno>
+#include <cassert>
+
+#include <midi++/types.h>
+#include <midi++/jack.h>
+#include <midi++/port_request.h>
+
+using namespace std;
+using namespace MIDI;
+
+JACK_MidiPort::JACK_MidiPort(PortRequest & req, jack_client_t* jack_client)
+       : Port(req)
+       , _jack_client(jack_client)
+       , _jack_input_port(NULL)
+       , _jack_output_port(NULL)
+       , _last_read_index(0)
+{
+       int err = create_ports(req);
+
+       if (!err) {
+               req.status = PortRequest::OK;
+               _ok = true;
+       } else {
+               req.status = PortRequest::Unknown;
+       }
+}
+
+JACK_MidiPort::~JACK_MidiPort()
+{
+       // FIXME: remove port
+}
+
+void
+JACK_MidiPort::cycle_start (nframes_t nframes)
+{
+       Port::cycle_start(nframes);
+       assert(_nframes_this_cycle == nframes);
+       _last_read_index = 0;
+       jack_midi_clear_buffer(jack_port_get_buffer(_jack_output_port, nframes), nframes);
+}
+
+int
+JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
+{
+       assert(_currently_in_cycle);
+       assert(timestamp < _nframes_this_cycle);
+       assert(_jack_output_port);
+
+       // FIXME: return value correct?
+       return jack_midi_event_write (
+               jack_port_get_buffer(_jack_output_port, _nframes_this_cycle),
+               timestamp, msg, msglen, _nframes_this_cycle);
+}
+
+int
+JACK_MidiPort::read(byte * buf, size_t max, timestamp_t timestamp)
+{
+       assert(_currently_in_cycle);
+       assert(timestamp < _nframes_this_cycle);
+       assert(_jack_input_port);
+
+       jack_midi_event_t ev;
+
+       int err = jack_midi_event_get (&ev,
+               jack_port_get_buffer(_jack_input_port, _nframes_this_cycle),
+               _last_read_index++, _nframes_this_cycle);
+       
+       if (!err) {
+               memcpy(buf, ev.buffer, ev.size);
+               return ev.size;
+       } else {
+               return 0;
+       }
+}
+
+int
+JACK_MidiPort::create_ports(PortRequest & req)
+{
+       assert(!_jack_input_port);
+       assert(!_jack_output_port);
+       
+       jack_nframes_t nframes = jack_get_buffer_size(_jack_client);
+
+       bool ret = true;
+
+       if (req.mode == O_RDWR || req.mode == O_WRONLY) {
+               _jack_output_port = jack_port_register(_jack_client,
+                       string(req.tagname).append("_out").c_str(),
+                       JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
+               jack_midi_reset_new_port(
+                       jack_port_get_buffer(_jack_output_port, nframes), nframes);
+               ret = ret && (_jack_output_port != NULL);
+       }
+
+       if (req.mode == O_RDWR || req.mode == O_RDONLY) {
+               _jack_input_port = jack_port_register(_jack_client,
+                       string(req.tagname).append("_in").c_str(),
+                       JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
+               jack_midi_reset_new_port(
+                       jack_port_get_buffer(_jack_input_port, nframes), nframes);
+               ret = ret && (_jack_input_port != NULL);
+       }
+
+       return ret ? 0 : -1;
+}
+
diff --git a/libs/midi++2/midi++/jack.h b/libs/midi++2/midi++/jack.h
new file mode 100644 (file)
index 0000000..c20b269
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+    Copyright (C) 2006 Paul Davis 
+       Written by Dave Robillard
+    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.
+    $Id: jack.h 4 2005-05-13 20:47:18Z taybin $
+*/
+
+#ifndef __jack_midiport_h__
+#define __jack_midiport_h__
+
+#include <vector>
+#include <string>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <jack/jack.h>
+#include <jack/midiport.h>
+#include <midi++/port.h>
+
+namespace MIDI
+{
+
+
+class JACK_MidiPort : public Port
+{
+public:
+       JACK_MidiPort (PortRequest &req, jack_client_t* jack_client);
+       virtual ~JACK_MidiPort ();
+
+       /* No select(2)/poll(2)-based I/O */
+       virtual int selectable() const { return -1; }
+       
+       virtual void cycle_start(nframes_t nframes);
+
+protected:
+       /* Direct I/O */
+       int write(byte *msg, size_t msglen, timestamp_t timestamp);
+       int read(byte *buf, size_t max, timestamp_t timestamp);
+
+private:
+       int create_ports(PortRequest &req);
+
+       jack_client_t* _jack_client;
+       jack_port_t*   _jack_input_port;
+       jack_port_t*   _jack_output_port;
+       nframes_t      _last_read_index;
+};
+
+
+} /* namespace MIDI */
+
+#endif // __jack_midiport_h__
+