Merged with trunk R846
authorDavid Robillard <d@drobilla.net>
Thu, 24 Aug 2006 07:37:17 +0000 (07:37 +0000)
committerDavid Robillard <d@drobilla.net>
Thu, 24 Aug 2006 07:37:17 +0000 (07:37 +0000)
Removed some overly verbose debug printing

git-svn-id: svn://localhost/ardour2/branches/midi@847 d708f5d6-7413-0410-9779-e7cbd77b26cf

86 files changed:
Makefile [new file with mode: 0644]
SConstruct
gtk2_ardour/ardbg
gtk2_ardour/ardev
gtk2_ardour/ardev_common.sh
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/ardour_ui_dialogs.cc
gtk2_ardour/ardour_ui_ed.cc
gtk2_ardour/audio_region_view.cc
gtk2_ardour/audio_streamview.cc
gtk2_ardour/audio_streamview.h
gtk2_ardour/automation_line.cc
gtk2_ardour/automation_time_axis.cc
gtk2_ardour/axis_view.h
gtk2_ardour/editor.cc
gtk2_ardour/editor.h
gtk2_ardour/editor_audio_import.cc
gtk2_ardour/editor_keyboard.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_route_list.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/editor_timefx.cc
gtk2_ardour/gain_automation_time_axis.cc
gtk2_ardour/location_ui.cc
gtk2_ardour/midi_streamview.cc
gtk2_ardour/mixer_ui.cc
gtk2_ardour/mixer_ui.h
gtk2_ardour/pan_automation_time_axis.cc
gtk2_ardour/playlist_selector.cc
gtk2_ardour/redirect_automation_time_axis.cc
gtk2_ardour/region_gain_line.cc
gtk2_ardour/route_params_ui.cc
gtk2_ardour/route_params_ui.h
gtk2_ardour/route_time_axis.cc
gtk2_ardour/route_ui.cc
gtk2_ardour/route_ui.h
gtk2_ardour/selection.cc
gtk2_ardour/streamview.cc
gtk2_ardour/streamview.h
libs/ardour/ardour/audio_diskstream.h
libs/ardour/ardour/audio_track.h
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/automation_event.h
libs/ardour/ardour/curve.h
libs/ardour/ardour/diskstream.h
libs/ardour/ardour/location.h
libs/ardour/ardour/midi_diskstream.h
libs/ardour/ardour/midi_ring_buffer.h
libs/ardour/ardour/midi_track.h
libs/ardour/ardour/route.h
libs/ardour/ardour/session.h
libs/ardour/ardour/track.h
libs/ardour/audio_diskstream.cc
libs/ardour/audio_track.cc
libs/ardour/audioengine.cc
libs/ardour/auditioner.cc
libs/ardour/automation_event.cc
libs/ardour/curve.cc
libs/ardour/diskstream.cc
libs/ardour/location.cc
libs/ardour/midi_diskstream.cc
libs/ardour/midi_track.cc
libs/ardour/route.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_command.cc
libs/ardour/session_export.cc
libs/ardour/session_midi.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_transport.cc
libs/ardour/smf_source.cc
libs/ardour/track.cc
libs/pbd/id.cc
libs/pbd/pbd/abstract_ui.cc
libs/pbd/pbd/destructible.h [new file with mode: 0644]
libs/pbd/pbd/id.h
libs/pbd/pbd/memento_command.h
libs/pbd/pbd/rcu.h
libs/pbd/pbd/stateful.h
libs/pbd/pbd/unknown_type.h [new file with mode: 0644]
libs/pbd/undo.cc
libs/surfaces/control_protocol/basic_ui.cc

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..1a39c6d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+all: scons cscope
+
+scons:
+       scons
+
+sconsi:
+       scons --implicit-deps-unchanged
+
+cscope: cscope.out
+
+cscope.out: cscope.files
+       cscope -b
+
+cscope.files:
+       find . -name '*.[ch]' -o -name '*.cc' > $@
+
+.PHONY: all cscope.files sconsi cscope
index e7e43a1405bba2a8192fccd10dddb7ebee33fadf..b6a2ed64c5131b70208e77938aa8ec2428fcdd92 100644 (file)
@@ -457,6 +457,16 @@ libraries['flac'] = conf.Finish ()
 # or if that fails...
 #libraries['flac']    = LibraryInfo (LIBS='FLAC')
 
+# boost (we don't link against boost, just use some header files)
+
+libraries['boost'] = LibraryInfo ()
+conf = Configure (libraries['boost'])
+if conf.CheckHeader ('boost/shared_ptr.hpp', language='CXX') == 0:
+        print "Boost header files do not appear to be installed."
+        sys.exit (1)
+    
+libraries['boost'] = conf.Finish ()
+
 #
 # Check for liblo
 
index 9d3f5bf6c75ae4d21ee0097490f4cff4044afebb..115db85f59196958c7eead99a3e833a6c2eb5b6f 100755 (executable)
@@ -1,3 +1,4 @@
 #!/bin/sh
-source ardev_common.sh
-exec gdb ./ardour.bin "$*"
+dir=`dirname "$0"`
+source $dir/ardev_common.sh
+exec gdb gtk2_ardour/ardour.bin $*
index 017a7e337dedd9ed5dd8df3d74747ad6c50915f6..751557d634fbec98440b914b5951e1098a945f01 100755 (executable)
@@ -1,4 +1,3 @@
 #!/bin/sh
-
-source ardev_common.sh
-exec ./ardour.bin --novst $*
+source `dirname "$0"`/ardev_common.sh
+exec gtk2_ardour/ardour.bin --novst "$*"
index bf644f3e845d91ab2fd95cb679a700d496c0e355..df4bb025c0367924e5288c57011365280a557eb0 100755 (executable)
@@ -1,8 +1,10 @@
+cd `dirname "$0"`/..
+
 #export G_DEBUG=fatal_criticals
 
-export ARDOUR_PATH=./glade:./pixmaps:.
+export ARDOUR_PATH=gtk2_ardour/glade:gtk2_ardour/pixmaps:gtk2_ardour
 
-export LD_LIBRARY_PATH=../libs/surfaces/control_protocol:../libs/ardour:../libs/midi++2:../libs/pbd:../libs/soundtouch:../libs/gtkmm2ext:../libs/sigc++2:../libs/glibmm2:../libs/gtkmm2/atk:../libs/gtkmm2/pango:../libs/gtkmm2/gdk:../libs/gtkmm2/gtk:../libs/libgnomecanvasmm:../libs/libsndfile:../libs/appleutility:$LD_LIBRARY_PATH
+export LD_LIBRARY_PATH=libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/soundtouch:libs/gtkmm2ext:libs/sigc++2:libs/glibmm2:libs/gtkmm2/atk:libs/gtkmm2/pango:libs/gtkmm2/gdk:libs/gtkmm2/gtk:libs/libgnomecanvasmm:libs/libsndfile:libs/appleutility:$LD_LIBRARY_PATH
 
 # DYLD_LIBRARY_PATH is for darwin.
 export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
index 34718dfb1ce2ba5c8af39621d652872289a921ea..de117a13990d9445965f50a162d9e5311e9f87ca 100644 (file)
@@ -546,7 +546,7 @@ void
 ARDOUR_UI::count_recenabled_diskstreams (Route& route)
 {
        Track* track = dynamic_cast<Track*>(&route);
-       if (track && track->diskstream().record_enabled()) {
+       if (track && track->diskstream()->record_enabled()) {
                rec_enabled_diskstreams++;
        }
 }
@@ -869,9 +869,9 @@ ARDOUR_UI::open_session ()
 
 
 void
-ARDOUR_UI::session_add_midi_route (bool disk)
+ARDOUR_UI::session_add_midi_route (bool disk, uint32_t how_many)
 {
-       boost::shared_ptr<Route> route;
+       list<boost::shared_ptr<MidiTrack> > tracks;
 
        if (session == 0) {
                warning << _("You cannot add a track without a session already loaded.") << endmsg;
@@ -880,14 +880,21 @@ ARDOUR_UI::session_add_midi_route (bool disk)
 
        try { 
                if (disk) {
-                       if ((route = session->new_midi_track (/*mode*/)) == 0) {
-                               error << _("could not create new midi track") << endmsg;
+
+                       tracks = session->new_midi_track (ARDOUR::Normal, how_many);
+
+                       if (tracks.size() != how_many) {
+                               if (how_many == 1) {
+                                       error << _("could not create a new midi track") << endmsg;
+                               } else {
+                                       error << string_compose (_("could not create %1 new midi tracks"), how_many) << endmsg;
+                               }
                        }
-               } else {
+               } /*else {
                        if ((route = session->new_midi_route ()) == 0) {
                                error << _("could not create new midi bus") << endmsg;
                        }
-               }
+               }*/
        }
 
        catch (...) {
@@ -902,23 +909,38 @@ restart JACK with more ports."));
 
 
 void
-ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode)
+ARDOUR_UI::session_add_audio_route (bool track, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many)
 {
-       boost::shared_ptr<Route> route;
+       list<boost::shared_ptr<AudioTrack> > tracks;
+       Session::RouteList routes;
 
        if (session == 0) {
-               warning << _("You cannot add a track without a session already loaded.") << endmsg;
+               warning << _("You cannot add a track or bus without a session already loaded.") << endmsg;
                return;
        }
 
        try { 
-               if (disk) {
-                       if ((route = session->new_audio_track (input_channels, output_channels, mode)) == 0) {
-                               error << _("could not create new audio track") << endmsg;
+               if (track) {
+                       tracks = session->new_audio_track (input_channels, output_channels, mode, how_many);
+
+                       if (tracks.size() != how_many) {
+                               if (how_many == 1) {
+                                       error << _("could not create a new audio track") << endmsg;
+                               } else {
+                                       error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
+                               }
                        }
+
                } else {
-                       if ((route = session->new_audio_route (input_channels, output_channels)) == 0) {
-                               error << _("could not create new audio bus") << endmsg;
+
+                       routes = session->new_audio_route (input_channels, output_channels, how_many);
+
+                       if (routes.size() != how_many) {
+                               if (how_many == 1) {
+                                       error << _("could not create a new audio track") << endmsg;
+                               } else {
+                                       error << string_compose (_("could not create %1 new audio tracks"), how_many) << endmsg;
+                               }
                        }
                }
                
@@ -945,11 +967,6 @@ restart JACK with more ports."));
        }
 }
 
-void
-ARDOUR_UI::diskstream_added (Diskstream* ds)
-{
-}
-
 void
 ARDOUR_UI::do_transport_locate (jack_nframes_t new_position)
 {
@@ -1200,7 +1217,7 @@ ARDOUR_UI::toggle_record_enable (uint32_t dstream)
                Track* t;
 
                if ((t = dynamic_cast<Track*>(r.get())) != 0) {
-                       t->diskstream().set_record_enabled (!t->diskstream().record_enabled());
+                       t->diskstream()->set_record_enabled (!t->diskstream()->record_enabled());
                }
        }
        if (session == 0) {
@@ -1326,7 +1343,6 @@ ARDOUR_UI::start_engine ()
                           settings for a new session 
                        */
                        session->save_state ("");
-                        session->save_history ("");
                }
 
                /* there is too much going on, in too many threads, for us to 
@@ -1500,7 +1516,6 @@ ARDOUR_UI::save_state_canfail (string name)
                }
 
                if ((ret = session->save_state (name)) != 0) {
-                        session->save_history (name);
                        return ret;
                }
        }
@@ -2080,15 +2095,15 @@ ARDOUR_UI::add_route ()
        }
 
        ResponseType r = (ResponseType) add_route_dialog->run ();
-       
+
        add_route_dialog->hide();
 
        switch (r) {
-       case RESPONSE_ACCEPT:
-               break;
-       default:
-               return;
-               break;
+               case RESPONSE_ACCEPT:
+                       break;
+               default:
+                       return;
+                       break;
        }
 
        if ((count = add_route_dialog->count()) <= 0) {
@@ -2110,25 +2125,20 @@ ARDOUR_UI::add_route ()
 
        /* XXX do something with name template */
 
-       while (count) {
-               if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
-                       if (track) {
-                               session_add_midi_track();
-                       } else  {
-                               MessageDialog msg (*editor,
-                                  _("Sorry, MIDI Busses are not supported at this time."));
-                               msg.run ();
-                               //session_add_midi_bus();
-                       }
-               } else if (track) {
-                       session_add_audio_track (input_chan, output_chan, add_route_dialog->mode());
-               } else {
-                       session_add_audio_bus (input_chan, output_chan);
+       if (add_route_dialog->type() == ARDOUR::DataType::MIDI) {
+               if (track) {
+                       session_add_midi_track(count);
+               } else  {
+                       MessageDialog msg (*editor,
+                                       _("Sorry, MIDI Busses are not supported at this time."));
+                       msg.run ();
+                       //session_add_midi_bus();
                }
-               --count;
-               
-               while (Main::events_pending()) {
-                       Main::iteration ();
+       } else { 
+               if (track) {
+                       session_add_audio_track (input_chan, output_chan, add_route_dialog->mode(), count);
+               } else {
+                       session_add_audio_bus (input_chan, output_chan, count);
                }
        }
 }
index 0af88eec185926af90243c8e1425bcbbd65bcbcf..1f5277b5fee6633732661fa4082a7682c135ca40 100644 (file)
@@ -189,21 +189,21 @@ class ARDOUR_UI : public Gtkmm2ext::UI
 
        void add_route ();
        
-       void session_add_audio_track (int input_channels, int32_t output_channels, ARDOUR::TrackMode mode) {
-               session_add_audio_route (true, input_channels, output_channels, mode);
+       void session_add_audio_track (int input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many) {
+               session_add_audio_route (true, input_channels, output_channels, mode, how_many);
        }
 
-       void session_add_audio_bus (int input_channels, int32_t output_channels) {
-               session_add_audio_route (false, input_channels, output_channels, ARDOUR::Normal);
+       void session_add_audio_bus (int input_channels, int32_t output_channels, uint32_t how_many) {
+               session_add_audio_route (false, input_channels, output_channels, ARDOUR::Normal, how_many);
        }
 
-       void session_add_midi_track () {
-               session_add_midi_route (true);
+       void session_add_midi_track (uint32_t how_many) {
+               session_add_midi_route (true, how_many);
        }
 
-       void session_add_midi_bus () {
+       /*void session_add_midi_bus () {
                session_add_midi_route (false);
-       }
+       }*/
 
        void set_engine (ARDOUR::AudioEngine&);
 
@@ -526,8 +526,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        sigc::connection point_one_second_connection;
        sigc::connection point_zero_one_second_connection;
 
-       void diskstream_added (ARDOUR::Diskstream*);
-
        gint session_menu (GdkEventButton *);
 
        bool _will_create_new_session_automatically;
@@ -540,8 +538,8 @@ class ARDOUR_UI : public Gtkmm2ext::UI
 
        void save_template ();
 
-       void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode);
-       void session_add_midi_route (bool disk);
+       void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels, ARDOUR::TrackMode mode, uint32_t how_many);
+       void session_add_midi_route (bool disk, uint32_t how_many);
 
        void set_transport_sensitivity (bool);
 
index 5a1ec874624e2d5c39862c049e0833c5a139ab5c..c90480c1dd9fbae244f4d5be8ba440c1b4440c6d 100644 (file)
@@ -76,10 +76,6 @@ ARDOUR_UI::connect_to_session (Session *s)
        rec_button.set_sensitive (true);
        shuttle_box.set_sensitive (true);
        
-       if (session->n_diskstreams() == 0) {
-               session->DiskstreamAdded.connect (mem_fun(*this, &ARDOUR_UI::diskstream_added));
-       }
-
        if (connection_editor) {
                connection_editor->set_session (s);
        }
@@ -156,7 +152,6 @@ ARDOUR_UI::unload_session ()
                        
                case 1:
                        session->save_state ("");
-                        session->save_history ("");
                        break;
                }
        }
index fc5ffb6e9cc337da10f6c9a4fa424f6ac7c225bb..2fe34127dc2c6f4d1b716b66bcb63dfb17344d0d 100644 (file)
@@ -194,14 +194,14 @@ ARDOUR_UI::install_actions ()
        act = ActionManager::register_action (common_actions, X_("About"), _("About"),  mem_fun(*this, &ARDOUR_UI::show_splash));
        act = ActionManager::register_toggle_action (common_actions, X_("ToggleColorManager"), _("Colors"), mem_fun(*this, &ARDOUR_UI::toggle_color_manager));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal));
+       act = ActionManager::register_action (common_actions, X_("AddAudioTrack"), _("Add Audio Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_track), 1, 1, ARDOUR::Normal, 1));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1));
+       act = ActionManager::register_action (common_actions, X_("AddAudioBus"), _("Add Audio Bus"), bind (mem_fun(*this, &ARDOUR_UI::session_add_audio_bus), 1, 1, 1));
        ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (common_actions, X_("AddMIDITrack"), _("Add MIDI Track"), (mem_fun(*this, &ARDOUR_UI::session_add_midi_track)));
-       ActionManager::session_sensitive_actions.push_back (act);
-       act = ActionManager::register_action (common_actions, X_("AddMidiBus"), _("Add Midi Bus"), mem_fun(*this, &ARDOUR_UI::session_add_midi_bus));
+       act = ActionManager::register_action (common_actions, X_("AddMIDITrack"), _("Add MIDI Track"), bind (mem_fun(*this, &ARDOUR_UI::session_add_midi_track), 1));
        ActionManager::session_sensitive_actions.push_back (act);
+       //act = ActionManager::register_action (common_actions, X_("AddMidiBus"), _("Add Midi Bus"), mem_fun(*this, &ARDOUR_UI::session_add_midi_bus));
+       //ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (common_actions, X_("Save"), _("Save"),  bind (mem_fun(*this, &ARDOUR_UI::save_state), string("")));
        ActionManager::session_sensitive_actions.push_back (act);
        act = ActionManager::register_action (common_actions, X_("RemoveLastCapture"), _("Remove Last Capture"), mem_fun(*this, &ARDOUR_UI::remove_last_capture));
index acde408c6b891cd8a25b1c5161933c5f65f4382d..93af5b3ec09f8a15ca283137c025086714b19461 100644 (file)
@@ -928,13 +928,13 @@ AudioRegionView::add_gain_point_event (ArdourCanvas::Item *item, GdkEvent *ev)
                XMLNode &before = audio_region().get_state();
                audio_region().set_envelope_active(true);
                XMLNode &after = audio_region().get_state();
-               trackview.session().add_command (new MementoCommand<AudioRegion>(audio_region(), before, after));
+               trackview.session().add_command (new MementoCommand<AudioRegion>(audio_region(), &before, &after));
        }
 
        audio_region().envelope().add (fx, y);
        
        XMLNode &after = audio_region().envelope().get_state();
-       trackview.session().add_command (new MementoCommand<Curve>(audio_region().envelope(), before, after));
+       trackview.session().add_command (new MementoCommand<Curve>(audio_region().envelope(), &before, &after));
        trackview.session().commit_reversible_command ();
 }
 
index 523395c503b31e9023601ba2950a20dfa447606f..83d1825ef52d0f1fe37ca88451a04514370c8cdf 100644 (file)
@@ -224,7 +224,7 @@ AudioStreamView::playlist_modified ()
 }
 
 void
-AudioStreamView::playlist_changed (Diskstream *ds)
+AudioStreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &AudioStreamView::playlist_changed), ds));
 
@@ -398,7 +398,7 @@ AudioStreamView::setup_rec_box ()
                                rec_data_ready_connections.clear();
                                        
                                // FIXME
-                               AudioDiskstream* ads = dynamic_cast<AudioDiskstream*>(_trackview.get_diskstream());
+                               boost::shared_ptr<AudioDiskstream> ads = boost::dynamic_pointer_cast<AudioDiskstream>(_trackview.get_diskstream());
                                assert(ads);
 
                                for (uint32_t n=0; n < ads->n_channels().get(DataType::AUDIO); ++n) {
@@ -430,8 +430,8 @@ AudioStreamView::setup_rec_box ()
                        AudioTrack* at;
 
                        at = _trackview.audio_track(); /* we know what it is already */
-                       AudioDiskstream& ds = at->audio_diskstream();
-                       jack_nframes_t frame_pos = ds.current_capture_start ();
+                       boost::shared_ptr<AudioDiskstream> ds = at->audio_diskstream();
+                       jack_nframes_t frame_pos = ds->current_capture_start ();
                        gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
                        gdouble xend;
                        uint32_t fill_color;
index 979240bd503f85d00f3b84ce1406a76cef8771a8..cf66637b9b2efc6d458df474dc665a4b0e13ecfa 100644 (file)
@@ -87,7 +87,7 @@ class AudioStreamView : public StreamView
        void undisplay_diskstream ();
        void redisplay_diskstream ();
        void playlist_modified ();
-       void playlist_changed (ARDOUR::Diskstream *ds);
+       void playlist_changed (boost::shared_ptr<ARDOUR::Diskstream>);
 
        void add_crossfade (ARDOUR::Crossfade*);
        void remove_crossfade (ARDOUR::Crossfade*);
index f3e30c4523428f6292d91a209863f11c18e5c4ad..c0ba957af86833d599dea92287e9079915567fd7 100644 (file)
@@ -244,6 +244,9 @@ AutomationLine::AutomationLine (const string & name, TimeAxisView& tv, ArdourCan
        line->signal_event().connect (mem_fun (*this, &AutomationLine::event_handler));
 
        alist.StateChanged.connect (mem_fun(*this, &AutomationLine::list_changed));
+
+        trackview.session().register_with_memento_command_factory(_id, this);
+
 }
 
 AutomationLine::~AutomationLine ()
@@ -888,7 +891,7 @@ AutomationLine::start_drag (ControlPoint* cp, float fraction)
        }
 
        trackview.editor.current_session()->begin_reversible_command (str);
-       trackview.editor.current_session()->add_command (new MementoUndoCommand<AutomationLine>(*this, get_state()));
+       trackview.editor.current_session()->add_command (new MementoCommand<AutomationLine>(*this, &get_state(), 0));
        
        first_drag_fraction = fraction;
        last_drag_fraction = fraction;
@@ -937,7 +940,7 @@ AutomationLine::end_drag (ControlPoint* cp)
 
                update_pending = false;
 
-               trackview.editor.current_session()->add_command (new MementoRedoCommand<AutomationLine>(*this, get_state()));
+               trackview.editor.current_session()->add_command (new MementoCommand<AutomationLine>(*this, 0, &get_state()));
                trackview.editor.current_session()->commit_reversible_command ();
                trackview.editor.current_session()->set_dirty ();
        }
@@ -1018,7 +1021,7 @@ AutomationLine::remove_point (ControlPoint& cp)
 
        alist.erase (mr.start, mr.end);
 
-       trackview.editor.current_session()->add_command(new MementoCommand<AutomationLine>(*this, before, get_state()));
+       trackview.editor.current_session()->add_command(new MementoCommand<AutomationLine>(*this, &before, &get_state()));
        trackview.editor.current_session()->commit_reversible_command ();
        trackview.editor.current_session()->set_dirty ();
 }
@@ -1228,7 +1231,7 @@ AutomationLine::clear ()
        /* parent must create command */
         XMLNode &before = get_state();
        alist.clear();
-       trackview.editor.current_session()->add_command (new MementoCommand<AutomationLine>(*this, before, get_state()));
+       trackview.editor.current_session()->add_command (new MementoCommand<AutomationLine>(*this, &before, &get_state()));
        trackview.editor.current_session()->commit_reversible_command ();
        trackview.editor.current_session()->set_dirty ();
 }
index 7025a11178371dfef981b576f72e890af63a2dcd..80ed2acd164502eaa5a929b1aad3aea3155aacd0 100644 (file)
@@ -482,7 +482,7 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
        case Cut:
                if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
                        editor.get_cut_buffer().add (what_we_got);
-                       _session.add_command(new MementoCommand<AutomationList>(alist, before, alist.get_state()));
+                       _session.add_command(new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
                        ret = true;
                }
                break;
@@ -494,7 +494,7 @@ AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& sel
 
        case Clear:
                if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) {
-                       _session.add_command(new MementoCommand<AutomationList>(alist, before, alist.get_state()));
+                       _session.add_command(new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
                        delete what_we_got;
                        what_we_got = 0;
                        ret = true;
@@ -526,7 +526,7 @@ AutomationTimeAxisView::reset_objects_one (AutomationLine& line, PointSelection&
 {
        AutomationList& alist (line.the_list());
 
-       _session.add_command (new MementoUndoCommand<AutomationList>(alist, alist.get_state()));
+       _session.add_command (new MementoCommand<AutomationList>(alist, &alist.get_state(), 0));
 
        for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) {
 
@@ -569,7 +569,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
                case Cut:
                        if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
                                editor.get_cut_buffer().add (what_we_got);
-                               _session.add_command (new MementoCommand<AutomationList>(alist, before, alist.get_state()));
+                               _session.add_command (new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
                                ret = true;
                        }
                        break;
@@ -581,7 +581,7 @@ AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointS
                        
                case Clear:
                        if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) {
-                               _session.add_command (new MementoCommand<AutomationList>(alist, before, alist.get_state()));
+                               _session.add_command (new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
                                delete what_we_got;
                                what_we_got = 0;
                                ret = true;
@@ -640,7 +640,7 @@ AutomationTimeAxisView::paste_one (AutomationLine& line, jack_nframes_t pos, flo
 
         XMLNode &before = alist.get_state();
        alist.paste (copy, pos, times);
-       _session.add_command (new MementoCommand<AutomationList>(alist, before, alist.get_state()));
+       _session.add_command (new MementoCommand<AutomationList>(alist, &before, &alist.get_state()));
 
        return true;
 }
index 12b7d32188d38d1fda1ea5d6ea60430381a096cf..4ae8f8d46e597ce0e15818c0d615f96e06336834 100644 (file)
@@ -84,8 +84,6 @@ class AxisView : public virtual Selectable
 
        Gtk::Label name_label;
 
-       bool _selected;
-
        bool _marked_for_display;
        
 }; /* class AxisView */
index 5c3847730c1720cc7495414ebf105af8dfbac0f5..eceaf24d38107e6b6517f9fba7a8e784ebb3a22f 100644 (file)
@@ -705,6 +705,7 @@ Editor::Editor (AudioEngine& eng)
        ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
        constructed = true;
        instant_save ();
+
 }
 
 Editor::~Editor()
@@ -1339,6 +1340,9 @@ Editor::connect_to_session (Session *t)
                no_route_list_redisplay = false;
                redisplay_route_list ();
        }
+
+        /* register for undo history */
+        session->register_with_memento_command_factory(_id, this);
 }
 
 void
@@ -1592,7 +1596,7 @@ Editor::build_track_region_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview);
 
        if (atv) {
-               Diskstream* ds;
+               boost::shared_ptr<Diskstream> ds;
                Playlist* pl;
                
                if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
@@ -1619,7 +1623,7 @@ Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
        AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_axisview);
 
        if (atv) {
-               Diskstream* ds;
+               boost::shared_ptr<Diskstream> ds;
                Playlist* pl;
                AudioPlaylist* apl;
 
@@ -2888,7 +2892,7 @@ void
 Editor::commit_reversible_command ()
 {
        if (session) {
-               session->commit_reversible_command (new MementoCommand<Editor>(*this, *before, get_state()));
+               session->commit_reversible_command (new MementoCommand<Editor>(*this, before, &get_state()));
        }
 }
 
@@ -3016,7 +3020,7 @@ Editor::mapped_set_selected_regionview_from_click (RouteTimeAxisView& tv, uint32
        Playlist* pl;
        vector<Region*> results;
        RegionView* marv;
-       Diskstream* ds;
+       boost::shared_ptr<Diskstream> ds;
 
        if ((ds = tv.get_diskstream()) == 0) {
                /* bus */
@@ -3242,7 +3246,7 @@ Editor::set_selected_regionview_from_region_list (Region& region, Selection::Ope
                        Playlist* pl;
                        vector<Region*> results;
                        RegionView* marv;
-                       Diskstream* ds;
+                       boost::shared_ptr<Diskstream> ds;
                        
                        if ((ds = tatv->get_diskstream()) == 0) {
                                /* bus */
@@ -3750,10 +3754,12 @@ Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
 void
 Editor::set_zoom_focus (ZoomFocus f)
 {
+       vector<string> txt = internationalize (zoom_focus_strings);
+       zoom_focus_selector.set_active_text (txt[(int)f]);
+       
        if (zoom_focus != f) {
                zoom_focus = f;
-               vector<string> txt = internationalize (zoom_focus_strings);
-               zoom_focus_selector.set_active_text (txt[(int)f]);
+
                ZoomFocusChanged (); /* EMIT_SIGNAL */
 
                instant_save ();
index 40ece795b1872893956a414bc95c2e3801774ee6..970acdc3a90910d62a7cdcee8f4c42d5e0be15a5 100644 (file)
@@ -466,7 +466,7 @@ class Editor : public PublicEditor
        void add_crossfade_context_items (AudioStreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many);
        void add_selection_context_items (Gtk::Menu_Helpers::MenuList&);
 
-       void handle_new_route (boost::shared_ptr<ARDOUR::Route>);
+       void handle_new_route (ARDOUR::Session::RouteList&);
        void remove_route (TimeAxisView *);
        bool route_removal;
 
index de256ce0e64ae07517adfdbfa1002724a98ac1c2..2b704e73721536ca3d9b789f1502f7ed2e60013a 100644 (file)
@@ -318,13 +318,13 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
                
        case ImportToTrack:
                if (track) {
-                       Playlist* playlist  = track->diskstream().playlist();
+                       Playlist* playlist  = track->diskstream()->playlist();
                        
                        AudioRegion* copy = new AudioRegion (region);
                        begin_reversible_command (_("insert sndfile"));
                         XMLNode &before = playlist->get_state();
                        playlist->add_region (*copy, pos);
-                       session->add_command (new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+                       session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
                        commit_reversible_command ();
 
                        pos += region.length();
@@ -333,17 +333,21 @@ Editor::finish_bringing_in_audio (AudioRegion& region, uint32_t in_chans, uint32
                
        case ImportAsTrack:
        { 
-               boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Normal));
-               copy = new AudioRegion (region);
-               at->diskstream().playlist()->add_region (*copy, pos);
+               list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Normal, 1));
+               if (!at.empty()) {
+                       copy = new AudioRegion (region);
+                       at.front()->diskstream()->playlist()->add_region (*copy, pos);
+               }
                break;
        }
 
        case ImportAsTapeTrack:
        {
-               boost::shared_ptr<AudioTrack> at (session->new_audio_track (in_chans, out_chans, Destructive));
-               copy = new AudioRegion (region);
-               at->diskstream().playlist()->add_region (*copy, pos);
+               list<boost::shared_ptr<AudioTrack> > at (session->new_audio_track (in_chans, out_chans, Destructive));
+               if (!at.empty()) {
+                       copy = new AudioRegion (region);
+                       at.front()->diskstream()->playlist()->add_region (*copy, pos);
+               }
                break;
        }
        }
index f48d860d15d54eb1bd01d50902cbd99e734310c8..95289c7f5a52fecfe33e7f31f5db290c37f62c47 100644 (file)
@@ -108,7 +108,7 @@ Editor::kbd_mute_unmute_region ()
            entered_regionview->region().set_muted (!entered_regionview->region().muted());
                
                XMLNode &after = entered_regionview->region().playlist()->get_state();
-               session->add_command (new MementoCommand<ARDOUR::Playlist>(*(entered_regionview->region().playlist()), before, after));
+               session->add_command (new MementoCommand<ARDOUR::Playlist>(*(entered_regionview->region().playlist()), &before, &after));
                commit_reversible_command();
        }
 }
index ccc1415888449f1c92bfac39f810de0106c48f25..40f00c2e109be2e24c8621f4badc5a0dec96e8f4 100644 (file)
@@ -294,7 +294,7 @@ Editor::mouse_add_new_marker (jack_nframes_t where)
                 XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
                 XMLNode &after = session->locations()->get_state();
-               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
                session->commit_reversible_command ();
        }
 }
@@ -334,7 +334,7 @@ Editor::really_remove_marker (Location* loc)
        XMLNode &before = session->locations()->get_state();
        session->locations()->remove (loc);
        XMLNode &after = session->locations()->get_state();
-       session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
        session->commit_reversible_command ();
        return FALSE;
 }
@@ -847,7 +847,7 @@ Editor::marker_menu_rename ()
        loc->set_name (txt);
        
         XMLNode &after = session->locations()->get_state();
-       session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
        commit_reversible_command ();
 }
 
@@ -876,14 +876,14 @@ Editor::new_transport_marker_menu_set_loop ()
                session->locations()->add (loc, true);
                session->set_auto_loop_location (loc);
                 XMLNode &after = session->locations()->get_state();
-               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
        }
        else {
                 XMLNode &before = tll->get_state();
                tll->set_hidden (false, this);
                tll->set (temp_location->start(), temp_location->end());
                 XMLNode &after = tll->get_state();
-                session->add_command (new MementoCommand<Location>(*tll, before, after));
+                session->add_command (new MementoCommand<Location>(*tll, &before, &after));
        }
        
        commit_reversible_command ();
@@ -904,13 +904,13 @@ Editor::new_transport_marker_menu_set_punch ()
                session->locations()->add (tpl, true);
                session->set_auto_punch_location (tpl);
                 XMLNode &after = session->locations()->get_state();
-               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
        } else {
                 XMLNode &before = tpl->get_state();
                tpl->set_hidden(false, this);
                tpl->set(temp_location->start(), temp_location->end());
                 XMLNode &after = tpl->get_state();
-                session->add_command (new MementoCommand<Location>(*tpl, before, after));
+                session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
        }
        
        commit_reversible_command ();
index eb0bd432e3dab127db026e4e134e93f74bb7bf7a..df2c1d101c51eb5cba8443e3da65e9c444a39063 100644 (file)
@@ -1825,8 +1825,8 @@ Editor::fade_in_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* even
 
         XMLNode &after = arv->audio_region().get_state();
         session->add_command(new MementoCommand<ARDOUR::AudioRegion>(arv->audio_region(),
-                                                                     before,
-                                                                     after));
+                                                                     &before,
+                                                                     &after));
        commit_reversible_command ();
        fade_in_drag_motion_callback (item, event);
 }
@@ -1921,7 +1921,7 @@ Editor::fade_out_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* eve
        arv->audio_region().set_fade_out_length (fade_length);
 
         XMLNode &after = arv->region().get_state();
-        session->add_command(new MementoCommand<ARDOUR::Region>(arv->region(), before, after));
+        session->add_command(new MementoCommand<ARDOUR::Region>(arv->region(), &before, &after));
        commit_reversible_command ();
 
        fade_out_drag_motion_callback (item, event);
@@ -2176,7 +2176,7 @@ Editor::marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
        }
 
        XMLNode &after = session->locations()->get_state();
-       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
        commit_reversible_command ();
        
        marker_drag_line->hide();
@@ -2293,7 +2293,7 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
                 XMLNode &before = map.get_state();
                map.add_meter (marker->meter(), when);
                XMLNode &after = map.get_state();
-                session->add_command(new MementoCommand<TempoMap>(map, before, after));
+                session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
                commit_reversible_command ();
                
                // delete the dummy marker we used for visual representation of copying.
@@ -2304,7 +2304,7 @@ Editor::meter_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
                XMLNode &before = map.get_state();
                map.move_meter (marker->meter(), when);
                XMLNode &after = map.get_state();
-                session->add_command(new MementoCommand<TempoMap>(map, before, after));
+                session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
                commit_reversible_command ();
        }
 }
@@ -2425,7 +2425,7 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
                XMLNode &before = map.get_state();
                map.add_tempo (marker->tempo(), when);
                XMLNode &after = map.get_state();
-               session->add_command (new MementoCommand<TempoMap>(map, before, after));
+               session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
                commit_reversible_command ();
                
                // delete the dummy marker we used for visual representation of copying.
@@ -2436,7 +2436,7 @@ Editor::tempo_marker_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent*
                 XMLNode &before = map.get_state();
                map.move_tempo (marker->tempo(), when);
                 XMLNode &after = map.get_state();
-                session->add_command (new MementoCommand<TempoMap>(map, before, after));
+                session->add_command (new MementoCommand<TempoMap>(map, &before, &after));
                commit_reversible_command ();
        }
 }
@@ -2800,7 +2800,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        
                        insert_result = affected_playlists.insert (to_playlist);
                        if (insert_result.second) {
-                               session->add_command (new MementoUndoCommand<Playlist>(*to_playlist, to_playlist->get_state()));
+                               session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
                        }
                        
                        latest_regionview = 0;
@@ -3238,7 +3238,7 @@ Editor::region_drag_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                                        insert_result = motion_frozen_playlists.insert (pl);
                                        if (insert_result.second) {
                                                pl->freeze();
-                                               session->add_command(new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
+                                               session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
                                        }
                                }
                        }
@@ -3366,7 +3366,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
                        insert_result = motion_frozen_playlists.insert(to_playlist);
                        if (insert_result.second) {
                                to_playlist->freeze();
-                                session->add_command(new MementoUndoCommand<Playlist>(*to_playlist, to_playlist->get_state()));
+                                session->add_command(new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
                        }
 
                }
@@ -3448,7 +3448,7 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
   out:
        for (set<Playlist*>::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
                (*p)->thaw ();
-               session->add_command (new MementoRedoCommand<Playlist>(*(*p), (*p)->get_state()));
+               session->add_command (new MementoCommand<Playlist>(*(*p), 0, & (*p)->get_state()));
        }
 
        motion_frozen_playlists.clear ();
@@ -3643,10 +3643,10 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
 
        Playlist* playlist = clicked_axisview->playlist();
 
-        before = &(playlist->get_state());
+        XMLNode *before = &(playlist->get_state());
        clicked_axisview->playlist()->add_region (*region, selection->time[clicked_selection].start);
-        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));
 
        commit_reversible_command ();
        
@@ -4013,7 +4013,7 @@ Editor::trim_motion_callback (ArdourCanvas::Item* item, GdkEvent* event)
                        Playlist * pl = (*i)->region().playlist();
                        insert_result = motion_frozen_playlists.insert (pl);
                        if (insert_result.second) {
-                                session->add_command(new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
+                                session->add_command(new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
                        }
                }
        }
@@ -4203,7 +4203,7 @@ Editor::trim_finished_callback (ArdourCanvas::Item* item, GdkEvent* event)
                
                for (set<Playlist*>::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) {
                        //(*p)->thaw ();
-                        session->add_command (new MementoRedoCommand<Playlist>(*(*p), (*p)->get_state()));
+                        session->add_command (new MementoCommand<Playlist>(*(*p), 0, &(*p)->get_state()));
                 }
                
                motion_frozen_playlists.clear ();
@@ -4241,7 +4241,7 @@ Editor::point_trim (GdkEvent* event)
                                         XMLNode &before = pl->get_state();
                                        (*i)->region().trim_front (new_bound, this);    
                                         XMLNode &after = pl->get_state();
-                                        session->add_command(new MementoCommand<Playlist>(*pl, before, after));
+                                        session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
                                }
                        }
 
@@ -4252,7 +4252,7 @@ Editor::point_trim (GdkEvent* event)
                                XMLNode &before = pl->get_state();
                                rv->region().trim_front (new_bound, this);      
                                 XMLNode &after = pl->get_state();
-                               session->add_command(new MementoCommand<Playlist>(*pl, before, after));
+                               session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
                        }
                }
 
@@ -4272,7 +4272,7 @@ Editor::point_trim (GdkEvent* event)
                                        XMLNode &before = pl->get_state();
                                        (*i)->region().trim_end (new_bound, this);
                                        XMLNode &after = pl->get_state();
-                                       session->add_command(new MementoCommand<Playlist>(*pl, before, after));
+                                       session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
                                }
                        }
 
@@ -4283,7 +4283,7 @@ Editor::point_trim (GdkEvent* event)
                                XMLNode &before = pl->get_state();
                                rv->region().trim_end (new_bound, this);
                                 XMLNode &after = pl->get_state();
-                               session->add_command (new MementoCommand<Playlist>(*pl, before, after));
+                               session->add_command (new MementoCommand<Playlist>(*pl, &before, &after));
                        }
                }
 
@@ -4306,7 +4306,7 @@ Editor::thaw_region_after_trim (RegionView& rv)
 
        region.thaw (_("trimmed region"));
         XMLNode &after = region.playlist()->get_state();
-       session->add_command (new MementoRedoCommand<Playlist>(*(region.playlist()), after));
+       session->add_command (new MementoCommand<Playlist>(*(region.playlist()), 0, &after));
 
        AudioRegionView* arv = dynamic_cast<AudioRegionView*>(&rv);
        if (arv)
@@ -4451,7 +4451,7 @@ Editor::end_range_markerbar_op (ArdourCanvas::Item* item, GdkEvent* event)
                        newloc = new Location(temp_location->start(), temp_location->end(), "unnamed", Location::IsRangeMarker);
                        session->locations()->add (newloc, true);
                         XMLNode &after = session->locations()->get_state();
-                       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+                       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
                        commit_reversible_command ();
                        
                        range_bar_drag_rect->hide();
@@ -4834,7 +4834,7 @@ Editor::mouse_brush_insert_region (RegionView* rv, jack_nframes_t pos)
         XMLNode &before = playlist->get_state();
        playlist->add_region (*(new AudioRegion (arv->audio_region())), (jack_nframes_t) (pos * speed));
         XMLNode &after = playlist->get_state();
-       session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
+       session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
        
        // playlist is frozen, so we have to update manually
        
index 7115bfe634fc7eb37596dff6d97951f425af8557..2532222c0de3b0c7ab15eb94591d59fcc703f30c 100644 (file)
@@ -213,7 +213,7 @@ Editor::split_regions_at (jack_nframes_t where, RegionSelection& regions)
                         XMLNode &before = pl->get_state();
                        pl->split_region ((*a)->region(), where);
                         XMLNode &after = pl->get_state();
-                        session->add_command(new MementoCommand<Playlist>(*pl, before, after));
+                        session->add_command(new MementoCommand<Playlist>(*pl, &before, &after));
                }
 
                a = tmp;
@@ -236,7 +236,7 @@ Editor::remove_clicked_region ()
         XMLNode &before = playlist->get_state();
        playlist->remove_region (&clicked_regionview->region());
         XMLNode &after = playlist->get_state();
-       session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
+       session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
        commit_reversible_command ();
 }
 
@@ -412,7 +412,7 @@ Editor::nudge_forward (bool next)
                         XMLNode &before = r.playlist()->get_state();
                        r.set_position (r.position() + distance, this);
                         XMLNode &after = r.playlist()->get_state();
-                       session->add_command (new MementoCommand<Playlist>(*(r.playlist()), before, after));
+                       session->add_command (new MementoCommand<Playlist>(*(r.playlist()), &before, &after));
                }
 
                commit_reversible_command ();
@@ -452,7 +452,7 @@ Editor::nudge_backward (bool next)
                                r.set_position (0, this);
                        }
                         XMLNode &after = r.playlist()->get_state();
-                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
+                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), &before, &after));
                }
 
                commit_reversible_command ();
@@ -488,7 +488,7 @@ Editor::nudge_forward_capture_offset ()
                        XMLNode &before = r.playlist()->get_state();
                        r.set_position (r.position() + distance, this);
                        XMLNode &after = r.playlist()->get_state();
-                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
+                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), &before, &after));
                }
 
                commit_reversible_command ();
@@ -520,7 +520,7 @@ Editor::nudge_backward_capture_offset ()
                                r.set_position (0, this);
                        }
                         XMLNode &after = r.playlist()->get_state();
-                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), before, after));
+                       session->add_command(new MementoCommand<Playlist>(*(r.playlist()), &before, &after));
                }
 
                commit_reversible_command ();
@@ -1300,7 +1300,7 @@ Editor::add_location_from_selection ()
         XMLNode &before = session->locations()->get_state();
        session->locations()->add (location, true);
         XMLNode &after = session->locations()->get_state();
-       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
        session->commit_reversible_command ();
 }
 
@@ -1314,7 +1314,7 @@ Editor::add_location_from_playhead_cursor ()
         XMLNode &before = session->locations()->get_state();
        session->locations()->add (location, true);
         XMLNode &after = session->locations()->get_state();
-       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
        session->commit_reversible_command ();
 }
 
@@ -1333,7 +1333,7 @@ Editor::add_location_from_audio_region ()
         XMLNode &before = session->locations()->get_state();
        session->locations()->add (location, true);
         XMLNode &after = session->locations()->get_state();
-       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
        session->commit_reversible_command ();
 }
 
@@ -1752,7 +1752,7 @@ Editor::clear_markers ()
                 XMLNode &before = session->locations()->get_state();
                session->locations()->clear_markers ();
                 XMLNode &after = session->locations()->get_state();
-               session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
                session->commit_reversible_command ();
        }
 }
@@ -1773,7 +1773,7 @@ Editor::clear_ranges ()
                if (punchloc) session->locations()->add (punchloc);
                
                 XMLNode &after = session->locations()->get_state();
-               session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
                session->commit_reversible_command ();
        }
 }
@@ -1785,7 +1785,7 @@ Editor::clear_locations ()
         XMLNode &before = session->locations()->get_state();
        session->locations()->clear ();
         XMLNode &after = session->locations()->get_state();
-       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
        session->commit_reversible_command ();
        session->locations()->clear ();
 }
@@ -1835,7 +1835,7 @@ Editor::insert_region_list_drag (AudioRegion& region, int x, int y)
        begin_reversible_command (_("insert dragged region"));
         XMLNode &before = playlist->get_state();
        playlist->add_region (*(new AudioRegion (region)), where, 1.0);
-       session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+       session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
        commit_reversible_command ();
 }
 
@@ -1871,7 +1871,7 @@ Editor::insert_region_list_selection (float times)
        begin_reversible_command (_("insert region"));
         XMLNode &before = playlist->get_state();
        playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times);
-       session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+       session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
        commit_reversible_command ();
 }
 
@@ -2311,7 +2311,7 @@ Editor::separate_region_from_selection ()
                                        }
 
                                        if (doing_undo) 
-                                            session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
+                                            session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
                                }
                        }
                }
@@ -2364,7 +2364,7 @@ Editor::separate_regions_using_location (Location& loc)
 
                                        playlist->partition ((jack_nframes_t)(loc.start() * speed), (jack_nframes_t)(loc.end() * speed), true);
                                        if (doing_undo) 
-                                            session->add_command(new MementoCommand<Playlist>(*playlist, *before, playlist->get_state()));
+                                            session->add_command(new MementoCommand<Playlist>(*playlist, before, &playlist->get_state()));
                                }
                        }
                }
@@ -2435,7 +2435,7 @@ Editor::crop_region_to_selection ()
                         XMLNode &before = (*i)->get_state();
                        region->trim_to (start, cnt, this);
                         XMLNode &after = (*i)->get_state();
