+
+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.
+ */
+ _temporary_note_group = new ArdourCanvas::Group (*group->property_parent ());
+ _temporary_note_group->move (group->property_x(), group->property_y());
+ _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 ();
+ }
+}
+
+/** @return channel (counted from 0) to add an event to, based on the current setting
+ * of the channel selector.
+ */
+uint8_t
+MidiRegionView::get_channel_for_add () const
+{
+ MidiTimeAxisView* const mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
+ uint16_t const chn_mask = mtv->channel_selector().get_selected_channels();
+ int chn_cnt = 0;
+ uint8_t channel = 0;
+
+ /* pick the highest selected channel, unless all channels are selected,
+ which is interpreted to mean channel 1 (zero)
+ */
+
+ for (uint16_t i = 0; i < 16; ++i) {
+ if (chn_mask & (1<<i)) {
+ channel = i;
+ chn_cnt++;
+ }
+ }
+
+ if (chn_cnt == 16) {
+ channel = 0;
+ }
+
+ return channel;
+}
+
+void
+MidiRegionView::edit_patch_change (ArdourCanvas::CanvasPatchChange* pc)
+{
+ PatchChangeDialog d (&_time_converter, trackview.session(), *pc->patch (), Gtk::Stock::APPLY);
+ if (d.run () != Gtk::RESPONSE_ACCEPT) {
+ return;
+ }
+
+ change_patch_change (pc->patch(), d.patch ());
+}