Preliminary visible MIDI notes in MidiRegionView.
git-svn-id: svn://localhost/ardour2/trunk@1943 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
b0685f4336
commit
b32765571b
|
@ -28,6 +28,7 @@
|
|||
#include <ardour/midi_region.h>
|
||||
#include <ardour/midi_source.h>
|
||||
#include <ardour/midi_diskstream.h>
|
||||
#include <ardour/midi_events.h>
|
||||
|
||||
#include "streamview.h"
|
||||
#include "midi_region_view.h"
|
||||
|
@ -35,7 +36,6 @@
|
|||
#include "simplerect.h"
|
||||
#include "simpleline.h"
|
||||
#include "public_editor.h"
|
||||
//#include "midi_region_editor.h"
|
||||
#include "ghostregion.h"
|
||||
#include "midi_time_axis.h"
|
||||
#include "utils.h"
|
||||
|
@ -53,12 +53,14 @@ using namespace ArdourCanvas;
|
|||
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu,
|
||||
Gdk::Color& basic_color)
|
||||
: RegionView (parent, tv, r, spu, basic_color)
|
||||
, _active_notes(0)
|
||||
{
|
||||
}
|
||||
|
||||
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu,
|
||||
Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility)
|
||||
: RegionView (parent, tv, r, spu, basic_color, visibility)
|
||||
, _active_notes(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -89,6 +91,7 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
|
|||
MidiRegionView::~MidiRegionView ()
|
||||
{
|
||||
in_destructor = true;
|
||||
end_write();
|
||||
|
||||
RegionViewGoingAway (this); /* EMIT_SIGNAL */
|
||||
}
|
||||
|
@ -113,3 +116,67 @@ MidiRegionView::add_ghost (AutomationTimeAxisView& atv)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Begin tracking note state for successive calls to add_event
|
||||
*/
|
||||
void
|
||||
MidiRegionView::begin_write()
|
||||
{
|
||||
_active_notes = new ArdourCanvas::SimpleRect*[127];
|
||||
}
|
||||
|
||||
|
||||
/** Destroy note state for add_event
|
||||
*/
|
||||
void
|
||||
MidiRegionView::end_write()
|
||||
{
|
||||
delete[] _active_notes;
|
||||
_active_notes = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MidiRegionView::add_event (const MidiEvent& ev)
|
||||
{
|
||||
/*printf("Event, time = %u, size = %zu, data = ",
|
||||
ev.time, ev.size);
|
||||
for (size_t i=0; i < ev.size; ++i) {
|
||||
printf("%X ", ev.buffer[i]);
|
||||
}
|
||||
printf("\n");*/
|
||||
double y1 = trackview.height / 2.0;
|
||||
if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_ON) {
|
||||
const Byte& note = ev.buffer[1];
|
||||
y1 = (trackview.height / 127.0) * note;
|
||||
|
||||
ArdourCanvas::SimpleRect * ev_rect = new Gnome::Canvas::SimpleRect(
|
||||
*(ArdourCanvas::Group*)get_canvas_group());
|
||||
ev_rect->property_x1() = trackview.editor.frame_to_pixel (
|
||||
ev.time);
|
||||
ev_rect->property_y1() = y1;
|
||||
ev_rect->property_x2() = trackview.editor.frame_to_pixel (
|
||||
_region->length());
|
||||
ev_rect->property_y2() = y1 + (trackview.height / 127.0);
|
||||
ev_rect->property_outline_color_rgba() = 0xFFFFFFAA;
|
||||
/* outline all but right edge */
|
||||
ev_rect->property_outline_what() = (guint32) (0x1 & 0x4 & 0x8);
|
||||
ev_rect->property_fill_color_rgba() = 0xFFFFFF66;
|
||||
|
||||
_events.push_back(ev_rect);
|
||||
if (_active_notes)
|
||||
_active_notes[note] = ev_rect;
|
||||
|
||||
} else if ((ev.buffer[0] & 0xF0) == MIDI_CMD_NOTE_OFF) {
|
||||
const Byte& note = ev.buffer[1];
|
||||
if (_active_notes && _active_notes[note]) {
|
||||
_active_notes[note]->property_x2() = trackview.editor.frame_to_pixel(ev.time);
|
||||
_active_notes[note]->property_outline_what() = (guint32) 0xF; // all edges
|
||||
_active_notes[note] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <libgnomecanvasmm/polygon.h>
|
||||
#include <sigc++/signal.h>
|
||||
#include <ardour/midi_region.h>
|
||||
#include <ardour/types.h>
|
||||
|
||||
#include "region_view.h"
|
||||
#include "route_time_axis.h"
|
||||
|
@ -61,6 +62,11 @@ class MidiRegionView : public RegionView
|
|||
|
||||
GhostRegion* add_ghost (AutomationTimeAxisView&);
|
||||
|
||||
void add_event(const ARDOUR::MidiEvent& ev);
|
||||
|
||||
void begin_write();
|
||||
void end_write();
|
||||
|
||||
protected:
|
||||
|
||||
/* this constructor allows derived types
|
||||
|
@ -79,6 +85,11 @@ class MidiRegionView : public RegionView
|
|||
|
||||
void set_flags (XMLNode *);
|
||||
void store_flags ();
|
||||
|
||||
private:
|
||||
|
||||
std::vector<ArdourCanvas::Item*> _events;
|
||||
ArdourCanvas::SimpleRect** _active_notes;
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_midi_region_view_h__ */
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "gui_thread.h"
|
||||
#include "utils.h"
|
||||
#include "color.h"
|
||||
#include "simplerect.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
|
@ -107,8 +108,13 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait
|
|||
// FIXME
|
||||
//region_view->set_waveform_visible(_trackview.editor.show_waveforms());
|
||||
|
||||
/* catch regionview going away */
|
||||
/* display events */
|
||||
region_view->begin_write();
|
||||
for (size_t i=0; i < region->midi_source(0)->model().n_events(); ++i)
|
||||
region_view->add_event(region->midi_source(0)->model().event_at(i));
|
||||
region_view->end_write();
|
||||
|
||||
/* catch regionview going away */
|
||||
region->GoingAway.connect (bind (mem_fun (*this, &MidiStreamView::remove_region_view), region));
|
||||
|
||||
RegionViewAdded (region_view);
|
||||
|
@ -337,12 +343,21 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiBuffer> data, nframes_
|
|||
if (origlen == 1) {
|
||||
/* our special initial length */
|
||||
iter->second = add_region_view_internal (region, false);
|
||||
((MidiRegionView*)iter->second)->begin_write();
|
||||
}
|
||||
|
||||
/* also update rect */
|
||||
ArdourCanvas::SimpleRect * rect = rec_rects[n].rectangle;
|
||||
gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length());
|
||||
rect->property_x2() = xend;
|
||||
|
||||
/* draw events */
|
||||
MidiRegionView* mrv = (MidiRegionView*)iter->second;
|
||||
for (size_t i = 0; i < data->size(); ++i) {
|
||||
const MidiEvent& ev = (*data.get())[i];
|
||||
mrv->add_event(ev);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ midi_diskstream.cc
|
|||
midi_playlist.cc
|
||||
midi_track.cc
|
||||
midi_region.cc
|
||||
midi_model.cc
|
||||
smf_source.cc
|
||||
auditioner.cc
|
||||
automation.cc
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <boost/utility.hpp>
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/data_type.h>
|
||||
#include <ardour/runtime_functions.h>
|
||||
|
@ -38,7 +39,7 @@ namespace ARDOUR {
|
|||
*
|
||||
* To actually read/write buffer contents, use the appropriate derived class.
|
||||
*/
|
||||
class Buffer
|
||||
class Buffer : public boost::noncopyable
|
||||
{
|
||||
public:
|
||||
virtual ~Buffer() {}
|
||||
|
@ -76,11 +77,6 @@ protected:
|
|||
size_t _capacity;
|
||||
size_t _size;
|
||||
bool _silent;
|
||||
|
||||
private:
|
||||
// Prevent copies (undefined)
|
||||
Buffer(const Buffer& copy);
|
||||
void operator=(const Buffer& other);
|
||||
};
|
||||
|
||||
|
||||
|
@ -175,10 +171,6 @@ public:
|
|||
{ assert(offset + nframes <= _capacity); return _data + offset; }
|
||||
|
||||
private:
|
||||
// These are undefined (prevent copies)
|
||||
AudioBuffer(const AudioBuffer& copy);
|
||||
AudioBuffer& operator=(const AudioBuffer& copy);
|
||||
|
||||
bool _owns_data;
|
||||
Sample* _data; ///< Actual buffer contents
|
||||
};
|
||||
|
@ -197,7 +189,7 @@ public:
|
|||
|
||||
void read_from(const Buffer& src, nframes_t nframes, nframes_t offset);
|
||||
|
||||
bool push_back(const MidiEvent& event);
|
||||
bool push_back(const ARDOUR::MidiEvent& event);
|
||||
Byte* reserve(nframes_t time, size_t size);
|
||||
|
||||
const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
|
||||
|
@ -206,10 +198,6 @@ public:
|
|||
static size_t max_event_size() { return MAX_EVENT_SIZE; }
|
||||
|
||||
private:
|
||||
// These are undefined (prevent copies)
|
||||
MidiBuffer(const MidiBuffer& copy);
|
||||
MidiBuffer& operator=(const MidiBuffer& copy);
|
||||
|
||||
// FIXME: Jack needs to tell us this
|
||||
static const size_t MAX_EVENT_SIZE = 4; // bytes
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
/*
|
||||
Copyright (C) 2006 Paul Davis
|
||||
Written by Dave Robillard, 2006
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __ardour_midi_model_h__
|
||||
#define __ardour_midi_model_h__
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <ardour/types.h>
|
||||
#include <ardour/buffer.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
/** A dynamically resizable collection of MIDI events, sorted by time
|
||||
*/
|
||||
class MidiModel : public boost::noncopyable {
|
||||
public:
|
||||
MidiModel(size_t size=0);
|
||||
~MidiModel();
|
||||
|
||||
/** Resizes vector if necessary (NOT realtime safe) */
|
||||
void append(const MidiBuffer& data);
|
||||
|
||||
inline const MidiEvent& event_at(unsigned i) const { return _events[i]; }
|
||||
|
||||
inline size_t n_events() const { return _events.size(); }
|
||||
|
||||
private:
|
||||
std::vector<MidiEvent> _events;
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR */
|
||||
|
||||
#endif /* __ardour_midi_model_h__ */
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include <ardour/source.h>
|
||||
#include <ardour/ardour.h>
|
||||
#include <ardour/buffer.h>
|
||||
#include <ardour/midi_model.h>
|
||||
#include <pbd/stateful.h>
|
||||
#include <pbd/xml++.h>
|
||||
|
||||
|
@ -62,12 +63,14 @@ class MidiSource : public Source
|
|||
|
||||
static sigc::signal<void,MidiSource*> MidiSourceCreated;
|
||||
|
||||
// The MIDI equivalent to "peaks"
|
||||
// The MIDI equivalent to "peaks" (but complete data)
|
||||
mutable sigc::signal<void,boost::shared_ptr<MidiBuffer>,nframes_t,nframes_t> ViewDataRangeReady;
|
||||
|
||||
XMLNode& get_state ();
|
||||
int set_state (const XMLNode&);
|
||||
|
||||
MidiModel& model() { return _model; }
|
||||
|
||||
protected:
|
||||
virtual nframes_t read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const = 0;
|
||||
virtual nframes_t write_unlocked (MidiRingBuffer& dst, nframes_t cnt) = 0;
|
||||
|
@ -77,6 +80,8 @@ class MidiSource : public Source
|
|||
mutable uint32_t _read_data_count; ///< modified in read()
|
||||
mutable uint32_t _write_data_count; ///< modified in write()
|
||||
|
||||
MidiModel _model;
|
||||
|
||||
private:
|
||||
bool file_changed (string path);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright (C) 2006 Paul Davis
|
||||
Written by Dave Robillard, 2006
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <ardour/midi_model.h>
|
||||
#include <ardour/types.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
|
||||
|
||||
MidiModel::MidiModel(size_t size)
|
||||
: _events(size)
|
||||
{
|
||||
}
|
||||
|
||||
MidiModel::~MidiModel()
|
||||
{
|
||||
for (size_t i=0; i < _events.size(); ++i)
|
||||
delete _events[i].buffer;
|
||||
}
|
||||
|
||||
|
||||
/** Append contents of \a buf to model. NOT (even remotely) realtime safe.
|
||||
*
|
||||
* Timestamps of events in \a buf are expected to be relative to
|
||||
* the start of this model (t=0) and MUST be monotonically increasing
|
||||
* and MUST be >= the latest event currently in the model.
|
||||
*
|
||||
* Events in buf are deep copied.
|
||||
*/
|
||||
void
|
||||
MidiModel::append(const MidiBuffer& buf)
|
||||
{
|
||||
for (size_t i=0; i < buf.size(); ++i) {
|
||||
const MidiEvent& buf_event = buf[i];
|
||||
assert(buf_event.time >= _events.back().time);
|
||||
|
||||
_events.push_back(buf_event);
|
||||
MidiEvent& my_event = _events.back();
|
||||
assert(my_event.time == buf_event.time);
|
||||
assert(my_event.size == buf_event.size);
|
||||
|
||||
my_event.buffer = new Byte[my_event.size];
|
||||
memcpy(my_event.buffer, buf_event.buffer, my_event.size);
|
||||
}
|
||||
}
|
||||
|
|
@ -352,9 +352,10 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
|||
// FIXME: start of source time?
|
||||
|
||||
for (size_t i=0; i < buf.size(); ++i) {
|
||||
const MidiEvent& ev = buf[i];
|
||||
MidiEvent& ev = buf[i];
|
||||
assert(ev.time >= _timeline_position);
|
||||
uint32_t delta_time = (ev.time - _timeline_position) - _last_ev_time;
|
||||
ev.time -= _timeline_position;
|
||||
uint32_t delta_time = ev.time - _last_ev_time;
|
||||
|
||||
/*printf("SMF - writing event, delta = %u, size = %zu, data = ",
|
||||
delta_time, ev.size);
|
||||
|
@ -376,6 +377,8 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
|||
const nframes_t oldlen = _length;
|
||||
update_length(oldlen, cnt);
|
||||
|
||||
_model.append(buf);
|
||||
|
||||
ViewDataRangeReady (buf_ptr, oldlen, cnt); /* EMIT SIGNAL */
|
||||
|
||||
return cnt;
|
||||
|
|
Loading…
Reference in New Issue