-                       session->add_command (new MementoCommand<Playlist>(*(*i), before, after));
+                       session->add_command (new MementoCommand<Playlist>(*(*i), &before, &after));
                }
 
                commit_reversible_command ();
@@ -2477,7 +2477,7 @@ Editor::region_fill_track ()
 
                XMLNode &before = pl->get_state();
                pl->add_region (*(new AudioRegion (*ar)), ar->last_frame(), times);
-               session->add_command (new MementoCommand<Playlist>(*pl, before, pl->get_state()));
+               session->add_command (new MementoCommand<Playlist>(*pl, &before, &pl->get_state()));
        }
 
        commit_reversible_command ();
@@ -2527,7 +2527,7 @@ Editor::region_fill_selection ()
                
                 XMLNode &before = playlist->get_state();
                playlist->add_region (*(createRegion (*region)), start, times);
-               session->add_command (new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+               session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
        }
        
        commit_reversible_command ();                   
@@ -2545,7 +2545,7 @@ Editor::set_a_regions_sync_position (Region& region, jack_nframes_t position)
         XMLNode &before = region.playlist()->get_state();
        region.set_sync_position (position);
         XMLNode &after = region.playlist()->get_state();
-       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
        commit_reversible_command ();
 }
 
@@ -2566,7 +2566,7 @@ Editor::set_region_sync_from_edit_cursor ()
         XMLNode &before = region.playlist()->get_state();
        region.set_sync_position (edit_cursor->current_frame);
         XMLNode &after = region.playlist()->get_state();
-       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
        commit_reversible_command ();
 }
 
@@ -2579,7 +2579,7 @@ Editor::remove_region_sync ()
                 XMLNode &before = region.playlist()->get_state();
                region.clear_sync_position ();
                 XMLNode &after = region.playlist()->get_state();
-               session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+               session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
                commit_reversible_command ();
        }
 }
@@ -2595,7 +2595,7 @@ Editor::naturalize ()
                 XMLNode &before = (*i)->region().get_state();
                (*i)->region().move_to_natural_position (this);
                 XMLNode &after = (*i)->region().get_state();
-               session->add_command (new MementoCommand<Region>((*i)->region(), before, after));
+               session->add_command (new MementoCommand<Region>((*i)->region(), &before, &after));
        }
        commit_reversible_command ();
 }
@@ -2670,7 +2670,7 @@ Editor::align_selection_relative (RegionPoint point, jack_nframes_t position)
                }
 
                 XMLNode &after = region.playlist()->get_state();
-               session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+               session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
 
        }
 
@@ -2723,7 +2723,7 @@ Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t
        }
 
        XMLNode &after = region.playlist()->get_state();
-       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
 }      
 
 void
@@ -2748,7 +2748,7 @@ Editor::trim_region_to_edit_cursor ()
         XMLNode &before = region.playlist()->get_state();
        region.trim_end( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
         XMLNode &after = region.playlist()->get_state();
-       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
        commit_reversible_command ();
 }
 
@@ -2774,7 +2774,7 @@ Editor::trim_region_from_edit_cursor ()
         XMLNode &before = region.playlist()->get_state();
        region.trim_front ( session_frame_to_track_frame(edit_cursor->current_frame, speed), this);
         XMLNode &after = region.playlist()->get_state();
-       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), before, after));
+       session->add_command(new MementoCommand<Playlist>(*(region.playlist()), &before, &after));
        commit_reversible_command ();
 }
 
@@ -2889,7 +2889,7 @@ Editor::bounce_range_selection ()
                 XMLNode &before = playlist->get_state();
                atv->audio_track()->bounce_range (start, cnt, itt);
                 XMLNode &after = playlist->get_state();
-               session->add_command (new MementoCommand<Playlist> (*playlist, before, after));
+               session->add_command (new MementoCommand<Playlist> (*playlist, &before, &after));
        }
        
        commit_reversible_command ();
@@ -3007,7 +3007,7 @@ Editor::cut_copy_regions (CutCopyOp op)
                                insert_result = freezelist.insert (pl);
                                if (insert_result.second) {
                                        pl->freeze ();
-                                        session->add_command (new MementoUndoCommand<Playlist>(*pl, pl->get_state()));
+                                        session->add_command (new MementoCommand<Playlist>(*pl, &pl->get_state(), 0));
                                }
                        }
                }
@@ -3071,7 +3071,7 @@ Editor::cut_copy_regions (CutCopyOp op)
        
        for (set<Playlist*>::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) {
                (*pl)->thaw ();
-               session->add_command (new MementoRedoCommand<Playlist>(*(*pl), (*pl)->get_state()));
+               session->add_command (new MementoCommand<Playlist>(*(*pl), 0, &(*pl)->get_state()));
        }
 }
 
@@ -3186,7 +3186,7 @@ Editor::paste_named_selection (float times)
 
                 XMLNode &before = apl->get_state();
                apl->paste (**chunk, edit_cursor->current_frame, times);
-               session->add_command(new MementoCommand<AudioPlaylist>(*apl, before, apl->get_state()));
+               session->add_command(new MementoCommand<AudioPlaylist>(*apl, &before, &apl->get_state()));
 
                if (tmp != ns->playlists.end()) {
                        chunk = tmp;
@@ -3217,7 +3217,7 @@ Editor::duplicate_some_regions (RegionSelection& regions, float times)
                playlist = (*i)->region().playlist();
                 XMLNode &before = playlist->get_state();
                playlist->duplicate (r, r.last_frame(), times);
-               session->add_command(new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+               session->add_command(new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
 
                c.disconnect ();
 
@@ -3258,7 +3258,7 @@ Editor::duplicate_selection (float times)
                 XMLNode &before = playlist->get_state();
                playlist->duplicate (**ri, selection->time[clicked_selection].end, times);
                 XMLNode &after = playlist->get_state();
-               session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
+               session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
 
                ++ri;
                if (ri == new_regions.end()) {
@@ -3309,7 +3309,7 @@ Editor::clear_playlist (Playlist& playlist)
         XMLNode &before = playlist.get_state();
        playlist.clear ();
         XMLNode &after = playlist.get_state();
-       session->add_command (new MementoCommand<Playlist>(playlist, before, after));
+       session->add_command (new MementoCommand<Playlist>(playlist, &before, &after));
        commit_reversible_command ();
 }
 
@@ -3346,7 +3346,7 @@ Editor::nudge_track (bool use_edit_cursor, bool forwards)
                 XMLNode &before = playlist->get_state();
                playlist->nudge_after (start, distance, forwards);
                 XMLNode &after = playlist->get_state();
-               session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
+               session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
        }
        
        commit_reversible_command ();                   
@@ -3402,7 +3402,7 @@ Editor::normalize_region ()
                        continue;
                XMLNode &before = arv->region().get_state();
                arv->audio_region().normalize_to (0.0f);
-               session->add_command (new MementoCommand<Region>(arv->region(), before, arv->region().get_state()));
+               session->add_command (new MementoCommand<Region>(arv->region(), &before, &arv->region().get_state()));
        }
 
        commit_reversible_command ();
@@ -3429,7 +3429,7 @@ Editor::denormalize_region ()
                        continue;
                XMLNode &before = arv->region().get_state();
                arv->audio_region().set_scale_amplitude (1.0f);
-               session->add_command (new MementoCommand<Region>(arv->region(), before, arv->region().get_state()));
+               session->add_command (new MementoCommand<Region>(arv->region(), &before, &arv->region().get_state()));
        }
 
        commit_reversible_command ();
@@ -3476,7 +3476,7 @@ Editor::apply_filter (AudioFilter& filter, string command)
                         XMLNode &before = playlist->get_state();
                        playlist->replace_region (arv->region(), *(filter.results.front()), arv->region().position());
                         XMLNode &after = playlist->get_state();
-                       session->add_command(new MementoCommand<Playlist>(*playlist, before, after));
+                       session->add_command(new MementoCommand<Playlist>(*playlist, &before, &after));
                } else {
                        goto out;
                }
index bb38953038a9613a60349bed0bc6b8efec820635..512e2ecef141f10b914d59de11bfc73f62197754 100644 (file)
@@ -30,6 +30,8 @@
 #include "mixer_strip.h"
 #include "gui_thread.h"
 
+#include <pbd/unknown_type.h>
+
 #include <ardour/route.h>
 
 #include "i18n.h"
@@ -41,79 +43,81 @@ using namespace Gtk;
 
 
 void
-Editor::handle_new_route (boost::shared_ptr<Route> route)
+Editor::handle_new_route (Session::RouteList& routes)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), route));
-
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::handle_new_route), routes));
+       
        TimeAxisView *tv;
+       RouteTimeAxisView *rtv;
        TreeModel::Row parent;
        TreeModel::Row row;
 
-       if (route->hidden()) {
-               return;
-       }
+       for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
+               boost::shared_ptr<Route> route = (*x);
 
-       // FIXME
-       DataType type = route->default_type();
-       assert(type == ARDOUR::DataType::AUDIO || type == ARDOUR::DataType::MIDI);
-       
-       if (type == ARDOUR::DataType::AUDIO)
-               tv = new AudioTimeAxisView (*this, *session, route, track_canvas);
-       else
-               tv = new MidiTimeAxisView (*this, *session, route, track_canvas);
-       
+               if (route->hidden()) {
+                       return;
+               }
+               
+               if (route->default_type() == ARDOUR::DataType::AUDIO)
+                       tv = new AudioTimeAxisView (*this, *session, route, track_canvas);
+               else if (route->default_type() == ARDOUR::DataType::MIDI)
+                       tv = new MidiTimeAxisView (*this, *session, route, track_canvas);
+               else
+                       throw unknown_type();
+               
 #if 0
-       if (route_display_model->children().size() == 0) {
+               if (route_display_model->children().size() == 0) {
+                       
+                       /* set up basic entries */
+                       
+                       TreeModel::Row row;
+                       
+                       row = *(route_display_model->append());  // path = "0"
+                       row[route_display_columns.text] = _("Busses");
+                       row[route_display_columns.tv] = 0;
+                       row = *(route_display_model->append());  // path = "1"
+                       row[route_display_columns.text] = _("Tracks");
+                       row[route_display_columns.tv] = 0;
+                       
+               }
                
-                /* set up basic entries */
-
-               TreeModel::Row row;
+               if (dynamic_cast<AudioTrack*>(route.get()) != 0) {
+                       TreeModel::iterator iter = route_display_model->get_iter ("1");  // audio tracks 
+                       parent = *iter;
+               } else {
+                       TreeModel::iterator iter = route_display_model->get_iter ("0");  // busses
+                       parent = *iter;
+               }
                
-               row = *(route_display_model->append());  // path = "0"
-               row[route_display_columns.text] = _("Busses");
-               row[route_display_columns.tv] = 0;
-               row = *(route_display_model->append());  // path = "1"
-               row[route_display_columns.text] = _("Tracks");
-               row[route_display_columns.tv] = 0;
-
-       }
-
-       if (dynamic_cast<AudioTrack*>(route.get()) != 0) {
-               TreeModel::iterator iter = route_display_model->get_iter ("1");  // audio tracks 
-               parent = *iter;
-       } else {
-               TreeModel::iterator iter = route_display_model->get_iter ("0");  // busses
-               parent = *iter;
-       }
-       
-
-       row = *(route_display_model->append (parent.children()));
+               
+               row = *(route_display_model->append (parent.children()));
 #else 
-       row = *(route_display_model->append ());
+               row = *(route_display_model->append ());
 #endif
