mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 23:35:03 +01:00
Midi pencil undo (not yet serializable).
Formatting fixes for session.h (ie kill more of those damned 8 space expanded tabs). git-svn-id: svn://localhost/ardour2/trunk@2135 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
37c74810d2
commit
f542fa693c
7 changed files with 210 additions and 54 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2001-2006 Paul Davis
|
Copyright (C) 2001-2007 Paul Davis
|
||||||
|
Author: Dave Robillard
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -24,6 +25,8 @@
|
||||||
|
|
||||||
#include <gtkmm2ext/gtk_ui.h>
|
#include <gtkmm2ext/gtk_ui.h>
|
||||||
|
|
||||||
|
#include <sigc++/signal.h>
|
||||||
|
|
||||||
#include <ardour/playlist.h>
|
#include <ardour/playlist.h>
|
||||||
#include <ardour/tempo.h>
|
#include <ardour/tempo.h>
|
||||||
#include <ardour/midi_region.h>
|
#include <ardour/midi_region.h>
|
||||||
|
|
@ -96,6 +99,9 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd)
|
||||||
display_events();
|
display_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
midi_region()->midi_source(0)->model()->ContentsChanged.connect(sigc::mem_fun(
|
||||||
|
this, &MidiRegionView::redisplay_model));
|
||||||
|
|
||||||
group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event));
|
group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,13 +133,15 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
const Tempo& t = trackview.session().tempo_map().tempo_at(stamp);
|
const Tempo& t = trackview.session().tempo_map().tempo_at(stamp);
|
||||||
double dur = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar();
|
double dur = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar();
|
||||||
|
|
||||||
|
MidiModel* model = midi_region()->midi_source(0)->model();
|
||||||
|
|
||||||
// Add a 1 beat long note (for now)
|
// Add a 1 beat long note (for now)
|
||||||
const MidiModel::Note new_note(stamp, dur, (uint8_t)note, 0x40);
|
const MidiModel::Note new_note(stamp, dur, (uint8_t)note, 0x40);
|
||||||
|
|
||||||
MidiModel::Notes& notes = midi_region()->midi_source(0)->model()->notes();
|
model->begin_command();
|
||||||
MidiModel::Notes::iterator i = upper_bound(notes.begin(), notes.end(), new_note,
|
model->add_note(new_note);
|
||||||
MidiModel::NoteTimeComparator());
|
model->finish_command();
|
||||||
notes.insert(i, new_note);
|
|
||||||
view->update_bounds(new_note.note);
|
view->update_bounds(new_note.note);
|
||||||
|
|
||||||
add_note(new_note);
|
add_note(new_note);
|
||||||
|
|
@ -144,6 +152,14 @@ MidiRegionView::canvas_event(GdkEvent* ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiRegionView::redisplay_model()
|
||||||
|
{
|
||||||
|
clear_events();
|
||||||
|
display_events();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiRegionView::clear_events()
|
MidiRegionView::clear_events()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
#include <libgnomecanvasmm.h>
|
#include <libgnomecanvasmm.h>
|
||||||
#include <libgnomecanvasmm/polygon.h>
|
#include <libgnomecanvasmm/polygon.h>
|
||||||
#include <sigc++/signal.h>
|
|
||||||
#include <ardour/midi_region.h>
|
#include <ardour/midi_region.h>
|
||||||
#include <ardour/midi_model.h>
|
#include <ardour/midi_model.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
|
|
@ -94,6 +93,7 @@ class MidiRegionView : public RegionView
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void redisplay_model();
|
||||||
void display_events();
|
void display_events();
|
||||||
void clear_events();
|
void clear_events();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,15 @@
|
||||||
#define __ardour_midi_model_h__
|
#define __ardour_midi_model_h__
|
||||||
|
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
|
#include <pbd/command.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
#include <ardour/midi_buffer.h>
|
#include <ardour/midi_buffer.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class Session;
|
||||||
|
|
||||||
|
|
||||||
/** This is a slightly higher level (than MidiBuffer) model of MIDI note data.
|
/** This is a slightly higher level (than MidiBuffer) model of MIDI note data.
|
||||||
* Currently it only represents note data, which is represented as complete
|
* Currently it only represents note data, which is represented as complete
|
||||||
* note events (ie with a start time and a duration) rather than separate
|
* note events (ie with a start time and a duration) rather than separate
|
||||||
|
|
@ -39,13 +43,16 @@ public:
|
||||||
Note(double s=0, double d=0, uint8_t n=0, uint8_t v=0)
|
Note(double s=0, double d=0, uint8_t n=0, uint8_t v=0)
|
||||||
: start(s), duration(d), note(n), velocity(v) {}
|
: start(s), duration(d), note(n), velocity(v) {}
|
||||||
|
|
||||||
|
inline bool operator==(const Note& other)
|
||||||
|
{ return start == other.start && note == other.note; }
|
||||||
|
|
||||||
double start;
|
double start;
|
||||||
double duration;
|
double duration;
|
||||||
uint8_t note;
|
uint8_t note;
|
||||||
uint8_t velocity;
|
uint8_t velocity;
|
||||||
};
|
};
|
||||||
|
|
||||||
MidiModel(size_t size=0);
|
MidiModel(Session& s, size_t size=0);
|
||||||
|
|
||||||
void clear() { _notes.clear(); }
|
void clear() { _notes.clear(); }
|
||||||
|
|
||||||
|
|
@ -73,13 +80,47 @@ public:
|
||||||
inline Notes& notes() { return _notes; }
|
inline Notes& notes() { return _notes; }
|
||||||
inline const Notes& notes() const { return _notes; }
|
inline const Notes& notes() const { return _notes; }
|
||||||
|
|
||||||
|
void begin_command();
|
||||||
|
Command* current_command() { return _command; }
|
||||||
|
void finish_command();
|
||||||
|
|
||||||
|
// Commands
|
||||||
|
void add_note(const Note& note);
|
||||||
|
void remove_note(const Note& note);
|
||||||
|
|
||||||
|
sigc::signal<void> ContentsChanged;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class MidiEditCommand : public Command
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MidiEditCommand (MidiModel& m) : _model(m) {}
|
||||||
|
//MidiEditCommand (MidiModel&, const XMLNode& node);
|
||||||
|
|
||||||
|
void operator()();
|
||||||
|
void undo();
|
||||||
|
|
||||||
|
/*int set_state (const XMLNode&);
|
||||||
|
XMLNode& get_state ();*/
|
||||||
|
|
||||||
|
void add_note(const Note& note);
|
||||||
|
void remove_note(const Note& note);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MidiModel& _model;
|
||||||
|
std::list<Note> _added_notes;
|
||||||
|
std::list<Note> _removed_notes;
|
||||||
|
};
|
||||||
|
|
||||||
void append_note_on(double time, uint8_t note, uint8_t velocity);
|
void append_note_on(double time, uint8_t note, uint8_t velocity);
|
||||||
void append_note_off(double time, uint8_t note);
|
void append_note_off(double time, uint8_t note);
|
||||||
|
|
||||||
|
Session& _session;
|
||||||
|
|
||||||
Notes _notes;
|
Notes _notes;
|
||||||
Notes _write_notes;
|
Notes _write_notes;
|
||||||
|
|
||||||
|
MidiEditCommand* _command; ///< In-progress command
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ARDOUR */
|
} /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -487,7 +487,7 @@ class Session : public PBD::StatefulDestructible
|
||||||
void resort_routes ();
|
void resort_routes ();
|
||||||
void resort_routes_using (boost::shared_ptr<RouteList>);
|
void resort_routes_using (boost::shared_ptr<RouteList>);
|
||||||
|
|
||||||
void set_remote_control_ids();
|
void set_remote_control_ids();
|
||||||
|
|
||||||
AudioEngine &engine() { return _engine; };
|
AudioEngine &engine() { return _engine; };
|
||||||
|
|
||||||
|
|
@ -538,7 +538,7 @@ class Session : public PBD::StatefulDestructible
|
||||||
void request_slave_source (SlaveSource);
|
void request_slave_source (SlaveSource);
|
||||||
bool synced_to_jack() const { return Config->get_slave_source() == JACK; }
|
bool synced_to_jack() const { return Config->get_slave_source() == JACK; }
|
||||||
|
|
||||||
float transport_speed() const { return _transport_speed; }
|
float transport_speed() const { return _transport_speed; }
|
||||||
bool transport_stopped() const { return _transport_speed == 0.0f; }
|
bool transport_stopped() const { return _transport_speed == 0.0f; }
|
||||||
bool transport_rolling() const { return _transport_speed != 0.0f; }
|
bool transport_rolling() const { return _transport_speed != 0.0f; }
|
||||||
|
|
||||||
|
|
@ -595,8 +595,8 @@ class Session : public PBD::StatefulDestructible
|
||||||
void remove_source (boost::weak_ptr<Source>);
|
void remove_source (boost::weak_ptr<Source>);
|
||||||
|
|
||||||
struct cleanup_report {
|
struct cleanup_report {
|
||||||
vector<string> paths;
|
vector<string> paths;
|
||||||
int64_t space;
|
int64_t space;
|
||||||
};
|
};
|
||||||
|
|
||||||
int cleanup_sources (cleanup_report&);
|
int cleanup_sources (cleanup_report&);
|
||||||
|
|
@ -673,8 +673,9 @@ class Session : public PBD::StatefulDestructible
|
||||||
|
|
||||||
/* flattening stuff */
|
/* flattening stuff */
|
||||||
|
|
||||||
int write_one_audio_track (AudioTrack&, nframes_t start, nframes_t cnt, bool overwrite, vector<boost::shared_ptr<Source> >&,
|
int write_one_audio_track (AudioTrack&, nframes_t start, nframes_t cnt, bool overwrite,
|
||||||
InterThreadInfo& wot);
|
vector<boost::shared_ptr<Source> >&, InterThreadInfo& wot);
|
||||||
|
|
||||||
int freeze (InterThreadInfo&);
|
int freeze (InterThreadInfo&);
|
||||||
|
|
||||||
/* session-wide solo/mute/rec-enable */
|
/* session-wide solo/mute/rec-enable */
|
||||||
|
|
@ -803,8 +804,8 @@ class Session : public PBD::StatefulDestructible
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalSoloStateCommand : public GlobalRouteStateCommand
|
class GlobalSoloStateCommand : public GlobalRouteStateCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GlobalSoloStateCommand (Session &, void *src);
|
GlobalSoloStateCommand (Session &, void *src);
|
||||||
GlobalSoloStateCommand (Session&, const XMLNode&);
|
GlobalSoloStateCommand (Session&, const XMLNode&);
|
||||||
|
|
@ -812,10 +813,10 @@ class Session : public PBD::StatefulDestructible
|
||||||
void undo();
|
void undo();
|
||||||
XMLNode &get_state();
|
XMLNode &get_state();
|
||||||
void mark();
|
void mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalMuteStateCommand : public GlobalRouteStateCommand
|
class GlobalMuteStateCommand : public GlobalRouteStateCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GlobalMuteStateCommand(Session &, void *src);
|
GlobalMuteStateCommand(Session &, void *src);
|
||||||
GlobalMuteStateCommand (Session&, const XMLNode&);
|
GlobalMuteStateCommand (Session&, const XMLNode&);
|
||||||
|
|
@ -823,10 +824,10 @@ class Session : public PBD::StatefulDestructible
|
||||||
void undo();
|
void undo();
|
||||||
XMLNode &get_state();
|
XMLNode &get_state();
|
||||||
void mark();
|
void mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalRecordEnableStateCommand : public GlobalRouteStateCommand
|
class GlobalRecordEnableStateCommand : public GlobalRouteStateCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GlobalRecordEnableStateCommand(Session &, void *src);
|
GlobalRecordEnableStateCommand(Session &, void *src);
|
||||||
GlobalRecordEnableStateCommand (Session&, const XMLNode&);
|
GlobalRecordEnableStateCommand (Session&, const XMLNode&);
|
||||||
|
|
@ -834,10 +835,10 @@ class Session : public PBD::StatefulDestructible
|
||||||
void undo();
|
void undo();
|
||||||
XMLNode &get_state();
|
XMLNode &get_state();
|
||||||
void mark();
|
void mark();
|
||||||
};
|
};
|
||||||
|
|
||||||
class GlobalMeteringStateCommand : public Command
|
class GlobalMeteringStateCommand : public Command
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GlobalMeteringStateCommand(Session &, void *src);
|
GlobalMeteringStateCommand(Session &, void *src);
|
||||||
GlobalMeteringStateCommand (Session&, const XMLNode&);
|
GlobalMeteringStateCommand (Session&, const XMLNode&);
|
||||||
|
|
@ -852,7 +853,7 @@ class Session : public PBD::StatefulDestructible
|
||||||
void* src;
|
void* src;
|
||||||
GlobalRouteMeterState before;
|
GlobalRouteMeterState before;
|
||||||
GlobalRouteMeterState after;
|
GlobalRouteMeterState after;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* clicking */
|
/* clicking */
|
||||||
|
|
||||||
|
|
@ -861,14 +862,14 @@ class Session : public PBD::StatefulDestructible
|
||||||
/* tempo FX */
|
/* tempo FX */
|
||||||
|
|
||||||
struct TimeStretchRequest {
|
struct TimeStretchRequest {
|
||||||
boost::shared_ptr<ARDOUR::AudioRegion> region;
|
boost::shared_ptr<ARDOUR::AudioRegion> region;
|
||||||
float fraction; /* session: read ; GUI: write */
|
float fraction; /* session: read ; GUI: write */
|
||||||
float progress; /* session: write ; GUI: read */
|
float progress; /* session: write ; GUI: read */
|
||||||
bool running; /* read/write */
|
bool running; /* read/write */
|
||||||
bool quick_seek; /* GUI: write */
|
bool quick_seek; /* GUI: write */
|
||||||
bool antialias; /* GUI: write */
|
bool antialias; /* GUI: write */
|
||||||
|
|
||||||
TimeStretchRequest () {}
|
TimeStretchRequest () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::shared_ptr<AudioRegion> tempoize_region (TimeStretchRequest&);
|
boost::shared_ptr<AudioRegion> tempoize_region (TimeStretchRequest&);
|
||||||
|
|
@ -1088,9 +1089,9 @@ class Session : public PBD::StatefulDestructible
|
||||||
bool session_midi_feedback;
|
bool session_midi_feedback;
|
||||||
bool play_loop;
|
bool play_loop;
|
||||||
bool loop_changing;
|
bool loop_changing;
|
||||||
nframes_t last_loopend;
|
nframes_t last_loopend;
|
||||||
|
|
||||||
boost::scoped_ptr<SessionDirectory> _session_dir;
|
boost::scoped_ptr<SessionDirectory> _session_dir;
|
||||||
|
|
||||||
RingBuffer<Event*> pending_events;
|
RingBuffer<Event*> pending_events;
|
||||||
|
|
||||||
|
|
@ -1110,11 +1111,11 @@ class Session : public PBD::StatefulDestructible
|
||||||
int load_state (string snapshot_name);
|
int load_state (string snapshot_name);
|
||||||
bool save_config_options_predicate (ConfigVariableBase::Owner owner) const;
|
bool save_config_options_predicate (ConfigVariableBase::Owner owner) const;
|
||||||
|
|
||||||
nframes_t _last_roll_location;
|
nframes_t _last_roll_location;
|
||||||
nframes_t _last_record_location;
|
nframes_t _last_record_location;
|
||||||
bool pending_locate_roll;
|
|
||||||
nframes_t pending_locate_frame;
|
|
||||||
|
|
||||||
|
bool pending_locate_roll;
|
||||||
|
nframes_t pending_locate_frame;
|
||||||
bool pending_locate_flush;
|
bool pending_locate_flush;
|
||||||
bool pending_abort;
|
bool pending_abort;
|
||||||
bool pending_auto_loop;
|
bool pending_auto_loop;
|
||||||
|
|
@ -1123,7 +1124,7 @@ class Session : public PBD::StatefulDestructible
|
||||||
float* butler_gain_buffer;
|
float* butler_gain_buffer;
|
||||||
pthread_t butler_thread;
|
pthread_t butler_thread;
|
||||||
Glib::Mutex butler_request_lock;
|
Glib::Mutex butler_request_lock;
|
||||||
Glib::Cond butler_paused;
|
Glib::Cond butler_paused;
|
||||||
bool butler_should_run;
|
bool butler_should_run;
|
||||||
mutable gint butler_should_do_transport_work;
|
mutable gint butler_should_do_transport_work;
|
||||||
int butler_request_pipe[2];
|
int butler_request_pipe[2];
|
||||||
|
|
@ -1512,13 +1513,13 @@ class Session : public PBD::StatefulDestructible
|
||||||
|
|
||||||
/* INSERT AND SEND MANAGEMENT */
|
/* INSERT AND SEND MANAGEMENT */
|
||||||
|
|
||||||
list<PortInsert *> _port_inserts;
|
list<PortInsert *> _port_inserts;
|
||||||
list<PluginInsert *> _plugin_inserts;
|
list<PluginInsert *> _plugin_inserts;
|
||||||
list<Send *> _sends;
|
list<Send *> _sends;
|
||||||
boost::dynamic_bitset<uint32_t> send_bitset;
|
boost::dynamic_bitset<uint32_t> send_bitset;
|
||||||
boost::dynamic_bitset<uint32_t> insert_bitset;
|
boost::dynamic_bitset<uint32_t> insert_bitset;
|
||||||
uint32_t send_cnt;
|
uint32_t send_cnt;
|
||||||
uint32_t insert_cnt;
|
uint32_t insert_cnt;
|
||||||
|
|
||||||
|
|
||||||
void add_processor (Processor *);
|
void add_processor (Processor *);
|
||||||
|
|
@ -1605,7 +1606,7 @@ class Session : public PBD::StatefulDestructible
|
||||||
pool.release (ptr);
|
pool.release (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Pool pool;
|
static Pool pool;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1620,9 +1621,9 @@ class Session : public PBD::StatefulDestructible
|
||||||
nframes_t click_emphasis_length;
|
nframes_t click_emphasis_length;
|
||||||
mutable Glib::RWLock click_lock;
|
mutable Glib::RWLock click_lock;
|
||||||
|
|
||||||
static const Sample default_click[];
|
static const Sample default_click[];
|
||||||
static const nframes_t default_click_length;
|
static const nframes_t default_click_length;
|
||||||
static const Sample default_click_emphasis[];
|
static const Sample default_click_emphasis[];
|
||||||
static const nframes_t default_click_emphasis_length;
|
static const nframes_t default_click_emphasis_length;
|
||||||
|
|
||||||
Click *get_click();
|
Click *get_click();
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,16 @@
|
||||||
#include <ardour/midi_model.h>
|
#include <ardour/midi_model.h>
|
||||||
#include <ardour/midi_events.h>
|
#include <ardour/midi_events.h>
|
||||||
#include <ardour/types.h>
|
#include <ardour/types.h>
|
||||||
|
#include <ardour/session.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
||||||
|
|
||||||
MidiModel::MidiModel(size_t size)
|
MidiModel::MidiModel(Session& s, size_t size)
|
||||||
: _notes(size)
|
: _session(s)
|
||||||
|
, _notes(size)
|
||||||
|
, _command(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,3 +143,98 @@ MidiModel::append_note_off(double time, uint8_t note_num)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::add_note(const Note& note)
|
||||||
|
{
|
||||||
|
Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note, NoteTimeComparator());
|
||||||
|
_notes.insert(i, note);
|
||||||
|
if (_command)
|
||||||
|
_command->add_note(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::remove_note(const Note& note)
|
||||||
|
{
|
||||||
|
Notes::iterator n = find(_notes.begin(), _notes.end(), note);
|
||||||
|
if (n != _notes.end())
|
||||||
|
_notes.erase(n);
|
||||||
|
|
||||||
|
if (_command)
|
||||||
|
_command->remove_note(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::begin_command()
|
||||||
|
{
|
||||||
|
assert(!_command);
|
||||||
|
_session.begin_reversible_command("midi edit");
|
||||||
|
_command = new MidiEditCommand(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::finish_command()
|
||||||
|
{
|
||||||
|
_session.commit_reversible_command(_command);
|
||||||
|
_command = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MidiEditCommand
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::MidiEditCommand::add_note(const Note& note)
|
||||||
|
{
|
||||||
|
//cerr << "MEC: apply" << endl;
|
||||||
|
|
||||||
|
_removed_notes.remove(note);
|
||||||
|
_added_notes.push_back(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::MidiEditCommand::remove_note(const Note& note)
|
||||||
|
{
|
||||||
|
//cerr << "MEC: remove" << endl;
|
||||||
|
|
||||||
|
_added_notes.remove(note);
|
||||||
|
_removed_notes.push_back(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::MidiEditCommand::operator()()
|
||||||
|
{
|
||||||
|
//cerr << "MEC: apply" << endl;
|
||||||
|
assert(!_model.current_command());
|
||||||
|
|
||||||
|
for (std::list<Note>::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i)
|
||||||
|
_model.add_note(*i);
|
||||||
|
|
||||||
|
for (std::list<Note>::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i)
|
||||||
|
_model.remove_note(*i);
|
||||||
|
|
||||||
|
_model.ContentsChanged(); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiModel::MidiEditCommand::undo()
|
||||||
|
{
|
||||||
|
//cerr << "MEC: undo" << endl;
|
||||||
|
assert(!_model.current_command());
|
||||||
|
|
||||||
|
for (std::list<Note>::iterator i = _added_notes.begin(); i != _added_notes.end(); ++i)
|
||||||
|
_model.remove_note(*i);
|
||||||
|
|
||||||
|
for (std::list<Note>::iterator i = _removed_notes.begin(); i != _removed_notes.end(); ++i)
|
||||||
|
_model.add_note(*i);
|
||||||
|
|
||||||
|
_model.ContentsChanged(); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ sigc::signal<void,MidiSource *> MidiSource::MidiSourceCreated;
|
||||||
|
|
||||||
MidiSource::MidiSource (Session& s, string name)
|
MidiSource::MidiSource (Session& s, string name)
|
||||||
: Source (s, name, DataType::MIDI)
|
: Source (s, name, DataType::MIDI)
|
||||||
, _model(new MidiModel())
|
, _model(new MidiModel(s))
|
||||||
, _model_loaded (false)
|
, _model_loaded (false)
|
||||||
{
|
{
|
||||||
_read_data_count = 0;
|
_read_data_count = 0;
|
||||||
|
|
@ -53,7 +53,7 @@ MidiSource::MidiSource (Session& s, string name)
|
||||||
|
|
||||||
MidiSource::MidiSource (Session& s, const XMLNode& node)
|
MidiSource::MidiSource (Session& s, const XMLNode& node)
|
||||||
: Source (s, node)
|
: Source (s, node)
|
||||||
, _model(new MidiModel())
|
, _model(new MidiModel(s))
|
||||||
, _model_loaded (false)
|
, _model_loaded (false)
|
||||||
{
|
{
|
||||||
_read_data_count = 0;
|
_read_data_count = 0;
|
||||||
|
|
|
||||||
|
|
@ -787,7 +787,7 @@ SMFSource::load_model(bool lock, bool force_reload)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! _model)
|
if (! _model)
|
||||||
_model = new MidiModel();
|
_model = new MidiModel(_session);
|
||||||
|
|
||||||
_model->start_write();
|
_model->start_write();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue