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