Fix session-open after selecting new, template, then back
[ardour.git] / gtk2_ardour / editor_regions.cc
index 63b96f1e64c3288b56638461842f5cbad8faf752..0372e1f3d89220c35179f11c9ec0b4dfb7078599 100644 (file)
 #include "ardour/session.h"
 #include "ardour/profile.h"
 
-#include "gtkmm2ext/choice.h"
 #include "gtkmm2ext/treeutils.h"
 #include "gtkmm2ext/utils.h"
 
+#include "widgets/choice.h"
+#include "widgets/tooltips.h"
+
 #include "audio_clock.h"
 #include "editor.h"
 #include "editing.h"
+#include "editing_convert.h"
 #include "keyboard.h"
 #include "ardour_ui.h"
 #include "gui_thread.h"
 #include "editor_regions.h"
 #include "editor_drag.h"
 #include "main_clock.h"
-#include "tooltips.h"
 #include "ui_config.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
+using namespace ArdourWidgets;
 using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace Gtk;
@@ -64,9 +67,9 @@ using namespace Editing;
 using Gtkmm2ext::Keyboard;
 
 struct ColumnInfo {
-    int         index;
-    const char* label;
-    const char* tooltip;
+       int         index;
+       const char* label;
+       const char* tooltip;
 };
 
 EditorRegions::EditorRegions (Editor* e)
@@ -77,13 +80,14 @@ EditorRegions::EditorRegions (Editor* e)
        , _show_automatic_regions (true)
        , ignore_region_list_selection_change (false)
        , ignore_selected_region_change (false)
-       , _no_redisplay (false)
+       , _no_redisplay (false)
        , _sort_type ((Editing::RegionListSortType) 0)
        , expanded (false)
 {
        _display.set_size_request (100, -1);
        _display.set_rules_hint (true);
        _display.set_name ("EditGroupList");
+       _display.set_fixed_height_mode (true);
 
        /* Try to prevent single mouse presses from initiating edits.
           This relies on a hack in gtktreeview.c:gtk_treeview_button_press()
@@ -94,19 +98,59 @@ EditorRegions::EditorRegions (Editor* e)
        _model->set_sort_func (0, sigc::mem_fun (*this, &EditorRegions::sorter));
        _model->set_sort_column (0, SORT_ASCENDING);
 
-       _display.set_model (_model);
-
-       _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);
+       /* column widths */
+       int bbt_width, check_width, height;
+
+       Glib::RefPtr<Pango::Layout> layout = _display.create_pango_layout (X_("000|000|000"));
+       Gtkmm2ext::get_pixel_size (layout, bbt_width, height);
+
+       check_width = 20;
+
+       TreeViewColumn* col_name = manage (new TreeViewColumn ("", _columns.name));
+       col_name->set_fixed_width (120);
+       col_name->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_position = manage (new TreeViewColumn ("", _columns.position));
+       col_position->set_fixed_width (bbt_width);
+       col_position->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_end = manage (new TreeViewColumn ("", _columns.end));
+       col_end->set_fixed_width (bbt_width);
+       col_end->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_length = manage (new TreeViewColumn ("", _columns.length));
+       col_length->set_fixed_width (bbt_width);
+       col_length->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_sync = manage (new TreeViewColumn ("", _columns.sync));
+       col_sync->set_fixed_width (bbt_width);
+       col_sync->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_fadein = manage (new TreeViewColumn ("", _columns.fadein));
+       col_fadein->set_fixed_width (bbt_width);
+       col_fadein->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_fadeout = manage (new TreeViewColumn ("", _columns.fadeout));
+       col_fadeout->set_fixed_width (bbt_width);
+       col_fadeout->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_locked = manage (new TreeViewColumn ("", _columns.locked));
+       col_locked->set_fixed_width (check_width);
+       col_locked->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_glued = manage (new TreeViewColumn ("", _columns.glued));
+       col_glued->set_fixed_width (check_width);
+       col_glued->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_muted = manage (new TreeViewColumn ("", _columns.muted));
+       col_muted->set_fixed_width (check_width);
+       col_muted->set_sizing (TREE_VIEW_COLUMN_FIXED);
+       TreeViewColumn* col_opaque = manage (new TreeViewColumn ("", _columns.opaque));
+       col_opaque->set_fixed_width (check_width);
+       col_opaque->set_sizing (TREE_VIEW_COLUMN_FIXED);
+
+       _display.append_column (*col_name);
+       _display.append_column (*col_position);
+       _display.append_column (*col_end);
+       _display.append_column (*col_length);
+       _display.append_column (*col_sync);
+       _display.append_column (*col_fadein);
+       _display.append_column (*col_fadeout);
+       _display.append_column (*col_locked);
+       _display.append_column (*col_glued);
+       _display.append_column (*col_muted);
+       _display.append_column (*col_opaque);
 
        TreeViewColumn* col;
        Gtk::Label* l;
@@ -138,6 +182,7 @@ EditorRegions::EditorRegions (Editor* e)
                        col->set_alignment (ALIGN_CENTER);
                }
        }
