summaryrefslogtreecommitdiff
path: root/gtk2_ardour/midi_time_axis.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2_ardour/midi_time_axis.cc')
-rw-r--r--gtk2_ardour/midi_time_axis.cc175
1 files changed, 166 insertions, 9 deletions
diff --git a/gtk2_ardour/midi_time_axis.cc b/gtk2_ardour/midi_time_axis.cc
index c8cd5fe464..33315cfaa6 100644
--- a/gtk2_ardour/midi_time_axis.cc
+++ b/gtk2_ardour/midi_time_axis.cc
@@ -28,7 +28,9 @@
#include "pbd/error.h"
#include "pbd/stl_delete.h"
#include "pbd/whitespace.h"
+#include "pbd/basename.h"
#include "pbd/enumwriter.h"
+#include "pbd/memento_command.h"
#include <gtkmm2ext/gtk_ui.h>
#include <gtkmm2ext/selector.h>
@@ -39,40 +41,44 @@
#include "ardour/midi_playlist.h"
#include "ardour/midi_diskstream.h"
#include "ardour/midi_patch_manager.h"
+#include "ardour/midi_source.h"
#include "ardour/processor.h"
#include "ardour/ladspa_plugin.h"
#include "ardour/location.h"
#include "ardour/playlist.h"
+#include "ardour/region_factory.h"
#include "ardour/session.h"
#include "ardour/session_playlist.h"
+#include "ardour/tempo.h"
#include "ardour/utils.h"
+#include "add_midi_cc_track_dialog.h"
#include "ardour_ui.h"
-#include "midi_time_axis.h"
-#include "automation_time_axis.h"
#include "automation_line.h"
-#include "add_midi_cc_track_dialog.h"
+#include "automation_time_axis.h"
+#include "canvas-note-event.h"
#include "canvas_impl.h"
#include "crossfade_view.h"
+#include "editor.h"
#include "enums.h"
+#include "ghostregion.h"
#include "gui_thread.h"
#include "keyboard.h"
+#include "midi_scroomer.h"
+#include "midi_streamview.h"
+#include "midi_region_view.h"
+#include "midi_time_axis.h"
+#include "piano_roll_header.h"
#include "playlist_selector.h"
#include "plugin_selector.h"
#include "plugin_ui.h"
#include "point_selection.h"
#include "prompter.h"
-#include "public_editor.h"
#include "region_view.h"
#include "rgb_macros.h"
#include "selection.h"
#include "simplerect.h"
-#include "midi_streamview.h"
#include "utils.h"
-#include "midi_scroomer.h"
-#include "piano_roll_header.h"
-#include "ghostregion.h"
-#include "canvas-note-event.h"
#include "ardour/midi_track.h"
@@ -553,3 +559,154 @@ MidiTimeAxisView::route_active_changed ()
}
}
+void
+MidiTimeAxisView::build_rec_context_menu ()
+{
+ using namespace Menu_Helpers;
+
+ if (!is_track()) {
+ return;
+ }
+
+ rec_context_menu = manage (new Menu);
+ rec_context_menu->set_name ("ArdourContextMenu");
+
+ MenuList& items = rec_context_menu->items();
+
+ items.push_back (CheckMenuElem (_("Step Edit"),
+ (mem_fun (*this, &MidiTimeAxisView::toggle_step_editing))));
+ _step_edit_item = dynamic_cast<CheckMenuItem*>(&items.back());
+ _step_edit_item->set_active (midi_track()->step_editing());
+}
+
+void
+MidiTimeAxisView::toggle_step_editing ()
+{
+ if (!is_track()) {
+ return;
+ }
+
+ bool yn = _step_edit_item->get_active();
+
+ if (yn) {
+ start_step_editing ();
+ } else {
+ stop_step_editing ();
+ }
+
+ midi_track()->set_step_editing (yn);
+}
+
+void
+MidiTimeAxisView::start_step_editing ()
+{
+ step_edit_connection = Glib::signal_timeout().connect (mem_fun (*this, &MidiTimeAxisView::check_step_edit), 20);
+ step_edit_insert_position = _editor.get_preferred_edit_position ();
+ step_edit_beat_pos = 0;
+ step_edit_region = playlist()->top_region_at (step_edit_insert_position);
+
+ if (step_edit_region) {
+ RegionView* rv = view()->find_view (step_edit_region);
+ step_edit_region_view = dynamic_cast<MidiRegionView*> (rv);
+ } else {
+ step_edit_region_view = 0;
+ }
+}
+
+void
+MidiTimeAxisView::stop_step_editing ()
+{
+ step_edit_connection.disconnect ();
+}
+
+bool
+MidiTimeAxisView::check_step_edit ()
+{
+ MidiRingBuffer<nframes_t>& incoming (midi_track()->step_edit_ring_buffer());
+ Evoral::Note<Evoral::MusicalTime> note;
+ uint8_t* buf;
+ uint32_t bufsize = 32;
+
+ buf = new uint8_t[bufsize];
+
+ while (incoming.read_space()) {
+ nframes_t time;
+ Evoral::EventType type;
+ uint32_t size;
+
+ incoming.read_prefix (&time, &type, &size);
+
+ if (size > bufsize) {
+ delete [] buf;
+ bufsize = size;
+ buf = new uint8_t[bufsize];
+ }
+
+ incoming.read_contents (size, buf);
+
+ if ((buf[0] & 0xf0) == MIDI_CMD_NOTE_ON) {
+
+ if (step_edit_region == 0) {
+ cerr << "Add new region first ..\n";
+
+ step_edit_region = add_region (step_edit_insert_position);
+ RegionView* rv = view()->find_view (step_edit_region);
+
+ if (rv) {
+ step_edit_region_view = dynamic_cast<MidiRegionView*>(rv);
+ } else {
+ fatal << X_("programming error: no view found for new MIDI region") << endmsg;
+ /*NOTREACHED*/
+ }
+ }
+
+ if (step_edit_region_view) {
+
+ bool success;
+ Evoral::MusicalTime beats = _editor.get_grid_type_as_beats (success, step_edit_insert_position);
+
+ if (!success) {
+ continue;
+ }
+
+ cerr << "will add note at " << step_edit_beat_pos << endl;
+ step_edit_region_view->add_note (buf[0] & 0xf, buf[1], buf[2], step_edit_beat_pos, beats);
+ step_edit_beat_pos += beats;
+ }
+ }
+
+ }
+
+ return true; /* keep checking */
+}
+
+boost::shared_ptr<Region>
+MidiTimeAxisView::add_region (nframes64_t pos)
+{
+ Editor* real_editor = dynamic_cast<Editor*> (&_editor);
+
+ real_editor->begin_reversible_command (_("create region"));
+ XMLNode &before = playlist()->get_state();
+
+ nframes64_t start = pos;
+ real_editor->snap_to (start, -1);
+ const Meter& m = _session.tempo_map().meter_at(start);
+ const Tempo& t = _session.tempo_map().tempo_at(start);
+ double length = floor (m.frames_per_bar(t, _session.frame_rate()));
+
+ const boost::shared_ptr<MidiDiskstream> diskstream =
+ boost::dynamic_pointer_cast<MidiDiskstream>(view()->trackview().track()->diskstream());
+
+ boost::shared_ptr<Source> src = _session.create_midi_source_for_session (*diskstream.get());
+
+ boost::shared_ptr<Region> region = (RegionFactory::create (src, 0, (nframes_t) length,
+ PBD::basename_nosuffix(src->name())));
+
+ playlist()->add_region (region, start);
+ XMLNode &after = playlist()->get_state();
+ _session.add_command (new MementoCommand<Playlist> (*playlist().get(), &before, &after));
+
+ real_editor->commit_reversible_command();
+
+ return region;
+}