-
-       row[route_display_columns.text] = route->name();
-       row[route_display_columns.visible] = tv->marked_for_display();
-       row[route_display_columns.tv] = tv;
-       
-       track_views.push_back (tv);
-
-       ignore_route_list_reorder = true;
-       
-       RouteTimeAxisView* rtv = NULL;
-       if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) != 0) {
-               /* added a new fresh one at the end */
-               if (rtv->route()->order_key(N_("editor")) == -1) {
-                       rtv->route()->set_order_key (N_("editor"), route_display_model->children().size()-1);
+               
+               row[route_display_columns.text] = route->name();
+               row[route_display_columns.visible] = tv->marked_for_display();
+               row[route_display_columns.tv] = tv;
+               
+               track_views.push_back (tv);
+               
+               ignore_route_list_reorder = true;
+               
+               if ((rtv = dynamic_cast<RouteTimeAxisView*> (tv)) != 0) {
+                       /* added a new fresh one at the end */
+                       if (rtv->route()->order_key(N_("editor")) == -1) {
+                               rtv->route()->set_order_key (N_("editor"), route_display_model->children().size()-1);
+                       }
                }
+               
+               ignore_route_list_reorder = false;
+               
+               route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes));
+               
+               tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv));
        }
 
-       ignore_route_list_reorder = false;
-       
-       route->gui_changed.connect (mem_fun(*this, &Editor::handle_gui_changes));
-
-       tv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), tv));
-       
        editor_mixer_button.set_sensitive(true);
 }
 
@@ -190,9 +194,9 @@ Editor::hide_track_in_display (TimeAxisView& tv)
                }
        }
 
-       AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&tv);
+       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
 
-       if (atv && current_mixer_strip && (atv->route() == current_mixer_strip->route())) {
+       if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
                // this will hide the mixer strip
                set_selected_mixer_strip (tv);
        }
@@ -234,7 +238,7 @@ Editor::redisplay_route_list ()
 
        for (n = 0, order = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
                TimeAxisView *tv = (*i)[route_display_columns.tv];
-               AudioTimeAxisView* at; 
+               RouteTimeAxisView* rt; 
 
                if (tv == 0) {
                        // just a "title" row
@@ -247,8 +251,8 @@ Editor::redisplay_route_list ()
                           to tracks.
                        */
                        
-                       if ((at = dynamic_cast<AudioTimeAxisView*> (tv)) != 0) {
-                               at->route()->set_order_key (N_("editor"), order);
+                       if ((rt = dynamic_cast<RouteTimeAxisView*> (tv)) != 0) {
+                               rt->route()->set_order_key (N_("editor"), order);
                                ++order;
                        }
                }
@@ -500,9 +504,7 @@ Editor::initial_route_list_display ()
 
        route_display_model->clear ();
 
-       for (Session::RouteList::iterator i = r.begin(); i != r.end(); ++i) {
-               handle_new_route (*i);
-       }
+       handle_new_route (r);
 
        no_route_list_redisplay = false;
 
index ff99c76351d0fd71177e08a6c6f5301670c1e6a6..e5b1a67cf3fb8ac73d097635450addf30fa0560f 100644 (file)
@@ -278,7 +278,7 @@ Editor::mouse_add_new_tempo_event (jack_nframes_t frame)
         XMLNode &before = map.get_state();
        map.add_tempo (Tempo (bpm), requested);
         XMLNode &after = map.get_state();
-       session->add_command(new MementoCommand<TempoMap>(map, before, after));
+       session->add_command(new MementoCommand<TempoMap>(map, &before, &after));
        commit_reversible_command ();
        
        map.dump (cerr);
@@ -318,7 +318,7 @@ Editor::mouse_add_new_meter_event (jack_nframes_t frame)
        begin_reversible_command (_("add meter mark"));
         XMLNode &before = map.get_state();
        map.add_meter (Meter (bpb, note_type), requested);
-       session->add_command(new MementoCommand<TempoMap>(map, before, map.get_state()));
+       session->add_command(new MementoCommand<TempoMap>(map, &before, &map.get_state()));
        commit_reversible_command ();
        
        map.dump (cerr);
@@ -370,7 +370,7 @@ Editor::edit_meter_section (MeterSection* section)
         XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().replace_meter (*section, Meter (bpb, note_type));
         XMLNode &after = session->tempo_map().get_state();
-       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), before, after));
+       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
        commit_reversible_command ();
 }
 
@@ -400,7 +400,7 @@ Editor::edit_tempo_section (TempoSection* section)
        session->tempo_map().replace_tempo (*section, Tempo (bpm));
        session->tempo_map().move_tempo (*section, when);
         XMLNode &after = session->tempo_map().get_state();
-       session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), before, after));
+       session->add_command (new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
        commit_reversible_command ();
 }
 
@@ -449,7 +449,7 @@ Editor::real_remove_tempo_marker (TempoSection *section)
        XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().remove_tempo (*section);
        XMLNode &after = session->tempo_map().get_state();
-       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), before, after));
+       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
        commit_reversible_command ();
 
        return FALSE;
@@ -483,7 +483,7 @@ Editor::real_remove_meter_marker (MeterSection *section)
        XMLNode &before = session->tempo_map().get_state();
        session->tempo_map().remove_meter (*section);
        XMLNode &after = session->tempo_map().get_state();
-       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), before, after));
+       session->add_command(new MementoCommand<TempoMap>(session->tempo_map(), &before, &after));
        commit_reversible_command ();
        return FALSE;
 }
index 3fe0023d07701cc326c5d769f1ef5757674ae275..caa9698b8c8679ded73f28423ec6342b38bf5e15 100644 (file)
@@ -188,7 +188,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
                        continue;
                }
        
-               if ((playlist = t->diskstream().playlist()) == 0) {
+               if ((playlist = t->diskstream()->playlist()) == 0) {
                        i = tmp;
                        continue;
                }
@@ -210,7 +210,7 @@ Editor::do_timestretch (TimeStretchDialog& dialog)
                XMLNode &before = playlist->get_state();
                playlist->replace_region (region, *new_region, region.position());
                XMLNode &after = playlist->get_state();
-               session->add_command (new MementoCommand<Playlist>(*playlist, before, after));
+               session->add_command (new MementoCommand<Playlist>(*playlist, &before, &after));
 
                i = tmp;
        }
index c86c1390f33dd96ac7c44d86ac0c41b0b0d62c62..47657e3292b5981a1852418c775a3ee6bbe2054f 100644 (file)
@@ -67,7 +67,7 @@ GainAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkE
         XMLNode &before = curve.get_state();
        curve.add (when, y);
         XMLNode &after = curve.get_state();
-        _session.add_command(new MementoCommand<ARDOUR::Curve>(curve, before, after));
+        _session.add_command(new MementoCommand<ARDOUR::Curve>(curve, &before, &after));
        _session.commit_reversible_command ();
        _session.set_dirty ();
 }
index deb4c1da36bf5408714863a7230f22361d83ddd2..12e7079de26358a5ec345ef05c103de50e5a2100 100644 (file)
@@ -658,7 +658,7 @@ gint LocationUI::do_location_remove (ARDOUR::Location *loc)
        XMLNode &before = session->locations()->get_state();
        session->locations()->remove (loc);
        XMLNode &after = session->locations()->get_state();
-       session->add_command(new MementoCommand<Locations>(*(session->locations()), before, after));
+       session->add_command(new MementoCommand<Locations>(*(session->locations()), &before, &after));
        session->commit_reversible_command ();
 
        return FALSE;
@@ -777,7 +777,7 @@ LocationUI::add_new_location()
                XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
                XMLNode &after = session->locations()->get_state();
-               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
                session->commit_reversible_command ();
        }
        
@@ -794,7 +794,7 @@ LocationUI::add_new_range()
                XMLNode &before = session->locations()->get_state();
                session->locations()->add (location, true);
                XMLNode &after = session->locations()->get_state();
-               session->add_command (new MementoCommand<Locations>(*(session->locations()), before, after));
+               session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
                session->commit_reversible_command ();
        }
 }
index f422005a5de36e5592d999d0b3ac97a2370eea0b..47148446eb20feaf971d40294e15e3bbe8046721 100644 (file)
@@ -163,7 +163,8 @@ MidiStreamView::setup_rec_box ()
 
                                MidiRegion::SourceList sources;
 
-                               MidiDiskstream* mds = dynamic_cast<MidiDiskstream*>(_trackview.get_diskstream());
+                               // FIXME
+                               boost::shared_ptr<MidiDiskstream> mds = boost::dynamic_pointer_cast<MidiDiskstream>(_trackview.get_diskstream());
                                assert(mds);
 
                                sources.push_back((Source*)mds->write_source());
@@ -189,8 +190,8 @@ MidiStreamView::setup_rec_box ()
                        /* start a new rec box */
 
                        MidiTrack* mt = _trackview.midi_track(); /* we know what it is already */
-                       MidiDiskstream& ds = mt->midi_diskstream();
-                       jack_nframes_t frame_pos = ds.current_capture_start ();
+                       boost::shared_ptr<MidiDiskstream> ds = mt->midi_diskstream();
+                       jack_nframes_t frame_pos = ds->current_capture_start ();
                        gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos);
                        gdouble xend;
                        uint32_t fill_color;
index c2eb588b2f2744865d085574155f36aff585e3cf..84fade54726e69085f8fae31c3e50236718e4790 100644 (file)
@@ -251,38 +251,42 @@ Mixer_UI::show_window ()
 }
 
 void
-Mixer_UI::add_strip (boost::shared_ptr<Route> route)
+Mixer_UI::add_strip (Session::RouteList& routes)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_strip), route));
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &Mixer_UI::add_strip), routes));
        
        MixerStrip* strip;
 
-       if (route->hidden()) {
-               return;
-       }
-
-       strip = new MixerStrip (*this, *session, route);
-       strips.push_back (strip);
-
-       strip->set_width (_strip_width);
-       show_strip (strip);
-
-       no_track_list_redisplay = true;
-
-       TreeModel::Row row = *(track_model->append());
-       row[track_columns.text] = route->name();
-
-       row[track_columns.visible] = true;
-       row[track_columns.route] = route;
-       row[track_columns.strip] = strip;
-
-       no_track_list_redisplay = false;
-       redisplay_track_list ();
-
-       route->name_changed.connect (bind (mem_fun(*this, &Mixer_UI::strip_name_changed), strip));
-       strip->GoingAway.connect (bind (mem_fun(*this, &Mixer_UI::remove_strip), strip));
+       for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
+               boost::shared_ptr<Route> route = (*x);
 
-       strip->signal_button_release_event().connect (bind (mem_fun(*this, &Mixer_UI::strip_button_release_event), strip));
+               if (route->hidden()) {
+                       return;
+               }
+               
+               strip = new MixerStrip (*this, *session, route);
+               strips.push_back (strip);
+               
+               strip->set_width (_strip_width);
+               show_strip (strip);
+               
+               no_track_list_redisplay = true;
+               
+               TreeModel::Row row = *(track_model->append());
+               row[track_columns.text] = route->name();
+               
+               row[track_columns.visible] = true;
+               row[track_columns.route] = route;
+               row[track_columns.strip] = strip;
+               
+               no_track_list_redisplay = false;
+               redisplay_track_list ();
+               
+               route->name_changed.connect (bind (mem_fun(*this, &Mixer_UI::strip_name_changed), strip));
+               strip->GoingAway.connect (bind (mem_fun(*this, &Mixer_UI::remove_strip), strip));
+               
+               strip->signal_button_release_event().connect (bind (mem_fun(*this, &Mixer_UI::strip_button_release_event), strip));
+       }
 }
 
 void
@@ -623,9 +627,7 @@ Mixer_UI::initial_track_display ()
 
        track_model->clear ();
 
-       for (Session::RouteList::iterator i = copy.begin(); i != copy.end(); ++i) {
-               add_strip (*i);
-       }
+       add_strip (copy);
 
        no_track_list_redisplay = false;
 
index 6fe41204279cc840ce0a12007cec0c729d3d1418..77021dc8feb5b9795df0205a3f4df637ae6bcbfb 100644 (file)
@@ -111,7 +111,7 @@ class Mixer_UI : public Gtk::Window
 
        bool strip_scroller_button_release (GdkEventButton*);
 
-       void add_strip (boost::shared_ptr<ARDOUR::Route>);
+       void add_strip (ARDOUR::Session::RouteList&);
        void remove_strip (MixerStrip *);
 
        void hide_all_strips (bool with_select);
