Move Playlist GUI functions to RouteUI

This allows to re-use playlist editing in all RouteUI derivatives,
not just the main editor time axis header.

The change is mostly a NO-OP, simply moving methods from
RouteTimeAxisView (is-a RouteUI), to RouteUI.
This commit is contained in:
Robin Gareus 2021-01-25 23:52:39 +01:00
parent e78de225d4
commit cf6e785ed3
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
8 changed files with 385 additions and 384 deletions

View File

@ -4329,12 +4329,12 @@ Editor::restore_editing_space ()
*/
void
Editor::new_playlists (TimeAxisView* v)
Editor::new_playlists (RouteUI* rui)
{
begin_reversible_command (_("new playlists"));
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
_session->playlists()->get (playlists);
mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
mapover_routes (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), rui, ARDOUR::Properties::group_select.property_id);
commit_reversible_command ();
}
@ -4345,12 +4345,12 @@ Editor::new_playlists (TimeAxisView* v)
*/
void
Editor::copy_playlists (TimeAxisView* v)
Editor::copy_playlists (RouteUI* rui)
{
begin_reversible_command (_("copy playlists"));
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
_session->playlists()->get (playlists);
mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
mapover_routes (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), rui, ARDOUR::Properties::group_select.property_id);
commit_reversible_command ();
}
@ -4360,31 +4360,31 @@ Editor::copy_playlists (TimeAxisView* v)
*/
void
Editor::clear_playlists (TimeAxisView* v)
Editor::clear_playlists (RouteUI* rui)
{
begin_reversible_command (_("clear playlists"));
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
_session->playlists()->get (playlists);
mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::group_select.property_id);
mapover_routes (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), rui, ARDOUR::Properties::group_select.property_id);
commit_reversible_command ();
}
void
Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
Editor::mapped_use_new_playlist (RouteUI& rui, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
{
atv.use_new_playlist (sz > 1 ? false : true, playlists, false);
rui.use_new_playlist (sz > 1 ? false : true, playlists, false);
}
void
Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
Editor::mapped_use_copy_playlist (RouteUI& rui, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
{
atv.use_new_playlist (sz > 1 ? false : true, playlists, true);
rui.use_new_playlist (sz > 1 ? false : true, playlists, true);
}
void
Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
Editor::mapped_clear_playlist (RouteUI& rui, uint32_t /*sz*/)
{
atv.clear_playlist ();
rui.clear_playlist ();
}
double

View File

@ -332,9 +332,9 @@ public:
PlaylistSelector& playlist_selector() const;
void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>);
void new_playlists (TimeAxisView* v);
void copy_playlists (TimeAxisView* v);
void clear_playlists (TimeAxisView* v);
void new_playlists (RouteUI* v);
void copy_playlists (RouteUI* v);
void clear_playlists (RouteUI* v);
void get_onscreen_tracks (TrackViewList&);
@ -763,14 +763,14 @@ private:
RegionView* regionview_from_region (boost::shared_ptr<ARDOUR::Region>) const;
RouteTimeAxisView* rtav_from_route (boost::shared_ptr<ARDOUR::Route>) const;
void mapover_tracks (sigc::slot<void,RouteTimeAxisView&,uint32_t> sl, TimeAxisView*, PBD::PropertyID) const;
void mapover_tracks_with_unique_playlists (sigc::slot<void,RouteTimeAxisView&,uint32_t> sl, TimeAxisView*, PBD::PropertyID) const;
/* functions to be passed to mapover_tracks(), possibly with sigc::bind()-supplied arguments */
void mapover_tracks_with_unique_playlists (sigc::slot<void,RouteTimeAxisView&,uint32_t> sl, TimeAxisView*, PBD::PropertyID) const;
void mapped_get_equivalent_regions (RouteTimeAxisView&, uint32_t, RegionView*, std::vector<RegionView*>*) const;
void mapped_use_new_playlist (RouteTimeAxisView&, uint32_t, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_use_copy_playlist (RouteTimeAxisView&, uint32_t, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void mapped_clear_playlist (RouteTimeAxisView&, uint32_t);
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_clear_playlist (RouteUI&, uint32_t);
void button_selection (ArdourCanvas::Item* item, GdkEvent* event, ItemType item_type);
bool button_release_can_deselect;

View File

@ -407,36 +407,30 @@ Editor::get_onscreen_tracks (TrackViewList& tvl)
*/
void
Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, PBD::PropertyID prop) const
Editor::mapover_routes (sigc::slot<void, RouteUI&, uint32_t> sl, RouteUI* basis, PBD::PropertyID prop) const
{
RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
set<RouteUI*> routes;
routes.insert (basis);
if (route_basis == 0) {
return;
}
set<RouteTimeAxisView*> tracks;
tracks.insert (route_basis);
RouteGroup* group = route_basis->route()->route_group();
RouteGroup* group = basis->route()->route_group();
if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id)) {
/* the basis is a member of an active route group, with the appropriate
properties; find other members */
* properties; find other members */
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
RouteUI* v = dynamic_cast<RouteUI*> (*i);
if (v && v->route()->route_group() == group) {
tracks.insert (v);
routes.insert (v);
}
}
}
/* call the slots */
uint32_t const sz = tracks.size ();
uint32_t const sz = routes.size ();
for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
for (set<RouteUI*>::iterator i = routes.begin(); i != routes.end(); ++i) {
sl (**i, sz);
}
}

