Glib::RefPtr<Gdk::Pixbuf> RouteTimeAxisView::slider;
-int
+void
RouteTimeAxisView::setup_slider_pix ()
{
- slider = ::get_icon ("fader_belt_h");
- return 0;
+ if ((slider = ::get_icon ("fader_belt_h")) == 0) {
+ throw failed_constructor ();
+ }
}
RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::shared_ptr<Route> rt, Canvas& canvas)
size_button (_("h")), // height
automation_button (_("a")),
visual_button (_("v")),
- lm (rt, sess),
- gain_slider (0),
- gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1),
- ignore_gain_adjustment (false)
+ gm (sess, slider, true)
{
- if (slider == 0) {
- setup_slider_pix ();
- }
+ gm.set_io (rt);
+ gm.get_level_meter().set_no_show_all();
+ gm.get_level_meter().setup_meters(50);
- lm.set_no_show_all();
- lm.setup_meters(50);
_has_state = true;
playlist_menu = 0;
playlist_action_menu = 0;
destructive_track_mode_item = 0;
normal_track_mode_item = 0;
- gain_slider = manage (new HSliderController (slider, &gain_adjustment, _route->gain_control(), false));
-
ignore_toggle = false;
edit_group_button.set_name ("TrackGroupButton");
visual_button.set_name ("TrackVisualButton");
hide_button.set_name ("TrackRemoveButton");
+ edit_group_button.unset_flags (Gtk::CAN_FOCUS);
+ playlist_button.unset_flags (Gtk::CAN_FOCUS);
+ automation_button.unset_flags (Gtk::CAN_FOCUS);
+ size_button.unset_flags (Gtk::CAN_FOCUS);
+ visual_button.unset_flags (Gtk::CAN_FOCUS);
+ hide_button.unset_flags (Gtk::CAN_FOCUS);
+
hide_button.add (*(manage (new Image (::get_icon("hide")))));
hide_button.show_all ();
hide_button.signal_clicked().connect (mem_fun(*this, &RouteTimeAxisView::hide_click));
solo_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::solo_press), false);
- solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release));
+ solo_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::solo_release), false);
mute_button->signal_button_press_event().connect (mem_fun(*this, &RouteUI::mute_press), false);
- mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release));
+ mute_button->signal_button_release_event().connect (mem_fun(*this, &RouteUI::mute_release), false);
if (is_track()) {
controls_table.attach (*rec_enable_button, 5, 6, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record"));
+ rec_enable_button->set_sensitive (_session.writable());
}
- controls_hbox.pack_start(lm, false, false);
+ controls_hbox.pack_start(gm.get_level_meter(), false, false);
_route->meter_change.connect (mem_fun(*this, &RouteTimeAxisView::meter_changed));
_route->input_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
_route->output_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
controls_table.attach (edit_group_button, 7, 8, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
- controls_table.attach (*gain_slider, 0, 5, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
+ controls_table.attach (gm.get_gain_slider(), 0, 5, 1, 2, Gtk::SHRINK, Gtk::SHRINK, 0, 0);
ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo"));
ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute"));
editor.ZoomChanged.connect (mem_fun(*this, &RouteTimeAxisView::reset_samples_per_unit));
ColorsChanged.connect (mem_fun (*this, &RouteTimeAxisView::color_handler));
- gain_slider->signal_button_press_event().connect (mem_fun(*this, &RouteTimeAxisView::start_gain_touch));
- gain_slider->signal_button_release_event().connect (mem_fun(*this, &RouteTimeAxisView::end_gain_touch));
- gain_slider->set_name ("TrackGainFader");
-
- gain_adjustment.signal_value_changed().connect (mem_fun(*this, &RouteTimeAxisView::gain_adjusted));
- _route->gain_changed.connect (mem_fun(*this, &RouteTimeAxisView::gain_changed));
-
- gain_slider->show_all();
+ gm.get_gain_slider().signal_scroll_event().connect(mem_fun(*this, &RouteTimeAxisView::controls_ebox_scroll), false);
+ gm.get_gain_slider().set_name ("TrackGainFader");
}
RouteTimeAxisView::~RouteTimeAxisView ()
/* map current state of the route */
update_diskstream_display ();
+ subplugin_menu.items().clear ();
_route->foreach_redirect (this, &RouteTimeAxisView::add_redirect_to_subplugin_menu);
_route->foreach_redirect (this, &RouteTimeAxisView::add_existing_redirect_automation_curves);
reset_redirect_automation_curves ();
void
RouteTimeAxisView::automation_click ()
{
- if (automation_action_menu == 0) {
- /* this seems odd, but the automation action
- menu is built as part of the display menu.
- */
- build_display_menu ();
- }
conditionally_add_to_selection ();
+ if (!automation_action_menu)
+ build_automation_action_menu ();
automation_action_menu->popup (1, gtk_get_current_event_time());
}
items.push_back (SeparatorElem());
- build_remote_control_menu ();
- build_automation_action_menu ();
-
if (!Profile->get_sae()) {
+ build_remote_control_menu ();
items.push_back (MenuElem (_("Remote Control ID"), *remote_control_menu));
+ /* rebuild this every time */
+ build_automation_action_menu ();
items.push_back (MenuElem (_("Automation"), *automation_action_menu));
items.push_back (SeparatorElem());
}
items.push_back (SeparatorElem());
items.push_back (MenuElem (_("Hide"), mem_fun(*this, &RouteTimeAxisView::hide_click)));
- items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
+ if (!Profile->get_sae()) {
+ items.push_back (MenuElem (_("Remove"), mem_fun(*this, &RouteUI::remove_this_route)));
+ } else {
+ items.push_front (SeparatorElem());
+ items.push_front (MenuElem (_("Delete"), mem_fun(*this, &RouteUI::remove_this_route)));
+ }
}
static bool __reset_item (RadioMenuItem* item)
{
int gmlen = h - 5;
bool height_changed = (height == 0) || (h != height);
- lm.setup_meters (gmlen);
+ gm.get_level_meter().setup_meters (gmlen);
TimeAxisView::set_height (h);
show_name_entry ();
hide_name_label ();
- gain_slider->show();
+ gm.get_gain_slider().show();
mute_button->show();
solo_button->show();
if (rec_enable_button)
show_name_entry ();
hide_name_label ();
- gain_slider->hide();
+ gm.get_gain_slider().hide();
mute_button->show();
solo_button->show();
if (rec_enable_button)
} else {
hide_meter ();
+
+ /* don't allow name_entry to be hidden while
+ it has focus, otherwise the GUI becomes unusable.
+ */
+
+ if (name_entry.has_focus()) {
+ if (name_entry.get_text() != _route->name()) {
+ name_entry_changed ();
+ }
+ controls_ebox.grab_focus ();
+ }
+
hide_name_entry ();
show_name_label ();
- gain_slider->hide();
+ gm.get_gain_slider().hide();
mute_button->hide();
solo_button->hide();
if (rec_enable_button)
}
}
+std::string
+RouteTimeAxisView::resolve_new_group_playlist_name(std::string &basename, vector<boost::shared_ptr<Playlist> > const & playlists)
+{
+ std::string ret(basename);
+
+ std::string group_string = "."+edit_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.c_str());
+ if (x > maxnumber) {
+ maxnumber = x;
+ }
+ }
+ }
+
+ maxnumber++;
+
+ char buf[32];
+ snprintf (buf, sizeof(buf), "%d", maxnumber);
+
+ ret = this->name()+"."+edit_group()->name()+"."+buf;
+
+ return ret;
+}
+
void
-RouteTimeAxisView::use_copy_playlist (bool prompt)
+RouteTimeAxisView::use_copy_playlist (bool prompt, vector<boost::shared_ptr<Playlist> > const & playlists_before_op)
{
string name;
return;
name = pl->name();
+
+ if (edit_group() && edit_group()->is_active()) {
+ name = resolve_new_group_playlist_name(name, playlists_before_op);
+ }
- do {
+ while (_session.playlist_by_name(name)) {
name = Playlist::bump_name (name, _session);
- } while (_session.playlist_by_name(name));
+ }
// TODO: The prompter "new" button should be de-activated if the user
// specifies a playlist name which already exists in the session.
}
void
-RouteTimeAxisView::use_new_playlist (bool prompt)
+RouteTimeAxisView::use_new_playlist (bool prompt, vector<boost::shared_ptr<Playlist> > const & playlists_before_op)
{
string name;
return;
name = pl->name();
+
+ if (edit_group() && edit_group()->is_active()) {
+ name = resolve_new_group_playlist_name(name,playlists_before_op);
+ }
- do {
+ while (_session.playlist_by_name(name)) {
name = Playlist::bump_name (name, _session);
- } while (_session.playlist_by_name(name));
+ }
if (prompt) {
nframes_t start_adjusted = session_frame_to_track_frame(start, speed);
nframes_t end_adjusted = session_frame_to_track_frame(end, speed);
- if (_view && ((top < 0.0 && bot < 0.0)) || touched (top, bot)) {
+ if ((_view && ((top < 0.0 && bot < 0.0))) || touched (top, bot)) {
_view->get_selectables (start_adjusted, end_adjusted, results);
}
}
+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 (Gtk::Menu * menu)
{
menu->set_name ("ArdourContextMenu");
playlist_items.clear();
- if (playlist_menu) {
- delete playlist_menu;
- }
-
- playlist_menu = new Menu;
- playlist_menu->set_name ("ArdourContextMenu");
-
- vector<boost::shared_ptr<Playlist> > playlists;
+ vector<boost::shared_ptr<Playlist> > playlists, playlists_ds;
boost::shared_ptr<Diskstream> ds = get_diskstream();
RadioMenuItem::Group playlist_group;
-
- _session.get_playlists (playlists);
- for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ _session.get_playlists (playlists);
- if ((*i)->get_orig_diskstream_id() == ds->id()) {
- playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name(), bind (mem_fun (*this, &RouteTimeAxisView::use_playlist),
- boost::weak_ptr<Playlist> (*i))));
+ /* find the playlists for this diskstream */
+ for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists.begin(); i != playlists.end(); ++i) {
+ if (((*i)->get_orig_diskstream_id() == ds->id()) || (ds->playlist()->id() == (*i)->id())) {
+ playlists_ds.push_back(*i);
+ }
+ }
+
+ /* sort the playlists */
+ PlaylistSorter cmp;
+ sort(playlists_ds.begin(), playlists_ds.end(), cmp);
+
+ /* add the playlists to the menu */
+ for (vector<boost::shared_ptr<Playlist> >::iterator i = playlists_ds.begin(); i != playlists_ds.end(); ++i) {
+ playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name()));
+ RadioMenuItem *item = static_cast<RadioMenuItem*>(&playlist_items.back());
- if (ds->playlist()->id() == (*i)->id()) {
- static_cast<RadioMenuItem*>(&playlist_items.back())->set_active();
- }
- } else if (ds->playlist()->id() == (*i)->id()) {
- playlist_items.push_back (RadioMenuElem (playlist_group, (*i)->name(), bind (mem_fun (*this, &RouteTimeAxisView::use_playlist),
- boost::weak_ptr<Playlist>(*i))));
- static_cast<RadioMenuItem*>(&playlist_items.back())->set_active();
-
+ item->signal_toggled().connect(bind (mem_fun (*this, &RouteTimeAxisView::use_playlist), item, boost::weak_ptr<Playlist> (*i)));
+
+ if (ds->playlist()->id() == (*i)->id()) {
+ item->set_active();
}
}
playlist_items.push_back (MenuElem (_("Rename"), mem_fun(*this, &RouteTimeAxisView::rename_current_playlist)));
playlist_items.push_back (SeparatorElem());
- playlist_items.push_back (MenuElem (_("New"), bind(mem_fun(editor, &PublicEditor::new_playlists), this)));
- playlist_items.push_back (MenuElem (_("New Copy"), bind(mem_fun(editor, &PublicEditor::copy_playlists), this)));
+ if (!edit_group() || !edit_group()->is_active()) {
+ playlist_items.push_back (MenuElem (_("New"), bind(mem_fun(editor, &PublicEditor::new_playlists), this)));
+ playlist_items.push_back (MenuElem (_("New Copy"), bind(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"), bind(mem_fun(editor, &PublicEditor::new_playlists), this)));
+ playlist_items.push_back (MenuElem (_("Copy Take"), bind(mem_fun(editor, &PublicEditor::copy_playlists), this)));
+ }
+
playlist_items.push_back (SeparatorElem());
playlist_items.push_back (MenuElem (_("Clear Current"), bind(mem_fun(editor, &PublicEditor::clear_playlists), this)));
playlist_items.push_back (SeparatorElem());
-
playlist_items.push_back (MenuElem(_("Select from all ..."), mem_fun(*this, &RouteTimeAxisView::show_playlist_selector)));
}
void
-RouteTimeAxisView::use_playlist (boost::weak_ptr<Playlist> wpl)
+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) {
boost::shared_ptr<AudioPlaylist> apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl);
if (apl) {
+ if (get_diskstream()->playlist() == apl) {
+ // exit when use_playlist is called by the creation of the playlist menu
+ // or the playlist choice is unchanged
+ return;
+ }
+
get_diskstream()->use_playlist (apl);
+
+ if (edit_group() && edit_group()->is_active()) {
+ //PBD::stacktrace(cerr, 20);
+ std::string group_string = "."+edit_group()->name()+".";
+
+ std::string take_name = apl->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
+
+ for (list<Route*>::const_iterator i = edit_group()->route_list().begin(); i != edit_group()->route_list().end(); ++i) {
+ if ( (*i) == this->route().get()) {
+ continue;
+ }
+
+ std::string playlist_name = (*i)->name()+group_string+take_name;
+
+ Track *track = dynamic_cast<Track *>(*i);
+ if (!track) {
+ continue;
+ }
+
+ boost::shared_ptr<Playlist> ipl = session().playlist_by_name(playlist_name);
+ if (!ipl) {
+ // No playlist for this track for this take yet, make it
+ track->diskstream()->use_new_playlist();
+ track->diskstream()->playlist()->set_name(playlist_name);
+ } else {
+ track->diskstream()->use_playlist(ipl);
+ }
+
+ //(*i)->get_dis
+ }
+ }
}
}
using namespace Menu_Helpers;
RedirectAutomationInfo *rai;
list<RedirectAutomationInfo*>::iterator x;
-
+
const std::set<uint32_t>& automatable = r->what_can_be_automated ();
std::set<uint32_t> has_visible_automation;
if (showit != ran->view->marked_for_display()) {
if (showit) {
+ ran->menu_item->set_active(true);
ran->view->set_marked_for_display (true);
ran->view->canvas_display->show();
+ ran->view->canvas_background->show();
} else {
+ ran->menu_item->set_active(false);
rai->redirect->mark_automation_visible (ran->what, true);
ran->view->set_marked_for_display (false);
ran->view->hide ();
++tmp;
if (!(*i)->valid) {
-
+
delete *i;
redirect_automation.erase (i);
void
RouteTimeAxisView::fast_update ()
{
- lm.update_meters ();
+ gm.get_level_meter().update_meters ();
}
void
RouteTimeAxisView::hide_meter ()
{
clear_meter ();
- lm.hide_meters ();
+ gm.get_level_meter().hide_meters ();
}
void
RouteTimeAxisView::reset_meter ()
{
if (Config->get_show_track_meters()) {
- lm.setup_meters (height-5);
+ gm.get_level_meter().setup_meters (height-5);
} else {
hide_meter ();
}
void
RouteTimeAxisView::clear_meter ()
{
- lm.clear_meters ();
+ gm.get_level_meter().clear_meters ();
}
void
reset_meter ();
}
-gint
-RouteTimeAxisView::start_gain_touch (GdkEventButton* ev)
-{
- _route->start_gain_touch ();
- return FALSE;
-}
-
-gint
-RouteTimeAxisView::end_gain_touch (GdkEventButton* ev)
-{
- _route->end_gain_touch ();
- return FALSE;
-}
-
-void
-RouteTimeAxisView::gain_adjusted ()
-{
- if (ignore_gain_adjustment) {
- return;
- }
-
- _route->set_gain (slider_position_to_gain (gain_adjustment.get_value()), this);
-}
-
-void
-RouteTimeAxisView::gain_changed (void *src)
-{
- Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &RouteTimeAxisView::effective_gain_display));
-}
-
-void
-RouteTimeAxisView::effective_gain_display ()
-{
- gfloat value = gain_to_slider_position (_route->effective_gain());
- ignore_gain_adjustment = true;
- gain_adjustment.set_value (value);
- ignore_gain_adjustment = false;
-}