diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2012-07-17 03:10:40 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2012-07-17 03:10:40 +0000 |
commit | 3c252e9321dccf9b653b6b9ab4a7ffe5cda31b79 (patch) | |
tree | b8afdbe754818713249fb9d14e5b8a79ab24243d /libs/ardour | |
parent | 539b94490f7ab660f24b3de80df5514f61d481b0 (diff) |
lots more fidgety work on automation. sort of works now, but undo/redo needs attention
git-svn-id: svn://localhost/ardour2/branches/3.0@13047 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/automation_watch.h | 2 | ||||
-rw-r--r-- | libs/ardour/automation_control.cc | 17 | ||||
-rw-r--r-- | libs/ardour/automation_watch.cc | 43 | ||||
-rw-r--r-- | libs/ardour/midi_source.cc | 4 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 6 | ||||
-rw-r--r-- | libs/ardour/smf_source.cc | 9 |
6 files changed, 67 insertions, 14 deletions
diff --git a/libs/ardour/ardour/automation_watch.h b/libs/ardour/ardour/automation_watch.h index 2dfadf6426..bb5ef69385 100644 --- a/libs/ardour/ardour/automation_watch.h +++ b/libs/ardour/ardour/automation_watch.h @@ -51,7 +51,9 @@ class AutomationWatch : public sigc::trackable, public ARDOUR::SessionHandlePtr, bool _run_thread; AutomationWatches automation_watches; Glib::Mutex automation_watch_lock; + PBD::ScopedConnection transport_connection; + void transport_state_change (); void remove_weak_automation_watch (boost::weak_ptr<ARDOUR::AutomationControl>); void thread (); }; diff --git a/libs/ardour/automation_control.cc b/libs/ardour/automation_control.cc index 237d51a9d3..83b7db34be 100644 --- a/libs/ardour/automation_control.cc +++ b/libs/ardour/automation_control.cc @@ -60,7 +60,6 @@ void AutomationControl::set_value (double value) { bool to_list = _list && ((AutomationList*)_list.get())->automation_write(); - bool erase_since_last = _session.transport_rolling(); if (to_list && parameter().toggled()) { @@ -68,15 +67,14 @@ AutomationControl::set_value (double value) // interpolation works right - _list->add (get_double(), _session.transport_frame()-1, erase_since_last); + _list->add (get_double(), _session.transport_frame()-1); } - Control::set_double (value, _session.transport_frame(), to_list, erase_since_last); + Control::set_double (value, _session.transport_frame(), to_list); Changed(); /* EMIT SIGNAL */ } - void AutomationControl::set_list (boost::shared_ptr<Evoral::ControlList> list) { @@ -91,17 +89,24 @@ AutomationControl::set_automation_state (AutoState as) cerr << name() << " setting automation state to " << enum_2_string (as) << endl; + alist()->set_automation_state (as); + if (as == Write) { AutomationWatch::instance().add_automation_watch (shared_from_this()); } else if (as == Touch) { if (!touching()) { AutomationWatch::instance().remove_automation_watch (shared_from_this()); + } else { + /* this seems unlikely, but the combination of + * a control surface and the mouse could make + * it possible to put the control into Touch + * mode *while* touching it. + */ + AutomationWatch::instance().add_automation_watch (shared_from_this()); } } else { AutomationWatch::instance().remove_automation_watch (shared_from_this()); } - - alist()->set_automation_state (as); } } diff --git a/libs/ardour/automation_watch.cc b/libs/ardour/automation_watch.cc index 670636e977..5fefcaca8d 100644 --- a/libs/ardour/automation_watch.cc +++ b/libs/ardour/automation_watch.cc @@ -68,6 +68,16 @@ AutomationWatch::add_automation_watch (boost::shared_ptr<AutomationControl> ac) DEBUG_TRACE (DEBUG::Automation, string_compose ("now watching control %1 for automation\n", ac->name())); automation_watches.push_back (ac); + /* if an automation control is added here while the transport is + * rolling, make sure that it knows that there is a write pass going + * on, rather than waiting for the transport to start. + */ + + if (_session && _session->transport_rolling() && ac->alist()->automation_write()) { + DEBUG_TRACE (DEBUG::Automation, string_compose ("\ttransport is rolling @ %1, so enter write pass\n", _session->transport_speed())); + ac->list()->set_in_write_pass (true); + } + /* we can't store shared_ptr<Destructible> in connections because it * creates reference cycles. we don't need to make the weak_ptr<> * explicit here, but it helps to remind us what is going on. @@ -95,6 +105,7 @@ AutomationWatch::remove_automation_watch (boost::shared_ptr<AutomationControl> a Glib::Mutex::Lock lm (automation_watch_lock); DEBUG_TRACE (DEBUG::Automation, string_compose ("remove control %1 from automation watch\n", ac->name())); automation_watches.remove (ac); + ac->list()->set_in_write_pass (false); } gint @@ -110,7 +121,9 @@ AutomationWatch::timer () framepos_t time = _session->audible_frame (); for (AutomationWatches::iterator aw = automation_watches.begin(); aw != automation_watches.end(); ++aw) { - (*aw)->list()->add (time, (*aw)->user_double(), true); + if ((*aw)->alist()->automation_write()) { + (*aw)->list()->add (time, (*aw)->user_double()); + } } } @@ -129,6 +142,8 @@ AutomationWatch::thread () void AutomationWatch::set_session (Session* s) { + transport_connection.disconnect (); + if (_thread) { _run_thread = false; _thread->join (); @@ -142,5 +157,31 @@ AutomationWatch::set_session (Session* s) _thread = Glib::Thread::create (boost::bind (&AutomationWatch::thread, this), 500000, true, true, Glib::THREAD_PRIORITY_NORMAL); + _session->TransportStateChange.connect_same_thread (transport_connection, boost::bind (&AutomationWatch::transport_state_change, this)); + } +} + +void +AutomationWatch::transport_state_change () +{ + if (!_session) { + return; + } + + bool rolling = _session->transport_rolling(); + + { + Glib::Mutex::Lock lm (automation_watch_lock); + + for (AutomationWatches::iterator aw = automation_watches.begin(); aw != automation_watches.end(); ++aw) { + DEBUG_TRACE (DEBUG::Automation, string_compose ("%1: transport state changed, speed %2, in write pass ? %3 writing ? %4\n", + (*aw)->name(), _session->transport_speed(), rolling, + (*aw)->alist()->automation_write())); + if (rolling && (*aw)->alist()->automation_write()) { + (*aw)->list()->set_in_write_pass (true); + } else { + (*aw)->list()->set_in_write_pass (false); + } + } } } diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 6c6821d773..96e7b2b934 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -300,8 +300,6 @@ MidiSource::mark_write_starting_now () set_timeline_position (_session.transport_frame ()); _last_write_end = _session.transport_frame (); - cerr << name() << " last write set to " << _last_write_end << endl; - } void @@ -388,7 +386,7 @@ MidiSource::session_saved() */ if (_model && _model->edited()) { - + // if the model is edited, write its contents into // the current source file (overwiting previous contents. diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index b5fb2a790f..795a106685 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -638,6 +638,7 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished) } PositionChanged (_transport_frame); /* EMIT SIGNAL */ + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC with speed = %1\n", _transport_speed)); TransportStateChange (); /* EMIT SIGNAL */ /* and start it up again if relevant */ @@ -766,6 +767,7 @@ Session::set_play_loop (bool yn) unset_play_loop (); } + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC2 with speed = %1\n", _transport_speed)); TransportStateChange (); } void @@ -1117,6 +1119,7 @@ Session::set_transport_speed (double speed, bool abort, bool clear_state, bool a _butler->schedule_transport_work (); } + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC3 with speed = %1\n", _transport_speed)); TransportStateChange (); /* EMIT SIGNAL */ } } @@ -1238,6 +1241,7 @@ Session::start_transport () } } + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC4 with speed = %1\n", _transport_speed)); TransportStateChange (); /* EMIT SIGNAL */ } @@ -1486,6 +1490,7 @@ Session::set_play_range (list<AudioRange>& range, bool leave_rolling) ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, SessionEvent::Immediate, range.front().start, 0.0f, false); merge_event (ev); + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC5 with speed = %1\n", _transport_speed)); TransportStateChange (); } @@ -1528,6 +1533,7 @@ Session::engine_halted () non_realtime_stop (false, 0, ignored); transport_sub_state = 0; + DEBUG_TRACE (DEBUG::Transport, string_compose ("send TSC6 with speed = %1\n", _transport_speed)); TransportStateChange (); /* EMIT SIGNAL */ } diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index da6b3cad6f..368982f10d 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -281,7 +281,7 @@ SMFSource::write_unlocked (MidiRingBuffer<framepos_t>& source, framepos_t positi append_event_unlocked_frames(ev, position); } - Evoral::SMF::flush(); + Evoral::SMF::flush (); free (buf); return duration; @@ -338,9 +338,9 @@ SMFSource::append_event_unlocked_frames (const Evoral::Event<framepos_t>& ev, fr return; } - /* printf("SMFSource: %s - append_event_unlocked_frames ID = %d time = %u, size = %u, data = ", - name().c_str(), ev.id(), ev.time(), ev.size()); - for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n");*/ + // printf("SMFSource: %s - append_event_unlocked_frames ID = %d time = %u, size = %u, data = ", + // name().c_str(), ev.id(), ev.time(), ev.size()); + // for (size_t i=0; i < ev.size(); ++i) printf("%X ", ev.buffer()[i]); printf("\n"); if (ev.time() < _last_ev_time_frames) { cerr << "SMFSource: Warning: Skipping event with non-monotonic time" << endl; @@ -431,6 +431,7 @@ SMFSource::mark_midi_streaming_write_completed (Evoral::Sequence<Evoral::Musical MidiSource::mark_midi_streaming_write_completed (stuck_notes_option, when); if (!writable()) { + warning << string_compose ("attempt to write to unwritable SMF file %1", _path) << endmsg; return; } |