index ec884151b5d46653fb5161888ab996d92af061a7..bbd4b3b06c31a48ae6c845b45c85f0dc5f1ab8a6 100644 (file)
@@ -92,7 +92,7 @@ PanAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item, GdkEv
        XMLNode &before = alist.get_state();
        alist.add (when, y);
        XMLNode &after = alist.get_state();
-        _session.add_command(new MementoCommand<AutomationList>(alist, before, after));
+        _session.add_command(new MementoCommand<AutomationList>(alist, &before, &after));
        _session.commit_reversible_command ();
        _session.set_dirty ();
 }
index 8eaac7cb9d3e74814db7bab3523fc1dd3075d03b..68227d193c281fb0f07dc2de54643dd247a9bfa9 100644 (file)
@@ -90,7 +90,7 @@ void
 PlaylistSelector::show_for (RouteUI* ruix)
 {
        vector<const char*> item;
-       Diskstream* this_ds;
+       boost::shared_ptr<Diskstream> this_ds;
        string str;
 
        rui = ruix;
@@ -116,7 +116,7 @@ PlaylistSelector::show_for (RouteUI* ruix)
        
        for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) {
 
-               Diskstream* ds = session->diskstream_by_id (x->first);
+               boost::shared_ptr<Diskstream> ds = session->diskstream_by_id (x->first);
 
                if (ds == 0) {
                        continue;
@@ -243,7 +243,7 @@ PlaylistSelector::selection_changed ()
                        return;
                }
                
-               at->diskstream().use_playlist (apl);
+               at->diskstream()->use_playlist (apl);
 
                hide ();
        }
index e527fd1d5e9123fee2cdc8e2e6389fd6da1b4ce7..f1e8eae9eb391a214e2f9ccd4ecf63568862cfee 100644 (file)
@@ -102,7 +102,7 @@ RedirectAutomationTimeAxisView::add_automation_event (ArdourCanvas::Item* item,
                 XMLNode &before = alist.get_state();
                alist.add (when, y);
                 XMLNode &after = alist.get_state();
-                _session.add_command(new MementoCommand<AutomationList>(alist, before, after));
+                _session.add_command(new MementoCommand<AutomationList>(alist, &before, &after));
                _session.commit_reversible_command ();
                _session.set_dirty ();
        }
index 0a4a3d29eaf48e47f9048b1e616a7c5b92c99c35..e2b1d6c8265b694ea7ec9a3944c7dc6e29d33e6e 100644 (file)
@@ -48,7 +48,7 @@ AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction)
 {
        AutomationLine::start_drag(cp,fraction);
        if (!rv.audio_region().envelope_active()) {
-                trackview.session().add_command(new MementoUndoCommand<AudioRegion>(rv.audio_region(), rv.audio_region().get_state()));
+                trackview.session().add_command(new MementoCommand<AudioRegion>(rv.audio_region(), &rv.audio_region().get_state(), 0));
                 rv.audio_region().set_envelope_active(false);
        }
 }
@@ -68,12 +68,12 @@ AudioRegionGainLine::remove_point (ControlPoint& cp)
                 XMLNode &before = rv.audio_region().get_state();
                rv.audio_region().set_envelope_active(true);
                 XMLNode &after = rv.audio_region().get_state();
-                trackview.session().add_command(new MementoCommand<AudioRegion>(rv.audio_region(), before, after));
+                trackview.session().add_command(new MementoCommand<AudioRegion>(rv.audio_region(), &before, &after));
        }
 
        alist.erase (mr.start, mr.end);
 
-       trackview.editor.current_session()->add_command (new MementoCommand<AudioRegionGainLine>(*this, before, get_state()));
+       trackview.editor.current_session()->add_command (new MementoCommand<AudioRegionGainLine>(*this, &before, &get_state()));
        trackview.editor.current_session()->commit_reversible_command ();
        trackview.editor.current_session()->set_dirty ();
 }
@@ -83,7 +83,7 @@ AudioRegionGainLine::end_drag (ControlPoint* cp)
 {
        if (!rv.audio_region().envelope_active()) {
                rv.audio_region().set_envelope_active(true);
-                trackview.session().add_command(new MementoRedoCommand<AudioRegion>(rv.audio_region(), rv.audio_region().get_state()));
+                trackview.session().add_command(new MementoCommand<AudioRegion>(rv.audio_region(), 0, &rv.audio_region().get_state()));
        }
        AutomationLine::end_drag(cp);
 }
index 8d8efad8a277040b849626428dc1aef60829e577..c23ed272e193eefacd1ae35d68f25cbe88d552e8 100644 (file)
@@ -159,22 +159,26 @@ RouteParams_UI::~RouteParams_UI ()
 }
 
 void
-RouteParams_UI::add_route (boost::shared_ptr<Route> route)
+RouteParams_UI::add_routes (Session::RouteList& routes)
 {
-       ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::add_route), route));
+       ENSURE_GUI_THREAD(bind (mem_fun(*this, &RouteParams_UI::add_routes), routes));
        
-       if (route->hidden()) {
-               return;
-       }
-
-       TreeModel::Row row = *(route_display_model->append());
-       row[route_display_columns.text] = route->name();
-       row[route_display_columns.route] = route;
+       for (Session::RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
+               boost::shared_ptr<Route> route = (*x);
 
-       //route_select_list.rows().back().select ();
-       
-       route->name_changed.connect (bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
-       route->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::route_removed), route));
+               if (route->hidden()) {
+                       return;
+               }
+               
+               TreeModel::Row row = *(route_display_model->append());
+               row[route_display_columns.text] = route->name();
+               row[route_display_columns.route] = route;
+               
+               //route_select_list.rows().back().select ();
+               
+               route->name_changed.connect (bind (mem_fun(*this, &RouteParams_UI::route_name_changed), route));
+               route->GoingAway.connect (bind (mem_fun(*this, &RouteParams_UI::route_removed), route));
+       }
 }
 
 
@@ -355,9 +359,10 @@ RouteParams_UI::set_session (Session *sess)
        route_display_model->clear();
 
        if (session) {
-               session->foreach_route (this, &RouteParams_UI::add_route);
+               boost::shared_ptr<Session::RouteList> r = session->get_routes();
+               add_routes (*r);
                session->going_away.connect (mem_fun(*this, &ArdourDialog::session_gone));
-               session->RouteAdded.connect (mem_fun(*this, &RouteParams_UI::add_route));
+               session->RouteAdded.connect (mem_fun(*this, &RouteParams_UI::add_routes));
                start_updating ();
        } else {
                stop_updating ();
index 5f487d6e5cfbbe44e30d642e40f1b8f93927465b..eff31023f7e7e7bd2bf9a0d8d340b67da8b66937 100644 (file)
@@ -159,7 +159,7 @@ class RouteParams_UI : public ArdourDialog
        Glib::RefPtr<Gtk::ListStore> route_display_model;
 
        
-       void add_route (boost::shared_ptr<ARDOUR::Route>);
+       void add_routes (ARDOUR::Session::RouteList&);
 
        void route_name_changed (void *src, boost::shared_ptr<ARDOUR::Route> route);
        void route_removed (boost::shared_ptr<ARDOUR::Route> route);
index e2e1fb2149f8ad7030a621bba7d5e8dedf831ea2..e7a6df2f273c2ec0f8da018f91845e4e9f9bacec 100644 (file)
@@ -728,7 +728,7 @@ RouteTimeAxisView::rename_current_playlist ()
        ArdourPrompter prompter (true);
        string name;
 
-       Diskstream *const ds = get_diskstream();
+       boost::shared_ptr<Diskstream> ds = get_diskstream();
        if (!ds || ds->destructive())
                return;
 
@@ -759,7 +759,7 @@ RouteTimeAxisView::use_copy_playlist (bool prompt)
 {
        string name;
        
-       Diskstream *const ds = get_diskstream();
+       boost::shared_ptr<Diskstream> ds = get_diskstream();
        if (!ds || ds->destructive())
                return;
 
@@ -800,7 +800,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt)
 {
        string name;
        
-       Diskstream *const ds = get_diskstream();
+       boost::shared_ptr<Diskstream> ds = get_diskstream();
        if (!ds || ds->destructive())
                return;
 
@@ -838,7 +838,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt)
 void
 RouteTimeAxisView::clear_playlist ()
 {
-       Diskstream *const ds = get_diskstream();
+       boost::shared_ptr<Diskstream> ds = get_diskstream();
        if (!ds || ds->destructive())
                return;
 
@@ -878,8 +878,7 @@ RouteTimeAxisView::selection_click (GdkEventButton* ev)
 
        switch (Keyboard::selection_type (ev->state)) {
        case Selection::Toggle:
-               /* XXX this is not right */
-               editor.get_selection().add (*tracks);
+               editor.get_selection().toggle (*tracks);
                break;
                
        case Selection::Set:
@@ -964,7 +963,7 @@ RouteTimeAxisView::name() const
 Playlist *
 RouteTimeAxisView::playlist () const 
 {
-       Diskstream *ds;
+       boost::shared_ptr<Diskstream> ds;
 
        if ((ds = get_diskstream()) != 0) {
                return ds->playlist(); 
@@ -1014,7 +1013,7 @@ RouteTimeAxisView::hide_click ()
 Region*
 RouteTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir)
 {
-       Diskstream *stream;
+       boost::shared_ptr<Diskstream> stream;
        Playlist *playlist;
 
        if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) {
@@ -1028,7 +1027,7 @@ bool
 RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
 {
        Playlist* what_we_got;
-       Diskstream* ds = get_diskstream();
+       boost::shared_ptr<Diskstream> ds = get_diskstream();
        Playlist* playlist;
        bool ret = false;
 
@@ -1054,7 +1053,7 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
        case Cut:
                if ((what_we_got = playlist->cut (time)) != 0) {
                        editor.get_cut_buffer().add (what_we_got);
-                       _session.add_command( new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+                       _session.add_command( new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
                        ret = true;
                }
                break;
@@ -1066,7 +1065,7 @@ RouteTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op)
 
        case Clear:
                if ((what_we_got = playlist->cut (time)) != 0) {
-                       _session.add_command( new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+                       _session.add_command( new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
                        what_we_got->unref ();
                        ret = true;
                }
@@ -1097,7 +1096,7 @@ RouteTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection,
        
        XMLNode &before = playlist->get_state();
        playlist->paste (**p, pos, times);
-       _session.add_command( new MementoCommand<Playlist>(*playlist, before, playlist->get_state()));
+       _session.add_command( new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
 
        return true;
 }
index 6b3c2a820cc7d8d1dcc29dde232b13b0d9d24489..3ede0bc1c721361d0057adce5083df446f9772b0 100644 (file)
@@ -76,7 +76,7 @@ RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, co
        if (is_track()) {
                boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
 
-               t->diskstream().RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
+               t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
 
                _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
 
@@ -577,7 +577,7 @@ RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool,
         XMLNode &before = _route->get_state();
         bind(mem_fun(*_route, func), yn, arg)();
         XMLNode &after = _route->get_state();
-        _session.add_command (new MementoCommand<Route>(*_route, before, after));
+        _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
        _session.commit_reversible_command ();
 }
 
@@ -588,7 +588,7 @@ RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*f
         XMLNode &before = audio_track()->get_state();
        bind (mem_fun (*audio_track(), func), yn, arg)();
         XMLNode &after = audio_track()->get_state();
-       _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), before, after));
+       _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), &before, &after));
        _session.commit_reversible_command ();
 }
 
@@ -599,7 +599,7 @@ RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool,
         XMLNode &before = track()->get_state();
        bind (mem_fun (*track(), func), yn, arg)();
         XMLNode &after = track()->get_state();
-       _session.add_command (new MementoCommand<Track>(*track(), before, after));
+       _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
        _session.commit_reversible_command ();
 }
 
@@ -746,7 +746,6 @@ void
 RouteUI::route_removed ()
 {
        ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::route_removed));
