From a3f7f86d9b8cee4183e9da6c2f8f6cfd4ee26969 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Fri, 3 Jul 2009 22:42:22 +0000 Subject: [PATCH] Factor regions list out of Editor. git-svn-id: svn://localhost/ardour2/branches/3.0@5312 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor.cc | 140 ++- gtk2_ardour/editor.h | 122 +-- gtk2_ardour/editor_actions.cc | 33 +- gtk2_ardour/editor_canvas_events.cc | 7 +- gtk2_ardour/editor_mixer.cc | 8 +- gtk2_ardour/editor_ops.cc | 40 +- gtk2_ardour/editor_region_list.cc | 1144 ------------------------- gtk2_ardour/editor_regions.cc | 1228 +++++++++++++++++++++++++++ gtk2_ardour/editor_regions.h | 151 ++++ gtk2_ardour/editor_selection.cc | 11 +- gtk2_ardour/wscript | 2 +- 11 files changed, 1489 insertions(+), 1397 deletions(-) delete mode 100644 gtk2_ardour/editor_region_list.cc create mode 100644 gtk2_ardour/editor_regions.cc create mode 100644 gtk2_ardour/editor_regions.h diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9e04d0c388..ca51d571be 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -102,6 +102,7 @@ #include "midi_time_axis.h" #include "mixer_strip.h" #include "editor_route_groups.h" +#include "editor_regions.h" #include "i18n.h" @@ -305,17 +306,14 @@ Editor::Editor () show_gain_after_trim = false; verbose_cursor_on = true; route_removal = false; - show_automatic_regions_in_region_list = true; last_item_entered = 0; last_item_entered_n = 0; - region_list_sort_type = (Editing::RegionListSortType) 0; have_pending_keyboard_selection = false; _follow_playhead = true; _xfade_visibility = true; editor_ruler_menu = 0; no_ruler_shown_update = false; - region_list_menu = 0; marker_menu = 0; start_end_marker_menu = 0; range_marker_menu = 0; @@ -352,7 +350,6 @@ Editor::Editor () } allow_vertical_scroll = false; no_save_visual = false; - no_region_list_redisplay = false; resize_idle_id = -1; scrubbing_direction = 0; @@ -532,74 +529,8 @@ Editor::Editor () _route_groups = new EditorRouteGroups (this); _routes = new EditorRoutes (this); + _regions = new EditorRegions (this); - region_list_display.set_size_request (100, -1); - region_list_display.set_name ("RegionListDisplay"); - /* Try to prevent single mouse presses from initiating edits. - This relies on a hack in gtktreeview.c:gtk_treeview_button_press() - */ - region_list_display.set_data ("mouse-edits-require-mod1", (gpointer) 0x1); - - region_list_model = TreeStore::create (region_list_columns); - region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter)); - region_list_model->set_sort_column (0, SORT_ASCENDING); - - region_list_display.set_model (region_list_model); - region_list_display.append_column (_("Regions"), region_list_columns.name); - region_list_display.append_column (_("Start"), region_list_columns.start); - region_list_display.append_column (_("End"), region_list_columns.end); - region_list_display.append_column (_("Length"), region_list_columns.length); - region_list_display.append_column (_("Sync"), region_list_columns.sync); - region_list_display.append_column (_("Fade In"), region_list_columns.fadein); - region_list_display.append_column (_("Fade Out"), region_list_columns.fadeout); - region_list_display.append_column (_("L"), region_list_columns.locked); - region_list_display.append_column (_("G"), region_list_columns.glued); - region_list_display.append_column (_("M"), region_list_columns.muted); - region_list_display.append_column (_("O"), region_list_columns.opaque); - region_list_display.append_column (_("Used"), region_list_columns.used); - region_list_display.append_column (_("Path"), region_list_columns.path); - region_list_display.set_headers_visible (true); - //region_list_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH); - - CellRendererText* region_name_cell = dynamic_cast(region_list_display.get_column_cell_renderer (0)); - region_name_cell->property_editable() = true; - region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit)); - - region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter)); - - TreeViewColumn* tv_col = region_list_display.get_column(0); - CellRendererText* renderer = dynamic_cast(region_list_display.get_column_cell_renderer (0)); - tv_col->add_attribute(renderer->property_text(), region_list_columns.name); - tv_col->add_attribute(renderer->property_foreground_gdk(), region_list_columns.color_); - - region_list_display.get_selection()->set_mode (SELECTION_MULTIPLE); - region_list_display.add_object_drag (region_list_columns.region.index(), "regions"); - - /* setup DnD handling */ - - list region_list_target_table; - - region_list_target_table.push_back (TargetEntry ("text/plain")); - region_list_target_table.push_back (TargetEntry ("text/uri-list")); - region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop")); - - region_list_display.add_drop_targets (region_list_target_table); - region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received)); - - region_list_scroller.add (region_list_display); - region_list_scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC); - - region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press)); - region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release)); - region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press), false); - region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release)); - region_list_change_connection = region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed)); - // region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0)); - - //ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::redisplay_regions)); - ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::update_all_region_rows)); - ARDOUR::Region::RegionPropertyChanged.connect (mem_fun(*this, &Editor::update_region_row)); - named_selection_scroller.add (named_selection_display); named_selection_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC); @@ -635,7 +566,7 @@ Editor::Editor () nlabel = manage (new Label (_("Regions"))); nlabel->set_angle (-90); - the_notebook.append_page (region_list_scroller, *nlabel); + the_notebook.append_page (_regions->widget (), *nlabel); nlabel = manage (new Label (_("Tracks/Busses"))); nlabel->set_angle (-90); the_notebook.append_page (_routes->widget (), *nlabel); @@ -1166,15 +1097,12 @@ Editor::connect_to_session (Session *t) session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state))); session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change))); session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route))); - session_connections.push_back (session->RegionsAdded.connect (mem_fun(*this, &Editor::handle_new_regions))); - session_connections.push_back (session->RegionRemoved.connect (mem_fun(*this, &Editor::handle_region_removed))); session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration))); session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection))); session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection))); session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title))); session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s))); session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog))); - session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden))); session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte))); @@ -1183,8 +1111,6 @@ Editor::connect_to_session (Session *t) session_connections.push_back (session->Located.connect (mem_fun (*this, &Editor::located))); session_connections.push_back (session->config.ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed))); - _route_groups->connect_to_session (session); - edit_point_clock.set_mode(AudioClock::BBT); edit_point_clock.set_session (session); zoom_range_clock.set_session (session); @@ -1256,7 +1182,6 @@ Editor::connect_to_session (Session *t) handle_new_duration (); - redisplay_regions (); redisplay_named_selections (); redisplay_snapshots (); @@ -1289,6 +1214,8 @@ Editor::connect_to_session (Session *t) _summary->connect_to_session (session); _group_tabs->connect_to_session (session); + _route_groups->connect_to_session (session); + _regions->connect_to_session (session); start_updating (); } @@ -2477,8 +2404,7 @@ Editor::set_state (const XMLNode& node) } if ((prop = node.property ("region-list-sort-type"))) { - region_list_sort_type = (Editing::RegionListSortType) -1; // force change - reset_region_list_sort_type(str2regionlistsorttype(prop->value())); + _regions->reset_sort_type (str2regionlistsorttype(prop->value()), true); } if ((prop = node.property ("xfades-visible"))) { @@ -2579,7 +2505,7 @@ Editor::get_state () node->add_property ("show-measures", _show_measures ? "yes" : "no"); node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no"); - node->add_property ("region-list-sort-type", enum2str(region_list_sort_type)); + node->add_property ("region-list-sort-type", enum2str (_regions->sort_type ())); node->add_property ("mouse-mode", enum2str(mouse_mode)); Glib::RefPtr act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer")); @@ -4086,14 +4012,13 @@ Editor::prepare_for_cleanup () selection->clear_regions (); selection->clear_playlists (); - no_region_list_redisplay = true; + _regions->suspend_redisplay (); } void Editor::finish_cleanup () { - no_region_list_redisplay = false; - redisplay_regions (); + _regions->resume_redisplay (); } Location* @@ -5276,3 +5201,50 @@ Editor::fit_route_group (RouteGroup *g) TrackSelection ts = axis_views_from_routes (g->route_list ()); fit_tracks (ts); } + +void +Editor::consider_auditioning (boost::shared_ptr region) +{ + boost::shared_ptr r = boost::dynamic_pointer_cast (region); + + if (r == 0) { + session->cancel_audition (); + return; + } + + if (session->is_auditioning()) { + session->cancel_audition (); + if (r == last_audition_region) { + return; + } + } + + session->audition_region (r); + last_audition_region = r; +} + + +void +Editor::hide_a_region (boost::shared_ptr r) +{ + r->set_hidden (true); +} + +void +Editor::remove_a_region (boost::shared_ptr r) +{ + session->remove_region_from_region_list (r); +} + +void +Editor::audition_region_from_region_list () +{ + _regions->selection_mapover (mem_fun (*this, &Editor::consider_auditioning)); +} + +void +Editor::hide_region_from_region_list () +{ + _regions->selection_mapover (mem_fun (*this, &Editor::hide_a_region)); +} + diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 2748beaf1a..9e8786f326 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -118,6 +118,7 @@ class TrackSelection; class EditorGroupTabs; class EditorRoutes; class EditorRouteGroups; +class EditorRegions; /* */ class ImageFrameView; @@ -279,6 +280,8 @@ class Editor : public PublicEditor void invert_selection_in_track (); void invert_selection (); void deselect_all (); + + void set_selected_regionview_from_region_list (boost::shared_ptr region, Selection::Operation op = Selection::Set); /* tempo */ @@ -404,6 +407,13 @@ class Editor : public PublicEditor return track_views; } + int get_regionview_count_from_region_list (boost::shared_ptr); + + void do_import (std::vector paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&); + void do_embed (std::vector paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&); + + void get_regions_corresponding_to (boost::shared_ptr region, std::vector& regions); + protected: void map_transport_state (); void map_position_change (nframes64_t); @@ -412,9 +422,9 @@ class Editor : public PublicEditor private: - /// The session that we are editing, or 0 void color_handler (); - ARDOUR::Session *session; + + ARDOUR::Session *session; ///< The session that we are editing, or 0 bool constructed; // to keep track of the playhead position for control_scroll @@ -557,14 +567,11 @@ class Editor : public PublicEditor void set_selected_track (TimeAxisView&, Selection::Operation op = Selection::Set, bool no_remove=false); void select_all_tracks (); - int get_regionview_count_from_region_list (boost::shared_ptr region); - bool set_selected_control_point_from_click (Selection::Operation op = Selection::Set, bool no_remove=false); void set_selected_track_from_click (bool press, Selection::Operation op = Selection::Set, bool no_remove=false); void set_selected_track_as_side_effect (bool force = false); bool set_selected_regionview_from_click (bool press, Selection::Operation op = Selection::Set, bool no_track_remove=false); - void set_selected_regionview_from_region_list (boost::shared_ptr region, Selection::Operation op = Selection::Set); bool set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, boost::weak_ptr); void collect_new_region_view (RegionView *); void collect_and_select_new_region_view (RegionView *); @@ -932,81 +939,6 @@ class Editor : public PublicEditor void end_location_changed (ARDOUR::Location*); - struct RegionListDisplayModelColumns : public Gtk::TreeModel::ColumnRecord { - RegionListDisplayModelColumns() { - add (name); - add (region); - add (color_); - add (start); - add (end); - add (length); - add (sync); - add (fadein); - add (fadeout); - add (locked); - add (glued); - add (muted); - add (opaque); - add (used); - add (path); - } - Gtk::TreeModelColumn name; - Gtk::TreeModelColumn > region; - Gtk::TreeModelColumn color_; - Gtk::TreeModelColumn start; - Gtk::TreeModelColumn end; - Gtk::TreeModelColumn length; - Gtk::TreeModelColumn sync; - Gtk::TreeModelColumn fadein; - Gtk::TreeModelColumn fadeout; - Gtk::TreeModelColumn locked; - Gtk::TreeModelColumn glued; - Gtk::TreeModelColumn muted; - Gtk::TreeModelColumn opaque; - Gtk::TreeModelColumn used; - Gtk::TreeModelColumn path; - }; - - RegionListDisplayModelColumns region_list_columns; - Gtkmm2ext::DnDTreeView > region_list_display; - - Glib::RefPtr region_list_model; - Glib::RefPtr toggle_full_region_list_action; - Glib::RefPtr toggle_show_auto_regions_action; - - void region_list_region_changed (ARDOUR::Change, boost::weak_ptr); - void region_list_selection_changed (); - sigc::connection region_list_change_connection; - void set_selected_in_region_list(RegionSelection&); - bool set_selected_in_region_list_subrow(boost::shared_ptr, Gtk::TreeModel::Row const &, int); - bool region_list_selection_filter (const Glib::RefPtr& model, const Gtk::TreeModel::Path& path, bool yn); - void region_name_edit (const Glib::ustring&, const Glib::ustring&); - void get_regions_corresponding_to (boost::shared_ptr region, std::vector& regions); - - Gtk::Menu *region_list_menu; - Gtk::ScrolledWindow region_list_scroller; - Gtk::Frame region_list_frame; - - bool region_list_display_key_press (GdkEventKey *); - bool region_list_display_key_release (GdkEventKey *); - bool region_list_display_button_press (GdkEventButton *); - bool region_list_display_button_release (GdkEventButton *); - void region_list_clear (); - void region_list_selection_mapover (sigc::slot >); - void build_region_list_menu (); - void show_region_list_display_context_menu (int button, int time); - - bool show_automatic_regions_in_region_list; - Editing::RegionListSortType region_list_sort_type; - - void reset_region_list_sort_direction (bool); - void reset_region_list_sort_type (Editing::RegionListSortType); - - void toggle_full_region_list (); - void toggle_show_auto_regions (); - - int region_list_sorter (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator); - /* snapshots */ Gtk::ScrolledWindow snapshot_display_scroller; @@ -1109,23 +1041,6 @@ class Editor : public PublicEditor int ensure_cursor (nframes64_t* pos); - void handle_new_region (boost::weak_ptr); - void handle_new_regions (std::vector >& ); - void handle_region_removed (boost::weak_ptr); - void add_region_to_region_display (boost::shared_ptr); - void add_regions_to_region_display (std::vector > & ); - void region_hidden (boost::shared_ptr); - void redisplay_regions (); - void populate_row (boost::shared_ptr, Gtk::TreeModel::Row const &); - void update_region_row (boost::shared_ptr); - bool update_region_subrows (boost::shared_ptr, Gtk::TreeModel::Row const &, int); - void update_all_region_rows (); - void update_all_region_subrows (Gtk::TreeModel::Row const &, int); - bool no_region_list_redisplay; - void insert_into_tmp_regionlist(boost::shared_ptr); - - std::list > tmp_region_list; - void cut_copy (Editing::CutCopyOp); bool can_cut_copy () const; void cut_copy_points (Editing::CutCopyOp); @@ -1192,7 +1107,6 @@ class Editor : public PublicEditor void audition_region_from_region_list (); void hide_region_from_region_list (); - void remove_region_from_region_list (); void align (ARDOUR::RegionPoint); void align_relative (ARDOUR::RegionPoint); @@ -1256,9 +1170,6 @@ class Editor : public PublicEditor bool idle_drop_paths (std::vector paths, nframes64_t frame, double ypos); void drop_paths_part_two (const std::vector& paths, nframes64_t frame, double ypos); - void do_import (std::vector paths, Editing::ImportDisposition, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t&); - void do_embed (std::vector paths, Editing::ImportDisposition, Editing::ImportMode mode, nframes64_t&); - int import_sndfiles (std::vector paths, Editing::ImportMode mode, ARDOUR::SrcQuality, nframes64_t& pos, int target_regions, int target_tracks, boost::shared_ptr, bool, uint32_t total); int embed_sndfiles (std::vector paths, bool multiple_files, bool& check_sample_rate, Editing::ImportMode mode, @@ -1768,6 +1679,7 @@ public: EditorRouteGroups* _route_groups; EditorRoutes* _routes; + EditorRegions* _regions; /* diskstream/route display management */ Glib::RefPtr rec_enabled_icon; @@ -1840,14 +1752,6 @@ public: const Gtk::SelectionData& data, guint info, guint time); - - void region_list_display_drag_data_received ( - const Glib::RefPtr& context, - gint x, - gint y, - const Gtk::SelectionData& data, - guint info, - guint time); void drop_paths ( const Glib::RefPtr& context, diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc index 6b98446fde..fa7619b78d 100644 --- a/gtk2_ardour/editor_actions.cc +++ b/gtk2_ardour/editor_actions.cc @@ -31,6 +31,7 @@ #include "audio_time_axis.h" #include "editor_group_tabs.h" #include "editor_routes.h" +#include "editor_regions.h" using namespace Gtk; using namespace Glib; @@ -766,37 +767,37 @@ Editor::register_actions () ActionManager::region_list_selection_sensitive_actions.push_back (act); act = ActionManager::register_action (rl_actions, X_("rlHide"), _("Hide"), mem_fun(*this, &Editor::hide_region_from_region_list)); ActionManager::region_list_selection_sensitive_actions.push_back (act); - act = ActionManager::register_action (rl_actions, X_("rlRemove"), _("Remove"), mem_fun (*this, &Editor::remove_region_from_region_list)); + act = ActionManager::register_action (rl_actions, X_("rlRemove"), _("Remove"), mem_fun (*_regions, &EditorRegions::remove_region)); ActionManager::region_list_selection_sensitive_actions.push_back (act); - ActionManager::register_toggle_action (rl_actions, X_("rlShowAll"), _("Show All"), mem_fun(*this, &Editor::toggle_full_region_list)); - ActionManager::register_toggle_action (rl_actions, X_("rlShowAuto"), _("Show Automatic Regions"), mem_fun(*this, &Editor::toggle_show_auto_regions)); + ActionManager::register_toggle_action (rl_actions, X_("rlShowAll"), _("Show All"), mem_fun(*_regions, &EditorRegions::toggle_full)); + ActionManager::register_toggle_action (rl_actions, X_("rlShowAuto"), _("Show Automatic Regions"), mem_fun (*_regions, &EditorRegions::toggle_show_auto_regions)); ActionManager::register_radio_action (rl_actions, sort_order_group, X_("SortAscending"), _("Ascending"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_direction), true)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_direction), true)); ActionManager::register_radio_action (rl_actions, sort_order_group, X_("SortDescending"), _("Descending"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_direction), false)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_direction), false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionName"), _("By Region Name"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByName)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), ByName, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionLength"), _("By Region Length"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByLength)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), ByLength, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionPosition"), _("By Region Position"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByPosition)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), ByPosition, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionTimestamp"), _("By Region Timestamp"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByTimestamp)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), ByTimestamp, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionStartinFile"), _("By Region Start in File"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByStartInFile)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), ByStartInFile, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionEndinFile"), _("By Region End in File"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByEndInFile)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), ByEndInFile, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFileName"), _("By Source File Name"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileName)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileName, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFileLength"), _("By Source File Length"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileLength)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileLength, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFileCreationDate"), _("By Source File Creation Date"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileCreationDate)); + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileCreationDate, false)); ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFilesystem"), _("By Source Filesystem"), - bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileFS)); - + bind (mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileFS, false)); + /* the next two are duplicate items with different names for use in two different contexts */ diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc index a7fbdec926..4a22c2bda7 100644 --- a/gtk2_ardour/editor_canvas_events.cc +++ b/gtk2_ardour/editor_canvas_events.cc @@ -47,6 +47,7 @@ #include "interactive-item.h" #include "editor_drag.h" #include "midi_time_axis.h" +#include "editor_regions.h" #include "i18n.h" @@ -929,11 +930,7 @@ Editor::track_canvas_drag_motion (Glib::RefPtr const & c, int return true; } - list > regions; - TreeView* source; - region_list_display.get_object_drag_data (regions, &source); - assert (regions.size() == 1); - boost::shared_ptr region = regions.front (); + boost::shared_ptr region = _regions->get_dragged_region (); boost::shared_ptr region_copy = RegionFactory::create (region); diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc index d4b9681c93..46b05a20f4 100644 --- a/gtk2_ardour/editor_mixer.cc +++ b/gtk2_ardour/editor_mixer.cc @@ -33,6 +33,7 @@ #include "actions.h" #include "editor_routes.h" #include "editor_route_groups.h" +#include "editor_regions.h" #include "i18n.h" @@ -369,15 +370,12 @@ Editor::session_going_away () /* rip everything out of the list displays */ - region_list_display.set_model (Glib::RefPtr(0)); + _regions->clear (); _routes->clear (); _route_groups->clear (); + named_selection_display.set_model (Glib::RefPtr(0)); - - region_list_model->clear (); named_selection_model->clear (); - - region_list_display.set_model (region_list_model); named_selection_display.set_model (named_selection_model); edit_point_clock_connection_a.disconnect(); diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc index be87baeafd..0570a43648 100644 --- a/gtk2_ardour/editor_ops.cc +++ b/gtk2_ardour/editor_ops.cc @@ -78,6 +78,7 @@ #include "editor_drag.h" #include "strip_silence_dialog.h" #include "editor_routes.h" +#include "editor_regions.h" #include "i18n.h" @@ -2314,29 +2315,17 @@ Editor::insert_region_list_selection (float times) if ((playlist = tv->playlist()) == 0) { return; } - - Glib::RefPtr selected = region_list_display.get_selection(); - - if (selected->count_selected_rows() != 1) { + + boost::shared_ptr region = _regions->get_single_selection (); + if (region == 0) { return; } - - TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows (); - - /* only one row selected, so rows.begin() is it */ - - TreeIter iter; - - if ((iter = region_list_model->get_iter (*rows.begin()))) { - - boost::shared_ptr region = (*iter)[region_list_columns.region]; - begin_reversible_command (_("insert region")); - XMLNode &before = playlist->get_state(); - playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times); - session->add_command(new MementoCommand(*playlist, &before, &playlist->get_state())); - commit_reversible_command (); - } + begin_reversible_command (_("insert region")); + XMLNode &before = playlist->get_state(); + playlist->add_region ((RegionFactory::create (region)), get_preferred_edit_position(), times); + session->add_command(new MementoCommand(*playlist, &before, &playlist->get_state())); + commit_reversible_command (); } /* BUILT-IN EFFECTS */ @@ -2590,7 +2579,7 @@ Editor::rename_region() strip_whitespace_edges (str); if (!str.empty()) { rs.front()->region()->set_name (str); - redisplay_regions (); + _regions->redisplay (); } } } @@ -3114,16 +3103,11 @@ Editor::region_fill_selection () return; } - - Glib::RefPtr selected = region_list_display.get_selection(); - - if (selected->count_selected_rows() != 1) { + boost::shared_ptr region = _regions->get_single_selection (); + if (region == 0) { return; } - TreeModel::iterator i = region_list_display.get_selection()->get_selected(); - boost::shared_ptr region = (*i)[region_list_columns.region]; - nframes64_t start = selection->time[clicked_selection].start; nframes64_t end = selection->time[clicked_selection].end; diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc deleted file mode 100644 index 46ad668f4d..0000000000 --- a/gtk2_ardour/editor_region_list.cc +++ /dev/null @@ -1,1144 +0,0 @@ -/* - Copyright (C) 2000-2005 Paul Davis - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include -#include -#include -#include -#include - -#include "pbd/basename.h" - -#include "ardour/audioregion.h" -#include "ardour/audiofilesource.h" -#include "ardour/silentfilesource.h" -#include "ardour/session_region.h" -#include "ardour/profile.h" - -#include - -#include "editor.h" -#include "editing.h" -#include "keyboard.h" -#include "ardour_ui.h" -#include "gui_thread.h" -#include "actions.h" -#include "region_view.h" -#include "utils.h" - - -#include "i18n.h" - -using namespace std; -using namespace sigc; -using namespace ARDOUR; -using namespace PBD; -using namespace Gtk; -using namespace Glib; -using namespace Editing; - -void -Editor::handle_region_removed (boost::weak_ptr wregion) -{ - ENSURE_GUI_THREAD (mem_fun (*this, &Editor::redisplay_regions)); - redisplay_regions (); -} - -void -Editor::handle_new_regions (vector >& v) -{ - ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_regions), v)); - add_regions_to_region_display (v); -} - -void -Editor::region_hidden (boost::shared_ptr r) -{ - ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::region_hidden), r)); - redisplay_regions (); -} - -void -Editor::add_regions_to_region_display (vector >& regions) -{ - for (vector >::iterator x = regions.begin(); x != regions.end(); ++x) { - boost::shared_ptr region ((*x).lock()); - if (region) { - add_region_to_region_display (region); - } - } -} - -void -Editor::add_region_to_region_display (boost::shared_ptr region) -{ - if (!region || !session) { - return; - } - - string str; - TreeModel::Row row; - Gdk::Color c; - bool missing_source = boost::dynamic_pointer_cast(region->source()); - - if (!show_automatic_regions_in_region_list && region->automatic()) { - return; - } - - if (region->hidden()) { - TreeModel::iterator iter = region_list_model->get_iter ("0"); - TreeModel::Row parent; - TreeModel::Row child; - - if (!iter) { - parent = *(region_list_model->append()); - parent[region_list_columns.name] = _("Hidden"); - boost::shared_ptr proxy = parent[region_list_columns.region]; - proxy.reset (); - } else { - if ((*iter)[region_list_columns.name] != _("Hidden")) { - parent = *(region_list_model->insert(iter)); - parent[region_list_columns.name] = _("Hidden"); - boost::shared_ptr proxy = parent[region_list_columns.region]; - proxy.reset (); - } else { - parent = *iter; - } - } - - row = *(region_list_model->append (parent.children())); - - } else if (region->whole_file()) { - - TreeModel::iterator i; - TreeModel::Children rows = region_list_model->children(); - - for (i = rows.begin(); i != rows.end(); ++i) { - boost::shared_ptr rr = (*i)[region_list_columns.region]; - - if (rr && region->region_list_equivalent (rr)) { - return; - } - } - - row = *(region_list_model->append()); - - if (missing_source) { - c.set_rgb(65535,0,0); // FIXME: error color from style - - } else if (region->automatic()){ - c.set_rgb(0,65535,0); // FIXME: error color from style - - } else { - set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false )); - - } - - row[region_list_columns.color_] = c; - - if (region->source()->name()[0] == '/') { // external file - - if (region->whole_file()) { - - boost::shared_ptr afs = boost::dynamic_pointer_cast(region->source()); - str = ".../"; - - if (afs) { - str = region_name_from_path (afs->path(), region->n_channels() > 1); - } else { - str += region->source()->name(); - } - - } else { - str = region->name(); - } - - } else { - str = region->name(); - } - - if (region->n_channels() > 1) { - std::stringstream foo; - foo << region->n_channels (); - str += " ["; - str += foo.str(); - str += "]"; - } - - row[region_list_columns.name] = str; - row[region_list_columns.region] = region; - - if (missing_source) { - row[region_list_columns.path] = _("(MISSING) ") + region->source()->name(); - - } else { - row[region_list_columns.path] = region->source()->name(); - - } - - if (region->automatic()) { - return; - } - - } else { - - /* find parent node, add as new child */ - - TreeModel::iterator i; - TreeModel::Children rows = region_list_model->children(); - bool found_parent = false; - - for (i = rows.begin(); i != rows.end(); ++i) { - boost::shared_ptr rr = (*i)[region_list_columns.region]; - boost::shared_ptr r = boost::dynamic_pointer_cast(rr); - - if (r && r->whole_file()) { - - if (region->source_equivalent (r)) { - row = *(region_list_model->append ((*i).children())); - found_parent = true; - break; - } - } - - TreeModel::iterator ii; - TreeModel::Children subrows = (*i).children(); - - for (ii = subrows.begin(); ii != subrows.end(); ++ii) { - boost::shared_ptr rrr = (*ii)[region_list_columns.region]; - - if (region->region_list_equivalent (rrr)) { - return; - - } - } - } - - if (!found_parent) { - row = *(region_list_model->append()); - } - } - - row[region_list_columns.region] = region; - - populate_row(region, (*row)); -} - - -void -Editor::region_list_region_changed (Change what_changed, boost::weak_ptr region) -{ - ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::region_list_region_changed), what_changed, region)); - - boost::shared_ptr r = region.lock (); - - if (!r) { - return; - } - - if (what_changed & ARDOUR::NameChanged) { - /* find the region in our model and change its name */ - TreeModel::Children rows = region_list_model->children (); - TreeModel::iterator i = rows.begin (); - while (i != rows.end ()) { - TreeModel::Children children = (*i)->children (); - TreeModel::iterator j = children.begin (); - while (j != children.end()) { - boost::shared_ptr c = (*j)[region_list_columns.region]; - if (c == r) { - break; - } - ++j; - } - - if (j != children.end()) { - (*j)[region_list_columns.name] = r->name (); - break; - } - - ++i; - } - - } -} - -void -Editor::region_list_selection_changed() -{ - if (region_list_display.get_selection()->count_selected_rows() > 0) { - - TreeIter iter; - TreeView::Selection::ListHandle_Path rows = region_list_display.get_selection()->get_selected_rows (); - - deselect_all(); - - for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { - - if (iter = region_list_model->get_iter (*i)) { // they could have clicked on a row that is just a placeholder, like "Hidden" - boost::shared_ptr region = (*iter)[region_list_columns.region]; - - if (region) { - - if (region->automatic()) { - region_list_display.get_selection()->unselect(*i); - - } else { - region_list_change_connection.block(true); - //editor_regions_selection_changed_connection.block(true); - - set_selected_regionview_from_region_list (region, Selection::Add); - - region_list_change_connection.block(false); - //editor_regions_selection_changed_connection.block(false); - } - } - } - } - } else { - deselect_all(); - } -} - -void -Editor::set_selected_in_region_list(RegionSelection& regions) -{ - for (RegionSelection::iterator iter = regions.begin(); iter != regions.end(); ++iter) { - - TreeModel::iterator i; - TreeModel::Children rows = region_list_model->children(); - boost::shared_ptr r ((*iter)->region()); - - for (i = rows.begin(); i != rows.end(); ++i) { - - boost::shared_ptr compared_region = (*i)[region_list_columns.region]; - - if (r == compared_region) { - region_list_display.get_selection()->select(*i); - break; - } - - if (!(*i).children().empty()) { - if (set_selected_in_region_list_subrow(r, (*i), 2)) { - break; - } - } - } - } -} - -bool -Editor::set_selected_in_region_list_subrow (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) -{ - TreeModel::iterator i; - TreeModel::Children subrows = (*parent_row).children(); - - for (i = subrows.begin(); i != subrows.end(); ++i) { - - boost::shared_ptr compared_region = (*i)[region_list_columns.region]; - - if (region == compared_region) { - region_list_display.get_selection()->select(*i); - return true; - } - - if (!(*i).children().empty()) { - if (set_selected_in_region_list_subrow(region, (*i), level + 1)) { - return true; - } - } - } - return false; -} - -void -Editor::insert_into_tmp_regionlist(boost::shared_ptr region) -{ - /* keep all whole files at the beginning */ - - if (region->whole_file()) { - tmp_region_list.push_front (region); - } else { - tmp_region_list.push_back (region); - } -} - -void -Editor::redisplay_regions () -{ - if (no_region_list_redisplay || !session) { - return; - } - - bool tree_expanded = false; - - if (toggle_full_region_list_action && toggle_full_region_list_action->get_active()) { //If the list was expanded prior to rebuilding, - tree_expanded = true; //expand it again afterwards - } - - region_list_display.set_model (Glib::RefPtr(0)); - region_list_model->clear (); - - /* now add everything we have, via a temporary list used to help with - sorting. - */ - - tmp_region_list.clear(); - session->foreach_region (this, &Editor::insert_into_tmp_regionlist); - - for (list >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { - add_region_to_region_display (*r); - } - tmp_region_list.clear(); - - region_list_display.set_model (region_list_model); - - if (tree_expanded) { - region_list_display.expand_all(); - } -} - -void -Editor::update_region_row (boost::shared_ptr region) -{ - if (!region || !session) { - return; - } - - TreeModel::iterator i; - TreeModel::Children rows = region_list_model->children(); - - for (i = rows.begin(); i != rows.end(); ++i) { - -// cerr << "Level 1: Compare " << region->name() << " with parent " << (*i)[region_list_columns.name] << "\n"; - - boost::shared_ptr compared_region = (*i)[region_list_columns.region]; - - if (region == compared_region) { -// cerr << "Matched\n"; - populate_row(region, (*i)); - return; - } - - if (!(*i).children().empty()) { - if (update_region_subrows(region, (*i), 2)) { - return; - } - } - } -// cerr << "Returning - No match\n"; -} - -bool -Editor::update_region_subrows (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) -{ - TreeModel::iterator i; - TreeModel::Children subrows = (*parent_row).children(); - - for (i = subrows.begin(); i != subrows.end(); ++i) { - -// cerr << "Level " << level << ": Compare " << region->name() << " with child " << (*i)[region_list_columns.name] << "\n"; - - boost::shared_ptr compared_region = (*i)[region_list_columns.region]; - - if (region == compared_region) { - populate_row(region, (*i)); -// cerr << "Matched\n"; - return true; - } - - if (!(*i).children().empty()) { - if (update_region_subrows(region, (*i), level + 1)) { - return true; - } - } - } - return false; -} - -void -Editor::update_all_region_rows () -{ - if (!session) { - return; - } - - TreeModel::iterator i; - TreeModel::Children rows = region_list_model->children(); - - for (i = rows.begin(); i != rows.end(); ++i) { - - boost::shared_ptr region = (*i)[region_list_columns.region]; - - if (!region->automatic()) { - cerr << "level 1 : Updating " << region->name() << "\n"; - populate_row(region, (*i)); - } - - if (!(*i).children().empty()) { - update_all_region_subrows((*i), 2); - } - } -} - -void -Editor::update_all_region_subrows (TreeModel::Row const &parent_row, int level) -{ - TreeModel::iterator i; - TreeModel::Children subrows = (*parent_row).children(); - - for (i = subrows.begin(); i != subrows.end(); ++i) { - - boost::shared_ptr region = (*i)[region_list_columns.region]; - - if (!region->automatic()) { - cerr << "level " << level << " : Updating " << region->name() << "\n"; - populate_row(region, (*i)); - } - - if (!(*i).children().empty()) { - update_all_region_subrows((*i), level + 1); - } - } -} - -void -Editor::populate_row (boost::shared_ptr region, TreeModel::Row const &row) -{ - char start_str[16]; - char end_str[16]; - char length_str[16]; - char sync_str[16]; - char fadein_str[16]; - char fadeout_str[16]; - char used_str[8]; - int used; - BBT_Time bbt; // FIXME Why do these have to be declared here ? - SMPTE::Time smpte; // FIXME I would like them declared in the case statment where they are used. - - bool missing_source = boost::dynamic_pointer_cast(region->source()); - - boost::shared_ptr audioRegion = boost::dynamic_pointer_cast(region); - - bool fades_in_seconds = false; - - start_str[0] = '\0'; - end_str[0] = '\0'; - length_str[0] = '\0'; - sync_str[0] = '\0'; - fadein_str[0] = '\0'; - fadeout_str[0] = '\0'; - used_str[0] = '\0'; - - used = get_regionview_count_from_region_list(region); - sprintf (used_str, "%4d" , used); - - switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { - case AudioClock::SMPTE: - case AudioClock::Off: /* If the secondary clock is off, default to SMPTE */ - session->smpte_time (region->position(), smpte); - sprintf (start_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); - session->smpte_time (region->position() + region->length() - 1, smpte); - sprintf (end_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); - session->smpte_time (region->length(), smpte); - sprintf (length_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); - session->smpte_time (region->sync_position() + region->position(), smpte); - sprintf (sync_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); - - if (audioRegion && !fades_in_seconds) { - session->smpte_time (audioRegion->fade_in()->back()->when, smpte); - sprintf (fadein_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); - session->smpte_time (audioRegion->fade_out()->back()->when, smpte); - sprintf (fadeout_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); - } - - break; - - case AudioClock::BBT: - session->tempo_map().bbt_time (region->position(), bbt); - sprintf (start_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); - session->tempo_map().bbt_time (region->position() + region->length() - 1, bbt); - sprintf (end_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); - session->tempo_map().bbt_time (region->length(), bbt); - sprintf (length_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); - session->tempo_map().bbt_time (region->sync_position() + region->position(), bbt); - sprintf (sync_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); - - if (audioRegion && !fades_in_seconds) { - session->tempo_map().bbt_time (audioRegion->fade_in()->back()->when, bbt); - sprintf (fadein_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); - session->tempo_map().bbt_time (audioRegion->fade_out()->back()->when, bbt); - sprintf (fadeout_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); - } - break; - - case AudioClock::MinSec: - nframes_t left; - int hrs; - int mins; - float secs; - - left = region->position(); - hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - secs = left / (float) session->frame_rate(); - sprintf (start_str, "%02d:%02d:%06.3f", hrs, mins, secs); - - left = region->position() + region->length() - 1; - hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - secs = left / (float) session->frame_rate(); - sprintf (end_str, "%02d:%02d:%06.3f", hrs, mins, secs); - - left = region->length(); - hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - secs = left / (float) session->frame_rate(); - sprintf (length_str, "%02d:%02d:%06.3f", hrs, mins, secs); - - left = region->sync_position() + region->position(); - hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - secs = left / (float) session->frame_rate(); - sprintf (sync_str, "%02d:%02d:%06.3f", hrs, mins, secs); - - if (audioRegion && !fades_in_seconds) { - left = audioRegion->fade_in()->back()->when; - hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - secs = left / (float) session->frame_rate(); - sprintf (fadein_str, "%02d:%02d:%06.3f", hrs, mins, secs); - - left = audioRegion->fade_out()->back()->when; - hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); - left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - secs = left / (float) session->frame_rate(); - sprintf (fadeout_str, "%02d:%02d:%06.3f", hrs, mins, secs); - } - - break; - - case AudioClock::Frames: - snprintf (start_str, sizeof (start_str), "%u", region->position()); - snprintf (end_str, sizeof (end_str), "%u", (region->position() + region->length() - 1)); - snprintf (length_str, sizeof (length_str), "%u", region->length()); - snprintf (sync_str, sizeof (sync_str), "%u", region->sync_position() + region->position()); - - if (audioRegion && !fades_in_seconds) { - snprintf (fadein_str, sizeof (fadein_str), "%u", uint (audioRegion->fade_in()->back()->when)); - snprintf (fadeout_str, sizeof (fadeout_str), "%u", uint (audioRegion->fade_out()->back()->when)); - } - - break; - - default: - break; - } - - if (audioRegion && fades_in_seconds) { - - nframes_t left; - int mins; - int millisecs; - - left = audioRegion->fade_in()->back()->when; - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - millisecs = (int) floor ((left * 1000.0f) / session->frame_rate()); - - if (audioRegion->fade_in()->back()->when >= session->frame_rate()) { - sprintf (fadein_str, "%01dM %01dmS", mins, millisecs); - } else { - sprintf (fadein_str, "%01dmS", millisecs); - } - - left = audioRegion->fade_out()->back()->when; - mins = (int) floor (left / (session->frame_rate() * 60.0f)); - left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); - millisecs = (int) floor ((left * 1000.0f) / session->frame_rate()); - - if (audioRegion->fade_out()->back()->when >= session->frame_rate()) { - sprintf (fadeout_str, "%01dM %01dmS", mins, millisecs); - } else { - sprintf (fadeout_str, "%01dmS", millisecs); - } - } - - if (used > 1) { - row[region_list_columns.start] = _("Multiple"); - row[region_list_columns.end] = _("Multiple"); - row[region_list_columns.sync] = _("Multiple"); - row[region_list_columns.fadein] = _("Multiple"); - row[region_list_columns.fadeout] = _("Multiple"); - row[region_list_columns.locked] = false; - row[region_list_columns.glued] = false; - row[region_list_columns.muted] = false; - row[region_list_columns.opaque] = false; - } else { - row[region_list_columns.start] = start_str; - row[region_list_columns.end] = end_str; - - if (region->sync_position() == 0) { - row[region_list_columns.sync] = _("Start"); - } else if (region->sync_position() == region->length() - 1) { - row[region_list_columns.sync] = _("End"); - } else { - row[region_list_columns.sync] = sync_str; - } - - if (audioRegion) { - if (audioRegion->fade_in_active()) { - row[region_list_columns.fadein] = string_compose("%1%2%3", " ", fadein_str, " "); - } else { - row[region_list_columns.fadein] = string_compose("%1%2%3", "(", fadein_str, ")"); - } - } else { - row[region_list_columns.fadein] = ""; - } - - if (audioRegion) { - if (audioRegion->fade_out_active()) { - row[region_list_columns.fadeout] = string_compose("%1%2%3", " ", fadeout_str, " "); - } else { - row[region_list_columns.fadeout] = string_compose("%1%2%3", "(", fadeout_str, ")"); - } - } else { - row[region_list_columns.fadeout] = ""; - } - - row[region_list_columns.locked] = region->locked(); - - if (region->positional_lock_style() == Region::MusicTime) { - row[region_list_columns.glued] = true; - } else { - row[region_list_columns.glued] = false; - } - - row[region_list_columns.muted] = region->muted(); - row[region_list_columns.opaque] = region->opaque(); - } - - row[region_list_columns.length] = length_str; - row[region_list_columns.used] = used_str; - - if (missing_source) { - row[region_list_columns.path] = _("MISSING ") + region->source()->name(); - } else { - row[region_list_columns.path] = region->source()->name(); - } - - if (region->n_channels() > 1) { - row[region_list_columns.name] = string_compose("%1 [%2]", region->name(), region->n_channels()); - } else { - row[region_list_columns.name] = region->name(); - } -} - -void -Editor::build_region_list_menu () -{ - region_list_menu = dynamic_cast(ActionManager::get_widget ("/RegionListMenu")); - - /* now grab specific menu items that we need */ - - Glib::RefPtr act; - - act = ActionManager::get_action (X_("RegionList"), X_("rlShowAll")); - if (act) { - toggle_full_region_list_action = Glib::RefPtr::cast_dynamic (act); - } - - act = ActionManager::get_action (X_("RegionList"), X_("rlShowAuto")); - if (act) { - toggle_show_auto_regions_action = Glib::RefPtr::cast_dynamic (act); - } -} - -void -Editor::toggle_show_auto_regions () -{ - show_automatic_regions_in_region_list = toggle_show_auto_regions_action->get_active(); - redisplay_regions (); -} - -void -Editor::toggle_full_region_list () -{ - if (toggle_full_region_list_action->get_active()) { - region_list_display.expand_all (); - } else { - region_list_display.collapse_all (); - } -} - -void -Editor::show_region_list_display_context_menu (int button, int time) -{ - if (region_list_menu == 0) { - build_region_list_menu (); - } - - if (region_list_display.get_selection()->count_selected_rows() > 0) { - ActionManager::set_sensitive (ActionManager::region_list_selection_sensitive_actions, true); - } else { - ActionManager::set_sensitive (ActionManager::region_list_selection_sensitive_actions, false); - } - - region_list_menu->popup (button, time); -} - -bool -Editor::region_list_display_key_press (GdkEventKey* ev) -{ - return false; -} - -bool -Editor::region_list_display_key_release (GdkEventKey* ev) -{ - switch (ev->keyval) { - case GDK_Delete: - remove_region_from_region_list (); - return true; - break; - default: - break; - } - - return false; -} - -bool -Editor::region_list_display_button_press (GdkEventButton *ev) -{ - boost::shared_ptr region; - TreeIter iter; - TreeModel::Path path; - TreeViewColumn* column; - int cellx; - int celly; - - if (region_list_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { - if ((iter = region_list_model->get_iter (path))) { - region = (*iter)[region_list_columns.region]; - } - } - - if (Keyboard::is_context_menu_event (ev)) { - show_region_list_display_context_menu (ev->button, ev->time); - return true; - } - - if (region != 0 && Keyboard::is_button2_event (ev)) { - // start/stop audition - if (!Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { - consider_auditioning (region); - } - return true; - } - - return false; -} - -bool -Editor::region_list_display_button_release (GdkEventButton *ev) -{ - TreeIter iter; - TreeModel::Path path; - TreeViewColumn* column; - int cellx; - int celly; - boost::shared_ptr region; - - if (region_list_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { - if ((iter = region_list_model->get_iter (path))) { - region = (*iter)[region_list_columns.region]; - } - } - - if (region && Keyboard::is_delete_event (ev)) { - session->remove_region_from_region_list (region); - return true; - } - - return false; -} - -void -Editor::consider_auditioning (boost::shared_ptr region) -{ - boost::shared_ptr r = boost::dynamic_pointer_cast (region); - - if (r == 0) { - session->cancel_audition (); - return; - } - - if (session->is_auditioning()) { - session->cancel_audition (); - if (r == last_audition_region) { - return; - } - } - - session->audition_region (r); - last_audition_region = r; -} - -int -Editor::region_list_sorter (TreeModel::iterator a, TreeModel::iterator b) -{ - int cmp = 0; - - boost::shared_ptr r1 = (*a)[region_list_columns.region]; - boost::shared_ptr r2 = (*b)[region_list_columns.region]; - - /* handle rows without regions, like "Hidden" */ - - if (r1 == 0) { - return -1; - } - - if (r2 == 0) { - return 1; - } - - boost::shared_ptr region1 = boost::dynamic_pointer_cast (r1); - boost::shared_ptr region2 = boost::dynamic_pointer_cast (r2); - - if (region1 == 0 || region2 == 0) { - Glib::ustring s1; - Glib::ustring s2; - switch (region_list_sort_type) { - case ByName: - s1 = (*a)[region_list_columns.name]; - s2 = (*b)[region_list_columns.name]; - return (s1.compare (s2)); - default: - return 0; - } - } - - switch (region_list_sort_type) { - case ByName: - cmp = strcasecmp (region1->name().c_str(), region2->name().c_str()); - break; - - case ByLength: - cmp = region1->length() - region2->length(); - break; - - case ByPosition: - cmp = region1->position() - region2->position(); - break; - - case ByTimestamp: - cmp = region1->source()->timestamp() - region2->source()->timestamp(); - break; - - case ByStartInFile: - cmp = region1->start() - region2->start(); - break; - - case ByEndInFile: - cmp = (region1->start() + region1->length()) - (region2->start() + region2->length()); - break; - - case BySourceFileName: - cmp = strcasecmp (region1->source()->name().c_str(), region2->source()->name().c_str()); - break; - - case BySourceFileLength: - cmp = region1->source_length(0) - region2->source_length(0); - break; - - case BySourceFileCreationDate: - cmp = region1->source()->timestamp() - region2->source()->timestamp(); - break; - - case BySourceFileFS: - if (region1->source()->name() == region2->source()->name()) { - cmp = strcasecmp (region1->name().c_str(), region2->name().c_str()); - } else { - cmp = strcasecmp (region1->source()->name().c_str(), region2->source()->name().c_str()); - } - break; - } - - if (cmp < 0) { - return -1; - } else if (cmp > 0) { - return 1; - } else { - return 0; - } -} - -void -Editor::reset_region_list_sort_type (RegionListSortType type) -{ - if (type != region_list_sort_type) { - region_list_sort_type = type; - region_list_model->set_sort_func (0, (mem_fun (*this, &Editor::region_list_sorter))); - } -} - -void -Editor::reset_region_list_sort_direction (bool up) -{ - region_list_model->set_sort_column (0, up ? SORT_ASCENDING : SORT_DESCENDING); -} - -void -Editor::region_list_selection_mapover (slot > sl) -{ - Glib::RefPtr selection = region_list_display.get_selection(); - TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows (); - TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); - - if (selection->count_selected_rows() == 0 || session == 0) { - return; - } - - for (; i != rows.end(); ++i) { - TreeIter iter; - - if ((iter = region_list_model->get_iter (*i))) { - - /* some rows don't have a region associated with them, but can still be - selected (XXX maybe prevent them from being selected) - */ - - boost::shared_ptr r = (*iter)[region_list_columns.region]; - - if (r) { - sl (r); - } - } - } -} - -void -Editor::hide_a_region (boost::shared_ptr r) -{ - r->set_hidden (true); -} - -void -Editor::remove_a_region (boost::shared_ptr r) -{ - session->remove_region_from_region_list (r); -} - -void -Editor::audition_region_from_region_list () -{ - region_list_selection_mapover (mem_fun (*this, &Editor::consider_auditioning)); -} - -void -Editor::hide_region_from_region_list () -{ - region_list_selection_mapover (mem_fun (*this, &Editor::hide_a_region)); -} - -void -Editor::remove_region_from_region_list () -{ - region_list_selection_mapover (mem_fun (*this, &Editor::remove_a_region)); -} - -void -Editor::region_list_display_drag_data_received (const RefPtr& context, - int x, int y, - const SelectionData& data, - guint info, guint time) -{ - vector paths; - - if (data.get_target() == "GTK_TREE_MODEL_ROW") { - region_list_display.on_drag_data_received (context, x, y, data, info, time); - return; - } - - if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) { - nframes64_t pos = 0; - if (Profile->get_sae() || Config->get_only_copy_imported_files()) { - do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsRegion, SrcBest, pos); - } else { - do_embed (paths, Editing::ImportDistinctFiles, ImportAsRegion, pos); - } - context->drag_finish (true, false, time); - } -} - -bool -Editor::region_list_selection_filter (const RefPtr& model, const TreeModel::Path& path, bool yn) -{ - /* not possible to select rows that do not represent regions, like "Hidden" */ - - TreeModel::iterator iter = model->get_iter (path); - - if (iter) { - boost::shared_ptr r =(*iter)[region_list_columns.region]; - if (!r) { - return false; - } - } - - return true; -} - -void -Editor::region_name_edit (const Glib::ustring& path, const Glib::ustring& new_text) -{ - boost::shared_ptr region; - TreeIter iter; - - if ((iter = region_list_model->get_iter (path))) { - region = (*iter)[region_list_columns.region]; - (*iter)[region_list_columns.name] = new_text; - } - - /* now mapover everything */ - - if (region) { - vector equivalents; - get_regions_corresponding_to (region, equivalents); - - for (vector::iterator i = equivalents.begin(); i != equivalents.end(); ++i) { - if (new_text != (*i)->region()->name()) { - (*i)->region()->set_name (new_text); - } - } - } - -} - diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc new file mode 100644 index 0000000000..dadeca4b1d --- /dev/null +++ b/gtk2_ardour/editor_regions.cc @@ -0,0 +1,1228 @@ +/* + Copyright (C) 2000-2005 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include +#include +#include + +#include "pbd/basename.h" + +#include "ardour/audioregion.h" +#include "ardour/audiofilesource.h" +#include "ardour/silentfilesource.h" +#include "ardour/session_region.h" +#include "ardour/profile.h" + +#include + +#include "editor.h" +#include "editing.h" +#include "keyboard.h" +#include "ardour_ui.h" +#include "gui_thread.h" +#include "actions.h" +#include "region_view.h" +#include "utils.h" +#include "editor_regions.h" + +#include "i18n.h" + +using namespace std; +using namespace sigc; +using namespace ARDOUR; +using namespace PBD; +using namespace Gtk; +using namespace Glib; +using namespace Editing; + +EditorRegions::EditorRegions (Editor* e) + : EditorComponent (e), + _menu (0), + _show_automatic_regions (true), + _sort_type ((Editing::RegionListSortType) 0), + _no_redisplay (false) +{ + _display.set_size_request (100, -1); + _display.set_name ("RegionListDisplay"); + /* Try to prevent single mouse presses from initiating edits. + This relies on a hack in gtktreeview.c:gtk_treeview_button_press() + */ + _display.set_data ("mouse-edits-require-mod1", (gpointer) 0x1); + + _model = TreeStore::create (_columns); + _model->set_sort_func (0, mem_fun (*this, &EditorRegions::sorter)); + _model->set_sort_column (0, SORT_ASCENDING); + + _display.set_model (_model); + _display.append_column (_("Regions"), _columns.name); + _display.append_column (_("Start"), _columns.start); + _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.set_headers_visible (true); + //_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH); + + CellRendererText* region_name_cell = dynamic_cast(_display.get_column_cell_renderer (0)); + region_name_cell->property_editable() = true; + region_name_cell->signal_edited().connect (mem_fun (*this, &EditorRegions::name_edit)); + + _display.get_selection()->set_select_function (mem_fun (*this, &EditorRegions::selection_filter)); + + TreeViewColumn* tv_col = _display.get_column(0); + 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_); + + _display.get_selection()->set_mode (SELECTION_MULTIPLE); + _display.add_object_drag (_columns.region.index(), "regions"); + + /* setup DnD handling */ + + list region_list_target_table; + + region_list_target_table.push_back (TargetEntry ("text/plain")); + region_list_target_table.push_back (TargetEntry ("text/uri-list")); + region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop")); + + _display.add_drop_targets (region_list_target_table); + _display.signal_drag_data_received().connect (mem_fun(*this, &EditorRegions::drag_data_received)); + + _scroller.add (_display); + _scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC); + + _display.signal_key_press_event().connect (mem_fun(*this, &EditorRegions::key_press)); + _display.signal_key_release_event().connect (mem_fun(*this, &EditorRegions::key_release)); + _display.signal_button_press_event().connect (mem_fun(*this, &EditorRegions::button_press), false); + _display.signal_button_release_event().connect (mem_fun(*this, &EditorRegions::button_release)); + _change_connection = _display.get_selection()->signal_changed().connect (mem_fun(*this, &EditorRegions::selection_changed)); + // _display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show__display_context_menu), 1, 0)); + + //ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::redisplay_regions)); + ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &EditorRegions::update_all_rows)); + ARDOUR::Region::RegionPropertyChanged.connect (mem_fun(*this, &EditorRegions::update_row)); + +} + +void +EditorRegions::connect_to_session (ARDOUR::Session* s) +{ + EditorComponent::connect_to_session (s); + + _session_connections.push_back (_session->RegionsAdded.connect (mem_fun(*this, &EditorRegions::handle_new_regions))); + _session_connections.push_back (_session->RegionRemoved.connect (mem_fun(*this, &EditorRegions::handle_region_removed))); + _session_connections.push_back (_session->RegionHiddenChange.connect (mem_fun(*this, &EditorRegions::region_hidden))); + + redisplay (); +} + +void +EditorRegions::handle_region_removed (boost::weak_ptr wregion) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRegions::handle_region_removed), wregion)); + + redisplay (); +} + +void +EditorRegions::handle_new_regions (vector >& v) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRegions::handle_new_regions), v)); + add_regions (v); +} + +void +EditorRegions::region_hidden (boost::shared_ptr r) +{ + ENSURE_GUI_THREAD(bind (mem_fun(*this, &EditorRegions::region_hidden), r)); + redisplay (); +} + +void +EditorRegions::add_regions (vector >& regions) +{ + for (vector >::iterator x = regions.begin(); x != regions.end(); ++x) { + boost::shared_ptr region ((*x).lock()); + if (region) { + add_region (region); + } + } +} + +void +EditorRegions::add_region (boost::shared_ptr region) +{ + if (!region || !_session) { + return; + } + + string str; + TreeModel::Row row; + Gdk::Color c; + bool missing_source = boost::dynamic_pointer_cast(region->source()); + + if (!_show_automatic_regions && region->automatic()) { + return; + } + + if (region->hidden()) { + TreeModel::iterator iter = _model->get_iter ("0"); + TreeModel::Row parent; + TreeModel::Row child; + + if (!iter) { + parent = *(_model->append()); + parent[_columns.name] = _("Hidden"); + boost::shared_ptr proxy = parent[_columns.region]; + proxy.reset (); + } else { + if ((*iter)[_columns.name] != _("Hidden")) { + parent = *(_model->insert(iter)); + parent[_columns.name] = _("Hidden"); + boost::shared_ptr proxy = parent[_columns.region]; + proxy.reset (); + } else { + parent = *iter; + } + } + + row = *(_model->append (parent.children())); + + } else if (region->whole_file()) { + + TreeModel::iterator i; + TreeModel::Children rows = _model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + boost::shared_ptr rr = (*i)[_columns.region]; + + if (rr && region->region_list_equivalent (rr)) { + return; + } + } + + row = *(_model->append()); + + if (missing_source) { + c.set_rgb(65535,0,0); // FIXME: error color from style + + } else if (region->automatic()){ + c.set_rgb(0,65535,0); // FIXME: error color from style + + } else { + set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false )); + + } + + row[_columns.color_] = c; + + if (region->source()->name()[0] == '/') { // external file + + if (region->whole_file()) { + + boost::shared_ptr afs = boost::dynamic_pointer_cast(region->source()); + str = ".../"; + + if (afs) { + str = region_name_from_path (afs->path(), region->n_channels() > 1); + } else { + str += region->source()->name(); + } + + } else { + str = region->name(); + } + + } else { + str = region->name(); + } + + if (region->n_channels() > 1) { + std::stringstream foo; + foo << region->n_channels (); + str += " ["; + str += foo.str(); + str += "]"; + } + + row[_columns.name] = str; + row[_columns.region] = region; + + if (missing_source) { + row[_columns.path] = _("(MISSING) ") + region->source()->name(); + + } else { + row[_columns.path] = region->source()->name(); + + } + + if (region->automatic()) { + return; + } + + } else { + + /* find parent node, add as new child */ + + TreeModel::iterator i; + TreeModel::Children rows = _model->children(); + bool found_parent = false; + + for (i = rows.begin(); i != rows.end(); ++i) { + boost::shared_ptr rr = (*i)[_columns.region]; + boost::shared_ptr r = boost::dynamic_pointer_cast(rr); + + if (r && r->whole_file()) { + + if (region->source_equivalent (r)) { + row = *(_model->append ((*i).children())); + found_parent = true; + break; + } + } + + TreeModel::iterator ii; + TreeModel::Children subrows = (*i).children(); + + for (ii = subrows.begin(); ii != subrows.end(); ++ii) { + boost::shared_ptr rrr = (*ii)[_columns.region]; + + if (region->region_list_equivalent (rrr)) { + return; + + } + } + } + + if (!found_parent) { + row = *(_model->append()); + } + } + + row[_columns.region] = region; + + populate_row(region, (*row)); +} + + +void +EditorRegions::region_changed (Change what_changed, boost::weak_ptr region) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRegions::region_changed), what_changed, region)); + + boost::shared_ptr r = region.lock (); + + if (!r) { + return; + } + + if (what_changed & ARDOUR::NameChanged) { + /* find the region in our model and change its name */ + TreeModel::Children rows = _model->children (); + TreeModel::iterator i = rows.begin (); + while (i != rows.end ()) { + TreeModel::Children children = (*i)->children (); + TreeModel::iterator j = children.begin (); + while (j != children.end()) { + boost::shared_ptr c = (*j)[_columns.region]; + if (c == r) { + break; + } + ++j; + } + + if (j != children.end()) { + (*j)[_columns.name] = r->name (); + break; + } + + ++i; + } + + } +} + +void +EditorRegions::selection_changed () +{ + if (_display.get_selection()->count_selected_rows() > 0) { + + TreeIter iter; + TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows (); + + _editor->deselect_all (); + + for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { + + if (iter = _model->get_iter (*i)) { // they could have clicked on a row that is just a placeholder, like "Hidden" + boost::shared_ptr region = (*iter)[_columns.region]; + + if (region) { + + if (region->automatic()) { + _display.get_selection()->unselect(*i); + + } else { + _change_connection.block (true); + //editor_regions_selection_changed_connection.block(true); + + _editor->set_selected_regionview_from_region_list (region, Selection::Add); + + _change_connection.block (false); + //editor_regions_selection_changed_connection.block(false); + } + } + } + } + } else { + _editor->deselect_all (); + } +} + +void +EditorRegions::set_selected (RegionSelection& regions) +{ + for (RegionSelection::iterator iter = regions.begin(); iter != regions.end(); ++iter) { + + TreeModel::iterator i; + TreeModel::Children rows = _model->children(); + boost::shared_ptr r ((*iter)->region()); + + for (i = rows.begin(); i != rows.end(); ++i) { + + boost::shared_ptr compared_region = (*i)[_columns.region]; + + if (r == compared_region) { + _display.get_selection()->select(*i); + break; + } + + if (!(*i).children().empty()) { + if (set_selected_in_subrow(r, (*i), 2)) { + break; + } + } + } + } +} + +bool +EditorRegions::set_selected_in_subrow (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) +{ + TreeModel::iterator i; + TreeModel::Children subrows = (*parent_row).children(); + + for (i = subrows.begin(); i != subrows.end(); ++i) { + + boost::shared_ptr compared_region = (*i)[_columns.region]; + + if (region == compared_region) { + _display.get_selection()->select(*i); + return true; + } + + if (!(*i).children().empty()) { + if (set_selected_in_subrow (region, (*i), level + 1)) { + return true; + } + } + } + return false; +} + +void +EditorRegions::insert_into_tmp_regionlist(boost::shared_ptr region) +{ + /* keep all whole files at the beginning */ + + if (region->whole_file()) { + tmp_region_list.push_front (region); + } else { + tmp_region_list.push_back (region); + } +} + +void +EditorRegions::redisplay () +{ + if (_no_redisplay || !_session) { + return; + } + + bool tree_expanded = false; + + if (_toggle_full_action && _toggle_full_action->get_active()) { //If the list was expanded prior to rebuilding, + tree_expanded = true; //expand it again afterwards + } + + _display.set_model (Glib::RefPtr(0)); + _model->clear (); + + /* now add everything we have, via a temporary list used to help with + sorting. + */ + + tmp_region_list.clear(); + _session->foreach_region (this, &EditorRegions::insert_into_tmp_regionlist); + + for (list >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { + add_region (*r); + } + tmp_region_list.clear(); + + _display.set_model (_model); + + if (tree_expanded) { + _display.expand_all(); + } +} + +void +EditorRegions::update_row (boost::shared_ptr region) +{ + if (!region || !_session) { + return; + } + + TreeModel::iterator i; + TreeModel::Children rows = _model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + +// cerr << "Level 1: Compare " << region->name() << " with parent " << (*i)[_columns.name] << "\n"; + + boost::shared_ptr compared_region = (*i)[_columns.region]; + + if (region == compared_region) { +// cerr << "Matched\n"; + populate_row(region, (*i)); + return; + } + + if (!(*i).children().empty()) { + if (update_subrows(region, (*i), 2)) { + return; + } + } + } +// cerr << "Returning - No match\n"; +} + +bool +EditorRegions::update_subrows (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) +{ + TreeModel::iterator i; + TreeModel::Children subrows = (*parent_row).children(); + + for (i = subrows.begin(); i != subrows.end(); ++i) { + +// cerr << "Level " << level << ": Compare " << region->name() << " with child " << (*i)[_columns.name] << "\n"; + + boost::shared_ptr compared_region = (*i)[_columns.region]; + + if (region == compared_region) { + populate_row(region, (*i)); +// cerr << "Matched\n"; + return true; + } + + if (!(*i).children().empty()) { + if (update_subrows (region, (*i), level + 1)) { + return true; + } + } + } + return false; +} + +void +EditorRegions::update_all_rows () +{ + if (!_session) { + return; + } + + TreeModel::iterator i; + TreeModel::Children rows = _model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + + boost::shared_ptr region = (*i)[_columns.region]; + + if (!region->automatic()) { + cerr << "level 1 : Updating " << region->name() << "\n"; + populate_row(region, (*i)); + } + + if (!(*i).children().empty()) { + update_all_subrows ((*i), 2); + } + } +} + +void +EditorRegions::update_all_subrows (TreeModel::Row const &parent_row, int level) +{ + TreeModel::iterator i; + TreeModel::Children subrows = (*parent_row).children(); + + for (i = subrows.begin(); i != subrows.end(); ++i) { + + boost::shared_ptr region = (*i)[_columns.region]; + + if (!region->automatic()) { + cerr << "level " << level << " : Updating " << region->name() << "\n"; + populate_row(region, (*i)); + } + + if (!(*i).children().empty()) { + update_all_subrows ((*i), level + 1); + } + } +} + +void +EditorRegions::populate_row (boost::shared_ptr region, TreeModel::Row const &row) +{ + char start_str[16]; + char end_str[16]; + char length_str[16]; + char sync_str[16]; + char fadein_str[16]; + char fadeout_str[16]; + char used_str[8]; + int used; + BBT_Time bbt; // FIXME Why do these have to be declared here ? + SMPTE::Time smpte; // FIXME I would like them declared in the case statment where they are used. + + bool missing_source = boost::dynamic_pointer_cast(region->source()); + + boost::shared_ptr audioRegion = boost::dynamic_pointer_cast(region); + + bool fades_in_seconds = false; + + start_str[0] = '\0'; + end_str[0] = '\0'; + length_str[0] = '\0'; + sync_str[0] = '\0'; + fadein_str[0] = '\0'; + fadeout_str[0] = '\0'; + used_str[0] = '\0'; + + used = _editor->get_regionview_count_from_region_list (region); + sprintf (used_str, "%4d" , used); + + switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { + case AudioClock::SMPTE: + case AudioClock::Off: /* If the secondary clock is off, default to SMPTE */ + _session->smpte_time (region->position(), smpte); + sprintf (start_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + _session->smpte_time (region->position() + region->length() - 1, smpte); + sprintf (end_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + _session->smpte_time (region->length(), smpte); + sprintf (length_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + _session->smpte_time (region->sync_position() + region->position(), smpte); + sprintf (sync_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + + if (audioRegion && !fades_in_seconds) { + _session->smpte_time (audioRegion->fade_in()->back()->when, smpte); + sprintf (fadein_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + _session->smpte_time (audioRegion->fade_out()->back()->when, smpte); + sprintf (fadeout_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } + + break; + + case AudioClock::BBT: + _session->tempo_map().bbt_time (region->position(), bbt); + sprintf (start_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + _session->tempo_map().bbt_time (region->position() + region->length() - 1, bbt); + sprintf (end_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + _session->tempo_map().bbt_time (region->length(), bbt); + sprintf (length_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + _session->tempo_map().bbt_time (region->sync_position() + region->position(), bbt); + sprintf (sync_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + + if (audioRegion && !fades_in_seconds) { + _session->tempo_map().bbt_time (audioRegion->fade_in()->back()->when, bbt); + sprintf (fadein_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + _session->tempo_map().bbt_time (audioRegion->fade_out()->back()->when, bbt); + sprintf (fadeout_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + } + break; + + case AudioClock::MinSec: + nframes_t left; + int hrs; + int mins; + float secs; + + left = region->position(); + hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + secs = left / (float) _session->frame_rate(); + sprintf (start_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = region->position() + region->length() - 1; + hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + secs = left / (float) _session->frame_rate(); + sprintf (end_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = region->length(); + hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + secs = left / (float) _session->frame_rate(); + sprintf (length_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = region->sync_position() + region->position(); + hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + secs = left / (float) _session->frame_rate(); + sprintf (sync_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + if (audioRegion && !fades_in_seconds) { + left = audioRegion->fade_in()->back()->when; + hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + secs = left / (float) _session->frame_rate(); + sprintf (fadein_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = audioRegion->fade_out()->back()->when; + hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + secs = left / (float) _session->frame_rate(); + sprintf (fadeout_str, "%02d:%02d:%06.3f", hrs, mins, secs); + } + + break; + + case AudioClock::Frames: + snprintf (start_str, sizeof (start_str), "%u", region->position()); + snprintf (end_str, sizeof (end_str), "%u", (region->position() + region->length() - 1)); + snprintf (length_str, sizeof (length_str), "%u", region->length()); + snprintf (sync_str, sizeof (sync_str), "%u", region->sync_position() + region->position()); + + if (audioRegion && !fades_in_seconds) { + snprintf (fadein_str, sizeof (fadein_str), "%u", uint (audioRegion->fade_in()->back()->when)); + snprintf (fadeout_str, sizeof (fadeout_str), "%u", uint (audioRegion->fade_out()->back()->when)); + } + + break; + + default: + break; + } + + if (audioRegion && fades_in_seconds) { + + nframes_t left; + int mins; + int millisecs; + + left = audioRegion->fade_in()->back()->when; + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + millisecs = (int) floor ((left * 1000.0f) / _session->frame_rate()); + + if (audioRegion->fade_in()->back()->when >= _session->frame_rate()) { + sprintf (fadein_str, "%01dM %01dmS", mins, millisecs); + } else { + sprintf (fadein_str, "%01dmS", millisecs); + } + + left = audioRegion->fade_out()->back()->when; + mins = (int) floor (left / (_session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f); + millisecs = (int) floor ((left * 1000.0f) / _session->frame_rate()); + + if (audioRegion->fade_out()->back()->when >= _session->frame_rate()) { + sprintf (fadeout_str, "%01dM %01dmS", mins, millisecs); + } else { + sprintf (fadeout_str, "%01dmS", millisecs); + } + } + + if (used > 1) { + row[_columns.start] = _("Multiple"); + row[_columns.end] = _("Multiple"); + row[_columns.sync] = _("Multiple"); + row[_columns.fadein] = _("Multiple"); + row[_columns.fadeout] = _("Multiple"); + row[_columns.locked] = false; + row[_columns.glued] = false; + row[_columns.muted] = false; + row[_columns.opaque] = false; + } else { + row[_columns.start] = start_str; + row[_columns.end] = end_str; + + if (region->sync_position() == 0) { + row[_columns.sync] = _("Start"); + } else if (region->sync_position() == region->length() - 1) { + row[_columns.sync] = _("End"); + } else { + row[_columns.sync] = sync_str; + } + + if (audioRegion) { + if (audioRegion->fade_in_active()) { + row[_columns.fadein] = string_compose("%1%2%3", " ", fadein_str, " "); + } else { + row[_columns.fadein] = string_compose("%1%2%3", "(", fadein_str, ")"); + } + } else { + row[_columns.fadein] = ""; + } + + if (audioRegion) { + if (audioRegion->fade_out_active()) { + row[_columns.fadeout] = string_compose("%1%2%3", " ", fadeout_str, " "); + } else { + row[_columns.fadeout] = string_compose("%1%2%3", "(", fadeout_str, ")"); + } + } else { + row[_columns.fadeout] = ""; + } + + row[_columns.locked] = region->locked(); + + if (region->positional_lock_style() == Region::MusicTime) { + row[_columns.glued] = true; + } else { + row[_columns.glued] = false; + } + + row[_columns.muted] = region->muted(); + row[_columns.opaque] = region->opaque(); + } + + row[_columns.length] = length_str; + row[_columns.used] = used_str; + + if (missing_source) { + row[_columns.path] = _("MISSING ") + region->source()->name(); + } else { + row[_columns.path] = region->source()->name(); + } + + if (region->n_channels() > 1) { + row[_columns.name] = string_compose("%1 [%2]", region->name(), region->n_channels()); + } else { + row[_columns.name] = region->name(); + } +} + +void +EditorRegions::build_menu () +{ + _menu = dynamic_cast(ActionManager::get_widget ("/RegionListMenu")); + + /* now grab specific menu items that we need */ + + Glib::RefPtr act; + + act = ActionManager::get_action (X_("RegionList"), X_("rlShowAll")); + if (act) { + _toggle_full_action = Glib::RefPtr::cast_dynamic (act); + } + + act = ActionManager::get_action (X_("RegionList"), X_("rlShowAuto")); + if (act) { + _toggle_show_auto_regions_action = Glib::RefPtr::cast_dynamic (act); + } +} + +void +EditorRegions::toggle_show_auto_regions () +{ + _show_automatic_regions = _toggle_show_auto_regions_action->get_active(); + redisplay (); +} + +void +EditorRegions::toggle_full () +{ + if (_toggle_full_action->get_active()) { + _display.expand_all (); + } else { + _display.collapse_all (); + } +} + +void +EditorRegions::show_context_menu (int button, int time) +{ + if (_menu == 0) { + build_menu (); + } + + if (_display.get_selection()->count_selected_rows() > 0) { + ActionManager::set_sensitive (ActionManager::region_list_selection_sensitive_actions, true); + } else { + ActionManager::set_sensitive (ActionManager::region_list_selection_sensitive_actions, false); + } + + _menu->popup (button, time); +} + +bool +EditorRegions::key_press (GdkEventKey* ev) +{ + return false; +} + +bool +EditorRegions::key_release (GdkEventKey* ev) +{ + switch (ev->keyval) { + case GDK_Delete: + remove_region (); + return true; + break; + default: + break; + } + + return false; +} + +bool +EditorRegions::button_press (GdkEventButton *ev) +{ + boost::shared_ptr region; + TreeIter iter; + TreeModel::Path path; + TreeViewColumn* column; + int cellx; + int celly; + + if (_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { + if ((iter = _model->get_iter (path))) { + region = (*iter)[_columns.region]; + } + } + + if (Keyboard::is_context_menu_event (ev)) { + show_context_menu (ev->button, ev->time); + return true; + } + + if (region != 0 && Keyboard::is_button2_event (ev)) { + // start/stop audition + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + _editor->consider_auditioning (region); + } + return true; + } + + return false; +} + +bool +EditorRegions::button_release (GdkEventButton *ev) +{ + TreeIter iter; + TreeModel::Path path; + TreeViewColumn* column; + int cellx; + int celly; + boost::shared_ptr region; + + if (_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { + if ((iter = _model->get_iter (path))) { + region = (*iter)[_columns.region]; + } + } + + if (region && Keyboard::is_delete_event (ev)) { + _session->remove_region_from_region_list (region); + return true; + } + + return false; +} + +int +EditorRegions::sorter (TreeModel::iterator a, TreeModel::iterator b) +{ + int cmp = 0; + + boost::shared_ptr r1 = (*a)[_columns.region]; + boost::shared_ptr r2 = (*b)[_columns.region]; + + /* handle rows without regions, like "Hidden" */ + + if (r1 == 0) { + return -1; + } + + if (r2 == 0) { + return 1; + } + + boost::shared_ptr region1 = boost::dynamic_pointer_cast (r1); + boost::shared_ptr region2 = boost::dynamic_pointer_cast (r2); + + if (region1 == 0 || region2 == 0) { + Glib::ustring s1; + Glib::ustring s2; + switch (_sort_type) { + case ByName: + s1 = (*a)[_columns.name]; + s2 = (*b)[_columns.name]; + return (s1.compare (s2)); + default: + return 0; + } + } + + switch (_sort_type) { + case ByName: + cmp = strcasecmp (region1->name().c_str(), region2->name().c_str()); + break; + + case ByLength: + cmp = region1->length() - region2->length(); + break; + + case ByPosition: + cmp = region1->position() - region2->position(); + break; + + case ByTimestamp: + cmp = region1->source()->timestamp() - region2->source()->timestamp(); + break; + + case ByStartInFile: + cmp = region1->start() - region2->start(); + break; + + case ByEndInFile: + cmp = (region1->start() + region1->length()) - (region2->start() + region2->length()); + break; + + case BySourceFileName: + cmp = strcasecmp (region1->source()->name().c_str(), region2->source()->name().c_str()); + break; + + case BySourceFileLength: + cmp = region1->source_length(0) - region2->source_length(0); + break; + + case BySourceFileCreationDate: + cmp = region1->source()->timestamp() - region2->source()->timestamp(); + break; + + case BySourceFileFS: + if (region1->source()->name() == region2->source()->name()) { + cmp = strcasecmp (region1->name().c_str(), region2->name().c_str()); + } else { + cmp = strcasecmp (region1->source()->name().c_str(), region2->source()->name().c_str()); + } + break; + } + + if (cmp < 0) { + return -1; + } else if (cmp > 0) { + return 1; + } else { + return 0; + } +} + +void +EditorRegions::reset_sort_type (RegionListSortType type, bool force) +{ + if (type != _sort_type || force) { + _sort_type = type; + _model->set_sort_func (0, (mem_fun (*this, &EditorRegions::sorter))); + } +} + +void +EditorRegions::reset_sort_direction (bool up) +{ + _model->set_sort_column (0, up ? SORT_ASCENDING : SORT_DESCENDING); +} + +void +EditorRegions::selection_mapover (slot > sl) +{ + Glib::RefPtr selection = _display.get_selection(); + TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows (); + TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); + + if (selection->count_selected_rows() == 0 || _session == 0) { + return; + } + + for (; i != rows.end(); ++i) { + TreeIter iter; + + if ((iter = _model->get_iter (*i))) { + + /* some rows don't have a region associated with them, but can still be + selected (XXX maybe prevent them from being selected) + */ + + boost::shared_ptr r = (*iter)[_columns.region]; + + if (r) { + sl (r); + } + } + } +} + + +void +EditorRegions::remove_region () +{ + selection_mapover (mem_fun (*_editor, &Editor::remove_a_region)); +} + +void +EditorRegions::drag_data_received (const RefPtr& context, + int x, int y, + const SelectionData& data, + guint info, guint time) +{ + vector paths; + + if (data.get_target() == "GTK_TREE_MODEL_ROW") { + _display.on_drag_data_received (context, x, y, data, info, time); + return; + } + + if (_editor->convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) { + nframes64_t pos = 0; + if (Profile->get_sae() || Config->get_only_copy_imported_files()) { + _editor->do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsRegion, SrcBest, pos); + } else { + _editor->do_embed (paths, Editing::ImportDistinctFiles, ImportAsRegion, pos); + } + context->drag_finish (true, false, time); + } +} + +bool +EditorRegions::selection_filter (const RefPtr& model, const TreeModel::Path& path, bool yn) +{ + /* not possible to select rows that do not represent regions, like "Hidden" */ + + TreeModel::iterator iter = model->get_iter (path); + + if (iter) { + boost::shared_ptr r =(*iter)[_columns.region]; + if (!r) { + return false; + } + } + + return true; +} + +void +EditorRegions::name_edit (const Glib::ustring& path, const Glib::ustring& new_text) +{ + boost::shared_ptr region; + TreeIter iter; + + if ((iter = _model->get_iter (path))) { + region = (*iter)[_columns.region]; + (*iter)[_columns.name] = new_text; + } + + /* now mapover everything */ + + if (region) { + vector equivalents; + _editor->get_regions_corresponding_to (region, equivalents); + + for (vector::iterator i = equivalents.begin(); i != equivalents.end(); ++i) { + if (new_text != (*i)->region()->name()) { + (*i)->region()->set_name (new_text); + } + } + } + +} + +boost::shared_ptr +EditorRegions::get_dragged_region () +{ + list > regions; + TreeView* source; + _display.get_object_drag_data (regions, &source); + assert (regions.size() == 1); + return regions.front (); +} + +void +EditorRegions::clear () +{ + _display.set_model (Glib::RefPtr (0)); + _model->clear (); + _display.set_model (_model); +} + +boost::shared_ptr +EditorRegions::get_single_selection () +{ + Glib::RefPtr selected = _display.get_selection(); + + if (selected->count_selected_rows() != 1) { + return boost::shared_ptr (); + } + + TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows (); + + /* only one row selected, so rows.begin() is it */ + + TreeIter iter = _model->get_iter (*rows.begin()); + + if (!iter) { + return boost::shared_ptr (); + } + + return (*iter)[_columns.region]; +} diff --git a/gtk2_ardour/editor_regions.h b/gtk2_ardour/editor_regions.h new file mode 100644 index 0000000000..ddb1477a16 --- /dev/null +++ b/gtk2_ardour/editor_regions.h @@ -0,0 +1,151 @@ +/* + Copyright (C) 2000-2009 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "editor_component.h" + +class EditorRegions : public EditorComponent +{ +public: + EditorRegions (Editor *); + + void connect_to_session (ARDOUR::Session *); + + Gtk::Widget& widget () { + return _scroller; + } + + void clear (); + + void toggle_full (); + void toggle_show_auto_regions (); + void reset_sort_direction (bool); + void reset_sort_type (Editing::RegionListSortType, bool); + void set_selected (RegionSelection &); + void remove_region (); + void selection_mapover (sigc::slot >); + boost::shared_ptr get_dragged_region (); + boost::shared_ptr get_single_selection (); + Editing::RegionListSortType sort_type () const { + return _sort_type; + } + void redisplay (); + + void suspend_redisplay () { + _no_redisplay = true; + } + void resume_redisplay () { + _no_redisplay = false; + redisplay (); + } + + void block_change_connection (bool b) { + _change_connection.block (b); + } + + void unselect_all () { + _display.get_selection()->unselect_all (); + } + +private: + + struct Columns : public Gtk::TreeModel::ColumnRecord { + Columns () { + add (name); + add (region); + add (color_); + add (start); + add (end); + add (length); + add (sync); + add (fadein); + add (fadeout); + add (locked); + add (glued); + add (muted); + add (opaque); + add (used); + add (path); + } + + Gtk::TreeModelColumn name; + Gtk::TreeModelColumn > region; + Gtk::TreeModelColumn color_; + Gtk::TreeModelColumn start; + Gtk::TreeModelColumn end; + Gtk::TreeModelColumn length; + Gtk::TreeModelColumn sync; + Gtk::TreeModelColumn fadein; + Gtk::TreeModelColumn fadeout; + Gtk::TreeModelColumn locked; + Gtk::TreeModelColumn glued; + Gtk::TreeModelColumn muted; + Gtk::TreeModelColumn opaque; + Gtk::TreeModelColumn used; + Gtk::TreeModelColumn path; + }; + + Columns _columns; + + void region_changed (ARDOUR::Change, boost::weak_ptr); + void selection_changed (); + sigc::connection _change_connection; + bool set_selected_in_subrow (boost::shared_ptr, Gtk::TreeModel::Row const &, int); + bool selection_filter (const Glib::RefPtr& model, const Gtk::TreeModel::Path& path, bool yn); + void name_edit (const Glib::ustring&, const Glib::ustring&); + + bool key_press (GdkEventKey *); + bool key_release (GdkEventKey *); + bool button_press (GdkEventButton *); + bool button_release (GdkEventButton *); + void build_menu (); + void show_context_menu (int button, int time); + + int sorter (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator); + + void handle_new_region (boost::weak_ptr); + void handle_new_regions (std::vector >& ); + void handle_region_removed (boost::weak_ptr); + void add_region (boost::shared_ptr); + void add_regions (std::vector > & ); + void region_hidden (boost::shared_ptr); + void populate_row (boost::shared_ptr, Gtk::TreeModel::Row const &); + void update_row (boost::shared_ptr); + bool update_subrows (boost::shared_ptr, Gtk::TreeModel::Row const &, int); + void update_all_rows (); + void update_all_subrows (Gtk::TreeModel::Row const &, int); + void insert_into_tmp_regionlist (boost::shared_ptr); + + void drag_data_received ( + Glib::RefPtr const &, gint, gint, Gtk::SelectionData const &, guint, guint + ); + + Gtk::Menu* _menu; + Gtk::ScrolledWindow _scroller; + Gtk::Frame _frame; + Gtkmm2ext::DnDTreeView > _display; + Glib::RefPtr _model; + Glib::RefPtr _toggle_full_action; + Glib::RefPtr _toggle_show_auto_regions_action; + bool _show_automatic_regions; + Editing::RegionListSortType _sort_type; + bool _no_redisplay; + std::list > tmp_region_list; +}; + + diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index 7c70400e39..3b53a2d821 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -34,6 +34,7 @@ #include "audio_streamview.h" #include "automation_line.h" #include "control_point.h" +#include "editor_regions.h" #include "i18n.h" @@ -878,15 +879,15 @@ Editor::sensitize_the_right_region_actions (bool have_selected_regions) void Editor::region_selection_changed () { - region_list_change_connection.block(true); + _regions->block_change_connection (true); editor_regions_selection_changed_connection.block(true); - - region_list_display.get_selection()->unselect_all(); + + _regions->unselect_all (); for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { (*i)->set_selected_regionviews (selection->regions); - set_selected_in_region_list(selection->regions); + _regions->set_selected (selection->regions); } @@ -894,7 +895,7 @@ Editor::region_selection_changed () zoomed_to_region = false; - region_list_change_connection.block(false); + _regions->block_change_connection (false); editor_regions_selection_changed_connection.block(false); } diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 3adac59e09..51d5f6a5e3 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -117,7 +117,7 @@ def build(bld): editor_mouse.cc editor_nudge.cc editor_ops.cc - editor_region_list.cc + editor_regions.cc editor_routes.cc editor_rulers.cc editor_scrub.cc