21 #include "gtk2ardour-config.h"
26 #include <sigc++/bind.h>
28 #include <gtkmm/accelmap.h>
33 #include <glibmm/threads.h>
40 #include "ardour/debug.h"
88 : Window (
Gtk::WINDOW_TOPLEVEL)
103 set_flags (CAN_FOCUS);
111 scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
118 VBox* b = manage (
new VBox);
124 scroller.set_policy (Gtk::POLICY_ALWAYS, Gtk::POLICY_AUTOMATIC);
132 group_display.get_column (0)->set_data (
X_(
"colnum"), GUINT_TO_POINTER(0));
133 group_display.get_column (1)->set_data (
X_(
"colnum"), GUINT_TO_POINTER(1));
137 group_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
144 CellRendererText* name_cell =
dynamic_cast<CellRendererText*
>(
group_display.get_column_cell_renderer (0));
145 name_cell->property_editable() =
true;
150 CellRendererToggle* active_cell =
dynamic_cast<CellRendererToggle*
>(
group_display.get_column_cell_renderer (1));
151 active_cell->property_activatable() =
true;
152 active_cell->property_radio() =
false;
162 HBox* route_group_display_button_box = manage (
new HBox());
164 Button* route_group_add_button = manage (
new Button ());
165 Button* route_group_remove_button = manage (
new Button ());
169 w = manage (
new Image (Stock::ADD, ICON_SIZE_BUTTON));
171 route_group_add_button->add (*w);
173 w = manage (
new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
175 route_group_remove_button->add (*w);
177 route_group_display_button_box->set_homogeneous (
true);
182 route_group_display_button_box->add (*route_group_add_button);
183 route_group_display_button_box->add (*route_group_remove_button);
215 set_name (
"MixerWindow");
219 set_wmclass (
X_(
"ardour_mixer"), PROGRAM_NAME);
222 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
226 route_group_display_button_box->show();
227 route_group_add_button->show();
228 route_group_remove_button->show();
250 #ifndef DEFER_PLUGIN_SELECTOR_LOAD
272 win.set_transient_for (*
this);
288 TreeModel::Children rows =
track_model->children();
289 TreeModel::Children::iterator ri;
291 for (ri = rows.begin(); ri != rows.end(); ++ri) {
311 return just_hide_it(ev, static_cast<Gtk::Window *>(
this));
318 bool from_scratch =
track_model->children().size() == 0;
319 Gtk::TreeModel::Children::iterator insert_iter =
track_model->children().end();
321 for (Gtk::TreeModel::Children::iterator it =
track_model->children().begin(); it !=
track_model->children().end(); ++it) {
324 if (r->
order_key() == (routes.front()->order_key() + routes.size())) {
340 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
380 TreeModel::Row row = *(
track_model->insert(insert_iter));
409 for (list<MixerStrip *>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
410 (*i)->deselect_all_processors();
424 for (list<MixerStrip *>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
425 (*i)->delete_processors();
438 TreeModel::Children rows =
track_model->children();
439 TreeModel::Children::iterator ri;
440 list<MixerStrip *>::iterator i;
446 for (ri = rows.begin(); ri != rows.end(); ++ri) {
462 TreeModel::Children rows =
track_model->children();
470 TreeModel::Children::iterator ri;
471 bool rid_change =
false;
473 uint32_t invisible_key = UINT32_MAX;
475 for (ri = rows.begin(); ri != rows.end(); ++ri) {
479 if (rid == Route::MasterBusRemoteControlID) {
483 if (rid == Route::MonitorBusRemoteControlID) {
492 uint32_t new_rid = (visible ? rid : invisible_key--);
518 TreeModel::Children rows =
track_model->children();
526 TreeModel::Children::iterator ri;
527 bool changed =
false;
528 bool rid_change =
false;
531 uint32_t invisible_key = UINT32_MAX;
533 for (ri = rows.begin(); ri != rows.end(); ++ri) {
539 if (order != old_key) {
546 uint32_t new_rid = (visible ? rid : invisible_key--);
587 vector<int> neworder;
588 TreeModel::Children rows =
track_model->children();
589 uint32_t old_order = 0;
590 bool changed =
false;
598 for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
605 sort (sorted_routes.begin(), sorted_routes.end(), cmp);
606 neworder.assign (sorted_routes.size(), 0);
610 for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) {
612 neworder[n] = sr->old_display_order;
614 if (sr->old_display_order != n) {
619 sr->route->name(), sr->old_display_order, n));
644 for (TrackViewList::iterator i = s.begin(); i != s.end(); ++i) {
662 for (list<MixerStrip *>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
663 if ((*i)->route() == r) {
674 if (ev->button == 1) {
677 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
684 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
686 }
else if (Keyboard::modifier_state_equals (ev->state, Keyboard::RangeSelectModifier)) {
692 vector<MixerStrip*> tmp;
693 bool accumulate =
false;
694 bool found_another =
false;
696 tmp.push_back (strip);
698 for (list<MixerStrip*>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
713 found_another =
true;
728 for (vector<MixerStrip*>::iterator i = tmp.begin(); i != tmp.end(); ++i) {
747 SessionHandlePtr::set_session (sess);
803 for (list<MixerStrip *>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
815 SessionHandlePtr::session_going_away ();
845 TreeModel::Children rows =
track_model->children();
846 TreeModel::Children::iterator i;
851 for (i = rows.begin(); i != rows.end(); ++i) {
868 TreeModel::Children rows =
track_model->children();
869 TreeModel::Children::iterator i;
871 for (i = rows.begin(); i != rows.end(); ++i) {
885 TreeModel::Children rows =
track_model->children();
886 TreeModel::Children::iterator i;
888 for (i = rows.begin(); i != rows.end(); ++i) {
917 for (list<MixerStrip *>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
918 (*i)->fast_update ();
926 TreeModel::Children rows =
track_model->children();
927 TreeModel::Children::iterator i;
932 for (i = rows.begin(); i != rows.end(); ++i) {
934 TreeModel::Row row = (*i);
956 TreeModel::Children rows =
track_model->children();
957 TreeModel::Children::iterator i;
962 for (i = rows.begin(); i != rows.end(); ++i) {
963 TreeModel::Row row = (*i);
1061 TreeModel::Children rows =
track_model->children();
1062 TreeModel::Children::iterator i;
1068 for (i = rows.begin(); i != rows.end(); ++i) {
1094 out_packer.pack_start (*strip,
false,
false);
1125 TreeModel::Children rows =
track_model->children();
1126 TreeModel::Children::iterator i;
1129 for (order = 0, i = rows.begin(); i != rows.end(); ++i, ++order) {
1139 strip->queue_draw();
1175 track_menu->popup (1, gtk_get_current_event_time());
1181 if (Keyboard::is_context_menu_event (ev)) {
1192 using namespace Menu_Helpers;
1193 using namespace Gtk;
1217 TreeModel::Children rows =
track_model->children();
1218 TreeModel::Children::iterator i;
1220 for (i = rows.begin(); i != rows.end(); ++i) {
1227 error <<
_(
"track display list item for renamed strip not found!") <<
endmsg;
1233 TreeModel::Path path;
1234 TreeViewColumn* column;
1238 if (!
group_display.get_path_at_pos ((
int)ev->x, (
int)ev->y, path, column, cellx, celly)) {
1251 if (Keyboard::is_context_menu_event (ev)) {
1256 switch (GPOINTER_TO_UINT (column->get_data (
X_(
"colnum")))) {
1258 if (Keyboard::is_edit_event (ev)) {
1344 TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows ();
1350 TreeView::Selection::ListHandle_Path::iterator i = rows.begin();
1376 for (list<MixerStrip *>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
1377 if ((*i)->route_group() == group) {
1378 (*i)->route_group_changed();
1382 TreeModel::iterator i;
1383 TreeModel::Children rows =
group_model->children();
1388 for (i = rows.begin(); i != rows.end(); ++i) {
1402 for (list<MixerStrip*>::iterator j =
strips.begin(); j !=
strips.end(); ++j) {
1403 if ((*j)->route_group() == group) {
1425 if (new_text != group->
name()) {
1446 if (name != group->
name()) {
1470 list<RouteGroup*> new_list;
1472 Gtk::TreeModel::Children children =
group_model->children();
1473 for (Gtk::TreeModel::Children::iterator i = children.begin(); i != children.end(); ++i) {
1476 new_list.push_back (g);
1495 if (!group->
name().empty()) {
1506 CellRendererText* name_cell =
dynamic_cast<CellRendererText*
>(
group_display.get_column_cell_renderer (0));
1518 using namespace Menu_Helpers;
1520 if (Keyboard::is_context_menu_event (ev)) {
1533 for (list<MixerStrip*>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
1534 (*i)->set_width_enum (w, save ? (*i)->width_owner() :
this);
1567 if ((prop = geometry->
property(
"x_size")) == 0) {
1568 prop = geometry->
property (
"x-size");
1573 if ((prop = geometry->
property(
"y_size")) == 0) {
1574 prop = geometry->
property (
"y-size");
1580 if ((prop = geometry->
property (
"x_pos")) == 0) {
1581 prop = geometry->
property (
"x-pos");
1587 if ((prop = geometry->
property (
"y_pos")) == 0) {
1588 prop = geometry->
property (
"y-pos");
1597 if ((prop = node.
property (
"narrow-strips"))) {
1605 if ((prop = node.
property (
"show-mixer"))) {
1611 if ((prop = node.
property (
"maximised"))) {
1615 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
1616 bool fs = tact && tact->get_active();
1619 "ToggleMaximalMixer");
1632 if (is_realized()) {
1633 Glib::RefPtr<Gdk::Window> win = get_window();
1639 snprintf(buf,
sizeof(buf),
"%d",
m_width);
1641 snprintf(buf,
sizeof(buf),
"%d",
m_height);
1643 snprintf(buf,
sizeof(buf),
"%d",
m_root_x);
1645 snprintf(buf,
sizeof(buf),
"%d",
m_root_y);
1649 snprintf(buf,
sizeof(buf),
"%d", 0);
1651 snprintf(buf,
sizeof(buf),
"%d", 0);
1654 snprintf(buf,
sizeof(buf),
"%d",gtk_paned_get_position (static_cast<Paned*>(&
rhs_pane1)->gobj()));
1656 snprintf(buf,
sizeof(buf),
"%d",gtk_paned_get_position (static_cast<Paned*>(&
list_hpane)->gobj()));
1681 static int32_t done[3] = { 0, 0, 0 };
1687 if ((prop = geometry->
property (
"y_size")) == 0) {
1688 prop = geometry->
property (
"y-size");
1695 if (which == static_cast<Gtk::Paned*> (&
rhs_pane1)) {
1701 if (!geometry || (prop = geometry->
property(
"mixer-rhs-pane1-pos")) == 0) {
1703 snprintf (buf,
sizeof(buf),
"%d", pos);
1708 if ((done[0] = GTK_WIDGET(
rhs_pane1.gobj())->allocation.height > pos)) {
1712 }
else if (which == static_cast<Gtk::Paned*> (&
list_hpane)) {
1718 if (!geometry || (prop = geometry->
property(
"mixer-list-hpane-pos")) == 0) {
1720 snprintf (buf,
sizeof(buf),
"%d", pos);
1725 if ((done[2] = GTK_WIDGET(
list_hpane.gobj())->allocation.width > pos)) {
1733 if (!
scroller.get_hscrollbar())
return;
1734 Adjustment* adj =
scroller.get_hscrollbar()->get_adjustment();
1736 scroller.get_hscrollbar()->set_value (max (adj->get_lower(), adj->get_value() - adj->get_step_increment()));
1742 if (!
scroller.get_hscrollbar())
return;
1743 Adjustment* adj =
scroller.get_hscrollbar()->get_adjustment();
1745 scroller.get_hscrollbar()->set_value (min (adj->get_upper(), adj->get_value() + adj->get_step_increment()));
1755 if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
1771 if (gtk_window_propagate_key_event (GTK_WINDOW(gobj()), ev)) {
1789 switch (ev->direction) {
1790 case GDK_SCROLL_LEFT:
1794 if (ev->state & Keyboard::TertiaryModifier) {
1800 case GDK_SCROLL_RIGHT:
1804 case GDK_SCROLL_DOWN:
1805 if (ev->state & Keyboard::TertiaryModifier) {
1819 if (p ==
"show-group-tabs") {
1826 }
else if (p ==
"default-narrow_ms") {
1828 for (list<MixerStrip*>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
1829 (*i)->set_width_enum (s ?
Narrow :
Wide,
this);
1831 }
else if (p ==
"remote-model") {
1845 #ifdef DEFER_PLUGIN_SELECTOR_LOAD
1860 track_display.get_column (0)->set_data (
X_(
"colnum"), GUINT_TO_POINTER(0));
1861 track_display.get_column (1)->set_data (
X_(
"colnum"), GUINT_TO_POINTER(1));
1864 track_display.get_column (0)->set_sizing (Gtk::TREE_VIEW_COLUMN_FIXED);
1866 track_display.get_selection()->set_mode (Gtk::SELECTION_NONE);
1873 CellRendererToggle* track_list_visible_cell =
dynamic_cast<CellRendererToggle*
>(
track_display.get_column_cell_renderer (1));
1874 track_list_visible_cell->property_activatable() =
true;
1875 track_list_visible_cell->property_radio() =
false;
1883 VBox* v = manage (
new VBox);
1887 Button* b = manage (
new Button);
1889 Widget* w = manage (
new Image (Stock::ADD, ICON_SIZE_BUTTON));
1895 v->pack_start (*b,
false,
false);
1930 title +=
S_(
"Window|Mixer");
1931 title += Glib::get_application_name ();
1937 title += Glib::get_application_name ();
1945 for (list<MixerStrip*>::iterator i =
strips.begin(); i !=
strips.end(); ++i) {
1948 (*i)->translate_coordinates (*
this, 0, 0, x1, y);
1949 x2 = x1 + (*i)->get_width();
1951 if (x >= x1 && x <= x2) {
1994 rl->push_back ((*r)->route());
TrackDisplayModelColumns track_columns
PBD::Signal0< void > route_groups_reordered
void set_order_key(uint32_t)
PluginSelector * plugin_selector()
bool no_track_list_redisplay
bool _following_editor_selection
void get_window_pos_and_size()
bool _maximised
true if we are in fullscreen mode
Gtk::TreeModelColumn< bool > visible
int atoi(const string &s)
Gtk::TreeModelColumn< bool > visible
void reorder_route_groups(std::list< RouteGroup * >)
PBD::Signal1< void, RouteGroup * > route_group_added
void set_session(ARDOUR::Session *)
PBD::Signal0< void > DropReferences
sigc::connection super_rapid_connect(const sigc::slot< void > &slot)
RouteUISelection _route_targets
const std::string & value() const
PBD::Signal1< void, const PropertyChange & > PropertyChanged
static Mixer_UI * _instance
void session_going_away()
Glib::RefPtr< Gtk::ListStore > track_model
void maximise_mixer_space()
void hide_strip(MixerStrip *)
LIBARDOUR_API PBD::PropertyDescriptor< bool > hidden
Gtk::Button group_display_button
RouteProcessorSelection & selection()
void route_groups_changed()
static ARDOUR_UI * instance()
XMLNode * tearoff_settings(const char *) const
LIBARDOUR_API PBD::PropertyDescriptor< std::string > name
void set_window_pos_and_size()
bool forward_key_press(GdkEventKey *ev)
bool activate(KeyboardKey, Operation)
Gtk::ScrolledWindow scroller
void set_exclusive_input_active(boost::shared_ptr< RouteList > rt, bool onoff, bool flip_others=false)
Gtk::Frame group_display_frame
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::Action > get_action(const char *group, const char *name)
Glib::RefPtr< Gtk::ListStore > group_model
void remove_route_group(RouteGroup &)
friend class MixerGroupTabs
LIBGTKMM2EXT_API void do_action(const char *group, const char *name)
LIBARDOUR_API uint64_t OrderKeys
void * width_owner() const
LIBPBD_API Transmitter error
sigc::signal< void > WidthChanged
Gtkmm2ext::TearOff & tearoff() const
void strip_width_changed()
bool is_auditioner() const
std::ostream & endmsg(std::ostream &ostr)
Gtkmm2ext::Bindings bindings
void ensure_float(Gtk::Window &)
SessionConfiguration config
Gtk::ScrolledWindow group_display_scroller
void strip_property_changed(const PBD::PropertyChange &, MixerStrip *)
void route_group_name_edit(const std::string &, const std::string &)
void follow_editor_selection()
bool _route_deletion_in_progress
void track_list_delete(const Gtk::TreeModel::Path &)
#define ENSURE_GUI_THREAD(obj, method,...)
void parameter_changed(std::string)
virtual bool set_marked_for_display(bool)
void set_session(ARDOUR::Session *)
Gtk::EventBox scroller_base
GroupDisplayModelColumns group_columns
void toggle_midi_input_active(bool flip_others)
void set_all_audio_visibility(int tracks, bool yn)
gint just_hide_it(GdkEventAny *, Gtk::Window *)
const std::string & get_string()
XMLNode * mixer_settings() const
void track_editor_selection()
Gtk::Menu * get_menu(ARDOUR::RouteGroup *g)
void route_group_row_deleted(Gtk::TreeModel::Path const &)
void track_list_reorder(const Gtk::TreeModel::Path &path, const Gtk::TreeModel::iterator &iter, int *new_order)
Gtk::TreeModelColumn< MixerStrip * > strip
XMLNode & get_state(void)
MonitorSection * _monitor_section
void foreach_route_group(boost::function< void(RouteGroup *)> f)
void disable_all_route_groups()
gboolean configure_handler(GdkEventConfigure *conf)
XMLProperty * property(const char *)
uint32_t order_key() const
void monitor_section_going_away()
LIBARDOUR_API RCConfiguration * Config
Gtk::TreeView track_display
Gtk::VBox mixer_scroller_vpacker
bool string_is_affirmative(const std::string &str)
Gtk::TreeModelColumn< std::string > text
virtual bool set_name(const std::string &str)
void restore_mixer_space()
PBD::Signal0< void > DirtyChanged
bool on_key_release_event(GdkEventKey *)
Gtk::TreeView group_display
Gtk::Frame track_display_frame
MixerStrip * strip_by_route(boost::shared_ptr< ARDOUR::Route >)
Gtk::VBox group_display_vbox
int set_state(const XMLNode &)
void setup_track_display()
bool deletion_in_progress() const
void remove_selected_route_group()
void set_all_strips_visibility(bool yn)
void deselect_all_strip_processors()
Gtk::TreeModelColumn< ARDOUR::RouteGroup * > group
void set_hidden(bool yn, void *src)
std::list< MixerStrip * > strips
boost::shared_ptr< RouteList > get_routes() const
#define DEBUG_TRACE(bits, str)
void set_strip_width(Width, bool save=false)
virtual Selection & get_selection() const =0
void show_track_list_menu()
LIBARDOUR_API XMLNode * find_named_node(const XMLNode &node, std::string name)
void route_group_row_change(const Gtk::TreeModel::Path &path, const Gtk::TreeModel::iterator &iter)
PBD::ScopedConnectionList _session_connections
void parameter_changed(std::string const &)
void notify_remote_id_change()
Gtk::ScrolledWindow track_display_scroller
PBD::Signal1< void, std::string > ParameterChanged
bool strip_scroller_button_release(GdkEventButton *)
LIBGTKMM2EXT_API void check_toggleaction(std::string)
void remove_strip(MixerStrip *)
bool hide_window(GdkEventAny *ev)
void route_group_property_changed(ARDOUR::RouteGroup *, const PBD::PropertyChange &)
XMLProperty * add_property(const char *name, const std::string &value)
void fast_update_strips()
void reset_remote_control_ids()
void activate_all_route_groups()
static PublicEditor & instance()
Gtk::HBox scroller_hpacker
std::vector< RoutePlusOrderKey > OrderKeySortedRoutes
void set_route_group_activation(ARDOUR::RouteGroup *, bool)
void show_all_audiotracks()
std::string snap_name() const
void redisplay_track_list()
void show_strip(MixerStrip *)
void add_child_nocopy(XMLNode &)
Gtk::TreeModelColumn< boost::shared_ptr< ARDOUR::Route > > route
Gtk::Label group_display_button_label
Gtk::TreeModelColumn< std::string > text
void set_width_enum(Width, void *owner)
PBD::Signal1< void, std::string > StateSaved
static const int32_t default_height
RouteProcessorSelection _selection
static UIConfiguration * config()
MixerGroupTabs * _group_tabs
bool input_active() const
bool on_scroll_event(GdkEventScroll *)
bool group_display_button_press(GdkEventButton *)
MixerStrip * strip_by_x(int x)
Width get_width_enum() const
bool on_key_press_event(GdkEventKey *)
static const int32_t default_width
PluginSelector * _plugin_selector
void set_session(ARDOUR::Session *)
void sync_treeview_from_order_keys()
bool contains(PropertyDescriptor< T > p) const
void set_gui_property(const std::string &property_name, const T &value)
bool _in_group_rebuild_or_clear
sigc::signal< void > TracksChanged
void initial_track_display()
virtual void set_session(ARDOUR::Session *)
void block_routes_changed(bool)
uint32_t remote_control_id() const
static Mixer_UI * instance()
void set_route_targets_for_operation()
boost::shared_ptr< ARDOUR::AudioTrack > audio_track() const
void hide_all_audiotracks()
void set_remote_control_id_explicit(uint32_t order_key)
bool marked_for_display() const
void add_route_group(ARDOUR::RouteGroup *)
bool track_display_button_press(GdkEventButton *)
std::list< boost::shared_ptr< Route > > RouteList
void set_active(bool yn, void *src)
void update_track_visibility()
static PBD::Signal1< void, MixerStrip * > CatchDeletion
bool strip_button_release_event(GdkEventButton *, MixerStrip *)
void track_visibility_changed(std::string const &path)
void add_route(Gtk::Window *float_window)
void run_new_group_dialog(ARDOUR::RouteList const &)
ARDOUR::Session * _session
boost::shared_ptr< ARDOUR::Route > route() const
void sync_order_keys_from_treeview()
void add_strips(ARDOUR::RouteList &)
void pane_allocation_handler(Gtk::Allocation &, Gtk::Paned *)
std::string string_compose(const std::string &fmt, const T1 &o1)
sigc::connection fast_screen_update_connection
PBD::Signal0< void > route_group_removed
void set_state(const XMLNode &)
PBD::Signal1< void, RouteList & > RouteAdded