diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 6c2919f5dd..8b6729cc4a 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -2029,7 +2029,7 @@ Editor::start_marker_grab (ArdourCanvas::Item* item, GdkEvent* event) drag_info.copied_location = new Location (*location); drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end()); - + update_marker_drag_item (location); if (location->is_mark()) { @@ -2088,31 +2088,39 @@ Editor::marker_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event) move_both = true; } - if (is_start) { // start marker + if (copy_location->is_mark()) { + /* just move it */ - if (move_both) { - copy_location->set_start (newframe); - copy_location->set_end (newframe + f_delta); - } else if (newframe < copy_location->end()) { - copy_location->set_start (newframe); - } else { - snap_to (next, 1, true); - copy_location->set_end (next); - copy_location->set_start (newframe); - } + copy_location->set_start (newframe); - } else { // end marker + } else { - if (move_both) { - copy_location->set_end (newframe); - copy_location->set_start (newframe - f_delta); - } else if (newframe > copy_location->start()) { - copy_location->set_end (newframe); + if (is_start) { // start-of-range marker - } else if (newframe > 0) { - snap_to (next, -1, true); - copy_location->set_start (next); - copy_location->set_end (newframe); + if (move_both) { + copy_location->set_start (newframe); + copy_location->set_end (newframe + f_delta); + } else if (newframe < copy_location->end()) { + copy_location->set_start (newframe); + } else { + snap_to (next, 1, true); + copy_location->set_end (next); + copy_location->set_start (newframe); + } + + } else { // end marker + + if (move_both) { + copy_location->set_end (newframe); + copy_location->set_start (newframe - f_delta); + } else if (newframe > copy_location->start()) { + copy_location->set_end (newframe); + + } else if (newframe > 0) { + snap_to (next, -1, true); + copy_location->set_start (next); + copy_location->set_end (newframe); + } } } @@ -2145,7 +2153,11 @@ Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event Location * location = find_location_from_marker (marker, is_start); if (location) { - location->set (drag_info.copied_location->start(), drag_info.copied_location->end()); + if (location->is_mark()) { + location->set_start (drag_info.copied_location->start()); + } else { + location->set (drag_info.copied_location->start(), drag_info.copied_location->end()); + } } session->add_redo_no_execute( session->locations()->get_memento() ); diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc index ca6b6c7efe..a39f2996f8 100644 --- a/gtk2_ardour/pan_automation_time_axis.cc +++ b/gtk2_ardour/pan_automation_time_axis.cc @@ -88,7 +88,7 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv _session.begin_reversible_command (_("add pan automation event")); _session.add_undo (alist.get_memento()); alist.add (when, y); - _session.add_undo (alist.get_memento()); + _session.add_redo_no_execute (alist.get_memento()); _session.commit_reversible_command (); _session.set_dirty (); } diff --git a/gtk2_ardour/taperegionview.cc b/gtk2_ardour/taperegionview.cc index 641d067350..228e45a9d5 100644 --- a/gtk2_ardour/taperegionview.cc +++ b/gtk2_ardour/taperegionview.cc @@ -42,16 +42,19 @@ using namespace PBD; using namespace Editing; using namespace ArdourCanvas; +const TimeAxisViewItem::Visibility TapeAudioRegionView::default_tape_visibility = TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameHighlight| + TimeAxisViewItem::ShowFrame| + TimeAxisViewItem::HideFrameRight| + TimeAxisViewItem::FullWidthNameHighlight); + TapeAudioRegionView::TapeAudioRegionView (ArdourCanvas::Group *parent, AudioTimeAxisView &tv, AudioRegion& r, double spu, Gdk::Color& basic_color) : AudioRegionView (parent, tv, r, spu, basic_color, - TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameHighlight| - TimeAxisViewItem::ShowFrame| - TimeAxisViewItem::HideFrameLR| - TimeAxisViewItem::FullWidthNameHighlight)) + TimeAxisViewItem::Visibility ((r.position() != 0) ? default_tape_visibility : + TimeAxisViewItem::Visibility (default_tape_visibility|TimeAxisViewItem::HideFrameLeft))) { } diff --git a/gtk2_ardour/taperegionview.h b/gtk2_ardour/taperegionview.h index 3e23e0fc19..6b4a57fc97 100644 --- a/gtk2_ardour/taperegionview.h +++ b/gtk2_ardour/taperegionview.h @@ -40,6 +40,8 @@ class TapeAudioRegionView : public AudioRegionView void set_frame_color (); void update (uint32_t n); + + static const TimeAxisViewItem::Visibility default_tape_visibility; }; #endif /* __gtk_ardour_tape_audio_region_view_h__ */ diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index f3f96e4065..047887abeb 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -661,8 +661,6 @@ TimeAxisView::show_selection (TimeSelection& ts) void TimeAxisView::reshow_selection (TimeSelection& ts) { - cerr << name() << ": reshow selection" << endl; - show_selection (ts); for (vector::iterator i = children.begin(); i != children.end(); ++i) { @@ -948,8 +946,6 @@ TimeAxisView::compute_controls_size_info () hSmaller = req.height + extra_height; - cerr << "hSmaller = " << hSmaller << endl; - window.remove (); window.add (two_row_table); diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc index a0ceb27293..28fafcaa09 100644 --- a/gtk2_ardour/time_axis_view_item.cc +++ b/gtk2_ardour/time_axis_view_item.cc @@ -93,8 +93,6 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& NAME_HIGHLIGHT_SIZE = height + 6; NAME_HIGHLIGHT_THRESH = NAME_HIGHLIGHT_SIZE * 2; - cerr << "name highlight threshold = " << NAME_HIGHLIGHT_THRESH << endl; - have_name_font = true; } @@ -139,8 +137,12 @@ TimeAxisViewItem::TimeAxisViewItem(const string & it_name, ArdourCanvas::Group& uint32_t outline_what = 0x1|0x2|0x4|0x8; - if (visibility & HideFrameLR) { - outline_what &= ~(0x1 | 0x2); + if (visibility & HideFrameLeft) { + outline_what &= ~(0x1); + } + + if (visibility & HideFrameRight) { + outline_what &= ~(0x2); } if (visibility & HideFrameTB) { diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h index b23350eef7..9ddb06876a 100644 --- a/gtk2_ardour/time_axis_view_item.h +++ b/gtk2_ardour/time_axis_view_item.h @@ -316,9 +316,10 @@ class TimeAxisViewItem : public Selectable ShowNameHighlight = 0x2, ShowNameText = 0x4, ShowHandles = 0x8, - HideFrameLR = 0x10, - HideFrameTB = 0x20, - FullWidthNameHighlight = 0x40 + HideFrameLeft = 0x10, + HideFrameRight = 0x20, + HideFrameTB = 0x40, + FullWidthNameHighlight = 0x80 }; /** diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 8409f99b51..60b40e3df2 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -439,6 +439,8 @@ class AudioDiskstream : public Stateful, public sigc::trackable void set_align_style_from_io(); void setup_destructive_playlist (); void use_destructive_playlist (); + void engage_record_enable (void* src); + void disengage_record_enable (void* src); }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h index 492fc9ac2e..35158a24e7 100644 --- a/libs/ardour/ardour/audiosource.h +++ b/libs/ardour/ardour/audiosource.h @@ -51,6 +51,13 @@ class AudioSource : public Source AudioSource (const XMLNode&); virtual ~AudioSource (); + /* one could argue that this should belong to Source, but other data types + generally do not come with a model of "offset along an audio timeline" + so its here in AudioSource for now. + */ + + virtual jack_nframes_t natural_position() const { return 0; } + /* returns the number of items in this `audio_source' */ virtual jack_nframes_t length() const { diff --git a/libs/ardour/ardour/sndfilesource.h b/libs/ardour/ardour/sndfilesource.h index fe90085048..55a0e990a0 100644 --- a/libs/ardour/ardour/sndfilesource.h +++ b/libs/ardour/ardour/sndfilesource.h @@ -51,6 +51,8 @@ class SndFileSource : public AudioFileSource { int update_header (jack_nframes_t when, struct tm&, time_t); int flush_header (); + jack_nframes_t natural_position () const; + protected: void set_header_timeline_position (); diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index a6103683e4..e7cb48452b 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -457,8 +457,10 @@ AudioDiskstream::setup_destructive_playlist () /* a single full-sized region */ + cerr << "setup DS using " << srcs.front()->natural_position () << endl; + AudioRegion* region = new AudioRegion (srcs, 0, max_frames, _name); - _playlist->add_region (*region, 0); + _playlist->add_region (*region, srcs.front()->natural_position()); } void @@ -1151,6 +1153,12 @@ AudioDiskstream::seek (jack_nframes_t frame, bool complete_refill) (*chan).capture_buf->reset (); } + /* can't rec-enable in destructive mode if transport is before start */ + + if (destructive() && record_enabled() && frame < _session.current_start_frame()) { + disengage_record_enable (this); + } + playback_sample = frame; file_frame = frame; @@ -1562,7 +1570,6 @@ AudioDiskstream::do_flush (char * workbuf, bool force_flush) to_write = min (disk_io_chunk_frames, (jack_nframes_t) vector.len[0]); - // check the transition buffer when recording destructive // important that we get this after the capture buf @@ -1899,15 +1906,15 @@ AudioDiskstream::finish_capture (bool rec_monitors_input) void AudioDiskstream::set_record_enabled (bool yn, void* src) { - bool rolling = _session.transport_speed() != 0.0f; - if (!recordable() || !_session.record_enabling_legal()) { return; } - - /* if we're turning on rec-enable, there needs to be an - input connection. - */ + + /* can't rec-enable in destructive mode if transport is before start */ + + if (destructive() && yn && _session.transport_frame() < _session.current_start_frame()) { + return; + } if (yn && channels[0].source == 0) { @@ -1924,37 +1931,52 @@ AudioDiskstream::set_record_enabled (bool yn, void* src) if (record_enabled() != yn) { if (yn) { - g_atomic_int_set (&_record_enabled, 1); - capturing_sources.clear (); - if (Config->get_use_hardware_monitoring()) { - for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { - if ((*chan).source) { - (*chan).source->request_monitor_input (!(_session.get_auto_input() && rolling)); - } - capturing_sources.push_back ((*chan).write_source); - } - } else { - for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { - capturing_sources.push_back ((*chan).write_source); - } - } - + engage_record_enable (src); } else { - g_atomic_int_set (&_record_enabled, 0); - if (Config->get_use_hardware_monitoring()) { - for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { - if ((*chan).source) { - (*chan).source->request_monitor_input (false); - } - } - } - capturing_sources.clear (); + disengage_record_enable (src); } - - record_enable_changed (src); /* EMIT SIGNAL */ } } +void +AudioDiskstream::engage_record_enable (void* src) +{ + bool rolling = _session.transport_speed() != 0.0f; + + g_atomic_int_set (&_record_enabled, 1); + capturing_sources.clear (); + if (Config->get_use_hardware_monitoring()) { + for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { + if ((*chan).source) { + (*chan).source->request_monitor_input (!(_session.get_auto_input() && rolling)); + } + capturing_sources.push_back ((*chan).write_source); + } + } else { + for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { + capturing_sources.push_back ((*chan).write_source); + } + } + + record_enable_changed (src); /* EMIT SIGNAL */ +} + +void +AudioDiskstream::disengage_record_enable (void* src) +{ + g_atomic_int_set (&_record_enabled, 0); + if (Config->get_use_hardware_monitoring()) { + for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { + if ((*chan).source) { + (*chan).source->request_monitor_input (false); + } + } + } + capturing_sources.clear (); + record_enable_changed (src); /* EMIT SIGNAL */ +} + + XMLNode& AudioDiskstream::get_state () { diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index ac5569bb24..034b61860a 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -594,7 +594,7 @@ void AudioFileSource::set_header_position_offset (jack_nframes_t offset) { header_position_offset = offset; - + cerr << "hpo set to " << offset << endl; HeaderPositionOffsetChanged (); } diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc index 15ff259283..68eeded9b2 100644 --- a/libs/ardour/destructive_filesource.cc +++ b/libs/ardour/destructive_filesource.cc @@ -130,8 +130,12 @@ DestructiveFileSource::setup_standard_crossfades (jack_nframes_t rate) void DestructiveFileSource::mark_capture_start (jack_nframes_t pos) { - _capture_start = true; - capture_start_frame = pos; + if (pos < timeline_position) { + _capture_start = false; + } else { + _capture_start = true; + capture_start_frame = pos; + } } void @@ -271,6 +275,11 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char * } if (_capture_start && _capture_end) { + + /* start and end of capture both occur within the data we are writing, + so do both crossfades. + */ + _capture_start = false; _capture_end = false; @@ -296,8 +305,12 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char * } file_pos = ofilepos; // adjusted below - } - else if (_capture_start) { + + } else if (_capture_start) { + + /* start of capture both occur within the data we are writing, + so do the fade in + */ _capture_start = false; _capture_end = false; @@ -311,6 +324,10 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char * } else if (_capture_end) { + /* end of capture both occur within the data we are writing, + so do the fade out + */ + _capture_start = false; _capture_end = false; @@ -320,6 +337,8 @@ DestructiveFileSource::write_unlocked (Sample* data, jack_nframes_t cnt, char * } else { + /* in the middle of recording */ + if (write_float (data, file_pos, cnt) != cnt) { return 0; } diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc index 6af87c58f3..5b5f733138 100644 --- a/libs/ardour/location.cc +++ b/libs/ardour/location.cc @@ -45,6 +45,10 @@ Location::Location (const Location& other) _end (other._end), _flags (other._flags) { + /* start and end flags can never be copied, because there can only ever be one of each */ + + _flags = Flags (_flags & ~IsStart); + _flags = Flags (_flags & ~IsEnd); } Location* diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 118bdd77cf..5936f62570 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -249,14 +249,14 @@ SndFileSource::open () _flags = Flag (_flags & ~Broadcast); } - set_timeline_position (0); + set_timeline_position (header_position_offset); } else { /* XXX 64 bit alert: when JACK switches to a 64 bit frame count, this needs to use the high bits of the time reference. */ - + set_timeline_position ( _broadcast_info->time_reference_low ); } @@ -525,3 +525,9 @@ SndFileSource::write_float (Sample* data, jack_nframes_t frame_pos, jack_nframes return cnt; } + +jack_nframes_t +SndFileSource::natural_position() const +{ + return timeline_position; +}