#include "sys_ex.h"
#include "ui_config.h"
-#include "i18n.h"
+#include "pbd/i18n.h"
using namespace ARDOUR;
using namespace PBD;
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
, _step_edit_cursor_width (1.0)
, _step_edit_cursor_position (0.0)
, _channel_selection_scoped_note (0)
- , _temporary_note_group (0)
, _mouse_state(None)
, _pressed_button(0)
, _sort_needed (true)
RegionView::init (false);
- set_height (trackview.current_height());
+ //set_height (trackview.current_height());
region_muted ();
region_sync_changed ();
region_resized (ARDOUR::bounds_change);
- region_locked ();
+ //region_locked ();
set_colors ();
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
MidiStreamView* const view = mtv->midi_view();
+ boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion> (_region);
+
+ if (!mr) {
+ return;
+ }
// Start of note in frames relative to region start
+ uint32_t divisions = 0;
+
if (snap_t) {
framecnt_t grid_frames;
t = snap_frame_to_grid_underneath (t, grid_frames);
+ divisions = trackview.editor().get_grid_music_divisions (0);
}
- const MidiModel::TimeType beat_time = region_frames_to_region_beats(
- t + _region->start());
+ const MidiModel::TimeType beat_time = Evoral::Beats (trackview.session()->tempo_map().exact_beat_at_frame (_region->position() + t, divisions)
+ - (mr->beat() - mr->start_beats().to_double()));
const double note = view->y_to_note(y);
const uint8_t chan = mtv->get_channel_for_add();
const uint8_t velocity = get_velocity_for_add(beat_time);
_optimization_iterator = _events.begin();
bool empty_when_starting = _events.empty();
+ NoteBase* cne;
for (MidiModel::Notes::iterator n = notes.begin(); n != notes.end(); ++n) {
boost::shared_ptr<NoteType> note (*n);
- NoteBase* cne;
bool visible;
if (note_in_region_range (note, visible)) {
if (!empty_when_starting && (cne = find_canvas_note (note)) != 0) {
- cne->validate ();
- update_note (cne);
-
if (visible) {
+ cne->validate ();
+ update_note (cne);
cne->show ();
} else {
cne->hide ();
delete _note_group;
delete _note_diff_command;
delete _step_edit_cursor;
- delete _temporary_note_group;
}
void
_region_relative_time_converter.set_origin_b(_region->position());
_region_relative_time_converter_double.set_origin_b(_region->position());
/* reset_width dependent_items() redisplays model */
+
}
if (what_changed.contains (ARDOUR::Properties::start) ||
what_changed.contains (ARDOUR::Properties::position)) {
_source_relative_time_converter.set_origin_b (_region->position() - _region->start());
}
+ /* catch end and start trim so we can update the view*/
+ if (!what_changed.contains (ARDOUR::Properties::start) &&
+ what_changed.contains (ARDOUR::Properties::length)) {
+ enable_display (true);
+ } else if (what_changed.contains (ARDOUR::Properties::start) &&
+ what_changed.contains (ARDOUR::Properties::length)) {
+ enable_display (true);
+ }
}
void
bool
MidiRegionView::note_in_region_range (const boost::shared_ptr<NoteType> note, bool& visible) const
{
- /* This is imprecise due to all the conversion conversion involved, so only
- hide notes if they seem to start more than one tick before the start. */
- const framecnt_t tick_frames = Evoral::Beats::tick().to_ticks(trackview.session()->frame_rate());
- const framepos_t note_start_frames = source_beats_to_region_frames (note->time());
- const bool outside = ((note_start_frames <= -tick_frames) ||
- (note_start_frames >= _region->length()));
+ const boost::shared_ptr<ARDOUR::MidiRegion> midi_reg = midi_region();
+ const bool outside = (note->time() < midi_reg->start_beats() ||
+ note->time() > midi_reg->start_beats() + midi_reg->length_beats());
visible = (note->note() >= midi_stream_view()->lowest_note()) &&
(note->note() <= midi_stream_view()->highest_note());
void
MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
{
+ TempoMap& map (trackview.session()->tempo_map());
+ const boost::shared_ptr<ARDOUR::MidiRegion> mr = midi_region();
boost::shared_ptr<NoteType> note = ev->note();
- const double x0 = trackview.editor().sample_to_pixel (source_beats_to_region_frames (note->time()));
+ const framepos_t note_start_frames = map.frame_at_beat (_region->beat() - mr->start_beats().to_double()
+ + note->time().to_double()) - _region->position();
+
+ const double x0 = trackview.editor().sample_to_pixel (note_start_frames);
double x1;
const double y0 = 1 + floor(midi_stream_view()->note_to_y(note->note()));
- double y1;
-
- /* trim note display to not overlap the end of its region */
+ double y1;/* trim note display to not overlap the end of its region */
if (note->length() > 0) {
- const framepos_t note_end_frames = min (source_beats_to_region_frames (note->end_time()), _region->length());
+ Evoral::Beats note_end_time = note->end_time();
+
+ if (note->end_time() > mr->start_beats() + mr->length_beats()) {
+ note_end_time = mr->start_beats() + mr->length_beats();
+ }
+
+ const framepos_t note_end_frames = map.frame_at_beat (_region->beat() - mr->start_beats().to_double()
+ + note_end_time.to_double()) - _region->position();
+
x1 = std::max(1., trackview.editor().sample_to_pixel (note_end_frames)) - 1;
} else {
x1 = std::max(1., trackview.editor().sample_to_pixel (_region->length())) - 1;
y1 = y0 + std::max(1., floor(midi_stream_view()->note_height()) - 1);
- ev->set_x0 (x0);
- ev->set_x1 (x1);
- ev->set_y0 (y0);
- ev->set_y1 (y1);
+ ArdourCanvas::Rect rect (x0, y0, x1, y1);
+ ev->set (rect);
if (!note->length()) {
if (_active_notes && note->note() < 128) {
}
// Update color in case velocity has changed
- //ev->set_fill_color(ev->base_color());
- //ev->set_outline_color(ev->calculate_outline(ev->base_color(), ev->selected()));
+ //const uint32_t base_col = ev->base_color();
+ //ev->set_fill_color(base_col);
+ //ev->set_outline_color(ev->calculate_outline(base_col, ev->selected()));
if (update_ghost_regions) {
for (std::vector<GhostRegion*>::iterator i = ghosts.begin(); i != ghosts.end(); ++i) {
{
boost::shared_ptr<NoteType> note = ev->note();
- const framepos_t note_start_frames = source_beats_to_region_frames(note->time());
+ const framepos_t note_start_frames = trackview.session()->tempo_map().frame_at_beat (_region->beat() - midi_region()->start_beats().to_double()
+ + note->time().to_double()) - _region->position();
const double x = trackview.editor().sample_to_pixel(note_start_frames);
const double diamond_size = std::max(1., floor(midi_stream_view()->note_height()) - 2.);
const double y = 1.5 + floor(midi_stream_view()->note_to_y(note->note())) + diamond_size * .5;
framepos_t region_end = _region->last_frame();
if (end_frame > region_end) {
- _region->set_length (end_frame - _region->position());
+ /* XX sets length in beats from audio space. make musical */
+ _region->set_length (end_frame - _region->position(), 0);
}
MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
void
MidiRegionView::update_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
{
+ TempoMap& tmap (trackview.session()->tempo_map());
bool cursor_set = false;
bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic;
sign = -1;
}
- const double snapped_x = (with_snap ? snap_pixel_to_sample (current_x, ensure_snap) : trackview.editor ().pixel_to_sample (current_x));
- Evoral::Beats beats = region_frames_to_region_beats (snapped_x);
- Evoral::Beats len = Evoral::Beats();
+ double snapped_x;
+ uint32_t divisions = 0;
+
+ if (with_snap) {
+ snapped_x = snap_pixel_to_sample (current_x, ensure_snap);
+ divisions = trackview.editor().get_grid_music_divisions (0);
+ } else {
+ snapped_x = trackview.editor ().pixel_to_sample (current_x);
+ }
+ const Evoral::Beats beats = Evoral::Beats (tmap.exact_beat_at_frame (snapped_x + midi_region()->position(), divisions)
+ - midi_region()->beat()) + midi_region()->start_beats();
+
+ Evoral::Beats len = Evoral::Beats();
if (at_front) {
if (beats < canvas_note->note()->end_time()) {
MidiRegionView::commit_resizing (NoteBase* primary, bool at_front, double delta_x, bool relative, double snap_delta, bool with_snap)
{
_note_diff_command = _model->new_note_diff_command (_("resize notes"));
+ TempoMap& tmap (trackview.session()->tempo_map());
/* XX why doesn't snap_pixel_to_sample() handle this properly? */
bool const ensure_snap = trackview.editor().snap_mode () != SnapMagnetic;
sign = -1;
}
+ uint32_t divisions = 0;
/* Convert the new x position to a frame within the source */
framepos_t current_fr;
if (with_snap) {
- current_fr = snap_pixel_to_sample (current_x, ensure_snap) + _region->start ();
+ current_fr = snap_pixel_to_sample (current_x, ensure_snap);
+ divisions = trackview.editor().get_grid_music_divisions (0);
} else {
- current_fr = trackview.editor().pixel_to_sample (current_x) + _region->start ();
+ current_fr = trackview.editor().pixel_to_sample (current_x);
}
/* and then to beats */
- const Evoral::Beats x_beats = region_frames_to_region_beats (current_fr);
+ const Evoral::Beats x_beats = Evoral::Beats (tmap.exact_beat_at_frame (current_fr + midi_region()->position(), divisions)
+ - midi_region()->beat()) + midi_region()->start_beats();
if (at_front && x_beats < canvas_note->note()->end_time()) {
note_diff_add_change (canvas_note, MidiModel::NoteDiffCommand::StartTime, x_beats - (sign * snap_delta_beats));
if (!fine) {
/* non-fine, move by 1 bar regardless of snap */
- delta = Evoral::Beats(trackview.session()->tempo_map().meter_at(ref_point).divisions_per_bar());
+ delta = Evoral::Beats(trackview.session()->tempo_map().meter_at_frame (ref_point).divisions_per_bar());
} else if (trackview.editor().snap_mode() == Editing::SnapOff) {
MidiRegionView::patch_entered (PatchChange* p)
{
ostringstream s;
- /* XXX should get patch name if we can */
s << _("Bank ") << (p->patch()->bank() + MIDI_BP_ZERO) << '\n'
- << _("Program ") << ((int) p->patch()->program()) + MIDI_BP_ZERO << '\n'
+ << instrument_info().get_patch_name_without (p->patch()->bank(), p->patch()->program(), p->patch()->channel()) << '\n'
<< _("Channel ") << ((int) p->patch()->channel() + 1);
show_verbose_cursor (s.str(), 10, 20);
p->item().grab_focus();
/** This method handles undo */
bool
-MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx)
+MidiRegionView::paste (framepos_t pos, const ::Selection& selection, PasteContext& ctx, const int32_t sub_num)
{
bool commit = false;
// Paste notes, if available
typedef RouteTimeAxisView::AutomationTracks ATracks;
const ATracks& atracks = midi_view()->automation_tracks();
for (ATracks::const_iterator a = atracks.begin(); a != atracks.end(); ++a) {
- if (a->second->paste(pos, selection, ctx)) {
+ if (a->second->paste(pos, selection, ctx, sub_num)) {
commit = true;
}
}
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("Paste extended region from %1 to %2\n", region_end, end_frame));
_region->clear_changes ();
- _region->set_length (end_frame - _region->position());
+ /* we probably need to get the snap modifier somehow to make this correct for non-musical use */
+ _region->set_length (end_frame - _region->position(), trackview.editor().get_grid_music_divisions (0));
trackview.session()->add_command (new StatefulDiffCommand (_region));
}
MidiRegionView::enable_display (bool yn)
{
RegionView::enable_display (yn);
- if (yn) {
- redisplay_model ();
- }
}
void
_step_edit_cursor_width = beats;
if (_step_edit_cursor) {
- _step_edit_cursor->set_x1 (_step_edit_cursor->x0() + trackview.editor().sample_to_pixel (region_beats_to_region_frames (beats)));
+ _step_edit_cursor->set_x1 (_step_edit_cursor->x0() + trackview.editor().sample_to_pixel (
+ region_beats_to_region_frames (_step_edit_cursor_position + beats)
+ - region_beats_to_region_frames (_step_edit_cursor_position)));
}
}
void
MidiRegionView::trim_front_starting ()
{
- /* Reparent the note group to the region view's parent, so that it doesn't change
- when the region view is trimmed.
+ /* We used to eparent the note group to the region view's parent, so that it didn't change.
+ now we update it.
*/
- _temporary_note_group = new ArdourCanvas::Container (group->parent ());
- _temporary_note_group->move (group->position ());
- _note_group->reparent (_temporary_note_group);
}
void
MidiRegionView::trim_front_ending ()
{
- _note_group->reparent (group);
- delete _temporary_note_group;
- _temporary_note_group = 0;
-
if (_region->start() < 0) {
/* Trim drag made start time -ve; fix this */
midi_region()->fix_negative_start ();
char buf[128];
snprintf (buf, sizeof (buf), "%d %s\nCh %d Vel %d",
(int) note_value,
- name.empty() ? Evoral::midi_note_name (note_value).c_str() : name.c_str(),
+ name.empty() ? ParameterDescriptor::midi_note_name (note_value).c_str() : name.c_str(),
(int) n->channel() + 1,
(int) n->velocity());
MidiRegionView::snap_frame_to_grid_underneath (framepos_t p, framecnt_t& grid_frames) const
{
PublicEditor& editor = trackview.editor ();
- const Evoral::Beats p_beat = region_frames_to_region_beats (p);
const Evoral::Beats grid_beats = get_grid_beats(p);
+ const Evoral::Beats p_beat = max (Evoral::Beats(), region_frames_to_region_beats (p));
grid_frames = region_beats_to_region_frames (p_beat + grid_beats) - region_beats_to_region_frames (p_beat);