Per-region MIDI CC "automation".
Extremely broken in several ways. This commit brought to you by the letters D, R, and my need to switch machines. git-svn-id: svn://localhost/ardour2/trunk@2323 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
fac0379cab
commit
e486a8d86f
|
@ -100,6 +100,7 @@ control_point.cc
|
|||
automation_line.cc
|
||||
automation_time_axis.cc
|
||||
automation_controller.cc
|
||||
automation_region_view.cc
|
||||
midi_port_dialog.cc
|
||||
midi_time_axis.cc
|
||||
midi_streamview.cc
|
||||
|
|
|
@ -55,7 +55,7 @@ using namespace PBD;
|
|||
using namespace Editing;
|
||||
using namespace Gnome; // for Canvas
|
||||
|
||||
AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr<AutomationList> al)
|
||||
AutomationLine::AutomationLine (const string& name, TimeAxisView& tv, ArdourCanvas::Group& parent, boost::shared_ptr<AutomationList> al)
|
||||
: trackview (tv),
|
||||
_name (name),
|
||||
alist (al),
|
||||
|
@ -353,7 +353,7 @@ AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr)
|
|||
mr.xval = (nframes_t) floor (cp.get_x());
|
||||
mr.yval = 1.0 - ( (cp.get_y() - _y_position) / _height);
|
||||
|
||||
/* if xval has not changed, set it directly from the model to avoid rounding errors */
|
||||
/* if xval has not changed, set it directly from the model to avoid rounding errors */
|
||||
|
||||
if (mr.xval == trackview.editor.frame_to_unit((*cp.model())->when)) {
|
||||
mr.xval = (nframes_t) (*cp.model())->when;
|
||||
|
@ -879,7 +879,7 @@ AutomationLine::remove_point (ControlPoint& cp)
|
|||
model_representation (cp, mr);
|
||||
|
||||
trackview.editor.current_session()->begin_reversible_command (_("remove control point"));
|
||||
XMLNode &before = alist->get_state();
|
||||
XMLNode &before = alist->get_state();
|
||||
|
||||
alist->erase (mr.start, mr.end);
|
||||
|
||||
|
@ -1044,7 +1044,7 @@ AutomationLine::list_changed ()
|
|||
void
|
||||
AutomationLine::reset_callback (const AutomationList& events)
|
||||
{
|
||||
ALPoints tmp_points;
|
||||
ALPoints tmp_points;
|
||||
uint32_t npoints = events.size();
|
||||
|
||||
if (npoints == 0) {
|
||||
|
@ -1086,7 +1086,7 @@ void
|
|||
AutomationLine::clear ()
|
||||
{
|
||||
/* parent must create command */
|
||||
XMLNode &before = get_state();
|
||||
XMLNode &before = get_state();
|
||||
alist->clear();
|
||||
trackview.editor.current_session()->add_command (new MementoCommand<AutomationLine>(*this, &before, &get_state()));
|
||||
trackview.editor.current_session()->commit_reversible_command ();
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
Copyright (C) 2007 Paul Davis
|
||||
Author: 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.
|
||||
*/
|
||||
|
||||
#include "automation_region_view.h"
|
||||
|
||||
AutomationRegionView::AutomationRegionView(ArdourCanvas::Group* parent,
|
||||
AutomationTimeAxisView& time_axis,
|
||||
boost::shared_ptr<ARDOUR::Region> region,
|
||||
boost::shared_ptr<ARDOUR::AutomationList> list,
|
||||
double spu,
|
||||
Gdk::Color& basic_color)
|
||||
: RegionView(parent, time_axis, region, spu, basic_color)
|
||||
, _line(list->parameter().to_string(), time_axis, *group, list)
|
||||
{
|
||||
_line.set_colors();
|
||||
_line.show();
|
||||
_line.show_all_control_points();
|
||||
|
||||
group->raise_to_top ();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AutomationRegionView::set_y_position_and_height (double y, double h)
|
||||
{
|
||||
RegionView::set_y_position_and_height(y, h - 1);
|
||||
|
||||
_line.set_y_position_and_height ((uint32_t)y, (uint32_t) rint (h - NAME_HIGHLIGHT_SIZE));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AutomationRegionView::entered()
|
||||
{
|
||||
_line.track_entered();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AutomationRegionView::exited()
|
||||
{
|
||||
_line.track_exited();
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright (C) 2007 Paul Davis
|
||||
Author: 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.
|
||||
*/
|
||||
|
||||
#ifndef __gtk_ardour_automation_region_view_h__
|
||||
#define __gtk_ardour_automation_region_view_h__
|
||||
|
||||
#include <ardour/diskstream.h>
|
||||
#include <ardour/types.h>
|
||||
|
||||
#include "region_view.h"
|
||||
#include "automation_time_axis.h"
|
||||
#include "automation_line.h"
|
||||
#include "enums.h"
|
||||
#include "canvas.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
class AutomationList;
|
||||
};
|
||||
|
||||
class AutomationTimeAxisView;
|
||||
|
||||
class AutomationRegionView : public RegionView
|
||||
{
|
||||
public:
|
||||
AutomationRegionView(ArdourCanvas::Group*,
|
||||
AutomationTimeAxisView&,
|
||||
boost::shared_ptr<ARDOUR::Region>,
|
||||
boost::shared_ptr<ARDOUR::AutomationList>,
|
||||
double initial_samples_per_unit,
|
||||
Gdk::Color& basic_color);
|
||||
|
||||
~AutomationRegionView() {}
|
||||
|
||||
// We are a ghost. Meta ghosts? Crazy talk.
|
||||
virtual GhostRegion* add_ghost(AutomationTimeAxisView&) { return NULL; }
|
||||
|
||||
protected:
|
||||
void set_y_position_and_height (double y, double h);
|
||||
void entered();
|
||||
void exited();
|
||||
|
||||
private:
|
||||
AutomationLine _line;
|
||||
};
|
||||
|
||||
#endif /* __gtk_ardour_automation_region_view_h__ */
|
|
@ -45,6 +45,8 @@
|
|||
#include "public_editor.h"
|
||||
#include "ghostregion.h"
|
||||
#include "midi_time_axis.h"
|
||||
#include "automation_time_axis.h"
|
||||
#include "automation_region_view.h"
|
||||
#include "utils.h"
|
||||
#include "midi_util.h"
|
||||
#include "gui_thread.h"
|
||||
|
@ -58,8 +60,7 @@ using namespace PBD;
|
|||
using namespace Editing;
|
||||
using namespace ArdourCanvas;
|
||||
|
||||
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu,
|
||||
Gdk::Color& basic_color)
|
||||
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)
|
||||
, _default_note_length(0.0)
|
||||
, _active_notes(0)
|
||||
|
@ -71,8 +72,7 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &
|
|||
_note_group->raise_to_top();
|
||||
}
|
||||
|
||||
MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView &tv, boost::shared_ptr<MidiRegion> r, double spu,
|
||||
Gdk::Color& basic_color, TimeAxisViewItem::Visibility visibility)
|
||||
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)
|
||||
, _default_note_length(0.0)
|
||||
, _active_notes(0)
|
||||
|
@ -399,15 +399,47 @@ MidiRegionView::redisplay_model()
|
|||
return;
|
||||
|
||||
if (_model) {
|
||||
|
||||
|
||||
clear_events();
|
||||
|
||||
begin_write();
|
||||
|
||||
_model->read_lock();
|
||||
|
||||
for (size_t i=0; i < _model->n_notes(); ++i)
|
||||
add_note(_model->note_at(i));
|
||||
|
||||
end_write();
|
||||
|
||||
for (Automatable::Controls::const_iterator i = _model->controls().begin();
|
||||
i != _model->controls().end(); ++i) {
|
||||
|
||||
assert(i->second);
|
||||
|
||||
boost::shared_ptr<AutomationTimeAxisView> at
|
||||
= midi_view()->automation_child(i->second->parameter());
|
||||
if (!at)
|
||||
continue;
|
||||
|
||||
Gdk::Color col = midi_stream_view()->get_region_color();
|
||||
|
||||
boost::shared_ptr<AutomationRegionView> arv;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock list_lock (i->second->list()->lock());
|
||||
|
||||
arv = boost::shared_ptr<AutomationRegionView>(
|
||||
new AutomationRegionView(at->canvas_display,
|
||||
*at.get(), _region, i->second->list(),
|
||||
midi_stream_view()->get_samples_per_unit(), col));
|
||||
|
||||
_automation_children.insert(std::make_pair(i->second->parameter(), arv));
|
||||
}
|
||||
|
||||
arv->init(col, true);
|
||||
}
|
||||
|
||||
_model->read_unlock();
|
||||
|
||||
} else {
|
||||
cerr << "MidiRegionView::redisplay_model called without a model" << endmsg;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2001-2006 Paul Davis
|
||||
Copyright (C) 2001-2007 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
|
||||
|
@ -46,6 +46,7 @@ namespace ARDOUR {
|
|||
class MidiTimeAxisView;
|
||||
class GhostRegion;
|
||||
class AutomationTimeAxisView;
|
||||
class AutomationRegionView;
|
||||
|
||||
class MidiRegionView : public RegionView
|
||||
{
|
||||
|
@ -177,6 +178,9 @@ class MidiRegionView : public RegionView
|
|||
ArdourCanvas::CanvasNote** _active_notes;
|
||||
ArdourCanvas::Group* _note_group;
|
||||
ARDOUR::MidiModel::DeltaCommand* _delta_command;
|
||||
|
||||
typedef std::map<const ARDOUR::Parameter, boost::shared_ptr<AutomationRegionView> > AutomationChildren;
|
||||
AutomationChildren _automation_children;
|
||||
|
||||
MouseState _mouse_state;
|
||||
int _pressed_button;
|
||||
|
|
|
@ -81,6 +81,7 @@ using namespace Editing;
|
|||
MidiTimeAxisView::MidiTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas)
|
||||
: AxisView(sess) // FIXME: won't compile without this, why??
|
||||
, RouteTimeAxisView(ed, sess, rt, canvas)
|
||||
, _note_mode(Sustained)
|
||||
, _note_mode_item(NULL)
|
||||
, _percussion_mode_item(NULL)
|
||||
{
|
||||
|
|
|
@ -58,11 +58,11 @@ static const int32_t sync_mark_width = 9;
|
|||
|
||||
sigc::signal<void,RegionView*> RegionView::RegionViewGoingAway;
|
||||
|
||||
RegionView::RegionView (ArdourCanvas::Group* parent,
|
||||
TimeAxisView& tv,
|
||||
RegionView::RegionView (ArdourCanvas::Group* parent,
|
||||
TimeAxisView& tv,
|
||||
boost::shared_ptr<ARDOUR::Region> r,
|
||||
double spu,
|
||||
Gdk::Color& basic_color)
|
||||
double spu,
|
||||
Gdk::Color& basic_color)
|
||||
: TimeAxisViewItem (r->name(), *parent, tv, spu, basic_color, r->position(), r->length(),
|
||||
TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText|
|
||||
TimeAxisViewItem::ShowNameHighlight|
|
||||
|
|
|
@ -1998,3 +1998,15 @@ RouteTimeAxisView::set_layer_display (LayerDisplay d)
|
|||
{
|
||||
_view->set_layer_display (d);
|
||||
}
|
||||
|
||||
|
||||
boost::shared_ptr<AutomationTimeAxisView>
|
||||
RouteTimeAxisView::automation_child(ARDOUR::Parameter param)
|
||||
{
|
||||
AutomationTracks::iterator i = _automation_tracks.find(param);
|
||||
if (i != _automation_tracks.end())
|
||||
return i->second->track;
|
||||
else
|
||||
return boost::shared_ptr<AutomationTimeAxisView>();
|
||||
}
|
||||
|
||||
|
|
|
@ -95,9 +95,24 @@ public:
|
|||
void clear_playlist ();
|
||||
|
||||
void build_playlist_menu (Gtk::Menu *);
|
||||
|
||||
/* This is a bit nasty to expose :/ */
|
||||
struct RouteAutomationNode {
|
||||
ARDOUR::Parameter param;
|
||||
Gtk::CheckMenuItem* menu_item;
|
||||
boost::shared_ptr<AutomationTimeAxisView> track;
|
||||
|
||||
RouteAutomationNode (ARDOUR::Parameter par, Gtk::CheckMenuItem* mi, boost::shared_ptr<AutomationTimeAxisView> tr)
|
||||
: param (par), menu_item (mi), track (tr) {}
|
||||
};
|
||||
|
||||
virtual void create_automation_child (ARDOUR::Parameter param, bool show) = 0;
|
||||
|
||||
typedef map<ARDOUR::Parameter, RouteAutomationNode*> AutomationTracks;
|
||||
AutomationTracks automation_tracks() { return _automation_tracks; }
|
||||
|
||||
boost::shared_ptr<AutomationTimeAxisView> automation_child(ARDOUR::Parameter param);
|
||||
|
||||
string name() const;
|
||||
StreamView* view() const { return _view; }
|
||||
ARDOUR::RouteGroup* edit_group() const;
|
||||
|
@ -105,18 +120,9 @@ public:
|
|||
|
||||
protected:
|
||||
friend class StreamView;
|
||||
|
||||
struct RouteAutomationNode {
|
||||
ARDOUR::Parameter param;
|
||||
Gtk::CheckMenuItem* menu_item;
|
||||
boost::shared_ptr<AutomationTimeAxisView> track;
|
||||
|
||||
RouteAutomationNode (ARDOUR::Parameter par, Gtk::CheckMenuItem* mi, boost::shared_ptr<AutomationTimeAxisView> tr)
|
||||
: param (par), menu_item (mi), track (tr) {}
|
||||
};
|
||||
|
||||
struct ProcessorAutomationNode {
|
||||
ARDOUR::Parameter what;
|
||||
ARDOUR::Parameter what;
|
||||
Gtk::CheckMenuItem* menu_item;
|
||||
boost::shared_ptr<AutomationTimeAxisView> view;
|
||||
RouteTimeAxisView& parent;
|
||||
|
@ -268,7 +274,6 @@ protected:
|
|||
// Set from XML so context menu automation buttons can be correctly initialized
|
||||
set<ARDOUR::Parameter> _show_automation;
|
||||
|
||||
typedef map<ARDOUR::Parameter, RouteAutomationNode*> AutomationTracks;
|
||||
AutomationTracks _automation_tracks;
|
||||
|
||||
sigc::connection modified_connection;
|
||||
|
|
|
@ -52,7 +52,8 @@ public:
|
|||
boost::shared_ptr<AutomationControl> control_factory(boost::shared_ptr<AutomationList> list);
|
||||
|
||||
typedef std::map<Parameter,boost::shared_ptr<AutomationControl> > Controls;
|
||||
Controls controls() { return _controls; }
|
||||
Controls& controls() { return _controls; }
|
||||
const Controls& controls() const { return _controls; }
|
||||
|
||||
virtual void add_control(boost::shared_ptr<AutomationControl>);
|
||||
|
||||
|
@ -79,6 +80,8 @@ public:
|
|||
const std::set<Parameter>& what_can_be_automated() const { return _can_automate_list; }
|
||||
|
||||
void mark_automation_visible(Parameter, bool);
|
||||
|
||||
Glib::Mutex& automation_lock() const { return _automation_lock; }
|
||||
|
||||
protected:
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ class AutomationList : public PBD::StatefulDestructible
|
|||
Glib::Mutex::Lock lm (_lock);
|
||||
(obj.*method)(*this);
|
||||
}
|
||||
|
||||
|
||||
sigc::signal<void> StateChanged;
|
||||
|
||||
XMLNode& get_state(void);
|
||||
|
|
|
@ -77,6 +77,12 @@ 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() { _lock.reader_lock(); _automation_lock.lock(); }
|
||||
void read_unlock() { _lock.reader_unlock(); _automation_lock.unlock(); }
|
||||
|
||||
void clear() { _notes.clear(); }
|
||||
|
||||
|
@ -167,9 +173,9 @@ private:
|
|||
bool is_sorted() const;
|
||||
#endif
|
||||
|
||||
void append_note_on(double time, uint8_t note, uint8_t velocity);
|
||||
void append_note_off(double time, uint8_t note);
|
||||
void append_cc(double time, uint8_t number, uint8_t value);
|
||||
void append_note_on_unlocked(double time, uint8_t note, uint8_t velocity);
|
||||
void append_note_off_unlocked(double time, uint8_t note);
|
||||
void append_cc_unlocked(double time, uint8_t number, uint8_t value);
|
||||
|
||||
Glib::RWLock _lock;
|
||||
|
||||
|
|
|
@ -193,9 +193,10 @@ void
|
|||
MidiModel::start_write()
|
||||
{
|
||||
//cerr << "MM " << this << " START WRITE, MODE = " << enum_2_string(_note_mode) << endl;
|
||||
_lock.writer_lock();
|
||||
write_lock();
|
||||
_writing = true;
|
||||
_write_notes.clear();
|
||||
write_unlock();
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,6 +210,7 @@ MidiModel::start_write()
|
|||
void
|
||||
MidiModel::end_write(bool delete_stuck)
|
||||
{
|
||||
write_lock();
|
||||
assert(_writing);
|
||||
|
||||
//cerr << "MM " << this << " END WRITE: " << _notes.size() << " NOTES\n";
|
||||
|
@ -226,7 +228,7 @@ MidiModel::end_write(bool delete_stuck)
|
|||
|
||||
_write_notes.clear();
|
||||
_writing = false;
|
||||
_lock.writer_unlock();
|
||||
write_unlock();
|
||||
}
|
||||
|
||||
|
||||
|
@ -241,12 +243,16 @@ MidiModel::end_write(bool delete_stuck)
|
|||
void
|
||||
MidiModel::append(const MidiBuffer& buf)
|
||||
{
|
||||
write_lock();
|
||||
|
||||
assert(_writing);
|
||||
|
||||
for (MidiBuffer::const_iterator i = buf.begin(); i != buf.end(); ++i) {
|
||||
assert(_notes.empty() || (*i).time() >= _notes.back().time());
|
||||
append(*i);
|
||||
}
|
||||
|
||||
write_unlock();
|
||||
}
|
||||
|
||||
|
||||
|
@ -259,22 +265,26 @@ MidiModel::append(const MidiBuffer& buf)
|
|||
void
|
||||
MidiModel::append(const MidiEvent& ev)
|
||||
{
|
||||
write_lock();
|
||||
|
||||
assert(_notes.empty() || ev.time() >= _notes.back().time());
|
||||
assert(_writing);
|
||||
|
||||
if (ev.is_note_on())
|
||||
append_note_on(ev.time(), ev.note(), ev.velocity());
|
||||
append_note_on_unlocked(ev.time(), ev.note(), ev.velocity());
|
||||
else if (ev.is_note_off())
|
||||
append_note_off(ev.time(), ev.note());
|
||||
append_note_off_unlocked(ev.time(), ev.note());
|
||||
else if (ev.is_cc())
|
||||
append_cc(ev.time(), ev.cc_number(), ev.cc_value());
|
||||
append_cc_unlocked(ev.time(), ev.cc_number(), ev.cc_value());
|
||||
else
|
||||
printf("MM Unknown event type %X\n", ev.type());
|
||||
|
||||
write_unlock();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MidiModel::append_note_on(double time, uint8_t note_num, uint8_t velocity)
|
||||
MidiModel::append_note_on_unlocked(double time, uint8_t note_num, uint8_t velocity)
|
||||
{
|
||||
//cerr << "MidiModel " << this << " note " << (int)note_num << " on @ " << time << endl;
|
||||
|
||||
|
@ -290,7 +300,7 @@ MidiModel::append_note_on(double time, uint8_t note_num, uint8_t velocity)
|
|||
|
||||
|
||||
void
|
||||
MidiModel::append_note_off(double time, uint8_t note_num)
|
||||
MidiModel::append_note_off_unlocked(double time, uint8_t note_num)
|
||||
{
|
||||
//cerr << "MidiModel " << this << " note " << (int)note_num << " off @ " << time << endl;
|
||||
|
||||
|
@ -322,7 +332,7 @@ MidiModel::append_note_off(double time, uint8_t note_num)
|
|||
|
||||
|
||||
void
|
||||
MidiModel::append_cc(double time, uint8_t number, uint8_t value)
|
||||
MidiModel::append_cc_unlocked(double time, uint8_t number, uint8_t value)
|
||||
{
|
||||
Parameter param(MidiCCAutomation, number);
|
||||
|
||||
|
@ -427,7 +437,7 @@ MidiModel::DeltaCommand::operator()()
|
|||
// This could be made much faster by using a priority_queue for added and
|
||||
// removed notes (or sort here), and doing a single iteration over _model
|
||||
|
||||
_model._lock.writer_lock();
|
||||
_model.write_lock();
|
||||
|
||||
for (std::list<Note>::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i)
|
||||
_model.add_note_unlocked(*i);
|
||||
|
@ -435,7 +445,7 @@ MidiModel::DeltaCommand::operator()()
|
|||
for (std::list<Note>::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i)
|
||||
_model.remove_note_unlocked(*i);
|
||||
|
||||
_model._lock.writer_unlock();
|
||||
_model.write_unlock();
|
||||
|
||||
_model.ContentsChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
@ -447,7 +457,7 @@ MidiModel::DeltaCommand::undo()
|
|||
// This could be made much faster by using a priority_queue for added and
|
||||
// removed notes (or sort here), and doing a single iteration over _model
|
||||
|
||||
_model._lock.writer_lock();
|
||||
_model.write_lock();
|
||||
|
||||
for (std::list<Note>::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i)
|
||||
_model.remove_note_unlocked(*i);
|
||||
|
@ -455,7 +465,7 @@ MidiModel::DeltaCommand::undo()
|
|||
for (std::list<Note>::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i)
|
||||
_model.add_note_unlocked(*i);
|
||||
|
||||
_model._lock.writer_unlock();
|
||||
_model.write_unlock();
|
||||
|
||||
_model.ContentsChanged(); /* EMIT SIGNAL */
|
||||
}
|
||||
|
@ -484,7 +494,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
|
|||
source->append_event_unlocked(ev);
|
||||
}*/
|
||||
|
||||
_lock.reader_lock();
|
||||
read_lock();
|
||||
|
||||
LaterNoteEndComparator cmp;
|
||||
ActiveNotes active_notes(cmp);
|
||||
|
@ -518,7 +528,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
|
|||
|
||||
_edited = false;
|
||||
|
||||
_lock.reader_unlock();
|
||||
read_unlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue