Compare commits
24 Commits
master
...
bens-sourc
Author | SHA1 | Date |
---|---|---|
Ben Loftis | a53da91c46 | |
Ben Loftis | a5c18d7338 | |
Ben Loftis | db95fb6b23 | |
Ben Loftis | 422e46e9c8 | |
Ben Loftis | 8dea1a033d | |
Ben Loftis | 29865677b8 | |
Ben Loftis | b23be53514 | |
Ben Loftis | 81f8bb24ff | |
Ben Loftis | e3b8a70cbb | |
Ben Loftis | 6a8ce91bd0 | |
Ben Loftis | c5eeea95c4 | |
Ben Loftis | 1ccc7454e1 | |
Paul Davis | aae54f1cc9 | |
Ben Loftis | 9e21d683a4 | |
Ben Loftis | edc91f3546 | |
Ben Loftis | d2dbf364a6 | |
Ben Loftis | 9a6194218e | |
Ben Loftis | 433f275c96 | |
Ben Loftis | 102555bb34 | |
Ben Loftis | 4f6d53aa32 | |
Ben Loftis | 74dd35f4b9 | |
Ben Loftis | 4a4ac0d867 | |
Ben Loftis | bdf1b54093 | |
Ben Loftis | ea9ea68c9d |
|
@ -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
|
||||
|
|
|
@ -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'/>
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, ®ion);
|
||||
|
||||
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;
|
||||
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 () {}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue