Compare commits

...

24 Commits

Author SHA1 Message Date
Ben Loftis a53da91c46 Catch new sources created by bounce-range-to-source-list 2019-07-30 15:43:22 -05:00
Ben Loftis a5c18d7338 Handle Session::RemoveSource 2019-07-30 13:43:14 -05:00
Ben Loftis db95fb6b23 Replace missing initializer; fixes a bug where Sources did not appear on startup. 2019-07-30 13:14:06 -05:00
Ben Loftis 422e46e9c8 Implement insert-region action... now uses the Source List. 2019-07-30 13:02:15 -05:00
Ben Loftis 8dea1a033d Recover Regions feature: WIP 2019-07-29 20:31:58 -05:00
Ben Loftis 29865677b8 Revert to displaying whole-file Regions instead of Sources.
This preserves the stereo-ness of files that were imported or recorded in stereo.

ToDo  (maybe someday): provide a disclosure triangle that exposes the individual channels in a multichannel region
2019-07-29 20:29:35 -05:00
Ben Loftis b23be53514 Add forall_regions function, used by Region and Source lists. 2019-07-29 20:29:35 -05:00
Ben Loftis 81f8bb24ff No need to show the path when file is internal to session. 2019-07-29 20:29:35 -05:00
Ben Loftis e3b8a70cbb merge fixes 2019-07-29 20:29:35 -05:00
Ben Loftis 6a8ce91bd0 Clean up the natural_position implementation (gtk2 part). 2019-07-29 20:29:35 -05:00
Ben Loftis c5eeea95c4 Clean up the natural_position implementation (libardour part). 2019-07-29 20:29:34 -05:00
Ben Loftis 1ccc7454e1 Source List: Implement remove_selected_sources when the user clicks Delete key. 2019-07-29 20:29:34 -05:00
Paul Davis aae54f1cc9 NOOP: whitespace cleanup
remove debug output
2019-07-29 20:29:34 -05:00
Ben Loftis 9e21d683a4 Source list: Fix drag-n-drop. 2019-07-29 20:29:34 -05:00
Ben Loftis edc91f3546 RegionFactory should return an empty region here. 2019-07-29 20:29:34 -05:00
Ben Loftis d2dbf364a6 Source list, Region List: Resolve various action+behaviors between the 2 lists.
Duplicate the remove_unsued_region action in the Session->Cleanup menu, for discoverability.
Region list should use the same Region actions as the canvas...
OK, now resolve the change in use-cases of Region List and Source List.  tentative.
Rough-in remove_selected_sources (Delete in Sources list).
Column tweaks.
2019-07-29 20:29:34 -05:00
Ben Loftis 9a6194218e Region Tags (gtk2 part) 2019-07-29 20:29:34 -05:00
Ben Loftis 433f275c96 Region Tags (libardour part)
Rough-in: Region-Tags.

More correct implementation of tags property (libardour).

Region Tags (libardour part)
2019-07-29 20:29:34 -05:00
Ben Loftis 102555bb34 Make clock change func more explicit. 2019-07-29 20:29:34 -05:00
Ben Loftis 4f6d53aa32 Region List rewrite (gtk2 part)
See:  https://docs.google.com/document/d/1sI7p9RoRVZtNx2n67RvBa0_16fuZblV_lNkkKN2g93s/edit?usp=sharing
2019-07-29 20:29:34 -05:00
Ben Loftis 74dd35f4b9 Region List rewrite (libardour part)
Region List rewrite (libardour part)
2019-07-29 20:29:34 -05:00
Ben Loftis 4a4ac0d867 Source List (gtk2 part)
See:  https://docs.google.com/document/d/1sI7p9RoRVZtNx2n67RvBa0_16fuZblV_lNkkKN2g93s/edit?usp=sharing
2019-07-29 20:29:34 -05:00
Ben Loftis bdf1b54093 Source List (libardour part) 2019-07-29 20:29:34 -05:00
Ben Loftis ea9ea68c9d Take-ID: new (working) implementation. 2019-07-29 20:29:34 -05:00
53 changed files with 1734 additions and 993 deletions

View File

@ -166,7 +166,7 @@ This mode provides many different operations on both regions and control points,
@edit|Editor/alternate-redo|<@PRIMARY@>y|redo
@select|Editor/select-all-between-cursors|<@PRIMARY@>u|all enclosed by edit range
@select|Editor/select-all-within-cursors|u|all present in edit range
@eep|Region/insert-region-from-region-list|i|insert from region list
@eep|Region/insert-region-from-source-list|i|insert from region list
@sess|Common/addExistingAudioFiles|<@PRIMARY@>i|import audio files
@gselect|Common/invert-selection|<@TERTIARY@>i|invert selection
@edtrk|Editor/toggle-midi-input-active|<@SECONDARY@>i|toggle sel. track MIDI input

View File

@ -49,7 +49,8 @@
<menu name='Cleanup' action='Cleanup'>
<menuitem action='bring-into-session'/>
<menuitem action='CleanupPeakFiles'/>
<menuitem action='CleanupUnused'/>
<menuitem action='CleanupUnusedSources'/>
<menuitem action='CleanupUnusedRegions'/>
<menuitem action='FlushWastebasket'/>
</menu>
#ifdef __APPLE__
@ -234,6 +235,7 @@
<menuitem action='toggle-region-fade-out'/>
</menu>
<separator/>
<menuitem action='tag-last-capture'/>
<menuitem action='remove-last-capture'/>
<separator/>
<menu action="EditPointMenu">
@ -291,8 +293,9 @@
</menu>
<menu name='RegionMenu' action='RegionMenu'>
<menuitem action='insert-region-from-region-list'/>
<menuitem action='insert-region-from-source-list'/>
<menuitem action='play-selected-regions'/>
<menuitem action='tag-selected-regions'/>
<menuitem action='loop-region'/>
<menuitem action='rename-region'/>
<menuitem action='show-region-properties'/>
@ -702,26 +705,6 @@
<popup name='RegionListMenu' accelerators='true'>
<menuitem action='rlAudition'/>
<menuitem action='rlHide'/>
<menuitem action='rlShow'/>
<separator/>
<menuitem action='rlShowAll'/>
<menuitem action='rlShowAuto'/>
<menu name='Sort' action='RegionListSort'>
<menuitem action='SortAscending'/>
<menuitem action='SortDescending'/>
<separator/>
<menuitem action='SortByRegionName'/>
<menuitem action='SortByRegionLength'/>
<menuitem action='SortByRegionPosition'/>
<menuitem action='SortByRegionTimestamp'/>
<menuitem action='SortByRegionStartinFile'/>
<menuitem action='SortByRegionEndinFile'/>
<menuitem action='SortBySourceFileName'/>
<menuitem action='SortBySourceFileLength'/>
<menuitem action='SortBySourceFileCreationDate'/>
<menuitem action='SortBySourceFilesystem'/>
</menu>
<separator/>
<menuitem action='addExternalAudioToRegionList'/>
<separator/>
@ -730,6 +713,7 @@
<popup name='PopupRegionMenu' action='PopupRegionMenu' accelerators='true'>
<menuitem action='play-selected-regions'/>
<menuitem action='tag-selected-regions'/>
<menuitem action='loop-region'/>
<menuitem action='rename-region'/>
<menuitem action='show-region-properties'/>

View File

@ -238,14 +238,6 @@ ARDOUR_UI::install_actions ()
act = ActionManager::register_action (main_actions, X_("Export"), _("Export"));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("CleanupUnused"), _("Clean-up Unused Sources..."), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("CleanupPeakFiles"), _("Reset Peak Files"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup_peakfiles));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("FlushWastebasket"), _("Flush Wastebasket"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::flush_trash));
ActionManager::write_sensitive_actions.push_back (act);
@ -568,6 +560,18 @@ ARDOUR_UI::install_dependent_actions ()
act = ActionManager::register_action (main_actions, X_("ExportAudio"), _("Export to Audio File(s)..."), sigc::mem_fun (*editor, &PublicEditor::export_audio));
ActionManager::session_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("CleanupUnusedSources"), _("Clean-up Unused Sources..."), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("CleanupUnusedRegions"), _("Clean-up Unused Regions..."), sigc::mem_fun (*editor, &PublicEditor::cleanup_regions));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (main_actions, X_("CleanupPeakFiles"), _("Reset Peak Files"), sigc::mem_fun (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup_peakfiles));
ActionManager::session_sensitive_actions.push_back (act);
ActionManager::write_sensitive_actions.push_back (act);
/* these actions are all currently implemented by the Editor, but need
* to be accessible from anywhere as actions.
*/

View File

@ -109,6 +109,7 @@
#include "editor_route_groups.h"
#include "editor_routes.h"
#include "editor_snapshots.h"
#include "editor_sources.h"
#include "editor_summary.h"
#include "enums_convert.h"
#include "export_report.h"
@ -639,6 +640,7 @@ Editor::Editor ()
_route_groups = new EditorRouteGroups (this);
_routes = new EditorRoutes (this);
_regions = new EditorRegions (this);
_sources = new EditorSources (this);
_snapshots = new EditorSnapshots (this);
_locations = new EditorLocations (this);
_time_info_box = new TimeInfoBox ("EditorTimeInfo", true);
@ -649,6 +651,7 @@ Editor::Editor ()
Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
add_notebook_page (_("Sources"), _sources->widget ());
add_notebook_page (_("Regions"), _regions->widget ());
add_notebook_page (_("Tracks & Busses"), _routes->widget ());
add_notebook_page (_("Snapshots"), _snapshots->widget ());
@ -1334,6 +1337,7 @@ Editor::set_session (Session *t)
_group_tabs->set_session (_session);
_route_groups->set_session (_session);
_regions->set_session (_session);
_sources->set_session (_session);
_snapshots->set_session (_session);
_routes->set_session (_session);
_locations->set_session (_session);
@ -1944,7 +1948,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
edit_items.push_back (SeparatorElem());
edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
// edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
edit_items.push_back (SeparatorElem());
edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
@ -1964,8 +1968,8 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
edit_items.push_back (SeparatorElem());
edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
edit_items.push_back (MenuElem (_("Bounce Range to Source List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
edit_items.push_back (MenuElem (_("Bounce Range to Source List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
@ -2037,7 +2041,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
/* Adding new material */
edit_items.push_back (SeparatorElem());
edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_source_list_selection), 1.0f)));
edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
/* Nudge track */
@ -2461,14 +2465,8 @@ Editor::set_state (const XMLNode& node, int version)
set_stationary_playhead (yn);
}
RegionListSortType sort_type;
if (node.get_property ("region-list-sort-type", sort_type)) {
_regions->reset_sort_type (sort_type, true);
}
if (node.get_property ("show-editor-mixer", yn)) {
yn = false;
node.get_property ("show-editor-mixer", yn);
{
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action (X_("Editor"), X_("show-editor-mixer"));
/* do it twice to force the change */
tact->set_active (!yn);
@ -2578,7 +2576,6 @@ Editor::get_state ()
node->set_property ("maximised", _maximised);
node->set_property ("follow-playhead", _follow_playhead);
node->set_property ("stationary-playhead", _stationary_playhead);
node->set_property ("region-list-sort-type", _regions->sort_type ());
node->set_property ("mouse-mode", mouse_mode);
node->set_property ("join-object-range", smart_mode_action->get_active ());
@ -4280,6 +4277,13 @@ Editor::audio_region_selection_covers (samplepos_t where)
return false;
}
void
Editor::cleanup_regions ()
{
_regions->remove_unused_regions();
}
void
Editor::prepare_for_cleanup ()
{
@ -5716,18 +5720,6 @@ Editor::audition_region_from_region_list ()
_regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
}
void
Editor::hide_region_from_region_list ()
{
_regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
}
void
Editor::show_region_in_region_list ()
{
_regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
}
void
Editor::step_edit_status_change (bool yn)
{
@ -6035,6 +6027,7 @@ Editor::session_going_away ()
/* rip everything out of the list displays */
_regions->clear ();
_sources->clear ();
_routes->clear ();
_route_groups->clear ();

View File

@ -110,6 +110,7 @@ class EditorCursor;
class EditorGroupTabs;
class EditorLocations;
class EditorRegions;
class EditorSources;
class EditorRoutes;
class EditorRouteGroups;
class EditorSnapshots;
@ -387,6 +388,8 @@ public:
void select_topmost_track ();
void cleanup_regions ();
void prepare_for_cleanup ();
void finish_cleanup ();
@ -1236,6 +1239,7 @@ private:
void align_regions_relative (ARDOUR::RegionPoint point);
void align_region (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, samplepos_t position);
void align_region_internal (boost::shared_ptr<ARDOUR::Region>, ARDOUR::RegionPoint point, samplepos_t position);
void recover_regions (ARDOUR::RegionList);
void remove_selected_regions ();
void remove_clicked_region ();
void show_region_properties ();
@ -1282,8 +1286,6 @@ private:
void define_one_bar (samplepos_t start, samplepos_t end);
void audition_region_from_region_list ();
void hide_region_from_region_list ();
void show_region_in_region_list ();
void naturalize_region ();
@ -1320,7 +1322,7 @@ private:
void temporal_zoom_by_sample (samplepos_t start, samplepos_t end);
void temporal_zoom_to_sample (bool coarser, samplepos_t sample);
void insert_region_list_selection (float times);
void insert_source_list_selection (float times);
/* import & embed */
@ -1440,6 +1442,11 @@ private:
void toggle_skip_playback ();
void remove_last_capture ();
void tag_last_capture ();
void tag_selected_region ();
void tag_regions (ARDOUR::RegionList);
void select_all_selectables_using_time_selection ();
void select_all_selectables_using_loop();
void select_all_selectables_using_punch();
@ -1606,6 +1613,7 @@ private:
friend class DragManager;
friend class EditorRouteGroups;
friend class EditorRegions;
friend class EditorSources;
/* non-public event handlers */
@ -1895,6 +1903,7 @@ private:
EditorRouteGroups* _route_groups;
EditorRoutes* _routes;
EditorRegions* _regions;
EditorSources* _sources;
EditorSnapshots* _snapshots;
EditorLocations* _locations;
@ -1971,7 +1980,8 @@ private:
gint y,
const Gtk::SelectionData& data,
guint info,
guint time);
guint time,
bool from_region_list);
void drop_routes (
const Glib::RefPtr<Gdk::DragContext>& context,

View File

@ -330,6 +330,8 @@ Editor::register_actions ()
/* this is a duplicated action so that the main menu can use a different label */
reg_sens (editor_actions, "main-menu-play-selected-regions", _("Play Selected Regions"), sigc::mem_fun (*this, &Editor::play_selected_region));
reg_sens (editor_actions, "main-menu-tag-selected-regions", _("Tag Selected Regions"), sigc::mem_fun (*this, &Editor::tag_selected_region));
reg_sens (editor_actions, "play-from-edit-point", _("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point));
reg_sens (editor_actions, "play-from-edit-point-and-return", _("Play from Edit Point and Return"), sigc::mem_fun(*this, &Editor::play_from_edit_point_and_return));
@ -422,6 +424,7 @@ Editor::register_actions ()
toggle_reg_sens (editor_actions, "toggle-follow-playhead", _("Follow Playhead"), (sigc::mem_fun(*this, &Editor::toggle_follow_playhead)));
act = reg_sens (editor_actions, "remove-last-capture", _("Remove Last Capture"), (sigc::mem_fun(*this, &Editor::remove_last_capture)));
act = reg_sens (editor_actions, "tag-last-capture", _("Tag Last Capture"), (sigc::mem_fun(*this, &Editor::tag_last_capture)));
ActionManager::register_toggle_action (editor_actions, "toggle-stationary-playhead", _("Stationary Playhead"), (mem_fun(*this, &Editor::toggle_stationary_playhead)));
@ -667,46 +670,9 @@ Editor::register_actions ()
RadioAction::Group sort_order_group;
/* the region list popup menu */
ActionManager::register_action (rl_actions, X_("RegionListSort"), _("Sort"));
act = ActionManager::register_action (rl_actions, X_("rlAudition"), _("Audition"), sigc::mem_fun(*this, &Editor::audition_region_from_region_list));
ActionManager::region_list_selection_sensitive_actions.push_back (act);
act = ActionManager::register_action (rl_actions, X_("rlHide"), _("Hide"), sigc::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_("rlShow"), _("Show"), sigc::mem_fun(*this, &Editor::show_region_in_region_list));
ActionManager::region_list_selection_sensitive_actions.push_back (act);
ActionManager::register_toggle_action (rl_actions, X_("rlShowAll"), _("Show All"), sigc::mem_fun(*_regions, &EditorRegions::toggle_full));
ActionManager::register_toggle_action (rl_actions, X_("rlShowAuto"), _("Show Automatic Regions"), sigc::mem_fun (*_regions, &EditorRegions::toggle_show_auto_regions));
ActionManager::register_radio_action (rl_actions, sort_order_group, X_("SortAscending"), _("Ascending"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_direction), true));
ActionManager::register_radio_action (rl_actions, sort_order_group, X_("SortDescending"), _("Descending"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_direction), false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionName"), _("By Region Name"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), ByName, false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionLength"), _("By Region Length"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), ByLength, false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionPosition"), _("By Region Position"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), ByPosition, false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortByRegionTimestamp"), _("By Region Timestamp"),
sigc::bind (sigc::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"),
sigc::bind (sigc::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"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), ByEndInFile, false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFileName"), _("By Source File Name"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileName, false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFileLength"), _("By Source File Length"),
sigc::bind (sigc::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"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileCreationDate, false));
ActionManager::register_radio_action (rl_actions, sort_type_group, X_("SortBySourceFilesystem"), _("By Source Filesystem"),
sigc::bind (sigc::mem_fun (*_regions, &EditorRegions::reset_sort_type), BySourceFileFS, false));
ActionManager::register_action (rl_actions, X_("removeUnusedRegions"), _("Remove Unused"), sigc::mem_fun (*_regions, &EditorRegions::remove_unused_regions));
act = reg_sens (editor_actions, X_("addExistingPTFiles"), _("Import PT session"), sigc::mem_fun (*this, &Editor::external_pt_dialog));
@ -714,7 +680,7 @@ Editor::register_actions ()
/* the next two are duplicate items with different names for use in two different contexts */
act = reg_sens (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Region List..."), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
act = reg_sens (editor_actions, X_("addExternalAudioToRegionList"), _("Import to Source List..."), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportAsRegion));
ActionManager::write_sensitive_actions.push_back (act);
act = ActionManager::register_action (editor_actions, X_("importFromSession"), _("Import from Session"), sigc::mem_fun(*this, &Editor::session_import_dialog));
@ -1549,6 +1515,7 @@ Editor::register_region_actions ()
register_region_action (_region_actions, RegionActionTarget (SelectedRegions), "show-region-properties", _("Properties..."), sigc::mem_fun (*this, &Editor::show_region_properties));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "play-selected-regions", _("Play selected Regions"), sigc::mem_fun(*this, &Editor::play_selected_region));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions|EnteredRegions), "tag-selected-regions", _("Tag selected Regions"), sigc::mem_fun(*this, &Editor::tag_selected_region));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions), "bounce-regions-processed", _("Bounce (with processing)"), (sigc::bind (sigc::mem_fun (*this, &Editor::bounce_region_selection), true)));
register_region_action (_region_actions, RegionActionTarget (SelectedRegions), "bounce-regions-unprocessed", _("Bounce (without processing)"), (sigc::bind (sigc::mem_fun (*this, &Editor::bounce_region_selection), false)));
@ -1592,7 +1559,7 @@ Editor::register_region_actions ()
/* PART 2: actions that are not related to the selection, but for which the edit point type and location is important */
register_region_action (_region_actions, RegionActionTarget (ListSelection), "insert-region-from-region-list", _("Insert Region from Region List"), sigc::bind (sigc::mem_fun (*this, &Editor::insert_region_list_selection), 1));
register_region_action (_region_actions, RegionActionTarget (ListSelection), "insert-region-from-source-list", _("Insert Region from Source List"), sigc::bind (sigc::mem_fun (*this, &Editor::insert_source_list_selection), 1));
/* PART 3: actions that operate on the selection and also require the edit point location */

View File

@ -249,9 +249,8 @@ Editor::initialize_canvas ()
vector<TargetEntry> target_table;
// Drag-N-Drop from the region list can generate this target
target_table.push_back (TargetEntry ("regions"));
target_table.push_back (TargetEntry ("regions")); // DnD from the region list will generate this target
target_table.push_back (TargetEntry ("sources")); // DnD from the source list will generate this target
target_table.push_back (TargetEntry ("text/uri-list"));
target_table.push_back (TargetEntry ("text/plain"));
target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
@ -376,8 +375,10 @@ Editor::track_canvas_drag_data_received (const RefPtr<Gdk::DragContext>& context
if (!ARDOUR_UI_UTILS::engine_is_running ()) {
return;
}
if (data.get_target() == "regions") {
drop_regions (context, x, y, data, info, time);
if (data.get_target() == X_("regions")) {
drop_regions (context, x, y, data, info, time, true);
} else if (data.get_target() == X_("sources")) {
drop_regions (context, x, y, data, info, time, false);
} else {
drop_paths (context, x, y, data, info, time);
}

View File

@ -27,8 +27,8 @@
#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
#include "ardour/midi_region.h"
#include "ardour/region_factory.h"
#include "ardour/profile.h"
#include "ardour/region_factory.h"
#include "canvas/canvas.h"
#include "canvas/text.h"
@ -48,6 +48,7 @@
#include "editor_drag.h"
#include "midi_time_axis.h"
#include "editor_regions.h"
#include "editor_sources.h"
#include "ui_config.h"
#include "verbose_cursor.h"
@ -1196,7 +1197,10 @@ Editor::track_canvas_drag_motion (Glib::RefPtr<Gdk::DragContext> const& context,
}
if (can_drop) {
region = _regions->get_dragged_region ();
if (target == X_("regions")) {
region = _regions->get_dragged_region ();
}
if (region) {
@ -1253,7 +1257,8 @@ void
Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
int x, int y,
const SelectionData& /*data*/,
guint /*info*/, guint /*time*/)
guint /*info*/, guint /*time*/,
bool from_region_list)
{
GdkEvent event;
double px;
@ -1266,7 +1271,14 @@ Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
event.motion.state = Gdk::BUTTON1_MASK;
samplepos_t const pos = window_event_sample (&event, &px, &py);
boost::shared_ptr<Region> region = _regions->get_dragged_region ();
boost::shared_ptr<Region> region;
if (from_region_list) {
region = _regions->get_dragged_region ();
} else {
region = _sources->get_dragged_region ();
}
if (!region) { return; }
RouteTimeAxisView* rtav = 0;
@ -1354,4 +1366,3 @@ Editor::key_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemType
return handled;
}

View File

@ -61,6 +61,7 @@
#include "ardour/selection.h"
#include "ardour/session.h"
#include "ardour/session_playlists.h"
#include "ardour/source.h"
#include "ardour/strip_silence.h"
#include "ardour/transient_detector.h"
#include "ardour/transport_master_manager.h"
@ -83,6 +84,7 @@
#include "editor_cursors.h"
#include "editor_drag.h"
#include "editor_regions.h"
#include "editor_sources.h"
#include "editor_routes.h"
#include "gui_thread.h"
#include "insert_remove_time_dialog.h"
@ -2541,7 +2543,7 @@ Editor::unhide_ranges ()
/* INSERT/REPLACE */
void
Editor::insert_region_list_selection (float times)
Editor::insert_source_list_selection (float times)
{
RouteTimeAxisView *tv = 0;
boost::shared_ptr<Playlist> playlist;
@ -2564,7 +2566,7 @@ Editor::insert_region_list_selection (float times)
return;
}
boost::shared_ptr<Region> region = _regions->get_single_selection ();
boost::shared_ptr<Region> region = _sources->get_single_selection ();
if (region == 0) {
return;
}
@ -4478,6 +4480,32 @@ Editor::remove_clicked_region ()
}
void
Editor::recover_regions (ARDOUR::RegionList regions)
{
#ifdef RECOVER_REGIONS_IS_WORKING
begin_reversible_command (_("recover regions"));
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
boost::shared_ptr<ARDOUR::Source> source = (*i)->source();
RouteList routes = _session->get_routelist();
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
boost::shared_ptr<ARDOUR::Track> track = boost::dynamic_pointer_cast<Track>(*it);
if (track) {
//ToDo
if (source->captured_for() == track->) {
//_session->add_command(new StatefulDiffCommand (playlist));
}
}
}
}
commit_reversible_command ();
#endif
}
/** Remove the selected regions */
void
Editor::remove_selected_regions ()
@ -5139,6 +5167,95 @@ Editor::remove_last_capture ()
}
}
void
Editor::tag_regions (RegionList regions)
{
ArdourDialog d (_("Tag Last Capture"), true, false);
Entry entry;
Label label (_("Tag:"));
HBox hbox;
hbox.set_spacing (6);
hbox.pack_start (label, false, false);
hbox.pack_start (entry, true, true);
d.get_vbox()->set_border_width (12);
d.get_vbox()->pack_start (hbox, false, false);
d.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
d.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
d.set_size_request (300, -1);
entry.set_text (_("Good"));
entry.select_region (0, -1);
entry.signal_activate().connect (sigc::bind (sigc::mem_fun (d, &Dialog::response), RESPONSE_OK));
d.show_all ();
entry.grab_focus();
int const ret = d.run();
d.hide ();
if (ret != RESPONSE_OK) {
return;
}
std::string tagstr = entry.get_text();
strip_whitespace_edges (tagstr);
if (!tagstr.empty()) {
for (RegionList::iterator r = regions.begin(); r != regions.end(); r++) {
(*r)->set_tags(tagstr);
}
_regions->redisplay ();
}
}
void
Editor::tag_selected_region ()
{
std::list<boost::shared_ptr<Region> > rlist;
RegionSelection rs = get_regions_from_selection_and_entered ();
for (RegionSelection::iterator r = rs.begin(); r != rs.end(); r++) {
rlist.push_back((*r)->region());
}
tag_regions(rlist);
}
void
Editor::tag_last_capture ()
{
if (!_session) {
return;
}
std::list<boost::shared_ptr<Region> > rlist;
std::list<boost::shared_ptr<Source> > srcs;
_session->get_last_capture_sources (srcs);
for (std::list<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
boost::shared_ptr<ARDOUR::Source> source = (*i);
if (source) {
set<boost::shared_ptr<Region> > regions;
RegionFactory::get_regions_using_source (source, regions);
for (set<boost::shared_ptr<Region> >::iterator r = regions.begin(); r != regions.end(); r++) {
rlist.push_back(*r);
}
}
}
tag_regions(rlist);
}
void
Editor::normalize_region ()
{

File diff suppressed because it is too large Load Diff

View File

@ -41,20 +41,12 @@ public:
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 selection_mapover (sigc::slot<void,boost::shared_ptr<ARDOUR::Region> >);
boost::shared_ptr<ARDOUR::Region> get_dragged_region ();
boost::shared_ptr<ARDOUR::Region> get_single_selection ();
Editing::RegionListSortType sort_type () const {
return _sort_type;
}
void redisplay ();
void suspend_redisplay () {
@ -84,11 +76,10 @@ private:
struct Columns : public Gtk::TreeModel::ColumnRecord {
Columns () {
add (name);
add (region);
add (color_);
add (position);
add (end);
add (tags);
add (start);
add (length);
add (end);
add (sync);
add (fadein);
add (fadeout);
@ -96,15 +87,16 @@ private:
add (glued);
add (muted);
add (opaque);
add (used);
add (path);
add (property_toggles_visible);
add (region);
add (color_);
add (position);
}
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
Gtk::TreeModelColumn<Gdk::Color> color_;
Gtk::TreeModelColumn<std::string> position;
Gtk::TreeModelColumn<std::string> tags;
Gtk::TreeModelColumn<samplepos_t> position;
Gtk::TreeModelColumn<std::string> start;
Gtk::TreeModelColumn<std::string> end;
Gtk::TreeModelColumn<std::string> length;
Gtk::TreeModelColumn<std::string> sync;
@ -114,10 +106,9 @@ private:
Gtk::TreeModelColumn<bool> glued;
Gtk::TreeModelColumn<bool> muted;
Gtk::TreeModelColumn<bool> opaque;
Gtk::TreeModelColumn<std::string> used;
Gtk::TreeModelColumn<std::string> path;
/** used to indicate whether the locked/glued/muted/opaque should be visible or not */
Gtk::TreeModelColumn<bool> property_toggles_visible;
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
Gtk::TreeModelColumn<Gdk::Color> color_;
};
Columns _columns;
@ -134,10 +125,17 @@ private:
bool selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
Gtk::Widget* old_focus;
Gtk::CellEditable* name_editable;
void name_editing_started (Gtk::CellEditable*, const Glib::ustring&);
void name_edit (const std::string&, const std::string&);
Gtk::CellEditable* tags_editable;
void tag_editing_started (Gtk::CellEditable*, const Glib::ustring&);
void tag_edit (const std::string&, const std::string&);
void locked_changed (std::string const &);
void glued_changed (std::string const &);
void muted_changed (std::string const &);
@ -153,44 +151,35 @@ private:
void show_context_menu (int button, int time);
int sorter (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator);
void format_position (ARDOUR::samplepos_t pos, char* buf, size_t bufsize, bool onoff = true);
void add_region (boost::shared_ptr<ARDOUR::Region>);
void destroy_region (boost::shared_ptr<ARDOUR::Region>);
void populate_row (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &, PBD::PropertyChange const &);
void populate_row_used (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_position (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_end (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_sync (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_fade_in (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used, boost::shared_ptr<ARDOUR::AudioRegion>);
void populate_row_fade_out (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used, boost::shared_ptr<ARDOUR::AudioRegion>);
void populate_row_locked (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_muted (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_glued (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_opaque (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, uint32_t used);
void populate_row_used (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_position (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_end (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_sync (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_fade_in (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, boost::shared_ptr<ARDOUR::AudioRegion>);
void populate_row_fade_out (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row, boost::shared_ptr<ARDOUR::AudioRegion>);
void populate_row_locked (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_muted (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_glued (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_opaque (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_length (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_name (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void populate_row_source (boost::shared_ptr<ARDOUR::Region> region, Gtk::TreeModel::Row const& row);
void update_row (boost::shared_ptr<ARDOUR::Region>);
void update_all_rows ();
void insert_into_tmp_regionlist (boost::shared_ptr<ARDOUR::Region>);
void clock_format_changed ();
void drag_data_received (
Glib::RefPtr<Gdk::DragContext> const &, gint, gint, Gtk::SelectionData const &, guint, guint
);
Glib::RefPtr<Gtk::RadioAction> sort_type_action (Editing::RegionListSortType) const;
void set_full (bool);
Glib::RefPtr<Gtk::Action> hide_action () const;
Glib::RefPtr<Gtk::Action> show_action () const;
Glib::RefPtr<Gtk::Action> remove_unused_regions_action () const;
Glib::RefPtr<Gtk::ToggleAction> toggle_full_action () const;
Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action () const;
Gtk::Menu* _menu;
Gtk::ScrolledWindow _scroller;
@ -200,28 +189,17 @@ private:
Glib::RefPtr<Gtk::TreeStore> _model;
bool _show_automatic_regions;
bool ignore_region_list_selection_change;
bool ignore_selected_region_change;
bool _no_redisplay;
Editing::RegionListSortType _sort_type;
std::list<boost::shared_ptr<ARDOUR::Region> > tmp_region_list;
typedef boost::unordered_map<boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::iterator> RegionRowMap;
typedef boost::unordered_map<std::string, Gtk::TreeModel::RowReference > RegionSourceMap;
RegionRowMap region_row_map;
RegionSourceMap parent_regions_sources_map;
PBD::ScopedConnection region_property_connection;
PBD::ScopedConnection check_new_region_connection;
PBD::ScopedConnection editor_freeze_connection;
PBD::ScopedConnection editor_thaw_connection;
bool expanded;
};
#endif /* __gtk_ardour_editor_regions_h__ */

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2000-2006 Paul Davis
Copyright (C) 2000-2018 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
@ -35,6 +35,7 @@
#include "editor.h"
#include "editor_drag.h"
#include "editor_routes.h"
#include "editor_sources.h"
#include "actions.h"
#include "audio_time_axis.h"
#include "audio_region_view.h"
@ -1214,6 +1215,7 @@ Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
bool have_selection = false;
bool have_entered = false;
bool have_edit_point = false;
bool have_selected_source = false;
RegionSelection rs;
// std::cerr << "STRRA: crossing ? " << because_canvas_crossing << " within ? " << within_track_canvas
@ -1229,6 +1231,10 @@ Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
rs.add (entered_regionview);
}
if ( _sources->get_single_selection() ) {
have_selected_source = true;
}
if (rs.empty() && !selection->tracks.empty()) {
/* no selected regions, but some selected tracks.
@ -1278,6 +1284,8 @@ Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
sensitive = true;
} else if ((tgt & EditPointRegions) && have_edit_point) {
sensitive = true;
} else if ((tgt & ListSelection) && have_selected_source ) {
sensitive = true;
}
x->second.action->set_sensitive (sensitive);
@ -1503,12 +1511,15 @@ Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
_region_actions->get_action("naturalize-region")->set_sensitive (false);
}
/* Todo: insert-region-from-source-list
/* XXX: should also check that there is a track of the appropriate type for the selected region */
#if 0
if (_edit_point == EditAtMouse || _regions->get_single_selection() == 0 || selection->tracks.empty()) {
_region_actions->get_action("insert-region-from-region-list")->set_sensitive (false);
_region_actions->get_action("insert-region-from-source-list")->set_sensitive (false);
} else {
_region_actions->get_action("insert-region-from-region-list")->set_sensitive (true);
_region_actions->get_action("insert-region-from-source-list")->set_sensitive (true);
}
#endif
a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-fade-in"));
a->set_active (have_active_fade_in && !have_inactive_fade_in);

View File

@ -0,0 +1,778 @@
/*
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 <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <sstream>
#include "pbd/basename.h"
#include "pbd/enumwriter.h"
#include "ardour/audioregion.h"
#include "ardour/source.h"
#include "ardour/audiofilesource.h"
#include "ardour/silentfilesource.h"
#include "ardour/region_factory.h"
#include "ardour/session.h"
#include "ardour/session_directory.h"
#include "ardour/profile.h"
#include "gtkmm2ext/treeutils.h"
#include "gtkmm2ext/utils.h"
#include "widgets/choice.h"
#include "widgets/tooltips.h"
#include "audio_clock.h"
#include "context_menu_helper.h"
#include "editor.h"
#include "editing.h"
#include "editing_convert.h"
#include "keyboard.h"
#include "ardour_ui.h"
#include "gui_thread.h"
#include "actions.h"
#include "region_view.h"
#include "utils.h"
#include "editor_drag.h"
#include "main_clock.h"
#include "ui_config.h"
#include "pbd/i18n.h"
#include "editor_sources.h"
using namespace std;
using namespace ARDOUR;
using namespace ArdourWidgets;
using namespace ARDOUR_UI_UTILS;
using namespace PBD;
using namespace Gtk;
using namespace Glib;
using namespace Editing;
using Gtkmm2ext::Keyboard;
struct ColumnInfo {
int index;
const char* label;
const char* tooltip;
};
EditorSources::EditorSources (Editor* e)
: EditorComponent (e)
, old_focus (0)
, _menu (0)
, _selection (0)
, _no_redisplay (false)
{
_display.set_size_request (100, -1);
_display.set_rules_hint (true);
_display.set_name ("SourcesList");
_display.set_fixed_height_mode (true);
/* Try to prevent single mouse presses from initiating edits.
This relies on a hack in gtktreeview.c:gtk_treeview_button_press()
*/
_display.set_data ("mouse-edits-require-mod1", (gpointer) 0x1);
_model = TreeStore::create (_columns);
_model->set_sort_column (0, SORT_ASCENDING);
/* column widths */
int bbt_width, date_width, height;
Glib::RefPtr<Pango::Layout> layout = _display.create_pango_layout (X_("000|000|000"));
Gtkmm2ext::get_pixel_size (layout, bbt_width, height);
Glib::RefPtr<Pango::Layout> layout2 = _display.create_pango_layout (X_("2018-10-14 12:12:30"));
Gtkmm2ext::get_pixel_size (layout2, date_width, height);
TreeViewColumn* col_name = manage (new TreeViewColumn ("", _columns.name));
col_name->set_fixed_width (bbt_width*2);
col_name->set_sizing (TREE_VIEW_COLUMN_FIXED);
col_name->set_sort_column(0);
TreeViewColumn* col_take_id = manage (new TreeViewColumn ("", _columns.take_id));
col_take_id->set_fixed_width (date_width);
col_take_id->set_sizing (TREE_VIEW_COLUMN_FIXED);
col_take_id->set_sort_column(1);
TreeViewColumn* col_nat_pos = manage (new TreeViewColumn ("", _columns.natural_pos));
col_nat_pos->set_fixed_width (bbt_width);
col_nat_pos->set_sizing (TREE_VIEW_COLUMN_FIXED);
col_nat_pos->set_sort_column(6);
TreeViewColumn* col_path = manage (new TreeViewColumn ("", _columns.path));
col_path->set_fixed_width (bbt_width);
col_path->set_sizing (TREE_VIEW_COLUMN_FIXED);
col_path->set_sort_column(3);
_display.append_column (*col_name);
_display.append_column (*col_take_id);
_display.append_column (*col_nat_pos);
_display.append_column (*col_path);
TreeViewColumn* col;
Gtk::Label* l;
ColumnInfo ci[] = {
{ 0, _("Source"), _("Source name, with number of channels in []'s") },
{ 1, _("Take ID"), _("Take ID") },
{ 2, _("Orig Pos"), _("Original Position of the file on timeline, when it was recorded") },
{ 3, _("Path"), _("Path (folder) of the file locationlosition of end of region") },
{ -1, 0, 0 }
};
for (int i = 0; ci[i].index >= 0; ++i) {
col = _display.get_column (ci[i].index);
l = manage (new Label (ci[i].label));
set_tooltip (*l, ci[i].tooltip);
col->set_widget (*l);
l->show ();
}
_display.set_model (_model);
_display.set_headers_visible (true);
_display.set_rules_hint ();
_display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorSources::selection_filter));
//set the color of the name field
TreeViewColumn* tv_col = _display.get_column(0);
CellRendererText* renderer = dynamic_cast<CellRendererText*>(_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_);
//right-align the Natural Pos column
TreeViewColumn* nat_col = _display.get_column(2);
nat_col->set_alignment (ALIGN_RIGHT);
renderer = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (2));
if (renderer) {
renderer->property_xalign() = ( 1.0 );
}
//the PATH field should expand when the pane is opened wider
tv_col = _display.get_column(3);
renderer = dynamic_cast<CellRendererText*>(_display.get_column_cell_renderer (3));
tv_col->add_attribute(renderer->property_text(), _columns.path);
tv_col->set_expand (true);
_display.get_selection()->set_mode (SELECTION_MULTIPLE);
_display.add_object_drag (_columns.region.index(), "regions");
_display.set_drag_column (_columns.name.index());
/* setup DnD handling */
list<TargetEntry> source_list_target_table;
source_list_target_table.push_back (TargetEntry ("text/plain"));
source_list_target_table.push_back (TargetEntry ("text/uri-list"));
source_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
_display.add_drop_targets (source_list_target_table);
_display.signal_drag_data_received().connect (sigc::mem_fun(*this, &EditorSources::drag_data_received));
_scroller.add (_display);
_scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
_display.signal_button_press_event().connect (sigc::mem_fun(*this, &EditorSources::button_press), false);
_change_connection = _display.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &EditorSources::selection_changed));
_scroller.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorSources::key_press), false);
_scroller.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditorSources::focus_in), false);
_scroller.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditorSources::focus_out));
_display.signal_enter_notify_event().connect (sigc::mem_fun (*this, &EditorSources::enter_notify), false);
_display.signal_leave_notify_event().connect (sigc::mem_fun (*this, &EditorSources::leave_notify), false);
ARDOUR_UI::instance()->primary_clock->mode_changed.connect (sigc::mem_fun(*this, &EditorSources::clock_format_changed));
e->EditorFreeze.connect (editor_freeze_connection, MISSING_INVALIDATOR, boost::bind (&EditorSources::freeze_tree_model, this), gui_context());
e->EditorThaw.connect (editor_thaw_connection, MISSING_INVALIDATOR, boost::bind (&EditorSources::thaw_tree_model, this), gui_context());
}
bool
EditorSources::focus_in (GdkEventFocus*)
{
Window* win = dynamic_cast<Window*> (_scroller.get_toplevel ());
if (win) {
old_focus = win->get_focus ();
} else {
old_focus = 0;
}
/* try to do nothing on focus in (doesn't work, hence selection_count nonsense) */
return true;
}
bool
EditorSources::focus_out (GdkEventFocus*)
{
if (old_focus) {
old_focus->grab_focus ();
old_focus = 0;
}
return false;
}
bool
EditorSources::enter_notify (GdkEventCrossing*)
{
/* arm counter so that ::selection_filter() will deny selecting anything for the
next two attempts to change selection status.
*/
_scroller.grab_focus ();
Keyboard::magic_widget_grab_focus ();
return false;
}
bool
EditorSources::leave_notify (GdkEventCrossing*)
{
if (old_focus) {
old_focus->grab_focus ();
old_focus = 0;
}
Keyboard::magic_widget_drop_focus ();
return false;
}
void
EditorSources::set_session (ARDOUR::Session* s)
{
SessionHandlePtr::set_session (s);
if (s) {
/* Currently, none of the displayed properties are mutable, so there is no reason to register for changes
* ARDOUR::Region::RegionPropertyChanged.connect (source_property_connection, MISSING_INVALIDATOR, boost::bind (&EditorSources::source_changed, this, _1, _2), gui_context());
*/
ARDOUR::RegionFactory::CheckNewRegion.connect (add_source_connection, MISSING_INVALIDATOR, boost::bind (&EditorSources::add_source, this, _1), gui_context());
s->SourceRemoved.connect (remove_source_connection, MISSING_INVALIDATOR, boost::bind (&EditorSources::remove_source, this, _1), gui_context());
redisplay();
} else {
clear();
}
}
void
EditorSources::remove_source (boost::shared_ptr<ARDOUR::Source> source)
{
TreeModel::iterator i;
TreeModel::Children rows = _model->children();
for (i = rows.begin(); i != rows.end(); ++i) {
boost::shared_ptr<ARDOUR::Region> rr = (*i)[_columns.region];
if (rr->source() == source) {
_model->erase(i);
break;
}
}
}
void
EditorSources::populate_row (TreeModel::Row row, boost::shared_ptr<ARDOUR::Region> region)
{
ENSURE_GUI_THREAD (*this, &ARDOUR_UI::record_state_changed, row, region);
if (!region) {
return;
}
boost::shared_ptr<ARDOUR::Source> source = region->source(); //ToDo: is it OK to use only the first source?
//COLOR (for missing files)
Gdk::Color c;
bool missing_source = boost::dynamic_pointer_cast<SilentFileSource>(source) != NULL;
if (missing_source) {
set_color_from_rgba (c, UIConfiguration::instance().color ("region list missing source"));
} else {
set_color_from_rgba (c, UIConfiguration::instance().color ("region list whole file"));
}
row[_columns.color_] = c;
//NAME
std::string str = region->name();
//if a multichannel region, show the number of channels ToDo: make a sortable column for this?
if ( region->n_channels() > 1 ) {
str += string_compose("[%1]", region->n_channels());
}
row[_columns.name] = str;
row[_columns.region] = region;
row[_columns.take_id] = source->take_id();
//PATH
if (missing_source) {
row[_columns.path] = _("(MISSING) ") + Gtkmm2ext::markup_escape_text (source->name());
} else {
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource>(source);
if (fs) {
const string sound_directory = _session->session_directory().sound_path();
if ( fs->path().find(sound_directory) == std::string::npos ) { // external file
row[_columns.path] = Gtkmm2ext::markup_escape_text (fs->path());
} else {
row[_columns.path] = source->name();
}
} else {
row[_columns.path] = Gtkmm2ext::markup_escape_text (source->name());
}
}
//Natural Position (samples, an invisible column for sorting)
row[_columns.natural_s] = source->natural_position();
//Natural Position (text representation)
if (source->have_natural_position()) {
char buf[64];
format_position (source->natural_position(), buf, sizeof (buf));
row[_columns.natural_pos] = buf;
} else {
row[_columns.natural_pos] = X_("--");
}
}
void
EditorSources::redisplay ()
{
if (_no_redisplay || !_session) {
return;
}
_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
_model->clear ();
_model->set_sort_column (-2, SORT_ASCENDING); //Disable sorting to gain performance
//Ask the region factory to fill our list of whole-file regions
RegionFactory::foreach_region (sigc::mem_fun (*this, &EditorSources::add_source));
_model->set_sort_column (0, SORT_ASCENDING); // re-enable sorting
_display.set_model (_model);
}
void
EditorSources::add_source (boost::shared_ptr<ARDOUR::Region> region)
{
if (!region || !_session ) {
return;
}
//by definition, the Source List only shows whole-file regions
//this roughly equates to Source objects, but preserves the stereo-ness (or multichannel-ness) of a stereo source file.
if ( !region->whole_file() ) {
return;
}
//we only show files-on-disk. if there's some other kind of source, we ignore it (for now)
boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (region->source());
if (!fs || fs->empty()) {
return;
}
TreeModel::Row row = *(_model->append());
populate_row (row, region);
}
void
EditorSources::source_changed (boost::shared_ptr<ARDOUR::Region> region)
{
/* Currently never reached .. we have no mutable properties shown in the list*/
TreeModel::iterator i;
TreeModel::Children rows = _model->children();
for (i = rows.begin(); i != rows.end(); ++i) {
boost::shared_ptr<ARDOUR::Region> rr = (*i)[_columns.region];
if (region == rr) {
populate_row(*i, region);
break;
}
}
}
void
EditorSources::selection_changed ()
{
if (_display.get_selection()->count_selected_rows() > 0) {
TreeIter iter;
TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
_editor->get_selection().clear_regions ();
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
if ((iter = _model->get_iter (*i))) {
//highlight any regions in the editor that use this region's source
boost::shared_ptr<ARDOUR::Region> region = (*iter)[_columns.region];
if (!region) continue;
boost::shared_ptr<ARDOUR::Source> source = region->source();
if (source) {
set<boost::shared_ptr<Region> > regions;
RegionFactory::get_regions_using_source ( source, regions );
for (set<boost::shared_ptr<Region> >::iterator region = regions.begin(); region != regions.end(); region++ ) {
_change_connection.block (true);
_editor->set_selected_regionview_from_region_list (*region, Selection::Add);
_change_connection.block (false);
}
}
}
}
} else {
_editor->get_selection().clear_regions ();
}
}
void
EditorSources::clock_format_changed ()
{
TreeModel::iterator i;
TreeModel::Children rows = _model->children();
for (i = rows.begin(); i != rows.end(); ++i) {
boost::shared_ptr<ARDOUR::Region> rr = (*i)[_columns.region];
populate_row(*i, rr);
}
}
void
EditorSources::format_position (samplepos_t pos, char* buf, size_t bufsize, bool onoff)
{
Timecode::BBT_Time bbt;
Timecode::Time timecode;
if (pos < 0) {
error << string_compose (_("EditorSources::format_position: negative timecode position: %1"), pos) << endmsg;
snprintf (buf, bufsize, "invalid");
return;
}
switch (ARDOUR_UI::instance()->primary_clock->mode ()) {
case AudioClock::BBT:
bbt = _session->tempo_map().bbt_at_sample (pos);
if (onoff) {
snprintf (buf, bufsize, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks);
} else {
snprintf (buf, bufsize, "(%03d|%02d|%04d)" , bbt.bars, bbt.beats, bbt.ticks);
}
break;
case AudioClock::MinSec:
samplepos_t left;
int hrs;
int mins;
float secs;
left = pos;
hrs = (int) floor (left / (_session->sample_rate() * 60.0f * 60.0f));
left -= (samplecnt_t) floor (hrs * _session->sample_rate() * 60.0f * 60.0f);
mins = (int) floor (left / (_session->sample_rate() * 60.0f));
left -= (samplecnt_t) floor (mins * _session->sample_rate() * 60.0f);
secs = left / (float) _session->sample_rate();
if (onoff) {
snprintf (buf, bufsize, "%02d:%02d:%06.3f", hrs, mins, secs);
} else {
snprintf (buf, bufsize, "(%02d:%02d:%06.3f)", hrs, mins, secs);
}
break;
case AudioClock::Seconds:
if (onoff) {
snprintf (buf, bufsize, "%.1f", pos / (float)_session->sample_rate());
} else {
snprintf (buf, bufsize, "(%.1f)", pos / (float)_session->sample_rate());
}
break;
case AudioClock::Samples:
if (onoff) {
snprintf (buf, bufsize, "%" PRId64, pos);
} else {
snprintf (buf, bufsize, "(%" PRId64 ")", pos);
}
break;
case AudioClock::Timecode:
default:
_session->timecode_time (pos, timecode);
if (onoff) {
snprintf (buf, bufsize, "%02d:%02d:%02d:%02d", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
} else {
snprintf (buf, bufsize, "(%02d:%02d:%02d:%02d)", timecode.hours, timecode.minutes, timecode.seconds, timecode.frames);
}
break;
}
}
void
EditorSources::show_context_menu (int button, int time)
{
using namespace Gtk::Menu_Helpers;
Gtk::Menu* menu = ARDOUR_UI_UTILS::shared_popup_menu ();
MenuList& items = menu->items();
#ifdef RECOVER_REGIONS_IS_WORKING
items.push_back(MenuElem(_("Recover the selected Sources to their original Track & Position"),
sigc::mem_fun(*this, &EditorSources::recover_selected_sources)));
#endif
items.push_back(MenuElem(_("Remove the selected Sources"),
sigc::mem_fun(*this, &EditorSources::remove_selected_sources)));
menu->popup(1, time);
}
void
EditorSources::recover_selected_sources ()
{
ARDOUR::RegionList to_be_recovered;
if (_display.get_selection()->count_selected_rows() > 0) {
TreeIter iter;
TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
if ((iter = _model->get_iter (*i))) {
boost::shared_ptr<ARDOUR::Region> region = (*iter)[_columns.region];
if (region) {
to_be_recovered.push_back(region);
}
}
}
}
/* ToDo */
_editor->recover_regions(to_be_recovered); //this operation should be undo-able
}
void
EditorSources::remove_selected_sources ()
{
vector<string> choices;
string prompt;
prompt = _("Do you want to remove the selected Sources?"
"\nThis operation cannot be undone."
"\nThe source files will not actually be deleted until you execute Session->Cleanup.");
choices.push_back (_("No, do nothing."));
choices.push_back (_("Only remove the Regions that use these Sources."));
choices.push_back (_("Yes, remove the Regions and Sources (cannot be undone!"));
Choice prompter (_("Remove selected Sources"), prompt, choices);
int opt = prompter.run ();
if ( opt >= 1) {
std::list<boost::weak_ptr<ARDOUR::Source> > to_be_removed;
if (_display.get_selection()->count_selected_rows() > 0) {
TreeIter iter;
TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
_editor->get_selection().clear_regions ();
for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
if ((iter = _model->get_iter (*i))) {
boost::shared_ptr<ARDOUR::Region> region = (*iter)[_columns.region];
if (!region) continue;
boost::shared_ptr<ARDOUR::Source> source = region->source();
if (source) {
set<boost::shared_ptr<Region> > regions;
RegionFactory::get_regions_using_source ( source, regions );
for (set<boost::shared_ptr<Region> >::iterator region = regions.begin(); region != regions.end(); region++ ) {
_change_connection.block (true);
_editor->set_selected_regionview_from_region_list (*region, Selection::Add);
_change_connection.block (false);
}
to_be_removed.push_back(source);
}
}
}
_editor->remove_selected_regions(); //this operation is undo-able
if (opt==2) {
for (std::list<boost::weak_ptr<ARDOUR::Source> >::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) {
_session->remove_source(*i); //this operation is (currently) not undo-able
}
}
}
}
}
bool
EditorSources::key_press (GdkEventKey* ev)
{
switch (ev->keyval) {
case GDK_Delete:
case GDK_BackSpace:
remove_selected_sources();
return true;
}
return false;
}
bool
EditorSources::button_press (GdkEventButton *ev)
{
boost::shared_ptr<ARDOUR::Region> 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 false;
}
return false;
}
void
EditorSources::selection_mapover (sigc::slot<void,boost::shared_ptr<Region> > sl)
{
}
void
EditorSources::drag_data_received (const RefPtr<Gdk::DragContext>& context,
int x, int y,
const SelectionData& data,
guint info, guint time)
{
/* ToDo: allow dropping files/loops into the source list? */
}
bool
EditorSources::selection_filter (const RefPtr<TreeModel>& model, const TreeModel::Path& path, bool already_selected)
{
return true;
}
/** @return Region that has been dragged out of the list, or 0 */
boost::shared_ptr<ARDOUR::Region>
EditorSources::get_dragged_region ()
{
list<boost::shared_ptr<ARDOUR::Region> > regions;
TreeView* region;
_display.get_object_drag_data (regions, &region);
if (regions.empty()) {
return boost::shared_ptr<ARDOUR::Region> ();
}
assert (regions.size() == 1);
return regions.front ();
}
void
EditorSources::clear ()
{
_display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
_model->clear ();
_display.set_model (_model);
}
boost::shared_ptr<ARDOUR::Region>
EditorSources::get_single_selection ()
{
Glib::RefPtr<TreeSelection> selected = _display.get_selection();
if (selected->count_selected_rows() != 1) {
return boost::shared_ptr<ARDOUR::Region> ();
}
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<ARDOUR::Region> ();
}
return (*iter)[_columns.region];
}
void
EditorSources::freeze_tree_model ()
{
_display.set_model (Glib::RefPtr<Gtk::TreeStore>(0));
_model->set_sort_column (-2, SORT_ASCENDING); //Disable sorting to gain performance
}
void
EditorSources::thaw_tree_model (){
_model->set_sort_column (0, SORT_ASCENDING); // renabale sorting
_display.set_model (_model);
}
XMLNode &
EditorSources::get_state () const
{
XMLNode* node = new XMLNode (X_("SourcesList"));
//TODO: save sort state?
return *node;
}
void
EditorSources::set_state (const XMLNode & node)
{
bool changed = false;
}

View File

@ -0,0 +1,159 @@
/*
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.
*/
#ifndef __gtk_ardour_editor_sources_h__
#define __gtk_ardour_editor_sources_h__
#include <boost/unordered_map.hpp>
#include <gtkmm/scrolledwindow.h>
#include <gtkmm/treemodel.h>
#include <gtkmm/treerowreference.h>
#include <gtkmm/treestore.h>
#include "editor_component.h"
#include "selection.h"
class EditorSources : public EditorComponent, public ARDOUR::SessionHandlePtr
{
public:
EditorSources (Editor *);
void set_session (ARDOUR::Session *);
void set_selection (Selection *sel) { _selection = sel; }
Gtk::Widget& widget () {
return _scroller;
}
void clear ();
void selection_mapover (sigc::slot<void,boost::shared_ptr<ARDOUR::Region> >);
boost::shared_ptr<ARDOUR::Region> get_dragged_region ();
boost::shared_ptr<ARDOUR::Region> get_single_selection ();
void block_change_connection (bool b) {
_change_connection.block (b);
}
void unselect_all () {
_display.get_selection()->unselect_all ();
}
//user actions
void remove_selected_sources ();
void recover_selected_sources();
XMLNode& get_state () const;
void set_state (const XMLNode &);
private:
struct Columns : public Gtk::TreeModel::ColumnRecord {
Columns () {
add (name);
add (take_id);
add (natural_pos);
add (path);
add (color_);
add (region);
add (natural_s);
}
Gtk::TreeModelColumn<std::string> name;
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
Gtk::TreeModelColumn<Gdk::Color> color_;
Gtk::TreeModelColumn<std::string> natural_pos;
Gtk::TreeModelColumn<std::string> path;
Gtk::TreeModelColumn<std::string> take_id;
Gtk::TreeModelColumn<samplepos_t> natural_s;
};
Columns _columns;
Gtk::TreeModel::RowReference last_row;
void freeze_tree_model ();
void thaw_tree_model ();
void source_changed (boost::shared_ptr<ARDOUR::Region>);
void populate_row (Gtk::TreeModel::Row row, boost::shared_ptr<ARDOUR::Region> region);
void selection_changed ();
sigc::connection _change_connection;
bool selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
Gtk::Widget* old_focus;
bool key_press (GdkEventKey *);
bool button_press (GdkEventButton *);
bool focus_in (GdkEventFocus*);
bool focus_out (GdkEventFocus*);
bool enter_notify (GdkEventCrossing*);
bool leave_notify (GdkEventCrossing*);
void show_context_menu (int button, int time);
void format_position (ARDOUR::samplepos_t pos, char* buf, size_t bufsize, bool onoff = true);
void add_source (boost::shared_ptr<ARDOUR::Region>);
void remove_source (boost::shared_ptr<ARDOUR::Source>);
void clock_format_changed ();
void redisplay ();
void suspend_redisplay () {
_no_redisplay = true;
}
void resume_redisplay () {
_no_redisplay = false;
redisplay ();
}
void drag_data_received (
Glib::RefPtr<Gdk::DragContext> const &, gint, gint, Gtk::SelectionData const &, guint, guint
);
Gtk::Menu* _menu;
Gtk::ScrolledWindow _scroller;
Gtk::Frame _frame;
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > _display;
Glib::RefPtr<Gtk::TreeStore> _model;
PBD::ScopedConnection source_property_connection;
PBD::ScopedConnection add_source_connection;
PBD::ScopedConnection remove_source_connection;
PBD::ScopedConnection editor_freeze_connection;
PBD::ScopedConnection editor_thaw_connection;
Selection* _selection;
bool _no_redisplay;
};
#endif /* __gtk_ardour_editor_regions_h__ */

View File

@ -990,7 +990,7 @@ ExportReport::audition (std::string path, unsigned n_chn, int page)
PBD::PropertyList plist;
plist.add (ARDOUR::Properties::start, 0);
plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->natural_position()));
plist.add (ARDOUR::Properties::name, rname);
plist.add (ARDOUR::Properties::layer, 0);

View File

@ -4204,7 +4204,7 @@ MidiRegionView::data_recorded (boost::weak_ptr<MidiSource> w)
/* convert from session samples to source beats */
Temporal::Beats const time_beats = _source_relative_time_converter.from(
ev.time() - src->timeline_position() + _region->start());
ev.time() - src->natural_position() + _region->start());
if (ev.type() == MIDI_CMD_NOTE_ON) {
boost::shared_ptr<NoteType> note (

View File

@ -316,6 +316,7 @@ public:
virtual bool scroll_down_one_track (bool skip_child_views = false) = 0;
virtual bool scroll_up_one_track (bool skip_child_views = false) = 0;
virtual void select_topmost_track () = 0;
virtual void cleanup_regions () = 0;
virtual void prepare_for_cleanup () = 0;
virtual void finish_cleanup () = 0;
virtual void reset_x_origin (samplepos_t sample) = 0;

View File

@ -342,7 +342,7 @@ SoundFileBox::setup_labels (const string& filename)
channels_value.set_text (to_string(ms->num_tracks()));
}
}
length_clock.set (ms->length(ms->timeline_position()));
length_clock.set (ms->length(ms->natural_position()));
switch (ms->num_tempos()) {
case 0:
tempomap_value.set_text (_("No tempo data"));
@ -497,7 +497,7 @@ SoundFileBox::audition ()
PropertyList plist;
plist.add (ARDOUR::Properties::start, 0);
plist.add (ARDOUR::Properties::length, ms->length(ms->timeline_position()));
plist.add (ARDOUR::Properties::length, ms->length(ms->natural_position()));
plist.add (ARDOUR::Properties::name, rname);
plist.add (ARDOUR::Properties::layer, 0);
@ -546,7 +546,7 @@ SoundFileBox::audition ()
PropertyList plist;
plist.add (ARDOUR::Properties::start, 0);
plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->timeline_position()));
plist.add (ARDOUR::Properties::length, srclist[0]->length(srclist[0]->natural_position()));
plist.add (ARDOUR::Properties::name, rname);
plist.add (ARDOUR::Properties::layer, 0);

View File

@ -91,6 +91,7 @@ gtk2_ardour_sources = [
'editor_rulers.cc',
'editor_selection.cc',
'editor_snapshots.cc',
'editor_sources.cc',
'editor_summary.cc',
'editor_tempodisplay.cc',
'editor_timefx.cc',

View File

@ -97,7 +97,7 @@ Analyser::work ()
boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource> (src);
if (afs && afs->length(afs->timeline_position())) {
if (afs && afs->length(afs->natural_position())) {
Glib::Threads::Mutex::Lock lm (analysis_active_lock);
analyse_audio_file_source (afs);
}

View File

@ -99,7 +99,7 @@ protected:
int init (const std::string& idstr, bool must_exist);
virtual void set_header_timeline_position () = 0;
virtual void set_header_natural_position () = 0;
virtual void handle_header_position_change () {}
int move_dependents_to_trash();

View File

@ -39,8 +39,7 @@
namespace ARDOUR {
class LIBARDOUR_API AudioSource : virtual public Source,
public ARDOUR::Readable,
public boost::enable_shared_from_this<ARDOUR::AudioSource>
public ARDOUR::Readable
{
public:
AudioSource (Session&, const std::string& name);
@ -65,9 +64,6 @@ class LIBARDOUR_API AudioSource : virtual public Source,
virtual bool can_truncate_peaks() const { return true; }
void set_captured_for (std::string str) { _captured_for = str; }
std::string captured_for() const { return _captured_for; }
int read_peaks (PeakData *peaks, samplecnt_t npeaks,
samplepos_t start, samplecnt_t cnt, double samples_per_visual_peak) const;
@ -125,7 +121,6 @@ class LIBARDOUR_API AudioSource : virtual public Source,
samplecnt_t _length;
std::string _peakpath;
std::string _captured_for;
int initialize_peakfile (const std::string& path, const bool in_session = false);
int build_peaks_from_scratch ();

View File

@ -43,7 +43,6 @@ class LIBARDOUR_API CAImportableSource : public ImportableSource {
samplecnt_t length() const;
samplecnt_t samplerate() const;
void seek (samplepos_t pos);
samplepos_t natural_position() const { return 0; }
bool clamped_at_unity () const { return false; }
protected:

View File

@ -46,7 +46,7 @@ class LIBARDOUR_API CoreAudioSource : public AudioFileSource {
uint32_t channel_count () const { return n_channels; }
int flush_header () {return 0;};
void set_header_timeline_position () {};
void set_header_natural_position () {};
bool clamped_at_unity () const { return false; }
void flush () {}

View File

@ -56,7 +56,6 @@ public:
void mark_immutable_except_write();
void mark_nonremovable ();
const std::string& take_id () const { return _take_id; }
bool within_session () const { return _within_session; }
uint16_t channel() const { return _channel; }
float gain() const { return _gain; }
@ -110,7 +109,6 @@ public:
void set_within_session_from_path (const std::string&);
std::string _path;
std::string _take_id;
bool _file_is_new;
uint16_t _channel;
bool _within_session;

View File

@ -43,7 +43,7 @@ class MidiStateTracker;
template<typename T> class MidiRingBuffer;
/** Source for MIDI data */
class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_shared_from_this<MidiSource>
class LIBARDOUR_API MidiSource : virtual public Source
{
public:
typedef Temporal::Beats TimeType;
@ -160,9 +160,6 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
virtual void session_saved();
std::string captured_for() const { return _captured_for; }
void set_captured_for (std::string str) { _captured_for = str; }
XMLNode& get_state ();
int set_state (const XMLNode&, int version);
@ -227,8 +224,6 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha
samplepos_t position,
samplecnt_t cnt) = 0;
std::string _captured_for;
boost::shared_ptr<MidiModel> _model;
bool _writing;

View File

@ -67,6 +67,7 @@ namespace Properties {
LIBARDOUR_API extern PBD::PropertyDescriptor<float> shift;
LIBARDOUR_API extern PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
LIBARDOUR_API extern PBD::PropertyDescriptor<uint64_t> layering_index;
LIBARDOUR_API extern PBD::PropertyDescriptor<std::string> tags;
};
class Playlist;
@ -282,6 +283,17 @@ public:
virtual boost::shared_ptr<const Evoral::Control>
control (const Evoral::Parameter& id) const = 0;
/* tags */
std::string tags() const { return _tags; }
virtual bool set_tags (const std::string& str) {
if (_tags != str) {
_tags = str;
PropertyChanged (PBD::PropertyChange (Properties::tags));
}
return true;
}
/* serialization */
XMLNode& get_state ();
@ -451,6 +463,7 @@ private:
PBD::Property<float> _shift;
PBD::EnumProperty<PositionLockStyle> _position_lock_style;
PBD::Property<uint64_t> _layering_index;
PBD::Property<std::string> _tags;
samplecnt_t _last_length;
samplepos_t _last_position;

View File

@ -86,6 +86,8 @@ public:
/** create a region with specified sources @param srcs and XML state */
static boost::shared_ptr<Region> create (SourceList& srcs, const XMLNode&);
static boost::shared_ptr<Region> get_whole_region_for_source (boost::shared_ptr<ARDOUR::Source>);
static void get_regions_using_source (boost::shared_ptr<Source>, std::set<boost::shared_ptr<Region> >& );
static void remove_regions_using_source (boost::shared_ptr<Source>);
@ -93,6 +95,15 @@ public:
static void delete_all_regions ();
static const RegionMap& regions() { return region_map; }
static uint32_t nregions ();
static void foreach_region (boost::function<void( boost::shared_ptr<Region> )> f) {
Glib::Threads::Mutex::Lock ls (region_map_lock);
for (RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
f ( (*i).second );
}
}
static int region_name (std::string &, std::string, bool new_level = false);
static std::string new_region_name (std::string);

View File

@ -780,6 +780,7 @@ public:
int destroy_sources (std::list<boost::shared_ptr<Source> >);
int remove_last_capture ();
void get_last_capture_sources (std::list<boost::shared_ptr<Source> >&);
/** handlers should return 0 for "everything OK", and any other value for
* "cannot setup audioengine".
@ -1754,8 +1755,22 @@ private:
mutable Glib::Threads::Mutex source_lock;
public:
/* Emited when a new source is added to the session */
PBD::Signal1< void, boost::shared_ptr<Source> > SourceAdded;
PBD::Signal1< void, boost::shared_ptr<Source> > SourceRemoved;
typedef std::map<PBD::ID,boost::shared_ptr<Source> > SourceMap;
void foreach_source (boost::function<void( boost::shared_ptr<Source> )> f) {
Glib::Threads::Mutex::Lock ls (source_lock);
for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
f ( (*i).second );
}
}
bool playlist_is_active( boost::shared_ptr<Playlist>);
private:
void reset_write_sources (bool mark_write_complete, bool force = false);
SourceMap sources;

View File

@ -59,7 +59,7 @@ protected:
samplecnt_t write_unlocked (Sample */*dst*/, samplecnt_t /*cnt*/) { return 0; }
void set_header_timeline_position () {}
void set_header_natural_position () {}
int read_peaks_with_fpp (PeakData *peaks, samplecnt_t npeaks, samplepos_t /*start*/, samplecnt_t /*cnt*/,
double /*samples_per_pixel*/, samplecnt_t /*fpp*/) const {

View File

@ -37,9 +37,9 @@ public:
uint32_t channels() const;
samplecnt_t length() const;
samplecnt_t samplerate() const;
void seek (samplepos_t pos);
samplepos_t natural_position() const;
bool clamped_at_unity () const;
void seek (samplepos_t pos);
bool clamped_at_unity () const;
samplepos_t natural_position () const;
protected:
SF_INFO sf_info;

View File

@ -60,8 +60,6 @@ class LIBARDOUR_API SndFileSource : public AudioFileSource {
int flush_header ();
void flush ();
samplepos_t natural_position () const;
samplepos_t last_capture_start_sample() const;
void mark_capture_start (samplepos_t);
void mark_capture_end ();
@ -81,7 +79,7 @@ class LIBARDOUR_API SndFileSource : public AudioFileSource {
void close ();
void set_path (const std::string& p);
void set_header_timeline_position ();
void set_header_natural_position ();
samplecnt_t read_unlocked (Sample *dst, samplepos_t start, samplecnt_t cnt) const;
samplecnt_t write_unlocked (Sample *dst, samplecnt_t cnt);
@ -111,7 +109,7 @@ class LIBARDOUR_API SndFileSource : public AudioFileSource {
Sample* xfade_buf;
samplecnt_t crossfade (Sample* data, samplecnt_t cnt, int dir);
void set_timeline_position (samplepos_t);
void set_natural_position (samplepos_t);
samplecnt_t destructive_write_unlocked (Sample *dst, samplecnt_t cnt);
samplecnt_t nondestructive_write_unlocked (Sample *dst, samplecnt_t cnt);
void handle_header_position_change ();

View File

@ -25,6 +25,8 @@
#include <glibmm/threads.h>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp>
#include "pbd/statefuldestructible.h"
@ -36,7 +38,8 @@ namespace ARDOUR {
class Session;
class LIBARDOUR_API Source : public SessionObject
class LIBARDOUR_API Source : public SessionObject,
public boost::enable_shared_from_this<ARDOUR::Source>
{
public:
enum Flag {
@ -68,7 +71,8 @@ public:
virtual samplecnt_t length (samplepos_t pos) const = 0;
virtual void update_length (samplecnt_t cnt) = 0;
virtual samplepos_t natural_position() const { return 0; }
void set_take_id (std::string id) { _take_id =id; }
const std::string& take_id () const { return _take_id; }
void mark_for_remove();
@ -98,8 +102,9 @@ public:
std::string get_transients_path() const;
int load_transients (const std::string&);
samplepos_t timeline_position() const { return _timeline_position; }
virtual void set_timeline_position (samplepos_t pos);
virtual samplepos_t natural_position() const { return _natural_position; }
virtual void set_natural_position (samplepos_t pos);
bool have_natural_position() const { return _have_natural_position; }
void set_allow_remove_if_empty (bool yn);
@ -114,23 +119,29 @@ public:
uint32_t level() const { return _level; }
std::string ancestor_name() { return _ancestor_name.empty() ? name() : _ancestor_name; }
void set_ancestor_name(const std::string& name) { _ancestor_name = name; }
void set_ancestor_name(const std::string& name) { _ancestor_name = name; }
protected:
DataType _type;
Flag _flags;
time_t _timestamp;
samplepos_t _timeline_position;
bool _analysed;
void set_captured_for (std::string str) { _captured_for = str; }
std::string captured_for() const { return _captured_for; }
mutable Glib::Threads::Mutex _lock;
mutable Glib::Threads::Mutex _analysis_lock;
static PBD::Signal1<void,boost::shared_ptr<ARDOUR::Source> > SourcePropertyChanged;
gint _use_count; /* atomic */
uint32_t _level; /* how deeply nested is this source w.r.t a disk file */
std::string _ancestor_name;
protected:
DataType _type;
Flag _flags;
time_t _timestamp;
std::string _take_id;
samplepos_t _natural_position;
samplepos_t _have_natural_position;
bool _analysed;
mutable Glib::Threads::Mutex _lock;
mutable Glib::Threads::Mutex _analysis_lock;
gint _use_count; /* atomic */
uint32_t _level; /* how deeply nested is this source w.r.t a disk file */
std::string _ancestor_name;
std::string _captured_for;
private:
private:
void fix_writable_flags ();
};

View File

@ -38,7 +38,7 @@ public:
int update_header (samplepos_t /*when*/, struct tm&, time_t) { return 0; }
int flush_header () { return 0; }
void flush () { }
void set_header_timeline_position () {};
void set_header_natural_position () {};
void set_length (samplecnt_t /*len*/) {};
float sample_rate () const { return _session.nominal_sample_rate(); }

View File

@ -441,7 +441,7 @@ AudioTrack::freeze_me (InterThreadInfo& itt)
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, srcs[0]->length(srcs[0]->timeline_position()));
plist.add (Properties::length, srcs[0]->length(srcs[0]->natural_position()));
plist.add (Properties::name, region_name);
plist.add (Properties::whole_file, true);

View File

@ -462,7 +462,7 @@ AudioRegion::master_read_at (Sample *buf, Sample* /*mixdown_buffer*/, float* /*g
assert (cnt >= 0);
return read_from_sources (
_master_sources, _master_sources.front()->length (_master_sources.front()->timeline_position()),
_master_sources, _master_sources.front()->length (_master_sources.front()->natural_position()),
buf, position, cnt, chan_n
);
}

View File

@ -267,7 +267,7 @@ AudioSource::initialize_peakfile (const string& audio_path, const bool in_sessio
/* we found it in the peaks dir, so check it out */
if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_timeline_position) / _FPP) * sizeof (PeakData)))) {
if (statbuf.st_size == 0 || (statbuf.st_size < (off_t) ((length(_natural_position) / _FPP) * sizeof (PeakData)))) {
DEBUG_TRACE(DEBUG::Peaks, string_compose("Peakfile %1 is empty\n", _peakpath));
_peaks_built = false;
} else {
@ -1067,7 +1067,7 @@ samplecnt_t
AudioSource::available_peaks (double zoom_factor) const
{
if (zoom_factor < _FPP) {
return length(_timeline_position); // peak data will come from the audio file
return length(_natural_position); // peak data will come from the audio file
}
/* peak data comes from peakfile, but the filesize might not represent

View File

@ -328,7 +328,7 @@ void
DiskWriter::non_realtime_locate (samplepos_t position)
{
if (_midi_write_source) {
_midi_write_source->set_timeline_position (position);
_midi_write_source->set_natural_position (position);
}
DiskIOProcessor::non_realtime_locate (position);
@ -1216,6 +1216,10 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
as->set_captured_for (_name.val());
as->mark_immutable ();
char buf[128];
strftime (buf, sizeof(buf), "%F %H.%M.%S", &when);
as->set_take_id ( buf );
if (Config->get_auto_analyse_audio()) {
Analyser::queue_source_for_analysis (as, true);
}
@ -1226,6 +1230,11 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
if (_midi_write_source) {
midi_srcs.push_back (_midi_write_source);
}
(*chan)->write_source->stamp (twhen);
/* "re-announce the source to the world */
Source::SourcePropertyChanged ((*chan)->write_source);
}
@ -1255,9 +1264,13 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo
midi_srcs.push_back (_midi_write_source);
_midi_write_source->set_timeline_position (capture_info.front()->start);
_midi_write_source->set_natural_position (capture_info.front()->start);
_midi_write_source->set_captured_for (_name);
char buf[128];
strftime (buf, sizeof(buf), "%F %H.%M.%S", &when);
_midi_write_source->set_take_id ( buf );
/* set length in beats to entire capture length */
BeatsSamplesConverter converter (_session.tempo_map(), capture_info.front()->start);

View File

@ -116,8 +116,6 @@ FileSource::removable () const
int
FileSource::init (const string& pathstr, bool must_exist)
{
_timeline_position = 0;
if (Stateful::loading_state_version < 3000) {
if (!find_2X (_session, _type, pathstr, must_exist, _file_is_new, _channel, _path)) {
throw MissingSource (pathstr, _type);

View File

@ -119,7 +119,7 @@ Filter::finish (boost::shared_ptr<Region> region, SourceList& nsrcs, string regi
boost::shared_ptr<SMFSource> smfs = boost::dynamic_pointer_cast<SMFSource>(*si);
if (smfs) {
smfs->set_timeline_position (region->position());
smfs->set_natural_position (region->position());
smfs->flush ();
}

View File

@ -184,7 +184,7 @@ static bool
create_mono_sources_for_writing (const vector<string>& new_paths,
Session& sess, uint32_t samplerate,
vector<boost::shared_ptr<Source> >& newfiles,
samplepos_t timeline_position)
samplepos_t natural_position)
{
for (vector<string>::const_iterator i = new_paths.begin(); i != new_paths.end(); ++i) {
@ -212,7 +212,7 @@ create_mono_sources_for_writing (const vector<string>& new_paths,
boost::shared_ptr<AudioFileSource> afs;
if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
afs->set_timeline_position(timeline_position);
afs->set_natural_position (natural_position);
}
}
return true;

View File

@ -1285,7 +1285,7 @@ LuaBindings::common (lua_State* L)
.addFunction ("writable", &Source::writable)
.addFunction ("has_been_analysed", &Source::has_been_analysed)
.addFunction ("can_be_analysed", &Source::can_be_analysed)
.addFunction ("timeline_position", &Source::timeline_position)
.addFunction ("timeline_position", &Source::natural_position) /* duplicate */
.addFunction ("use_count", &Source::use_count)
.addFunction ("used", &Source::used)
.addFunction ("ancestor_name", &Source::ancestor_name)

View File

@ -352,7 +352,7 @@ MidiSource::mark_write_starting_now (samplecnt_t position,
because it is not RT-safe.
*/
set_timeline_position(position);
set_natural_position (position);
_capture_length = capture_length;
_capture_loop_length = loop_length;
@ -417,7 +417,7 @@ MidiSource::write_to (const Lock& lock, boost::shared_ptr<MidiSource> newsrc, Te
{
Lock newsrc_lock (newsrc->mutex ());
newsrc->set_timeline_position (_timeline_position);
newsrc->set_natural_position (_natural_position);
newsrc->copy_interpolation_from (this);
newsrc->copy_automation_state_from (this);

View File

@ -601,6 +601,7 @@ Playlist::flush_notifications (bool from_undo)
crossfade_ranges.push_back ((*s)->range ());
remove_dependents (*s);
RegionRemoved (boost::weak_ptr<Region> (*s)); /* EMIT SIGNAL */
Region::RegionPropertyChanged(*s, Properties::hidden);
}
for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {

View File

@ -75,6 +75,7 @@ namespace ARDOUR {
PBD::PropertyDescriptor<float> shift;
PBD::PropertyDescriptor<PositionLockStyle> position_lock_style;
PBD::PropertyDescriptor<uint64_t> layering_index;
PBD::PropertyDescriptor<std::string> tags;
}
}
@ -134,7 +135,9 @@ Region::make_property_quarks ()
Properties::position_lock_style.property_id = g_quark_from_static_string (X_("positional-lock-style"));
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for position_lock_style = %1\n", Properties::position_lock_style.property_id));
Properties::layering_index.property_id = g_quark_from_static_string (X_("layering-index"));
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id));
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for layering_index = %1\n", Properties::layering_index.property_id));
Properties::tags.property_id = g_quark_from_static_string (X_("tags"));
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for tags = %1\n", Properties::tags.property_id));
}
void
@ -167,6 +170,7 @@ Region::register_properties ()
add_property (_shift);
add_property (_position_lock_style);
add_property (_layering_index);
add_property (_tags);
}
#define REGION_DEFAULT_STATE(s,l) \
@ -199,7 +203,8 @@ Region::register_properties ()
, _stretch (Properties::stretch, 1.0) \
, _shift (Properties::shift, 1.0) \
, _position_lock_style (Properties::position_lock_style, _type == DataType::AUDIO ? AudioTime : MusicTime) \
, _layering_index (Properties::layering_index, 0)
, _layering_index (Properties::layering_index, 0) \
, _tags (Properties::tags, "")
#define REGION_COPY_STATE(other) \
_sync_marked (Properties::sync_marked, other->_sync_marked) \
@ -233,7 +238,8 @@ Region::register_properties ()
, _stretch (Properties::stretch, other->_stretch) \
, _shift (Properties::shift, other->_shift) \
, _position_lock_style (Properties::position_lock_style, other->_position_lock_style) \
, _layering_index (Properties::layering_index, other->_layering_index)
, _layering_index (Properties::layering_index, other->_layering_index) \
, _tags (Properties::tags, other->_tags)
/* derived-from-derived constructor (no sources in constructor) */
Region::Region (Session& s, samplepos_t start, samplecnt_t length, const string& name, DataType type)
@ -1555,6 +1561,7 @@ Region::set_master_sources (const SourceList& srcs)
for (SourceList::const_iterator i = _master_sources.begin (); i != _master_sources.end(); ++i) {
(*i)->inc_use_count ();
// Source::SourcePropertyChanged( *i );
}
}
@ -1981,3 +1988,4 @@ Region::latest_possible_sample () const
return _position + (minlen - _start) - 1;
}

View File

@ -126,7 +126,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const PropertyList& pli
ret->apply_changes (plist);
if (ret->session().config.get_glue_new_regions_to_bars_and_beats() && ret->position_lock_style() != MusicTime) {
ret->set_position_lock_style (MusicTime);
ret->set_position_lock_style (MusicTime);
}
if (announce) {
@ -194,7 +194,7 @@ RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
if ((other = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
// XXX use me in caller where plist is setup, this is start i think srcs.front()->length (srcs.front()->timeline_position())
// XXX use me in caller where plist is setup, this is start i think srcs.front()->length (srcs.front()->natural_position())
ret = boost::shared_ptr<Region> (new AudioRegion (other, srcs));
@ -629,6 +629,20 @@ RegionFactory::new_region_name (string old)
return old;
}
boost::shared_ptr<Region>
RegionFactory::get_whole_region_for_source (boost::shared_ptr<Source> s)
{
Glib::Threads::Mutex::Lock lm (region_map_lock);
for (RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
if (i->second->uses_source (s) && i->second->whole_file()) {
return (i->second);
}
}
return boost::shared_ptr<Region>();
}
void
RegionFactory::get_regions_using_source (boost::shared_ptr<Source> s, std::set<boost::shared_ptr<Region> >& r)
{

View File

@ -4789,6 +4789,7 @@ Session::destroy_sources (list<boost::shared_ptr<Source> > srcs)
(*s)->mark_for_remove ();
(*s)->drop_references ();
SourceRemoved(*s);
s = srcs.erase (s);
}
@ -4823,6 +4824,25 @@ Session::remove_last_capture ()
return 0;
}
void
Session::get_last_capture_sources (std::list<boost::shared_ptr<Source> >& srcs)
{
boost::shared_ptr<RouteList> rl = routes.reader ();
for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
if (!tr) {
continue;
}
list<boost::shared_ptr<Source> >& l = tr->last_capture_sources();
if (!l.empty()) {
srcs.insert (srcs.end(), l.begin(), l.end());
l.clear ();
}
}
}
/* Source Management */
void
@ -4862,6 +4882,8 @@ Session::add_source (boost::shared_ptr<Source> source)
}
source->DropReferences.connect_same_thread (*this, boost::bind (&Session::remove_source, this, boost::weak_ptr<Source> (source)));
SourceAdded(source);
}
}
@ -4884,6 +4906,7 @@ Session::remove_source (boost::weak_ptr<Source> src)
if ((i = sources.find (source->id())) != sources.end()) {
sources.erase (i);
SourceRemoved(source);
}
}
@ -5374,6 +5397,17 @@ Session::create_midi_source_by_stealing_name (boost::shared_ptr<Track> track)
DataType::MIDI, *this, path, false, sample_rate()));
}
bool
Session::playlist_is_active (boost::shared_ptr<Playlist> playlist)
{
Glib::Threads::Mutex::Lock lm (_playlists->lock);
for (SessionPlaylists::List::iterator i = _playlists->playlists.begin(); i != _playlists->playlists.end(); i++) {
if ( (*i) == playlist ) {
return true;
}
}
return false;
}
void
Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused)
@ -6148,7 +6182,7 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
goto out;
}
legal_playlist_name = legalize_for_path (playlist->name());
legal_playlist_name = "(BOUNCE) " + legalize_for_path (playlist->name());
for (uint32_t chan_n = 0; chan_n < diskstream_channels.n(data_type); ++chan_n) {
@ -6240,7 +6274,7 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
if (!endpoint || for_export) {
ev.set_time(ev.time() - position);
}
ms->append_event_samples(lock, ev, ms->timeline_position());
ms->append_event_samples(lock, ev, ms->natural_position());
}
}
}
@ -6294,10 +6328,11 @@ Session::write_one_track (Track& track, samplepos_t start, samplepos_t end,
PropertyList plist;
plist.add (Properties::start, 0);
plist.add (Properties::length, srcs.front()->length(srcs.front()->timeline_position()));
plist.add (Properties::whole_file, true);
plist.add (Properties::length, srcs.front()->length(srcs.front()->natural_position()));
plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true));
result = RegionFactory::create (srcs, plist);
result = RegionFactory::create (srcs, plist, true);
}

View File

@ -3411,7 +3411,7 @@ Session::cleanup_sources (CleanupReport& rep)
* capture files.
*/
if (!i->second->used() && (i->second->length(i->second->timeline_position()) > 0)) {
if (!i->second->used() && (i->second->length(i->second->natural_position()) > 0)) {
dead_sources.push_back (i->second);
i->second->drop_references ();
}

View File

@ -622,7 +622,8 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload
}
if (!_model) {
_model = boost::shared_ptr<MidiModel> (new MidiModel (shared_from_this ()));
boost::shared_ptr<SMFSource> smf = boost::dynamic_pointer_cast<SMFSource> ( shared_from_this () );
_model = boost::shared_ptr<MidiModel> (new MidiModel (smf));
} else {
_model->clear();
}

View File

@ -350,7 +350,7 @@ SndFileSource::init_sndfile ()
if (destructive()) {
xfade_buf = new Sample[xfade_samples];
_timeline_position = header_position_offset;
_natural_position = header_position_offset;
}
AudioFileSource::HeaderPositionOffsetChanged.connect_same_thread (header_position_connection, boost::bind (&SndFileSource::handle_header_position_change, this));
@ -447,15 +447,22 @@ SndFileSource::open ()
if (_file_is_new && _length == 0 && writable() && !bwf_info_exists) {
/* newly created files will not have a BWF header at this point in time.
* Import will have called Source::set_timeline_position() if one exists
* Import will have called Source::set_natural_position() if one exists
* in the original. */
header_position_offset = _timeline_position;
header_position_offset = _natural_position;
}
/* Set our timeline position to either the time reference from a BWF header or the current
start of the session.
*/
set_timeline_position (bwf_info_exists ? _broadcast_info->get_time_reference() : header_position_offset);
if (destructive()) {
/* Set our timeline position to either the time reference from a BWF header or the current
start of the session.
*/
set_natural_position (bwf_info_exists ? _broadcast_info->get_time_reference() : header_position_offset);
} else {
/* If a BWF header exists, set our _natural_position from it */
if (bwf_info_exists) {
set_natural_position (_broadcast_info->get_time_reference());
}
}
if (_length != 0 && !bwf_info_exists) {
delete _broadcast_info;
@ -668,7 +675,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, samplecnt_t cnt)
_capture_end = false;
/* move to the correct location place */
file_pos = capture_start_sample - _timeline_position;
file_pos = capture_start_sample - _natural_position;
// split cnt in half
samplecnt_t subcnt = cnt / 2;
@ -700,7 +707,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, samplecnt_t cnt)
_capture_end = false;
/* move to the correct location place */
file_pos = capture_start_sample - _timeline_position;
file_pos = capture_start_sample - _natural_position;
if (crossfade (data, cnt, 1) != cnt) {
return 0;
@ -742,7 +749,7 @@ SndFileSource::destructive_write_unlocked (Sample* data, samplecnt_t cnt)
int
SndFileSource::update_header (samplepos_t when, struct tm& now, time_t tnow)
{
set_timeline_position (when);
set_natural_position (when);
if (_flags & Broadcast) {
if (setup_broadcast_info (when, now, tnow)) {
@ -810,20 +817,20 @@ SndFileSource::setup_broadcast_info (samplepos_t /*when*/, struct tm& now, time_
/* now update header position taking header offset into account */
set_header_timeline_position ();
set_header_natural_position ();
return 0;
}
void
SndFileSource::set_header_timeline_position ()
SndFileSource::set_header_natural_position ()
{
if (!(_flags & Broadcast)) {
return;
}
assert (_broadcast_info);
_broadcast_info->set_time_reference (_timeline_position);
_broadcast_info->set_time_reference (_natural_position);
if (_sndfile == 0 || !_broadcast_info->write_to_file (_sndfile)) {
error << string_compose (_("cannot set broadcast info for audio file %1 (%2); dropping broadcast info for this file"),
@ -855,12 +862,6 @@ SndFileSource::write_float (Sample* data, samplepos_t sample_pos, samplecnt_t cn
return cnt;
}
samplepos_t
SndFileSource::natural_position() const
{
return _timeline_position;
}
void
SndFileSource::clear_capture_marks ()
{
@ -873,7 +874,7 @@ void
SndFileSource::mark_capture_start (samplepos_t pos)
{
if (destructive()) {
if (pos < _timeline_position) {
if (pos < _natural_position) {
_capture_start = false;
} else {
_capture_start = true;
@ -1031,8 +1032,8 @@ SndFileSource::handle_header_position_change ()
error << string_compose(_("Filesource: start time is already set for existing file (%1): Cannot change start time."), _path ) << endmsg;
//in the future, pop up a dialog here that allows user to regenerate file with new start offset
} else if (writable()) {
_timeline_position = header_position_offset;
set_header_timeline_position (); //this will get flushed if/when the file is recorded to
_natural_position = header_position_offset;
set_header_natural_position (); //this will get flushed if/when the file is recorded to
}
}
}
@ -1056,14 +1057,14 @@ SndFileSource::setup_standard_crossfades (Session const & s, samplecnt_t rate)
}
void
SndFileSource::set_timeline_position (samplepos_t pos)
SndFileSource::set_natural_position (samplepos_t pos)
{
// destructive track timeline postion does not change
// except at instantion or when header_position_offset
// (session start) changes
if (!destructive()) {
AudioFileSource::set_timeline_position (pos);
AudioFileSource::set_natural_position (pos);
}
}
@ -1149,4 +1150,3 @@ SndFileSource::set_path (const string& p)
{
FileSource::set_path (p);
}

View File

@ -52,12 +52,16 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
PBD::Signal1<void,boost::shared_ptr<ARDOUR::Source> > Source::SourcePropertyChanged;
Source::Source (Session& s, DataType type, const string& name, Flag flags)
: SessionObject(s, name)
, _type(type)
, _flags(flags)
, _timeline_position(0)
, _use_count (0)
, _natural_position(0)
, _have_natural_position (false)
, _use_count (0)
, _level (0)
{
_analysed = false;
@ -69,7 +73,8 @@ Source::Source (Session& s, const XMLNode& node)
: SessionObject(s, "unnamed source")
, _type(DataType::AUDIO)
, _flags (Flag (Writable|CanRename))
, _timeline_position(0)
, _natural_position(0)
, _have_natural_position (false)
, _use_count (0)
, _level (0)
{
@ -102,12 +107,18 @@ Source::get_state ()
XMLNode *node = new XMLNode ("Source");
node->set_property ("name", name());
node->set_property ("take-id", take_id());
node->set_property ("type", _type);
node->set_property (X_("flags"), _flags);
node->set_property ("id", id());
if (_timestamp != 0) {
node->set_property ("timestamp", (int64_t)_timestamp);
int64_t t = _timestamp;
node->set_property ("timestamp", t);
}
if (_have_natural_position) {
node->set_property ("natural-position", _natural_position);
}
return *node;
@ -131,13 +142,29 @@ Source::set_state (const XMLNode& node, int version)
int64_t t;
if (node.get_property ("timestamp", t)) {
_timestamp = t;
_timestamp = (time_t) t;
}
samplepos_t ts;
if (node.get_property ("natural-position", ts)) {
_natural_position = ts;
_have_natural_position = true;
} else if (node.get_property ("timeline-position", ts)) {
/* some older versions of ardour might have stored this with
this property name.
*/
_natural_position = ts;
_have_natural_position = true;
}
if (!node.get_property (X_("flags"), _flags)) {
_flags = Flag (0);
}
if (!node.get_property (X_("take-id"), _take_id)) {
_take_id = "";
}
/* old style, from the period when we had DestructiveFileSource */
if (node.get_property (X_("destructive"), str)) {
_flags = Flag (_flags | Destructive);
@ -265,9 +292,10 @@ Source::mark_for_remove ()
}
void
Source::set_timeline_position (samplepos_t pos)
Source::set_natural_position (samplepos_t pos)
{
_timeline_position = pos;
_natural_position = pos;
_have_natural_position = true;
}
void
@ -287,7 +315,14 @@ Source::set_allow_remove_if_empty (bool yn)
void
Source::inc_use_count ()
{
g_atomic_int_inc (&_use_count);
g_atomic_int_inc (&_use_count);
try {
boost::shared_ptr<Source> sptr = shared_from_this();
SourcePropertyChanged (sptr);
} catch (...) {
/* no shared_ptr available, relax; */
}
}
void
@ -303,6 +338,13 @@ Source::dec_use_count ()
#else
g_atomic_int_add (&_use_count, -1);
#endif
try {
boost::shared_ptr<Source> sptr = shared_from_this();
SourcePropertyChanged (sptr);
} catch (...) {
/* no shared_ptr available, relax; */
}
}
bool
@ -310,4 +352,3 @@ Source::writable () const
{
return (_flags & Writable) && _session.writable();
}

View File

@ -626,6 +626,13 @@ Track::find_and_use_playlist (DataType dt, PBD::ID const & id)
return use_playlist (dt, playlist);
}
void
update_region_visibility(boost::shared_ptr<Region> r)
{
Region::RegionPropertyChanged(r, Properties::hidden);
}
int
Track::use_playlist (DataType dt, boost::shared_ptr<Playlist> p)
{
@ -637,9 +644,15 @@ Track::use_playlist (DataType dt, boost::shared_ptr<Playlist> p)
}
}
boost::shared_ptr<Playlist> old = _playlists[dt];
if (ret == 0) {
_playlists[dt] = p;
}
//allow all regions of prior and new playlists to update their visibility?
if (old) old->foreach_region(update_region_visibility);
if (p) p->foreach_region(update_region_visibility);
_session.set_dirty ();
PlaylistChanged (); /* EMIT SIGNAL */

View File

@ -76,7 +76,7 @@ write_bbt_source_to_source (boost::shared_ptr<MidiSource> bbt_source, boost::sh
bbt_source->model()->set_percussive (old_percussive);
source->mark_streaming_write_completed (source_lock);
source->set_timeline_position (bbt_source->timeline_position());
source->set_natural_position (bbt_source->natural_position());
return true;
}