View File

@ -288,9 +288,9 @@ public:
virtual void reset_zoom (samplecnt_t) = 0;
virtual PlaylistSelector& playlist_selector() const = 0;
virtual void clear_playlist (boost::shared_ptr<ARDOUR::Playlist>) = 0;
virtual void new_playlists (TimeAxisView*) = 0;
virtual void copy_playlists (TimeAxisView*) = 0;
virtual void clear_playlists (TimeAxisView*) = 0;
virtual void new_playlists (RouteUI*) = 0;
virtual void copy_playlists (RouteUI*) = 0;
virtual void clear_playlists (RouteUI*) = 0;
virtual void select_all_visible_lanes () = 0;
virtual void select_all_tracks () = 0;
virtual void deselect_all () = 0;

View File

@ -61,7 +61,6 @@
#include "ardour/profile.h"
#include "ardour/route_group.h"
#include "ardour/session.h"
#include "ardour/session_playlists.h"
#include "ardour/track.h"
#include "canvas/debug.h"
@ -85,7 +84,6 @@
#include "keyboard.h"
#include "paste_context.h"
#include "patch_change_widget.h"
#include "playlist_selector.h"
#include "point_selection.h"
#include "public_editor.h"
#include "region_view.h"
@ -118,7 +116,6 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session* sess, ArdourCan
, automation_action_menu (0)
, plugins_submenu_item (0)
, route_group_menu (0)
, playlist_action_menu (0)
, overlaid_menu_item (0)
, stacked_menu_item (0)
, gm (sess, true, 75, 14)
@ -348,7 +345,6 @@ RouteTimeAxisView::~RouteTimeAxisView ()
delete *i;
}
delete playlist_action_menu;
delete automation_action_menu;
delete _view;
@ -1051,167 +1047,6 @@ RouteTimeAxisView::set_align_choice (RadioMenuItem* mitem, AlignChoice choice, b
}
}
void
RouteTimeAxisView::rename_current_playlist ()
{
Prompter prompter (true);
string name;
boost::shared_ptr<Track> tr = track();
if (!tr) {
return;
}
boost::shared_ptr<Playlist> pl = tr->playlist();
if (!pl) {
return;
}
prompter.set_title (_("Rename Playlist"));
prompter.set_prompt (_("New name for playlist:"));
prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
prompter.set_initial_text (pl->name());
prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
while (true) {
if (prompter.run () != Gtk::RESPONSE_ACCEPT) {
break;
}
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 {
pl->set_name (name);
break;
}
}
}
}
std::string
RouteTimeAxisView::resolve_new_group_playlist_name(std::string &basename, vector<boost::shared_ptr<Playlist> > const & playlists)
{
std::string ret (basename);
std::string const group_string = "." + route_group()->name() + ".";
// iterate through all playlists
int maxnumber = 0;
for (vector<boost::shared_ptr<Playlist> >::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
std::string tmp = (*i)->name();
std::string::size_type idx = tmp.find(group_string);
// find those which belong to this group
if (idx != string::npos) {
tmp = tmp.substr(idx + group_string.length());
// and find the largest current number
int x = atoi(tmp);
if (x > maxnumber) {
maxnumber = x;
}
}
}
maxnumber++;
char buf[32];
snprintf (buf, sizeof(buf), "%d", maxnumber);
ret = this->name() + "." + route_group()->name () + "." + buf;
return ret;
}
void
RouteTimeAxisView::use_new_playlist (bool prompt, vector<boost::shared_ptr<Playlist> > const & playlists_before_op, bool copy)
{
string name;
boost::shared_ptr<Track> tr = track ();
if (!tr) {
return;
}
boost::shared_ptr<const Playlist> pl = tr->playlist();
if (!pl) {
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);
}
if (prompt) {
// 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);
}
}
void
RouteTimeAxisView::clear_playlist ()
{
boost::shared_ptr<Track> tr = track ();
if (!tr) {
return;
}
boost::shared_ptr<Playlist> pl = tr->playlist();
if (!pl) {
return;
}
_editor.clear_playlist (pl);
}
void
RouteTimeAxisView::speed_changed ()
{
@ -1529,174 +1364,10 @@ RouteTimeAxisView::paste (samplepos_t pos, const Selection& selection, PasteCont
}
struct PlaylistSorter {
bool operator() (boost::shared_ptr<Playlist> a, boost::shared_ptr<Playlist> b) const {
return a->sort_id() < b->sort_id();
}
};
void
RouteTimeAxisView::build_playlist_menu ()
{
using namespace Menu_Helpers;
if (!is_track()) {
return;
}
delete playlist_action_menu;
playlist_action_menu = new Menu;
playlist_action_menu->set_name ("ArdourContextMenu");
MenuList& playlist_items = playlist_action_menu->items();
playlist_action_menu->set_name ("ArdourContextMenu");
playlist_items.clear();
RadioMenuItem::Group playlist_group;
boost::shared_ptr<Track> tr = track ();
vector<boost::shared_ptr<Playlist> > playlists_tr = _session->playlists()->playlists_for_track (tr);
/* sort the playlists */
PlaylistSorter cmp;
sort (playlists_tr.begin(), playlists_tr.end(), cmp);
/* 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()));
RadioMenuItem *item = static_cast<RadioMenuItem*>(&playlist_items.back());
item->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteTimeAxisView::use_playlist), item, boost::weak_ptr<Playlist> (*i)));
if (tr->playlist()->id() == (*i)->id()) {
item->set_active();
}
}
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &RouteTimeAxisView::rename_current_playlist)));
playlist_items.push_back (SeparatorElem());
if (!route_group() || !route_group()->is_active() || !route_group()->enabled_property (ARDOUR::Properties::group_select.property_id)) {
playlist_items.push_back (MenuElem (_("New..."), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::new_playlists), this)));
playlist_items.push_back (MenuElem (_("New Copy..."), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::copy_playlists), this)));
} else {
// Use a label which tells the user what is happening
playlist_items.push_back (MenuElem (_("New Take"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::new_playlists), this)));
playlist_items.push_back (MenuElem (_("Copy Take"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::copy_playlists), this)));
}
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem (_("Clear Current"), sigc::bind(sigc::mem_fun(_editor, &PublicEditor::clear_playlists), this)));
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem(_("Select from All..."), sigc::mem_fun(*this, &RouteTimeAxisView::show_playlist_selector)));
}
void
RouteTimeAxisView::use_playlist (RadioMenuItem *item, boost::weak_ptr<Playlist> wpl)
{
assert (is_track());
// exit if we were triggered by deactivating the old playlist
if (!item->get_active()) {
return;
}
boost::shared_ptr<Playlist> pl (wpl.lock());
if (!pl) {
return;
}
if (track()->playlist() == pl) {
// exit when use_playlist is called by the creation of the playlist menu
// or the playlist choice is unchanged
return;
}
track()->use_playlist (track()->data_type(), pl);
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 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);
}
}
}
}
void
RouteTimeAxisView::update_playlist_tip ()
{
RouteGroup* rg = route_group ();
if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::group_select.property_id)) {
string group_string = "." + rg->name() + ".";
string take_name = track()->playlist()->name();
string::size_type idx = take_name.find(group_string);
if (idx != string::npos) {
/* find the bit containing the take number / name */
take_name = take_name.substr (idx + group_string.length());
/* set the playlist button tooltip to the take name */
set_tooltip (
playlist_button,
string_compose(_("Take: %1.%2"),
Gtkmm2ext::markup_escape_text (rg->name()),
Gtkmm2ext::markup_escape_text (take_name))
);
return;
}
}
/* set the playlist button tooltip to the playlist name */
set_tooltip (playlist_button, _("Playlist") + std::string(": ") + Gtkmm2ext::markup_escape_text (track()->playlist()->name()));
}
void
RouteTimeAxisView::show_playlist_selector ()
{
_editor.playlist_selector().show_for (this);
set_tooltip (playlist_button, playlist_tip ());
}
void

View File

@ -118,15 +118,6 @@ public:
void toggle_automation_track (const Evoral::Parameter& param);
void fade_range (TimeSelection&);
/* The editor calls these when mapping an operation across multiple tracks */
void use_new_playlist (bool prompt, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &, bool copy);
void clear_playlist ();
/* group playlist name resolving */
std::string resolve_new_group_playlist_name(std::string &, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &);
void build_playlist_menu ();
void add_underlay (StreamView*, bool update_xml = true);
void remove_underlay (StreamView*);
void build_underlay_menu(Gtk::Menu*);
@ -231,11 +222,8 @@ protected:
void set_align_choice (Gtk::RadioMenuItem*, ARDOUR::AlignChoice, bool apply_to_selection = false);
bool playlist_click (GdkEventButton *);
void show_playlist_selector ();
void playlist_changed ();
void rename_current_playlist ();
bool automation_click (GdkEventButton *);
void timestretch (samplepos_t start, samplepos_t end);
@ -263,12 +251,9 @@ protected:
Gtk::Menu* automation_action_menu;
Gtk::MenuItem* plugins_submenu_item;
RouteGroupMenu* route_group_menu;
Gtk::Menu* playlist_action_menu;
Gtk::MenuItem* overlaid_menu_item;
Gtk::MenuItem* stacked_menu_item;
void use_playlist (Gtk::RadioMenuItem *item, boost::weak_ptr<ARDOUR::Playlist> wpl);
ArdourCanvas::Rectangle* timestretch_rect;
/** Information about all automatable processor parameters that apply to

View File

@ -56,6 +56,7 @@
#include "ardour/send.h"
#include "ardour/route.h"
#include "ardour/session.h"
#include "ardour/session_playlists.h"
#include "ardour/template_utils.h"
#include "gtkmm2ext/gtk_ui.h"
@ -79,6 +80,7 @@
#include "mixer_strip.h"
#include "mixer_ui.h"
#include "patch_change_widget.h"
#include "playlist_selector.h"
#include "plugin_pin_dialog.h"
#include "rgb_macros.h"
#include "route_time_axis.h"
@ -114,6 +116,7 @@ RouteUI::RouteUI (ARDOUR::Session* sess)
, comment_area(0)
, input_selector (0)
, output_selector (0)
, playlist_action_menu (0)
, _invert_menu(0)
{
if (program_port_prefix.empty()) {
@ -148,6 +151,7 @@ RouteUI::~RouteUI()
delete output_selector;
delete monitor_input_button;
delete monitor_disk_button;
delete playlist_action_menu;
delete _invert_menu;
send_blink_connection.disconnect ();
@ -2357,3 +2361,336 @@ RouteUI::set_disk_io_point (DiskIOPoint diop)
track()->set_disk_io_point (diop);
}
}
std::string
RouteUI::playlist_tip () const
{
if (!is_track()) {
return "";
}
RouteGroup* rg = route_group ();
if (rg && rg->is_active() && rg->enabled_property (ARDOUR::Properties::group_select.property_id)) {
string group_string = "." + rg->name() + ".";
string take_name = track()->playlist()->name();
string::size_type idx = take_name.find(group_string);
if (idx != string::npos) {
/* find the bit containing the take number / name */
take_name = take_name.substr (idx + group_string.length());
/* set the playlist button tooltip to the take name */
return string_compose(_("Take: %1.%2"),
Gtkmm2ext::markup_escape_text (rg->name()),
Gtkmm2ext::markup_escape_text (take_name));
}
}
/* set the playlist button tooltip to the playlist name */
return _("Playlist") + std::string(": ") + Gtkmm2ext::markup_escape_text (track()->playlist()->name());
}
std::string
RouteUI::resolve_new_group_playlist_name (std::string const& basename, vector<boost::shared_ptr<Playlist> > const& playlists)
{
std::string ret (basename);
std::string const group_string = "." + route_group()->name() + ".";
// iterate through all playlists
int maxnumber = 0;
for (vector<boost::shared_ptr<Playlist> >::const_iterator i = playlists.begin(); i != playlists.end(); ++i) {
std::string tmp = (*i)->name();
std::string::size_type idx = tmp.find(group_string);
// find those which belong to this group
if (idx != string::npos) {
tmp = tmp.substr(idx + group_string.length());
// and find the largest current number
int x = atoi(tmp);
if (x > maxnumber) {
maxnumber = x;
}
}
}
maxnumber++;
char buf[32];
snprintf (buf, sizeof(buf), "%d", maxnumber);
ret = _route->name() + "." + route_group()->name () + "." + buf;
return ret;
}
void
RouteUI::use_new_playlist (bool prompt, vector<boost::shared_ptr<Playlist> > const& playlists_before_op, bool copy)
{
string name;
boost::shared_ptr<Track> tr = track ();
if (!tr) {
return;
}
boost::shared_ptr<const Playlist> pl = tr->playlist();
if (!pl) {
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);
}
if (prompt) {
// 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);
}
}
void
RouteUI::clear_playlist ()
{
boost::shared_ptr<Track> tr = track ();
if (!tr) {
return;
}
boost::shared_ptr<Playlist> pl = tr->playlist();
if (!pl) {
return;
}
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 ()
{
using namespace Menu_Helpers;
if (!is_track()) {
return;
}
PublicEditor* editor = &ARDOUR_UI::instance()->the_editor();
delete playlist_action_menu;
playlist_action_menu = new Menu;
playlist_action_menu->set_name ("ArdourContextMenu");
MenuList& playlist_items = playlist_action_menu->items();
playlist_action_menu->set_name ("ArdourContextMenu");
playlist_items.clear();
RadioMenuItem::Group playlist_group;
boost::shared_ptr<Track> tr = track ();
vector<boost::shared_ptr<Playlist> > playlists_tr = _session->playlists()->playlists_for_track (tr);
/* sort the playlists */
PlaylistSorter cmp;
sort (playlists_tr.begin(), playlists_tr.end(), cmp);
/* 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()));
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)));
if (tr->playlist()->id() == (*i)->id()) {
item->set_active();
}
}
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &RouteUI::rename_current_playlist)));
playlist_items.push_back (SeparatorElem());
if (!route_group() || !route_group()->is_active() || !route_group()->enabled_property (ARDOUR::Properties::group_select.property_id)) {
playlist_items.push_back (MenuElem (_("New..."), sigc::bind(sigc::mem_fun(editor, &PublicEditor::new_playlists), this)));
playlist_items.push_back (MenuElem (_("New Copy..."), sigc::bind(sigc::mem_fun(editor, &PublicEditor::copy_playlists), this)));
} else {
// Use a label which tells the user what is happening
playlist_items.push_back (MenuElem (_("New Take"), sigc::bind(sigc::mem_fun(editor, &PublicEditor::new_playlists), this)));
playlist_items.push_back (MenuElem (_("Copy Take"), sigc::bind(sigc::mem_fun(editor, &PublicEditor::copy_playlists), this)));
}
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem (_("Clear Current"), sigc::bind(sigc::mem_fun(editor, &PublicEditor::clear_playlists), this)));
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem(_("Select from All..."), sigc::mem_fun(*this, &RouteUI::show_playlist_selector)));
}
void
RouteUI::use_playlist (RadioMenuItem *item, boost::weak_ptr<Playlist> wpl)
{
assert (is_track());
// exit if we were triggered by deactivating the old playlist
if (!item->get_active()) {
return;
}
boost::shared_ptr<Playlist> pl (wpl.lock());
if (!pl) {
return;
}
if (track()->playlist() == pl) {
// exit when use_playlist is called by the creation of the playlist menu
// or the playlist choice is unchanged
return;
}
track()->use_playlist (track()->data_type(), pl);
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 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);
}
}
}
}
void
RouteUI::show_playlist_selector ()
{
ARDOUR_UI::instance()->the_editor().playlist_selector().show_for (this);
}
void
RouteUI::rename_current_playlist ()
{
Prompter prompter (true);
string name;
boost::shared_ptr<Track> tr = track();
if (!tr) {
return;
}
boost::shared_ptr<Playlist> pl = tr->playlist();
if (!pl) {
return;
}
prompter.set_title (_("Rename Playlist"));
prompter.set_prompt (_("New name for playlist:"));
prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
prompter.set_initial_text (pl->name());
prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
while (true) {
if (prompter.run () != Gtk::RESPONSE_ACCEPT) {
break;
}
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 {
pl->set_name (name);
break;
}
}
}
}

View File

@ -211,6 +211,12 @@ public:
void build_mute_menu(void);
void init_mute_menu(ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*);
/* The editor calls these when mapping an operation across multiple tracks */
void use_new_playlist (bool prompt, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const &, bool copy);
void clear_playlist ();
std::string resolve_new_group_playlist_name(std::string const&, std::vector<boost::shared_ptr<ARDOUR::Playlist> > const&);
int set_color_from_route ();
void route_rename();
@ -333,6 +339,14 @@ protected:
ControlSlaveUI* csu;
std::string playlist_tip () const;
void build_playlist_menu ();
void use_playlist (Gtk::RadioMenuItem *item, boost::weak_ptr<ARDOUR::Playlist> wpl);
void show_playlist_selector ();
void rename_current_playlist ();
Gtk::Menu* playlist_action_menu;
private:
void setup_invert_buttons ();
void invert_menu_toggled (uint32_t);