summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2008-04-03 21:47:47 +0000
committerHans Baier <hansfbaier@googlemail.com>2008-04-03 21:47:47 +0000
commitfbfe9a798313fcb98b2d25df8d23c5c90c76a7ef (patch)
tree4d99a55cb00c85b67c2936cddce46ae411f44fe8 /libs/ardour
parent6554200e66cc243e92818e6e74d4647d1c34ae9c (diff)
* implemented editing velocities (http://tracker.ardour.org/view.php?id=2148)
* added MIDI panic button (http://tracker.ardour.org/view.php?id=2118) * bugfix: moving notes above midi 127 or below 0 does not wrap around anymore * bugfix: deadlock on editing notes after playback (http://tracker.ardour.org/view.php?id=2140) due to unbalanced lock acquire/release * bugfix: First note off lost in playback (http://tracker.ardour.org/view.php?id=2132) * bugfix: Last note off lost in saving MIDI files (http://tracker.ardour.org/view.php?id=2132) * bandaid fix for http://tracker.ardour.org/view.php?id=1985 (Cannot reopen session because jack ports are not unregistered on session close) * bandaid fix: replaced conf.CheckPKGExists ('\"slv2 >= 0.6.0\"') by conf.CheckPKGExists ('slv2') in SConstruct, because the former would fail, even if SLV 0.6.0 was installed * added/enabled debugging output for debugging MIDI model (might be removed later) git-svn-id: svn://localhost/ardour2/branches/3.0@3211 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/midi_model.h8
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h4
-rw-r--r--libs/ardour/ardour/midi_track.h1
-rw-r--r--libs/ardour/ardour/note.h2
-rw-r--r--libs/ardour/ardour/session.h1
-rw-r--r--libs/ardour/audioengine.cc20
-rw-r--r--libs/ardour/midi_buffer.cc8
-rw-r--r--libs/ardour/midi_model.cc69
-rw-r--r--libs/ardour/midi_source.cc4
-rw-r--r--libs/ardour/midi_track.cc13
-rw-r--r--libs/ardour/session_midi.cc19
-rw-r--r--libs/ardour/smf_source.cc13
12 files changed, 123 insertions, 39 deletions
diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h
index 11ef4e0f76..0852108077 100644
--- a/libs/ardour/ardour/midi_model.h
+++ b/libs/ardour/ardour/midi_model.h
@@ -58,10 +58,10 @@ public:
MidiModel(Session& s, size_t size=0);
// This is crap.
- void write_lock() { _lock.writer_lock(); _automation_lock.lock(); }
- void write_unlock() { _lock.writer_unlock(); _automation_lock.unlock(); }
- void read_lock() const { _lock.reader_lock(); /*_automation_lock.lock();*/ }
- void read_unlock() const { _lock.reader_unlock(); /*_automation_lock.unlock();*/ }
+ void write_lock();
+ void write_unlock();
+ void read_lock() const;
+ void read_unlock() const;
void clear() { _notes.clear(); }
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index 1b3ab50f91..136d587550 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -280,8 +280,8 @@ MidiRingBuffer::read_contents(size_t size, Byte* buf)
inline size_t
MidiRingBuffer::write(double time, size_t size, const Byte* buf)
{
- //printf("MRB - write %#X %d %d with time %lf\n",
- // buf[0], buf[1], buf[2], time);
+ printf("MRB - write %#X %d %d with time %lf\n",
+ buf[0], buf[1], buf[2], time);
assert(size > 0);
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index c9ead65d49..c2c7bed056 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -70,6 +70,7 @@ public:
int set_state(const XMLNode& node);
+ void midi_panic(void);
bool write_immediate_event(size_t size, const Byte* buf);
struct MidiControl : public AutomationControl {
diff --git a/libs/ardour/ardour/note.h b/libs/ardour/ardour/note.h
index 41c18358d3..5b5a38d645 100644
--- a/libs/ardour/ardour/note.h
+++ b/libs/ardour/ardour/note.h
@@ -40,7 +40,7 @@ public:
const Note& operator=(const Note& copy);
inline bool operator==(const Note& other)
- { return time() == other.time() && note() == other.note(); }
+ { return time() == other.time() && note() == other.note() && duration() == other.duration(); }
inline double time() const { return _on_event.time(); }
inline double end_time() const { return _off_event.time(); }
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 33ac03f77e..a2380357d3 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -754,6 +754,7 @@ class Session : public PBD::StatefulDestructible
/* MIDI */
+ void midi_panic(void);
int set_mtc_port (string port_tag);
int set_mmc_port (string port_tag);
int set_midi_port (string port_tag);
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 84fd06d079..0f13b05a09 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -527,7 +527,8 @@ AudioEngine::remove_session ()
session = 0;
}
- remove_all_ports ();
+ //FIXME: Preliminary bugfix for http://tracker.ardour.org/view.php?id=1985
+ //remove_all_ports ();
}
void
@@ -555,6 +556,7 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input,
{
Port* newport = 0;
+ cerr << "trying to register port with name " << portname << endl;
try {
if (dtype == DataType::AUDIO) {
newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle());
@@ -564,11 +566,17 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input,
throw unknown_type();
}
+ cerr << "successfully got port " << portname << " with address " << newport << endl;
+
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
+ cerr << "Address of ports list: " << ps << endl
+ << "Ports set size before insert: " << ps->size() << endl;
ps->insert (ps->begin(), newport);
+ cerr << "Ports set size after insert: " << ps->size() << endl;
/* writer goes out of scope, forces update */
+
return newport;
}
@@ -608,22 +616,31 @@ AudioEngine::unregister_port (Port& port)
{
/* caller must hold process lock */
+ cerr << "about to unregister Port xx x" << &port << "\n";
+
if (!_running) {
/* probably happening when the engine has been halted by JACK,
in which case, there is nothing we can do here.
*/
+ cerr << "not running\n";
return 0;
}
{
+ cerr << "before getcopy\n";
RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy ();
+ cerr << "Ports set size: " << ps.get()->size() << endl;
+
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
+ cerr << "before delete" << endl;
if ((*i) == &port) {
+ cerr << "About to delete " << &port << endl;
delete *i;
ps->erase (i);
+ cerr << "After erasing ports size: " << ps->size();
break;
}
}
@@ -631,6 +648,7 @@ AudioEngine::unregister_port (Port& port)
/* writer goes out of scope, forces update */
}
+ cerr << "before remove_connections\n";
remove_connections_for (port);
return 0;
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index a77a608fcd..4eae1eefc6 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -117,7 +117,7 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
for (size_t i=0; i < msrc.size(); ++i) {
const MIDI::Event& ev = msrc[i];
if (ev.time() >= offset && ev.time() < offset+nframes) {
- //cout << "MidiBuffer::read_from got event, " << ev.time() << endl;
+ cout << "MidiBuffer::read_from got event, " << int(ev.type()) << " time: " << ev.time() << " buffer size: " << _size << endl;
push_back(ev);
} else {
cerr << "MidiBuffer event out of range, " << ev.time() << endl;
@@ -148,7 +148,7 @@ MidiBuffer::push_back(const MIDI::Event& ev)
_events[_size].set_buffer(write_loc, false);
++_size;
- //cerr << "MidiBuffer: pushed, size = " << _size << endl;
+ cerr << "MidiBuffer: pushed, size = " << _size << endl;
_silent = false;
@@ -177,7 +177,7 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
_events[_size].set_buffer(write_loc, false);
++_size;
- //cerr << "MidiBuffer: pushed, size = " << _size << endl;
+ cerr << "MidiBuffer: pushed, size = " << _size << endl;
_silent = false;
@@ -207,7 +207,7 @@ MidiBuffer::reserve(double time, size_t size)
_events[_size].set_buffer(write_loc, false);
++_size;
- //cerr << "MidiBuffer: reserved, size = " << _size << endl;
+ cerr << "MidiBuffer: reserved, size = " << _size << endl;
_silent = false;
diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc
index a49094df91..4aa229b450 100644
--- a/libs/ardour/midi_model.cc
+++ b/libs/ardour/midi_model.cc
@@ -36,6 +36,34 @@ using namespace std;
using namespace ARDOUR;
+void
+MidiModel::write_lock()
+{
+ _lock.writer_lock();
+ _automation_lock.lock();
+}
+
+void
+MidiModel::write_unlock()
+{
+ _lock.writer_unlock();
+ _automation_lock.unlock();
+}
+
+void
+MidiModel::read_lock() const
+{
+ _lock.reader_lock();
+ /*_automation_lock.lock();*/
+}
+
+void
+MidiModel::read_unlock() const
+{
+ _lock.reader_unlock();
+ /*_automation_lock.unlock();*/
+}
+
// Read iterator (const_iterator)
MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
@@ -51,7 +79,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
model.read_lock();
_note_iter = model.notes().end();
-
+ // find first note which begins after t
for (MidiModel::Notes::const_iterator i = model.notes().begin(); i != model.notes().end(); ++i) {
if ((*i)->time() >= t) {
_note_iter = i;
@@ -95,6 +123,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
if (_note_iter != model.notes().end()) {
_event = MIDI::Event((*_note_iter)->on_event(), false);
_active_notes.push(*_note_iter);
+ cerr << " new const iterator: size active notes: " << _active_notes.size() << " is empty: " << _active_notes.empty() << endl;
++_note_iter;
}
@@ -106,19 +135,22 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
if (_event.size() == 0) {
//cerr << "Created MIDI iterator @ " << t << " is at end." << endl;
_is_end = true;
+ if(_locked) {
_model->read_unlock();
_locked = false;
- } /*else {
+ }
+ } else {
printf("MIDI Iterator = %X @ %lf\n", _event.type(), _event.time());
- }*/
+}
}
MidiModel::const_iterator::~const_iterator()
{
- if (_locked)
+ if (_locked) {
_model->read_unlock();
}
+}
const MidiModel::const_iterator&
@@ -168,6 +200,7 @@ MidiModel::const_iterator::operator++()
t = (*_note_iter)->time();
}
+ cerr << " operator++ before test: size active notes: " << _active_notes.size() << " is empty: " << _active_notes.empty() << endl;
// Use the next earliest note off iff it's earlier than the note on
if (_model->note_mode() == Sustained && (! _active_notes.empty())) {
if (type == NIL || _active_notes.top()->end_time() <= (*_note_iter)->time()) {
@@ -182,22 +215,20 @@ MidiModel::const_iterator::operator++()
type = CC;
if (type == NOTE_ON) {
- //cerr << "********** MIDI Iterator = note on" << endl;
+ cerr << "********** MIDI Iterator = note on" << endl;
_event = MIDI::Event((*_note_iter)->on_event(), false);
_active_notes.push(*_note_iter);
++_note_iter;
} else if (type == NOTE_OFF) {
- //cerr << "********** MIDI Iterator = note off" << endl;
+ cerr << "********** MIDI Iterator = note off" << endl;
_event = MIDI::Event(_active_notes.top()->off_event(), false);
_active_notes.pop();
} else if (type == CC) {
- //cerr << "********** MIDI Iterator = CC" << endl;
+ cerr << "********** MIDI Iterator = CC" << endl;
_model->control_to_midi_event(_event, *_control_iter);
} else {
- //cerr << "********** MIDI Iterator = END" << endl;
+ cerr << "********** MIDI Iterator = END" << endl;
_is_end = true;
- _model->read_unlock();
- _locked = false;
}
assert(_is_end || _event.size() > 0);
@@ -226,6 +257,7 @@ MidiModel::const_iterator::operator=(const const_iterator& other)
_model = other._model;
_event = other._event;
+ _active_notes = other._active_notes;
_is_end = other._is_end;
_locked = other._locked;
_note_iter = other._note_iter;
@@ -234,9 +266,6 @@ MidiModel::const_iterator::operator=(const const_iterator& other)
assert( ! _event.owns_buffer());
- if (_locked)
- _model->read_lock();
-
return *this;
}
@@ -265,16 +294,16 @@ MidiModel::MidiModel(Session& s, size_t size)
size_t
MidiModel::read(MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const
{
- //cerr << this << " MM::read @ " << start << " * " << nframes << " + " << stamp_offset << endl;
- //cerr << this << " MM # notes: " << n_notes() << endl;
+ cerr << this << " MM::read @ " << start << " * " << nframes << " + " << stamp_offset << endl;
+ cerr << this << " MM # notes: " << n_notes() << endl;
size_t read_events = 0;
if (start != _next_read) {
_read_iter = const_iterator(*this, (double)start);
- //cerr << "Repositioning iterator from " << _next_read << " to " << start << endl;
+ cerr << "Repositioning iterator from " << _next_read << " to " << start << endl;
} else {
- //cerr << "Using cached iterator at " << _next_read << endl;
+ cerr << "Using cached iterator at " << _next_read << endl;
}
_next_read = start + nframes;
@@ -282,7 +311,11 @@ MidiModel::read(MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes
while (_read_iter != end() && _read_iter->time() < start + nframes) {
assert(_read_iter->size() > 0);
dst.write(_read_iter->time() + stamp_offset, _read_iter->size(), _read_iter->buffer());
- //cerr << this << " MM::read event @ " << _read_iter->time() << endl;
+ cerr << this << " MM::read event @ " << _read_iter->time()
+ << " type: " << hex << int(_read_iter->type()) << dec
+ << " note: " << int(_read_iter->note())
+ << " velocity: " << int(_read_iter->velocity())
+ << endl;
++_read_iter;
++read_events;
}
diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc
index 794959328a..eab87376eb 100644
--- a/libs/ardour/midi_source.cc
+++ b/libs/ardour/midi_source.cc
@@ -105,8 +105,8 @@ MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nfra
{
Glib::Mutex::Lock lm (_lock);
if (_model) {
- /*const size_t n_events = */_model->read(dst, start, cnt, stamp_offset);
- //cout << "Read " << n_events << " events from model." << endl;
+ const size_t n_events = _model->read(dst, start, cnt, stamp_offset);
+ cout << "Read " << n_events << " events from model." << endl;
return cnt;
} else {
return read_unlocked (dst, start, cnt, stamp_offset);
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index bf97b19106..cbd9c52bf6 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -697,6 +697,19 @@ MidiTrack::set_note_mode (NoteMode m)
midi_diskstream()->set_note_mode(m);
}
+void
+MidiTrack::midi_panic()
+{
+ for(uint8_t channel = 0; channel <= 0xF; channel++) {
+ Byte ev[3] = { MIDI_CMD_CONTROL | channel, MIDI_CTL_SUSTAIN, 0 };
+ write_immediate_event(3, ev);
+ ev[1] = MIDI_CTL_ALL_NOTES_OFF;
+ write_immediate_event(3, ev);
+ ev[1] = MIDI_CTL_RESET_CONTROLLERS;
+ write_immediate_event(3, ev);
+ }
+}
+
/** \return true on success, false on failure (no buffer space left)
*/
bool
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index eca6d25ea8..b4938636a2 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -26,6 +26,8 @@
#include <fcntl.h>
#include <poll.h>
+#include <boost/shared_ptr.hpp>
+
#include <midi++/mmc.h>
#include <midi++/port.h>
#include <midi++/manager.h>
@@ -37,6 +39,7 @@
#include <ardour/audioengine.h>
#include <ardour/session.h>
#include <ardour/audio_track.h>
+#include <ardour/midi_track.h>
#include <ardour/audio_diskstream.h>
#include <ardour/slave.h>
#include <ardour/cycles.h>
@@ -52,6 +55,22 @@ using namespace MIDI;
MachineControl::CommandSignature MMC_CommandSignature;
MachineControl::ResponseSignature MMC_ResponseSignature;
+
+void
+Session::midi_panic()
+{
+ {
+ boost::shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ MidiTrack *track = dynamic_cast<MidiTrack*>((*i).get());
+ if (track != 0) {
+ track->midi_panic();
+ }
+ }
+ }
+}
+
int
Session::use_config_midi_ports ()
{
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 720626e936..6df78f3b29 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -192,7 +192,7 @@ SMFSource::flush_header ()
_fd = freopen(path().c_str(), "r+", _fd);
assert(_fd);
- fseek(_fd, 0, 0);
+ fseek(_fd, 0, SEEK_SET);
write_chunk("MThd", 6, data);
write_chunk_header("MTrk", _track_size);
@@ -204,9 +204,8 @@ SMFSource::flush_header ()
int
SMFSource::flush_footer()
{
- seek_to_end();
+ fseek(_fd, 0, SEEK_END);
write_footer();
- seek_to_end();
return 0;
}
@@ -321,11 +320,11 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const
if (event_size > 1)
fread((*buf) + 1, 1, *size - 1, _fd);
- /*printf("%s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size);
+ printf("%s read event: delta = %u, size = %u, data = ", _name.c_str(), *delta_t, *size);
for (size_t i=0; i < *size; ++i) {
printf("%X ", (*buf)[i]);
}
- printf("\n");*/
+ printf("\n");
return (int)*size;
}
@@ -334,7 +333,7 @@ SMFSource::read_event(uint32_t* delta_t, uint32_t* size, Byte** buf) const
nframes_t
SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const
{
- //cerr << "SMF " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl;
+ cerr << "SMF read_unlocked " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl;
// 64 bits ought to be enough for anybody
uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
@@ -349,7 +348,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
// FIXME: don't seek to start and search every read (brutal!)
- fseek(_fd, _header_size, 0);
+ fseek(_fd, _header_size, SEEK_SET);
// FIXME: assumes tempo never changes after start
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(