X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_regions.cc;h=8561fbbfb53f99e7274e90408441a889ff5e13f1;hb=2b8fc2a43b155d9a22d68554508181dd0894b69d;hp=e4798650b15f329b939e0be31e353d3428afb00e;hpb=7a5b6a5031d4c573c90d2455276aa174a665239b;p=ardour.git diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc index e4798650b1..8561fbbfb5 100644 --- a/gtk2_ardour/editor_regions.cc +++ b/gtk2_ardour/editor_regions.cc @@ -28,15 +28,15 @@ #include "ardour/audioregion.h" #include "ardour/audiofilesource.h" +#include "ardour/silentfilesource.h" #include "ardour/region_factory.h" #include "ardour/session.h" -#include "ardour/session_playlists.h" -#include "ardour/silentfilesource.h" #include "ardour/profile.h" #include "gtkmm2ext/choice.h" #include "gtkmm2ext/treeutils.h" +#include "audio_clock.h" #include "editor.h" #include "editing.h" #include "keyboard.h" @@ -47,6 +47,7 @@ #include "utils.h" #include "editor_regions.h" #include "editor_drag.h" +#include "main_clock.h" #include "i18n.h" @@ -58,22 +59,28 @@ using namespace Glib; using namespace Editing; using Gtkmm2ext::Keyboard; +struct ColumnInfo { + int index; + const char* label; + const char* tooltip; +}; + EditorRegions::EditorRegions (Editor* e) : EditorComponent (e) , old_focus (0) , name_editable (0) , _menu (0) , _show_automatic_regions (true) - , _sort_type ((Editing::RegionListSortType) 0) - , _no_redisplay (false) , ignore_region_list_selection_change (false) , ignore_selected_region_change (false) + , _no_redisplay (false) + , _sort_type ((Editing::RegionListSortType) 0) , expanded (false) { _display.set_size_request (100, -1); - _display.set_name ("RegionListDisplay"); _display.set_rules_hint (true); - + _display.set_name ("EditGroupList"); + /* Try to prevent single mouse presses from initiating edits. This relies on a hack in gtktreeview.c:gtk_treeview_button_press() */ @@ -85,24 +92,54 @@ EditorRegions::EditorRegions (Editor* e) _display.set_model (_model); - _display.append_column (_("Regions"), _columns.name); - _display.append_column (_("Position"), _columns.position); - _display.append_column (_("End"), _columns.end); - _display.append_column (_("Length"), _columns.length); - _display.append_column (_("Sync"), _columns.sync); - _display.append_column (_("Fade In"), _columns.fadein); - _display.append_column (_("Fade Out"), _columns.fadeout); - _display.append_column (_("L"), _columns.locked); - _display.append_column (_("G"), _columns.glued); - _display.append_column (_("M"), _columns.muted); - _display.append_column (_("O"), _columns.opaque); - // _display.append_column (_("Used"), _columns.used); - // _display.append_column (_("Path"), _columns.path); + _display.append_column ("", _columns.name); + _display.append_column ("", _columns.position); + _display.append_column ("", _columns.end); + _display.append_column ("", _columns.length); + _display.append_column ("", _columns.sync); + _display.append_column ("", _columns.fadein); + _display.append_column ("", _columns.fadeout); + _display.append_column ("", _columns.locked); + _display.append_column ("", _columns.glued); + _display.append_column ("", _columns.muted); + _display.append_column ("", _columns.opaque); + + TreeViewColumn* col; + Gtk::Label* l; + + ColumnInfo ci[] = { + { 0, _("Region"), _("Region name, with number of channels in []'s") }, + { 1, _("Position"), _("Position of start of region") }, + { 2, _("End"), _("Position of end of region") }, + { 3, _("Length"), _("Length of the region") }, + { 4, _("Sync"), _("Position of region sync point, relative to start of the region") }, + { 5, _("Fade In"), _("Length of region fade-in (units: secondary clock), () if disabled") }, + { 6, _("Fade Out"), _("Length of region fade-out (units: secondary clock), () if dsisabled") }, + { 7, _("L"), _("Region position locked?") }, + { 8, _("G"), _("Region position glued to Bars|Beats time?") }, + { 9, _("M"), _("Region muted?") }, + { 10, _("O"), _("Region opaque (blocks regions below it from being heard)?") }, + { -1, 0, 0 } + }; + + for (int i = 0; ci[i].index >= 0; ++i) { + col = _display.get_column (ci[i].index); + l = manage (new Label (ci[i].label)); + ARDOUR_UI::instance()->set_tip (*l, ci[i].tooltip); + col->set_widget (*l); + l->show (); + + if (ci[i].index > 6) { + col->set_expand (false); + col->set_alignment (ALIGN_CENTER); + } + } + _display.set_headers_visible (true); - //_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH); + _display.set_rules_hint (); /* show path as the row tooltip */ - _display.set_tooltip_column (15); /* path */ + _display.set_tooltip_column (14); /* path */ CellRendererText* region_name_cell = dynamic_cast(_display.get_column_cell_renderer (0)); region_name_cell->property_editable() = true; @@ -115,35 +152,36 @@ EditorRegions::EditorRegions (Editor* e) CellRendererText* renderer = dynamic_cast(_display.get_column_cell_renderer (0)); tv_col->add_attribute(renderer->property_text(), _columns.name); tv_col->add_attribute(renderer->property_foreground_gdk(), _columns.color_); + tv_col->set_expand (true); CellRendererToggle* locked_cell = dynamic_cast (_display.get_column_cell_renderer (7)); locked_cell->property_activatable() = true; locked_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::locked_changed)); - + TreeViewColumn* locked_col = _display.get_column (7); locked_col->add_attribute (locked_cell->property_visible(), _columns.property_toggles_visible); CellRendererToggle* glued_cell = dynamic_cast (_display.get_column_cell_renderer (8)); glued_cell->property_activatable() = true; glued_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::glued_changed)); - + TreeViewColumn* glued_col = _display.get_column (8); glued_col->add_attribute (glued_cell->property_visible(), _columns.property_toggles_visible); CellRendererToggle* muted_cell = dynamic_cast (_display.get_column_cell_renderer (9)); muted_cell->property_activatable() = true; muted_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::muted_changed)); - + TreeViewColumn* muted_col = _display.get_column (9); muted_col->add_attribute (muted_cell->property_visible(), _columns.property_toggles_visible); CellRendererToggle* opaque_cell = dynamic_cast (_display.get_column_cell_renderer (10)); opaque_cell->property_activatable() = true; opaque_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRegions::opaque_changed)); - + TreeViewColumn* opaque_col = _display.get_column (10); opaque_col->add_attribute (opaque_cell->property_visible(), _columns.property_toggles_visible); - + _display.get_selection()->set_mode (SELECTION_MULTIPLE); _display.add_object_drag (_columns.region.index(), "regions"); @@ -174,12 +212,12 @@ EditorRegions::EditorRegions (Editor* e) // _display.signal_popup_menu().connect (sigc::bind (sigc::mem_fun (*this, &Editor::show__display_context_menu), 1, 0)); //ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (sigc::mem_fun(*this, &Editor::redisplay_regions)); - ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (sigc::mem_fun(*this, &EditorRegions::update_all_rows)); - ARDOUR::Region::RegionPropertyChanged.connect (region_property_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::region_changed, this, _1, _2), gui_context()); - ARDOUR::RegionFactory::CheckNewRegion.connect (check_new_region_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::add_region, this, _1), gui_context()); - - e->EditorFreeze.connect (editor_freeze_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::freeze_tree_model, this), gui_context()); - e->EditorThaw.connect (editor_thaw_connection, MISSING_INVALIDATOR, ui_bind (&EditorRegions::thaw_tree_model, this), gui_context()); + ARDOUR_UI::instance()->secondary_clock->mode_changed.connect (sigc::mem_fun(*this, &EditorRegions::update_all_rows)); + ARDOUR::Region::RegionPropertyChanged.connect (region_property_connection, MISSING_INVALIDATOR, boost::bind (&EditorRegions::region_changed, this, _1, _2), gui_context()); + ARDOUR::RegionFactory::CheckNewRegion.connect (check_new_region_connection, MISSING_INVALIDATOR, boost::bind (&EditorRegions::add_region, this, _1), gui_context()); + + e->EditorFreeze.connect (editor_freeze_connection, MISSING_INVALIDATOR, boost::bind (&EditorRegions::freeze_tree_model, this), gui_context()); + e->EditorThaw.connect (editor_thaw_connection, MISSING_INVALIDATOR, boost::bind (&EditorRegions::thaw_tree_model, this), gui_context()); } bool @@ -213,13 +251,13 @@ EditorRegions::focus_out (GdkEventFocus*) } bool -EditorRegions::enter_notify (GdkEventCrossing* ev) +EditorRegions::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. */ _scroller.grab_focus (); @@ -266,7 +304,6 @@ EditorRegions::add_region (boost::shared_ptr region) TreeModel::iterator iter = _model->get_iter ("0"); TreeModel::Row parent; - TreeModel::Row child; if (!iter) { parent = *(_model->append()); @@ -368,16 +405,15 @@ EditorRegions::add_region (boost::shared_ptr region) } else { // find parent node, add as new child TreeModel::iterator i; - TreeModel::Children rows = _model->children(); - + boost::unordered_map::iterator it; - + it = parent_regions_sources_map.find (region->source_string()); - + if (it != parent_regions_sources_map.end()){ TreeModel::iterator j = _model->get_iter ((*it).second.get_path()); - + TreeModel::iterator ii; TreeModel::Children subrows = (*j).children(); @@ -391,11 +427,11 @@ EditorRegions::add_region (boost::shared_ptr region) } } */ - + row = *(_model->insert (subrows.end())); - } - else { - row = *(_model->append()); + + } else { + row = *(_model->append()); } row[_columns.property_toggles_visible] = true; @@ -409,7 +445,7 @@ EditorRegions::add_region (boost::shared_ptr region) } void -EditorRegions::delete_unused_regions () +EditorRegions::remove_unused_regions () { vector choices; string prompt; @@ -449,7 +485,9 @@ EditorRegions::region_changed (boost::shared_ptr r, const PropertyChange our_interests.add (ARDOUR::Properties::opaque); our_interests.add (ARDOUR::Properties::fade_in); our_interests.add (ARDOUR::Properties::fade_out); - + our_interests.add (ARDOUR::Properties::fade_in_active); + our_interests.add (ARDOUR::Properties::fade_out_active); + if (what_changed.contains (our_interests)) { if (last_row != 0) { @@ -459,19 +497,19 @@ EditorRegions::region_changed (boost::shared_ptr r, const PropertyChange if (c == r) { populate_row (r, (*j)); - + if (what_changed.contains (ARDOUR::Properties::hidden)) { redisplay (); } - + return; } } - + RegionRowMap::iterator it; - + it = region_row_map.find (r); - + if (it != region_row_map.end()){ TreeModel::iterator j = _model->get_iter ((*it).second.get_path()); @@ -479,19 +517,14 @@ EditorRegions::region_changed (boost::shared_ptr r, const PropertyChange if (c == r) { populate_row (r, (*j)); - + if (what_changed.contains (ARDOUR::Properties::hidden)) { redisplay (); } - + return; - } + } } - - /* find the region in our model and update its row */ - TreeModel::Children rows = _model->children (); - TreeModel::iterator i = rows.begin (); - } if (what_changed.contains (ARDOUR::Properties::hidden)) { @@ -517,7 +550,7 @@ EditorRegions::selection_changed () for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { - if (iter = _model->get_iter (*i)) { + if ((iter = _model->get_iter (*i))) { boost::shared_ptr region = (*iter)[_columns.region]; // they could have clicked on a row that is just a placeholder, like "Hidden" @@ -525,7 +558,7 @@ EditorRegions::selection_changed () // since we need a region ptr. if (region) { - + if (region->automatic()) { _display.get_selection()->unselect(*i); @@ -552,9 +585,9 @@ EditorRegions::set_selected (RegionSelection& regions) for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { boost::shared_ptr r ((*i)->region()); - + RegionRowMap::iterator it; - + it = region_row_map.find (r); if (it != region_row_map.end()){ @@ -581,17 +614,17 @@ EditorRegions::redisplay () _display.set_model (Glib::RefPtr(0)); _model->clear (); _model->set_sort_column (-2, SORT_ASCENDING); //Disable sorting to gain performance - + region_row_map.clear(); parent_regions_sources_map.clear(); - + /* now add everything we have, via a temporary list used to help with sorting */ const RegionFactory::RegionMap& regions (RegionFactory::regions()); for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) { - + if ( i->second->whole_file()) { /* add automatic regions first so that children can find their parents as we add them */ add_region (i->second); @@ -604,7 +637,7 @@ EditorRegions::redisplay () for (list >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { add_region (*r); } - + _model->set_sort_column (0, SORT_ASCENDING); // renabale sorting _display.set_model (_model); @@ -623,7 +656,7 @@ EditorRegions::update_row (boost::shared_ptr region) } RegionRowMap::iterator it; - + it = region_row_map.find (region); if (it != region_row_map.end()){ @@ -645,9 +678,9 @@ EditorRegions::update_all_rows () for (i = region_row_map.begin(); i != region_row_map.end(); ++i) { TreeModel::iterator j = _model->get_iter ((*i).second.get_path()); - + boost::shared_ptr region = (*j)[_columns.region]; - + if (!region->automatic()) { populate_row(region, (*j)); } @@ -655,15 +688,19 @@ EditorRegions::update_all_rows () } void -EditorRegions::format_position (framepos_t pos, char* buf, size_t bufsize) +EditorRegions::format_position (framepos_t pos, char* buf, size_t bufsize, bool onoff) { Timecode::BBT_Time bbt; Timecode::Time timecode; - switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { + switch (ARDOUR_UI::instance()->secondary_clock->mode ()) { case AudioClock::BBT: _session->tempo_map().bbt_time (pos, bbt); - snprintf (buf, bufsize, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + if (onoff) { + snprintf (buf, bufsize, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + } else { + snprintf (buf, bufsize, "(%03d|%02d|%04d)" , bbt.bars, bbt.beats, bbt.ticks); + } break; case AudioClock::MinSec: @@ -678,18 +715,29 @@ EditorRegions::format_position (framepos_t pos, char* buf, size_t bufsize) mins = (int) floor (left / (_session->frame_rate() * 60.0f)); left -= (framecnt_t) floor (mins * _session->frame_rate() * 60.0f); secs = left / (float) _session->frame_rate(); - snprintf (buf, bufsize, "%02d:%02d:%06.3f", hrs, mins, secs); + if (onoff) { + snprintf (buf, bufsize, "%02d:%02d:%06.3f", hrs, mins, secs); + } else { + snprintf (buf, bufsize, "(%02d:%02d:%06.3f)", hrs, mins, secs); + } break; case AudioClock::Frames: - snprintf (buf, bufsize, "%" PRId64, pos); + if (onoff) { + snprintf (buf, bufsize, "%" PRId64, pos); + } else { + snprintf (buf, bufsize, "(%" PRId64 ")", pos); + } break; case AudioClock::Timecode: - case AudioClock::Off: /* If the secondary clock is off, default to Timecode */ default: _session->timecode_time (pos, timecode); - snprintf (buf, bufsize, "%02d:%02d:%02d:%02d", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + if (onoff) { + snprintf (buf, bufsize, "%02d:%02d:%02d:%02d", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + } else { + snprintf (buf, bufsize, "(%02d:%02d:%02d:%02d)", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames); + } break; } } @@ -701,7 +749,7 @@ EditorRegions::populate_row (boost::shared_ptr region, TreeModel::Row co //uint32_t used = _session->playlists->region_use_count (region); /* Presently a region is only used once so let's save on the sequential scan to determine use count */ uint32_t used = 1; - + populate_row_position (region, row, used); populate_row_end (region, row, used); populate_row_sync (region, row, used); @@ -749,7 +797,7 @@ EditorRegions::populate_row (boost::shared_ptr region, TreeModel::Row co #endif void -EditorRegions::populate_row_used (boost::shared_ptr region, TreeModel::Row const& row, uint32_t used) +EditorRegions::populate_row_used (boost::shared_ptr, TreeModel::Row const& row, uint32_t used) { char buf[8]; snprintf (buf, sizeof (buf), "%4d" , used); @@ -821,16 +869,9 @@ EditorRegions::populate_row_fade_in (boost::shared_ptr region, TreeModel if (used > 1) { row[_columns.fadein] = _("Multiple"); } else { - - char buf[16]; - format_position (audioregion->fade_in()->back()->when, buf, sizeof (buf)); + char buf[32]; + format_position (audioregion->fade_in()->back()->when, buf, sizeof (buf), audioregion->fade_in_active()); row[_columns.fadein] = buf; - - if (audioregion->fade_in_active()) { - row[_columns.fadein] = string_compose("%1%2%3", " ", buf, " "); - } else { - row[_columns.fadein] = string_compose("%1%2%3", "(", buf, ")"); - } } } } @@ -844,18 +885,13 @@ EditorRegions::populate_row_fade_out (boost::shared_ptr region, TreeMode if (used > 1) { row[_columns.fadeout] = _("Multiple"); } else { - char buf[16]; - format_position (audioregion->fade_out()->back()->when, buf, sizeof (buf)); - - if (audioregion->fade_out_active()) { - row[_columns.fadeout] = string_compose("%1%2%3", " ", buf, " "); - } else { - row[_columns.fadeout] = string_compose("%1%2%3", "(", buf, ")"); - } - } + char buf[32]; + format_position (audioregion->fade_out()->back()->when, buf, sizeof (buf), audioregion->fade_out_active()); + row[_columns.fadeout] = buf; + } } } - + void EditorRegions::populate_row_locked (boost::shared_ptr region, TreeModel::Row const &row, uint32_t used) { @@ -910,7 +946,7 @@ EditorRegions::populate_row_name (boost::shared_ptr region, TreeModel::R } else { row[_columns.name] = region->name(); } -} +} void EditorRegions::populate_row_source (boost::shared_ptr region, TreeModel::Row const &row) @@ -964,7 +1000,7 @@ EditorRegions::show_context_menu (int button, int time) bool have_shown = false; bool have_hidden = false; - + TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows (); for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { TreeIter t = _model->get_iter (*i); @@ -992,7 +1028,7 @@ EditorRegions::key_press (GdkEventKey* ev) switch (ev->keyval) { case GDK_Tab: case GDK_ISO_Left_Tab: - + if (name_editable) { name_editable->editing_done (); name_editable = 0; @@ -1237,7 +1273,7 @@ void EditorRegions::name_editing_started (CellEditable* ce, const Glib::ustring&) { name_editable = ce; - + /* give it a special name */ Gtk::Entry *e = dynamic_cast (ce); @@ -1246,7 +1282,7 @@ EditorRegions::name_editing_started (CellEditable* ce, const Glib::ustring&) e->set_name (X_("RegionNameEditorEntry")); } } - + void EditorRegions::name_edit (const std::string& path, const std::string& new_text) { @@ -1286,7 +1322,7 @@ EditorRegions::get_dragged_region () if (regions.empty()) { return boost::shared_ptr (); } - + assert (regions.size() == 1); return regions.front (); } @@ -1297,6 +1333,10 @@ EditorRegions::clear () _display.set_model (Glib::RefPtr (0)); _model->clear (); _display.set_model (_model); + + /* Clean up the maps */ + region_row_map.clear(); + parent_regions_sources_map.clear(); } boost::shared_ptr @@ -1321,15 +1361,15 @@ EditorRegions::get_single_selection () return (*iter)[_columns.region]; } -void +void EditorRegions::freeze_tree_model (){ - + _display.set_model (Glib::RefPtr(0)); _model->set_sort_column (-2, SORT_ASCENDING); //Disable sorting to gain performance } -void +void EditorRegions::thaw_tree_model (){ _model->set_sort_column (0, SORT_ASCENDING); // renabale sorting @@ -1418,7 +1458,7 @@ EditorRegions::set_state (const XMLNode & node) } XMLProperty const * p = node.property (X_("sort-type")); - + if (p) { Editing::RegionListSortType const t = static_cast (string_2_enum (p->value(), _sort_type)); @@ -1432,21 +1472,21 @@ EditorRegions::set_state (const XMLNode & node) } p = node.property (X_("sort-ascending")); - + if (p) { bool const yn = string_is_affirmative (p->value ()); SortType old_sort_type; int old_sort_column; _model->get_sort_column_id (old_sort_column, old_sort_type); - + if (old_sort_type != (yn ? SORT_ASCENDING : SORT_DESCENDING)) { changed = true; } reset_sort_direction (yn); RefPtr act; - + if (yn) { act = ActionManager::get_action (X_("RegionList"), X_("SortAscending")); } else { @@ -1463,7 +1503,7 @@ EditorRegions::set_state (const XMLNode & node) if (expanded != yn) { changed = true; } - + set_full (yn); toggle_full_action()->set_active (yn); } @@ -1478,7 +1518,7 @@ EditorRegions::set_state (const XMLNode & node) changed = true; } } - + if (changed) { redisplay (); } @@ -1535,7 +1575,7 @@ RefPtr EditorRegions::hide_action () const { return ActionManager::get_action (X_("RegionList"), X_("rlHide")); - + } RefPtr @@ -1545,7 +1585,7 @@ EditorRegions::show_action () const } RefPtr -EditorRegions::delete_unused_regions_action () const +EditorRegions::remove_unused_regions_action () const { return ActionManager::get_action (X_("RegionList"), X_("removeUnusedRegions")); }