X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_routes.cc;h=8867328d25d75b11db9b2f714e784bcc34652c23;hb=a49b0f53aa2d83a9291c35f323f90b46d8869390;hp=bc432990dee7af5b1c9fac3af7e3c8d9721bfbf2;hpb=b565ada188a2787a33947f0b06194b835c142e46;p=ardour.git diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index bc432990de..8867328d25 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -68,6 +68,8 @@ EditorRoutes::EditorRoutes (Editor* e) , selection_countdown (0) , name_editable (0) { + static const int column_width = 22; + _scroller.add (_display); _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); @@ -77,25 +79,43 @@ EditorRoutes::EditorRoutes (Editor* e) // Record enable toggle CellRendererPixbufMulti* rec_col_renderer = manage (new CellRendererPixbufMulti()); - rec_col_renderer->set_pixbuf (0, ::get_icon("act-disabled")); - rec_col_renderer->set_pixbuf (1, ::get_icon("rec-in-progress")); - rec_col_renderer->set_pixbuf (2, ::get_icon("rec-enabled")); - rec_col_renderer->set_pixbuf (3, ::get_icon("step-editing")); + rec_col_renderer->set_pixbuf (0, ::get_icon("record-normal-disabled")); + rec_col_renderer->set_pixbuf (1, ::get_icon("record-normal-in-progress")); + rec_col_renderer->set_pixbuf (2, ::get_icon("record-normal-enabled")); + rec_col_renderer->set_pixbuf (3, ::get_icon("record-step")); rec_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_rec_enable_changed)); TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer)); rec_state_column->add_attribute(rec_col_renderer->property_state(), _columns.rec_state); rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track); + rec_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); rec_state_column->set_alignment(ALIGN_CENTER); rec_state_column->set_expand(false); - rec_state_column->set_fixed_width(15); + rec_state_column->set_fixed_width(column_width); + + // MIDI Input Active + + CellRendererPixbufMulti* input_active_col_renderer = manage (new CellRendererPixbufMulti()); + input_active_col_renderer->set_pixbuf (0, ::get_icon("midi-input-inactive")); + input_active_col_renderer->set_pixbuf (1, ::get_icon("midi-input-active")); + input_active_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_input_active_changed)); + + TreeViewColumn* input_active_column = manage (new TreeViewColumn ("I", *input_active_col_renderer)); + + input_active_column->add_attribute(input_active_col_renderer->property_state(), _columns.is_input_active); + input_active_column->add_attribute (input_active_col_renderer->property_visible(), _columns.is_midi); + + input_active_column->set_sizing(TREE_VIEW_COLUMN_FIXED); + input_active_column->set_alignment(ALIGN_CENTER); + input_active_column->set_expand(false); + input_active_column->set_fixed_width(column_width); // Mute enable toggle CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti()); - mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled")); + mute_col_renderer->set_pixbuf (0, ::get_icon("mute-disabled")); mute_col_renderer->set_pixbuf (1, ::get_icon("muted-by-others")); mute_col_renderer->set_pixbuf (2, ::get_icon("mute-enabled")); mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled)); @@ -111,7 +131,7 @@ EditorRoutes::EditorRoutes (Editor* e) // Solo enable toggle CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti()); - solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled")); + solo_col_renderer->set_pixbuf (0, ::get_icon("solo-disabled")); solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled")); solo_col_renderer->set_pixbuf (3, ::get_icon("soloed-by-others")); solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled)); @@ -122,13 +142,13 @@ EditorRoutes::EditorRoutes (Editor* e) solo_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_state_column->set_alignment(ALIGN_CENTER); solo_state_column->set_expand(false); - solo_state_column->set_fixed_width(15); + solo_state_column->set_fixed_width(column_width); // Solo isolate toggle CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti()); - solo_iso_renderer->set_pixbuf (0, ::get_icon("act-disabled")); - solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolated")); + solo_iso_renderer->set_pixbuf (0, ::get_icon("solo-isolate-disabled")); + solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolate-enabled")); solo_iso_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled)); TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("SI", *solo_iso_renderer)); @@ -137,13 +157,13 @@ EditorRoutes::EditorRoutes (Editor* e) solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_isolate_state_column->set_alignment(ALIGN_CENTER); solo_isolate_state_column->set_expand(false); - solo_isolate_state_column->set_fixed_width(22); + solo_isolate_state_column->set_fixed_width(column_width); // Solo safe toggle CellRendererPixbufMulti* solo_safe_renderer = manage (new CellRendererPixbufMulti ()); - solo_safe_renderer->set_pixbuf (0, ::get_icon("act-disabled")); - solo_safe_renderer->set_pixbuf (1, ::get_icon("solo-enabled")); + solo_safe_renderer->set_pixbuf (0, ::get_icon("solo-safe-disabled")); + solo_safe_renderer->set_pixbuf (1, ::get_icon("solo-safe-enabled")); solo_safe_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_safe_toggled)); TreeViewColumn* solo_safe_state_column = manage (new TreeViewColumn(_("SS"), *solo_safe_renderer)); @@ -151,19 +171,19 @@ EditorRoutes::EditorRoutes (Editor* e) solo_safe_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_safe_state_column->set_alignment(ALIGN_CENTER); solo_safe_state_column->set_expand(false); - solo_safe_state_column->set_fixed_width(22); + solo_safe_state_column->set_fixed_width(column_width); + _display.append_column (*input_active_column); _display.append_column (*rec_state_column); _display.append_column (*mute_state_column); _display.append_column (*solo_state_column); _display.append_column (*solo_isolate_state_column); _display.append_column (*solo_safe_state_column); - - int colnum = _display.append_column (_("Name"), _columns.text); - TreeViewColumn* c = _display.get_column (colnum-1); - c->set_data ("i_am_the_tab_column", (void*) 0xfeedface); - _display.append_column (_("V"), _columns.visible); - + + _name_column = _display.append_column (_("Name"), _columns.text) - 1; + _visible_column = _display.append_column (_("V"), _columns.visible) - 1; + _active_column = _display.append_column (_("A"), _columns.active) - 1; + _display.set_headers_visible (true); _display.set_name ("TrackListDisplay"); _display.get_selection()->set_mode (SELECTION_SINGLE); @@ -173,12 +193,12 @@ EditorRoutes::EditorRoutes (Editor* e) _display.set_size_request (100, -1); _display.add_object_drag (_columns.route.index(), "routes"); - CellRendererText* name_cell = dynamic_cast (_display.get_column_cell_renderer (5)); + CellRendererText* name_cell = dynamic_cast (_display.get_column_cell_renderer (_name_column)); assert (name_cell); name_cell->signal_editing_started().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit_started)); - TreeViewColumn* name_column = _display.get_column (5); + TreeViewColumn* name_column = _display.get_column (_name_column); assert (name_column); @@ -191,21 +211,33 @@ EditorRoutes::EditorRoutes (Editor* e) name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit)); // Set the visible column cell renderer to radio toggle - CellRendererToggle* visible_cell = dynamic_cast (_display.get_column_cell_renderer (6)); + CellRendererToggle* visible_cell = dynamic_cast (_display.get_column_cell_renderer (_visible_column)); visible_cell->property_activatable() = true; visible_cell->property_radio() = false; visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::visible_changed)); - - TreeViewColumn* visible_col = dynamic_cast (_display.get_column (6)); + + TreeViewColumn* visible_col = dynamic_cast (_display.get_column (_visible_column)); visible_col->set_expand(false); visible_col->set_sizing(TREE_VIEW_COLUMN_FIXED); visible_col->set_fixed_width(30); visible_col->set_alignment(ALIGN_CENTER); + + CellRendererToggle* active_cell = dynamic_cast (_display.get_column_cell_renderer (_active_column)); + + active_cell->property_activatable() = true; + active_cell->property_radio() = false; + active_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::active_changed)); + + TreeViewColumn* active_col = dynamic_cast (_display.get_column (_active_column)); + active_col->set_expand (false); + active_col->set_sizing (TREE_VIEW_COLUMN_FIXED); + active_col->set_fixed_width (30); + active_col->set_alignment (ALIGN_CENTER); _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::route_deleted)); _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered)); - + _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false); _scroller.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorRoutes::key_press), false); @@ -254,8 +286,8 @@ EditorRoutes::enter_notify (GdkEventCrossing*) if (name_editable) { return true; } - - /* arm counter so that ::selection_filter() will deny selecting anything for the + + /* arm counter so that ::selection_filter() will deny selecting anything for the next two attempts to change selection status. */ selection_countdown = 2; @@ -291,6 +323,24 @@ EditorRoutes::set_session (Session* s) } } +void +EditorRoutes::on_input_active_changed (std::string const & path_string) +{ + // Get the model row that has been toggled. + Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string)); + + TimeAxisView* tv = row[_columns.tv]; + RouteTimeAxisView *rtv = dynamic_cast (tv); + + if (rtv) { + boost::shared_ptr mt; + mt = rtv->midi_track(); + if (mt) { + mt->set_input_active (!mt->input_active()); + } + } +} + void EditorRoutes::on_tv_rec_enable_changed (std::string const & path_string) { @@ -315,7 +365,7 @@ EditorRoutes::on_tv_mute_enable_toggled (std::string const & path_string) TimeAxisView *tv = row[_columns.tv]; RouteTimeAxisView *rtv = dynamic_cast (tv); - + if (rtv != 0) { boost::shared_ptr rl (new RouteList); rl->push_back (rtv->route()); @@ -336,7 +386,7 @@ EditorRoutes::on_tv_solo_enable_toggled (std::string const & path_string) boost::shared_ptr rl (new RouteList); rl->push_back (rtv->route()); if (Config->get_solo_control_is_listen_control()) { - _session->set_listen (rl, !rtv->route()->listening(), Session::rt_cleanup); + _session->set_listen (rl, !rtv->route()->listening_via_monitor(), Session::rt_cleanup); } else { _session->set_solo (rl, !rtv->route()->self_soloed(), Session::rt_cleanup); } @@ -431,15 +481,13 @@ EditorRoutes::redisplay () route->set_order_key (N_ ("editor"), n); } - bool visible = (*i)[_columns.visible]; + bool visible = tv->marked_for_display (); /* show or hide the TimeAxisView */ if (visible) { - tv->set_marked_for_display (true); position += tv->show_at (position, n, &_editor->edit_controls_vbox); tv->clip_to_viewport (); } else { - tv->set_marked_for_display (false); tv->hide (); } @@ -452,6 +500,8 @@ EditorRoutes::redisplay () */ Glib::signal_idle().connect (sigc::mem_fun (*_editor, &Editor::sync_track_view_list_and_routes)); + _editor->reset_controls_layout_height (position); + _editor->reset_controls_layout_width (); _editor->full_canvas_height = position + _editor->canvas_timebars_vsize; _editor->vertical_adjustment.set_upper (_editor->full_canvas_height); @@ -474,7 +524,7 @@ EditorRoutes::route_deleted (Gtk::TreeModel::Path const &) if (!_session || _session->deletion_in_progress()) { return; } - + /* this could require an order reset & sync */ _session->set_remote_control_ids(); _ignore_reorder = true; @@ -495,14 +545,29 @@ EditorRoutes::visible_changed (std::string const & path) TimeAxisView* tv = (*iter)[_columns.tv]; if (tv) { bool visible = (*iter)[_columns.visible]; - (*iter)[_columns.visible] = !visible; + + if (tv->set_marked_for_display (!visible)) { + _redisplay_does_not_reset_order_keys = true; + _session->set_remote_control_ids(); + update_visibility (); + redisplay (); + _redisplay_does_not_reset_order_keys = false; + } } } +} - _redisplay_does_not_reset_order_keys = true; - _session->set_remote_control_ids(); - redisplay (); - _redisplay_does_not_reset_order_keys = false; +void +EditorRoutes::active_changed (std::string const & path) +{ + if (_session && _session->deletion_in_progress ()) { + return; + } + + Gtk::TreeModel::Row row = *_model->get_iter (path); + boost::shared_ptr route = row[_columns.route]; + bool const active = row[_columns.active]; + route->set_active (!active, this); } void @@ -515,13 +580,25 @@ EditorRoutes::routes_added (list routes) for (list::iterator x = routes.begin(); x != routes.end(); ++x) { + boost::shared_ptr midi_trk = boost::dynamic_pointer_cast ((*x)->route()); + row = *(_model->append ()); row[_columns.text] = (*x)->route()->name(); row[_columns.visible] = (*x)->marked_for_display(); + row[_columns.active] = (*x)->route()->active (); row[_columns.tv] = *x; row[_columns.route] = (*x)->route (); row[_columns.is_track] = (boost::dynamic_pointer_cast ((*x)->route()) != 0); + + if (midi_trk) { + row[_columns.is_input_active] = midi_trk->input_active (); + row[_columns.is_midi] = true; + } else { + row[_columns.is_input_active] = false; + row[_columns.is_midi] = false; + } + row[_columns.mute_state] = (*x)->route()->muted(); row[_columns.solo_state] = RouteUI::solo_visual_state ((*x)->route()); row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated(); @@ -550,6 +627,7 @@ EditorRoutes::routes_added (list routes) if ((*x)->is_midi_track()) { boost::shared_ptr t = boost::dynamic_pointer_cast ((*x)->route()); t->StepEditStatusChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context()); + t->InputActiveChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_input_active_display, this), gui_context()); } (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context()); @@ -557,6 +635,7 @@ EditorRoutes::routes_added (list routes) (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::update_solo_display, this, _1), gui_context()); (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context()); (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context()); + (*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ()); } update_rec_display (); @@ -564,6 +643,8 @@ EditorRoutes::routes_added (list routes) update_solo_display (true); update_solo_isolate_display (); update_solo_safe_display (); + update_input_active_display (); + update_active_display (); resume_redisplay (); _redisplay_does_not_sync_order_keys = false; } @@ -637,6 +718,18 @@ EditorRoutes::route_property_changed (const PropertyChange& what_changed, boost: } } +void +EditorRoutes::update_active_display () +{ + TreeModel::Children rows = _model->children(); + TreeModel::Children::iterator i; + + for (i = rows.begin(); i != rows.end(); ++i) { + boost::shared_ptr route = (*i)[_columns.route]; + (*i)[_columns.active] = route->active (); + } +} + void EditorRoutes::update_visibility () { @@ -648,7 +741,6 @@ EditorRoutes::update_visibility () for (i = rows.begin(); i != rows.end(); ++i) { TimeAxisView *tv = (*i)[_columns.tv]; (*i)[_columns.visible] = tv->marked_for_display (); - cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl; } resume_redisplay (); @@ -662,12 +754,12 @@ EditorRoutes::hide_track_in_display (TimeAxisView& tv) for (i = rows.begin(); i != rows.end(); ++i) { if ((*i)[_columns.tv] == &tv) { + tv.set_marked_for_display (false); (*i)[_columns.visible] = false; + redisplay (); break; } } - - redisplay (); } void @@ -676,14 +768,15 @@ EditorRoutes::show_track_in_display (TimeAxisView& tv) TreeModel::Children rows = _model->children(); TreeModel::Children::iterator i; + for (i = rows.begin(); i != rows.end(); ++i) { if ((*i)[_columns.tv] == &tv) { + tv.set_marked_for_display (true); (*i)[_columns.visible] = true; + redisplay (); break; } } - - redisplay (); } void @@ -698,7 +791,7 @@ EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, i void EditorRoutes::sync_order_keys (string const & src) { - vector neworder; + map new_order; TreeModel::Children rows = _model->children(); TreeModel::Children::iterator ri; @@ -706,20 +799,16 @@ EditorRoutes::sync_order_keys (string const & src) return; } - for (ri = rows.begin(); ri != rows.end(); ++ri) { - neworder.push_back (0); - } - bool changed = false; int order; for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) { boost::shared_ptr route = (*ri)[_columns.route]; - int old_key = order; - int new_key = route->order_key (N_ ("editor")); + int const old_key = order; + int const new_key = route->order_key (N_ ("editor")); - neworder[new_key] = old_key; + new_order[new_key] = old_key; if (new_key != old_key) { changed = true; @@ -728,7 +817,16 @@ EditorRoutes::sync_order_keys (string const & src) if (changed) { _redisplay_does_not_reset_order_keys = true; - _model->reorder (neworder); + + /* `compact' new_order into a vector */ + vector co; + for (map::const_iterator i = new_order.begin(); i != new_order.end(); ++i) { + co.push_back (i->second); + } + + assert (co.size() == _model->children().size ()); + + _model->reorder (co); _redisplay_does_not_reset_order_keys = false; } } @@ -795,13 +893,13 @@ EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn) suspend_redisplay (); for (i = rows.begin(); i != rows.end(); ++i) { - + TreeModel::Row row = (*i); TimeAxisView* tv = row[_columns.tv]; - + AudioTimeAxisView* atv; MidiTimeAxisView* mtv; - + if (tv == 0) { continue; } @@ -904,9 +1002,9 @@ EditorRoutes::key_press (GdkEventKey* ev) if (name_editable) { name_editable->editing_done (); name_editable = 0; - } + } - col = _display.get_column (5); // select&focus on name column + col = _display.get_column (_name_column); // select&focus on name column if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) { treeview_select_previous (_display, _model, col); @@ -926,7 +1024,7 @@ EditorRoutes::key_press (GdkEventKey* ev) case 's': if (Config->get_solo_control_is_listen_control()) { - _session->set_listen (rl, !rl->front()->listening(), Session::rt_cleanup); + _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup); } else { _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup); } @@ -996,35 +1094,35 @@ EditorRoutes::button_press (GdkEventButton* ev) show_menu (); return true; } - + //Scroll editor canvas to selected track if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - + TreeModel::Path path; TreeViewColumn *tvc; int cell_x; int cell_y; - + _display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y); // Get the model row. Gtk::TreeModel::Row row = *_model->get_iter (path); - + TimeAxisView *tv = row[_columns.tv]; - + int y_pos = tv->y_position(); - + //Clamp the y pos so that we do not extend beyond the canvas full height. if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){ y_pos = _editor->full_canvas_height - _editor->_canvas_height; } - + //Only scroll to if the track is visible if(y_pos != -1){ _editor->reset_y_origin (y_pos); } } - + return false; } @@ -1230,6 +1328,25 @@ EditorRoutes::move_selected_tracks (bool up) _session->sync_order_keys (N_ ("editor")); } +void +EditorRoutes::update_input_active_display () +{ + TreeModel::Children rows = _model->children(); + TreeModel::Children::iterator i; + + for (i = rows.begin(); i != rows.end(); ++i) { + boost::shared_ptr route = (*i)[_columns.route]; + + if (boost::dynamic_pointer_cast (route)) { + boost::shared_ptr mt = boost::dynamic_pointer_cast (route); + + if (mt) { + (*i)[_columns.is_input_active] = mt->input_active(); + } + } + } +} + void EditorRoutes::update_rec_display () { @@ -1253,7 +1370,7 @@ EditorRoutes::update_rec_display () } else { (*i)[_columns.rec_state] = 0; } - + (*i)[_columns.name_editable] = !route->record_enabled (); } } @@ -1378,7 +1495,7 @@ EditorRoutes::show_tracks_with_regions_at_playhead () } suspend_redisplay (); - + TreeModel::Children rows = _model->children (); for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) { TimeAxisView* tv = (*i)[_columns.tv];