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<Source> not Source*

git-svn-id: svn://localhost/ardour2/trunk@959 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2006-10-09 15:50:44 +00:00
parent 8011cbf5f8
commit 0d0f71ee92
37 changed files with 287 additions and 292 deletions

View file

@ -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<boost::shared_ptr<ARDOUR::Source> >* deletion_list)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list));
for (list<boost::shared_ptr<Source> >::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) {
(*i)->drop_references ();
}
delete deletion_list;
}
void
ARDOUR_UI::disk_overrun_handler ()
{

View file

@ -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<boost::shared_ptr<ARDOUR::Source> >*);
void editor_display_control_changed (Editing::DisplayControl c);
bool have_disk_overrun_displayed;

View file

@ -128,6 +128,8 @@ AudioStreamView::set_amplitude_above_axis (gdouble app)
void
AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wait_for_waves)
{
AudioRegionView *region_view;
ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::add_region_view), r));
boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (r);
@ -136,10 +138,7 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> r, bool wai
return;
}
AudioRegionView *region_view;
list<RegionView *>::iterator i;
for (i = region_views.begin(); i != region_views.end(); ++i) {
for (list<RegionView *>::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. */
@ -170,15 +169,21 @@ AudioStreamView::add_region_view_internal (boost::shared_ptr<Region> 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<Region> (r)));
RegionViewAdded (region_view);
}
void
AudioStreamView::remove_region_view (boost::shared_ptr<Region> r)
AudioStreamView::remove_region_view (boost::weak_ptr<Region> 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<Region> r (weak_r.lock());
if (!r) {
return;
}
for (list<CrossfadeView *>::iterator i = crossfade_views.begin(); i != crossfade_views.end();) {
list<CrossfadeView*>::iterator tmp;
@ -406,7 +411,7 @@ AudioStreamView::setup_rec_box ()
boost::shared_ptr<AudioFileSource> src = boost::static_pointer_cast<AudioFileSource> (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<Source>(src))));
}
}
@ -420,11 +425,8 @@ AudioStreamView::setup_rec_box ()
boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion>
(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 */
}
/* start a new rec box */
@ -504,12 +506,8 @@ AudioStreamView::setup_rec_box ()
/* remove temp regions */
for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end();) {
list<boost::shared_ptr<Region> >::iterator tmp;
tmp = iter;
++tmp;
for (list<boost::shared_ptr<Region> >::iterator iter = rec_regions.begin(); iter != rec_regions.end(); ++iter) {
(*iter)->drop_references ();
iter = tmp;
}
rec_regions.clear();
@ -537,11 +535,17 @@ AudioStreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void))
}
void
AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::shared_ptr<Source> src)
AudioStreamView::rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr<Source> 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));
ENSURE_GUI_THREAD(bind (mem_fun (*this, &AudioStreamView::rec_peak_range_ready), start, cnt, src));
boost::shared_ptr<Source> src (weak_src.lock());
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;

View file

@ -23,6 +23,8 @@
#include <map>
#include <cmath>
#include <boost/weak_ptr.hpp>
#include <ardour/location.h>
#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<ARDOUR::Source> src);
void rec_peak_range_ready (nframes_t start, nframes_t cnt, boost::weak_ptr<ARDOUR::Source> src);
void update_rec_regions ();
void add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves);
void remove_region_view (boost::shared_ptr<ARDOUR::Region> );
void remove_region_view (boost::weak_ptr<ARDOUR::Region> );
void remove_audio_region_view (boost::shared_ptr<ARDOUR::AudioRegion> );
void remove_audio_rec_region (boost::shared_ptr<ARDOUR::AudioRegion>);
void undisplay_diskstream ();
void redisplay_diskstream ();

View file

@ -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()) {

View file

@ -164,9 +164,11 @@ StreamView::add_region_view (boost::shared_ptr<Region> r)
}
void
StreamView::remove_region_view (boost::shared_ptr<Region> r)
StreamView::remove_region_view (boost::weak_ptr<Region> 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<Region> r (weak_r.lock());
for (list<RegionView *>::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<Region> r)
}
}
#if 0
(unused)
void
StreamView::remove_rec_region (boost::shared_ptr<Region> 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<boost::shared_ptr<Region> >::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) {
if (*i == r) {
rec_regions.erase (i);
break;
}
}
}
#endif
void
StreamView::undisplay_diskstream ()
{

View file

@ -108,7 +108,7 @@ protected:
virtual void update_rec_regions () = 0;
virtual void add_region_view_internal (boost::shared_ptr<ARDOUR::Region>, bool wait_for_waves) = 0;
virtual void remove_region_view (boost::shared_ptr<ARDOUR::Region> );
virtual void remove_region_view (boost::weak_ptr<ARDOUR::Region> );
//void remove_rec_region (boost::shared_ptr<ARDOUR::Region>); (unused)
void display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);

