summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2006-08-24 07:37:17 +0000
committerDavid Robillard <d@drobilla.net>2006-08-24 07:37:17 +0000
commit25d1670a61d19e795227b939a98be9cf5a050c67 (patch)
treef288677bdbc2a2ff85763e59e5a9f801ca8f8489 /libs
parentea71de278461b2bc0240515b82bb56ef68f5eee3 (diff)
Merged with trunk R846
Removed some overly verbose debug printing git-svn-id: svn://localhost/ardour2/branches/midi@847 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r--libs/ardour/ardour/audio_diskstream.h7
-rw-r--r--libs/ardour/ardour/audio_track.h4
-rw-r--r--libs/ardour/ardour/audioengine.h8
-rw-r--r--libs/ardour/ardour/automation_event.h2
-rw-r--r--libs/ardour/ardour/curve.h2
-rw-r--r--libs/ardour/ardour/diskstream.h21
-rw-r--r--libs/ardour/ardour/location.h1
-rw-r--r--libs/ardour/ardour/midi_diskstream.h4
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h12
-rw-r--r--libs/ardour/ardour/midi_track.h4
-rw-r--r--libs/ardour/ardour/route.h5
-rw-r--r--libs/ardour/ardour/session.h43
-rw-r--r--libs/ardour/ardour/track.h6
-rw-r--r--libs/ardour/audio_diskstream.cc8
-rw-r--r--libs/ardour/audio_track.cc81
-rw-r--r--libs/ardour/audioengine.cc138
-rw-r--r--libs/ardour/auditioner.cc6
-rw-r--r--libs/ardour/automation_event.cc6
-rw-r--r--libs/ardour/curve.cc5
-rw-r--r--libs/ardour/diskstream.cc2
-rw-r--r--libs/ardour/location.cc11
-rw-r--r--libs/ardour/midi_diskstream.cc9
-rw-r--r--libs/ardour/midi_track.cc54
-rw-r--r--libs/ardour/route.cc1
-rw-r--r--libs/ardour/session.cc680
-rw-r--r--libs/ardour/session_butler.cc18
-rw-r--r--libs/ardour/session_command.cc93
-rw-r--r--libs/ardour/session_export.cc5
-rw-r--r--libs/ardour/session_midi.cc1
-rw-r--r--libs/ardour/session_process.cc36
-rw-r--r--libs/ardour/session_state.cc88
-rw-r--r--libs/ardour/session_transport.cc87
-rw-r--r--libs/ardour/smf_source.cc8
-rw-r--r--libs/ardour/track.cc6
-rw-r--r--libs/pbd/id.cc10
-rw-r--r--libs/pbd/pbd/abstract_ui.cc10
-rw-r--r--libs/pbd/pbd/destructible.h20
-rw-r--r--libs/pbd/pbd/id.h8
-rw-r--r--libs/pbd/pbd/memento_command.h82
-rw-r--r--libs/pbd/pbd/rcu.h14
-rw-r--r--libs/pbd/pbd/stateful.h3
-rw-r--r--libs/pbd/pbd/unknown_type.h11
-rw-r--r--libs/pbd/undo.cc8
-rw-r--r--libs/surfaces/control_protocol/basic_ui.cc1
44 files changed, 993 insertions, 636 deletions
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h
index 0cc2079d8e..18f8328cfd 100644
--- a/libs/ardour/ardour/audio_diskstream.h
+++ b/libs/ardour/ardour/audio_diskstream.h
@@ -59,12 +59,10 @@ class AudioDiskstream : public Diskstream
public:
AudioDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
AudioDiskstream (Session &, const XMLNode&);
+ ~AudioDiskstream();
const PBD::ID& id() const { return _id; }
- // FIXME
- AudioDiskstream& ref() { _refcnt++; return *this; }
-
float playback_buffer_load() const;
float capture_buffer_load() const;
@@ -176,9 +174,6 @@ class AudioDiskstream : public Diskstream
private:
- /* use unref() to destroy a diskstream */
- ~AudioDiskstream();
-
struct ChannelInfo {
Sample *playback_wrap_buffer;
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h
index bca79b0d7d..fe6c88cf7f 100644
--- a/libs/ardour/ardour/audio_track.h
+++ b/libs/ardour/ardour/audio_track.h
@@ -46,7 +46,7 @@ class AudioTrack : public Track
int silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframes_t end_frame,
jack_nframes_t offset, bool can_record, bool rec_monitors_input);
- AudioDiskstream& audio_diskstream() const;
+ boost::shared_ptr<AudioDiskstream> audio_diskstream() const;
int use_diskstream (string name);
int use_diskstream (const PBD::ID& id);
@@ -67,7 +67,7 @@ class AudioTrack : public Track
ChanCount n_process_buffers ();
private:
- int set_diskstream (AudioDiskstream&, void *);
+ int set_diskstream (boost::shared_ptr<AudioDiskstream>, void *);
int deprecated_use_diskstream_connections ();
void set_state_part_two ();
void set_state_part_three ();
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 570ad2830d..db814bbb5f 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -31,6 +31,8 @@
#include <glibmm/thread.h>
+#include <pbd/rcu.h>
+
#include <ardour/ardour.h>
#include <jack/jack.h>
#include <jack/transport.h>
@@ -119,6 +121,9 @@ class AudioEngine : public sigc::trackable
uint32_t n_physical_outputs () const;
uint32_t n_physical_inputs () const;
+ void get_physical_outputs (std::vector<std::string>&);
+ void get_physical_inputs (std::vector<std::string>&);
+
std::string get_nth_physical_output (DataType type, uint32_t n) {
return get_nth_physical (type, n, JackPortIsInput);
}
@@ -187,7 +192,6 @@ class AudioEngine : public sigc::trackable
ARDOUR::Session *session;
jack_client_t *_jack;
std::string jack_client_name;
- Glib::Mutex port_lock;
Glib::Mutex _process_lock;
Glib::Mutex session_remove_lock;
Glib::Cond session_removed;
@@ -206,7 +210,7 @@ class AudioEngine : public sigc::trackable
int _usecs_per_cycle;
typedef std::set<Port*> Ports;
- Ports ports;
+ SerializedRCUManager<Ports> ports;
int process_callback (jack_nframes_t nframes);
void remove_all_ports ();
diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
index 5864de73c6..dad94161d0 100644
--- a/libs/ardour/ardour/automation_event.h
+++ b/libs/ardour/ardour/automation_event.h
@@ -183,6 +183,8 @@ class AutomationList : public StateManager, public Stateful
}
};
+ static sigc::signal<void, AutomationList*> AutomationListCreated;
+
protected:
PBD::ID _id;
struct State : public ARDOUR::StateManager::State {
diff --git a/libs/ardour/ardour/curve.h b/libs/ardour/ardour/curve.h
index df632c5171..87893ca260 100644
--- a/libs/ardour/ardour/curve.h
+++ b/libs/ardour/ardour/curve.h
@@ -59,6 +59,8 @@ class Curve : public AutomationList
AutomationEventList::iterator closest_control_point_after (double xval);
void solve ();
+
+ static sigc::signal<void, Curve*> CurveCreated;
protected:
ControlEvent* point_factory (double,double) const;
diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h
index 0803436913..858ed1af6f 100644
--- a/libs/ardour/ardour/diskstream.h
+++ b/libs/ardour/ardour/diskstream.h
@@ -34,6 +34,7 @@
#include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h>
#include <pbd/stateful.h>
+#include <pbd/destructible.h>
#include <ardour/ardour.h>
#include <ardour/configuration.h>
@@ -43,7 +44,6 @@
#include <ardour/port.h>
#include <ardour/utils.h>
-
struct tm;
namespace ARDOUR {
@@ -54,7 +54,7 @@ class Session;
class Playlist;
class IO;
-class Diskstream : public Stateful, public sigc::trackable
+ class Diskstream : public Stateful, public sigc::trackable, public PBD::Destructible
{
public:
enum Flag {
@@ -63,16 +63,16 @@ class Diskstream : public Stateful, public sigc::trackable
Destructive = 0x4
};
+ Diskstream (Session &, const string& name, Flag f = Recordable);
+ Diskstream (Session &, const XMLNode&);
+ virtual ~Diskstream();
+
string name () const { return _name; }
virtual int set_name (string str);
ARDOUR::IO* io() const { return _io; }
void set_io (ARDOUR::IO& io);
- Diskstream& ref() { _refcnt++; return *this; }
- void unref() { if (_refcnt) _refcnt--; if (_refcnt == 0) delete this; }
- uint32_t refcnt() const { return _refcnt; }
-
virtual float playback_buffer_load() const = 0;
virtual float capture_buffer_load() const = 0;
@@ -147,15 +147,11 @@ class Diskstream : public Stateful, public sigc::trackable
static sigc::signal<void> DiskOverrun;
static sigc::signal<void> DiskUnderrun;
- static sigc::signal<void,Diskstream*> DiskstreamCreated; // XXX use a ref with sigc2
static sigc::signal<void,list<Source*>*> DeleteSources;
protected:
friend class Session;
- Diskstream (Session &, const string& name, Flag f = Recordable);
- Diskstream (Session &, const XMLNode&);
-
/* the Session is the only point of access for these because they require
* that the Session is "inactive" while they are called.
*/
@@ -186,9 +182,6 @@ class Diskstream : public Stateful, public sigc::trackable
//private:
- /** Use unref() to destroy a diskstream */
- virtual ~Diskstream();
-
enum TransitionType {
CaptureStart = 0,
CaptureEnd
@@ -303,8 +296,6 @@ class Diskstream : public Stateful, public sigc::trackable
jack_nframes_t scrub_buffer_size;
jack_nframes_t scrub_offset;
- uint32_t _refcnt;
-
sigc::connection ports_created_c;
sigc::connection plmod_connection;
sigc::connection plstate_connection;
diff --git a/libs/ardour/ardour/location.h b/libs/ardour/ardour/location.h
index ff953d1d78..beae4a6e07 100644
--- a/libs/ardour/ardour/location.h
+++ b/libs/ardour/ardour/location.h
@@ -149,6 +149,7 @@ class Locations : public Stateful, public StateManager
XMLNode& get_state (void);
int set_state (const XMLNode&);
PBD::ID id() { return _id; }
+ Location *get_location_by_id(PBD::ID);
Location* auto_loop_location () const;
Location* auto_punch_location () const;
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index 0e4aed1929..bf64cedd08 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -63,6 +63,7 @@ class MidiDiskstream : public Diskstream
public:
MidiDiskstream (Session &, const string& name, Diskstream::Flag f = Recordable);
MidiDiskstream (Session &, const XMLNode&);
+ ~MidiDiskstream();
float playback_buffer_load() const;
float capture_buffer_load() const;
@@ -116,9 +117,6 @@ class MidiDiskstream : public Diskstream
private:
- /* use unref() to destroy a diskstream */
- ~MidiDiskstream();
-
/* The two central butler operations */
int do_flush (Session::RunContext context, bool force = false);
int do_refill ();
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index 662f5a8350..e8b499397d 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -148,9 +148,9 @@ MidiRingBuffer::write (const MidiEvent& ev)
write_ev->buffer = &_raw_buf[raw_index];
g_atomic_int_set(&_write_ptr, (priv_write_ptr + 1) % _size);
- printf("MRB - wrote %xd %d %d with time %u at index %zu (raw index %zu)\n",
- write_ev->buffer[0], write_ev->buffer[1], write_ev->buffer[2], write_ev->time,
- priv_write_ptr, raw_index);
+ //printf("MRB - wrote %xd %d %d with time %u at index %zu (raw index %zu)\n",
+ // write_ev->buffer[0], write_ev->buffer[1], write_ev->buffer[2], write_ev->time,
+ // priv_write_ptr, raw_index);
assert(write_ev->size = ev.size);
@@ -176,9 +176,9 @@ MidiRingBuffer::read(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end)
MidiEvent* const read_ev = &_ev_buf[priv_read_ptr];
if (time >= start) {
dst.push_back(*read_ev);
- printf("MRB - read %#X %d %d with time %u at index %zu\n",
- read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time,
- priv_read_ptr);
+ //printf("MRB - read %#X %d %d with time %u at index %zu\n",
+ // read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time,
+ // priv_read_ptr);
} else {
printf("MRB - SKIPPING - %#X %d %d with time %u at index %zu\n",
read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time,
diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h
index 409aa171e9..7c4befe116 100644
--- a/libs/ardour/ardour/midi_track.h
+++ b/libs/ardour/ardour/midi_track.h
@@ -53,7 +53,7 @@ public:
jack_nframes_t nframes, jack_nframes_t offset, bool with_redirects, int declick,
bool meter);
- MidiDiskstream& midi_diskstream() const;
+ boost::shared_ptr<MidiDiskstream> midi_diskstream() const;
int use_diskstream (string name);
int use_diskstream (const PBD::ID& id);
@@ -79,7 +79,7 @@ protected:
ChanCount n_process_buffers ();
private:
- int set_diskstream (MidiDiskstream&);
+ int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
void set_state_part_two ();
void set_state_part_three ();
diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h
index 107abb7b48..5b9c92dc71 100644
--- a/libs/ardour/ardour/route.h
+++ b/libs/ardour/ardour/route.h
@@ -35,6 +35,7 @@
#include <pbd/undo.h>
#include <pbd/stateful.h>
#include <pbd/controllable.h>
+#include <pbd/destructible.h>
#include <ardour/ardour.h>
#include <ardour/io.h>
@@ -55,7 +56,7 @@ enum mute_type {
MAIN_OUTS = 0x8
};
-class Route : public IO
+ class Route : public IO, public PBD::Destructible
{
protected:
@@ -192,8 +193,6 @@ class Route : public IO
sigc::signal<void> active_changed;
sigc::signal<void,void*> meter_change;
- sigc::signal<void> GoingAway;
-
/* gui's call this for their own purposes. */
sigc::signal<void,std::string,void*> gui_changed;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 2737d86a3f..eeb905a301 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -285,8 +285,9 @@ class Session : public sigc::trackable, public Stateful
BufferSet& get_scratch_buffers (ChanCount count = ChanCount::ZERO);
BufferSet& get_send_buffers (ChanCount count = ChanCount::ZERO);
- Diskstream *diskstream_by_id (const PBD::ID& id);
- Diskstream *diskstream_by_name (string name);
+ void add_diskstream (boost::shared_ptr<Diskstream>);
+ boost::shared_ptr<Diskstream> diskstream_by_id (const PBD::ID& id);
+ boost::shared_ptr<Diskstream> diskstream_by_name (string name);
bool have_captured() const { return _have_captured; }
@@ -296,9 +297,8 @@ class Session : public sigc::trackable, public Stateful
uint32_t get_next_diskstream_id() const { return n_diskstreams(); }
uint32_t n_diskstreams() const;
- typedef list<Diskstream *> DiskstreamList;
-
- typedef std::list<boost::shared_ptr<Route> > RouteList;
+ typedef std::list<boost::shared_ptr<Diskstream> > DiskstreamList;
+ typedef std::list<boost::shared_ptr<Route> > RouteList;
boost::shared_ptr<RouteList> get_routes() const {
return routes.reader ();
@@ -317,6 +317,7 @@ class Session : public sigc::trackable, public Stateful
template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg);
boost::shared_ptr<Route> route_by_name (string);
+ boost::shared_ptr<Route> route_by_id (PBD::ID);
boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
bool route_name_unique (string) const;
@@ -350,7 +351,7 @@ class Session : public sigc::trackable, public Stateful
/* Record status signals */
- sigc::signal<void> RecordStateChanged;
+ sigc::signal<void> RecordStateChanged;
/* Transport mechanism signals */
@@ -359,8 +360,7 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void> DurationChanged;
sigc::signal<void> HaltOnXrun;
- sigc::signal<void,boost::shared_ptr<Route> > RouteAdded;
- sigc::signal<void,Diskstream*> DiskstreamAdded;
+ sigc::signal<void,RouteList&> RouteAdded;
void request_roll ();
void request_bounded_roll (jack_nframes_t start, jack_nframes_t end);
@@ -494,6 +494,7 @@ class Session : public sigc::trackable, public Stateful
int restore_state (string snapshot_name);
int save_template (string template_name);
int save_history (string snapshot_name = "");
+ int restore_history (string snapshot_name);
static int rename_template (string old_name, string new_name);
@@ -551,11 +552,11 @@ class Session : public sigc::trackable, public Stateful
/* fundamental operations. duh. */
- boost::shared_ptr<AudioTrack> new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal);
- boost::shared_ptr<Route> new_audio_route (int input_channels, int output_channels);
+ std::list<boost::shared_ptr<AudioTrack> > new_audio_track (int input_channels, int output_channels, TrackMode mode = Normal, uint32_t how_many = 1);
+ RouteList new_audio_route (int input_channels, int output_channels, uint32_t how_many);
- boost::shared_ptr<MidiTrack> new_midi_track (TrackMode mode = Normal);
- boost::shared_ptr<Route> new_midi_route ();
+ std::list<boost::shared_ptr<MidiTrack> > new_midi_track (TrackMode mode = Normal, uint32_t how_many = 1);
+ //boost::shared_ptr<Route> new_midi_route (uint32_t how_many = 1);
void remove_route (boost::shared_ptr<Route>);
void resort_routes ();
@@ -735,6 +736,10 @@ class Session : public sigc::trackable, public Stateful
sigc::signal<void> NamedSelectionAdded;
sigc::signal<void> NamedSelectionRemoved;
+ /* Curves and AutomationLists (TODO when they go away) */
+ void add_curve(Curve*);
+ void add_automation_list(AutomationList*);
+
/* fade curves */
float get_default_fade_length () const { return default_fade_msecs; }
@@ -861,6 +866,7 @@ class Session : public sigc::trackable, public Stateful
// these commands are implemented in libs/ardour/session_command.cc
Command *memento_command_factory(XMLNode *n);
+ void register_with_memento_command_factory(PBD::ID, Stateful *);
class GlobalSoloStateCommand : public Command
{
GlobalRouteBooleanState before, after;
@@ -1520,17 +1526,16 @@ class Session : public sigc::trackable, public Stateful
/* disk-streams */
- DiskstreamList diskstreams;
- mutable Glib::RWLock diskstream_lock;
+ SerializedRCUManager<DiskstreamList> diskstreams;
+
uint32_t dstream_buffer_size;
- void add_diskstream (Diskstream*);
int load_diskstreams (const XMLNode&);
/* routes stuff */
SerializedRCUManager<RouteList> routes;
- void add_route (boost::shared_ptr<Route>);
+ void add_routes (RouteList&, bool save = true);
uint32_t destructive_index;
int load_routes (const XMLNode&);
@@ -1591,7 +1596,7 @@ class Session : public sigc::trackable, public Stateful
Playlist *XMLPlaylistFactory (const XMLNode&);
void playlist_length_changed (Playlist *);
- void diskstream_playlist_changed (Diskstream *);
+ void diskstream_playlist_changed (boost::shared_ptr<Diskstream>);
/* NAMED SELECTIONS */
@@ -1604,6 +1609,10 @@ class Session : public sigc::trackable, public Stateful
NamedSelection *named_selection_factory (string name);
NamedSelection *XMLNamedSelectionFactory (const XMLNode&);
+ /* CURVES and AUTOMATION LISTS */
+ std::map<PBD::ID, Curve*> curves;
+ std::map<PBD::ID, AutomationList*> automation_lists;
+
/* DEFAULT FADE CURVES */
float default_fade_steepness;
diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h
index 2b317a0299..2e628fa586 100644
--- a/libs/ardour/ardour/track.h
+++ b/libs/ardour/ardour/track.h
@@ -19,6 +19,8 @@
#ifndef __ardour_track_h__
#define __ardour_track_h__
+#include <boost/shared_ptr.hpp>
+
#include <ardour/route.h>
namespace ARDOUR {
@@ -50,7 +52,7 @@ class Track : public Route
bool can_record();
- Diskstream& diskstream() const { return *_diskstream; }
+ boost::shared_ptr<Diskstream> diskstream() const { return _diskstream; }
virtual int use_diskstream (string name) = 0;
virtual int use_diskstream (const PBD::ID& id) = 0;
@@ -97,7 +99,7 @@ class Track : public Route
virtual ChanCount n_process_buffers () = 0;
- Diskstream *_diskstream;
+ boost::shared_ptr<Diskstream> _diskstream;
MeterPoint _saved_meter_point;
TrackMode _mode;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 40c8e3301b..dceaea3f7e 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -72,8 +72,6 @@ AudioDiskstream::AudioDiskstream (Session &sess, const string &name, Diskstream:
use_new_playlist ();
in_set_state = false;
-
- DiskstreamCreated (this); /* EMIT SIGNAL */
}
AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
@@ -93,8 +91,6 @@ AudioDiskstream::AudioDiskstream (Session& sess, const XMLNode& node)
if (destructive()) {
use_destructive_playlist ();
}
-
- DiskstreamCreated (this); /* EMIT SIGNAL */
}
void
@@ -1622,8 +1618,8 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca
}
_playlist->thaw ();
- XMLNode &after = _playlist->get_state();
- _session.add_command (new MementoCommand<Playlist>(*_playlist, before, after));
+ XMLNode &after = _playlist->get_state();
+ _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after));
}
mark_write_completed = true;
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc
index b12b79858e..7a44be9b54 100644
--- a/libs/ardour/audio_track.cc
+++ b/libs/ardour/audio_track.cc
@@ -55,9 +55,10 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
dflags = AudioDiskstream::Flag (dflags | AudioDiskstream::Destructive);
}
- AudioDiskstream* ds = new AudioDiskstream (_session, name, dflags);
-
- set_diskstream (*ds, this);
+ boost::shared_ptr<AudioDiskstream> ds (new AudioDiskstream (_session, name, dflags));
+ _session.add_diskstream (ds);
+
+ set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
}
AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
@@ -73,18 +74,18 @@ AudioTrack::~AudioTrack ()
int
AudioTrack::deprecated_use_diskstream_connections ()
{
- AudioDiskstream& diskstream = audio_diskstream();
+ boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
- if (diskstream.deprecated_io_node == 0) {
+ if (diskstream->deprecated_io_node == 0) {
return 0;
}
const XMLProperty* prop;
- XMLNode& node (*diskstream.deprecated_io_node);
+ XMLNode& node (*diskstream->deprecated_io_node);
/* don't do this more than once. */
- diskstream.deprecated_io_node = 0;
+ diskstream->deprecated_io_node = 0;
set_input_minimum (-1);
set_input_maximum (-1);
@@ -125,17 +126,13 @@ AudioTrack::deprecated_use_diskstream_connections ()
}
int
-AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
+AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
{
- if (_diskstream) {
- _diskstream->unref();
- }
-
- _diskstream = &ds.ref();
+ _diskstream = ds;
_diskstream->set_io (*this);
_diskstream->set_destructive (_mode == Destructive);
- if (audio_diskstream().deprecated_io_node) {
+ if (audio_diskstream()->deprecated_io_node) {
if (!connecting_legal) {
ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
@@ -158,33 +155,33 @@ AudioTrack::set_diskstream (AudioDiskstream& ds, void *src)
int
AudioTrack::use_diskstream (string name)
{
- AudioDiskstream *dstream;
+ boost::shared_ptr<AudioDiskstream> dstream;
- if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_name (name))) == 0) {
- error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
+ if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream>(_session.diskstream_by_name (name))) == 0) {
+ error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
- return set_diskstream (*dstream, this);
+ return set_diskstream (dstream, this);
}
int
AudioTrack::use_diskstream (const PBD::ID& id)
{
- AudioDiskstream *dstream;
+ boost::shared_ptr<AudioDiskstream> dstream;
- if ((dstream = dynamic_cast<AudioDiskstream*>(_session.diskstream_by_id (id))) == 0) {
+ if ((dstream = boost::dynamic_pointer_cast<AudioDiskstream> (_session.diskstream_by_id (id))) == 0) {
error << string_compose(_("AudioTrack: audio diskstream \"%1\" not known by session"), id) << endmsg;
return -1;
}
- return set_diskstream (*dstream, this);
+ return set_diskstream (dstream, this);
}
-AudioDiskstream&
+boost::shared_ptr<AudioDiskstream>
AudioTrack::audio_diskstream() const
{
- return *dynamic_cast<AudioDiskstream*>(_diskstream);
+ return boost::dynamic_pointer_cast<AudioDiskstream>(_diskstream);
}
int
@@ -427,7 +424,7 @@ AudioTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nf
return 0;
}
- audio_diskstream().check_record_status (start_frame, nframes, can_record);
+ audio_diskstream()->check_record_status (start_frame, nframes, can_record);
bool send_silence;
@@ -494,7 +491,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
Sample* b;
Sample* tmpb;
jack_nframes_t transport_frame;
- AudioDiskstream& diskstream = audio_diskstream();
+ boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
{
Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
@@ -521,13 +518,13 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
playback distance to zero, thus causing diskstream::commit
to do nothing.
*/
- return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input);
+ return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
}
_silent = false;
apply_gain_automation = false;
- if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
+ if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
silence (nframes, offset);
@@ -540,7 +537,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
just_meter_input (start_frame, end_frame, nframes, offset);
}
- if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) {
+ if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
/* not actually recording, but we want to hear the input material anyway,
at least potentially (depending on monitoring options)
@@ -548,7 +545,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
passthru (start_frame, end_frame, nframes, offset, 0, true);
- } else if ((b = diskstream.playback_buffer(0)) != 0) {
+ } else if ((b = diskstream->playback_buffer(0)) != 0) {
/*
XXX is it true that the earlier test on n_outputs()
@@ -569,8 +566,8 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
for (i = 0, n = 1; i < limit; ++i, ++n) {
memcpy (bufs.get_audio(i).data(nframes), b, sizeof (Sample) * nframes);
- if (n < diskstream.n_channels().get(DataType::AUDIO)) {
- tmpb = diskstream.playback_buffer(n);
+ if (n < diskstream->n_channels().get(DataType::AUDIO)) {
+ tmpb = diskstream->playback_buffer(n);
if (tmpb!=0) {
b = tmpb;
}
@@ -579,7 +576,7 @@ AudioTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfram
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
- if (!diskstream.record_enabled() && _session.transport_rolling()) {
+ if (!diskstream->record_enabled() && _session.transport_rolling()) {
Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
if (am.locked() && gain_automation_playback()) {
@@ -615,7 +612,7 @@ AudioTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jac
silence (nframes, offset);
- return audio_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
+ return audio_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
}
int
@@ -627,12 +624,12 @@ AudioTrack::export_stuff (BufferSet& buffers, jack_nframes_t start, jack_nframes
RedirectList::iterator i;
bool post_fader_work = false;
gain_t this_gain = _gain;
- AudioDiskstream& diskstream = audio_diskstream();
+ boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
Glib::RWLock::ReaderLock rlock (redirect_lock);
// FIXME
- AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream.playlist());
+ AudioPlaylist* const apl = dynamic_cast<AudioPlaylist*>(diskstream->playlist());
assert(apl);
if (apl->read (buffers.get_audio(nframes).data(nframes),
@@ -646,7 +643,7 @@ AudioTrack::export_stuff (BufferSet& buffers, jack_nframes_t start, jack_nframes
BufferSet::audio_iterator bi = buffers.audio_begin();
++bi;
for ( ; bi != buffers.audio_end(); ++bi, ++n) {
- if (n < diskstream.n_channels().get(DataType::AUDIO)) {
+ if (n < diskstream->n_channels().get(DataType::AUDIO)) {
if (apl->read (bi->data(nframes), mix_buffer, gain_buffer, start, nframes, n) != nframes) {
return -1;
}
@@ -743,9 +740,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
string dir;
AudioRegion* region;
string region_name;
- AudioDiskstream& diskstream = audio_diskstream();
+ boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream();
- if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream.playlist())) == 0) {
+ if ((_freeze_record.playlist = dynamic_cast<AudioPlaylist*>(diskstream->playlist())) == 0) {
return;
}
@@ -813,13 +810,13 @@ AudioTrack::freeze (InterThreadInfo& itt)
(AudioRegion::Flag) (AudioRegion::WholeFile|AudioRegion::DefaultFlags),
false);
- new_playlist->set_orig_diskstream_id (diskstream.id());
+ new_playlist->set_orig_diskstream_id (diskstream->id());
new_playlist->add_region (*region, 0);
new_playlist->set_frozen (true);
region->set_locked (true);
- diskstream.use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
- diskstream.set_record_enabled (false);
+ diskstream->use_playlist (dynamic_cast<AudioPlaylist*>(new_playlist));
+ diskstream->set_record_enabled (false);
_freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */
@@ -829,7 +826,7 @@ void
AudioTrack::unfreeze ()
{
if (_freeze_record.playlist) {
- audio_diskstream().use_playlist (_freeze_record.playlist);
+ audio_diskstream()->use_playlist (_freeze_record.playlist);
if (_freeze_record.have_mementos) {
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index d00b83f53d..15ad6e442c 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -24,6 +24,7 @@
#include <glibmm/timer.h>
#include <pbd/pthread_utils.h>
+#include <pbd/unknown_type.h>
#include <ardour/audioengine.h>
#include <ardour/buffer.h>
@@ -46,6 +47,7 @@ using namespace ARDOUR;
using namespace PBD;
AudioEngine::AudioEngine (string client_name)
+ : ports (new Ports)
{
session = 0;
session_remove_pending = false;
@@ -257,8 +259,10 @@ AudioEngine::process_callback (jack_nframes_t nframes)
return 0;
}
+ boost::shared_ptr<Ports> p = ports.reader();
+
// Prepare ports (ie read data if necessary)
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i)
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i)
(*i)->cycle_start(nframes);
session->process (nframes);
@@ -273,11 +277,14 @@ AudioEngine::process_callback (jack_nframes_t nframes)
}
// Finalize ports (ie write data if necessary)
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i)
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i)
(*i)->cycle_end();
if (last_monitor_check + monitor_check_interval < next_processed_frames) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
Port *port = (*i);
bool x;
@@ -336,7 +343,9 @@ AudioEngine::jack_bufsize_callback (jack_nframes_t nframes)
_usecs_per_cycle = (int) floor ((((double) nframes / frame_rate())) * 1000000.0);
last_monitor_check = 0;
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
(*i)->reset();
}
@@ -407,21 +416,26 @@ AudioEngine::register_input_port (DataType type, const string& portname)
}
}
- jack_port_t *p = jack_port_register (_jack, portname.c_str(),
- type.to_jack_type(), JackPortIsInput, 0);
+ jack_port_t *p = jack_port_register (_jack, portname.c_str(), type.to_jack_type(), JackPortIsInput, 0);
if (p) {
Port* newport = 0;
-
+
if (type == DataType::AUDIO)
newport = new AudioPort (p);
else if (type == DataType::MIDI)
newport = new MidiPort (p);
+ else
+ throw unknown_type();
+
+ if (newport != 0) {
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+ ps->insert (ps->begin(), newport);
+ /* writer goes out of scope, forces update */
+ }
- if (newport)
- ports.insert (ports.begin(), newport);
-
return newport;
} else {
@@ -449,16 +463,23 @@ AudioEngine::register_output_port (DataType type, const string& portname)
if ((p = jack_port_register (_jack, portname.c_str(),
type.to_jack_type(), JackPortIsOutput, 0)) != 0) {
- Port *newport = NULL;
+
+ Port* newport = 0;
if (type == DataType::AUDIO)
newport = new AudioPort (p);
else if (type == DataType::MIDI)
newport = new MidiPort (p);
-
- if (newport)
- ports.insert (ports.begin(), newport);
-
+ else
+ throw unknown_type ();
+
+ if (newport != 0) {
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+ ps->insert (ps->begin(), newport);
+ /* writer goes out of scope, forces update */
+ }
+
return newport;
} else {
@@ -485,18 +506,25 @@ AudioEngine::unregister_port (Port& port)
if (ret == 0) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
- if (*i == &port) {
- ports.erase (i);
- break;
+ {
+
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+
+ for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
+ if ((*i) == &port) {
+ ps->erase (i);
+ break;
+ }
}
+
+ /* writer goes out of scope, forces update */
}
remove_connections_for (port);
}
return ret;
-
}
int
@@ -630,7 +658,9 @@ AudioEngine::get_port_by_name (const string& portname, bool keep)
}
}
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> pr = ports.reader();
+
+ for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) {
if (portname == (*i)->name()) {
return (*i);
}
@@ -709,6 +739,50 @@ AudioEngine::n_physical_inputs () const
return i;
}
+void
+AudioEngine::get_physical_inputs (vector<string>& ins)
+{
+ const char ** ports;
+ uint32_t i = 0;
+
+ if (!_jack) {
+ return;
+ }
+
+ if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsOutput)) == 0) {
+ return;
+ }
+
+ if (ports) {
+ for (i = 0; ports[i]; ++i) {
+ ins.push_back (ports[i]);
+ }
+ free (ports);
+ }
+}
+
+void
+AudioEngine::get_physical_outputs (vector<string>& outs)
+{
+ const char ** ports;
+ uint32_t i = 0;
+
+ if (!_jack) {
+ return;
+ }
+
+ if ((ports = jack_get_ports (_jack, NULL, NULL, JackPortIsPhysical|JackPortIsInput)) == 0) {
+ return;
+ }
+
+ if (ports) {
+ for (i = 0; ports[i]; ++i) {
+ outs.push_back (ports[i]);
+ }
+ free (ports);
+ }
+}
+
string
AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag)
{
@@ -836,12 +910,19 @@ AudioEngine::remove_all_ports ()
/* process lock MUST be held */
if (_jack) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> p = ports.reader();
+
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
jack_port_unregister (_jack, (*i)->_port);
}
}
- ports.clear ();
+ {
+ RCUWriter<Ports> writer (ports);
+ boost::shared_ptr<Ports> ps = writer.get_copy ();
+ ps->clear ();
+ }
+
port_connections.clear ();
}
@@ -941,7 +1022,7 @@ AudioEngine::reconnect_to_jack ()
if (_jack) {
disconnect_from_jack ();
/* XXX give jackd a chance */
- Glib::usleep (250000);
+ Glib::usleep (250000);
}
if (connect_to_jack (jack_client_name)) {
@@ -951,7 +1032,9 @@ AudioEngine::reconnect_to_jack ()
Ports::iterator i;
- for (i = ports.begin(); i != ports.end(); ++i) {
+ boost::shared_ptr<Ports> p = ports.reader ();
+
+ for (i = p->begin(); i != p->end(); ++i) {
/* XXX hack hack hack */
@@ -973,8 +1056,9 @@ AudioEngine::reconnect_to_jack ()
}
}
- if (i != ports.end()) {
- for (Ports::iterator i = ports.begin(); i != ports.end(); ++i) {
+ if (i != p->end()) {
+ /* failed */
+ for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
jack_port_unregister (_jack, (*i)->_port);
}
return -1;
diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc
index af3072d215..3109323acd 100644
--- a/libs/ardour/auditioner.cc
+++ b/libs/ardour/auditioner.cc
@@ -49,7 +49,7 @@ Auditioner::Auditioner (Session& s)
}
if (right.length()) {
- audio_diskstream().add_channel();
+ audio_diskstream()->add_channel();
add_output_port (right, this, DataType::AUDIO);
}
@@ -119,11 +119,11 @@ Auditioner::audition_region (AudioRegion& region)
_diskstream->playlist()->add_region (*the_region, 0, 1, false);
while (_diskstream->n_channels().get(DataType::AUDIO) < the_region->n_channels()) {
- audio_diskstream().add_channel ();
+ audio_diskstream()->add_channel ();
}
while (_diskstream->n_channels().get(DataType::AUDIO) > the_region->n_channels()) {
- audio_diskstream().remove_channel ();
+ audio_diskstream()->remove_channel ();
}
/* force a panner reset now that we have all channels */
diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
index dc1767d1e7..ccfcef28f4 100644
--- a/libs/ardour/automation_event.cc
+++ b/libs/ardour/automation_event.cc
@@ -33,6 +33,8 @@ using namespace ARDOUR;
using namespace sigc;
using namespace PBD;
+sigc::signal<void,AutomationList *> AutomationList::AutomationListCreated;
+
#if 0
static void dumpit (const AutomationList& al, string prefix = "")
{
@@ -64,6 +66,8 @@ AutomationList::AutomationList (double defval, bool with_state)
if (!no_state) {
save_state (_("initial"));
}
+
+ AutomationListCreated(this);
}
AutomationList::AutomationList (const AutomationList& other)
@@ -91,6 +95,7 @@ AutomationList::AutomationList (const AutomationList& other)
}
mark_dirty ();
+ AutomationListCreated(this);
}
AutomationList::AutomationList (const AutomationList& other, double start, double end)
@@ -123,6 +128,7 @@ AutomationList::AutomationList (const AutomationList& other, double start, doubl
delete section;
mark_dirty ();
+ AutomationListCreated(this);
}
AutomationList::~AutomationList()
diff --git a/libs/ardour/curve.cc b/libs/ardour/curve.cc
index b0052c96fb..7d62c5bc94 100644
--- a/libs/ardour/curve.cc
+++ b/libs/ardour/curve.cc
@@ -40,11 +40,14 @@ using namespace ARDOUR;
using namespace sigc;
using namespace PBD;
+sigc::signal<void, Curve*> Curve::CurveCreated;
+
Curve::Curve (double minv, double maxv, double canv, bool nostate)
: AutomationList (canv, nostate)
{
min_yval = minv;
max_yval = maxv;
+ CurveCreated(this);
}
Curve::Curve (const Curve& other)
@@ -52,6 +55,7 @@ Curve::Curve (const Curve& other)
{
min_yval = other.min_yval;
max_yval = other.max_yval;
+ CurveCreated(this);
}
Curve::Curve (const Curve& other, double start, double end)
@@ -59,6 +63,7 @@ Curve::Curve (const Curve& other, double start, double end)
{
min_yval = other.min_yval;
max_yval = other.max_yval;
+ CurveCreated(this);
}
Curve::~Curve ()
diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc
index 22a0b0460e..9a80f3e70f 100644
--- a/libs/ardour/diskstream.cc
+++ b/libs/ardour/diskstream.cc
@@ -63,7 +63,6 @@ using namespace PBD;
*/
jack_nframes_t Diskstream::disk_io_chunk_frames = 1024 * 256;
-sigc::signal<void,Diskstream*> Diskstream::DiskstreamCreated;
sigc::signal<void,list<Source*>*> Diskstream::DeleteSources;
sigc::signal<void> Diskstream::DiskOverrun;
sigc::signal<void> Diskstream::DiskUnderrun;
@@ -86,7 +85,6 @@ Diskstream::Diskstream (Session& sess, const XMLNode& node)
void
Diskstream::init (Flag f)
{
- _refcnt = 0;
_flags = f;
_io = 0;
_alignment_style = ExistingMaterial;
diff --git a/libs/ardour/location.cc b/libs/ardour/location.cc
index 5b5f733138..ca88a2851b 100644
--- a/libs/ardour/location.cc
+++ b/libs/ardour/location.cc
@@ -834,3 +834,14 @@ Locations::num_range_markers () const
}
return cnt;
}
+
+Location *
+Locations::get_location_by_id(PBD::ID id)
+{
+ LocationList::iterator it;
+ for (it = locations.begin(); it != locations.end(); it++)
+ if (id == (*it)->id())
+ return *it;
+
+ return 0;
+}
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index 40b0b11564..e42e455df0 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -80,7 +80,6 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
in_set_state = false;
assert(!destructive());
- DiskstreamCreated (this); /* EMIT SIGNAL */
}
MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
@@ -109,8 +108,6 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
if (destructive()) {
use_destructive_playlist ();
}
-
- DiskstreamCreated (this); /* EMIT SIGNAL */
}
void
@@ -1108,7 +1105,7 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
_playlist->thaw ();
XMLNode &after = _playlist->get_state();
- _session.add_command (new MementoCommand<Playlist>(*_playlist, before, after));
+ _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after));
mark_write_completed = true;
@@ -1526,9 +1523,9 @@ MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes
for (size_t i=0; i < dst.size(); ++i) {
assert(dst[i].time >= start);
assert(dst[i].time <= end);
- cerr << "Translating event stamp " << dst[i].time << " to ";
+ //cerr << "Translating event stamp " << dst[i].time << " to ";
dst[i].time -= start;
- cerr << dst[i].time << endl;
+ //cerr << dst[i].time << endl;
}
}
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 91aad5ea80..aeff92bed3 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -51,18 +51,17 @@ MidiTrack::MidiTrack (Session& sess, string name, Route::Flag flag, TrackMode mo
dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Recordable);
}
- if (mode == Destructive) {
- dflags = MidiDiskstream::Flag (dflags | MidiDiskstream::Destructive);
- }
+ assert(mode != Destructive);
+
+ boost::shared_ptr<MidiDiskstream> ds (new MidiDiskstream (_session, name, dflags));
+ _session.add_diskstream (ds);
- MidiDiskstream* ds = new MidiDiskstream (_session, name, dflags);
+ set_diskstream (boost::dynamic_pointer_cast<MidiDiskstream> (ds));
_declickable = true;
_freeze_record.state = NoFreeze;
_saved_meter_point = _meter_point;
_mode = mode;
-
- set_diskstream (*ds);
}
MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
@@ -76,20 +75,13 @@ MidiTrack::MidiTrack (Session& sess, const XMLNode& node)
MidiTrack::~MidiTrack ()
{
- if (_diskstream) {
- _diskstream->unref();
- }
}
int
-MidiTrack::set_diskstream (MidiDiskstream& ds)
+MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
{
- if (_diskstream) {
- _diskstream->unref();
- }
-
- _diskstream = &ds.ref();
+ _diskstream = ds;
_diskstream->set_io (*this);
_diskstream->set_destructive (_mode == Destructive);
@@ -107,33 +99,33 @@ MidiTrack::set_diskstream (MidiDiskstream& ds)
int
MidiTrack::use_diskstream (string name)
{
- MidiDiskstream *dstream;
+ boost::shared_ptr<MidiDiskstream> dstream;
- if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_name (name))) == 0) {
- error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
+ if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream>(_session.diskstream_by_name (name))) == 0) {
+ error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
- return set_diskstream (*dstream);
+ return set_diskstream (dstream);
}
int
MidiTrack::use_diskstream (const PBD::ID& id)
{
- MidiDiskstream *dstream;
+ boost::shared_ptr<MidiDiskstream> dstream;
- if ((dstream = dynamic_cast<MidiDiskstream*>(_session.diskstream_by_id (id))) == 0) {
+ if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream> (_session.diskstream_by_id (id))) == 0) {
error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), id) << endmsg;
return -1;
}
- return set_diskstream (*dstream);
+ return set_diskstream (dstream);
}
-MidiDiskstream&
+boost::shared_ptr<MidiDiskstream>
MidiTrack::midi_diskstream() const
{
- return *dynamic_cast<MidiDiskstream*>(_diskstream);
+ return boost::dynamic_pointer_cast<MidiDiskstream>(_diskstream);
}
int
@@ -377,7 +369,7 @@ MidiTrack::no_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nfr
return 0;
}
- midi_diskstream().check_record_status (start_frame, nframes, can_record);
+ midi_diskstream()->check_record_status (start_frame, nframes, can_record);
bool send_silence;
@@ -441,7 +433,7 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe
bool can_record, bool rec_monitors_input)
{
int dret;
- MidiDiskstream& diskstream = midi_diskstream();
+ boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
{
Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
@@ -468,12 +460,12 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe
playback distance to zero, thus causing diskstream::commit
to do nothing.
*/
- return diskstream.process (transport_frame, 0, 0, can_record, rec_monitors_input);
+ return diskstream->process (transport_frame, 0, 0, can_record, rec_monitors_input);
}
_silent = false;
- if ((dret = diskstream.process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
+ if ((dret = diskstream->process (transport_frame, nframes, offset, can_record, rec_monitors_input)) != 0) {
silence (nframes, offset);
@@ -486,7 +478,7 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe
just_meter_input (start_frame, end_frame, nframes, offset);
}
- if (diskstream.record_enabled() && !can_record && !_session.get_auto_input()) {
+ if (diskstream->record_enabled() && !can_record && !_session.get_auto_input()) {
/* not actually recording, but we want to hear the input material anyway,
at least potentially (depending on monitoring options)
@@ -509,7 +501,7 @@ MidiTrack::roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack_nframe
//const size_t limit = n_process_buffers().get(DataType::AUDIO);
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
- diskstream.get_playback(bufs.get_midi(0), start_frame, end_frame);
+ diskstream->get_playback(bufs.get_midi(0), start_frame, end_frame);
process_output_buffers (bufs, start_frame, end_frame, nframes, offset,
(!_session.get_record_enabled() || !_session.get_do_not_record_plugins()), declick, (_meter_point != MeterInput));
@@ -537,7 +529,7 @@ MidiTrack::silent_roll (jack_nframes_t nframes, jack_nframes_t start_frame, jack
silence (nframes, offset);
- return midi_diskstream().process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
+ return midi_diskstream()->process (_session.transport_frame() + offset, nframes, offset, can_record, rec_monitors_input);
}
void
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc
index 2ea6c314c1..039f88e2ea 100644
--- a/libs/ardour/route.cc
+++ b/libs/ardour/route.cc
@@ -114,7 +114,6 @@ Route::init ()
Route::~Route ()
{
- GoingAway (); /* EMIT SIGNAL */
clear_redirects (this);
if (_control_outs) {
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index ab8d867414..7d5f838499 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -266,6 +266,7 @@ Session::Session (AudioEngine &eng,
pending_events (2048),
//midi_requests (128), // the size of this should match the midi request pool size
_send_smpte_update (false),
+ diskstreams (new DiskstreamList),
routes (new RouteList),
auditioner ((Auditioner*) 0),
_click_io ((IO*) 0),
@@ -273,7 +274,7 @@ Session::Session (AudioEngine &eng,
{
bool new_session;
- cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << endl;
+ cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
n_physical_outputs = _engine.n_physical_outputs();
n_physical_inputs = _engine.n_physical_inputs();
@@ -320,13 +321,14 @@ Session::Session (AudioEngine &eng,
pending_events (2048),
//midi_requests (16),
_send_smpte_update (false),
+ diskstreams (new DiskstreamList),
routes (new RouteList),
main_outs (0)
{
bool new_session;
- cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << endl;
+ cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl;
n_physical_outputs = max (requested_physical_out, _engine.n_physical_outputs());
n_physical_inputs = max (requested_physical_in, _engine.n_physical_inputs());
@@ -339,13 +341,17 @@ Session::Session (AudioEngine &eng,
if (control_out_channels) {
shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
- add_route (r);
+ RouteList rl;
+ rl.push_back (r);
+ add_routes (rl);
_control_out = r;
}
if (master_out_channels) {
shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
- add_route (r);
+ RouteList rl;
+ rl.push_back (r);
+ add_routes (rl);
_master_out = r;
} else {
/* prohibit auto-connect to master, because there isn't one */
@@ -445,18 +451,43 @@ Session::~Session ()
}
#ifdef TRACK_DESTRUCTION
- cerr << "delete diskstreams\n";
+ cerr << "delete routes\n";
#endif /* TRACK_DESTRUCTION */
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ) {
- DiskstreamList::iterator tmp;
-
- tmp = i;
- ++tmp;
+ {
+ RCUWriter<RouteList> writer (routes);
+ boost::shared_ptr<RouteList> r = writer.get_copy ();
+ for (RouteList::iterator i = r->begin(); i != r->end(); ) {
+ RouteList::iterator tmp;
+ tmp = i;
+ ++tmp;
+ (*i)->drop_references ();
+ i = tmp;
+ }
+ r->clear ();
+ /* writer goes out of scope and updates master */
+ }
- delete *i;
+ routes.flush ();
- i = tmp;
- }
+#ifdef TRACK_DESTRUCTION
+ cerr << "delete diskstreams\n";
+#endif /* TRACK_DESTRUCTION */
+ {
+ RCUWriter<DiskstreamList> dwriter (diskstreams);
+ boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ) {
+ DiskstreamList::iterator tmp;
+
+ tmp = i;
+ ++tmp;
+
+ (*i)->drop_references ();
+
+ i = tmp;
+ }
+ dsl->clear ();
+ }
+ diskstreams.flush ();
#ifdef TRACK_DESTRUCTION
cerr << "delete audio sources\n";
@@ -867,7 +898,7 @@ Session::playlist_length_changed (Playlist* pl)
}
void
-Session::diskstream_playlist_changed (Diskstream* dstream)
+Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
{
Playlist *playlist;
@@ -941,13 +972,10 @@ Session::set_auto_input (bool yn)
if (Config->get_use_hardware_monitoring() && transport_rolling()) {
/* auto-input only makes a difference if we're rolling */
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- /* Even though this can called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@@ -964,16 +992,19 @@ void
Session::reset_input_monitor_state ()
{
if (transport_rolling()) {
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring() && !auto_input);
}
}
} else {
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (Config->get_use_hardware_monitoring());
@@ -1015,7 +1046,6 @@ Session::auto_punch_start_changed (Location* location)
if (get_record_enabled() && get_punch_in()) {
/* capture start has been changed, so save new pending state */
save_state ("", true);
- save_history("");
}
}
@@ -1246,13 +1276,8 @@ Session::enable_record ()
deliver_mmc(MIDI::MachineControl::cmdRecordStrobe, _last_record_location);
if (Config->get_use_hardware_monitoring() && auto_input) {
- /* Even though this can be called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
-
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (true);
}
@@ -1285,13 +1310,9 @@ Session::disable_record (bool rt_context, bool force)
deliver_mmc (MIDI::MachineControl::cmdRecordExit, _transport_frame);
if (Config->get_use_hardware_monitoring() && auto_input) {
- /* Even though this can be called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
(*i)->monitor_input (false);
}
@@ -1312,13 +1333,9 @@ Session::step_back_from_record ()
g_atomic_int_set (&_record_status, Enabled);
if (Config->get_use_hardware_monitoring()) {
- /* Even though this can be called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@@ -1337,7 +1354,6 @@ Session::maybe_enable_record ()
*/
save_state ("", true);
- save_history ("");
if (_transport_speed) {
if (!punch_in) {
@@ -1442,7 +1458,6 @@ Session::set_block_size (jack_nframes_t nframes)
*/
{
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
current_block_size = nframes;
@@ -1461,7 +1476,8 @@ Session::set_block_size (jack_nframes_t nframes)
(*i)->set_block_size (nframes);
}
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_block_size (nframes);
}
@@ -1641,7 +1657,88 @@ Session::resort_routes_using (shared_ptr<RouteList> r)
}
-boost::shared_ptr<MidiTrack>
+list<boost::shared_ptr<MidiTrack> >
+Session::new_midi_track (TrackMode mode, uint32_t how_many)
+{
+ char track_name[32];
+ uint32_t track_id = 0;
+ uint32_t n = 0;
+ uint32_t channels_used = 0;
+ string port;
+ RouteList new_routes;
+ list<boost::shared_ptr<MidiTrack> > ret;
+
+ /* count existing audio tracks */
+
+ {
+ shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if (dynamic_cast<MidiTrack*>((*i).get()) != 0) {
+ if (!(*i)->hidden()) {
+ n++;
+ channels_used += (*i)->n_inputs().get(DataType::MIDI);
+ }
+ }
+ }
+ }
+
+ while (how_many) {
+
+ /* check for duplicate route names, since we might have pre-existing
+ routes with this name (e.g. create Midi1, Midi2, delete Midi1,
+ save, close,restart,add new route - first named route is now
+ Midi2)
+ */
+
+
+ do {
+ ++track_id;
+
+ snprintf (track_name, sizeof(track_name), "Midi %" PRIu32, track_id);
+
+ if (route_by_name (track_name) == 0) {
+ break;
+ }
+
+ } while (track_id < (UINT_MAX-1));
+
+ try {
+ shared_ptr<MidiTrack> track (new MidiTrack (*this, track_name, Route::Flag (0), mode));
+
+ if (track->ensure_io (ChanCount(DataType::MIDI, 1), ChanCount(DataType::MIDI, 1), false, this)) {
+ error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
+ }
+
+ channels_used += track->n_inputs ().get(DataType::MIDI);
+
+ track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
+ track->set_remote_control_id (ntracks());
+
+ new_routes.push_back (track);
+ ret.push_back (track);
+ }
+
+ catch (failed_constructor &err) {
+ error << _("Session: could not create new midi track.") << endmsg;
+ // XXX should we delete the tracks already created?
+ ret.clear ();
+ return ret;
+ }
+
+ --how_many;
+ }
+
+ if (!new_routes.empty()) {
+ add_routes (new_routes, false);
+ save_state (_current_snapshot_name);
+ }
+
+ return ret;
+}
+
+#if 0
+std::list<boost::shared_ptr<MidiTrack> >
Session::new_midi_track (TrackMode mode)
{
char track_name[32];
@@ -1686,50 +1783,7 @@ Session::new_midi_track (TrackMode mode)
error << string_compose (_("cannot configure %1 in/%2 out configuration for new midi track"), track_name)
<< endmsg;
}
-#if 0
- if (nphysical_in) {
- for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) {
-
- port = "";
-
- if (input_auto_connect & AutoConnectPhysical) {
- port = _engine.get_nth_physical_input ((channels_used+x)%nphysical_in);
- }
-
- if (port.length() && track->connect_input (track->input (x), port, this)) {
- break;
- }
- }
- }
-
- for (uint32_t x = 0; x < track->n_outputs(); ++x) {
-
- port = "";
-
- if (nphysical_out && (output_auto_connect & AutoConnectPhysical)) {
- port = _engine.get_nth_physical_output ((channels_used+x)%nphysical_out);
- } else if (output_auto_connect & AutoConnectMaster) {
- if (_master_out) {
- port = _master_out->input (x%_master_out->n_inputs())->name();
- }
- }
-
- if (port.length() && track->connect_output (track->output (x), port, this)) {
- break;
- }
- }
-
- if (_control_out) {
- vector<string> cports;
- uint32_t ni = _control_out->n_inputs();
- for (n = 0; n < ni; ++n) {
- cports.push_back (_control_out->input(n)->name());
- }
-
- track->set_control_outs (cports);
- }
-#endif
track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
add_route (track);
@@ -1744,7 +1798,6 @@ Session::new_midi_track (TrackMode mode)
}
}
-
boost::shared_ptr<Route>
Session::new_midi_route ()
{
@@ -1832,17 +1885,18 @@ Session::new_midi_route ()
return shared_ptr<Route> ((Route*) 0);
}
}
+#endif
-
-shared_ptr<AudioTrack>
-Session::new_audio_track (int input_channels, int output_channels, TrackMode mode)
+list<boost::shared_ptr<AudioTrack> >
+Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many)
{
char track_name[32];
+ uint32_t track_id = 0;
uint32_t n = 0;
uint32_t channels_used = 0;
string port;
- uint32_t nphysical_in;
- uint32_t nphysical_out;
+ RouteList new_routes;
+ list<boost::shared_ptr<AudioTrack> > ret;
/* count existing audio tracks */
@@ -1859,105 +1913,133 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
}
}
- /* check for duplicate route names, since we might have pre-existing
- routes with this name (e.g. create Audio1, Audio2, delete Audio1,
- save, close,restart,add new route - first named route is now
- Audio2)
- */
+ vector<string> physinputs;
+ vector<string> physoutputs;
+ uint32_t nphysical_in;
+ uint32_t nphysical_out;
- do {
- snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, n+1);
- if (route_by_name (track_name) == 0) {
- break;
- }
- n++;
+ _engine.get_physical_outputs (physoutputs);
+ _engine.get_physical_inputs (physinputs);
- } while (n < (UINT_MAX-1));
+ while (how_many) {
- if (input_auto_connect & AutoConnectPhysical) {
- nphysical_in = n_physical_inputs;
- } else {
- nphysical_in = 0;
- }
+ /* check for duplicate route names, since we might have pre-existing
+ routes with this name (e.g. create Audio1, Audio2, delete Audio1,
+ save, close,restart,add new route - first named route is now
+ Audio2)
+ */
+
- if (output_auto_connect & AutoConnectPhysical) {
- nphysical_out = n_physical_outputs;
- } else {
- nphysical_out = 0;
- }
+ do {
+ ++track_id;
- try {
- shared_ptr<AudioTrack> track (new AudioTrack (*this, track_name, Route::Flag (0), mode));
+ snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, track_id);
- if (track->ensure_io (input_channels, output_channels, false, this)) {
- error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
- input_channels, output_channels)
- << endmsg;
- }
+ if (route_by_name (track_name) == 0) {
+ break;
+ }
+
+ } while (track_id < (UINT_MAX-1));
- if (nphysical_in) {
- for (uint32_t x = 0; x < track->n_inputs().get(DataType::AUDIO) && x < nphysical_in; ++x) {
+ if (input_auto_connect & AutoConnectPhysical) {
+ nphysical_in = min (n_physical_inputs, (uint32_t) physinputs.size());
+ } else {
+ nphysical_in = 0;
+ }
+
+ if (output_auto_connect & AutoConnectPhysical) {
+ nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size());
+ } else {
+ nphysical_out = 0;
+ }
+
+ try {
+ shared_ptr<AudioTrack> track (new AudioTrack (*this, track_name, Route::Flag (0), mode));
+
+ if (track->ensure_io (input_channels, output_channels, false, this)) {
+ error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ }
+
+ if (nphysical_in) {
+ for (uint32_t x = 0; x < track->n_inputs().get(DataType::AUDIO) && x < nphysical_in; ++x) {
+
+ port = "";
+
+ if (input_auto_connect & AutoConnectPhysical) {
+ port = physinputs[(channels_used+x)%nphysical_in];
+ }
+
+ if (port.length() && track->connect_input (track->input (x), port, this)) {
+ break;
+ }
+ }
+ }
+
+ for (uint32_t x = 0; x < track->n_outputs().get(DataType::MIDI); ++x) {
port = "";
- if (input_auto_connect & AutoConnectPhysical) {
- port = _engine.get_nth_physical_input (DataType::AUDIO, (channels_used+x)%nphysical_in);
- }
+ if (nphysical_out && (output_auto_connect & AutoConnectPhysical)) {
+ port = physoutputs[(channels_used+x)%nphysical_out];
+ } else if (output_auto_connect & AutoConnectMaster) {
+ if (_master_out) {
+ port = _master_out->input (x%_master_out->n_inputs().get(DataType::AUDIO))->name();
+ }
+ }
- if (port.length() && track->connect_input (track->input (x), port, this)) {
+ if (port.length() && track->connect_output (track->output (x), port, this)) {
break;
}
}
- }
-
- for (uint32_t x = 0; x < track->n_outputs().get(DataType::AUDIO); ++x) {
- port = "";
+ channels_used += track->n_inputs ().get(DataType::AUDIO);
- if (nphysical_out && (output_auto_connect & AutoConnectPhysical)) {
- port = _engine.get_nth_physical_output (DataType::AUDIO, (channels_used+x)%nphysical_out);
- } else if (output_auto_connect & AutoConnectMaster) {
- if (_master_out) {
- port = _master_out->audio_input (x%_master_out->n_inputs().get(DataType::AUDIO))->name();
+ if (_control_out) {
+ vector<string> cports;
+ uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO);
+
+ for (n = 0; n < ni; ++n) {
+ cports.push_back (_control_out->input(n)->name());
}
+
+ track->set_control_outs (cports);
}
+
+ track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
+ track->set_remote_control_id (ntracks());
- if (port.length() && track->connect_output (track->output (x), port, this)) {
- break;
- }
+ new_routes.push_back (track);
+ ret.push_back (track);
}
- if (_control_out) {
- vector<string> cports;
- uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO);
-
- for (n = 0; n < ni; ++n) {
- cports.push_back (_control_out->audio_input(n)->name());
- }
-
- track->set_control_outs (cports);
+ catch (failed_constructor &err) {
+ error << _("Session: could not create new audio track.") << endmsg;
+ // XXX should we delete the tracks already created?
+ ret.clear ();
+ return ret;
}
-
- track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
-
- add_route (track);
-
- track->set_remote_control_id (ntracks());
- return track;
+
+ --how_many;
}
- catch (failed_constructor &err) {
- error << _("Session: could not create new audio track.") << endmsg;
- return shared_ptr<AudioTrack> ((AudioTrack*) 0);
+ if (!new_routes.empty()) {
+ add_routes (new_routes, false);
+ save_state (_current_snapshot_name);
}
+
+ return ret;
}
-shared_ptr<Route>
-Session::new_audio_route (int input_channels, int output_channels)
+Session::RouteList
+Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
{
char bus_name[32];
+ uint32_t bus_id = 1;
uint32_t n = 0;
string port;
+ RouteList ret;
/* count existing audio busses */
@@ -1967,127 +2049,148 @@ Session::new_audio_route (int input_channels, int output_channels)
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
if (!(*i)->hidden()) {
- n++;
+ bus_id++;
}
}
}
}
- do {
- snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, n+1);
- if (route_by_name (bus_name) == 0) {
- break;
- }
- n++;
+ vector<string> physinputs;
+ vector<string> physoutputs;
- } while (n < (UINT_MAX-1));
+ _engine.get_physical_outputs (physoutputs);
+ _engine.get_physical_inputs (physinputs);
- try {
- shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
+ while (how_many) {
- if (bus->ensure_io (input_channels, output_channels, false, this)) {
- error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
- input_channels, output_channels)
- << endmsg;
- }
+ do {
+ ++bus_id;
- for (uint32_t x = 0; x < bus->n_inputs().get(DataType::AUDIO); ++x) {
-
- port = "";
+ snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id);
- if (input_auto_connect & AutoConnectPhysical) {
- port = _engine.get_nth_physical_input (DataType::AUDIO, (n+x)%n_physical_inputs);
- }
-
- if (port.length() && bus->connect_input (bus->input (x), port, this)) {
+ if (route_by_name (bus_name) == 0) {
break;
}
- }
- for (uint32_t x = 0; x < bus->n_outputs().get(DataType::AUDIO); ++x) {
-
- port = "";
+ } while (bus_id < (UINT_MAX-1));
- if (output_auto_connect & AutoConnectPhysical) {
- port = _engine.get_nth_physical_input (DataType::AUDIO, (n+x)%n_physical_outputs);
- } else if (output_auto_connect & AutoConnectMaster) {
- if (_master_out) {
- port = _master_out->audio_input (x%_master_out->n_inputs().get(DataType::AUDIO))->name();
+ try {
+ shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
+
+ if (bus->ensure_io (input_channels, output_channels, false, this)) {
+ error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
+ input_channels, output_channels)
+ << endmsg;
+ }
+
+ for (uint32_t x = 0; x < bus->n_inputs().get(DataType::AUDIO); ++x) {
+
+ port = "";
+
+ if (input_auto_connect & AutoConnectPhysical) {
+ port = physinputs[((n+x)%n_physical_inputs)];
+ }
+
+ if (port.length() && bus->connect_input (bus->input (x), port, this)) {
+ break;
}
}
-
- if (port.length() && bus->connect_output (bus->output (x), port, this)) {
- break;
+
+ for (uint32_t x = 0; x < bus->n_outputs().get(DataType::AUDIO); ++x) {
+
+ port = "";
+
+ if (output_auto_connect & AutoConnectPhysical) {
+ port = physoutputs[((n+x)%n_physical_outputs)];
+ } else if (output_auto_connect & AutoConnectMaster) {
+ if (_master_out) {
+ port = _master_out->input (x%_master_out->n_inputs().get(DataType::AUDIO))->name();
+ }
+ }
+
+ if (port.length() && bus->connect_output (bus->output (x), port, this)) {
+ break;
+ }
+ }
+
+ if (_control_out) {
+ vector<string> cports;
+ uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO);
+
+ for (uint32_t n = 0; n < ni; ++n) {
+ cports.push_back (_control_out->input(n)->name());
+ }
+ bus->set_control_outs (cports);
}
- }
- if (_control_out) {
- vector<string> cports;
- uint32_t ni = _control_out->n_inputs().get(DataType::AUDIO);
+ ret.push_back (bus);
+ }
+
- for (uint32_t n = 0; n < ni; ++n) {
- cports.push_back (_control_out->input(n)->name());
- }
- bus->set_control_outs (cports);
+ catch (failed_constructor &err) {
+ error << _("Session: could not create new audio route.") << endmsg;
+ ret.clear ();
+ return ret;
}
-
- add_route (bus);
- return bus;
+
+ --how_many;
}
- catch (failed_constructor &err) {
- error << _("Session: could not create new audio route.") << endmsg;
- return shared_ptr<Route> ((Route*) 0);
+ if (!ret.empty()) {
+ add_routes (ret, false);
+ save_state (_current_snapshot_name);
}
+
+ return ret;
+
}
void
-Session::add_route (shared_ptr<Route> route)
+Session::add_routes (RouteList& new_routes, bool save)
{
{
RCUWriter<RouteList> writer (routes);
shared_ptr<RouteList> r = writer.get_copy ();
- r->push_front (route);
+ r->insert (r->end(), new_routes.begin(), new_routes.end());
resort_routes_using (r);
}
- route->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), route));
- route->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
- route->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
- route->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
-
- if (route->master()) {
- _master_out = route;
- }
-
- if (route->control()) {
- _control_out = route;
+ for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
+ (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), (*x)));
+ (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
+ (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
+ (*x)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
+
+ if ((*x)->master()) {
+ _master_out = (*x);
+ }
+
+ if ((*x)->control()) {
+ _control_out = (*x);
+ }
}
set_dirty();
- save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
- RouteAdded (route); /* EMIT SIGNAL */
+ if (save) {
+ save_state (_current_snapshot_name);
+ }
+
+ RouteAdded (new_routes); /* EMIT SIGNAL */
}
void
-Session::add_diskstream (Diskstream* dstream)
+Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
{
/* need to do this in case we're rolling at the time, to prevent false underruns */
dstream->do_refill_with_alloc();
{
- Glib::RWLock::WriterLock lm (diskstream_lock);
- diskstreams.push_back (dstream);
+ RCUWriter<DiskstreamList> writer (diskstreams);
+ boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
+ ds->push_back (dstream);
}
- /* take a reference to the diskstream, preventing it from
- ever being deleted until the session itself goes away,
- or chooses to remove it for its own purposes.
- */
-
- dstream->ref();
dstream->set_block_size (current_block_size);
dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
@@ -2095,12 +2198,6 @@ Session::add_diskstream (Diskstream* dstream)
diskstream_playlist_changed (dstream);
dstream->prepare ();
-
- set_dirty();
- save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
-
- DiskstreamAdded (dstream); /* EMIT SIGNAL */
}
void
@@ -2138,20 +2235,19 @@ Session::remove_route (shared_ptr<Route> route)
}
Track* t;
- Diskstream* ds = 0;
+ boost::shared_ptr<Diskstream> ds;
if ((t = dynamic_cast<Track*>(route.get())) != 0) {
- ds = &t->diskstream();
+ ds = t->diskstream();
}
if (ds) {
{
- Glib::RWLock::WriterLock lm (diskstream_lock);
- diskstreams.remove (ds);
+ RCUWriter<DiskstreamList> dsl (diskstreams);
+ boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
+ d->remove (ds);
}
-
- ds->unref ();
}
find_current_end ();
@@ -2162,9 +2258,10 @@ Session::remove_route (shared_ptr<Route> route)
/* XXX should we disconnect from the Route's signals ? */
save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
- /* all shared ptrs to route should go out of scope here */
+ /* try to cause everyone to drop their references */
+
+ route->drop_references ();
}
void
@@ -2403,6 +2500,20 @@ Session::route_by_name (string name)
}
shared_ptr<Route>
+Session::route_by_id (PBD::ID id)
+{
+ shared_ptr<RouteList> r = routes.reader ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ if ((*i)->id() == id) {
+ return *i;
+ }
+ }
+
+ return shared_ptr<Route> ((Route*) 0);
+}
+
+shared_ptr<Route>
Session::route_by_remote_id (uint32_t id)
{
shared_ptr<RouteList> r = routes.reader ();
@@ -2438,11 +2549,9 @@ Session::get_maximum_extent () const
jack_nframes_t max = 0;
jack_nframes_t me;
- /* Don't take the diskstream lock. Caller must have other ways to
- ensure atomicity.
- */
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
Playlist* pl = (*i)->playlist();
if ((me = pl->get_maximum_extent()) > max) {
max = me;
@@ -2452,32 +2561,32 @@ Session::get_maximum_extent () const
return max;
}
-Diskstream *
+boost::shared_ptr<Diskstream>
Session::diskstream_by_name (string name)
{
- Glib::RWLock::ReaderLock lm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->name() == name) {
- return* i;
+ return *i;
}
}
- return 0;
+ return boost::shared_ptr<Diskstream>((Diskstream*) 0);
}
-Diskstream *
+boost::shared_ptr<Diskstream>
Session::diskstream_by_id (const PBD::ID& id)
{
- Glib::RWLock::ReaderLock lm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->id() == id) {
return *i;
}
}
- return 0;
+ return boost::shared_ptr<Diskstream>((Diskstream*) 0);
}
/* Region management */
@@ -2767,10 +2876,10 @@ int
Session::remove_last_capture ()
{
list<Region*> r;
-
- Glib::RWLock::ReaderLock lm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
list<Region*>& l = (*i)->last_capture_regions();
if (!l.empty()) {
@@ -2829,7 +2938,6 @@ Session::remove_source (Source* source)
*/
save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
}
SourceRemoved(source); /* EMIT SIGNAL */
@@ -3404,10 +3512,11 @@ Session::set_all_mute (bool yn)
uint32_t
Session::n_diskstreams () const
{
- Glib::RWLock::ReaderLock lm (diskstream_lock);
uint32_t n = 0;
- for (DiskstreamList::const_iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
n++;
}
@@ -3426,15 +3535,15 @@ Session::graph_reordered ()
return;
}
- Glib::RWLock::ReaderLock lm2 (diskstream_lock);
-
resort_routes ();
/* force all diskstreams to update their capture offset values to
reflect any changes in latencies within the graph.
*/
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_capture_offset ();
}
}
@@ -3691,11 +3800,9 @@ Session::remove_named_selection (NamedSelection* named_selection)
void
Session::reset_native_file_format ()
{
- // jlc - WHY take routelock?
- //RWLockMonitor lm1 (route_lock, true, __LINE__, __FILE__);
- Glib::RWLock::ReaderLock lm2 (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->reset_write_sources (false);
}
}
@@ -3792,7 +3899,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
uint32_t x;
char buf[PATH_MAX+1];
string dir;
- ChanCount nchans(track.audio_diskstream().n_channels());
+ ChanCount nchans(track.audio_diskstream()->n_channels());
jack_nframes_t position;
jack_nframes_t this_chunk;
jack_nframes_t to_do;
@@ -3805,7 +3912,7 @@ Session::write_one_audio_track (AudioTrack& track, jack_nframes_t start, jack_nf
/* call tree *MUST* hold route_lock */
- if ((playlist = track.diskstream().playlist()) == 0) {
+ if ((playlist = track.diskstream()->playlist()) == 0) {
goto out;
}
@@ -4007,3 +4114,14 @@ Session::set_xfade_model (CrossfadeModel xm)
}
}
+void
+Session::add_curve(Curve *curve)
+{
+ curves[curve->id()] = curve;
+}
+
+void
+Session::add_automation_list(AutomationList *al)
+{
+ automation_lists[al->id()] = al;
+}
diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc
index 6509a783bb..5d691a7425 100644
--- a/libs/ardour/session_butler.cc
+++ b/libs/ardour/session_butler.cc
@@ -248,11 +248,11 @@ Session::butler_thread_work ()
gettimeofday (&begin, 0);
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader ();
- for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
+ for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
- Diskstream* const ds = *i;
+ boost::shared_ptr<Diskstream> ds = *i;
switch (ds->do_refill ()) {
case 0:
@@ -271,7 +271,7 @@ Session::butler_thread_work ()
}
- if (i != diskstreams.end()) {
+ if (i != dsl->end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
@@ -293,7 +293,7 @@ Session::butler_thread_work ()
compute_io = true;
gettimeofday (&begin, 0);
- for (i = diskstreams.begin(); !transport_work_requested() && butler_should_run && i != diskstreams.end(); ++i) {
+ for (i = dsl->begin(); !transport_work_requested() && butler_should_run && i != dsl->end(); ++i) {
// cerr << "write behind for " << (*i)->name () << endl;
switch ((*i)->do_flush (Session::ButlerContext)) {
@@ -322,7 +322,7 @@ Session::butler_thread_work ()
request_stop ();
}
- if (i != diskstreams.end()) {
+ if (i != dsl->end()) {
/* we didn't get to all the streams */
disk_work_outstanding = true;
}
@@ -349,7 +349,7 @@ Session::butler_thread_work ()
Glib::Mutex::Lock lm (butler_request_lock);
if (butler_should_run && (disk_work_outstanding || transport_work_requested())) {
-// for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+// for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
// cerr << "AFTER " << (*i)->name() << ": pb = " << (*i)->playback_buffer_load() << " cp = " << (*i)->capture_buffer_load() << endl;
// }
@@ -388,8 +388,8 @@ Session::overwrite_some_buffers (Diskstream* ds)
} else {
- Glib::RWLock::ReaderLock dm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_pending_overwrite (true);
}
}
diff --git a/libs/ardour/session_command.cc b/libs/ardour/session_command.cc
index af507208ab..4e7c4151b7 100644
--- a/libs/ardour/session_command.cc
+++ b/libs/ardour/session_command.cc
@@ -2,24 +2,99 @@
#include <ardour/route.h>
#include <pbd/memento_command.h>
#include <ardour/diskstream.h>
+#include <ardour/playlist.h>
+#include <ardour/tempo.h>
+#include <ardour/audiosource.h>
+#include <ardour/audioregion.h>
+#include <pbd/error.h>
+using namespace PBD;
+#include "i18n.h"
+
namespace ARDOUR {
+static map<PBD::ID, Stateful*> registry;
+
+void Session::register_with_memento_command_factory(PBD::ID id, Stateful *ptr)
+{
+ registry[id] = ptr;
+}
+
Command *Session::memento_command_factory(XMLNode *n)
{
PBD::ID id;
- XMLNode *before, *after;
+ XMLNode *before = 0, *after = 0;
+ XMLNode *child;
+
+ /* get id */
+ id = PBD::ID(n->property("obj_id")->value());
+
+ /* get before/after */
+ if (n->name() == "MementoCommand")
+ {
+ before = new XMLNode(*n->children().front());
+ after = new XMLNode(*n->children().back());
+ child = before;
+ } else if (n->name() == "MementoUndoCommand")
+ {
+ before = new XMLNode(*n->children().front());
+ child = before;
+ }
+ else if (n->name() == "MementoRedoCommand")
+ {
+ after = new XMLNode(*n->children().front());
+ child = after;
+ }
+
+ if (!child)
+ {
+ error << _("Tried to reconstitute a MementoCommand with no contents, failing. id=") << id.to_s() << endmsg;
+ return 0;
+ }
- /* get obj_id */
- /* get before and/or after */
+ /* create command */
+ string obj_T = n->children().front()->name();
+ if (obj_T == "AudioRegion" || obj_T == "MidiRegion" || obj_T == "Region")
+ {
+ if (regions.count(id))
+ return new MementoCommand<Region>(*regions[id], before, after);
+ }
+ else if (obj_T == "Source" || obj_T == "AudioSource" || obj_T == "MidiSource")
+ {
+ if (sources.count(id))
+ return new MementoCommand<Source>(*sources[id], before, after);
+ }
+ else if (obj_T == "Location")
+ return new MementoCommand<Location>(*_locations.get_location_by_id(id), before, after);
+ else if (obj_T == "Locations")
+ return new MementoCommand<Locations>(_locations, before, after);
+ else if (obj_T == "TempoMap")
+ return new MementoCommand<TempoMap>(*_tempo_map, before, after);
+ else if (obj_T == "Playlist" || obj_T == "MidiPlaylist" || obj_T == "AudioPlaylist")
+ {
+ if (Playlist *pl = playlist_by_name(child->property("name")->value()))
+ return new MementoCommand<Playlist>(*pl, before, after);
+ }
+ else if (obj_T == "Route") // inlcudes AudioTrack
+ return new MementoCommand<Route>(*route_by_id(id), before, after);
+ else if (obj_T == "Curve")
+ {
+ if (curves.count(id))
+ return new MementoCommand<Curve>(*curves[id], before, after);
+ }
+ else if (obj_T == "AutomationList")
+ {
+ if (automation_lists.count(id))
+ return new MementoCommand<AutomationList>(*automation_lists[id], before, after);
+ }
+ // For Editor and AutomationLine which are off-limits here
+ else if (registry.count(id))
+ return new MementoCommand<Stateful>(*registry[id], before, after);
- /* get an object by id by trial and error, and use it to construct an
- * appropriate memento command */
- // e.g.
- if (Diskstream *obj = diskstream_by_id(id))
- return new MementoCommand<Diskstream>(*obj, *before, *after);
- // etc.
+ /* we failed */
+ error << _("could not reconstitute MementoCommand from XMLNode. id=") << id.to_s() << endmsg;
+ return 0;
return 0;
}
diff --git a/libs/ardour/session_export.cc b/libs/ardour/session_export.cc
index c5449d3e06..946d825c1c 100644
--- a/libs/ardour/session_export.cc
+++ b/libs/ardour/session_export.cc
@@ -496,8 +496,9 @@ Session::prepare_to_export (AudioExportSpecification& spec)
/* get everyone to the right position */
{
- Glib::RWLock::ReaderLock lm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)-> seek (spec.start_frame, true)) {
error << string_compose (_("%1: cannot seek to %2 for export"),
(*i)->name(), spec.start_frame)
diff --git a/libs/ardour/session_midi.cc b/libs/ardour/session_midi.cc
index b0738e95a7..d7cdd94b2b 100644
--- a/libs/ardour/session_midi.cc
+++ b/libs/ardour/session_midi.cc
@@ -605,7 +605,6 @@ Session::mmc_record_strobe (MIDI::MachineControl &mmc)
*/
save_state ("", true);
- save_history ("");
g_atomic_int_set (&_record_status, Enabled);
RecordStateChanged (); /* EMIT SIGNAL */
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 6d13caced8..e99478e0b4 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -72,7 +72,8 @@ Session::process (jack_nframes_t nframes)
void
Session::prepare_diskstreams ()
{
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->prepare ();
}
}
@@ -150,7 +151,8 @@ Session::process_routes (jack_nframes_t nframes, jack_nframes_t offset)
call path, so make sure we release any outstanding locks here before we return failure.
*/
- for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
(*ids)->recover ();
}
@@ -193,7 +195,8 @@ Session::silent_process_routes (jack_nframes_t nframes, jack_nframes_t offset)
call path, so make sure we release any outstanding locks here before we return failure.
*/
- for (DiskstreamList::iterator ids = diskstreams.begin(); ids != diskstreams.end(); ++ids) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator ids = dsl->begin(); ids != dsl->end(); ++ids) {
(*ids)->recover ();
}
@@ -212,7 +215,8 @@ Session::commit_diskstreams (jack_nframes_t nframes, bool &needs_butler)
float pworst = 1.0f;
float cworst = 1.0f;
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->hidden()) {
continue;
@@ -305,12 +309,10 @@ Session::process_with_events (jack_nframes_t nframes)
end_frame = _transport_frame + nframes;
{
- Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
-
Event* this_event;
Events::iterator the_next_one;
- if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
+ if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
no_roll (nframes, 0);
return;
}
@@ -575,17 +577,17 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
if (slave_state == Waiting) {
// cerr << "waiting at " << slave_transport_frame << endl;
- Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
-
- if (dsm.locked() && slave_transport_frame >= slave_wait_end) {
+ if (slave_transport_frame >= slave_wait_end) {
// cerr << "\tstart at " << _transport_frame << endl;
slave_state = Running;
bool ok = true;
jack_nframes_t frame_delta = slave_transport_frame - _transport_frame;
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->can_internal_playback_seek (frame_delta)) {
ok = false;
break;
@@ -593,7 +595,7 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
}
if (ok) {
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->internal_playback_seek (frame_delta);
}
_transport_frame += frame_delta;
@@ -697,12 +699,6 @@ Session::follow_slave (jack_nframes_t nframes, jack_nframes_t offset)
bool need_butler;
- Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
- if (!dsm.locked()) {
- goto noroll;
- }
-
-
prepare_diskstreams ();
silent_process_routes (nframes, offset);
commit_diskstreams (nframes, need_butler);
@@ -748,9 +744,7 @@ Session::process_without_events (jack_nframes_t nframes)
long frames_moved;
{
- Glib::RWLock::ReaderLock dsm (diskstream_lock, Glib::TRY_LOCK);
-
- if (!dsm.locked() || (post_transport_work & (PostTransportLocate|PostTransportStop))) {
+ if (post_transport_work & (PostTransportLocate|PostTransportStop)) {
no_roll (nframes, 0);
return;
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index cefae9dd3d..5553127b90 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -271,8 +271,9 @@ Session::first_stage_init (string fullpath, string snapshot_name)
Source::SourceCreated.connect (mem_fun (*this, &Session::add_source));
Playlist::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
- Diskstream::DiskstreamCreated.connect (mem_fun (*this, &Session::add_diskstream));
NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
+ Curve::CurveCreated.connect (mem_fun (*this, &Session::add_curve));
+ AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
Controllable::Created.connect (mem_fun (*this, &Session::add_controllable));
Controllable::GoingAway.connect (mem_fun (*this, &Session::remove_controllable));
@@ -354,6 +355,7 @@ Session::second_stage_init (bool new_session)
_end_location_is_free = false;
}
+ restore_history(_current_snapshot_name);
return 0;
}
@@ -631,14 +633,15 @@ Session::load_diskstreams (const XMLNode& node)
clist = node.children();
for (citer = clist.begin(); citer != clist.end(); ++citer) {
- Diskstream* dstream = 0;
try {
/* diskstreams added automatically by DiskstreamCreated handler */
if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
- dstream = new AudioDiskstream (*this, **citer);
+ boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
+ add_diskstream (dstream);
} else if ((*citer)->name() == "MidiDiskstream") {
- dstream = new MidiDiskstream (*this, **citer);
+ boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
+ add_diskstream (dstream);
} else {
error << _("Session: unknown diskstream type in XML") << endmsg;
}
@@ -727,6 +730,7 @@ Session::save_state (string snapshot_name, bool pending)
}
if (!pending) {
+ save_history(snapshot_name);
bool was_dirty = dirty();
@@ -1391,8 +1395,8 @@ Session::state(bool full_state)
child = node->add_child ("DiskStreams");
{
- Glib::RWLock::ReaderLock dl (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
child->add_child_nocopy ((*i)->get_state());
}
@@ -1695,7 +1699,6 @@ Session::set_state (const XMLNode& node)
if (state_was_pending) {
save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
remove_pending_capture_state ();
state_was_pending = false;
}
@@ -1713,6 +1716,7 @@ Session::load_routes (const XMLNode& node)
{
XMLNodeList nlist;
XMLNodeConstIterator niter;
+ RouteList new_routes;
nlist = node.children();
@@ -1727,9 +1731,11 @@ Session::load_routes (const XMLNode& node)
return -1;
}
- add_route (route);
+ new_routes.push_back (route);
}
+ add_routes (new_routes);
+
return 0;
}
@@ -2599,7 +2605,6 @@ void
Session::auto_save()
{
save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
}
RouteGroup *
@@ -3270,7 +3275,6 @@ Session::cleanup_sources (Session::cleanup_report& rep)
*/
save_state ("");
- save_history ("");
out:
_state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
@@ -3410,6 +3414,7 @@ Session::save_history (string snapshot_name)
string xml_path;
string bak_path;
+
tree.set_root (&history.get_state());
if (snapshot_name.empty()) {
@@ -3417,6 +3422,7 @@ Session::save_history (string snapshot_name)
}
xml_path = _path + snapshot_name + ".history";
+ cerr << "Saving history to " << xml_path << endmsg;
bak_path = xml_path + ".bak";
@@ -3450,3 +3456,65 @@ Session::save_history (string snapshot_name)
return 0;
}
+
+int
+Session::restore_history (string snapshot_name)
+{
+ XMLTree tree;
+ string xmlpath;
+
+ /* read xml */
+ xmlpath = _path + snapshot_name + ".history";
+ cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
+
+ if (access (xmlpath.c_str(), F_OK)) {
+ error << string_compose(_("%1: session history file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
+ return 1;
+ }
+
+ if (!tree.read (xmlpath)) {
+ error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
+ return -1;
+ }
+
+ /* replace history */
+ history.clear();
+ for (XMLNodeConstIterator it = tree.root()->children().begin();
+ it != tree.root()->children().end();
+ it++)
+ {
+ XMLNode *t = *it;
+ UndoTransaction ut;
+ struct timeval tv;
+
+ ut.set_name(t->property("name")->value());
+ stringstream ss(t->property("tv_sec")->value());
+ ss >> tv.tv_sec;
+ ss.str(t->property("tv_usec")->value());
+ ss >> tv.tv_usec;
+ ut.set_timestamp(tv);
+
+ for (XMLNodeConstIterator child_it = t->children().begin();
+ child_it != t->children().end();
+ child_it++)
+ {
+ XMLNode *n = *child_it;
+ Command *c;
+ if (n->name() == "MementoCommand" ||
+ n->name() == "MementoUndoCommand" ||
+ n->name() == "MementoRedoCommand")
+ {
+ c = memento_command_factory(n);
+ if (c)
+ ut.add_command(c);
+ }
+ else
+ {
+ error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
+ }
+ }
+ history.add(ut);
+ }
+
+ return 0;
+}
diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
index aad3617580..85e2dd391f 100644
--- a/libs/ardour/session_transport.cc
+++ b/libs/ardour/session_transport.cc
@@ -197,8 +197,8 @@ Session::realtime_stop (bool abort)
void
Session::butler_transport_work ()
{
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
boost::shared_ptr<RouteList> r = routes.reader ();
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
if (post_transport_work & PostTransportCurveRealloc) {
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@@ -207,7 +207,7 @@ Session::butler_transport_work ()
}
if (post_transport_work & PostTransportInputChange) {
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->non_realtime_input_change ();
}
}
@@ -223,7 +223,7 @@ Session::butler_transport_work ()
cumulative_rf_motion = 0;
reset_rf_scale (0);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@@ -253,9 +253,9 @@ Session::butler_transport_work ()
void
Session::non_realtime_set_speed ()
{
- Glib::RWLock::ReaderLock lm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->non_realtime_set_speed ();
}
}
@@ -263,9 +263,9 @@ Session::non_realtime_set_speed ()
void
Session::non_realtime_overwrite ()
{
- Glib::RWLock::ReaderLock lm (diskstream_lock);
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->pending_overwrite) {
(*i)->overwrite_existing_buffers ();
}
@@ -281,7 +281,9 @@ Session::non_realtime_stop (bool abort)
did_record = false;
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->get_captured_frames () != 0) {
did_record = true;
break;
@@ -329,14 +331,14 @@ Session::non_realtime_stop (bool abort)
XMLNode &before = loc->get_state();
loc->set_end(_transport_frame);
XMLNode &after = loc->get_state();
- add_command (new MementoCommand<Location>(*loc, before, after));
+ add_command (new MementoCommand<Location>(*loc, &before, &after));
}
_end_location_is_free = false;
_have_captured = true;
}
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->transport_stopped (*now, xnow, abort);
}
@@ -375,7 +377,7 @@ Session::non_realtime_stop (bool abort)
}
#endif
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
(*i)->seek ((jack_nframes_t) (_transport_frame * (double) (*i)->speed()));
@@ -413,7 +415,6 @@ 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);
- save_history ("");
}
/* always try to get rid of this */
@@ -424,7 +425,6 @@ Session::non_realtime_stop (bool abort)
if (did_record) {
save_state (_current_snapshot_name);
- save_history (_current_snapshot_name);
}
if (post_transport_work & PostTransportDuration) {
@@ -501,7 +501,8 @@ Session::set_auto_loop (bool yn)
if (seamless_loop) {
// set all diskstreams to use internal looping
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (loc);
}
@@ -509,7 +510,8 @@ Session::set_auto_loop (bool yn)
}
else {
// set all diskstreams to NOT use internal looping
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (0);
}
@@ -539,7 +541,8 @@ Session::set_auto_loop (bool yn)
clear_events (Event::AutoLoop);
// set all diskstreams to NOT use internal looping
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
(*i)->set_loop (0);
}
@@ -657,12 +660,10 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
if (with_roll) {
/* switch from input if we're going to roll */
if (Config->get_use_hardware_monitoring()) {
- /* Even though this is called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (!auto_input);
@@ -672,12 +673,9 @@ Session::locate (jack_nframes_t target_frame, bool with_roll, bool with_flush, b
} else {
/* otherwise we're going to stop, so do the opposite */
if (Config->get_use_hardware_monitoring()) {
- /* Even though this is called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true);
@@ -718,12 +716,9 @@ Session::set_transport_speed (float speed, bool abort)
if (Config->get_use_hardware_monitoring())
{
- /* Even though this is called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->record_enabled ()) {
//cerr << "switching to input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (true);
@@ -744,12 +739,10 @@ Session::set_transport_speed (float speed, bool abort)
}
if (Config->get_use_hardware_monitoring()) {
- /* Even though this is called from RT context we are using
- a non-tentative rwlock here, because the action must occur.
- The rarity and short potential lock duration makes this "OK"
- */
- Glib::RWLock::ReaderLock dsm (diskstream_lock);
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (auto_input && (*i)->record_enabled ()) {
//cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
(*i)->monitor_input (false);
@@ -800,7 +793,8 @@ Session::set_transport_speed (float speed, bool abort)
_last_transport_speed = _transport_speed;
_transport_speed = speed;
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed);
}
@@ -890,7 +884,8 @@ Session::actually_start_transport ()
transport_sub_state |= PendingDeclickIn;
_transport_speed = 1.0;
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->realtime_set_speed ((*i)->speed(), true);
}
@@ -1023,7 +1018,8 @@ Session::set_slave_source (SlaveSource src, jack_nframes_t frame)
_slave_type = src;
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
if (!(*i)->hidden()) {
if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
non_rt_required = true;
@@ -1214,7 +1210,6 @@ Session::update_latency_compensation (bool with_stop, bool abort)
return;
}
- Glib::RWLock::ReaderLock lm2 (diskstream_lock);
_worst_track_latency = 0;
boost::shared_ptr<RouteList> r = routes.reader ();
@@ -1252,7 +1247,9 @@ Session::update_latency_compensation (bool with_stop, bool abort)
/* reflect any changes in latencies into capture offsets
*/
- for (DiskstreamList::iterator i = diskstreams.begin(); i != diskstreams.end(); ++i) {
+ boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+
+ for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
(*i)->set_capture_offset ();
}
}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index bd5649bc2e..5a5bafb6ca 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -294,7 +294,7 @@ SMFSource::read_event(MidiEvent& ev) const
jack_nframes_t
SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframes_t cnt, jack_nframes_t stamp_offset) const
{
- cerr << "SMF - read " << start << " -- " << cnt;
+ //cerr << "SMF - read " << start << " -- " << cnt;
jack_nframes_t time = 0;
@@ -312,12 +312,12 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframe
while (!feof(_fd)) {
int ret = read_event(ev);
if (ret == -1) { // EOF
- cerr << "SMF - EOF\n";
+ //cerr << "SMF - EOF\n";
break;
}
if (ret == 0) { // meta-event (skipped)
- cerr << "SMF - META\n";
+ //cerr << "SMF - META\n";
time += ev.time; // just accumulate delta time and ignore event
continue;
}
@@ -370,7 +370,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, jack_nframes_t start, jack_nframe
jack_nframes_t
SMFSource::write_unlocked (MidiRingBuffer& src, jack_nframes_t cnt)
{
- cerr << "SMF WRITE -- " << _length << "--" << cnt << endl;
+ //cerr << "SMF WRITE -- " << _length << "--" << cnt << endl;
MidiBuffer buf(1024); // FIXME: allocation, size?
src.read(buf, /*_length*/0, _length + cnt); // FIXME?
diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc
index 28816541f1..a96a4a1a82 100644
--- a/libs/ardour/track.cc
+++ b/libs/ardour/track.cc
@@ -41,7 +41,6 @@ using namespace PBD;
Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, DataType default_type)
: Route (sess, name, 1, -1, -1, -1, flag, default_type)
- , _diskstream (0)
, _rec_enable_control (*this)
{
_declickable = true;
@@ -52,7 +51,6 @@ Track::Track (Session& sess, string name, Route::Flag flag, TrackMode mode, Data
Track::Track (Session& sess, const XMLNode& node, DataType default_type)
: Route (sess, "to be renamed", 0, 0, -1, -1, Route::Flag(0), default_type)
- , _diskstream (0)
, _rec_enable_control (*this)
{
_freeze_record.state = NoFreeze;
@@ -62,9 +60,6 @@ Track::Track (Session& sess, const XMLNode& node, DataType default_type)
Track::~Track ()
{
- if (_diskstream) {
- _diskstream->unref();
- }
}
void
@@ -224,7 +219,6 @@ Track::set_name (string str, void *src)
if ((ret = IO::set_name (str, src)) == 0) {
_session.save_state ("");
- _session.save_history ("");
}
return ret;
}
diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc
index 0de0d052c3..ab7806873e 100644
--- a/libs/pbd/id.cc
+++ b/libs/pbd/id.cc
@@ -25,7 +25,7 @@ ID::init ()
ID::ID ()
{
Glib::Mutex::Lock lm (*counter_lock);
- id = _counter++;
+ _id = _counter++;
}
ID::ID (string str)
@@ -36,14 +36,14 @@ ID::ID (string str)
int
ID::string_assign (string str)
{
- return sscanf (str.c_str(), "%" PRIu64, &id) != 0;
+ return sscanf (str.c_str(), "%" PRIu64, &_id) != 0;
}
void
ID::print (char* buf) const
{
/* XXX sizeof buf is unknown. bad API design */
- snprintf (buf, 16, "%" PRIu64, id);
+ snprintf (buf, 16, "%" PRIu64, _id);
}
string ID::to_s() const
@@ -61,10 +61,10 @@ ID::operator= (string str)
}
ostream&
-operator<< (ostream& ostr, const ID& id)
+operator<< (ostream& ostr, const ID& _id)
{
char buf[32];
- id.print (buf);
+ _id.print (buf);
ostr << buf;
return ostr;
}
diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
index 0e34787a2d..eca53916af 100644
--- a/libs/pbd/pbd/abstract_ui.cc
+++ b/libs/pbd/pbd/abstract_ui.cc
@@ -4,6 +4,10 @@
#include <pbd/pthread_utils.h>
#include <pbd/failed_constructor.h>
+#include "i18n.h"
+
+using namespace std;
+
template <typename RequestObject>
AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
: BaseUI (name, with_signal_pipes)
@@ -44,7 +48,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
if (rbuf == 0) {
/* Cannot happen, but if it does we can't use the error reporting mechanism */
cerr << _("programming error: ")
- << string_compose (X_("no %1-UI request buffer found for thread %2"), name(), pthread_name())
+ << string_compose ("no %1-UI request buffer found for thread %2", name(), pthread_name())
<< endl;
abort ();
}
@@ -55,7 +59,7 @@ AbstractUI<RequestObject>::get_request (RequestType rt)
if (vec.len[0] == 0) {
if (vec.len[1] == 0) {
- cerr << string_compose (X_("no space in %1-UI request buffer for thread %2"), name(), pthread_name())
+ cerr << string_compose ("no space in %1-UI request buffer for thread %2", name(), pthread_name())
<< endl;
return 0;
} else {
@@ -131,7 +135,7 @@ AbstractUI<RequestObject>::send_request (RequestObject *req)
thread isn't registered!
*/
cerr << _("programming error: ")
- << string_compose (X_("AbstractUI::send_request() called from %1, but no request buffer exists for that thread"), pthread_name())
+ << string_compose ("AbstractUI::send_request() called from %1 (%2), but no request buffer exists for that thread", name(), pthread_name())
<< endl;
abort ();
}
diff --git a/libs/pbd/pbd/destructible.h b/libs/pbd/pbd/destructible.h
new file mode 100644
index 0000000000..126bd04bba
--- /dev/null
+++ b/libs/pbd/pbd/destructible.h
@@ -0,0 +1,20 @@
+#ifndef __pbd_destructible_h__
+#define __pbd_destructible_h__
+
+#include <sigc++/signal.h>
+
+namespace PBD {
+
+class Destructible {
+ public:
+ Destructible() {}
+ virtual ~Destructible () {}
+
+ sigc::signal<void> GoingAway;
+
+ void drop_references () const { GoingAway(); }
+};
+
+}
+
+#endif /* __pbd_destructible_h__ */
diff --git a/libs/pbd/pbd/id.h b/libs/pbd/pbd/id.h
index 1ce448d58b..c110362734 100644
--- a/libs/pbd/pbd/id.h
+++ b/libs/pbd/pbd/id.h
@@ -14,17 +14,17 @@ class ID {
ID (std::string);
bool operator== (const ID& other) const {
- return id == other.id;
+ return _id == other._id;
}
bool operator!= (const ID& other) const {
- return id != other.id;
+ return _id != other._id;
}
ID& operator= (std::string);
bool operator< (const ID& other) const {
- return id < other.id;
+ return _id < other._id;
}
void print (char* buf) const;
@@ -35,7 +35,7 @@ class ID {
static void init ();
private:
- uint64_t id;
+ uint64_t _id;
int string_assign (std::string);
static Glib::Mutex* counter_lock;
diff --git a/libs/pbd/pbd/memento_command.h b/libs/pbd/pbd/memento_command.h
index 122dcb4c86..3a72fc9841 100644
--- a/libs/pbd/pbd/memento_command.h
+++ b/libs/pbd/pbd/memento_command.h
@@ -36,70 +36,44 @@ class MementoCommand : public Command
public:
MementoCommand(XMLNode &state);
MementoCommand(obj_T &obj,
- XMLNode &before,
- XMLNode &after
+ XMLNode *before,
+ XMLNode *after
)
: obj(obj), before(before), after(after) {}
- void operator() () { obj.set_state(after); }
- void undo() { obj.set_state(before); }
+ void operator() ()
+ {
+ if (after)
+ obj.set_state(*after);
+ }
+ void undo()
+ {
+ if (before)
+ obj.set_state(*before);
+ }
virtual XMLNode &get_state()
{
- XMLNode *node = new XMLNode("MementoCommand");
+ string name;
+ if (before && after)
+ name = "MementoCommand";
+ else if (before)
+ name = "MementoUndoCommand";
+ else
+ name = "MementoRedoCommand";
+
+ XMLNode *node = new XMLNode(name);
node->add_property("obj_id", obj.id().to_s());
node->add_property("type_name", typeid(obj).name());
- node->add_child_copy(before);
- node->add_child_copy(after);
+
+ if (before)
+ node->add_child_copy(*before);
+ if (after)
+ node->add_child_copy(*after);
+
return *node;
}
protected:
obj_T &obj;
- XMLNode &before, &after;
-};
-
-template <class obj_T>
-class MementoUndoCommand : public Command
-{
-public:
- MementoUndoCommand(XMLNode &state);
- MementoUndoCommand(obj_T &obj,
- XMLNode &before)
- : obj(obj), before(before) {}
- void operator() () { /* noop */ }
- void undo() { obj.set_state(before); }
- virtual XMLNode &get_state()
- {
- XMLNode *node = new XMLNode("MementoUndoCommand");
- node->add_property("obj_id", obj.id().to_s());
- node->add_property("type_name", typeid(obj).name());
- node->add_child_copy(before);
- return *node;
- }
-protected:
- obj_T &obj;
- XMLNode &before;
-};
-
-template <class obj_T>
-class MementoRedoCommand : public Command
-{
-public:
- MementoRedoCommand(XMLNode &state);
- MementoRedoCommand(obj_T &obj,
- XMLNode &after)
- : obj(obj), after(after) {}
- void operator() () { obj.set_state(after); }
- void undo() { /* noop */ }
- virtual XMLNode &get_state()
- {
- XMLNode *node = new XMLNode("MementoRedoCommand");
- node->add_property("obj_id", obj.id().to_s());
- node->add_property("type_name", typeid(obj).name());
- node->add_child_copy(after);
- return *node;
- }
-protected:
- obj_T &obj;
- XMLNode &after;
+ XMLNode *before, *after;
};
#endif // __lib_pbd_memento_h__
diff --git a/libs/pbd/pbd/rcu.h b/libs/pbd/pbd/rcu.h
index 58a92a206a..e81db8ba87 100644
--- a/libs/pbd/pbd/rcu.h
+++ b/libs/pbd/pbd/rcu.h
@@ -5,8 +5,7 @@
#include "glibmm/thread.h"
#include <list>
-
-
+
template<class T>
class RCUManager
{
@@ -43,7 +42,7 @@ public:
}
- virtual boost::shared_ptr<T> write_copy ()
+ boost::shared_ptr<T> write_copy ()
{
m_lock.lock();
@@ -64,11 +63,11 @@ public:
current_write_old = RCUManager<T>::m_rcu_value;
boost::shared_ptr<T> new_copy (new T(**current_write_old));
-
+
return new_copy;
}
- virtual bool update (boost::shared_ptr<T> new_value)
+ bool update (boost::shared_ptr<T> new_value)
{
// we hold the lock at this point effectively blocking
// other writers.
@@ -98,6 +97,11 @@ public:
return ret;
}
+
+ void flush () {
+ Glib::Mutex::Lock lm (m_lock);
+ m_dead_wood.clear ();
+ }
private:
Glib::Mutex m_lock;
diff --git a/libs/pbd/pbd/stateful.h b/libs/pbd/pbd/stateful.h
index 3038f16b4f..5adddfc1c0 100644
--- a/libs/pbd/pbd/stateful.h
+++ b/libs/pbd/pbd/stateful.h
@@ -22,6 +22,7 @@
#define __pbd_stateful_h__
#include <string>
+#include <pbd/id.h>
class XMLNode;
@@ -41,10 +42,12 @@ class Stateful {
virtual void add_instant_xml (XMLNode&, const std::string& dir);
XMLNode *instant_xml (const std::string& str, const std::string& dir);
+ PBD::ID id() { return _id; }
protected:
XMLNode *_extra_xml;
XMLNode *_instant_xml;
+ PBD::ID _id;
};
#endif /* __pbd_stateful_h__ */
diff --git a/libs/pbd/pbd/unknown_type.h b/libs/pbd/pbd/unknown_type.h
new file mode 100644
index 0000000000..fddc1aeddb
--- /dev/null
+++ b/libs/pbd/pbd/unknown_type.h
@@ -0,0 +1,11 @@
+#ifndef __pbd_unknown_type_h__
+#define __pbd_unknown_type_h__
+
+#include <exception>
+
+class unknown_type : public std::exception {
+ public:
+ virtual const char *what() const throw() { return "unknown type"; }
+};
+
+#endif /* __pbd_unknown_type_h__ */
diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc
index 8d1b416c16..6f421de84e 100644
--- a/libs/pbd/undo.cc
+++ b/libs/pbd/undo.cc
@@ -23,6 +23,7 @@
#include <pbd/undo.h>
#include <pbd/xml++.h>
#include <string>
+#include <sstream>
using namespace std;
using namespace sigc;
@@ -87,6 +88,13 @@ UndoTransaction::redo ()
XMLNode &UndoTransaction::get_state()
{
XMLNode *node = new XMLNode ("UndoTransaction");
+ stringstream ss;
+ ss << _timestamp.tv_sec;
+ node->add_property("tv_sec", ss.str());
+ ss.str("");
+ ss << _timestamp.tv_usec;
+ node->add_property("tv_usec", ss.str());
+ node->add_property("name", _name);
list<Command*>::iterator it;
for (it=actions.begin(); it!=actions.end(); it++)
diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc
index bee4783914..3dc93cc64a 100644
--- a/libs/surfaces/control_protocol/basic_ui.cc
+++ b/libs/surfaces/control_protocol/basic_ui.cc
@@ -145,7 +145,6 @@ void
BasicUI::save_state ()
{
session->save_state ("");
- session->save_history("");
}
void