From 0d0f71ee92fb7ce53fbcb8c7b0cd93b1cdf3529f Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 9 Oct 2006 15:50:44 +0000 Subject: fix abort-capture path, including many subtle issues with shared_ptr<>; remove old automation feedback code; make new automation feedback code slightly configurable ; fix zoom focus options for playhead + edit cursor ; prevent zoom < 2 samples per pixel to avoid crashes ; peak building now uses shared_ptr not Source* git-svn-id: svn://localhost/ardour2/trunk@959 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/ardour_ui.cc | 16 +------ gtk2_ardour/ardour_ui.h | 2 - gtk2_ardour/audio_streamview.cc | 56 ++++++++++++---------- gtk2_ardour/audio_streamview.h | 7 +-- gtk2_ardour/editor.cc | 12 +++-- gtk2_ardour/streamview.cc | 27 ++--------- gtk2_ardour/streamview.h | 2 +- libs/ardour/ardour/audiofilesource.h | 3 ++ libs/ardour/ardour/audioregion.h | 2 +- libs/ardour/ardour/audiosource.h | 13 +++-- libs/ardour/ardour/diskstream.h | 1 - libs/ardour/ardour/insert.h | 1 - libs/ardour/ardour/io.h | 16 +------ libs/ardour/ardour/route.h | 2 - libs/ardour/ardour/source_factory.h | 3 ++ libs/ardour/audio_diskstream.cc | 31 ++++-------- libs/ardour/audio_track.cc | 9 ---- libs/ardour/audiofilesource.cc | 27 +++++++++-- libs/ardour/audioregion.cc | 25 +++++----- libs/ardour/audiosource.cc | 12 ++--- libs/ardour/coreaudiosource.cc | 5 +- libs/ardour/destructive_filesource.cc | 2 +- libs/ardour/diskstream.cc | 1 - libs/ardour/insert.cc | 18 ------- libs/ardour/io.cc | 19 -------- libs/ardour/playlist.cc | 15 +++++- libs/ardour/route.cc | 23 --------- libs/ardour/session.cc | 45 ++++++++--------- libs/ardour/session_state.cc | 1 - libs/ardour/session_transport.cc | 33 +++++++------ libs/ardour/sndfilesource.cc | 32 +++---------- libs/ardour/source_factory.cc | 52 +++++++++++++++++++- libs/pbd/pbd/stacktrace.h | 2 +- libs/pbd/stacktrace.cc | 6 +-- .../control_protocol/control_protocol.h | 4 ++ .../generic_midi/generic_midi_control_protocol.cc | 43 +++++++++++++++-- .../generic_midi/generic_midi_control_protocol.h | 5 ++ 37 files changed, 284 insertions(+), 289 deletions(-) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 55370e7557..b2da3fdc4c 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -178,7 +178,6 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) gettimeofday (&last_peak_grab, 0); gettimeofday (&last_shuttle_request, 0); - ARDOUR::AudioDiskstream::DeleteSources.connect (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread)); ARDOUR::Diskstream::DiskOverrun.connect (mem_fun(*this, &ARDOUR_UI::disk_overrun_handler)); ARDOUR::Diskstream::DiskUnderrun.connect (mem_fun(*this, &ARDOUR_UI::disk_underrun_handler)); @@ -1041,8 +1040,7 @@ ARDOUR_UI::transport_record () switch (session->record_status()) { case Session::Disabled: if (session->ntracks() == 0) { - string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."); - MessageDialog msg (*editor, txt); + MessageDialog msg (*editor, _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu.")); msg.run (); return; } @@ -2197,18 +2195,6 @@ ARDOUR_UI::halt_on_xrun_message () msg.run (); } -void -ARDOUR_UI::delete_sources_in_the_right_thread (list >* deletion_list) -{ - ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list)); - - for (list >::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) { - (*i)->drop_references (); - } - - delete deletion_list; -} - void ARDOUR_UI::disk_overrun_handler () { diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h index cf6cda526a..69f2cd0492 100644 --- a/gtk2_ardour/ardour_ui.h +++ b/gtk2_ardour/ardour_ui.h @@ -624,8 +624,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI struct timeval last_peak_grab; struct timeval last_shuttle_request; - void delete_sources_in_the_right_thread (list >*); - void editor_display_control_changed (Editing::DisplayControl c); bool have_disk_overrun_displayed; diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc index 085f429f99..222c920709 100644 --- a/gtk2_ardour/audio_streamview.cc +++ b/gtk2_ardour/audio_streamview.cc @@ -128,6 +128,8 @@ AudioStreamView::set_amplitude_above_axis (gdouble app) void AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wait_for_waves) { + AudioRegionView *region_view; + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r)); boost::shared_ptr region = boost::dynamic_pointer_cast (r); @@ -136,19 +138,16 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wai return; } - AudioRegionView *region_view; - list::iterator i; - - for (i = region_views.begin(); i != region_views.end(); ++i) { + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { if ((*i)->region() == r) { /* great. we already have a AudioRegionView for this Region. use it again. */ - + (*i)->set_valid (true); return; } } - + switch (_trackview.audio_track()->mode()) { case Normal: region_view = new AudioRegionView (canvas_group, _trackview, region, @@ -170,15 +169,21 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr r, bool wai /* catch regionview going away */ - region->GoingAway.connect (bind (mem_fun (*this, &AudioStreamView::remove_region_view), region)); - + region->GoingAway.connect (bind (mem_fun (*this, &AudioStreamView::remove_region_view), boost::weak_ptr (r))); + RegionViewAdded (region_view); } void -AudioStreamView::remove_region_view (boost::shared_ptr r) +AudioStreamView::remove_region_view (boost::weak_ptr weak_r) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), r)); + ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::remove_region_view), weak_r)); + + boost::shared_ptr r (weak_r.lock()); + + if (!r) { + return; + } for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end();) { list::iterator tmp; @@ -406,7 +411,7 @@ AudioStreamView::setup_rec_box () boost::shared_ptr src = boost::static_pointer_cast (ads->write_source (n)); if (src) { sources.push_back (src); - peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), src))); + peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), boost::weak_ptr(src)))); } } @@ -420,11 +425,8 @@ AudioStreamView::setup_rec_box () boost::shared_ptr region (boost::dynamic_pointer_cast (RegionFactory::create (sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false))); region->set_position (_trackview.session().transport_frame(), this); - rec_regions.push_back (region); - - // rec regions are destroyed in setup_rec_box - /* we add the region later */ + rec_regions.push_back (region); } /* start a new rec box */ @@ -503,13 +505,9 @@ AudioStreamView::setup_rec_box () last_rec_peak_frame = 0; /* remove temp regions */ - - for (list >::iterator iter = rec_regions.begin(); iter != rec_regions.end();) { - list >::iterator tmp; - tmp = iter; - ++tmp; + + for (list >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); ++iter) { (*iter)->drop_references (); - iter = tmp; } rec_regions.clear(); @@ -537,18 +535,24 @@ AudioStreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void)) } void -AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::shared_ptr src) +AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr weak_src) { - // this is called from the peak building thread + ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, weak_src)); + + boost::shared_ptr src (weak_src.lock()); - ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, src)); + if (!src) { + return; + } + + // this is called from the peak building thread if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) { last_rec_peak_frame = start + cnt; } - + rec_peak_ready_map[src] = true; - + if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) { this->update_rec_regions (); rec_peak_ready_map.clear(); diff --git a/gtk2_ardour/audio_streamview.h b/gtk2_ardour/audio_streamview.h index b61101f788..c6db40f336 100644 --- a/gtk2_ardour/audio_streamview.h +++ b/gtk2_ardour/audio_streamview.h @@ -23,6 +23,8 @@ #include #include +#include + #include #include "enums.h" #include "simplerect.h" @@ -76,13 +78,12 @@ class AudioStreamView : public StreamView private: void setup_rec_box (); - void rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::shared_ptr src); + void rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr src); void update_rec_regions (); void add_region_view_internal (boost::shared_ptr, bool wait_for_waves); - void remove_region_view (boost::shared_ptr ); + void remove_region_view (boost::weak_ptr ); void remove_audio_region_view (boost::shared_ptr ); - void remove_audio_rec_region (boost::shared_ptr); void undisplay_diskstream (); void redisplay_diskstream (); diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index f1fe88cd7a..fb0d0782dc 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -132,8 +132,8 @@ static const gchar *zoom_focus_strings[] = { N_("Focus Left"), N_("Focus Right"), N_("Focus Center"), - N_("Focus Play"), - N_("Focus Edit"), + N_("Focus Playhead"), + N_("Focus Edit Cursor"), 0 }; @@ -801,8 +801,8 @@ Editor::set_frames_per_unit (double fpu) return; } - if (fpu < 1.0) { - fpu = 1.0; + if (fpu < 2.0) { + fpu = 2.0; } // convert fpu to frame count @@ -817,6 +817,10 @@ Editor::set_frames_per_unit (double fpu) return; } + if (fpu == frames_per_unit) { + return; + } + frames_per_unit = fpu; if (frames != zoom_range_clock.current_duration()) { diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc index 097e581cdf..0a35709538 100644 --- a/gtk2_ardour/streamview.cc +++ b/gtk2_ardour/streamview.cc @@ -164,9 +164,11 @@ StreamView::add_region_view (boost::shared_ptr r) } void -StreamView::remove_region_view (boost::shared_ptr r) +StreamView::remove_region_view (boost::weak_ptr weak_r) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_region_view), r)); + ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::remove_region_view), weak_r)); + + boost::shared_ptr r (weak_r.lock()); for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { if (((*i)->region()) == r) { @@ -177,27 +179,6 @@ StreamView::remove_region_view (boost::shared_ptr r) } } -#if 0 -(unused) -void -StreamView::remove_rec_region (boost::shared_ptr r) -{ - ENSURE_GUI_THREAD(bind (mem_fun (*this, &StreamView::remove_rec_region), r)); - - if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) { - fatal << "region deleted from non-GUI thread!" << endmsg; - /*NOTREACHED*/ - } - - for (list >::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) { - if (*i == r) { - rec_regions.erase (i); - break; - } - } -} -#endif - void StreamView::undisplay_diskstream () { diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h index b1fd3c1b29..cc5f9cb414 100644 --- a/gtk2_ardour/streamview.h +++ b/gtk2_ardour/streamview.h @@ -108,7 +108,7 @@ protected: virtual void update_rec_regions () = 0; virtual void add_region_view_internal (boost::shared_ptr, bool wait_for_waves) = 0; - virtual void remove_region_view (boost::shared_ptr ); + virtual void remove_region_view (boost::weak_ptr ); //void remove_rec_region (boost::shared_ptr); (unused) void display_diskstream (boost::shared_ptr); diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h index fb32d892d2..de12cb05e5 100644 --- a/libs/ardour/ardour/audiofilesource.h +++ b/libs/ardour/ardour/audiofilesource.h @@ -88,6 +88,8 @@ class AudioFileSource : public AudioSource { static void set_search_path (string); static void set_header_position_offset (nframes_t offset ); + int setup_peakfile (); + static sigc::signal HeaderPositionOffsetChanged; XMLNode& get_state (); @@ -122,6 +124,7 @@ class AudioFileSource : public AudioSource { Flag _flags; string _take_id; uint64_t timeline_position; + bool file_is_new; static string peak_dir; static string search_path; diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index d1d7c6e5fb..c9cb2b8152 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -189,7 +189,7 @@ class AudioRegion : public Region void envelope_changed (Change); void source_offset_changed (); - void source_deleted (boost::shared_ptr); + void source_deleted (); SourceList sources; diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h index d2d23bcfab..7bdc0f5d7d 100644 --- a/libs/ardour/ardour/audiosource.h +++ b/libs/ardour/ardour/audiosource.h @@ -25,6 +25,9 @@ #include #include +#include +#include + #include #include @@ -44,7 +47,7 @@ namespace ARDOUR { const nframes_t frames_per_peak = 256; -class AudioSource : public Source + class AudioSource : public Source, public boost::enable_shared_from_this { public: AudioSource (Session&, string name); @@ -104,13 +107,15 @@ class AudioSource : public Source _build_peakfiles = yn; } + virtual int setup_peakfile () { return 0; } + protected: static bool _build_missing_peakfiles; static bool _build_peakfiles; bool _peaks_built; mutable Glib::Mutex _lock; - nframes_t _length; + nframes_t _length; bool next_peak_clear_should_notify; string peakpath; string _captured_for; @@ -143,10 +148,10 @@ class AudioSource : public Source }; }; - static vector pending_peak_sources; + static vector > pending_peak_sources; static Glib::Mutex* pending_peak_sources_lock; - static void queue_for_peaks (AudioSource*); + static void queue_for_peaks (boost::shared_ptr); static void clear_queue_for_peaks (); struct PeakBuildRecord { diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index d3b5d6dce4..cffe02e859 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -147,7 +147,6 @@ class IO; static sigc::signal DiskOverrun; static sigc::signal DiskUnderrun; - static sigc::signal >*> DeleteSources; protected: friend class Session; diff --git a/libs/ardour/ardour/insert.h b/libs/ardour/ardour/insert.h index ee07b7ebd3..30378139ab 100644 --- a/libs/ardour/ardour/insert.h +++ b/libs/ardour/ardour/insert.h @@ -157,7 +157,6 @@ class PluginInsert : public Insert nframes_t latency(); void transport_stopped (nframes_t now); - void automation_snapshot (nframes_t now); protected: void store_state (PluginInsertState&) const; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index c32ef31de8..e59ec6c23d 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -234,16 +234,7 @@ public: AutoStyle gain_automation_style () const { return _gain_automation_curve.automation_style(); } sigc::signal gain_automation_style_changed; - static void set_automation_interval (nframes_t frames) { - _automation_interval = frames; - } - - static nframes_t automation_interval() { - return _automation_interval; - } - virtual void transport_stopped (nframes_t now); - virtual void automation_snapshot (nframes_t now); ARDOUR::Curve& gain_automation_curve () { return _gain_automation_curve; } @@ -310,12 +301,7 @@ public: Change restore_state (State&); StateManager::State* state_factory (std::string why) const; - /* automation */ - - nframes_t last_automation_snapshot; - static nframes_t _automation_interval; - - AutoState _gain_automation_state; + AutoState _gain_automation_state; AutoStyle _gain_automation_style; bool apply_gain_automation; diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index b3ac609880..af104bb6ea 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -238,8 +238,6 @@ class Route : public IO return _mute_control; } - void automation_snapshot (nframes_t now); - void protect_automation (); void set_remote_control_id (uint32_t id); diff --git a/libs/ardour/ardour/source_factory.h b/libs/ardour/ardour/source_factory.h index 815b825b8d..6cb262a299 100644 --- a/libs/ardour/ardour/source_factory.h +++ b/libs/ardour/ardour/source_factory.h @@ -24,6 +24,9 @@ class SourceFactory { // MIDI sources will have to be hacked in here somehow static boost::shared_ptr createReadable (Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true); static boost::shared_ptr createWritable (Session&, std::string name, bool destructive, nframes_t rate, bool announce = true); + + private: + static int setup_peakfile (boost::shared_ptr); }; } diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 1374589608..9bd690c23a 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -1484,29 +1484,21 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca if (abort_capture) { - ChannelList::iterator chan; - - list >* deletion_list = new list >; + if (destructive()) { + goto outout; + } - for ( chan = channels.begin(); chan != channels.end(); ++chan) { + for (ChannelList::iterator chan = channels.begin(); chan != channels.end(); ++chan) { if ((*chan).write_source) { (*chan).write_source->mark_for_remove (); - - deletion_list->push_back ((*chan).write_source); - + (*chan).write_source->drop_references (); (*chan).write_source.reset (); } /* new source set up in "out" below */ } - - if (!deletion_list->empty()) { - DeleteSources (deletion_list); - } else { - delete deletion_list; - } goto out; } @@ -1606,9 +1598,11 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca mark_write_completed = true; + out: reset_write_sources (mark_write_completed); - out: + outout: + for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) { delete *ci; } @@ -1933,13 +1927,8 @@ AudioDiskstream::use_new_write_source (uint32_t n) ChannelInfo &chan = channels[n]; if (chan.write_source) { - - if (AudioFileSource::is_empty (_session, chan.write_source->path())) { - chan.write_source->mark_for_remove (); - chan.write_source.reset (); - } else { - chan.write_source.reset (); - } + chan.write_source->set_allow_remove_if_empty (true); + chan.write_source.reset (); } try { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 171f2d7c6b..677c9a0497 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -507,15 +507,6 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t transport_frame; boost::shared_ptr diskstream = audio_diskstream(); - { - Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); - if (lm.locked()) { - // automation snapshot can also be called from the non-rt context - // and it uses the redirect list, so we take the lock out here - automation_snapshot (start_frame); - } - } - if (n_outputs() == 0 && _redirects.empty()) { return 0; } diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc index 9564fff53b..0eb416e905 100644 --- a/libs/ardour/audiofilesource.cc +++ b/libs/ardour/audiofilesource.cc @@ -59,8 +59,11 @@ string AudioFileSource::search_path; sigc::signal AudioFileSource::HeaderPositionOffsetChanged; uint64_t AudioFileSource::header_position_offset = 0; +/* XXX turn this into a Config option */ char AudioFileSource::bwf_country_code[3] = "US"; +/* XXX turn this into a Config option */ char AudioFileSource::bwf_organization_code[4] = "LAS"; +/* XXX maybe this too */ char AudioFileSource::bwf_serial_number[13] = "000000000000"; AudioFileSource::AudioFileSource (Session& s, string idstr, Flag flags) @@ -120,7 +123,9 @@ AudioFileSource::init (string pathstr, bool must_exist) _length = 0; timeline_position = 0; next_peak_clear_should_notify = false; - + _peaks_built = false; + file_is_new = false; + if (!find (pathstr, must_exist, is_new)) { return -1; } @@ -285,7 +290,8 @@ AudioFileSource::mark_for_remove () if (!writable()) { return; } - _flags = Flag (_flags | RemoveAtDestroy); + + _flags = Flag (_flags | Removable | RemoveAtDestroy); } void @@ -518,8 +524,14 @@ AudioFileSource::set_timeline_position (nframes_t pos) void AudioFileSource::set_allow_remove_if_empty (bool yn) { - if (writable()) { + if (!writable()) { + return; + } + + if (yn) { _flags = Flag (_flags | RemovableIfEmpty); + } else { + _flags = Flag (_flags & ~RemovableIfEmpty); } } @@ -565,3 +577,12 @@ AudioFileSource::is_empty (Session& s, string path) return ret; } +int +AudioFileSource::setup_peakfile () +{ + if (!(_flags & NoPeakFile)) { + return initialize_peakfile (file_is_new, _path); + } else { + return 0; + } +} diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 07da0039ce..787b408ace 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -75,7 +75,7 @@ AudioRegion::AudioRegion (boost::shared_ptr src, nframes_t start, n sources.push_back (src); master_sources.push_back (src); - src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src)); + src->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); boost::shared_ptr afs = boost::dynamic_pointer_cast (src); if (afs) { @@ -102,7 +102,7 @@ AudioRegion::AudioRegion (boost::shared_ptr src, nframes_t start, n sources.push_back (src); master_sources.push_back (src); - src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src)); + src->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); boost::shared_ptr afs = boost::dynamic_pointer_cast (src); if (afs) { @@ -129,7 +129,7 @@ AudioRegion::AudioRegion (SourceList& srcs, nframes_t start, nframes_t length, c for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) { sources.push_back (*i); master_sources.push_back (*i); - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), (*i))); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); boost::shared_ptr afs = boost::dynamic_pointer_cast ((*i)); if (afs) { @@ -159,7 +159,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other, nframes_t for (SourceList::const_iterator i= other->sources.begin(); i != other->sources.end(); ++i) { sources.push_back (*i); - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i)); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); pair >::iterator,bool> result; @@ -175,7 +175,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other, nframes_t for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) { if (unique_srcs.find (*i) == unique_srcs.end()) { - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i)); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); } master_sources.push_back (*i); } @@ -224,7 +224,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other) for (SourceList::const_iterator i = other->sources.begin(); i != other->sources.end(); ++i) { sources.push_back (*i); - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i)); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); pair >::iterator,bool> result; result = unique_srcs.insert (*i); @@ -240,7 +240,7 @@ AudioRegion::AudioRegion (boost::shared_ptr other) for (SourceList::const_iterator i = other->master_sources.begin(); i != other->master_sources.end(); ++i) { master_sources.push_back (*i); if (unique_srcs.find (*i) == unique_srcs.end()) { - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i)); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); } } @@ -263,7 +263,7 @@ AudioRegion::AudioRegion (boost::shared_ptr src, const XMLNode& nod { sources.push_back (src); master_sources.push_back (src); - src->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), src)); + src->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); boost::shared_ptr afs = boost::dynamic_pointer_cast (src); if (afs) { @@ -291,7 +291,7 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) for (SourceList::iterator i=srcs.begin(); i != srcs.end(); ++i) { sources.push_back (*i); - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i)); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); pair >::iterator,bool> result; result = unique_srcs.insert (*i); @@ -307,7 +307,7 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) for (SourceList::iterator i = srcs.begin(); i != srcs.end(); ++i) { master_sources.push_back (*i); if (unique_srcs.find (*i) == unique_srcs.end()) { - (*i)->GoingAway.connect (bind (mem_fun (*this, &AudioRegion::source_deleted), *i)); + (*i)->GoingAway.connect (mem_fun (*this, &AudioRegion::source_deleted)); } } @@ -1117,9 +1117,10 @@ AudioRegion::separate_by_channel (Session& session, vector& v) con } void -AudioRegion::source_deleted (boost::shared_ptr ignored) +AudioRegion::source_deleted () { - delete this; + sources.clear (); + drop_references (); } vector diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index 9aee818588..cd8c192d13 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -44,7 +44,7 @@ using namespace PBD; pthread_t AudioSource::peak_thread; bool AudioSource::have_peak_thread = false; -vector AudioSource::pending_peak_sources; +vector > AudioSource::pending_peak_sources; Glib::Mutex* AudioSource::pending_peak_sources_lock = 0; int AudioSource::peak_request_pipe[2]; @@ -191,7 +191,7 @@ AudioSource::peak_thread_work (void* arg) while (!pending_peak_sources.empty()) { - AudioSource* s = pending_peak_sources.front(); + boost::shared_ptr s = pending_peak_sources.front(); pending_peak_sources.erase (pending_peak_sources.begin()); pending_peak_sources_lock->unlock (); @@ -251,7 +251,7 @@ AudioSource::stop_peak_thread () } void -AudioSource::queue_for_peaks (AudioSource* source) +AudioSource::queue_for_peaks (boost::shared_ptr source) { if (have_peak_thread) { @@ -387,11 +387,11 @@ AudioSource::initialize_peakfile (bool newfile, string audio_path) } } } - + if (!newfile && !_peaks_built && _build_missing_peakfiles && _build_peakfiles) { build_peaks_from_scratch (); } - + return 0; } @@ -847,7 +847,7 @@ AudioSource::build_peaks_from_scratch () next_peak_clear_should_notify = true; pending_peak_builds.push_back (new PeakBuildRecord (0, _length)); - queue_for_peaks (this); + queue_for_peaks (shared_from_this()); } bool diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc index 448e9c0b32..c8cbb7a40d 100644 --- a/libs/ardour/coreaudiosource.cc +++ b/libs/ardour/coreaudiosource.cc @@ -86,10 +86,7 @@ CoreAudioSource::init (const string& idstr) } if (_build_peakfiles) { - if (initialize_peakfile (false, _path)) { - error << string_compose("CoreAudioSource: initialize peakfile failed (%1)", name()) << endmsg; - throw failed_constructor (); - } + _need_peakfile = true; } } diff --git a/libs/ardour/destructive_filesource.cc b/libs/ardour/destructive_filesource.cc index 3cd6586799..e160ffd608 100644 --- a/libs/ardour/destructive_filesource.cc +++ b/libs/ardour/destructive_filesource.cc @@ -376,7 +376,7 @@ DestructiveFileSource::write_unlocked (Sample* data, nframes_t cnt) } if (_build_peakfiles) { - queue_for_peaks (this); + queue_for_peaks (shared_from_this ()); } return cnt; diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 4f6515d076..f9fb540099 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -65,7 +65,6 @@ using namespace PBD; */ nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256; -sigc::signal >*> Diskstream::DeleteSources; sigc::signal Diskstream::DiskOverrun; sigc::signal Diskstream::DiskUnderrun; diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index d955588c44..d64cce36f9 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -316,23 +316,6 @@ PluginInsert::connect_and_run (vector& bufs, uint32_t nbufs, nframes_t /* leave remaining channel buffers alone */ } -void -PluginInsert::automation_snapshot (nframes_t now) -{ - map::iterator li; - - for (li = parameter_automation.begin(); li != parameter_automation.end(); ++li) { - - AutomationList *alist = ((*li).second); - if (alist != 0 && alist->automation_write ()) { - - float val = _plugins[0]->get_parameter ((*li).first); - alist->rt_add (now, val); - last_automation_snapshot = now; - } - } -} - void PluginInsert::transport_stopped (nframes_t now) { @@ -468,7 +451,6 @@ PluginInsert::set_port_automation_state (uint32_t port, AutoState s) if (s != al.automation_state()) { al.set_automation_state (s); - last_automation_snapshot = 0; _session.set_dirty (); } } diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 34070f3dff..b6c3648cda 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -61,7 +61,6 @@ using namespace PBD; static float current_automation_version_number = 1.0; -nframes_t IO::_automation_interval = 0; const string IO::state_node_name = "IO"; bool IO::connecting_legal = false; bool IO::ports_legal = false; @@ -127,8 +126,6 @@ IO::IO (Session& s, string name, apply_gain_automation = false; - last_automation_snapshot = 0; - _gain_automation_state = Off; _gain_automation_style = Absolute; @@ -2513,7 +2510,6 @@ IO::set_gain_automation_state (AutoState state) if (state != _gain_automation_curve.automation_state()) { changed = true; - last_automation_snapshot = 0; _gain_automation_curve.set_automation_state (state); if (state != Off) { @@ -2611,21 +2607,6 @@ IO::end_pan_touch (uint32_t which) } -void -IO::automation_snapshot (nframes_t now) -{ - if (last_automation_snapshot > now || (now - last_automation_snapshot) > _automation_interval) { - - if (gain_automation_recording()) { - _gain_automation_curve.rt_add (now, gain()); - } - - _panner->snapshot (now); - - last_automation_snapshot = now; - } -} - void IO::transport_stopped (nframes_t frame) { diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 6d6a07da95..38c7e387f8 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -1373,10 +1373,21 @@ Playlist::set_state (const XMLNode& node) if (child->name() == "Region") { - if ((region = RegionFactory::create (_session, *child, true)) == 0) { - error << _("Playlist: cannot create region from state file") << endmsg; +#if 0 + if ((prop = child->property ("id")) == 0) { + error << _("region state node has no ID, ignored") << endmsg; continue; } + + ID id = prop->value (); + + if ((region = region_by_id (id)) == 0) { +#endif + if ((region = RegionFactory::create (_session, *child, true)) == 0) { + error << _("Playlist: cannot create region from state file") << endmsg; + continue; + } +// } add_region (region, region->position(), 1.0, false); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 15b148ffb3..318989bb60 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1959,10 +1959,6 @@ Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_f { Glib::RWLock::ReaderLock lm (redirect_lock); - if (!did_locate) { - automation_snapshot (now); - } - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { if (Config->get_plugins_stop_with_transport() && can_flush_redirects) { @@ -2075,15 +2071,6 @@ int Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick, bool can_record, bool rec_monitors_input) { - { - Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK); - if (lm.locked()) { - // automation snapshot can also be called from the non-rt context - // and it uses the redirect list, so we take the lock out here - automation_snapshot (_session.transport_frame()); - } - } - if ((n_outputs() == 0 && _redirects.empty()) || n_inputs() == 0 || !_active) { silence (nframes, offset); return 0; @@ -2220,16 +2207,6 @@ Route::set_latency_delay (nframes_t longest_session_latency) } } -void -Route::automation_snapshot (nframes_t now) -{ - IO::automation_snapshot (now); - - for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) { - (*i)->automation_snapshot (now); - } -} - Route::ToggleControllable::ToggleControllable (std::string name, Route& s, ToggleType tp) : Controllable (name), route (s), type(tp) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 3bcaaf3aca..8474eab523 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1220,8 +1220,8 @@ Session::maybe_enable_record () { g_atomic_int_set (&_record_status, Enabled); - /* XXX this save should really happen in another thread. its needed so that - pending capture state can be recovered if we crash. + /* this function is currently called from somewhere other than an RT thread. + this save_state() call therefore doesn't impact anything. */ save_state ("", true); @@ -1310,8 +1310,6 @@ Session::set_frame_rate (nframes_t frames_per_second) sync_time_vars(); - Route::set_automation_interval ((nframes_t) ceil ((double) frames_per_second * 0.25)); - // XXX we need some equivalent to this, somehow // DestructiveFileSource::setup_standard_crossfades (frames_per_second); @@ -2472,7 +2470,7 @@ Session::remove_region (boost::shared_ptr region) AudioRegionList::iterator i; boost::shared_ptr ar; bool removed = false; - + { Glib::Mutex::Lock lm (region_lock); @@ -2480,6 +2478,7 @@ Session::remove_region (boost::shared_ptr region) if ((i = audio_regions.find (region->id())) != audio_regions.end()) { audio_regions.erase (i); removed = true; + cerr << "done\n"; } } else { @@ -2642,29 +2641,27 @@ Session::remove_source (boost::weak_ptr src) boost::shared_ptr source = src.lock(); if (!source) { - cerr << "removing a source DEAD\n"; - } else { - cerr << "removing a source " << source->name () << endl; + return; + } + + { + Glib::Mutex::Lock lm (audio_source_lock); - { - Glib::Mutex::Lock lm (audio_source_lock); - - if ((i = audio_sources.find (source->id())) != audio_sources.end()) { - audio_sources.erase (i); - } - } + if ((i = audio_sources.find (source->id())) != audio_sources.end()) { + audio_sources.erase (i); + } + } + + if (!_state_of_the_state & InCleanup) { - if (!_state_of_the_state & InCleanup) { - - /* save state so we don't end up with a session file - referring to non-existent sources. - */ - - save_state (_current_snapshot_name); - } + /* save state so we don't end up with a session file + referring to non-existent sources. + */ - SourceRemoved(source); /* EMIT SIGNAL */ + save_state (_current_snapshot_name); } + + SourceRemoved(source); /* EMIT SIGNAL */ } boost::shared_ptr diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 159f8a8473..c302633918 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -161,7 +161,6 @@ Session::first_stage_init (string fullpath, string snapshot_name) mmc = 0; session_send_mmc = false; session_send_mtc = false; - session_midi_feedback = false; post_transport_work = PostTransportWork (0); g_atomic_int_set (&butler_should_do_transport_work, 0); g_atomic_int_set (&butler_active, 0); diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 1f2dc3215e..678a03ad4e 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -261,11 +261,13 @@ Session::non_realtime_stop (bool abort) struct tm* now; time_t xnow; bool did_record; - + bool saved; + did_record = false; - - boost::shared_ptr dsl = diskstreams.reader(); + saved = false; + boost::shared_ptr dsl = diskstreams.reader(); + for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { if ((*i)->get_captured_frames () != 0) { did_record = true; @@ -291,7 +293,7 @@ Session::non_realtime_stop (bool abort) Location* loc = _locations.end_location(); bool change_end = false; - + if (_transport_frame < loc->end()) { /* stopped recording before current end */ @@ -332,17 +334,17 @@ Session::non_realtime_stop (bool abort) (*i)->set_pending_declick (0); } } - + if (did_record) { commit_reversible_command (); } - + if (_engine.running()) { update_latency_compensation (true, abort); } if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) { - + if (pending_locate_flush) { flush_all_redirects (); } @@ -370,7 +372,7 @@ Session::non_realtime_stop (bool abort) } } } - + deliver_mmc (MIDI::MachineControl::cmdLocate, _transport_frame); #ifdef LEAVE_TRANSPORT_UNADJUSTED @@ -389,7 +391,7 @@ Session::non_realtime_stop (bool abort) when realtime_stop(), which has already executed, will have done this. */ - + if (!Config->get_latched_record_enable()) { g_atomic_int_set (&_record_status, Disabled); } else { @@ -401,6 +403,7 @@ Session::non_realtime_stop (bool abort) if ((post_transport_work & PostTransportLocate) && get_record_enabled()) { /* capture start has been changed, so save pending state */ save_state ("", true); + saved = true; } /* always try to get rid of this */ @@ -409,7 +412,7 @@ Session::non_realtime_stop (bool abort) /* save the current state of things if appropriate */ - if (did_record) { + if (did_record && !saved) { save_state (_current_snapshot_name); } @@ -421,7 +424,7 @@ Session::non_realtime_stop (bool abort) _play_range = false; /* do not turn off autoloop on stop */ - + } PositionChanged (_transport_frame); /* EMIT SIGNAL */ @@ -708,7 +711,7 @@ Session::set_transport_speed (float speed, bool abort) } else { stop_transport (abort); } - + } else if (transport_stopped() && speed == 1.0) { if (!get_record_enabled() && Config->get_stop_at_session_end() && _transport_frame >= current_end_frame()) { @@ -789,7 +792,7 @@ Session::stop_transport (bool abort) if (_transport_speed == 0.0f) { return; } - + if (actively_recording() && !(transport_sub_state & StopPendingCapture) && _worst_output_latency > current_block_size) { @@ -812,9 +815,11 @@ Session::stop_transport (bool abort) return; } + if ((transport_sub_state & PendingDeclickOut) == 0) { transport_sub_state |= PendingDeclickOut; /* we'll be called again after the declick */ + pending_abort = abort; return; } @@ -951,7 +956,7 @@ Session::set_slave_source (SlaveSource src) case None: stop_transport (); break; - + case MTC: if (_mtc_port) { try { diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 340dd1fb08..c30b1af2a4 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -43,14 +43,6 @@ SndFileSource::SndFileSource (Session& s, const XMLNode& node) if (open()) { throw failed_constructor (); } - - if (_build_peakfiles) { - if (initialize_peakfile (false, _path)) { - sf_close (sf); - sf = 0; - throw failed_constructor (); - } - } } SndFileSource::SndFileSource (Session& s, string idstr, Flag flags) @@ -62,14 +54,6 @@ SndFileSource::SndFileSource (Session& s, string idstr, Flag flags) if (open()) { throw failed_constructor (); } - - if (!(_flags & NoPeakFile) && _build_peakfiles) { - if (initialize_peakfile (false, _path)) { - sf_close (sf); - sf = 0; - throw failed_constructor (); - } - } } SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, HeaderFormat hf, nframes_t rate, Flag flags) @@ -79,6 +63,12 @@ SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, Heade init (idstr); + /* this constructor is used to construct new files, not open + existing ones. + */ + + file_is_new = true; + switch (hf) { case CAF: fmt = SF_FORMAT_CAF; @@ -171,14 +161,6 @@ SndFileSource::SndFileSource (Session& s, string idstr, SampleFormat sfmt, Heade } } - - if (!(_flags & NoPeakFile) && _build_peakfiles) { - if (initialize_peakfile (true, _path)) { - sf_close (sf); - sf = 0; - throw failed_constructor (); - } - } } void @@ -413,7 +395,7 @@ SndFileSource::write_unlocked (Sample *data, nframes_t cnt) if (_build_peakfiles) { - queue_for_peaks (this); + queue_for_peaks (shared_from_this ()); } _write_data_count = cnt; diff --git a/libs/ardour/source_factory.cc b/libs/ardour/source_factory.cc index 81a96491ce..7e639590c5 100644 --- a/libs/ardour/source_factory.cc +++ b/libs/ardour/source_factory.cc @@ -18,6 +18,8 @@ $Id$ */ +#include + #include #include #include @@ -31,16 +33,34 @@ using namespace ARDOUR; using namespace std; +using namespace PBD; sigc::signal > SourceFactory::SourceCreated; +int +SourceFactory::setup_peakfile (boost::shared_ptr s) +{ + boost::shared_ptr as (boost::dynamic_pointer_cast (s)); + if (as) { + if (as->setup_peakfile ()) { + error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg; + return -1; + } + } + + return 0; +} + #ifdef HAVE_COREAUDIO boost::shared_ptr SourceFactory::create (Session& s, const XMLNode& node) { if (node.property (X_("destructive")) != 0) { - + boost::shared_ptr ret (new DestructiveFileSource (s, node)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } SourceCreated (ret); return ret; @@ -48,6 +68,9 @@ SourceFactory::create (Session& s, const XMLNode& node) try { boost::shared_ptr ret (new CoreAudioSource (s, node)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } SourceCreated (ret); return ret; } @@ -55,6 +78,9 @@ SourceFactory::create (Session& s, const XMLNode& node) catch (failed_constructor& err) { boost::shared_ptr ret (new SndFileSource (s, node)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } SourceCreated (ret); return ret; } @@ -71,12 +97,18 @@ SourceFactory::create (Session& s, const XMLNode& node) if (node.property (X_("destructive")) != 0) { boost::shared_ptr ret (new DestructiveFileSource (s, node)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } SourceCreated (ret); return ret; } else { boost::shared_ptr ret (new SndFileSource (s, node)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } SourceCreated (ret); return ret; } @@ -90,6 +122,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f { if (flags & Destructive) { boost::shared_ptr ret (new DestructiveFileSource (s, idstr, flags)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } if (announce) { SourceCreated (ret); } @@ -98,6 +133,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f try { boost::shared_ptr ret (new CoreAudioSource (s, idstr, flags)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } if (announce) { SourceCreated (ret); } @@ -106,6 +144,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f catch (failed_constructor& err) { boost::shared_ptr ret (new SndFileSource (s, idstr, flags)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } if (announce) { SourceCreated (ret); } @@ -121,6 +162,9 @@ boost::shared_ptr SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce) { boost::shared_ptr ret (new SndFileSource (s, idstr, flags)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } if (announce) { SourceCreated (ret); } @@ -139,6 +183,9 @@ SourceFactory::createWritable (Session& s, std::string path, bool destructive, n Config->get_native_file_data_format(), Config->get_native_file_header_format(), rate)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } if (announce) { SourceCreated (ret); } @@ -149,6 +196,9 @@ SourceFactory::createWritable (Session& s, std::string path, bool destructive, n Config->get_native_file_data_format(), Config->get_native_file_header_format(), rate)); + if (setup_peakfile (ret)) { + return boost::shared_ptr(); + } if (announce) { SourceCreated (ret); } diff --git a/libs/pbd/pbd/stacktrace.h b/libs/pbd/pbd/stacktrace.h index d7278bd35a..fa90a07355 100644 --- a/libs/pbd/pbd/stacktrace.h +++ b/libs/pbd/pbd/stacktrace.h @@ -4,7 +4,7 @@ #include namespace PBD { - void stacktrace (std::ostream& out); + void stacktrace (std::ostream& out, int levels = 0); } #endif /* __libpbd_stacktrace_h__ */ diff --git a/libs/pbd/stacktrace.cc b/libs/pbd/stacktrace.cc index 1e7dfa08e9..a653fe3033 100644 --- a/libs/pbd/stacktrace.cc +++ b/libs/pbd/stacktrace.cc @@ -9,7 +9,7 @@ #include void -PBD::stacktrace (std::ostream& out) +PBD::stacktrace (std::ostream& out, int levels) { void *array[200]; size_t size; @@ -23,7 +23,7 @@ PBD::stacktrace (std::ostream& out) printf ("Obtained %zd stack frames.\n", size); - for (i = 0; i < size; i++) { + for (i = 0; i < size && (levels == 0 || i < levels); i++) { out << strings[i] << std::endl; } @@ -34,7 +34,7 @@ PBD::stacktrace (std::ostream& out) #else void -PBD::stacktrace (std::ostream& out) +PBD::stacktrace (std::ostream& out, int levels) { out << "stack tracing is not enabled on this platform" << std::endl; } diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 8be652b9df..3635b267ce 100644 --- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -45,6 +45,10 @@ class ControlProtocol : public sigc::trackable, public Stateful, public BasicUI virtual int set_active (bool yn) = 0; bool get_active() const { return _active; } + virtual int set_feedback (bool yn) { return 0; } + virtual bool get_feedback () const { return false; } + virtual bool supports_feedback () const { return false; } + sigc::signal ActiveChanged; /* signals that a control protocol can emit and other (presumably graphical) diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc index a8a5b6eace..8e8f707bab 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc @@ -54,6 +54,7 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s) throw failed_constructor(); } + do_feedback = false; _feedback_interval = 10000; // microseconds last_feedback_time = 0; @@ -82,6 +83,10 @@ GenericMidiControlProtocol::set_feedback_interval (microseconds_t ms) void GenericMidiControlProtocol::send_feedback () { + if (!do_feedback) { + return; + } + microseconds_t now = get_microseconds (); if (last_feedback_time != 0) { @@ -98,7 +103,7 @@ GenericMidiControlProtocol::send_feedback () void GenericMidiControlProtocol::_send_feedback () { - const int32_t bufsize = 16 * 1024; + const int32_t bufsize = 16 * 1024; /* XXX too big */ MIDI::byte buf[bufsize]; int32_t bsize = bufsize; MIDI::byte* end = buf; @@ -174,8 +179,12 @@ XMLNode& GenericMidiControlProtocol::get_state () { XMLNode* node = new XMLNode ("Protocol"); + char buf[32]; node->add_property (X_("name"), _name); + node->add_property (X_("feedback"), do_feedback ? "1" : "0"); + snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval); + node->add_property (X_("feedback_interval"), buf); XMLNode* children = new XMLNode (X_("controls")); @@ -194,6 +203,22 @@ GenericMidiControlProtocol::set_state (const XMLNode& node) { XMLNodeList nlist; XMLNodeConstIterator niter; + const XMLProperty* prop; + + if ((prop = node.property ("feedback")) != 0) { + do_feedback = (bool) atoi (prop->value().c_str()); + } else { + do_feedback = false; + } + + if ((prop = node.property ("feedback_interval")) != 0) { + if (sscanf (prop->value().c_str(), "%" PRIu64, &_feedback_interval) != 1) { + _feedback_interval = 10000; + } + } else { + _feedback_interval = 10000; + } + Controllable* c; { @@ -215,8 +240,6 @@ GenericMidiControlProtocol::set_state (const XMLNode& node) for (niter = nlist.begin(); niter != nlist.end(); ++niter) { - XMLProperty* prop; - if ((prop = (*niter)->property ("id")) != 0) { ID id = prop->value (); @@ -239,3 +262,17 @@ GenericMidiControlProtocol::set_state (const XMLNode& node) return 0; } + +int +GenericMidiControlProtocol::set_feedback (bool yn) +{ + do_feedback = yn; + last_feedback_time = 0; + return 0; +} + +bool +GenericMidiControlProtocol::get_feedback () const +{ + return do_feedback; +} diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index 5f5a470b13..d008744727 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -32,6 +32,10 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { MIDI::Port* port () const { return _port; } void set_feedback_interval (ARDOUR::microseconds_t); + int set_feedback (bool yn); + bool get_feedback () const; + bool supports_feedback () const { return true; } + XMLNode& get_state (); int set_state (const XMLNode&); @@ -40,6 +44,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { ARDOUR::microseconds_t _feedback_interval; ARDOUR::microseconds_t last_feedback_time; + bool do_feedback; void _send_feedback (); void send_feedback (); -- cgit v1.2.3