From b339d083a8179b439486fcb526e7eff1d6b75f16 Mon Sep 17 00:00:00 2001 From: Ben Loftis Date: Mon, 31 May 2021 21:00:59 -0500 Subject: [PATCH] Playlist UI tweaks: relax requirement that playlists have a discrete name, and use pgroup for organization instead --- gtk2_ardour/editor.cc | 72 ++++++++++++++++-- gtk2_ardour/editor.h | 4 +- gtk2_ardour/route_ui.cc | 164 ++++++++++++++++------------------------ gtk2_ardour/route_ui.h | 2 +- 4 files changed, 135 insertions(+), 107 deletions(-) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 7f07561ba8..ff35f40c71 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -58,6 +58,7 @@ #include "pbd/unwind.h" #include "pbd/timersub.h" +#include /*for playlist group_id */ #include #include #include @@ -96,6 +97,7 @@ #include "widgets/ardour_spacer.h" #include "widgets/eventboxext.h" #include "widgets/tooltips.h" +#include "widgets/prompter.h" #include "control_protocol/control_protocol.h" @@ -4360,10 +4362,39 @@ Editor::restore_editing_space () void Editor::new_playlists (RouteUI* rui) { + time_t now; + time (&now); + Glib::DateTime tm (Glib::DateTime::create_now_local (now)); + string gid (tm.format ("%F %H.%M.%S")); + string name(gid); + + Prompter prompter (true); + prompter.set_title (_("New Playlist")); + prompter.set_prompt (_("Name for new playlist:")); + prompter.set_initial_text (name); + prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); + prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, true); + prompter.show_all (); + + while (true) { + if (prompter.run () != Gtk::RESPONSE_ACCEPT) { + return; + } + prompter.get_result (name); + if (name.length()) { + if (_session->playlists()->by_name (name)) { + prompter.set_prompt (_("That name is already in use. Use this instead?")); + prompter.set_initial_text (Playlist::bump_name (name, *_session)); + } else { + break; + } + } + } + /* begin_reversible_command (_("new playlists")); */ /* ToDo: this does not work */ vector > playlists; _session->playlists()->get (playlists); - mapover_routes (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), rui, ARDOUR::Properties::group_select.property_id); + mapover_routes (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), name, gid, playlists), rui, ARDOUR::Properties::group_select.property_id); /* commit_reversible_command (); */ } @@ -4376,10 +4407,39 @@ Editor::new_playlists (RouteUI* rui) void Editor::copy_playlists (RouteUI* rui) { + time_t now; + time (&now); + Glib::DateTime tm (Glib::DateTime::create_now_local (now)); + string gid (tm.format ("%F %H.%M.%S")); + string name(gid); + + Prompter prompter (true); + prompter.set_title (_("New Playlist")); + prompter.set_prompt (_("Name for new playlist:")); + prompter.set_initial_text (name); + prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); + prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, true); + prompter.show_all (); + + while (true) { + if (prompter.run () != Gtk::RESPONSE_ACCEPT) { + return; + } + prompter.get_result (name); + if (name.length()) { + if (_session->playlists()->by_name (name)) { + prompter.set_prompt (_("That name is already in use. Use this instead?")); + prompter.set_initial_text (Playlist::bump_name (name, *_session)); + } else { + break; + } + } + } + /* begin_reversible_command (_("copy playlists")); */ /* ToDo: this does not work */ vector > playlists; _session->playlists()->get (playlists); - mapover_routes (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), rui, ARDOUR::Properties::group_select.property_id); + mapover_routes (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), name, gid, playlists), rui, ARDOUR::Properties::group_select.property_id); /* commit_reversible_command (); */ } @@ -4399,15 +4459,15 @@ Editor::clear_playlists (RouteUI* rui) } void -Editor::mapped_use_new_playlist (RouteUI& rui, uint32_t sz, vector > const & playlists) +Editor::mapped_use_new_playlist (RouteUI& rui, uint32_t sz, std::string name, string gid, vector > const & playlists) { - rui.use_new_playlist (playlists, false); + rui.use_new_playlist (name, gid, playlists, false); } void -Editor::mapped_use_copy_playlist (RouteUI& rui, uint32_t sz, vector > const & playlists) +Editor::mapped_use_copy_playlist (RouteUI& rui, uint32_t sz, std::string name, string gid, vector > const & playlists) { - rui.use_new_playlist (playlists, true); + rui.use_new_playlist (name, gid, playlists, true); } void diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 13ab2af5af..0537f00ef2 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -784,8 +784,8 @@ private: void mapped_get_equivalent_regions (RouteTimeAxisView&, uint32_t, RegionView*, std::vector*) const; void mapover_routes (sigc::slot sl, RouteUI*, PBD::PropertyID) const; - void mapped_use_new_playlist (RouteUI&, uint32_t, std::vector > const &); - void mapped_use_copy_playlist (RouteUI&, uint32_t, std::vector > const &); + void mapped_use_new_playlist (RouteUI&, uint32_t, std::string name, std::string gid, std::vector > const &); + void mapped_use_copy_playlist (RouteUI&, uint32_t, std::string name, std::string gid, std::vector > const &); void mapped_clear_playlist (RouteUI&, uint32_t); void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type); diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index bf981de836..7e9168cbed 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -2435,10 +2435,8 @@ RouteUI::resolve_new_group_playlist_name (std::string const& basename, vector > const& playlists_before_op, bool copy) +RouteUI::use_new_playlist (std::string name, std::string gid, vector > const& playlists_before_op, bool copy) { - string name; - boost::shared_ptr tr = track (); if (!tr) { return; @@ -2449,59 +2447,13 @@ RouteUI::use_new_playlist (vector > const& playlists return; } - name = pl->name(); - - if (route_group() && route_group()->is_active() && route_group()->enabled_property (ARDOUR::Properties::group_select.property_id)) { - name = resolve_new_group_playlist_name (name, playlists_before_op); - } - - while (_session->playlists()->by_name(name)) { - name = Playlist::bump_name (name, *_session); - } - - { - // TODO: The prompter "new" button should be de-activated if the user - // specifies a playlist name which already exists in the session. - - Prompter prompter (true); - - if (copy) { - prompter.set_title (_("New Copy Playlist")); - prompter.set_prompt (_("Name for playlist copy:")); - } else { - prompter.set_title (_("New Playlist")); - prompter.set_prompt (_("Name for new playlist:")); - } - prompter.set_initial_text (name); - prompter.add_button (Gtk::Stock::NEW, Gtk::RESPONSE_ACCEPT); - prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, true); - prompter.show_all (); - - while (true) { - if (prompter.run () != Gtk::RESPONSE_ACCEPT) { - return; - } - prompter.get_result (name); - if (name.length()) { - if (_session->playlists()->by_name (name)) { - MessageDialog msg (_("Given playlist name is not unique.")); - msg.run (); - prompter.set_initial_text (Playlist::bump_name (name, *_session)); - } else { - break; - } - } - } - } - - if (name.length()) { - if (copy) { - tr->use_copy_playlist (); - } else { - tr->use_default_new_playlist (); - } - tr->playlist()->set_name (name); + if (copy) { + tr->use_copy_playlist (); + } else { + tr->use_default_new_playlist (); } + tr->playlist()->set_name (name); + tr->playlist()->set_pgroup_id (gid); } void @@ -2520,13 +2472,6 @@ RouteUI::clear_playlist () ARDOUR_UI::instance()->the_editor().clear_playlist (pl); } - -struct PlaylistSorter { - bool operator() (boost::shared_ptr a, boost::shared_ptr b) const { - return a->sort_id() < b->sort_id(); - } -}; - void RouteUI::build_playlist_menu () { @@ -2557,7 +2502,10 @@ RouteUI::build_playlist_menu () /* add the playlists to the menu */ for (vector >::iterator i = playlists_tr.begin(); i != playlists_tr.end(); ++i) { - playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name())); + string text = (*i)->name(); + if ((*i)->pgroup_id().length()>0) + text.append( string_compose( " (%1)", (*i)->pgroup_id())); + playlist_items.push_back (RadioMenuElem (playlist_group, text)); RadioMenuItem *item = static_cast(&playlist_items.back()); item->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::use_playlist), item, boost::weak_ptr (*i))); @@ -2624,44 +2572,65 @@ RouteUI::use_playlist (RadioMenuItem *item, boost::weak_ptr wpl) RouteGroup* rg = route_group(); if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::group_select.property_id)) { - std::string group_string = "." + rg->name() + "."; - std::string take_name = pl->name(); - std::string::size_type idx = take_name.find(group_string); - - if (idx == std::string::npos) - return; - - take_name = take_name.substr(idx + group_string.length()); // find the bit containing the take number / name - - boost::shared_ptr rl (rg->route_list()); - - for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) { - if ((*i) == this->route()) { - continue; + std::string pgrp_id = pl->pgroup_id(); + if (pgrp_id.length()>0) { //easy: find other pl's with the same group id + boost::shared_ptr rl (rg->route_list()); + for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) { + if ((*i) == this->route()) { + continue; + } + if ((*i)->route_group() != rg) { + continue; + } + boost::shared_ptr track = boost::dynamic_pointer_cast(*i); + if (!track) { + continue; + } + boost::shared_ptr ipl = session()->playlists()->for_pgroup(pgrp_id, track->id()); + if (ipl) { + track->use_playlist(track->data_type(), ipl); + } } + } else { //fallback to prior behavior ... try to find matching names /*DEPRECATED*/ + std::string take_name = pl->name(); + std::string group_string = "." + rg->name() + "."; - std::string playlist_name = (*i)->name()+group_string+take_name; + std::string::size_type idx = take_name.find(group_string); - boost::shared_ptr track = boost::dynamic_pointer_cast(*i); - if (!track) { - continue; + if (idx == std::string::npos) + return; + + take_name = take_name.substr(idx + group_string.length()); // find the bit containing the take number / name + + boost::shared_ptr rl (rg->route_list()); + for (RouteList::const_iterator i = rl->begin(); i != rl->end(); ++i) { + if ((*i) == this->route()) { + continue; + } + + std::string playlist_name = (*i)->name()+group_string+take_name; + + boost::shared_ptr track = boost::dynamic_pointer_cast(*i); + if (!track) { + continue; + } + + if (track->freeze_state() == Track::Frozen) { + /* Don't change playlists of frozen tracks */ + continue; + } + + boost::shared_ptr ipl = session()->playlists()->by_name(playlist_name); + if (!ipl) { + // No playlist for this track for this take yet, make it + track->use_default_new_playlist(); + track->playlist()->set_name(playlist_name); + } else { + track->use_playlist(track->data_type(), ipl); + } } - - if (track->freeze_state() == Track::Frozen) { - /* Don't change playlists of frozen tracks */ - continue; - } - - boost::shared_ptr ipl = session()->playlists()->by_name(playlist_name); - if (!ipl) { - // No playlist for this track for this take yet, make it - track->use_default_new_playlist(); - track->playlist()->set_name(playlist_name); - } else { - track->use_playlist(track->data_type(), ipl); - } - } + } //fallback } } @@ -2734,8 +2703,7 @@ RouteUI::rename_current_playlist () prompter.get_result (name); if (name.length()) { if (_session->playlists()->by_name (name)) { - MessageDialog msg (_("Given playlist name is not unique.")); - msg.run (); + prompter.set_prompt (_("That name is already in use. Use this instead?")); prompter.set_initial_text (Playlist::bump_name (name, *_session)); } else { pl->set_name (name); diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h index 838e4e14ae..18991a546d 100644 --- a/gtk2_ardour/route_ui.h +++ b/gtk2_ardour/route_ui.h @@ -158,7 +158,7 @@ public: void fan_out (bool to_busses = true, bool group = true); /* The editor calls these when mapping an operation across multiple tracks */ - void use_new_playlist (std::vector > const&, bool copy); + void use_new_playlist (std::string name, std::string group_id, std::vector > const&, bool copy); void clear_playlist (); void use_playlist (Gtk::RadioMenuItem* item, boost::weak_ptr wpl);