View file

@ -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<void> 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;

View file

@ -189,7 +189,7 @@ class AudioRegion : public Region
void envelope_changed (Change);
void source_offset_changed ();
void source_deleted (boost::shared_ptr<Source>);
void source_deleted ();
SourceList sources;

View file

@ -25,6 +25,9 @@
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <time.h>
#include <glibmm/thread.h>
@ -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<ARDOUR::AudioSource>
{
public:
AudioSource (Session&, string name);
@ -104,6 +107,8 @@ class AudioSource : public Source
_build_peakfiles = yn;
}
virtual int setup_peakfile () { return 0; }
protected:
static bool _build_missing_peakfiles;
static bool _build_peakfiles;
@ -143,10 +148,10 @@ class AudioSource : public Source
};
};
static vector<AudioSource*> pending_peak_sources;
static vector<boost::shared_ptr<AudioSource> > pending_peak_sources;
static Glib::Mutex* pending_peak_sources_lock;
static void queue_for_peaks (AudioSource*);
static void queue_for_peaks (boost::shared_ptr<AudioSource>);
static void clear_queue_for_peaks ();
struct PeakBuildRecord {

View file

@ -147,7 +147,6 @@ class IO;
static sigc::signal<void> DiskOverrun;
static sigc::signal<void> DiskUnderrun;
static sigc::signal<void,std::list<boost::shared_ptr<Source> >*> DeleteSources;
protected:
friend class Session;

View file

@ -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;

View file

@ -234,16 +234,7 @@ public:
AutoStyle gain_automation_style () const { return _gain_automation_curve.automation_style(); }
sigc::signal<void> 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,11 +301,6 @@ 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;
AutoStyle _gain_automation_style;

View file

@ -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);

View file

@ -24,6 +24,9 @@ class SourceFactory {
// MIDI sources will have to be hacked in here somehow
static boost::shared_ptr<Source> createReadable (Session&, std::string idstr, AudioFileSource::Flag flags, bool announce = true);
static boost::shared_ptr<Source> createWritable (Session&, std::string name, bool destructive, nframes_t rate, bool announce = true);
private:
static int setup_peakfile (boost::shared_ptr<Source>);
};
}

View file

@ -1484,30 +1484,22 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
if (abort_capture) {
ChannelList::iterator chan;
if (destructive()) {
goto outout;
}
list<boost::shared_ptr<Source> >* deletion_list = new list<boost::shared_ptr<Source> >;
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->set_allow_remove_if_empty (true);
chan.write_source.reset ();
} else {
chan.write_source.reset ();
}
}
try {

View file

@ -507,15 +507,6 @@ AudioTrack::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame,
nframes_t transport_frame;
boost::shared_ptr<AudioDiskstream> 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;
}

View file

@ -59,8 +59,11 @@ string AudioFileSource::search_path;
sigc::signal<void> 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,6 +123,8 @@ 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;
}
}

View file

@ -75,7 +75,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> 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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs) {
@ -102,7 +102,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<AudioSource> 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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> ((*i));
if (afs) {
@ -159,7 +159,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> 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<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
@ -175,7 +175,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> 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<const AudioRegion> 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<set<boost::shared_ptr<AudioSource> >::iterator,bool> result;
result = unique_srcs.insert (*i);
@ -240,7 +240,7 @@ AudioRegion::AudioRegion (boost::shared_ptr<const AudioRegion> 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<AudioSource> 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<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (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<set<boost::shared_ptr<AudioSource> >::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<AudioRegion*>& v) con
}
void
AudioRegion::source_deleted (boost::shared_ptr<Source> ignored)
AudioRegion::source_deleted ()
{
delete this;
sources.clear ();
drop_references ();
}
vector<string>

View file

@ -44,7 +44,7 @@ using namespace PBD;
pthread_t AudioSource::peak_thread;
bool AudioSource::have_peak_thread = false;
vector<AudioSource*> AudioSource::pending_peak_sources;
vector<boost::shared_ptr<AudioSource> > 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<AudioSource> 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<AudioSource> source)
{
if (have_peak_thread) {
@ -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

View file

@ -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;
}
}

View file

@ -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;

View file

@ -65,7 +65,6 @@ using namespace PBD;
*/
nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
sigc::signal<void,list<boost::shared_ptr<Source> >*> Diskstream::DeleteSources;
sigc::signal<void> Diskstream::DiskOverrun;
sigc::signal<void> Diskstream::DiskUnderrun;

View file

@ -316,23 +316,6 @@ PluginInsert::connect_and_run (vector<Sample*>& bufs, uint32_t nbufs, nframes_t
/* leave remaining channel buffers alone */
}
void
PluginInsert::automation_snapshot (nframes_t now)
{
map<uint32_t,AutomationList*>::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 ();
}
}

View file

@ -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)
{

View file

@ -1373,10 +1373,21 @@ Playlist::set_state (const XMLNode& node)
if (child->name() == "Region") {
#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);

View file

@ -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)
{

View file

@ -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);
@ -2480,6 +2478,7 @@ Session::remove_region (boost::shared_ptr<Region> region)
if ((i = audio_regions.find (region->id())) != audio_regions.end()) {
audio_regions.erase (i);
removed = true;
cerr << "done\n";
}
} else {
@ -2642,9 +2641,8 @@ Session::remove_source (boost::weak_ptr<Source> src)
boost::shared_ptr<Source> 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);
@ -2664,7 +2662,6 @@ Session::remove_source (boost::weak_ptr<Source> src)
}
SourceRemoved(source); /* EMIT SIGNAL */
}
}
boost::shared_ptr<Source>

View file

@ -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);

View file

@ -261,8 +261,10 @@ Session::non_realtime_stop (bool abort)
struct tm* now;
time_t xnow;
bool did_record;
bool saved;
did_record = false;
saved = false;
boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
@ -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);
}
@ -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;
}

View file

@ -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;

View file

@ -18,6 +18,8 @@
$Id$
*/
#include <pbd/error.h>
#include <ardour/source_factory.h>
#include <ardour/sndfilesource.h>
#include <ardour/destructive_filesource.h>
@ -31,9 +33,24 @@
using namespace ARDOUR;
using namespace std;
using namespace PBD;
sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
int
SourceFactory::setup_peakfile (boost::shared_ptr<Source> s)
{
boost::shared_ptr<AudioSource> as (boost::dynamic_pointer_cast<AudioSource> (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<Source>
SourceFactory::create (Session& s, const XMLNode& node)
@ -41,6 +58,9 @@ SourceFactory::create (Session& s, const XMLNode& node)
if (node.property (X_("destructive")) != 0) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
SourceCreated (ret);
return ret;
@ -48,6 +68,9 @@ SourceFactory::create (Session& s, const XMLNode& node)
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
SourceCreated (ret);
return ret;
}
@ -55,6 +78,9 @@ SourceFactory::create (Session& s, const XMLNode& node)
catch (failed_constructor& err) {
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
SourceCreated (ret);
return ret;
}
@ -71,12 +97,18 @@ SourceFactory::create (Session& s, const XMLNode& node)
if (node.property (X_("destructive")) != 0) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, node));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
SourceCreated (ret);
return ret;
} else {
boost::shared_ptr<Source> ret (new SndFileSource (s, node));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
SourceCreated (ret);
return ret;
}
@ -90,6 +122,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
{
if (flags & Destructive) {
boost::shared_ptr<Source> ret (new DestructiveFileSource (s, idstr, flags));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
if (announce) {
SourceCreated (ret);
}
@ -98,6 +133,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
try {
boost::shared_ptr<Source> ret (new CoreAudioSource (s, idstr, flags));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
if (announce) {
SourceCreated (ret);
}
@ -106,6 +144,9 @@ SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag f
catch (failed_constructor& err) {
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
if (announce) {
SourceCreated (ret);
}
@ -121,6 +162,9 @@ boost::shared_ptr<Source>
SourceFactory::createReadable (Session& s, string idstr, AudioFileSource::Flag flags, bool announce)
{
boost::shared_ptr<Source> ret (new SndFileSource (s, idstr, flags));
if (setup_peakfile (ret)) {
return boost::shared_ptr<Source>();
}
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<Source>();
}
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<Source>();
}
if (announce) {
SourceCreated (ret);
}

View file

@ -4,7 +4,7 @@
#include <ostream>
namespace PBD {
void stacktrace (std::ostream& out);
void stacktrace (std::ostream& out, int levels = 0);
}
#endif /* __libpbd_stacktrace_h__ */

View file

@ -9,7 +9,7 @@
#include <stdlib.h>
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;
}

View file

@ -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<void> ActiveChanged;
/* signals that a control protocol can emit and other (presumably graphical)

View file

@ -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;
}

View file

@ -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 ();