+       _display.set_model (_model);
 
        _display.set_headers_visible (true);
        _display.set_rules_hint ();
@@ -379,15 +424,7 @@ EditorRegions::add_region (boost::shared_ptr<Region> region)
                        str = region->name();
                }
 
-               if (region->n_channels() > 1) {
-                       std::stringstream foo;
-                       foo << region->n_channels ();
-                       str += " [";
-                       str += foo.str();
-                       str += "]";
-               }
-
-               row[_columns.name] = str;
+               populate_row_name (region, row);
                row[_columns.region] = region;
                row[_columns.property_toggles_visible] = false;
 
@@ -446,8 +483,8 @@ EditorRegions::add_region (boost::shared_ptr<Region> region)
        row[_columns.region] = region;
 
        region_row_map.insert(pair<boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::RowReference>(region, TreeRowReference(_model, TreePath (row))) );
-
-       populate_row(region, (*row));
+       PropertyChange pc;
+       populate_row(region, (*row), pc);
 }
 
 void
@@ -460,13 +497,13 @@ EditorRegions::remove_unused_regions ()
                return;
        }
 
-       prompt  = _("Do you really want to remove unused regions?"
-                   "\n(This is destructive and cannot be undone)");
+       prompt = _("Do you really want to remove unused regions?"
+                  "\n(This is destructive and cannot be undone)");
 
        choices.push_back (_("No, do nothing."));
        choices.push_back (_("Yes, remove."));
 
