summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-06-09 01:48:38 +0000
committerDavid Robillard <d@drobilla.net>2006-06-09 01:48:38 +0000
commit2f4392f043fe174f798f0d2ca60dc37b2dd8ec7b (patch)
tree3291ee209671d0d49c4ec93080ba4167fda4e6aa /libs
parent5905d4f7b6481b3c51fb4c5c687cd87b8361ab06 (diff)
Removed excessive debug printing, added missing files for SMPTE namespace and Jack libmidi++ ports
git-svn-id: svn://localhost/ardour2/branches/midi@577 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/smpte.h76
-rw-r--r--libs/ardour/session_midi.cc1
-rw-r--r--libs/ardour/session_process.cc10
-rw-r--r--libs/ardour/smpte.cc406
-rw-r--r--libs/midi++2/jack_midiport.cc128
-rw-r--r--libs/midi++2/midi++/jack.h68
6 files changed, 681 insertions, 8 deletions
diff --git a/libs/ardour/ardour/smpte.h b/libs/ardour/ardour/smpte.h
new file mode 100644
index 0000000000..6a7684c5ba
--- /dev/null
+++ b/libs/ardour/ardour/smpte.h
@@ -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__
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index 95d6d02f39..bb3c0018df 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -22,6 +22,7 @@
#include <string>
#include <cmath>
#include <cerrno>
+#include <cassert>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index bbd35a9055..2f35bbfee2 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -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
index 0000000000..17e5a6b42b
--- /dev/null
+++ b/libs/ardour/smpte.cc
@@ -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
index 0000000000..4fc24e8711
--- /dev/null
+++ b/libs/midi++2/jack_midiport.cc
@@ -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
index 0000000000..c20b2693f1
--- /dev/null
+++ b/libs/midi++2/midi++/jack.h
@@ -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__
+