-       
        delete this;
 }
 
@@ -930,15 +929,15 @@ RouteUI::midi_track() const
        return dynamic_cast<MidiTrack*>(_route.get());
 }
 
-Diskstream*
+boost::shared_ptr<Diskstream>
 RouteUI::get_diskstream () const
 {
        boost::shared_ptr<Track> t;
 
        if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
-               return &t->diskstream();
+               return t->diskstream();
        } else {
-               return 0;
+               return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
        }
 }
 
index 156063a8e5f4ee9f5e46828a637acfeddeeb28c5..b01d7d41cb984629ef7ff3044dfd31b21b10841e 100644 (file)
@@ -60,7 +60,7 @@ class RouteUI : public virtual AxisView
        ARDOUR::AudioTrack* audio_track() const;
        ARDOUR::MidiTrack*  midi_track() const;
        
-       ARDOUR::Diskstream* get_diskstream() const;
+       boost::shared_ptr<ARDOUR::Diskstream> get_diskstream() const;
 
        string name() const;
 
index 086d878994813f56ce96e2faa98cbfd7b15b46da..aa7fdbe30f8ff6d803ce3bec91b9534737c6def3 100644 (file)
@@ -179,6 +179,14 @@ Selection::toggle (Playlist* pl)
        PlaylistsChanged ();
 }
 
+void
+Selection::toggle (const list<TimeAxisView*>& track_list)
+{
+       for (list<TimeAxisView*>::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
+               toggle ( (*i) );
+       }
+}
+
 void
 Selection::toggle (TimeAxisView* track)
 {
@@ -616,6 +624,7 @@ Selection::set (list<Selectable*>& selectables)
        add (selectables);
 }
 
+
 void
 Selection::add (list<Selectable*>& selectables)
 {
index 82f941f9bdc482cfea5b7976a009d5b2d0affc73..ff51ca4b9f9f22c45212a566663cf57c9ebb2044 100644 (file)
@@ -207,7 +207,7 @@ StreamView::undisplay_diskstream ()
 }
 
 void
-StreamView::display_diskstream (Diskstream *ds)
+StreamView::display_diskstream (boost::shared_ptr<Diskstream> ds)
 {
        playlist_change_connection.disconnect();
        playlist_changed (ds);
@@ -225,7 +225,7 @@ StreamView::playlist_modified ()
 }
 
 void
-StreamView::playlist_changed (Diskstream *ds)
+StreamView::playlist_changed (boost::shared_ptr<Diskstream> ds)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &StreamView::playlist_changed), ds));
 
@@ -264,9 +264,7 @@ StreamView::diskstream_changed ()
        Track *t;
 
        if ((t = _trackview.track()) != 0) {
-               Diskstream& ds = t->diskstream();
-               /* XXX grrr: when will SigC++ allow me to bind references? */
-               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), &ds));
+               Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*this, &StreamView::display_diskstream), t->diskstream()));
        } else {
                Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &StreamView::undisplay_diskstream));
        }
index bee51e88350c9787b76f51e74e1336847740fb6a..fb49433cce8cb4da303a25b6eb37199e40766a42 100644 (file)
@@ -111,13 +111,13 @@ protected:
        virtual void remove_region_view (ARDOUR::Region* );
        void         remove_rec_region (ARDOUR::Region*);
 
-       void         display_diskstream (ARDOUR::Diskstream* );
+       void         display_diskstream (boost::shared_ptr<ARDOUR::Diskstream>);
        virtual void undisplay_diskstream ();
        virtual void redisplay_diskstream () = 0;
        void         diskstream_changed ();
        
        void         playlist_state_changed (ARDOUR::Change);
-       virtual void playlist_changed (ARDOUR::Diskstream* );
+       virtual void playlist_changed (boost::shared_ptr<ARDOUR::Diskstream>);
        virtual void playlist_modified ();
        
        virtual void color_handler (ColorID, uint32_t) = 0;
index 0cc2079d8e87e6a5ed93b2e80e942f33797d4029..18f8328cfd55cd102621a44a0f7e9cc1b0219bcf 100644 (file)
@@ -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;
index bca79b0d7dec88dadf4f2ff8d593e8b304bccf8a..fe6c88cf7f6de6204d621d14fd686913b9899e3c 100644 (file)
@@ -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 ();
index 570ad2830d7c6db79e1ed889c87b1e1b060ddb92..db814bbb5fce39f93a09047eda03149a23d5b4d8 100644 (file)
@@ -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 ();
index 5864de73c668201a761dc9209afa62b5d1ac4815..dad94161d06744df181c3a18a7663efec0d26a27 100644 (file)
@@ -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 {
index df632c5171c9a535371b57b8aa6945ab06acaadc..87893ca2609a12de03608e0a748baeb432539a74 100644 (file)
@@ -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;
index 080343691390fe954f727b459d232245b2feef4d..858ed1af6f12fa006a30a6e689a1131139532ff8 100644 (file)
@@ -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;
index ff953d1d7895ab8c138776acc1565480900bd0ce..beae4a6e07734278d235af689409303eb062714b 100644 (file)
@@ -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;
index 0e4aed1929e49bb342bd996c38ba4f5ca4c5206d..bf64cedd088897235e68792ea90f8a3f8f44c2a3 100644 (file)
@@ -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 ();
index 662f5a835040cbf6131d31b3eb00994e12419375..e8b499397d50e5a5f026bd8bbd4c6b4c734f7317 100644 (file)
@@ -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,
index 409aa171e9812bbdde1d346e0f330145bf30dc28..7c4befe11601b38fc666ba5dab94d344a40b44c2 100644 (file)
@@ -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 ();
index 107abb7b48954df13b2edc242934870d79c19f5d..5b9c92dc71fe3b27688aef572740dc4c9ce8af27 100644 (file)
@@ -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;
index 2737d86a3fb70312fa591cc2af1173ab64f94d71..eeb905a3018a170a4147c1f22b1cb3cf1a563993 100644 (file)
@@ -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;
index 2b317a0299c61b535fa23ef523e4f25268a59ef9..2e628fa5869cbf9fffb360bce46e3002e61ef634 100644 (file)
@@ -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;
 
index 40c8e3301bb71660c86c1b784133aef3931bf60a..dceaea3f7e6d5424b13d5233b9759a471f5be04e 100644 (file)
@@ -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;
index b12b79858e50155513e5055ef8be9a08e99c1ed4..7a44be9b54f7767dde9ca5593822ef14ab5ccb94 100644 (file)
@@ -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) {
 
index d00b83f53d6e4347309c7bddb60a03e998607934..15ad6e442c07807bc44ac90494cac790af4642e1 100644 (file)
@@ -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;
index af3072d215335c8081f1555cb2b6f91cc7f5d674..3109323acd57a5841f5acf2bd97b05fbad8b5014 100644 (file)
@@ -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 */
index dc1767d1e79abc2d881f52e11572b73f205dbab0..ccfcef28f4d01616bd67a4b737ec1f6cab533908 100644 (file)
@@ -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()
index b0052c96fb2799c4b3d96f17b2386d3805936866..7d62c5bc9422ba027f1d2b8a36f67635a1335e45 100644 (file)
@@ -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 ()
index 22a0b0460e9cafab5b9509daade4b506940e2392..9a80f3e70f338bae34003a15e84022150f5733ef 100644 (file)
@@ -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;
index 5b5f73313884cdcde02c37f36ba43837407afe65..ca88a2851b131826d9a88ab0a04c396ef49050dc 100644 (file)
@@ -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;
+}
index 40b0b11564e5715be762aa0c1556e157a6b84899..e42e455df0930082af9cf3a93f25d886e62573f9 100644 (file)
@@ -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;
 
        }
 }
index 91aad5ea80107967ac2d971ad0883f2e41c69a70..aeff92bed319e409ce280d3ada46c67b709feb87 100644 (file)
@@ -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
index 2ea6c314c1591bbcb8863030f44152e672d69e75..039f88e2ea2b639d03f4719f4d2999e376d21807 100644 (file)
@@ -114,7 +114,6 @@ Route::init ()
 
 Route::~Route ()
 {
-       GoingAway (); /* EMIT SIGNAL */
        clear_redirects (this);
 
        if (_control_outs) {
index ab8d8674142d5d00086bde3182f408c6d7e0145b..7d5f8384992d487e47c5507092e2064b2893e0ed 100644 (file)
@@ -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
@@ -2402,6 +2499,20 @@ Session::route_by_name (string name)
        return shared_ptr<Route> ((Route*) 0);
 }
 
+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)
 {
@@ -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) {
-                       returni;
+                       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;
+}
index 6509a783bb8ad8481050480cea09241087001c81..5d691a7425c3a8ce5a3071d45d30690f362adbb4 100644 (file)
@@ -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);
                }
        }
index af507208ab7e031172328bd8cf8b68650f32cbb2..4e7c4151b74d1032961620092e489efd3cb05ac1 100644 (file)
@@ -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;
 }
index c5449d3e06bb24b9533427817075f71b2dbfbc7a..946d825c1c6c414f7a3130086d3430fdc2ea31ac 100644 (file)
@@ -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)
index b0738e95a7fb3dcb578b519eb678420c9f152043..d7cdd94b2bf59debb3511da29f6c59cb1a40b34e 100644 (file)
@@ -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 */
                
index 6d13caced8d981a3f943c136ea77fa4b3235d1f0..e99478e0b40e73aa63f3ab353ef955e1754bdf36 100644 (file)
@@ -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;
                }
index cefae9dd3daa45ec9ae242619e65289c7d230c60..5553127b90941a840c4d2baa950c71c9626ccaea 100644 (file)
@@ -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;
+}
index aad3617580be73453b9423031fd98b7ef7535bfe..85e2dd391f31ab23dfec420c1eee60b520dbcd79 100644 (file)
@@ -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 ();
        }
 }
index bd5649bc2e0f0de5112e468bff198e4f393a5aca..5a5bafb6cac0420d2e821966b63b09ddad29ed1d 100644 (file)
@@ -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?
index 28816541f1a7d86d5049d29d615a48e2386fc623..a96a4a1a82591cfd275c05fa639a12bb4b7054cb 100644 (file)
@@ -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;
 }
index 0de0d052c3d7a5e2d6e5c84697f8d553adba61df..ab7806873ebb54fed9852d27cb1a53505fcfc785 100644 (file)
@@ -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;
 }
index 0e34787a2dbee8a4931217f34e1088d021e27b11..eca53916afc1462b2ba9ed6cc5d424b5f5994957 100644 (file)
@@ -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 (file)
index 0000000..126bd04
--- /dev/null
@@ -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__ */
index 1ce448d58bd1397b15d7379f4a8a426f9c6d1a98..c1103627342ba4d313052baa62cc03acb39de70e 100644 (file)
@@ -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;
index 122dcb4c860ed0972c7fd2377a0c7daba2ba48e6..3a72fc984139ecea2062bddaf0dcbf6ef19b93a0 100644 (file)
@@ -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__
index 58a92a206a574e3e4066af422ff065cbfad304b8..e81db8ba8717108d9cb8dcf110bb2fee219c4a74 100644 (file)
@@ -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;
index 3038f16b4f4a05c0367fc160784eca8577d6c7b0..5adddfc1c06e8b10e19414cc8f7a2fa7bc5e26ed 100644 (file)
@@ -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 (file)
index 0000000..fddc1ae
--- /dev/null
@@ -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__ */
index 8d1b416c16bcf66d1c611eaf45902288b9113cba..6f421de84edcfa450f1c7605ba796af9591b8a22 100644 (file)
@@ -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++)
index bee47839140d46398d1c46cd2accda67737418df..3dc93cc64ad980070886d6215a613b25a5288260 100644 (file)
@@ -145,7 +145,6 @@ void
 BasicUI::save_state ()
 {
        session->save_state ("");
-        session->save_history("");
 }
 
 void