From 0c4c6e031a3624cfc74c2eef6e79527b7c49eca8 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 9 Nov 2006 20:38:39 +0000 Subject: first pass on track mode switch; fixes to dangling region refs after capture; destroy region menu item removed; small fix to SConstruct for missing C++ case; playlist selection mechanism modified ; new Selection operation added (Add); handle crashing situation with align style change handling caused by recursion git-svn-id: svn://localhost/ardour2/trunk@1099 d708f5d6-7413-0410-9779-e7cbd77b26cf --- SConstruct | 2 +- gtk2_ardour/ardour_ui.cc | 2 +- gtk2_ardour/editor.cc | 34 +++---- gtk2_ardour/editor.h | 6 +- gtk2_ardour/editor_ops.cc | 14 +-- gtk2_ardour/editor_region_list.cc | 15 ++-- gtk2_ardour/keyboard.cc | 2 + gtk2_ardour/redirect_box.cc | 2 + gtk2_ardour/region_selection.cc | 12 +-- gtk2_ardour/region_view.cc | 2 - gtk2_ardour/route_time_axis.cc | 165 +++++++++++++++++++++++++++++----- gtk2_ardour/route_time_axis.h | 10 ++- gtk2_ardour/selection.h | 1 + gtk2_ardour/time_axis_view.cc | 2 + gtk2_ardour/utils.cc | 2 +- libs/ardour/SConscript | 1 - libs/ardour/ardour/audio_diskstream.h | 3 + libs/ardour/ardour/audio_track.h | 2 + libs/ardour/ardour/audioregion.h | 2 + libs/ardour/ardour/diskstream.h | 5 +- libs/ardour/ardour/playlist.h | 17 ++-- libs/ardour/ardour/region.h | 5 +- libs/ardour/ardour/session.h | 5 +- libs/ardour/ardour/source.h | 12 +++ libs/ardour/ardour/track.h | 8 +- libs/ardour/audio_diskstream.cc | 71 ++++++++++++++- libs/ardour/audio_playlist.cc | 21 ++++- libs/ardour/audio_track.cc | 17 ++++ libs/ardour/audioregion.cc | 41 ++++++++- libs/ardour/diskstream.cc | 16 ++-- libs/ardour/playlist.cc | 28 ++++-- libs/ardour/region_factory.cc | 3 +- libs/ardour/session.cc | 54 +++++++---- libs/ardour/session_state.cc | 3 +- libs/ardour/sndfilesource.cc | 6 +- libs/ardour/source.cc | 24 +++++ libs/ardour/track.cc | 12 --- libs/gtkmm2ext/barcontroller.cc | 1 + 38 files changed, 479 insertions(+), 149 deletions(-) diff --git a/SConstruct b/SConstruct index 6b278ea3c4..6f4f1bdde1 100644 --- a/SConstruct +++ b/SConstruct @@ -703,7 +703,7 @@ config_prefix = '$DESTDIR' + final_config_prefix conf = Configure (env) -have_cxx = conf.TryAction (Action (env['CXX'] + ' --version')) +have_cxx = conf.TryAction (Action (str(env['CXX']) + ' --version')) if have_cxx[0] != 1: print "This system has no functional C++ compiler. You cannot build Ardour from source without one." sys.exit (1) diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 873c3849c2..df2848a88e 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -1946,7 +1946,7 @@ ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* l _("No audio files were ready for cleanup"), true, Gtk::MESSAGE_INFO, - (Gtk::ButtonsType)(Gtk::BUTTONS_CLOSE) ); + (Gtk::ButtonsType)(Gtk::BUTTONS_OK) ); msgd.set_secondary_text (_("If this seems suprising, \n\ check for any existing snapshots.\n\ These may still include regions that\n\ diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index a9f4b4b7dc..d0b8f757f1 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -62,6 +62,7 @@ #include "selection.h" #include "audio_streamview.h" #include "time_axis_view.h" +#include "audio_time_axis.h" #include "utils.h" #include "crossfade_view.h" #include "editing.h" @@ -1695,7 +1696,7 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr become selected. */ - region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr(region))); + // region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr(region))); items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region))); items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top))); @@ -1793,8 +1794,6 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track)))); items.push_back (SeparatorElem()); items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region))); - items.push_back (SeparatorElem()); - items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region))); /* OK, stick the region submenu at the top of the list, and then add the standard items. @@ -2847,6 +2846,13 @@ Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no } break; + case Selection::Add: + if (!selection->selected (&view)) { + selection->add (&view); + commit = true; + } + break; + case Selection::Set: if (selection->selected (&view) && selection->tracks.size() == 1) { /* no commit necessary */ @@ -2894,7 +2900,7 @@ Editor::set_selected_control_point_from_click (Selection::Operation op, bool no_ } void -Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set& relevant_tracks) +Editor::get_relevant_audio_tracks (set& relevant_tracks) { /* step one: get all selected tracks and all tracks in the relevant edit groups */ @@ -2923,14 +2929,9 @@ Editor::get_relevant_audio_tracks (AudioTimeAxisView& base, set sl) { set relevant_tracks; - if (!clicked_audio_trackview) { - return; - } - - get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks); + get_relevant_audio_tracks (relevant_tracks); uint32_t sz = relevant_tracks.size(); - + for (set::iterator ati = relevant_tracks.begin(); ati != relevant_tracks.end(); ++ati) { sl (**ati, sz); } @@ -3134,7 +3131,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, set relevant_tracks; - get_relevant_audio_tracks (*clicked_audio_trackview, relevant_tracks); + get_relevant_audio_tracks (relevant_tracks); for (set::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) { (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results); @@ -3209,6 +3206,9 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr regi case Selection::Extend: selection->add (all_equivalent_regions); break; + case Selection::Add: + selection->add (all_equivalent_regions); + break; } commit_reversible_command () ; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 10747735b5..bbf5e8ad01 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -412,7 +412,7 @@ class Editor : public PublicEditor CrossfadeView* clicked_crossfadeview; ControlPoint* clicked_control_point; - void get_relevant_audio_tracks (AudioTimeAxisView& base, std::set& relevant_tracks); + void get_relevant_audio_tracks (std::set& relevant_tracks); void mapover_audio_tracks (sigc::slot sl); /* functions to be passed to mapover_audio_tracks(), possibly with sigc::bind()-supplied arguments */ @@ -814,8 +814,8 @@ class Editor : public PublicEditor int ensure_cursor (nframes_t* pos); - void handle_new_audio_region (boost::shared_ptr); - void handle_audio_region_removed (boost::shared_ptr); + void handle_new_audio_region (boost::weak_ptr); + void handle_audio_region_removed (boost::weak_ptr); void add_audio_region_to_region_display (boost::shared_ptr); void region_hidden (boost::shared_ptr); void redisplay_regions (); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index 6d006f94bf..a29d00fd5a 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -162,9 +162,9 @@ Editor::remove_clicked_region () void Editor::destroy_clicked_region () { - int32_t selected = selection->regions.size(); + uint32_t selected = selection->regions.size(); - if (!session || clicked_regionview == 0 && selected == 0) { + if (!session || !selected) { return; } @@ -191,7 +191,7 @@ Do you really want to destroy %1 ?"), return; } - if (selected > 0) { + if (selected) { list > r; for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) { @@ -199,9 +199,6 @@ Do you really want to destroy %1 ?"), } session->destroy_regions (r); - - } else if (clicked_regionview) { - session->destroy_region (clicked_regionview->region()); } } @@ -1275,6 +1272,9 @@ Editor::select_all_in_track (Selection::Operation op) case Selection::Extend: /* not defined yet */ break; + case Selection::Add: + selection->add (touched); + break; } } @@ -1291,6 +1291,7 @@ Editor::select_all (Selection::Operation op) } begin_reversible_command (_("select all")); switch (op) { + case Selection::Add: case Selection::Toggle: selection->add (touched); break; @@ -1348,6 +1349,7 @@ Editor::select_all_within (nframes_t start, nframes_t end, double top, double bo begin_reversible_command (_("select all within")); switch (op) { + case Selection::Add: case Selection::Toggle: cerr << "toggle\n"; selection->add (touched); diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc index 397c401e0c..1ebf59fecd 100644 --- a/gtk2_ardour/editor_region_list.cc +++ b/gtk2_ardour/editor_region_list.cc @@ -48,22 +48,27 @@ using namespace Glib; using namespace Editing; void -Editor::handle_audio_region_removed (boost::shared_ptr region) +Editor::handle_audio_region_removed (boost::weak_ptr wregion) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_audio_region_removed), region)); + ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_audio_region_removed), wregion)); redisplay_regions (); } void -Editor::handle_new_audio_region (boost::shared_ptr region) +Editor::handle_new_audio_region (boost::weak_ptr wregion) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_audio_region), region)); + ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_audio_region), wregion)); /* don't copy region - the one we are being notified about belongs to the session, and so it will never be edited. */ - add_audio_region_to_region_display (region); + + boost::shared_ptr region (wregion.lock()); + + if (region) { + add_audio_region_to_region_display (region); + } } void diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc index 17390b8b4d..a6a14ad55b 100644 --- a/gtk2_ardour/keyboard.cc +++ b/gtk2_ardour/keyboard.cc @@ -796,6 +796,8 @@ Keyboard::modifier_state_equals (guint state, ModifierMask mask) Selection::Operation Keyboard::selection_type (guint state) { + /* note that there is no modifier for "Add" */ + if (modifier_state_equals (state, Shift)) { return Selection::Extend; } else if (modifier_state_equals (state, Control)) { diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc index 6153d093f3..b7eb117703 100644 --- a/gtk2_ardour/redirect_box.cc +++ b/gtk2_ardour/redirect_box.cc @@ -968,11 +968,13 @@ RedirectBox::edit_redirect (boost::shared_ptr redirect) if (plugin_insert->get_gui() == 0) { plugin_ui = new PluginUIWindow (plugin_insert); + if (_owner_is_mixer) { ARDOUR_UI::instance()->the_mixer()->ensure_float (*plugin_ui); } else { ARDOUR_UI::instance()->the_editor().ensure_float (*plugin_ui); } + plugin_ui->set_title (generate_redirect_title (plugin_insert)); plugin_insert->set_gui (plugin_ui); diff --git a/gtk2_ardour/region_selection.cc b/gtk2_ardour/region_selection.cc index d887021a42..a418b1de23 100644 --- a/gtk2_ardour/region_selection.cc +++ b/gtk2_ardour/region_selection.cc @@ -79,23 +79,19 @@ RegionSelection::clear_all() { clear(); _bylayer.clear(); + _current_start = 0; + _current_end = 0; } bool RegionSelection::contains (RegionView* rv) { - if (this->find (rv) != end()) { - return true; - } - else { - return false; - } - + return this->find (rv) != end(); } void RegionSelection::add (RegionView* rv, bool dosort) { - if (this->find (rv) != end()) { + if (contains (rv)) { /* we already have it */ return; } diff --git a/gtk2_ardour/region_view.cc b/gtk2_ardour/region_view.cc index db2726e515..634c29f767 100644 --- a/gtk2_ardour/region_view.cc +++ b/gtk2_ardour/region_view.cc @@ -149,8 +149,6 @@ RegionView::~RegionView () { in_destructor = true; - RegionViewGoingAway (this); /* EMIT_SIGNAL */ - for (vector::iterator g = ghosts.begin(); g != ghosts.end(); ++g) { delete *g; } diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc index f5f0f1dd10..ab8ebb32b5 100644 --- a/gtk2_ardour/route_time_axis.cc +++ b/gtk2_ardour/route_time_axis.cc @@ -40,6 +40,7 @@ #include #include +#include #include #include #include @@ -182,6 +183,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh if (is_track()) { + track()->TrackModeChanged.connect (mem_fun(*this, &RouteTimeAxisView::track_mode_changed)); track()->FreezeChange.connect (mem_fun(*this, &RouteTimeAxisView::map_frozen)); track()->DiskstreamChanged.connect (mem_fun(*this, &RouteTimeAxisView::diskstream_changed)); get_diskstream()->SpeedChanged.connect (mem_fun(*this, &RouteTimeAxisView::speed_changed)); @@ -276,8 +278,6 @@ RouteTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Grou MenuList &items = edit_group_menu.items(); - cerr << "adding edit group " << eg->name() << endl; - items.push_back (RadioMenuElem (*group, eg->name(), bind (mem_fun(*this, &RouteTimeAxisView::set_edit_group_from_menu), eg))); if (_route->edit_group() == eg) { static_cast(&items.back())->set_active (); @@ -286,18 +286,10 @@ RouteTimeAxisView::add_edit_group_menu_item (RouteGroup *eg, RadioMenuItem::Grou void RouteTimeAxisView::set_edit_group_from_menu (RouteGroup *eg) - { _route->set_edit_group (eg, this); } -void -RouteTimeAxisView::playlist_state_changed (Change ignored) -{ - // ENSURE_GUI_THREAD (bind (mem_fun(*this, &RouteTimeAxisView::playlist_state_changed), ignored)); - // why are we here ? -} - void RouteTimeAxisView::playlist_changed () @@ -342,13 +334,15 @@ RouteTimeAxisView::playlist_click () { // always build a new action menu - if (playlist_action_menu == 0) { - playlist_action_menu = new Menu; - playlist_action_menu->set_name ("ArdourContextMenu"); - } - - build_playlist_menu(playlist_action_menu); + if (playlist_action_menu != 0) { + delete playlist_action_menu; + } + playlist_action_menu = new Menu; + playlist_action_menu->set_name ("ArdourContextMenu"); + + build_playlist_menu (playlist_action_menu); + editor.set_selected_track (*this, Selection::Add); playlist_action_menu->popup (1, 0); } @@ -361,6 +355,7 @@ RouteTimeAxisView::automation_click () */ build_display_menu (); } + editor.set_selected_track (*this, Selection::Add); automation_action_menu->popup (1, 0); } @@ -443,6 +438,24 @@ RouteTimeAxisView::build_display_menu () get_diskstream()->AlignmentStyleChanged.connect ( mem_fun(*this, &RouteTimeAxisView::align_style_changed)); + + RadioMenuItem::Group mode_group; + items.push_back (RadioMenuElem (mode_group, _("Normal mode"), + bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Normal))); + normal_track_mode_item = dynamic_cast(&items.back()); + items.push_back (RadioMenuElem (mode_group, _("Tape mode"), + bind (mem_fun (*this, &RouteTimeAxisView::set_track_mode), ARDOUR::Destructive))); + destructive_track_mode_item = dynamic_cast(&items.back()); + + + switch (track()->mode()) { + case ARDOUR::Destructive: + destructive_track_mode_item->set_active (); + break; + case ARDOUR::Normal: + normal_track_mode_item->set_active (); + break; + } } items.push_back (SeparatorElem()); @@ -454,6 +467,63 @@ RouteTimeAxisView::build_display_menu () items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route))); } +static bool __reset_item (RadioMenuItem* item) +{ + cerr << "reset item to true\n"; + item->set_active (); + return false; +} + +void +RouteTimeAxisView::set_track_mode (TrackMode mode) +{ + RadioMenuItem* item; + RadioMenuItem* other_item; + + cerr << "STM, mode = " << mode; + + switch (mode) { + case ARDOUR::Normal: + item = normal_track_mode_item; + other_item = destructive_track_mode_item; + break; + case ARDOUR::Destructive: + item = destructive_track_mode_item; + other_item = normal_track_mode_item; + break; + default: + fatal << string_compose (_("programming error: %1 %2"), "illegal track mode in RouteTimeAxisView::set_track_mode", mode) << endmsg; + /*NOTREACHED*/ + return; + } + + if (item->get_active () && track()->mode() != mode) { + if (track()->set_mode (mode)) { + Glib::signal_idle().connect (bind (sigc::ptr_fun (__reset_item), other_item)); + } + } +} + +void +RouteTimeAxisView::track_mode_changed () +{ + RadioMenuItem* item; + + switch (track()->mode()) { + case ARDOUR::Normal: + item = normal_track_mode_item; + break; + case ARDOUR::Destructive: + item = destructive_track_mode_item; + break; + default: + fatal << string_compose (_("programming error: %1 %2"), "illegal track mode in RouteTimeAxisView::set_track_mode", track()->mode()) << endmsg; + /*NOTREACHED*/ + return; + } + + item->set_active (); +} void RouteTimeAxisView::show_timestretch (nframes_t start, nframes_t end) @@ -700,7 +770,24 @@ RouteTimeAxisView::align_style_changed () void RouteTimeAxisView::set_align_style (AlignStyle style) { - get_diskstream()->set_align_style (style); + RadioMenuItem* item; + + switch (style) { + case ExistingMaterial: + item = align_existing_item; + break; + case CaptureTime: + item = align_capture_item; + break; + default: + fatal << string_compose (_("programming error: %1 %2"), "illegal align style in RouteTimeAxisView::set_align_style", style) << endmsg; + /*NOTREACHED*/ + return; + } + + if (item->get_active()) { + get_diskstream()->set_align_style (style); + } } void @@ -772,7 +859,7 @@ RouteTimeAxisView::use_copy_playlist (bool prompt) if (name.length()) { ds->use_copy_playlist (); - pl->set_name (name); + ds->playlist()->set_name (name); } } @@ -799,7 +886,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt) prompter.set_initial_text (name); prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false); - + switch (prompter.run ()) { case Gtk::RESPONSE_ACCEPT: prompter.get_result (name); @@ -812,7 +899,7 @@ RouteTimeAxisView::use_new_playlist (bool prompt) if (name.length()) { ds->use_new_playlist (); - pl->set_name (name); + ds->playlist()->set_name (name); } } @@ -869,6 +956,10 @@ RouteTimeAxisView::selection_click (GdkEventButton* ev) case Selection::Extend: /* not defined yet */ break; + + case Selection::Add: + editor.get_selection().add (*tracks); + break; } delete tracks; @@ -1114,12 +1205,28 @@ RouteTimeAxisView::build_playlist_menu (Gtk::Menu * menu) if (playlist_menu) { delete playlist_menu; } + playlist_menu = new Menu; playlist_menu->set_name ("ArdourContextMenu"); - playlist_items.push_back (MenuElem (string_compose (_("Current: %1"), get_diskstream()->playlist()->name()))); - playlist_items.push_back (SeparatorElem()); + vector playlists; + boost::shared_ptr ds = get_diskstream(); + RadioMenuItem::Group playlist_group; + + _session.get_playlists (playlists); + for (vector::iterator i = playlists.begin(); i != playlists.end(); ++i) { + + if ((*i)->get_orig_diskstream_id() == ds->id()) { + playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name(), bind (mem_fun (*this, &RouteTimeAxisView::use_playlist), (*i)))); + + if (ds->playlist()->id() == (*i)->id()) { + static_cast(&playlist_items.back())->set_active(); + } + } + } + + playlist_items.push_back (SeparatorElem()); playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RouteTimeAxisView::rename_current_playlist))); playlist_items.push_back (SeparatorElem()); @@ -1128,8 +1235,20 @@ RouteTimeAxisView::build_playlist_menu (Gtk::Menu * menu) playlist_items.push_back (SeparatorElem()); playlist_items.push_back (MenuElem (_("Clear Current"), mem_fun(editor, &PublicEditor::clear_playlists))); playlist_items.push_back (SeparatorElem()); - playlist_items.push_back (MenuElem(_("Select"), mem_fun(*this, &RouteTimeAxisView::show_playlist_selector))); + playlist_items.push_back (MenuElem(_("Select from all ..."), mem_fun(*this, &RouteTimeAxisView::show_playlist_selector))); +} + +void +RouteTimeAxisView::use_playlist (Playlist* pl) +{ + AudioPlaylist* apl = dynamic_cast (pl); + + assert (is_track()); + + if (apl) { + get_diskstream()->use_playlist (apl); + } } void diff --git a/gtk2_ardour/route_time_axis.h b/gtk2_ardour/route_time_axis.h index 54fb387fcd..4a6f89e0af 100644 --- a/gtk2_ardour/route_time_axis.h +++ b/gtk2_ardour/route_time_axis.h @@ -180,7 +180,6 @@ protected: void playlist_click (); void show_playlist_selector (); void playlist_changed (); - void playlist_state_changed (ARDOUR::Change); void playlist_modified (); void rename_current_playlist (); @@ -224,12 +223,19 @@ protected: Gtk::Menu edit_group_menu; Gtk::RadioMenuItem* align_existing_item; Gtk::RadioMenuItem* align_capture_item; + Gtk::RadioMenuItem* normal_track_mode_item; + Gtk::RadioMenuItem* destructive_track_mode_item; Gtk::Menu* playlist_menu; Gtk::Menu* playlist_action_menu; Gtk::MenuItem* playlist_item; + void use_playlist (ARDOUR::Playlist*); + ArdourCanvas::SimpleRect* timestretch_rect; - + + void set_track_mode (ARDOUR::TrackMode); + void track_mode_changed (); + list redirect_automation; vector redirect_automation_curves; diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h index a1b1ae0da3..c4336fba21 100644 --- a/gtk2_ardour/selection.h +++ b/gtk2_ardour/selection.h @@ -56,6 +56,7 @@ class Selection : public sigc::trackable enum Operation { Set, + Add, Toggle, Extend }; diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc index 3a9ea7b4de..783a41e0a1 100644 --- a/gtk2_ardour/time_axis_view.cc +++ b/gtk2_ardour/time_axis_view.cc @@ -475,12 +475,14 @@ TimeAxisView::popup_display_menu (guint32 when) if (display_menu == 0) { build_display_menu (); } + editor.set_selected_track (*this, Selection::Add); display_menu->popup (1, when); } gint TimeAxisView::size_click (GdkEventButton *ev) { + editor.set_selected_track (*this, Selection::Add); popup_size_menu (ev->time); return TRUE; } diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc index 76b237713a..433fdd647a 100644 --- a/gtk2_ardour/utils.cc +++ b/gtk2_ardour/utils.cc @@ -362,7 +362,7 @@ key_press_focus_accelerator_handler (Gtk::Window& window, GdkEventKey* ev) if (focus) { if (GTK_IS_ENTRY(focus)) { special_handling_of_unmodified_accelerators = true; - } + } } /* This exists to allow us to override the way GTK handles diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index 8c6bd36c2d..7d1520a98c 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -274,7 +274,6 @@ if env['NLS']: env.Alias('install', env.Install(os.path.join(install_prefix, 'lib/ardour2'), libardour)) -env.AlwaysBuild ('version.cc') env.Alias('version', ardour.VersionBuild(['version.cc', 'ardour/version.h'], 'SConscript')) env.Alias('tarball', env.Distribute (env['DISTTREE'], diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 4dee5e9b00..74c804e5bb 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -77,6 +77,7 @@ class AudioDiskstream : public Diskstream } void set_record_enabled (bool yn); + int set_destructive (bool yn); float peak_power(uint32_t n=0) { float x = channels[n].peak_power; @@ -251,6 +252,8 @@ class AudioDiskstream : public Diskstream typedef vector ChannelList; ChannelList channels; + + bool can_become_destructive () const; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 66fcd16a56..ae299dae4a 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -37,6 +37,8 @@ class AudioTrack : public Track AudioTrack (Session&, const XMLNode&); ~AudioTrack (); + int set_mode (TrackMode m); + int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick, bool can_record, bool rec_monitors_input); diff --git a/libs/ardour/ardour/audioregion.h b/libs/ardour/ardour/audioregion.h index 4be5d27a6b..b739935d96 100644 --- a/libs/ardour/ardour/audioregion.h +++ b/libs/ardour/ardour/audioregion.h @@ -136,6 +136,8 @@ class AudioRegion : public Region void resume_fade_in (); void resume_fade_out (); + void set_playlist (Playlist *); + private: friend class RegionFactory; diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 0afed75348..4cee6d1268 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -90,7 +90,7 @@ class IO; virtual void set_record_enabled (bool yn) = 0; bool destructive() const { return _flags & Destructive; } - virtual void set_destructive (bool yn); + virtual int set_destructive (bool yn) { return -1; } bool hidden() const { return _flags & Hidden; } bool recordable() const { return _flags & Recordable; } @@ -138,6 +138,8 @@ class IO; void handle_input_change (IOChange, void *src); + void remove_region_from_last_capture (boost::weak_ptr wregion); + sigc::signal RecordEnableChanged; sigc::signal SpeedChanged; sigc::signal ReverseChanged; @@ -224,6 +226,7 @@ class IO; virtual bool realtime_set_speed (double, bool global_change); std::list > _last_capture_regions; + virtual int use_pending_capture_data (XMLNode& node) = 0; virtual void get_input_sources () = 0; diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 9cc3f86f0b..7b9ae718bc 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -62,14 +62,15 @@ class Playlist : public PBD::StatefulDestructible { void unref(); uint32_t refcnt() const { return _refcnt; } - const string& name() const { return _name; } - void set_name (const string& str); + std::string name() const { return _name; } + void set_name (std::string str); bool frozen() const { return _frozen; } void set_frozen (bool yn); bool hidden() const { return _hidden; } bool empty() const; + uint32_t n_regions() const; nframes_t get_maximum_extent () const; layer_t top_layer() const; @@ -88,19 +89,15 @@ class Playlist : public PBD::StatefulDestructible { void duplicate (boost::shared_ptr, nframes_t position, float times); void nudge_after (nframes_t start, nframes_t distance, bool forwards); - boost::shared_ptr find_region (const PBD::ID&) const; - Playlist* cut (list&, bool result_is_hidden = true); Playlist* copy (list&, bool result_is_hidden = true); int paste (Playlist&, nframes_t position, float times); - uint32_t read_data_count() { return _read_data_count; } - - RegionList* regions_at (nframes_t frame); - RegionList* regions_touched (nframes_t start, nframes_t end); + RegionList* regions_at (nframes_t frame); + RegionList* regions_touched (nframes_t start, nframes_t end); + boost::shared_ptr find_region (const PBD::ID&) const; boost::shared_ptr top_region_at (nframes_t frame); - - boost::shared_ptr find_next_region (nframes_t frame, RegionPoint point, int dir); + boost::shared_ptr find_next_region (nframes_t frame, RegionPoint point, int dir); template void foreach_region (T *t, void (T::*func)(boost::shared_ptr, void *), void *arg); template void foreach_region (T *t, void (T::*func)(boost::shared_ptr)); diff --git a/libs/ardour/ardour/region.h b/libs/ardour/ardour/region.h index 67e00d0ee8..7f511c4dd4 100644 --- a/libs/ardour/ardour/region.h +++ b/libs/ardour/ardour/region.h @@ -163,10 +163,7 @@ class Region : public PBD::StatefulDestructible, public boost::enable_shared_fro ARDOUR::Playlist* playlist() const { return _playlist; } - void set_playlist (ARDOUR::Playlist*); - - virtual void lock_sources () {} - virtual void unlock_sources () {} + virtual void set_playlist (ARDOUR::Playlist*); /* serialization */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 85c0ef508c..93c093ec85 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -542,8 +542,8 @@ class Session : public PBD::StatefulDestructible /* region info */ - sigc::signal > AudioRegionAdded; - sigc::signal > AudioRegionRemoved; + sigc::signal > AudioRegionAdded; + sigc::signal > AudioRegionRemoved; int region_name (string& result, string base = string(""), bool newlevel = false) const; string new_region_name (string); @@ -630,6 +630,7 @@ class Session : public PBD::StatefulDestructible uint32_t n_playlists() const; template void foreach_playlist (T *obj, void (T::*func)(Playlist *)); + void get_playlists (std::vector&); /* named selections */ diff --git a/libs/ardour/ardour/source.h b/libs/ardour/ardour/source.h index 7e05e628ac..15e814e946 100644 --- a/libs/ardour/ardour/source.h +++ b/libs/ardour/ardour/source.h @@ -22,6 +22,7 @@ #define __ardour_source_h__ #include +#include #include @@ -32,6 +33,7 @@ namespace ARDOUR { class Session; +class Playlist; class Source : public PBD::StatefulDestructible { @@ -49,13 +51,23 @@ class Source : public PBD::StatefulDestructible XMLNode& get_state (); int set_state (const XMLNode&); + void use () { _in_use++; } + void disuse () { if (_in_use) { _in_use--; } } + + void add_playlist (ARDOUR::Playlist*); + void remove_playlist (ARDOUR::Playlist*); + + uint32_t used() const; protected: Session& _session; string _name; time_t _timestamp; + std::set _playlists; + private: + uint32_t _in_use; }; } diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index cf380de153..a24b614157 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -39,6 +39,10 @@ class Track : public Route int set_name (string str, void *src); + TrackMode mode () const { return _mode; } + virtual int set_mode (TrackMode m) { return false; } + sigc::signal TrackModeChanged; + virtual int roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick, bool can_record, bool rec_monitors_input) = 0; @@ -57,9 +61,6 @@ class Track : public Route virtual int use_diskstream (string name) = 0; virtual int use_diskstream (const PBD::ID& id) = 0; - TrackMode mode() const { return _mode; } - void set_mode (TrackMode m); - nframes_t update_total_latency(); void set_latency_delay (nframes_t); @@ -88,7 +89,6 @@ class Track : public Route void set_meter_point (MeterPoint, void* src); - sigc::signal ModeChanged; sigc::signal DiskstreamChanged; sigc::signal FreezeChange; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index ad9fec2d41..7e753fa601 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -381,7 +381,7 @@ AudioDiskstream::setup_destructive_playlist () void AudioDiskstream::use_destructive_playlist () { - /* this is called from the XML-based constructor. when its done, + /* this is called from the XML-based constructor or ::set_destructive. when called, we already have a playlist and a region, but we need to set up our sources for write. we use the sources associated with the (presumed single, full-extent) region. @@ -400,6 +400,10 @@ AudioDiskstream::use_destructive_playlist () throw failed_constructor(); } + /* be sure to stretch the region out to the maximum length */ + + region->set_length (max_frames - region->position(), this); + uint32_t n; ChannelList::iterator chan; @@ -407,6 +411,10 @@ AudioDiskstream::use_destructive_playlist () (*chan).write_source = boost::dynamic_pointer_cast(region->source (n)); assert((*chan).write_source); (*chan).write_source->set_allow_remove_if_empty (false); + + /* this might be false if we switched modes, so force it */ + + (*chan).write_source->set_destructive (true); } /* the source list will never be reset for a destructive track */ @@ -1584,9 +1592,9 @@ AudioDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_ca continue; /* XXX is this OK? */ } - _last_capture_regions.push_back (region); + region->GoingAway.connect (bind (mem_fun (*this, &Diskstream::remove_region_from_last_capture), boost::weak_ptr(region))); - // cerr << "add new region, buffer position = " << buffer_position << " @ " << (*ci)->start << endl; + _last_capture_regions.push_back (region); i_am_the_modifier++; _playlist->add_region (region, (*ci)->start); @@ -2228,3 +2236,60 @@ AudioDiskstream::use_pending_capture_data (XMLNode& node) return 0; } + +int +AudioDiskstream::set_destructive (bool yn) +{ + if (yn != destructive()) { + + if (yn) { + if (!can_become_destructive ()) { + return -1; + } + _flags |= Destructive; + use_destructive_playlist (); + } else { + _flags &= ~Destructive; + reset_write_sources (true, true); + } + } + + return 0; +} + +bool +AudioDiskstream::can_become_destructive () const +{ + if (!_playlist) { + return false; + } + + /* is there only one region ? */ + + if (_playlist->n_regions() != 1) { + return false; + } + + boost::shared_ptr first = _playlist->find_next_region (_session.current_start_frame(), Start, 1); + assert (first); + + /* do the source(s) for the region cover the session start position ? */ + + if (first->position() != _session.current_start_frame()) { + if (first->start() > _session.current_start_frame()) { + return false; + } + } + + /* is the source used by only 1 playlist ? */ + + boost::shared_ptr afirst = boost::dynamic_pointer_cast (first); + + assert (afirst); + + if (afirst->source()->used() > 1) { + return false; + } + + return true; +} diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc index 290907746b..5118aab684 100644 --- a/libs/ardour/audio_playlist.cc +++ b/libs/ardour/audio_playlist.cc @@ -624,12 +624,10 @@ AudioPlaylist::destroy_region (boost::shared_ptr region) { RegionLock rlock (this); - RegionList::iterator i; - RegionList::iterator tmp; - for (i = regions.begin(); i != regions.end(); ) { + for (RegionList::iterator i = regions.begin(); i != regions.end(); ) { - tmp = i; + RegionList::iterator tmp = i; ++tmp; if ((*i) == region) { @@ -639,6 +637,21 @@ AudioPlaylist::destroy_region (boost::shared_ptr region) i = tmp; } + + for (set >::iterator x = all_regions.begin(); x != all_regions.end(); ) { + + set >::iterator xtmp = x; + ++xtmp; + + if ((*x) == region) { + all_regions.erase (x); + changed = true; + } + + x = xtmp; + } + + region->set_playlist (0); } for (c = _crossfades.begin(); c != _crossfades.end(); ) { diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 23ece02fa8..9c5020e9aa 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -72,6 +72,23 @@ AudioTrack::~AudioTrack () { } +int +AudioTrack::set_mode (TrackMode m) +{ + if (m != _mode) { + + if (_diskstream->set_destructive (m == Destructive)) { + return -1; + } + + _mode = m; + + TrackModeChanged (); /* EMIT SIGNAL */ + } + + return 0; +} + int AudioTrack::deprecated_use_diskstream_connections () { diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc index 2f0ae03f2d..a3ba886e38 100644 --- a/libs/ardour/audioregion.cc +++ b/libs/ardour/audioregion.cc @@ -306,6 +306,12 @@ AudioRegion::AudioRegion (SourceList& srcs, const XMLNode& node) AudioRegion::~AudioRegion () { + if (_playlist) { + for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { + (*i)->remove_playlist (_playlist); + } + } + notify_callbacks (); GoingAway (); /* EMIT SIGNAL */ } @@ -1145,8 +1151,6 @@ AudioRegion::exportme (Session& session, AudioExportSpecification& spec) boost::shared_ptr AudioRegion::get_parent() { - boost::shared_ptr r; - if (_playlist) { boost::shared_ptr ar; boost::shared_ptr grrr2 = boost::dynamic_pointer_cast (shared_from_this()); @@ -1156,7 +1160,7 @@ AudioRegion::get_parent() } } - return r; + return boost::shared_ptr(); } void @@ -1305,6 +1309,37 @@ AudioRegion::source_offset_changed () } } +void +AudioRegion::set_playlist (Playlist* pl) +{ + if (pl == _playlist) { + return; + } + + Playlist* old_playlist = _playlist; + + Region::set_playlist (pl); + + if (pl) { + if (old_playlist) { + for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { + (*i)->remove_playlist (old_playlist); + (*i)->add_playlist (_playlist); + } + } else { + for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { + (*i)->add_playlist (_playlist); + } + } + } else { + if (old_playlist) { + for (SourceList::const_iterator i = sources.begin(); i != sources.end(); ++i) { + (*i)->remove_playlist (old_playlist); + } + } + } +} + extern "C" { int region_read_peaks_from_c (void *arg, uint32_t npeaks, uint32_t start, uint32_t cnt, intptr_t data, uint32_t n_chan, double samples_per_unit) diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 9e83c5e21a..7b3db9aab4 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -392,14 +392,14 @@ Diskstream::set_name (string str) } void -Diskstream::set_destructive (bool yn) +Diskstream::remove_region_from_last_capture (boost::weak_ptr wregion) { - if (yn != destructive()) { - reset_write_sources (true, true); - if (yn) { - _flags |= Destructive; - } else { - _flags &= ~Destructive; - } + boost::shared_ptr region (wregion.lock()); + + if (!region) { + return; } + + _last_capture_regions.remove (region); } + diff --git a/libs/ardour/playlist.cc b/libs/ardour/playlist.cc index 713558f15e..a06fe2b5fd 100644 --- a/libs/ardour/playlist.cc +++ b/libs/ardour/playlist.cc @@ -85,10 +85,8 @@ Playlist::Playlist (Session& sess, const XMLNode& node, bool hide) { init (hide); _name = "unnamed"; /* reset by set_state */ - - if (set_state (node)) { - throw failed_constructor(); - } + + /* derived class calls set_state() */ } Playlist::Playlist (const Playlist& other, string namestr, bool hide) @@ -257,11 +255,19 @@ Playlist::Playlist (Playlist& pl) Playlist::~Playlist () { + { + RegionLock rl (this); + + for (set >::iterator i = all_regions.begin(); i != all_regions.end(); ++i) { + (*i)->set_playlist (0); + } + } + /* GoingAway must be emitted by derived classes */ } void -Playlist::set_name (const string& str) +Playlist::set_name (string str) { /* in a typical situation, a playlist is being used by one diskstream and also is referenced by the @@ -1442,13 +1448,21 @@ Playlist::state (bool full_state) bool Playlist::empty() const { + RegionLock rlock (const_cast(this), false); return regions.empty(); } +uint32_t +Playlist::n_regions() const +{ + RegionLock rlock (const_cast(this), false); + return regions.size(); +} + nframes_t Playlist::get_maximum_extent () const { - RegionLock rlock (const_cast(this)); + RegionLock rlock (const_cast(this), false); return _get_maximum_extent (); } @@ -1475,7 +1489,7 @@ Playlist::bump_name (string name, Session &session) do { newname = Playlist::bump_name_once (newname); - } while (session.playlist_by_name(newname)!=NULL); + } while (session.playlist_by_name (newname)!=NULL); return newname; } diff --git a/libs/ardour/region_factory.cc b/libs/ardour/region_factory.cc index 313bb31f2a..5bcbdb8b80 100644 --- a/libs/ardour/region_factory.cc +++ b/libs/ardour/region_factory.cc @@ -93,8 +93,7 @@ RegionFactory::create (Session& session, XMLNode& node, bool yn) boost::shared_ptr RegionFactory::create (SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Region::Flag flags, bool announce) { - AudioRegion* ar = new AudioRegion (srcs, start, length, name, layer, flags); - boost::shared_ptr arp (ar); + boost::shared_ptr arp (new AudioRegion (srcs, start, length, name, layer, flags)); boost::shared_ptr ret (boost::static_pointer_cast (arp)); if (announce) { CheckNewRegion (ret); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index b2705c2cbd..a4def58bb4 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2535,7 +2535,7 @@ Session::remove_region (boost::weak_ptr weak_region) set_dirty(); if (removed) { - AudioRegionRemoved(ar); /* EMIT SIGNAL */ + AudioRegionRemoved (ar); /* EMIT SIGNAL */ } } @@ -2571,32 +2571,38 @@ Session::find_equivalent_playlist_regions (boost::shared_ptr region, vec int Session::destroy_region (boost::shared_ptr region) { - boost::shared_ptr aregion; - - if ((aregion = boost::dynamic_pointer_cast (region)) == 0) { - return 0; - } - - if (aregion->playlist()) { - aregion->playlist()->destroy_region (region); - } - vector > srcs; - - for (uint32_t n = 0; n < aregion->n_channels(); ++n) { - srcs.push_back (aregion->source (n)); + + { + boost::shared_ptr aregion; + + if ((aregion = boost::dynamic_pointer_cast (region)) == 0) { + return 0; + } + + if (aregion->playlist()) { + aregion->playlist()->destroy_region (region); + } + + for (uint32_t n = 0; n < aregion->n_channels(); ++n) { + srcs.push_back (aregion->source (n)); + } } + region->drop_references (); + for (vector >::iterator i = srcs.begin(); i != srcs.end(); ++i) { - - if ((*i).use_count() == 1) { - boost::shared_ptr afs = boost::dynamic_pointer_cast(*i); + if (!(*i)->used()) { + boost::shared_ptr afs = boost::dynamic_pointer_cast(*i); + if (afs) { (afs)->mark_for_remove (); } (*i)->drop_references (); + + cerr << "source was not used by any playlist\n"; } } @@ -2988,6 +2994,20 @@ Session::add_playlist (Playlist* playlist) PlaylistAdded (playlist); /* EMIT SIGNAL */ } +void +Session::get_playlists (vector& s) +{ + { + Glib::Mutex::Lock lm (playlist_lock); + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { + s.push_back (*i); + } + for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { + s.push_back (*i); + } + } +} + void Session::track_playlist (Playlist* pl, bool inuse) { diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 763f8b9c01..f80c9e9a82 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -520,7 +520,6 @@ Session::create (bool& new_session, string* mix_template, nframes_t initial_leng _state_of_the_state = Clean; if (save_state (_current_snapshot_name)) { - save_history (_current_snapshot_name); return -1; } @@ -2456,6 +2455,8 @@ Session::cleanup_sources (Session::cleanup_report& rep) capture files. */ + cerr << "checking out source " << i->second->name() << " use_count = " << i->second.use_count() << endl; + if (i->second.use_count() == 1 && i->second->length() > 0) { dead_sources.push_back (i->second); diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc index 3c3798c8ab..4b9c7ff33b 100644 --- a/libs/ardour/sndfilesource.cc +++ b/libs/ardour/sndfilesource.cc @@ -212,7 +212,7 @@ SndFileSource::init (string idstr) _capture_end = false; file_pos = 0; - if (destructive()) { + if (destructive()) { xfade_buf = new Sample[xfade_frames]; timeline_position = header_position_offset; } @@ -680,11 +680,15 @@ SndFileSource::set_destructive (bool yn) { if (yn) { _flags = Flag (_flags | Destructive); + if (!xfade_buf) { + xfade_buf = new Sample[xfade_frames]; + } clear_capture_marks (); timeline_position = header_position_offset; } else { _flags = Flag (_flags & ~Destructive); timeline_position = 0; + /* leave xfade buf alone in case we need it again later */ } return true; diff --git a/libs/ardour/source.cc b/libs/ardour/source.cc index 7ade8a8573..74ca0afcd4 100644 --- a/libs/ardour/source.cc +++ b/libs/ardour/source.cc @@ -34,6 +34,7 @@ #include #include +#include #include "i18n.h" @@ -47,12 +48,14 @@ Source::Source (Session& s, string name) { _name = name; _timestamp = 0; + _in_use = 0; } Source::Source (Session& s, const XMLNode& node) : _session (s) { _timestamp = 0; + _in_use = 0; if (set_state (node)) { throw failed_constructor(); @@ -106,3 +109,24 @@ Source::set_state (const XMLNode& node) return 0; } +void +Source::add_playlist (Playlist* pl) +{ + _playlists.insert (pl); +} + +void +Source::remove_playlist (Playlist* pl) +{ + std::set::iterator x; + + if ((x = _playlists.find (pl)) != _playlists.end()) { + _playlists.erase (x); + } +} + +uint32_t +Source::used () const +{ + return _playlists.size(); +} diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index 2c3d7c9151..95e21e6735 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -183,18 +183,6 @@ Track::set_record_enable (bool yn, void *src) _rec_enable_control.Changed (); } -void -Track::set_mode (TrackMode m) -{ - if (_diskstream) { - if (_mode != m) { - _mode = m; - _diskstream->set_destructive (m == Destructive); - ModeChanged(); - } - } -} - int Track::set_name (string str, void *src) { diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc index eefe6ca843..734c4b77e2 100644 --- a/libs/gtkmm2ext/barcontroller.cc +++ b/libs/gtkmm2ext/barcontroller.cc @@ -423,6 +423,7 @@ BarController::switch_to_spinner () remove (); add (spinner); spinner.show (); + spinner.select_region (0, spinner.get_text_length()); spinner.grab_focus (); switching = false; -- cgit v1.2.3