-       Gtkmm2ext::Choice prompter (_("Remove unused regions"), prompt, choices);
+       ArdourWidgets::Choice prompter (_("Remove unused regions"), prompt, choices);
 
        if (prompter.run () == 1) {
                _no_redisplay = true;
@@ -485,6 +522,7 @@ EditorRegions::region_changed (boost::shared_ptr<Region> r, const PropertyChange
        our_interests.add (ARDOUR::Properties::position);
        our_interests.add (ARDOUR::Properties::length);
        our_interests.add (ARDOUR::Properties::start);
+       our_interests.add (ARDOUR::Properties::sync_position);
        our_interests.add (ARDOUR::Properties::locked);
        our_interests.add (ARDOUR::Properties::position_lock_style);
        our_interests.add (ARDOUR::Properties::muted);
@@ -495,14 +533,13 @@ EditorRegions::region_changed (boost::shared_ptr<Region> r, const PropertyChange
        our_interests.add (ARDOUR::Properties::fade_out_active);
 
        if (what_changed.contains (our_interests)) {
-
                if (last_row != 0) {
 
                        TreeModel::iterator j = _model->get_iter (last_row.get_path());
                        boost::shared_ptr<Region> c = (*j)[_columns.region];
 
                        if (c == r) {
-                               populate_row (r, (*j));
+                               populate_row (r, (*j), what_changed);
 
                                if (what_changed.contains (ARDOUR::Properties::hidden)) {
                                        redisplay ();
@@ -522,7 +559,7 @@ EditorRegions::region_changed (boost::shared_ptr<Region> r, const PropertyChange
                        boost::shared_ptr<Region> c = (*j)[_columns.region];
 
                        if (c == r) {
-                               populate_row (r, (*j));
+                               populate_row (r, (*j), what_changed);
 
                                if (what_changed.contains (ARDOUR::Properties::hidden)) {
                                        redisplay ();
@@ -661,9 +698,9 @@ EditorRegions::update_row (boost::shared_ptr<Region> region)
        it = region_row_map.find (region);
 
        if (it != region_row_map.end()){
-
+               PropertyChange c;
                TreeModel::iterator j = _model->get_iter ((*it).second.get_path());
-               populate_row(region, (*j));
+               populate_row(region, (*j), c);
        }
 }
 
@@ -683,7 +720,8 @@ EditorRegions::update_all_rows ()
                boost::shared_ptr<Region> region = (*j)[_columns.region];
 
                if (!region->automatic()) {
-                       populate_row(region, (*j));
+                       PropertyChange c;
+                       populate_row(region, (*j), c);
                }
        }
 }
@@ -702,7 +740,7 @@ EditorRegions::format_position (framepos_t pos, char* buf, size_t bufsize, bool
 
        switch (ARDOUR_UI::instance()->secondary_clock->mode ()) {
        case AudioClock::BBT:
-               _session->tempo_map().bbt_time (pos, bbt);
+               bbt = _session->tempo_map().bbt_at_frame (pos);
                if (onoff) {
                        snprintf (buf, bufsize, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
                } else {
@@ -750,26 +788,53 @@ EditorRegions::format_position (framepos_t pos, char* buf, size_t bufsize, bool
 }
 
 void
-EditorRegions::populate_row (boost::shared_ptr<Region> region, TreeModel::Row const &row)
+EditorRegions::populate_row (boost::shared_ptr<Region> region, TreeModel::Row const &row, PBD::PropertyChange const &what_changed)
 {
        boost::shared_ptr<AudioRegion> audioregion = boost::dynamic_pointer_cast<AudioRegion>(region);
        //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);
-       populate_row_fade_in (region, row, used, audioregion);
-       populate_row_fade_out (region, row, used, audioregion);
-       populate_row_locked (region, row, used);
-       populate_row_glued (region, row, used);
-       populate_row_muted (region, row, used);
-       populate_row_opaque (region, row, used);
-       populate_row_length (region, row);
-       populate_row_source (region, row);
-       populate_row_name (region, row);
-       populate_row_used (region, row, used);
+       PropertyChange c;
+       const bool all = what_changed == c;
+
+       if (all || what_changed.contains (Properties::position)) {
+               populate_row_position (region, row, used);
+       }
+       if (all || what_changed.contains (Properties::start) || what_changed.contains (Properties::sync_position)) {
+               populate_row_sync (region, row, used);
+       }
+       if (all || what_changed.contains (Properties::fade_in)) {
+               populate_row_fade_in (region, row, used, audioregion);
+       }
+       if (all || what_changed.contains (Properties::fade_out)) {
+               populate_row_fade_out (region, row, used, audioregion);
+       }
+       if (all || what_changed.contains (Properties::locked)) {
+               populate_row_locked (region, row, used);
+       }
+       if (all || what_changed.contains (Properties::position_lock_style)) {
+               populate_row_glued (region, row, used);
+       }
+       if (all || what_changed.contains (Properties::muted)) {
+               populate_row_muted (region, row, used);
+       }
+       if (all || what_changed.contains (Properties::opaque)) {
+               populate_row_opaque (region, row, used);
+       }
+       if (all || what_changed.contains (Properties::length)) {
+               populate_row_end (region, row, used);
+               populate_row_length (region, row);
+       }
+       if (all) {
+               populate_row_source (region, row);
+       }
+       if (all || what_changed.contains (Properties::name)) {
+               populate_row_name (region, row);
+       }
+       if (all) {
+               populate_row_used (region, row, used);
+       }
 }
 
 #if 0
@@ -815,7 +880,15 @@ void
 EditorRegions::populate_row_length (boost::shared_ptr<Region> region, TreeModel::Row const &row)
 {
        char buf[16];
-       format_position (region->length(), buf, sizeof (buf));
+
+       if (ARDOUR_UI::instance()->secondary_clock->mode () == AudioClock::BBT) {
+               TempoMap& map (_session->tempo_map());
+               Timecode::BBT_Time bbt = map.bbt_at_beat (map.beat_at_frame (region->last_frame()) - map.beat_at_frame (region->first_frame()));
+               snprintf (buf, sizeof (buf), "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
+       } else {
+               format_position (region->length(), buf, sizeof (buf));
+       }
+
        row[_columns.length] = buf;
 }
 
@@ -960,7 +1033,7 @@ EditorRegions::populate_row_name (boost::shared_ptr<Region> region, TreeModel::R
 void
 EditorRegions::populate_row_source (boost::shared_ptr<Region> region, TreeModel::Row const &row)
 {
-        if (boost::dynamic_pointer_cast<SilentFileSource>(region->source())) {
+       if (boost::dynamic_pointer_cast<SilentFileSource>(region->source())) {
                row[_columns.path] = _("MISSING ") + Gtkmm2ext::markup_escape_text (region->source()->name());
        } else {
                row[_columns.path] = Gtkmm2ext::markup_escape_text (region->source()->name());
@@ -985,10 +1058,10 @@ EditorRegions::set_full (bool f)
 {
        if (f) {
                _display.expand_all ();
-                expanded = true;
+               expanded = true;
        } else {
                _display.collapse_all ();
-                expanded = false;
+               expanded = false;
        }
 }
 
@@ -1232,9 +1305,9 @@ EditorRegions::selection_mapover (sigc::slot<void,boost::shared_ptr<Region> > sl
 
 void
 EditorRegions::drag_data_received (const RefPtr<Gdk::DragContext>& context,
-                                  int x, int y,
-                                  const SelectionData& data,
-                                  guint info, guint time)
+                                   int x, int y,
+                                   const SelectionData& data,
+                                   guint info, guint time)
 {
        vector<string> paths;
 
@@ -1250,7 +1323,8 @@ EditorRegions::drag_data_received (const RefPtr<Gdk::DragContext>& context,
                bool copy = ((context->get_actions() & (Gdk::ACTION_COPY | Gdk::ACTION_LINK | Gdk::ACTION_MOVE)) == Gdk::ACTION_COPY);
 
                if (UIConfiguration::instance().get_only_copy_imported_files() || copy) {
-                       _editor->do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsRegion, SrcBest, pos);
+                       _editor->do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsRegion,
+                                           SrcBest, SMFTrackName, SMFTempoIgnore, pos);
                } else {
                        _editor->do_embed (paths, Editing::ImportDistinctFiles, ImportAsRegion, pos);
                }
@@ -1281,7 +1355,7 @@ EditorRegions::selection_filter (const RefPtr<TreeModel>& model, const TreeModel
 }
 
 void
-EditorRegions::name_editing_started (CellEditable* ce, const Glib::ustring&)
+EditorRegions::name_editing_started (CellEditable* ce, const Glib::ustring& path)
 {
        name_editable = ce;
 
@@ -1291,6 +1365,15 @@ EditorRegions::name_editing_started (CellEditable* ce, const Glib::ustring&)
 
        if (e) {
                e->set_name (X_("RegionNameEditorEntry"));
+
+               TreeIter iter;
+               if ((iter = _model->get_iter (path))) {
+                       boost::shared_ptr<Region> region = (*iter)[_columns.region];
+
+                       if(region) {
+                               e->set_text(region->name());
+                       }
+               }
        }
 }
 
@@ -1300,11 +1383,11 @@ EditorRegions::name_edit (const std::string& path, const std::string& new_text)
        name_editable = 0;
 
        boost::shared_ptr<Region> region;
-       TreeIter iter;
+       TreeIter row_iter;
 
-       if ((iter = _model->get_iter (path))) {
-               region = (*iter)[_columns.region];
-               (*iter)[_columns.name] = new_text;
+       if ((row_iter = _model->get_iter (path))) {
+               region = (*row_iter)[_columns.region];
+               (*row_iter)[_columns.name] = new_text;
        }
 
        /* now mapover everything */
@@ -1318,8 +1401,9 @@ EditorRegions::name_edit (const std::string& path, const std::string& new_text)
                                (*i)->region()->set_name (new_text);
                        }
                }
-       }
 
+               populate_row_name (region, (*row_iter));
+       }
 }
 
 /** @return Region that has been dragged out of the list, or 0 */
@@ -1448,13 +1532,13 @@ EditorRegions::get_state () const
 {
        XMLNode* node = new XMLNode (X_("RegionList"));
 
-       node->add_property (X_("sort-type"), enum_2_string (_sort_type));
+       node->set_property (X_("sort-type"), _sort_type);
 
        RefPtr<Action> act = ActionManager::get_action (X_("RegionList"), X_("SortAscending"));
        bool const ascending = RefPtr<RadioAction>::cast_dynamic(act)->get_active ();
-       node->add_property (X_("sort-ascending"), ascending ? "yes" : "no");
-       node->add_property (X_("show-all"), toggle_full_action()->get_active() ? "yes" : "no");
-       node->add_property (X_("show-automatic-regions"), _show_automatic_regions ? "yes" : "no");
+       node->set_property (X_("sort-ascending"), ascending);
+       node->set_property (X_("show-all"), toggle_full_action()->get_active());
+       node->set_property (X_("show-automatic-regions"), _show_automatic_regions);
 
        return *node;
 }
@@ -1468,10 +1552,8 @@ EditorRegions::set_state (const XMLNode & node)
                return;
        }
 
-       XMLProperty const * p = node.property (X_("sort-type"));
-
-       if (p) {
-               Editing::RegionListSortType const t = static_cast<Editing::RegionListSortType> (string_2_enum (p->value(), _sort_type));
+       Editing::RegionListSortType t;
+       if (node.get_property (X_("sort-type"), t)) {
 
                if (_sort_type != t) {
                        changed = true;
@@ -1482,10 +1564,8 @@ EditorRegions::set_state (const XMLNode & node)
                ract->set_active ();
        }
 
-       p = node.property (X_("sort-ascending"));
-
-       if (p) {
-               bool const yn = string_is_affirmative (p->value ());
+       bool yn;
+       if (node.get_property (X_("sort-ascending"), yn)) {
                SortType old_sort_type;
                int old_sort_column;
 
@@ -1507,10 +1587,7 @@ EditorRegions::set_state (const XMLNode & node)
                RefPtr<RadioAction>::cast_dynamic(act)->set_active ();
        }
 
-       p = node.property (X_("show-all"));
-       if (p) {
-               bool const yn = string_is_affirmative (p->value ());
-
+       if (node.get_property (X_("show-all"), yn)) {
                if (expanded != yn) {
                        changed = true;
                }
@@ -1519,10 +1596,7 @@ EditorRegions::set_state (const XMLNode & node)
                toggle_full_action()->set_active (yn);
        }
 
-       p = node.property (X_("show-automatic-regions"));
-       if (p) {
-               bool const yn = string_is_affirmative (p->value ());
-
+       if (node.get_property (X_("show-automatic-regions"), yn)) {
                if (yn != _show_automatic_regions) {
                        _show_automatic_regions = yn;
                        toggle_show_auto_regions_action()->set_active (yn);