13
0

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
This commit is contained in:
David Robillard 2006-06-09 01:48:38 +00:00
parent 5905d4f7b6
commit 2f4392f043
6 changed files with 681 additions and 8 deletions

View File

@ -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__

View File

@ -22,6 +22,7 @@
#include <string>
#include <cmath>
#include <cerrno>
#include <cassert>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>

View 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;

406
libs/ardour/smpte.cc Normal file
View File

@ -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

View File

@ -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;
}

View File

@ -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__