From 7250433f50236a05fc652fa41c23bf53fbf6a0fd Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 16 Aug 2006 20:36:14 +0000 Subject: Progress on the disk side of things: - MidiRingBuffer implementation - MidiDiskstream reading from playlists - MidiPlaylist reading from regions - MidiRegions returning random notes for the time being, but the inter-thread stuff works.. Horrible awful mess, not really commit worthy, but I need to move machines. Nothing to see here.. :) git-svn-id: svn://localhost/ardour2/branches/midi@835 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor.cc | 66 ++--- gtk2_ardour/editor.h | 16 +- gtk2_ardour/editor_canvas_events.cc | 42 +-- gtk2_ardour/editor_imageframe.cc | 44 +-- gtk2_ardour/editor_mixer.cc | 4 +- gtk2_ardour/editor_mouse.cc | 44 +-- gtk2_ardour/editor_ops.cc | 46 +-- libs/ardour/ardour/audio_track.h | 4 - libs/ardour/ardour/buffer.h | 27 +- libs/ardour/ardour/buffer_set.h | 6 + libs/ardour/ardour/midi_diskstream.h | 23 +- libs/ardour/ardour/midi_playlist.h | 4 +- libs/ardour/ardour/midi_port.h | 16 +- libs/ardour/ardour/midi_region.h | 14 +- libs/ardour/ardour/midi_ring_buffer.h | 242 +++++++++++++++ libs/ardour/ardour/midi_track.h | 4 - libs/ardour/ardour/route.h | 5 +- libs/ardour/ardour/track.h | 3 - libs/ardour/ardour/types.h | 3 +- libs/ardour/audio_diskstream.cc | 2 +- libs/ardour/audio_track.cc | 6 - libs/ardour/buffer.cc | 93 ++++-- libs/ardour/io.cc | 9 +- libs/ardour/midi_diskstream.cc | 537 ++++++++++++++++++++-------------- libs/ardour/midi_playlist.cc | 32 +- libs/ardour/midi_port.cc | 40 ++- libs/ardour/midi_region.cc | 44 ++- libs/ardour/midi_track.cc | 81 ++--- libs/ardour/route.cc | 6 + libs/ardour/track.cc | 2 +- 30 files changed, 947 insertions(+), 518 deletions(-) create mode 100644 libs/ardour/ardour/midi_ring_buffer.h diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index b991982855..5c3847730c 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -239,8 +239,8 @@ Editor::Editor (AudioEngine& eng) selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed)); clicked_regionview = 0; - clicked_trackview = 0; - clicked_audio_trackview = 0; + clicked_axisview = 0; + clicked_routeview = 0; clicked_crossfadeview = 0; clicked_control_point = 0; latest_regionview = 0; @@ -1474,7 +1474,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, break; case StreamItem: - if (clicked_audio_trackview->get_diskstream()) { + if (clicked_routeview->is_track()) { build_menu_function = &Editor::build_track_context_menu; } else { build_menu_function = &Editor::build_track_bus_context_menu; @@ -1530,7 +1530,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, return; } - if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) { + if (clicked_routeview && clicked_routeview->audio_track()) { /* Bounce to disk */ @@ -1539,7 +1539,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, edit_items.push_back (SeparatorElem()); - switch (clicked_audio_trackview->audio_track()->freeze_state()) { + switch (clicked_routeview->audio_track()->freeze_state()) { case AudioTrack::NoFreeze: edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route))); break; @@ -1589,7 +1589,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame) MenuList& edit_items = track_region_context_menu.items(); edit_items.clear(); - AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); + AudioTimeAxisView* atv = dynamic_cast (clicked_axisview); if (atv) { Diskstream* ds; @@ -1616,7 +1616,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame) MenuList& edit_items = track_crossfade_context_menu.items(); edit_items.clear (); - AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); + AudioTimeAxisView* atv = dynamic_cast (clicked_axisview); if (atv) { Diskstream* ds; @@ -2897,29 +2897,29 @@ Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool { bool commit = false; - if (!clicked_trackview) { + if (!clicked_axisview) { return false; } switch (op) { case Selection::Toggle: - if (selection->selected (clicked_trackview)) { + if (selection->selected (clicked_axisview)) { if (!no_remove) { - selection->remove (clicked_trackview); + selection->remove (clicked_axisview); commit = true; } } else { - selection->add (clicked_trackview); + selection->add (clicked_axisview); commit = false; } break; case Selection::Set: - if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) { + if (selection->selected (clicked_axisview) && selection->tracks.size() == 1) { /* no commit necessary */ } - selection->set (clicked_trackview); + selection->set (clicked_axisview); break; case Selection::Extend: @@ -2951,13 +2951,13 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation } void -Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set& relevant_tracks) +Editor::get_relevant_tracks (RouteTimeAxisView& base, set& relevant_tracks) { /* step one: get all selected tracks and all tracks in the relevant edit groups */ for (TrackSelection::iterator ti = selection->tracks.begin(); ti != selection->tracks.end(); ++ti) { - AudioTimeAxisView* atv = dynamic_cast(*ti); + RouteTimeAxisView* atv = dynamic_cast(*ti); if (!atv) { continue; @@ -2971,9 +2971,9 @@ Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set (*i)) != 0) { + if ((tatv = dynamic_cast (*i)) != 0) { if (tatv->route()->edit_group() == group) { relevant_tracks.insert (tatv); @@ -2992,19 +2992,19 @@ Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set sl) +Editor::mapover_tracks (slot sl) { - set relevant_tracks; + set relevant_tracks; - if (!clicked_audio_trackview) { + if (!clicked_routeview) { return; } - get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks); + get_relevant_tracks (*clicked_routeview, relevant_tracks); uint32_t sz = relevant_tracks.size(); - for (set::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) { + for (set::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) { sl (**ati, sz); } } @@ -3046,13 +3046,13 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, vector all_equivalent_regions; bool commit = false; - if (!clicked_regionview || !clicked_audio_trackview) { + if (!clicked_regionview || !clicked_routeview) { return false; } if (op == Selection::Toggle || op == Selection::Set) { - mapover_audio_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click), + mapover_tracks (bind (mem_fun (*this, &Editor::mapped_set_selected_regionview_from_click), clicked_regionview, &all_equivalent_regions)); @@ -3198,11 +3198,11 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, one that was clicked. */ - set relevant_tracks; + set relevant_tracks; - get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks); + get_relevant_tracks (*clicked_routeview, relevant_tracks); - for (set::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) { + for (set::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) { (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results); } @@ -4100,7 +4100,7 @@ void Editor::new_playlists () { begin_reversible_command (_("new playlists")); - mapover_audio_tracks (mem_fun (*this, &Editor::mapped_use_new_playlist)); + mapover_tracks (mem_fun (*this, &Editor::mapped_use_new_playlist)); commit_reversible_command (); } @@ -4108,7 +4108,7 @@ void Editor::copy_playlists () { begin_reversible_command (_("copy playlists")); - mapover_audio_tracks (mem_fun (*this, &Editor::mapped_use_copy_playlist)); + mapover_tracks (mem_fun (*this, &Editor::mapped_use_copy_playlist)); commit_reversible_command (); } @@ -4116,24 +4116,24 @@ void Editor::clear_playlists () { begin_reversible_command (_("clear playlists")); - mapover_audio_tracks (mem_fun (*this, &Editor::mapped_clear_playlist)); + mapover_tracks (mem_fun (*this, &Editor::mapped_clear_playlist)); commit_reversible_command (); } void -Editor::mapped_use_new_playlist (AudioTimeAxisView& atv, uint32_t sz) +Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz) { atv.use_new_playlist (sz > 1 ? false : true); } void -Editor::mapped_use_copy_playlist (AudioTimeAxisView& atv, uint32_t sz) +Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz) { atv.use_copy_playlist (sz > 1 ? false : true); } void -Editor::mapped_clear_playlist (AudioTimeAxisView& atv, uint32_t sz) +Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t sz) { atv.clear_playlist (); } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 3f2a278f09..40ece795b1 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -410,23 +410,23 @@ class Editor : public PublicEditor void clear_marker_display (); void mouse_add_new_marker (jack_nframes_t where); - TimeAxisView* clicked_trackview; - AudioTimeAxisView* clicked_audio_trackview; + TimeAxisView* clicked_axisview; + RouteTimeAxisView* clicked_routeview; RegionView* clicked_regionview; RegionView* latest_regionview; uint32_t clicked_selection; CrossfadeView* clicked_crossfadeview; ControlPoint* clicked_control_point; - void get_relevant_audio_tracks (AudioTimeAxisView& base, std::set& relevant_tracks); - void mapover_audio_tracks (sigc::slot sl); + void get_relevant_tracks (RouteTimeAxisView& base, std::set& relevant_tracks); + void mapover_tracks (sigc::slot sl); - /* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */ + /* functions to be passed to mapover_tracks(), possibly with sigc::bind()-supplied arguments */ void mapped_set_selected_regionview_from_click (RouteTimeAxisView&, uint32_t, RegionView*, vector*); - void mapped_use_new_playlist (AudioTimeAxisView&, uint32_t); - void mapped_use_copy_playlist (AudioTimeAxisView&, uint32_t); - void mapped_clear_playlist (AudioTimeAxisView&, uint32_t); + void mapped_use_new_playlist (RouteTimeAxisView&, uint32_t); + void mapped_use_copy_playlist (RouteTimeAxisView&, uint32_t); + void mapped_clear_playlist (RouteTimeAxisView&, uint32_t); /* end */ diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index 8e635bbe13..c6b5d1e1c5 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -222,8 +222,8 @@ Editor::canvas_region_view_event (GdkEvent *event, ArdourCanvas::Item* item, Reg case GDK_3BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &rv->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); ret = button_press_handler (item, event, RegionItem); break; @@ -261,8 +261,8 @@ Editor::canvas_stream_view_event (GdkEvent *event, ArdourCanvas::Item* item, Rou case GDK_3BUTTON_PRESS: clicked_regionview = 0; clicked_control_point = 0; - clicked_trackview = tv; - clicked_audio_trackview = dynamic_cast(tv); + clicked_axisview = tv; + clicked_routeview = dynamic_cast(tv); ret = button_press_handler (item, event, StreamItem); break; @@ -297,8 +297,8 @@ Editor::canvas_automation_track_event (GdkEvent *event, ArdourCanvas::Item* item case GDK_3BUTTON_PRESS: clicked_regionview = 0; clicked_control_point = 0; - clicked_trackview = atv; - clicked_audio_trackview = 0; + clicked_axisview = atv; + clicked_routeview = 0; ret = button_press_handler (item, event, AutomationTrackItem); break; @@ -334,8 +334,8 @@ Editor::canvas_fade_in_event (GdkEvent *event, ArdourCanvas::Item* item, AudioRe case GDK_BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &rv->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); if (event->button.button == 3) { return button_press_handler (item, event, FadeInItem); } @@ -368,8 +368,8 @@ Editor::canvas_fade_in_handle_event (GdkEvent *event, ArdourCanvas::Item* item, case GDK_3BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &rv->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); ret = button_press_handler (item, event, FadeInHandleItem); break; @@ -405,8 +405,8 @@ Editor::canvas_fade_out_event (GdkEvent *event, ArdourCanvas::Item* item, AudioR case GDK_BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &rv->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); if (event->button.button == 3) { return button_press_handler (item, event, FadeOutItem); } @@ -439,8 +439,8 @@ Editor::canvas_fade_out_handle_event (GdkEvent *event, ArdourCanvas::Item* item, case GDK_3BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &rv->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &rv->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); ret = button_press_handler (item, event, FadeOutHandleItem); break; @@ -481,7 +481,7 @@ Editor::canvas_crossfade_view_event (GdkEvent* event, ArdourCanvas::Item* item, switch (event->type) { case GDK_BUTTON_PRESS: clicked_crossfadeview = xfv; - clicked_trackview = &clicked_crossfadeview->get_time_axis_view(); + clicked_axisview = &clicked_crossfadeview->get_time_axis_view(); if (event->button.button == 3) { return button_press_handler (item, event, CrossfadeViewItem); } @@ -547,8 +547,8 @@ Editor::canvas_control_point_event (GdkEvent *event, ArdourCanvas::Item* item, C case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: clicked_control_point = cp; - clicked_trackview = &cp->line.trackview; - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &cp->line.trackview; + clicked_routeview = dynamic_cast(clicked_axisview); clicked_regionview = 0; break; @@ -709,8 +709,8 @@ Editor::canvas_region_view_name_highlight_event (GdkEvent* event, ArdourCanvas:: case GDK_3BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &clicked_regionview->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &clicked_regionview->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); ret = button_press_handler (item, event, RegionViewNameHighlight); break; case GDK_BUTTON_RELEASE: @@ -745,8 +745,8 @@ Editor::canvas_region_view_name_event (GdkEvent *event, ArdourCanvas::Item* item case GDK_3BUTTON_PRESS: clicked_regionview = rv; clicked_control_point = 0; - clicked_trackview = &clicked_regionview->get_time_axis_view(); - clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_axisview = &clicked_regionview->get_time_axis_view(); + clicked_routeview = dynamic_cast(clicked_axisview); ret = button_press_handler (item, event, RegionViewName); break; case GDK_BUTTON_RELEASE: diff --git a/gtk2_ardour/editor_imageframe.cc b/gtk2_ardour/editor_imageframe.cc index 6b8691b09f..2cabb95461 100644 --- a/gtk2_ardour/editor_imageframe.cc +++ b/gtk2_ardour/editor_imageframe.cc @@ -124,7 +124,7 @@ Editor::add_imageframe_marker_time_axis(const string & track_name, TimeAxisView* void Editor::popup_imageframe_edit_menu(int button, int32_t time, ArdourCanvas::Item* ifv, bool with_item) { - ImageFrameTimeAxis* ifta = dynamic_cast(clicked_trackview) ; + ImageFrameTimeAxis* ifta = dynamic_cast(clicked_axisview) ; if(ifta) { @@ -141,7 +141,7 @@ Editor::popup_imageframe_edit_menu(int button, int32_t time, ArdourCanvas::Item* void Editor::popup_marker_time_axis_edit_menu(int button, int32_t time, ArdourCanvas::Item* ifv, bool with_item) { - MarkerTimeAxis* mta = dynamic_cast(clicked_trackview) ; + MarkerTimeAxis* mta = dynamic_cast(clicked_axisview) ; if(mta) { @@ -188,9 +188,9 @@ Editor::canvas_imageframe_item_view_event (GdkEvent *event, ArdourCanvas::Item* case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = &ifv->get_time_axis_view(); + clicked_axisview = &ifv->get_time_axis_view(); iftag = ifv->get_time_axis_group() ; - dynamic_cast(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv); + dynamic_cast(clicked_axisview)->get_view()->set_selected_imageframe_view(iftag, ifv); ret = button_press_handler (item, event, ImageFrameItem) ; break ; case GDK_BUTTON_RELEASE: @@ -216,9 +216,9 @@ Editor::canvas_imageframe_start_handle_event (GdkEvent *event, ArdourCanvas::Ite case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = &ifv->get_time_axis_view() ; + clicked_axisview = &ifv->get_time_axis_view() ; iftag = ifv->get_time_axis_group() ; - dynamic_cast(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv); + dynamic_cast(clicked_axisview)->get_view()->set_selected_imageframe_view(iftag, ifv); ret = button_press_handler (item, event, ImageFrameHandleStartItem) ; break ; @@ -251,9 +251,9 @@ Editor::canvas_imageframe_end_handle_event (GdkEvent *event, ArdourCanvas::Item* case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = &ifv->get_time_axis_view() ; + clicked_axisview = &ifv->get_time_axis_view() ; iftag = ifv->get_time_axis_group() ; - dynamic_cast(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv); + dynamic_cast(clicked_axisview)->get_view()->set_selected_imageframe_view(iftag, ifv); ret = button_press_handler (item, event, ImageFrameHandleEndItem) ; break ; @@ -284,7 +284,7 @@ Editor::canvas_imageframe_view_event (GdkEvent* event, ArdourCanvas::Item* item, case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = ifta ; + clicked_axisview = ifta ; ret = button_press_handler (item, event, ImageFrameTimeAxisItem) ; break ; case GDK_BUTTON_RELEASE: @@ -307,7 +307,7 @@ Editor::canvas_marker_time_axis_view_event (GdkEvent* event, ArdourCanvas::Item* case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = mta ; + clicked_axisview = mta ; ret = button_press_handler(item, event, MarkerTimeAxisItem) ; break ; case GDK_BUTTON_RELEASE: @@ -330,8 +330,8 @@ Editor::canvas_markerview_item_view_event (GdkEvent* event, ArdourCanvas::Item* case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = &mta->get_time_axis_view() ; - dynamic_cast(clicked_trackview)->get_view()->set_selected_time_axis_item(mta); + clicked_axisview = &mta->get_time_axis_view() ; + dynamic_cast(clicked_axisview)->get_view()->set_selected_time_axis_item(mta); ret = button_press_handler(item, event, MarkerViewItem) ; break ; case GDK_BUTTON_RELEASE: @@ -355,8 +355,8 @@ Editor::canvas_markerview_start_handle_event (GdkEvent* event, ArdourCanvas::Ite case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = &mta->get_time_axis_view() ; - dynamic_cast(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ; + clicked_axisview = &mta->get_time_axis_view() ; + dynamic_cast(clicked_axisview)->get_view()->set_selected_time_axis_item(mta) ; ret = button_press_handler(item, event, MarkerViewHandleStartItem) ; break ; case GDK_BUTTON_RELEASE: @@ -386,8 +386,8 @@ Editor::canvas_markerview_end_handle_event (GdkEvent* event, ArdourCanvas::Item* case GDK_BUTTON_PRESS: case GDK_2BUTTON_PRESS: case GDK_3BUTTON_PRESS: - clicked_trackview = &mta->get_time_axis_view() ; - dynamic_cast(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ; + clicked_axisview = &mta->get_time_axis_view() ; + dynamic_cast(clicked_axisview)->get_view()->set_selected_time_axis_item(mta) ; ret = button_press_handler(item, event, MarkerViewHandleEndItem) ; break ; case GDK_BUTTON_RELEASE: @@ -425,7 +425,7 @@ Editor::canvas_markerview_end_handle_event (GdkEvent* event, ArdourCanvas::Item* void Editor::start_imageframe_grab(ArdourCanvas::Item* item, GdkEvent* event) { - ImageFrameView* ifv = ((ImageFrameTimeAxis*)clicked_trackview)->get_view()->get_selected_imageframe_view() ; + ImageFrameView* ifv = ((ImageFrameTimeAxis*)clicked_axisview)->get_view()->get_selected_imageframe_view() ; drag_info.copy = false ; drag_info.item = item ; drag_info.data = ifv ; @@ -458,7 +458,7 @@ Editor::start_imageframe_grab(ArdourCanvas::Item* item, GdkEvent* event) void Editor::start_markerview_grab(ArdourCanvas::Item* item, GdkEvent* event) { - MarkerView* mv = ((MarkerTimeAxis*)clicked_trackview)->get_view()->get_selected_time_axis_item() ; + MarkerView* mv = ((MarkerTimeAxis*)clicked_axisview)->get_view()->get_selected_time_axis_item() ; drag_info.copy = false ; drag_info.item = item ; drag_info.data = mv ; @@ -616,7 +616,7 @@ void Editor::imageframe_start_handle_op(ArdourCanvas::Item* item, GdkEvent* event) { // get the selected item from the parent time axis - ImageFrameTimeAxis* ifta = dynamic_cast(clicked_trackview) ; + ImageFrameTimeAxis* ifta = dynamic_cast(clicked_axisview) ; if(ifta) { ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ; @@ -644,7 +644,7 @@ void Editor::imageframe_end_handle_op(ArdourCanvas::Item* item, GdkEvent* event) { // get the selected item from the parent time axis - ImageFrameTimeAxis* ifta = dynamic_cast(clicked_trackview) ; + ImageFrameTimeAxis* ifta = dynamic_cast(clicked_axisview) ; if(ifta) { @@ -841,7 +841,7 @@ Editor::imageframe_end_handle_end_trim (ArdourCanvas::Item* item, GdkEvent* even void Editor::markerview_item_start_handle_op(ArdourCanvas::Item* item, GdkEvent* event) { - MarkerView* mv = reinterpret_cast(clicked_trackview)->get_view()->get_selected_time_axis_item() ; + MarkerView* mv = reinterpret_cast(clicked_axisview)->get_view()->get_selected_time_axis_item() ; if (mv == 0) { @@ -864,7 +864,7 @@ Editor::markerview_item_start_handle_op(ArdourCanvas::Item* item, GdkEvent* even void Editor::markerview_item_end_handle_op(ArdourCanvas::Item* item, GdkEvent* event) { - MarkerView* mv = reinterpret_cast(clicked_trackview)->get_view()->get_selected_time_axis_item() ; + MarkerView* mv = reinterpret_cast(clicked_axisview)->get_view()->get_selected_time_axis_item() ; if (mv == 0) { fatal << _("programming error: no MarkerView selected") << endmsg ; diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index 9fa1a0b0b6..0e50df2137 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -258,8 +258,8 @@ Editor::session_going_away () cut_buffer->clear (); clicked_regionview = 0; - clicked_trackview = 0; - clicked_audio_trackview = 0; + clicked_axisview = 0; + clicked_routeview = 0; clicked_crossfadeview = 0; entered_regionview = 0; entered_track = 0; diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index f459f24341..eb0bd432e3 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -758,10 +758,10 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp scroll_tracks_up_line (); } else { if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { - if (clicked_trackview) { + if (clicked_axisview) { if (!current_stepping_trackview) { step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); - current_stepping_trackview = clicked_trackview; + current_stepping_trackview = clicked_axisview; } gettimeofday (&last_track_height_step_timestamp, 0); current_stepping_trackview->step_height (true); @@ -795,10 +795,10 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp scroll_tracks_down_line (); } else { if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { - if (clicked_trackview) { + if (clicked_axisview) { if (!current_stepping_trackview) { step_timeout = Glib::signal_timeout().connect (mem_fun(*this, &Editor::track_height_step_timeout), 500); - current_stepping_trackview = clicked_trackview; + current_stepping_trackview = clicked_axisview; } gettimeofday (&last_track_height_step_timestamp, 0); current_stepping_trackview->step_height (false); @@ -1036,7 +1036,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT case MouseObject: switch (item_type) { case AutomationTrackItem: - dynamic_cast(clicked_trackview)->add_automation_event + dynamic_cast(clicked_axisview)->add_automation_event (item, event, where, @@ -1061,7 +1061,7 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT break; case AutomationTrackItem: - dynamic_cast(clicked_trackview)-> + dynamic_cast(clicked_axisview)-> add_automation_event (item, event, where, event->button.y); return true; break; @@ -2679,7 +2679,7 @@ Editor::start_region_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab (event); double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_track()) { @@ -2743,7 +2743,7 @@ Editor::start_region_brush_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab (event); double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_track()) { @@ -3633,7 +3633,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) */ latest_regionview = 0; - sigc::connection c = clicked_audio_trackview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); + sigc::connection c = clicked_routeview->view()->RegionViewAdded.connect (mem_fun(*this, &Editor::collect_new_region_view)); /* A selection grab currently creates two undo/redo operations, one for creating the new region and another for moving it. @@ -3641,10 +3641,10 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) begin_reversible_command (_("selection grab")); - Playlist* playlist = clicked_trackview->playlist(); + Playlist* playlist = clicked_axisview->playlist(); before = &(playlist->get_state()); - clicked_trackview->playlist()->add_region (*region, selection->time[clicked_selection].start); + clicked_axisview->playlist()->add_region (*region, selection->time[clicked_selection].start); XMLNode &after = playlist->get_state(); session->add_command(new MementoCommand(*playlist, *before, after)); @@ -3668,7 +3668,7 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event) start_grab (event); - drag_info.last_trackview = clicked_trackview; + drag_info.last_trackview = clicked_axisview; drag_info.last_frame_position = latest_regionview->region().position(); drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; @@ -3714,8 +3714,8 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection break; case SelectionStartTrim: - if (clicked_trackview) { - clicked_trackview->order_selection_trims (item, true); + if (clicked_axisview) { + clicked_axisview->order_selection_trims (item, true); } start_grab (event, trimmer_cursor); start = selection->time[clicked_selection].start; @@ -3723,8 +3723,8 @@ Editor::start_selection_op (ArdourCanvas::Item* item, GdkEvent* event, Selection break; case SelectionEndTrim: - if (clicked_trackview) { - clicked_trackview->order_selection_trims (item, false); + if (clicked_axisview) { + clicked_axisview->order_selection_trims (item, false); } start_grab (event, trimmer_cursor); end = selection->time[clicked_selection].end; @@ -3799,7 +3799,7 @@ Editor::drag_selection (ArdourCanvas::Item* item, GdkEvent* event) drag_info.copy = false; } else { /* new selection-> */ - clicked_selection = selection->set (clicked_trackview, start, end); + clicked_selection = selection->set (clicked_axisview, start, end); } } break; @@ -3903,7 +3903,7 @@ void Editor::start_trim (ArdourCanvas::Item* item, GdkEvent* event) { double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_track()) { @@ -3963,7 +3963,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) */ double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); pair::iterator,bool> insert_result; @@ -4090,7 +4090,7 @@ Editor::single_contents_trim (RegionView& rv, jack_nframes_t frame_delta, bool l jack_nframes_t new_bound; double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_track()) { @@ -4130,7 +4130,7 @@ Editor::single_start_trim (RegionView& rv, jack_nframes_t frame_delta, bool left jack_nframes_t new_bound; double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_track()) { @@ -4164,7 +4164,7 @@ Editor::single_end_trim (RegionView& rv, jack_nframes_t frame_delta, bool left_d jack_nframes_t new_bound; double speed = 1.0; - TimeAxisView* tvp = clicked_trackview; + TimeAxisView* tvp = clicked_axisview; RouteTimeAxisView* tv = dynamic_cast(tvp); if (tv && tv->is_track()) { diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 30e19c484c..7115bfe634 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -226,11 +226,11 @@ Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions) void Editor::remove_clicked_region () { - if (clicked_audio_trackview == 0 || clicked_regionview == 0) { + if (clicked_routeview == 0 || clicked_regionview == 0) { return; } - Playlist* playlist = clicked_audio_trackview->playlist(); + Playlist* playlist = clicked_routeview->playlist(); begin_reversible_command (_("remove region")); XMLNode &before = playlist->get_state(); @@ -585,10 +585,10 @@ Editor::build_region_boundary_cache () break; } - } else if (clicked_trackview) { + } else if (clicked_axisview) { TrackViewList t; - t.push_back (clicked_trackview); + t.push_back (clicked_axisview); if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) { break; @@ -725,10 +725,10 @@ Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir) r = find_next_region (pos, point, dir, selection->tracks, &ontrack); - } else if (clicked_trackview) { + } else if (clicked_axisview) { TrackViewList t; - t.push_back (clicked_trackview); + t.push_back (clicked_axisview); r = find_next_region (pos, point, dir, t, &ontrack); @@ -1287,7 +1287,7 @@ Editor::add_location_from_selection () return; } - if (session == 0 || clicked_trackview == 0) { + if (session == 0 || clicked_axisview == 0) { return; } @@ -1342,11 +1342,11 @@ Editor::select_all_in_track (Selection::Operation op) { list touched; - if (!clicked_trackview) { + if (!clicked_axisview) { return; } - clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched); + clicked_axisview->get_selectables (0, max_frames, 0, DBL_MAX, touched); switch (op) { case Selection::Toggle: @@ -1392,11 +1392,11 @@ Editor::invert_selection_in_track () { list touched; - if (!clicked_trackview) { + if (!clicked_axisview) { return; } - clicked_trackview->get_inverted_selectables (*selection, touched); + clicked_axisview->get_inverted_selectables (*selection, touched); selection->set (touched); } @@ -1845,8 +1845,8 @@ Editor::insert_region_list_selection (float times) RouteTimeAxisView *tv = 0; Playlist *playlist; - if (clicked_audio_trackview != 0) { - tv = clicked_audio_trackview; + if (clicked_routeview != 0) { + tv = clicked_routeview; } else if (!selection->tracks.empty()) { if ((tv = dynamic_cast(selection->tracks.front())) == 0) { return; @@ -2171,7 +2171,7 @@ Editor::interthread_cancel_clicked () void Editor::region_from_selection () { - if (clicked_trackview == 0) { + if (clicked_axisview == 0) { return; } @@ -2383,9 +2383,9 @@ Editor::crop_region_to_selection () vector playlists; Playlist *playlist; - if (clicked_trackview != 0) { + if (clicked_axisview != 0) { - if ((playlist = clicked_trackview->playlist()) == 0) { + if ((playlist = clicked_axisview->playlist()) == 0) { return; } @@ -2486,7 +2486,7 @@ Editor::region_fill_track () void Editor::region_fill_selection () { - if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) { + if (clicked_routeview == 0 || !clicked_routeview->is_audio_track()) { return; } @@ -2738,7 +2738,7 @@ Editor::trim_region_to_edit_cursor () float speed = 1.0f; AudioTimeAxisView *atav; - if ( clicked_trackview != 0 && (atav = dynamic_cast(clicked_trackview)) != 0 ) { + if ( clicked_axisview != 0 && (atav = dynamic_cast(clicked_axisview)) != 0 ) { if (atav->get_diskstream() != 0) { speed = atav->get_diskstream()->speed(); } @@ -2764,7 +2764,7 @@ Editor::trim_region_from_edit_cursor () float speed = 1.0f; AudioTimeAxisView *atav; - if ( clicked_trackview != 0 && (atav = dynamic_cast(clicked_trackview)) != 0 ) { + if ( clicked_axisview != 0 && (atav = dynamic_cast(clicked_axisview)) != 0 ) { if (atav->get_diskstream() != 0) { speed = atav->get_diskstream()->speed(); } @@ -2781,11 +2781,11 @@ Editor::trim_region_from_edit_cursor () void Editor::unfreeze_route () { - if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_track()) { + if (clicked_routeview == 0 || !clicked_routeview->is_track()) { return; } - clicked_audio_trackview->track()->unfreeze (); + clicked_routeview->track()->unfreeze (); } void* @@ -2798,7 +2798,7 @@ Editor::_freeze_thread (void* arg) void* Editor::freeze_thread () { - clicked_audio_trackview->audio_track()->freeze (*current_interthread_info); + clicked_routeview->audio_track()->freeze (*current_interthread_info); return 0; } @@ -2812,7 +2812,7 @@ Editor::freeze_progress_timeout (void *arg) void Editor::freeze_route () { - if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_track()) { + if (clicked_routeview == 0 || !clicked_routeview->is_track()) { return; } diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 54a8c19a22..bca79b0d7d 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -64,10 +64,6 @@ class AudioTrack : public Track protected: XMLNode& state (bool full); - void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, int declick, - bool meter); - ChanCount n_process_buffers (); private: diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h index df7f57455b..896d6e7616 100644 --- a/libs/ardour/ardour/buffer.h +++ b/libs/ardour/ardour/buffer.h @@ -181,23 +181,36 @@ public: ~MidiBuffer(); - // FIXME: clear events starting at offset in time - void silence(jack_nframes_t len, jack_nframes_t offset=0) { assert(offset == 0); _size = 0; } + void silence(jack_nframes_t dur, jack_nframes_t offset=0); void read_from(const Buffer& src, jack_nframes_t nframes, jack_nframes_t offset); - void set_size(size_t size) { _size = size; } + bool push_back(const MidiEvent& event); + + const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; } + MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; } + + static size_t max_event_size() { return MAX_EVENT_SIZE; } + + //void set_size(size_t size) { _size = size; } - const RawMidi* data() const { return _data; } - RawMidi* data() { return _data; } + //const RawMidi* data() const { return _data; } + //RawMidi* data() { return _data; } private: // These are undefined (prevent copies) MidiBuffer(const MidiBuffer& copy); MidiBuffer& operator=(const MidiBuffer& copy); - bool _owns_data; - RawMidi* _data; ///< Actual buffer contents + // FIXME: Jack needs to tell us this + static const size_t MAX_EVENT_SIZE = 4; // bytes + + /* We use _size as "number of events", so the size of _data is + * (_size * MAX_EVENT_SIZE) + */ + + MidiEvent* _events; ///< Event structs that point to offsets in _data + RawMidi* _data; ///< MIDI, straight up. No time stamps. }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h index dfb5dd3611..43df729e05 100644 --- a/libs/ardour/ardour/buffer_set.h +++ b/libs/ardour/ardour/buffer_set.h @@ -28,6 +28,7 @@ namespace ARDOUR { class Buffer; class AudioBuffer; +class MidiBuffer; class PortSet; @@ -77,6 +78,11 @@ public: { return (AudioBuffer&)get(DataType::AUDIO, i); } + + MidiBuffer& get_midi(size_t i) + { + return (MidiBuffer&)get(DataType::MIDI, i); + } void read_from(BufferSet& in, jack_nframes_t nframes, jack_nframes_t offset=0) { diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 901baf3c64..ccff993638 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -45,6 +45,8 @@ #include #include #include +#include + struct tm; namespace ARDOUR { @@ -65,8 +67,7 @@ class MidiDiskstream : public Diskstream float playback_buffer_load() const; float capture_buffer_load() const; - RawMidi* playback_buffer () { return _current_playback_buffer; } - RawMidi* capture_buffer () { return _current_capture_buffer; } + void get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end); void set_record_enabled (bool yn); @@ -124,7 +125,7 @@ class MidiDiskstream : public Diskstream int do_refill_with_alloc(); - int read (MidiBuffer& dst, jack_nframes_t& start, jack_nframes_t cnt, bool reversed); + int read (jack_nframes_t& start, jack_nframes_t cnt, bool reversed); void finish_capture (bool rec_monitors_input); void transport_stopped (struct tm&, time_t, bool abort); @@ -147,17 +148,17 @@ class MidiDiskstream : public Diskstream void disengage_record_enable (); // FIXME: This is basically a single ChannelInfo.. abstractify that concept? - RingBufferNPT* _playback_buf; - RingBufferNPT* _capture_buf; - RawMidi* _current_playback_buffer; - RawMidi* _current_capture_buffer; - RawMidi* _playback_wrap_buffer; - RawMidi* _capture_wrap_buffer; + MidiRingBuffer* _playback_buf; + MidiRingBuffer* _capture_buf; + //RawMidi* _current_playback_buffer; + //RawMidi* _current_capture_buffer; + //RawMidi* _playback_wrap_buffer; + //RawMidi* _capture_wrap_buffer; MidiPort* _source_port; SMFSource* _write_source; ///< aka capturing source RingBufferNPT* _capture_transition_buf; - RingBufferNPT::rw_vector _playback_vector; - RingBufferNPT::rw_vector _capture_vector; + //RingBufferNPT::rw_vector _playback_vector; + //RingBufferNPT::rw_vector _capture_vector; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index 9e9cf250e2..11627b5a07 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -33,7 +33,7 @@ class Session; class Region; class MidiRegion; class Source; -class MidiBuffer; +class MidiRingBuffer; class MidiPlaylist : public ARDOUR::Playlist { @@ -56,7 +56,7 @@ public: MidiPlaylist (const MidiPlaylist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false); - jack_nframes_t read (MidiBuffer& buf, + jack_nframes_t read (MidiRingBuffer& buf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0); int set_state (const XMLNode&); diff --git a/libs/ardour/ardour/midi_port.h b/libs/ardour/ardour/midi_port.h index 3c48f0ce9e..f6eafe11bd 100644 --- a/libs/ardour/ardour/midi_port.h +++ b/libs/ardour/ardour/midi_port.h @@ -39,19 +39,23 @@ class MidiPort : public Port { DataType type() const { return DataType(DataType::MIDI); } - MidiBuffer& get_buffer() { - return *_buffer; + Buffer& get_buffer() { + return _buffer; + } + + MidiBuffer& get_midi_buffer() { + return _buffer; } void cycle_start(jack_nframes_t nframes); void cycle_end(); - size_t capacity() { return _buffer->capacity(); } - size_t size() { return _buffer->size(); } + size_t capacity() { return _buffer.capacity(); } + size_t size() { return _buffer.size(); } /** Assumes that the port is an output port */ void silence (jack_nframes_t nframes, jack_nframes_t offset) { - _buffer->silence(nframes, offset); + _buffer.silence(nframes, offset); } protected: @@ -61,7 +65,7 @@ class MidiPort : public Port { /* engine isn't supposed to access below here */ - MidiBuffer* _buffer; + MidiBuffer _buffer; jack_nframes_t _nframes_this_cycle; }; diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 0144f52473..745d3fa4a8 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -41,7 +41,7 @@ class Playlist; class Session; class MidiFilter; class MidiSource; -class MidiBuffer; +class MidiRingBuffer; class MidiRegion : public Region { @@ -57,16 +57,16 @@ class MidiRegion : public Region MidiSource& midi_source (uint32_t n=0) const; - jack_nframes_t read_at (MidiBuffer& out, + jack_nframes_t read_at (MidiRingBuffer& dst, jack_nframes_t position, - jack_nframes_t cnt, + jack_nframes_t dur, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const; - jack_nframes_t master_read_at (MidiBuffer& buf, + jack_nframes_t master_read_at (MidiRingBuffer& dst, jack_nframes_t position, - jack_nframes_t cnt, + jack_nframes_t dur, uint32_t chan_n=0) const; XMLNode& state (bool); @@ -83,9 +83,9 @@ class MidiRegion : public Region StateManager::State* state_factory (std::string why) const; Change restore_state (StateManager::State&); - jack_nframes_t _read_at (const SourceList&, MidiBuffer& buf, + jack_nframes_t _read_at (const SourceList&, MidiRingBuffer& dst, jack_nframes_t position, - jack_nframes_t cnt, + jack_nframes_t dur, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const; diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h new file mode 100644 index 0000000000..53057dbcba --- /dev/null +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -0,0 +1,242 @@ +/* + Copyright (C) 2006 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 + 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 __ardour_midi_ring_buffer_h__ +#define __ardour_midi_ring_buffer_h__ + +#include +#include +#include +#include + +namespace ARDOUR { + +/** A MIDI RingBuffer + * (necessary because MIDI events are variable sized so a generic RB won't do). + * + * ALL publically accessible sizes refer to event COUNTS. What actually goes + * on in here is none of the callers business :) + */ +class MidiRingBuffer { +public: + MidiRingBuffer (size_t size) + : _size(size) + , _max_event_size(MidiBuffer::max_event_size()) + , _ev_buf(new MidiEvent[size]) + , _raw_buf(new RawMidi[size * _max_event_size]) + { + reset (); + assert(read_space() == 0); + assert(write_space() == size - 1); + } + + virtual ~MidiRingBuffer() { + delete[] _ev_buf; + delete[] _raw_buf; + } + + void reset () { + /* !!! NOT THREAD SAFE !!! */ + g_atomic_int_set (&_write_ptr, 0); + g_atomic_int_set (&_read_ptr, 0); + } + + size_t write_space () { + size_t w, r; + + w = g_atomic_int_get (&_write_ptr); + r = g_atomic_int_get (&_read_ptr); + + if (w > r) { + return ((r - w + _size) % _size) - 1; + } else if (w < r) { + return (r - w) - 1; + } else { + return _size - 1; + } + } + + size_t read_space () { + size_t w, r; + + w = g_atomic_int_get (&_write_ptr); + r = g_atomic_int_get (&_read_ptr); + + if (w > r) { + return w - r; + } else { + return (w - r + _size) % _size; + } + } + + size_t capacity() const { return _size; } + + /** Read one event and appends it to @a out. */ + //size_t read(MidiBuffer& out); + + /** Write one event (@a in) */ + size_t write(const MidiEvent& in); // deep copies in + + /** Read events all events up to time @a end into @a out, leaving stamps intact. + * Any events before @a start will be dropped. */ + size_t read(MidiBuffer& out, jack_nframes_t start, jack_nframes_t end); + + /** Write all events from @a in, applying @a offset to all time stamps */ + size_t write(const MidiBuffer& in, jack_nframes_t offset = 0); + + inline void clear_event(size_t index); + +private: + + // _event_ indices + mutable gint _write_ptr; + mutable gint _read_ptr; + + size_t _size; // size (capacity) in events + size_t _max_event_size; // ratio of raw_buf size to ev_buf size + MidiEvent* _ev_buf; // these point into... + RawMidi* _raw_buf; // this + +}; + +/** Just for sanity checking */ +inline void +MidiRingBuffer::clear_event(size_t index) +{ + memset(&_ev_buf[index].buffer, 0, _max_event_size); + _ev_buf[index].time = 0; + _ev_buf[index].size = 0; + _ev_buf[index].buffer = 0; + +} +#if 0 +inline size_t +MidiRingBuffer::read (MidiBuffer& buf) +{ + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + + if (read_space() == 0) { + return 0; + } else { + MidiEvent* const read_ev = &_ev_buf[priv_read_ptr]; + assert(read_ev->size > 0); + buf.push_back(*read_ev); + printf("MRB - read %xd %d %d with time %u at index %zu\n", + read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time, + priv_read_ptr); + clear_event(priv_read_ptr); + g_atomic_int_set(&_read_ptr, (priv_read_ptr + 1) % _size); + return 1; + } +} +#endif +inline size_t +MidiRingBuffer::write (const MidiEvent& ev) +{ + //static jack_nframes_t last_write_time = 0; + + assert(ev.size > 0); + + size_t priv_write_ptr = g_atomic_int_get(&_write_ptr); + + if (write_space () == 0) { + return 0; + } else { + //assert(ev.time >= last_write_time); + + const size_t raw_index = priv_write_ptr * _max_event_size; + + MidiEvent* const write_ev = &_ev_buf[priv_write_ptr]; + *write_ev = ev; + + memcpy(&_raw_buf[raw_index], ev.buffer, ev.size); + write_ev->buffer = &_raw_buf[raw_index]; + g_atomic_int_set(&_write_ptr, (priv_write_ptr + 1) % _size); + + printf("MRB - wrote %xd %d %d with time %u at index %zu (raw index %zu)\n", + write_ev->buffer[0], write_ev->buffer[1], write_ev->buffer[2], write_ev->time, + priv_write_ptr, raw_index); + + assert(write_ev->size = ev.size); + + //last_write_time = ev.time; + printf("(W) read space: %zu\n", read_space()); + + return 1; + } +} + +inline size_t +MidiRingBuffer::read(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end) +{ + if (read_space() == 0) + return 0; + + size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + jack_nframes_t time = _ev_buf[priv_read_ptr].time; + size_t count = 0; + size_t limit = read_space(); + + while (time <= end && limit > 0) { + MidiEvent* const read_ev = &_ev_buf[priv_read_ptr]; + if (time >= start) { + dst.push_back(*read_ev); + printf("MRB - read %xd %d %d with time %u at index %zu\n", + read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time, + priv_read_ptr); + } else { + cerr << "MRB: LOST EVENT!" << endl; + } + + clear_event(priv_read_ptr); + + ++count; + --limit; + + priv_read_ptr = (priv_read_ptr + 1) % _size; + + assert(read_ev->time <= end); + time = _ev_buf[priv_read_ptr].time; + } + + g_atomic_int_set(&_read_ptr, priv_read_ptr); + printf("(R) read space: %zu\n", read_space()); + + return count; +} + +inline size_t +MidiRingBuffer::write(const MidiBuffer& in, jack_nframes_t offset) +{ + size_t num_events = in.size(); + size_t to_write = std::min(write_space(), num_events); + + // FIXME: double copy :/ + for (size_t i=0; i < to_write; ++i) { + MidiEvent ev = in[i]; + ev.time += offset; + write(ev); + } + + return to_write; +} + +} // namespace ARDOUR + +#endif // __ardour_midi_ring_buffer_h__ + diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 654eb98e30..409aa171e9 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -76,10 +76,6 @@ public: protected: XMLNode& state (bool full); - void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, int declick, - bool meter); - ChanCount n_process_buffers (); private: diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index db5cddca39..107abb7b48 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -309,10 +309,13 @@ class Route : public IO bool meter); protected: - /* for derived classes */ virtual XMLNode& state(bool); + void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset, int declick, + bool meter); + void silence (jack_nframes_t nframes, jack_nframes_t offset); sigc::connection input_signal_connection; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 15a0a28aab..2b317a0299 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -95,9 +95,6 @@ class Track : public Route virtual XMLNode& state (bool full) = 0; - virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0; - virtual ChanCount n_process_buffers () = 0; Diskstream *_diskstream; diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 00833f6547..d5bfded460 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -50,7 +50,8 @@ namespace ARDOUR { typedef uint32_t layer_t; typedef uint64_t microseconds_t; - typedef jack_midi_event_t RawMidi; + typedef jack_midi_event_t MidiEvent; + typedef unsigned char RawMidi; enum IOChange { NoChange = 0, diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 784a14bb2b..40c8e3301b 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -968,7 +968,7 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill) { Glib::Mutex::Lock lm (state_lock); uint32_t n; - int ret; + int ret = -1; ChannelList::iterator chan; for (n = 0, chan = channels.begin(); chan != channels.end(); ++chan, ++n) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 52cc7726c9..b12b79858e 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -406,12 +406,6 @@ AudioTrack::n_process_buffers () return max (_diskstream->n_channels(), redirect_max_outs); } -void -AudioTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) -{ - process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, offset, true, declick, meter); -} - int AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool session_state_changing, bool can_record, bool rec_monitors_input) diff --git a/libs/ardour/buffer.cc b/libs/ardour/buffer.cc index fa4669cef6..7b99f2a900 100644 --- a/libs/ardour/buffer.cc +++ b/libs/ardour/buffer.cc @@ -16,8 +16,11 @@ 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include #include +using std::cerr; using std::endl; + +#include namespace ARDOUR { @@ -62,47 +65,95 @@ AudioBuffer::~AudioBuffer() // FIXME: mirroring for MIDI buffers? MidiBuffer::MidiBuffer(size_t capacity) : Buffer(DataType::MIDI, capacity) - , _owns_data(true) +// , _owns_data(true) + , _events(NULL) , _data(NULL) { assert(capacity > 0); - _size = capacity; // For audio buffers, size = capacity (always) + _size = 0; + #ifdef NO_POSIX_MEMALIGN - _data = (RawMidi *) malloc(sizeof(RawMidi) * capacity); + _events = (MidiEvent *) malloc(sizeof(MidiEvent) * capacity); + _data = (RawMidi *) malloc(sizeof(RawMidi) * capacity * MAX_EVENT_SIZE); #else - posix_memalign((void**)&_data, 16, sizeof(RawMidi) * capacity); + posix_memalign((void**)&_events, 16, sizeof(MidiEvent) * capacity); + posix_memalign((void**)&_data, 16, sizeof(RawMidi) * capacity * MAX_EVENT_SIZE); #endif assert(_data); - memset(_data, 0, sizeof(RawMidi) * capacity); + assert(_events); + silence(_capacity); } MidiBuffer::~MidiBuffer() { - if (_owns_data) - free(_data); + free(_events); + free(_data); } -/** Note that offset and nframes refer to sample time, not actual buffer locations */ +/** Read events from @a src starting at time @a offset into the START of this buffer, for + * time direction @a nframes. Relative time, where 0 = start of buffer. + * + * Note that offset and nframes refer to sample time, NOT buffer offsets or event counts. + */ void MidiBuffer::read_from(const Buffer& src, jack_nframes_t nframes, jack_nframes_t offset) { - // FIXME: offsets? param semantics? - assert(src.type() == _type); assert(src.type() == DataType::MIDI); - assert(offset == 0); - MidiBuffer& msrc = (MidiBuffer&)src; - _size = 0; - for (size_t i=0; i < msrc.size() && msrc.data()[i].time < nframes; ++i) { - assert(i < _capacity); - _data[i] = msrc.data()[i]; - ++_size; + const MidiBuffer& msrc = (MidiBuffer&)src; + + assert(_capacity >= src.size()); + + clear(); + assert(_size == 0); + + // FIXME: This is embarrassingly slow. branch branch branch + for (size_t i=0; i < src.size(); ++i) { + const MidiEvent& ev = msrc[i]; + if (ev.time >= offset && ev.time < offset+nframes) { + push_back(ev); + } } - assert(_size == msrc.size()); +} - //if (_size > 0) - // std::cerr << "MidiBuffer wrote " << _size << " events.\n"; + +/** Push an event into the buffer. + * + * Note that the raw MIDI pointed to by ev will be COPIED and unmodified. + * That is, the caller still owns it, if it needs freeing it's Not My Problem(TM). + * Realtime safe. + * @return false if operation failed (not enough room) + */ +bool +MidiBuffer::push_back(const MidiEvent& ev) +{ + if (_size == _capacity) + return false; + + RawMidi* const write_loc = _data + (_size * MAX_EVENT_SIZE); + + memcpy(write_loc, ev.buffer, ev.size); + _events[_size] = ev; + _events[_size].buffer = write_loc; + ++_size; + + //cerr << "MidiBuffer: pushed, size = " << _size << endl; + + return true; +} + + +void +MidiBuffer::silence(jack_nframes_t dur, jack_nframes_t offset) +{ + // FIXME use parameters + assert(offset == 0); + //assert(dur == _capacity); + + memset(_events, 0, sizeof(MidiEvent) * _capacity); + memset(_data, 0, sizeof(RawMidi) * _capacity * MAX_EVENT_SIZE); + _size = 0; } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index fce8c3f1d8..430801310d 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -213,15 +213,12 @@ IO::deliver_output (BufferSet& bufs, jack_nframes_t start_frame, jack_nframes_t return; } - const DataType type = DataType::MIDI; // type type type type... + const DataType type = DataType::MIDI; // Just dump any MIDI 1-to-1, we're not at all clever with MIDI routing yet BufferSet::iterator o = output_buffers().begin(type); - for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i) { - - for (PortSet::iterator i = _inputs.begin(type); i != _inputs.end(type); ++i, ++o) { - o->read_from(i->get_buffer(), nframes, offset); - } + for (BufferSet::iterator i = bufs.begin(type); i != bufs.end(type); ++i, ++o) { + o->read_from(*i, nframes, offset); } } diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc index 86a95a3cc0..223cfc15f6 100644 --- a/libs/ardour/midi_diskstream.cc +++ b/libs/ardour/midi_diskstream.cc @@ -61,10 +61,10 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F : Diskstream(sess, name, flag) , _playback_buf(0) , _capture_buf(0) - , _current_playback_buffer(0) - , _current_capture_buffer(0) - , _playback_wrap_buffer(0) - , _capture_wrap_buffer(0) + //, _current_playback_buffer(0) + //, _current_capture_buffer(0) + //, _playback_wrap_buffer(0) + //, _capture_wrap_buffer(0) , _source_port(0) , _write_source(0) , _capture_transition_buf(0) @@ -86,10 +86,10 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node) : Diskstream(sess, node) , _playback_buf(0) , _capture_buf(0) - , _current_playback_buffer(0) - , _current_capture_buffer(0) - , _playback_wrap_buffer(0) - , _capture_wrap_buffer(0) + //, _current_playback_buffer(0) + //, _current_capture_buffer(0) + //, _playback_wrap_buffer(0) + //, _capture_wrap_buffer(0) , _source_port(0) , _write_source(0) , _capture_transition_buf(0) @@ -124,10 +124,10 @@ MidiDiskstream::init (Diskstream::Flag f) set_block_size (_session.get_block_size()); allocate_temporary_buffers (); - _playback_wrap_buffer = new RawMidi[wrap_buffer_size]; - _capture_wrap_buffer = new RawMidi[wrap_buffer_size]; - _playback_buf = new RingBufferNPT (_session.diskstream_buffer_size()); - _capture_buf = new RingBufferNPT (_session.diskstream_buffer_size()); + //_playback_wrap_buffer = new RawMidi[wrap_buffer_size]; + //_capture_wrap_buffer = new RawMidi[wrap_buffer_size]; + _playback_buf = new MidiRingBuffer (_session.diskstream_buffer_size()); + _capture_buf = new MidiRingBuffer (_session.diskstream_buffer_size()); _capture_transition_buf = new RingBufferNPT (128); _n_channels = ChanCount(DataType::MIDI, 1); @@ -435,9 +435,9 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, bool nominally_recording; bool re = record_enabled (); bool collect_playback = false; - - _current_capture_buffer = 0; - _current_playback_buffer = 0; + + /*_current_capture_buffer = 0; + _current_playback_buffer = 0;*/ /* if we've already processed the frames corresponding to this call, just return. this allows multiple routes that are taking input @@ -445,7 +445,7 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, this stuff only happen once. more commonly, it allows both the AudioTrack that is using this AudioDiskstream *and* the Session to call process() without problems. - */ + */ if (_processed) { return 0; @@ -463,58 +463,58 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, /* This lock is held until the end of AudioDiskstream::commit, so these two functions must always be called as a pair. The only exception is if this function returns a non-zero value, in which case, ::commit should not be called. - */ + */ // If we can't take the state lock return. if (!state_lock.trylock()) { return 1; } - + adjust_capture_position = 0; if (nominally_recording || (_session.get_record_enabled() && _session.get_punch_in())) { OverlapType ot; - + ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes); switch (ot) { - case OverlapNone: - rec_nframes = 0; - break; - - case OverlapInternal: - /* ---------- recrange - |---| transrange - */ - rec_nframes = nframes; - rec_offset = 0; - break; - - case OverlapStart: - /* |--------| recrange - -----| transrange - */ - rec_nframes = transport_frame + nframes - first_recordable_frame; - if (rec_nframes) { + case OverlapNone: + rec_nframes = 0; + break; + + case OverlapInternal: + /* ---------- recrange + |---| transrange + */ + rec_nframes = nframes; + rec_offset = 0; + break; + + case OverlapStart: + /* |--------| recrange + -----| transrange + */ + rec_nframes = transport_frame + nframes - first_recordable_frame; + if (rec_nframes) { + rec_offset = first_recordable_frame - transport_frame; + } + break; + + case OverlapEnd: + /* |--------| recrange + |-------- transrange + */ + rec_nframes = last_recordable_frame - transport_frame; + rec_offset = 0; + break; + + case OverlapExternal: + /* |--------| recrange + -------------- transrange + */ + rec_nframes = last_recordable_frame - last_recordable_frame; rec_offset = first_recordable_frame - transport_frame; - } - break; - - case OverlapEnd: - /* |--------| recrange - |-------- transrange - */ - rec_nframes = last_recordable_frame - transport_frame; - rec_offset = 0; - break; - - case OverlapExternal: - /* |--------| recrange - -------------- transrange - */ - rec_nframes = last_recordable_frame - last_recordable_frame; - rec_offset = first_recordable_frame - transport_frame; - break; + break; } if (rec_nframes && !was_recording) { @@ -529,64 +529,20 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, } if (nominally_recording || rec_nframes) { - _capture_buf->get_write_vector (&_capture_vector); - - if (rec_nframes <= _capture_vector.len[0]) { - - _current_capture_buffer = _capture_vector.buf[0]; - - /* note: grab the entire port buffer, but only copy what we were supposed to for recording, and use - rec_offset - */ - - // FIXME: midi buffer size? - - // FIXME: reading from a MIDI port is different, can't just memcpy - //memcpy (_current_capture_buffer, _io->input(0)->get_buffer (rec_nframes) + offset + rec_offset, sizeof (RawMidi) * rec_nframes); - assert(_source_port); - - /*for (size_t i=0; i < _source_port->size(); ++i) { - cerr << "DISKSTREAM GOT EVENT(1) " << i << "!!\n"; - } - - if (_source_port->size() == 0) - cerr << "No events :/ (1)\n"; - */ + assert(_source_port); - } else { - - jack_nframes_t total = _capture_vector.len[0] + _capture_vector.len[1]; - - if (rec_nframes > total) { - cerr << "DiskOverrun\n"; - //DiskOverrun (); // FIXME - goto out; - } - - // FIXME (see above) - //RawMidi* buf = _io->input (0)->get_buffer (nframes) + offset; - assert(_source_port); - - /* - for (size_t i=0; i < _source_port->size(); ++i) { - cerr << "DISKSTREAM GOT EVENT(2) " << i << "!!\n"; - } - if (_source_port->size() == 0) - cerr << "No events :/ (2)\n"; - */ + // Pump entire port buffer into the ring buffer (FIXME!) + _capture_buf->write(_source_port->get_midi_buffer(), transport_frame); - RawMidi* buf = NULL; // FIXME FIXME FIXME (make it compile) - assert(false); - jack_nframes_t first = _capture_vector.len[0]; + /* + for (size_t i=0; i < _source_port->size(); ++i) { + cerr << "DISKSTREAM GOT EVENT(1) " << i << "!!\n"; + } - memcpy (_capture_wrap_buffer, buf, sizeof (RawMidi) * first); - memcpy (_capture_vector.buf[0], buf, sizeof (RawMidi) * first); - memcpy (_capture_wrap_buffer+first, buf + first, sizeof (RawMidi) * (rec_nframes - first)); - memcpy (_capture_vector.buf[1], buf + first, sizeof (RawMidi) * (rec_nframes - first)); - - _current_capture_buffer = _capture_wrap_buffer; - } + if (_source_port->size() == 0) + cerr << "No events :/ (1)\n"; + */ } else { if (was_recording) { @@ -594,38 +550,19 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, } } - + if (rec_nframes) { - - // FIXME: filthy hack to fool the GUI into thinking we're doing something - //if (_write_source) - // _write_source->ViewDataRangeReady (transport_frame, rec_nframes); /* EMIT SIGNAL */ + /* XXX XXX XXX XXX XXX XXX XXX XXX */ /* data will be written to disk */ - if (rec_nframes == nframes && rec_offset == 0) { - - _current_playback_buffer = _current_capture_buffer; - playback_distance = nframes; - - } else { - - - /* we can't use the capture buffer as the playback buffer, because - we recorded only a part of the current process' cycle data - for capture. - */ - - collect_playback = true; - } - adjust_capture_position = rec_nframes; } else if (nominally_recording) { /* can't do actual capture yet - waiting for latency effects to finish before we start*/ - _current_playback_buffer = _current_capture_buffer; + throw; // forget all that jazz! playback_distance = nframes; @@ -647,84 +584,22 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, } else { necessary_samples = nframes; } - - _playback_buf->get_read_vector (&_playback_vector); - - if (necessary_samples <= _playback_vector.len[0]) { - - _current_playback_buffer = _playback_vector.buf[0]; - - } else { - jack_nframes_t total = _playback_vector.len[0] + _playback_vector.len[1]; - - if (necessary_samples > total) { - //cerr << "DiskUnderrun\n"; - //DiskUnderrun (); // FIXME - //goto out; - - } else { - - memcpy (_playback_wrap_buffer, _playback_vector.buf[0], - _playback_vector.len[0] * sizeof (RawMidi)); - memcpy (_playback_wrap_buffer + _playback_vector.len[0], _playback_vector.buf[1], - (necessary_samples - _playback_vector.len[0]) * sizeof (RawMidi)); - - _current_playback_buffer = _playback_wrap_buffer; - } - } - -#if 0 - if (rec_nframes == 0 && _actual_speed != 1.0f && _actual_speed != -1.0f) { - - uint64_t phase = last_phase; - jack_nframes_t i = 0; - - // Linearly interpolate into the alt buffer - // using 40.24 fixp maths (swh) - - for (c = channels.begin(); c != channels.end(); ++c) { - - float fr; - ChannelInfo& chan (*c); - - i = 0; - phase = last_phase; - - for (jack_nframes_t outsample = 0; outsample < nframes; ++outsample) { - i = phase >> 24; - fr = (phase & 0xFFFFFF) / 16777216.0f; - chan.speed_buffer[outsample] = - chan._current_playback_buffer[i] * (1.0f - fr) + - chan._current_playback_buffer[i+1] * fr; - phase += phi; - } - - chan._current_playback_buffer = chan.speed_buffer; - } - - playback_distance = i + 1; - last_phase = (phase & 0xFFFFFF); - - } else { - playback_distance = nframes; - } -#endif - playback_distance = nframes; + // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX + // Write into playback buffer here, and whatnot } ret = 0; - out: _processed = true; if (ret) { /* we're exiting with failure, so ::commit will not be called. unlock the state lock. - */ - + */ + state_lock.unlock(); } @@ -746,24 +621,27 @@ MidiDiskstream::commit (jack_nframes_t nframes) playback_sample += playback_distance; } - _playback_buf->increment_read_ptr (playback_distance); - - if (adjust_capture_position) { - _capture_buf->increment_write_ptr (adjust_capture_position); - } - + /* XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX */ + + /* + _playback_buf->increment_read_ptr (playback_distance); + + if (adjust_capture_position) { + _capture_buf->increment_write_ptr (adjust_capture_position); + } + if (adjust_capture_position != 0) { capture_captured += adjust_capture_position; adjust_capture_position = 0; } - + if (_slaved) { need_butler = _playback_buf->write_space() >= _playback_buf->bufsize() / 2; } else { need_butler = _playback_buf->write_space() >= disk_io_chunk_frames || _capture_buf->read_space() >= disk_io_chunk_frames; } - + */ state_lock.unlock(); _processed = false; @@ -792,24 +670,126 @@ int MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill) { Glib::Mutex::Lock lm (state_lock); - return 0; + int ret = -1; + + _playback_buf->reset(); + _capture_buf->reset(); + + playback_sample = frame; + file_frame = frame; + + if (complete_refill) { + while ((ret = do_refill_with_alloc ()) > 0) ; + } else { + ret = do_refill_with_alloc (); + } + + return ret; } int MidiDiskstream::can_internal_playback_seek (jack_nframes_t distance) { - return 0; + if (_playback_buf->read_space() < distance) { + return false; + } else { + return true; + } } int MidiDiskstream::internal_playback_seek (jack_nframes_t distance) { + first_recordable_frame += distance; + playback_sample += distance; + return 0; } +/** @a start is set to the new frame position (TIME) read up to */ int -MidiDiskstream::read (MidiBuffer& dst, jack_nframes_t& start, jack_nframes_t cnt, bool reversed) -{ +MidiDiskstream::read (jack_nframes_t& start, jack_nframes_t dur, bool reversed) +{ + jack_nframes_t this_read = 0; + bool reloop = false; + jack_nframes_t loop_end = 0; + jack_nframes_t loop_start = 0; + jack_nframes_t loop_length = 0; + Location *loc = 0; + + if (!reversed) { + /* Make the use of a Location atomic for this read operation. + + Note: Locations don't get deleted, so all we care about + when I say "atomic" is that we are always pointing to + the same one and using a start/length values obtained + just once. + */ + + if ((loc = loop_location) != 0) { + loop_start = loc->start(); + loop_end = loc->end(); + loop_length = loop_end - loop_start; + } + + /* if we are looping, ensure that the first frame we read is at the correct + position within the loop. + */ + + if (loc && start >= loop_end) { + //cerr << "start adjusted from " << start; + start = loop_start + ((start - loop_start) % loop_length); + //cerr << "to " << start << endl; + } + //cerr << "start is " << start << " loopstart: " << loop_start << " loopend: " << loop_end << endl; + } + + while (dur) { + + /* take any loop into account. we can't read past the end of the loop. */ + + if (loc && (loop_end - start < dur)) { + this_read = loop_end - start; + //cerr << "reloop true: thisread: " << this_read << " dur: " << dur << endl; + reloop = true; + } else { + reloop = false; + this_read = dur; + } + + if (this_read == 0) { + break; + } + + this_read = min(dur,this_read); + + if (midi_playlist()->read (*_playback_buf, start, this_read) != this_read) { + error << string_compose(_("MidiDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read, + start) << endmsg; + return -1; + } + + _read_data_count = _playlist->read_data_count(); + + if (reversed) { + + cerr << "Reversed MIDI.. that's just crazy talk." << endl; + // Swap note ons with note offs here + + } else { + + /* if we read to the end of the loop, go back to the beginning */ + + if (reloop) { + start = loop_start; + } else { + start += this_read; + } + } + + dur -= this_read; + } + return 0; } @@ -822,8 +802,94 @@ MidiDiskstream::do_refill_with_alloc () int MidiDiskstream::do_refill () { - // yeah, the data's ready. promise. - return 0; + int32_t ret = 0; + size_t write_space = _playback_buf->write_space(); + + bool reversed = (_visible_speed * _session.transport_speed()) < 0.0f; + + if (write_space == 0) { + return 0; + } + + /* if there are 2+ chunks of disk i/o possible for + this track, let the caller know so that it can arrange + for us to be called again, ASAP. + */ + + // FIXME: using disk_io_chunk_frames as an event count, not good + if (_playback_buf->write_space() >= (_slaved?3:2) * disk_io_chunk_frames) { + ret = 1; + } + + /* if we're running close to normal speed and there isn't enough + space to do disk_io_chunk_frames of I/O, then don't bother. + + at higher speeds, just do it because the sync between butler + and audio thread may not be good enough. + */ + + if ((write_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) { + cerr << "No refill 1\n"; + return 0; + } + + /* when slaved, don't try to get too close to the read pointer. this + leaves space for the buffer reversal to have something useful to + work with. + */ + + if (_slaved && write_space < (_playback_buf->capacity() / 2)) { + cerr << "No refill 2\n"; + return 0; + } + + if (reversed) { + cerr << "No refill 3 (reverse)\n"; + return 0; + } + + if (file_frame == max_frames) { + cerr << "No refill 4 (EOF)\n"; + + /* at end: nothing to do */ + + return 0; + } + +#if 0 + // or this + if (file_frame > max_frames - total_space) { + + /* to close to the end: read what we can, and zero fill the rest */ + + zero_fill = total_space - (max_frames - file_frame); + total_space = max_frames - file_frame; + + } else { + zero_fill = 0; + } +#endif + + // At this point we: + assert(_playback_buf->write_space() > 0); // ... have something to write to, and + assert(file_frame <= max_frames); // ... something to write + + // So (read it, then) write it: + + jack_nframes_t file_frame_tmp = file_frame; + jack_nframes_t to_read = min(disk_io_chunk_frames, (max_frames - file_frame)); + + // FIXME: read count? + if (read (file_frame_tmp, to_read, reversed)) { + ret = -1; + goto out; + } + + file_frame = file_frame_tmp; + +out: + + return ret; } /** Flush pending data to disk. @@ -1338,14 +1404,14 @@ float MidiDiskstream::playback_buffer_load () const { return (float) ((double) _playback_buf->read_space()/ - (double) _playback_buf->bufsize()); + (double) _playback_buf->capacity()); } float MidiDiskstream::capture_buffer_load () const { return (float) ((double) _capture_buf->write_space()/ - (double) _capture_buf->bufsize()); + (double) _capture_buf->capacity()); } @@ -1354,3 +1420,48 @@ MidiDiskstream::use_pending_capture_data (XMLNode& node) { return 0; } + +/** Writes playback events in the given range to dst, translating time stamps + * so that an event at start has time = 0 + */ +void +MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end) +{ + assert(end > start); + dst.clear(); + assert(dst.size() == 0); +/* + cerr << "MIDI Diskstream pretending to read" << endl; + + MidiEvent ev; + RawMidi data[4]; + + const char note = rand()%30 + 30; + + ev.buffer = data; + ev.time = 0; + ev.size = 3; + + data[0] = 0x90; + data[1] = note; + data[2] = 120; + + dst.push_back(ev); + + ev.buffer = data; + ev.time = (end - start) / 2; + ev.size = 3; + + data[0] = 0x80; + data[1] = note; + data[2] = 64; +*/ + _playback_buf->read(dst, start, end); + + // Translate time stamps to be relative to the start of this cycle + for (size_t i=0; i < dst.size(); ++i) { + assert(dst[i].time >= start); + assert(dst[i].time <= end); + dst[i].time -= start; + } +} diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc index 582df6f5be..051203e55e 100644 --- a/libs/ardour/midi_playlist.cc +++ b/libs/ardour/midi_playlist.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -118,8 +119,8 @@ MidiPlaylist::MidiPlaylist (const MidiPlaylist& other, string name, bool hidden) } } -MidiPlaylist::MidiPlaylist (const MidiPlaylist& other, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden) - : Playlist (other, start, cnt, name, hidden) +MidiPlaylist::MidiPlaylist (const MidiPlaylist& other, jack_nframes_t start, jack_nframes_t dur, string name, bool hidden) + : Playlist (other, start, dur, name, hidden) { save_state (_("initial state")); @@ -168,10 +169,10 @@ struct RegionSortByLayer } }; -/** FIXME: semantics of return value? */ +/** Returns the number of frames in time duration read (eg could be large when 0 events are read) */ jack_nframes_t -MidiPlaylist::read (MidiBuffer& buf, jack_nframes_t start, - jack_nframes_t cnt, unsigned chan_n) +MidiPlaylist::read (MidiRingBuffer& dst, jack_nframes_t start, + jack_nframes_t dur, unsigned chan_n) { /* this function is never called from a realtime thread, so its OK to block (for short intervals). @@ -180,11 +181,11 @@ MidiPlaylist::read (MidiBuffer& buf, jack_nframes_t start, Glib::Mutex::Lock rm (region_lock); jack_nframes_t ret = 0; - jack_nframes_t end = start + cnt - 1; - jack_nframes_t read_frames = 0; - jack_nframes_t skip_frames = 0; + jack_nframes_t end = start + dur - 1; + //jack_nframes_t read_frames = 0; + //jack_nframes_t skip_frames = 0; - _read_data_count = 0; + //_read_data_count = 0; vector regs; // relevent regions overlapping start <--> end @@ -199,13 +200,15 @@ MidiPlaylist::read (MidiBuffer& buf, jack_nframes_t start, sort(regs.begin(), regs.end(), layer_cmp); for (vector::iterator i = regs.begin(); i != regs.end(); ++i) { - (*i)->read_at (buf, start, cnt, chan_n, read_frames, skip_frames); - ret += (*i)->read_data_count(); + // FIXME: ensure time is monotonic here + (*i)->read_at (dst, start, dur, chan_n, 0, 0);// FIXME read_frames, skip_frames); + ret += (*i)->read_data_count(); } _read_data_count += ret; - return ret; + //return ret; FIXME? + return dur; } @@ -386,8 +389,7 @@ MidiPlaylist::drop_all_states () /* delete every region that is left - these are all things that are part of our "history" */ - for (set - ::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) { + for (set::iterator ar = all_regions.begin(); ar != all_regions.end(); ++ar) { (*ar)->unlock_sources (); delete *ar; } @@ -587,6 +589,8 @@ MidiPlaylist::region_changed (Change what_changed, Region* region) return false; } + // Feeling rather uninterested today, but thanks for the heads up anyway! + Change our_interests = Change (/*MidiRegion::FadeInChanged| MidiRegion::FadeOutChanged| MidiRegion::FadeInActiveChanged| diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 83322dedb6..f4d1912061 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -26,7 +26,7 @@ using namespace std; MidiPort::MidiPort(jack_port_t* p) : Port(p) - , _buffer(NULL) + , _buffer(4096) // FIXME FIXME FIXME Jack needs to tell us this , _nframes_this_cycle(0) { DataType dt(_type); @@ -34,22 +34,25 @@ MidiPort::MidiPort(jack_port_t* p) reset(); - _buffer = new MidiBuffer(4096); // FIXME FIXME FIXME + } MidiPort::~MidiPort() { - delete _buffer; } void MidiPort::cycle_start (jack_nframes_t nframes) { + _buffer.clear(); + assert(_buffer.size() == 0); + _nframes_this_cycle = nframes; if (_flags & JackPortIsOutput) { - _buffer->set_size(0); + _buffer.silence(nframes); + assert(_buffer.size() == 0); return; } @@ -60,21 +63,26 @@ MidiPort::cycle_start (jack_nframes_t nframes) const jack_nframes_t event_count = jack_midi_port_get_info(jack_buffer, nframes)->event_count; - assert(event_count < _buffer->capacity()); + assert(event_count < _buffer.capacity()); + MidiEvent ev; + + // FIXME: too slow, event struct is copied twice (here and MidiBuffer::push_back) for (jack_nframes_t i=0; i < event_count; ++i) { - jack_midi_event_t* const ev = &_buffer->data()[i]; - jack_midi_event_get(ev, jack_buffer, i, nframes); + // This will fail to compile if we change MidiEvent to our own class + jack_midi_event_get(static_cast(&ev), jack_buffer, i, nframes); + + _buffer.push_back(ev); // Convert note ons with velocity 0 to proper note offs // FIXME: Jack MIDI should guarantee this - does it? //if (ev->buffer[0] == MIDI_CMD_NOTE_ON && ev->buffer[2] == 0) // ev->buffer[0] = MIDI_CMD_NOTE_OFF; } - _buffer->set_size(event_count); - - //if (_buffer->size() > 0) + assert(_buffer.size() == event_count); + + //if (_buffer.size() > 0) // cerr << "MIDIPort got " << event_count << " events." << endl; } @@ -82,7 +90,7 @@ void MidiPort::cycle_end() { if (_flags & JackPortIsInput) { - _nframes_this_cycle = 0; // catch any oopses + _nframes_this_cycle = 0; return; } @@ -90,13 +98,17 @@ MidiPort::cycle_end() void* jack_buffer = jack_port_get_buffer(_port, _nframes_this_cycle); - const jack_nframes_t event_count = _buffer->size(); + const jack_nframes_t event_count = _buffer.size(); + + //if (event_count > 0) + // cerr << "MIDIPort writing " << event_count << " events." << endl; jack_midi_clear_buffer(jack_buffer, _nframes_this_cycle); for (jack_nframes_t i=0; i < event_count; ++i) { - const jack_midi_event_t& ev = _buffer->data()[i]; + const jack_midi_event_t& ev = _buffer[i]; + assert(ev.time < _nframes_this_cycle); jack_midi_event_write(jack_buffer, ev.time, ev.buffer, ev.size, _nframes_this_cycle); } - _nframes_this_cycle = 0; // catch oopses + _nframes_this_cycle = 0; } diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc index 84b03b9aa9..9098bf6f40 100644 --- a/libs/ardour/midi_region.cc +++ b/libs/ardour/midi_region.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include "i18n.h" #include @@ -178,25 +179,51 @@ MidiRegion::get_memento() const } jack_nframes_t -MidiRegion::read_at (MidiBuffer& out, jack_nframes_t position, - jack_nframes_t cnt, +MidiRegion::read_at (MidiRingBuffer& out, jack_nframes_t position, + jack_nframes_t dur, uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const { - return _read_at (_sources, out, position, cnt, chan_n, read_frames, skip_frames); + return _read_at (_sources, out, position, dur, chan_n, read_frames, skip_frames); } jack_nframes_t -MidiRegion::master_read_at (MidiBuffer& out, jack_nframes_t position, - jack_nframes_t cnt, uint32_t chan_n) const +MidiRegion::master_read_at (MidiRingBuffer& out, jack_nframes_t position, + jack_nframes_t dur, uint32_t chan_n) const { - return _read_at (_master_sources, out, position, cnt, chan_n, 0, 0); + return _read_at (_master_sources, out, position, dur, chan_n, 0, 0); } jack_nframes_t -MidiRegion::_read_at (const SourceList& srcs, MidiBuffer& buf, - jack_nframes_t position, jack_nframes_t cnt, +MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, + jack_nframes_t position, jack_nframes_t dur, uint32_t chan_n, jack_nframes_t read_frames, jack_nframes_t skip_frames) const { + MidiEvent ev; + RawMidi data[4]; + + const char note = rand()%30 + 30; + + ev.buffer = data; + ev.time = position; + ev.size = 3; + data[0] = 0x90; + data[1] = note; + data[2] = 120; + dst.write(ev); + + ev.buffer = data; + ev.time = (jack_nframes_t)(position + (9/10.0 * dur)); + assert(ev.time < position + dur); + ev.size = 3; + data[0] = 0x80; + data[1] = note; + data[2] = 64; + dst.write(ev); + + _read_data_count += dur; + + return dur; +#if 0 jack_nframes_t internal_offset; jack_nframes_t buf_offset; jack_nframes_t to_read; @@ -240,6 +267,7 @@ MidiRegion::_read_at (const SourceList& srcs, MidiBuffer& buf, _read_data_count += src.read_data_count(); return to_read; +#endif } XMLNode& diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc index 470759f3ac..91aad5ea80 100644 --- a/libs/ardour/midi_track.cc +++ b/libs/ardour/midi_track.cc @@ -32,6 +32,7 @@ #include #include #include +#include #include "i18n.h" @@ -354,23 +355,18 @@ MidiTrack::n_process_buffers () return max (_diskstream->n_channels(), redirect_max_outs); } -void -MidiTrack::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) -{ - process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, offset, true, declick, meter); -} - int MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, bool session_state_changing, bool can_record, bool rec_monitors_input) { if (n_outputs().get(DataType::MIDI) == 0) { - return 0; + //return 0; + throw; // FIXME } if (!_active) { silence (nframes, offset); - return 0; + //return 0; // FIXME } if (session_state_changing) { @@ -444,13 +440,9 @@ int MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t offset, int declick, bool can_record, bool rec_monitors_input) { - //passthru (start_frame, end_frame, nframes, offset, declick, false); int dret; - RawMidi* b; // FIXME: this won't work, duh - //Sample* tmpb; - jack_nframes_t transport_frame; MidiDiskstream& diskstream = midi_diskstream(); - + { Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); if (lm.locked()) { @@ -459,7 +451,7 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe automation_snapshot (start_frame); } } - + if (n_outputs().get_total() == 0 && _redirects.empty()) { return 0; } @@ -469,28 +461,27 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe return 0; } - transport_frame = _session.transport_frame(); + jack_nframes_t transport_frame = _session.transport_frame(); if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) { /* need to do this so that the diskstream sets its playback distance to zero, thus causing diskstream::commit to do nothing. - */ + */ return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input); } _silent = false; - //apply_gain_automation = false; if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) { - + silence (nframes, offset); return dret; } /* special condition applies */ - + if (_meter_point == MeterInput) { just_meter_input (start_frame, end_frame, nframes, offset); } @@ -499,53 +490,30 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe /* not actually recording, but we want to hear the input material anyway, at least potentially (depending on monitoring options) - */ + */ passthru (start_frame, end_frame, nframes, offset, 0, true); - } else if ((b = diskstream.playback_buffer()) != 0) { + } else { /* - XXX is it true that the earlier test on n_outputs() - means that we can avoid checking it again here? i think - so, because changing the i/o configuration of an IO - requires holding the AudioEngine lock, which we hold - while in the process() tree. - */ + XXX is it true that the earlier test on n_outputs() + means that we can avoid checking it again here? i think + so, because changing the i/o configuration of an IO + requires holding the AudioEngine lock, which we hold + while in the process() tree. + */ + - /* copy the diskstream data to all output buffers */ - + //const size_t limit = n_process_buffers().get(DataType::AUDIO); BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers()); - - //uint32_t n; - //uint32_t i; -#if 0 - for (i = 0, n = 1; i < limit; ++i, ++n) { - memcpy (bufs.get_audio(i).data(nframes), b, sizeof (Sample) * nframes); - if (n < diskstream.n_channels().get(DataType::AUDIO)) { - tmpb = diskstream.playback_buffer(n); - if (tmpb!=0) { - b = tmpb; - } - } - } - /* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */ + diskstream.get_playback(bufs.get_midi(0), start_frame, end_frame); - if (!diskstream.record_enabled() && _session.transport_rolling()) { - Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK); - - if (am.locked() && gain_automation_playback()) { - apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes); - } - } -#endif - process_output_buffers (bufs, start_frame, end_frame, nframes, offset, (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput)); - - } else { - /* problem with the diskstream; just be quiet for a bit */ - silence (nframes, offset); + process_output_buffers (bufs, start_frame, end_frame, nframes, offset, + (!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput)); + } return 0; @@ -584,7 +552,6 @@ MidiTrack::process_output_buffers (BufferSet& bufs, // Main output stage is the only stage we've got. // I think it's a pretty good stage though, wouldn't you say? - if (muted()) { IO::silence(nframes, offset); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 757c40452f..2ea6c314c1 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -679,6 +679,12 @@ Route::passthru (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nfra #undef meter_stream } +void +Route::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) +{ + process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, offset, true, declick, meter); +} + void Route::set_solo (bool yn, void *src) { diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index aa2f12aa65..28816541f1 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -224,7 +224,7 @@ Track::set_name (string str, void *src) if ((ret = IO::set_name (str, src)) == 0) { _session.save_state (""); - _session.save_history (""); + _session.save_history (""); } return ret; } -- cgit v1.2.3