Playlist UI tweaks: relax requirement that playlists have a discrete name, and use pgroup for organization instead
This commit is contained in:
parent
0e86e3337c
commit
b339d083a8
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue