Playlist UI tweaks: relax requirement that playlists have a discrete name, and use pgroup for organization instead

This commit is contained in:
Ben Loftis 2021-05-31 21:00:59 -05:00
parent 0e86e3337c
commit b339d083a8
4 changed files with 135 additions and 107 deletions

View File

@ -58,6 +58,7 @@
#include "pbd/unwind.h"
#include "pbd/timersub.h"
#include <glibmm/datetime.h> /*for playlist group_id */
#include <glibmm/miscutils.h>
#include <glibmm/uriutils.h>
#include <gtkmm/image.h>
@ -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<boost::shared_ptr<ARDOUR::Playlist> > 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<boost::shared_ptr<ARDOUR::Playlist> > 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<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
Editor::mapped_use_new_playlist (RouteUI& rui, uint32_t sz, std::string name, string gid, vector<boost::shared_ptr<ARDOUR::Playlist> > 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<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
Editor::mapped_use_copy_playlist (RouteUI& rui, uint32_t sz, std::string name, string gid, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
{
rui.use_new_playlist (playlists, true);
rui.use_new_playlist (name, gid, playlists, true);
}
void

View File

@ -784,8 +784,8 @@ private:
void mapped_get_equivalent_regions (RouteTimeAxisView&, uint32_t, RegionView*, std::vector<RegionView*>*) const;
void mapover_routes (sigc::slot<void, RouteUI&, uint32_t> sl, RouteUI*, PBD::PropertyID) const;
void mapped_use_new_playlist (RouteUI&, uint32_t, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_use_copy_playlist (RouteUI&, uint32_t, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_use_new_playlist (RouteUI&, uint32_t, std::string name, std::string gid, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_use_copy_playlist (RouteUI&, uint32_t, std::string name, std::string gid, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_clear_playlist (RouteUI&, uint32_t);
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);

View File

@ -2435,10 +2435,8 @@ RouteUI::resolve_new_group_playlist_name (std::string const& basename, vector<bo
}
void
RouteUI::use_new_playlist (vector<boost::shared_ptr<Playlist> > const& playlists_before_op, bool copy)
RouteUI::use_new_playlist (std::string name, std::string gid, vector<boost::shared_ptr<Playlist> > const& playlists_before_op, bool copy)
{
string name;
boost::shared_ptr<Track> tr = track ();
if (!tr) {
return;
@ -2449,59 +2447,13 @@ RouteUI::use_new_playlist (vector<boost::shared_ptr<Playlist> > 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<Playlist> a, boost::shared_ptr<Playlist> 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<boost::shared_ptr<Playlist> >::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<RadioMenuItem*>(&playlist_items.back());
item->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::use_playlist), item, boost::weak_ptr<Playlist> (*i)));
@ -2624,44 +2572,65 @@ RouteUI::use_playlist (RadioMenuItem *item, boost::weak_ptr<Playlist> 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<RouteList> 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<RouteList> 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> track = boost::dynamic_pointer_cast<Track>(*i);
if (!track) {
continue;
}
boost::shared_ptr<Playlist> 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> track = boost::dynamic_pointer_cast<Track>(*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<RouteList> 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> track = boost::dynamic_pointer_cast<Track>(*i);
if (!track) {
continue;
}
if (track->freeze_state() == Track::Frozen) {
/* Don't change playlists of frozen tracks */
continue;
}
boost::shared_ptr<Playlist> 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<Playlist> 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);

View File

@ -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<boost::shared_ptr<ARDOUR::Playlist> > const&, bool copy);
void use_new_playlist (std::string name, std::string group_id, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const&, bool copy);
void clear_playlist ();
void use_playlist (Gtk::RadioMenuItem* item, boost::weak_ptr<ARDOUR::Playlist> wpl);