1 /* 2 * Copyright (C) 2000-2017 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2006-2014 David Robillard <d@drobilla.net> 4 * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net> 5 * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org> 6 * Copyright (C) 2015-2017 Nick Mainsbridge <mainsbridge@gmail.com> 7 * Copyright (C) 2018 Ben Loftis <ben@harrisonconsoles.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write to the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 */ 23 24 #ifndef __ardour_region_h__ 25 #define __ardour_region_h__ 26 27 #include <vector> 28 #include <boost/shared_ptr.hpp> 29 #include <boost/enable_shared_from_this.hpp> 30 #include <boost/utility.hpp> 31 32 #include "pbd/undo.h" 33 #include "pbd/signals.h" 34 #include "ardour/ardour.h" 35 #include "ardour/data_type.h" 36 #include "ardour/automatable.h" 37 #include "ardour/movable.h" 38 #include "ardour/readable.h" 39 #include "ardour/session_object.h" 40 #include "ardour/trimmable.h" 41 #include "ardour/types_convert.h" 42 43 class XMLNode; 44 45 namespace ARDOUR { 46 47 namespace Properties { 48 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> muted; 49 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> opaque; 50 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> locked; 51 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> video_locked; 52 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> automatic; 53 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> whole_file; 54 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> import; 55 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> external; 56 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> sync_marked; 57 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> left_of_split; 58 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> right_of_split; 59 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> hidden; 60 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> position_locked; 61 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> valid_transients; 62 LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> start; 63 LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> length; 64 LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> position; 65 LIBARDOUR_API extern PBD::PropertyDescriptor<double> beat; 66 LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> sync_position; 67 LIBARDOUR_API extern PBD::PropertyDescriptor<layer_t> layer; 68 LIBARDOUR_API extern PBD::PropertyDescriptor<samplepos_t> ancestral_start; 69 LIBARDOUR_API extern PBD::PropertyDescriptor<samplecnt_t> ancestral_length; 70 LIBARDOUR_API extern PBD::PropertyDescriptor<float> stretch; 71 LIBARDOUR_API extern PBD::PropertyDescriptor<float> shift; 72 LIBARDOUR_API extern PBD::PropertyDescriptor<PositionLockStyle> position_lock_style; 73 LIBARDOUR_API extern PBD::PropertyDescriptor<uint64_t> layering_index; 74 LIBARDOUR_API extern PBD::PropertyDescriptor<std::string> tags; 75 LIBARDOUR_API extern PBD::PropertyDescriptor<bool> contents; // type doesn't matter here 76 }; 77 78 class Playlist; 79 class Filter; 80 class ExportSpecification; 81 class Progress; 82 83 enum LIBARDOUR_API RegionEditState { 84 EditChangesNothing = 0, 85 EditChangesName = 1, 86 EditChangesID = 2 87 }; 88 89 90 class LIBARDOUR_API Region 91 : public SessionObject 92 , public boost::enable_shared_from_this<Region> 93 , public Readable 94 , public Trimmable 95 , public Movable 96 { 97 public: 98 typedef std::vector<boost::shared_ptr<Source> > SourceList; 99 100 static void make_property_quarks (); 101 102 static PBD::Signal2<void,boost::shared_ptr<RegionList>, const PBD::PropertyChange&> RegionsPropertyChanged; 103 104 typedef std::map <PBD::PropertyChange, RegionList> ChangeMap; 105 106 virtual ~Region(); 107 108 /** Note: changing the name of a Region does not constitute an edit */ 109 bool set_name (const std::string& str); 110 data_type()111 const DataType& data_type () const { return _type; } 112 113 /** How the region parameters play together: 114 * 115 * POSITION: first sample of the region along the timeline 116 * START: first sample of the region within its source(s) 117 * LENGTH: number of samples the region represents 118 */ position()119 samplepos_t position () const { return _position; } start()120 samplepos_t start () const { return _start; } length()121 samplecnt_t length () const { return _length; } layer()122 layer_t layer () const { return _layer; } 123 124 void set_selected_for_solo(bool yn); 125 126 samplecnt_t source_length (uint32_t n) const; 127 uint32_t max_source_level () const; 128 129 /* these two are valid ONLY during a StateChanged signal handler */ 130 last_position()131 samplepos_t last_position () const { return _last_position; } last_length()132 samplecnt_t last_length () const { return _last_length; } 133 ancestral_start()134 samplepos_t ancestral_start () const { return _ancestral_start; } ancestral_length()135 samplecnt_t ancestral_length () const { return _ancestral_length; } 136 stretch()137 float stretch () const { return _stretch; } shift()138 float shift () const { return _shift; } 139 140 void set_ancestral_data (samplepos_t start, samplecnt_t length, float stretch, float shift); 141 142 sampleoffset_t sync_offset (int& dir) const; 143 samplepos_t sync_position () const; 144 145 samplepos_t adjust_to_sync (samplepos_t) const; 146 147 /* first_sample() is an alias; last_sample() just hides some math */ 148 first_sample()149 samplepos_t first_sample () const { return _position; } last_sample()150 samplepos_t last_sample () const { return _position + _length - 1; } 151 152 /** Return the earliest possible value of _position given the 153 * value of _start within the region's sources 154 */ 155 samplepos_t earliest_possible_position () const; 156 /** Return the last possible value of _last_sample given the 157 * value of _startin the regions's sources 158 */ 159 samplepos_t latest_possible_sample () const; 160 last_range()161 Evoral::Range<samplepos_t> last_range () const { 162 return Evoral::Range<samplepos_t> (_last_position, _last_position + _last_length - 1); 163 } 164 range()165 Evoral::Range<samplepos_t> range () const { 166 return Evoral::Range<samplepos_t> (first_sample(), last_sample()); 167 } 168 hidden()169 bool hidden () const { return _hidden; } muted()170 bool muted () const { return _muted; } opaque()171 bool opaque () const { return _opaque; } locked()172 bool locked () const { return _locked; } position_locked()173 bool position_locked () const { return _position_locked; } video_locked()174 bool video_locked () const { return _video_locked; } automatic()175 bool automatic () const { return _automatic; } whole_file()176 bool whole_file () const { return _whole_file; } captured()177 bool captured () const { return !(_import || _external); } can_move()178 bool can_move () const { return !_position_locked && !_locked; } sync_marked()179 bool sync_marked () const { return _sync_marked; } external()180 bool external () const { return _external; } import()181 bool import () const { return _import; } 182 183 Trimmable::CanTrim can_trim () const; 184 position_lock_style()185 PositionLockStyle position_lock_style () const { return _position_lock_style; } 186 void set_position_lock_style (PositionLockStyle ps); 187 void recompute_position_from_lock_style (const int32_t sub_num); 188 189 /* meter-based beat at the region position */ beat()190 double beat () const { return _beat; } set_beat(double beat)191 void set_beat (double beat) { _beat = beat; } 192 /* quarter-note at the region position */ quarter_note()193 double quarter_note () const { return _quarter_note; } set_quarter_note(double qn)194 void set_quarter_note (double qn) { _quarter_note = qn; } 195 196 void suspend_property_changes (); 197 covers(samplepos_t sample)198 bool covers (samplepos_t sample) const { 199 return first_sample() <= sample && sample <= last_sample(); 200 } 201 202 /** @return coverage of this region with the given range; 203 * OverlapInternal: the range is internal to this region. 204 * OverlapStart: the range overlaps the start of this region. 205 * OverlapEnd: the range overlaps the end of this region. 206 * OverlapExternal: the range overlaps all of this region. 207 */ coverage(samplepos_t start,samplepos_t end)208 Evoral::OverlapType coverage (samplepos_t start, samplepos_t end) const { 209 return Evoral::coverage (first_sample(), last_sample(), start, end); 210 } 211 212 bool exact_equivalent (boost::shared_ptr<const Region>) const; 213 bool size_equivalent (boost::shared_ptr<const Region>) const; 214 bool overlap_equivalent (boost::shared_ptr<const Region>) const; 215 bool enclosed_equivalent (boost::shared_ptr<const Region>) const; 216 bool layer_and_time_equivalent (boost::shared_ptr<const Region>) const; 217 bool source_equivalent (boost::shared_ptr<const Region>) const; 218 bool any_source_equivalent (boost::shared_ptr<const Region>) const; 219 bool uses_source (boost::shared_ptr<const Source>, bool shallow = false) const; 220 void deep_sources (std::set<boost::shared_ptr<Source> >&) const; 221 222 std::string source_string () const; 223 224 225 /* EDITING OPERATIONS */ 226 227 void set_length (samplecnt_t, const int32_t sub_num); 228 void set_start (samplepos_t); 229 void set_position (samplepos_t, int32_t sub_num = 0); 230 void set_position_music (double qn); 231 void set_initial_position (samplepos_t); 232 void special_set_position (samplepos_t); 233 virtual void update_after_tempo_map_change (bool send_change = true); 234 void nudge_position (sampleoffset_t); 235 236 bool at_natural_position () const; 237 void move_to_natural_position (); 238 239 void move_start (sampleoffset_t distance, const int32_t sub_num = 0); 240 void trim_front (samplepos_t new_position, const int32_t sub_num = 0); 241 void trim_end (samplepos_t new_position, const int32_t sub_num = 0); 242 void trim_to (samplepos_t position, samplecnt_t length, const int32_t sub_num = 0); 243 fade_range(samplepos_t,samplepos_t)244 virtual void fade_range (samplepos_t, samplepos_t) {} 245 246 void cut_front (samplepos_t new_position, const int32_t sub_num = 0); 247 void cut_end (samplepos_t new_position, const int32_t sub_num = 0); 248 249 void set_layer (layer_t l); /* ONLY Playlist can call this */ 250 void raise (); 251 void lower (); 252 void raise_to_top (); 253 void lower_to_bottom (); 254 255 void set_sync_position (samplepos_t n); 256 void clear_sync_position (); 257 void set_hidden (bool yn); 258 void set_muted (bool yn); 259 void set_whole_file (bool yn); 260 void set_automatic (bool yn); 261 void set_opaque (bool yn); 262 void set_locked (bool yn); 263 void set_video_locked (bool yn); 264 void set_position_locked (bool yn); 265 266 int apply (Filter &, Progress* progress = 0); 267 playlist()268 boost::shared_ptr<ARDOUR::Playlist> playlist () const { return _playlist.lock(); } 269 virtual void set_playlist (boost::weak_ptr<ARDOUR::Playlist>); 270 271 void source_deleted (boost::weak_ptr<Source>); 272 273 bool is_compound () const; 274 275 boost::shared_ptr<Source> source (uint32_t n=0) const { return _sources[ (n < _sources.size()) ? n : 0 ]; } n_channels()276 uint32_t n_channels() const { return _sources.size(); } 277 sources_for_edit()278 SourceList& sources_for_edit () { return _sources; } sources()279 const SourceList& sources () const { return _sources; } master_sources()280 const SourceList& master_sources () const { return _master_sources; } 281 282 std::vector<std::string> master_source_names(); 283 void set_master_sources (const SourceList&); 284 285 /* automation */ 286 287 virtual boost::shared_ptr<Evoral::Control> 288 control (const Evoral::Parameter& id, bool create=false) = 0; 289 290 virtual boost::shared_ptr<const Evoral::Control> 291 control (const Evoral::Parameter& id) const = 0; 292 293 /* tags */ 294 tags()295 std::string tags() const { return _tags; } set_tags(const std::string & str)296 virtual bool set_tags (const std::string& str) { 297 if (_tags != str) { 298 _tags = str; 299 PropertyChanged (PBD::PropertyChange (Properties::tags)); 300 } 301 return true; 302 } 303 304 /* serialization */ 305 306 XMLNode& get_state (); 307 virtual int set_state (const XMLNode&, int version); 308 309 virtual boost::shared_ptr<Region> get_parent() const; 310 layering_index()311 uint64_t layering_index () const { return _layering_index; } set_layering_index(uint64_t when)312 void set_layering_index (uint64_t when) { _layering_index = when; } 313 is_dependent()314 virtual bool is_dependent() const { return false; } depends_on(boost::shared_ptr<Region>)315 virtual bool depends_on (boost::shared_ptr<Region> /*other*/) const { return false; } 316 add_transient(samplepos_t)317 virtual void add_transient (samplepos_t) { 318 // no transients, but its OK 319 } 320 clear_transients()321 virtual void clear_transients () { 322 // no transients, but its OK 323 } 324 update_transient(samplepos_t,samplepos_t)325 virtual void update_transient (samplepos_t /* old_position */, samplepos_t /* new_position */) { 326 // no transients, but its OK 327 } 328 remove_transient(samplepos_t)329 virtual void remove_transient (samplepos_t /* where */) { 330 // no transients, but its OK 331 } 332 set_onsets(AnalysisFeatureList &)333 virtual void set_onsets (AnalysisFeatureList&) { 334 // no transients, but its OK 335 } 336 337 /** merges _onsets and _user_transients into given list 338 * and removed exact duplicates. 339 */ 340 void transients (AnalysisFeatureList&); 341 342 void captured_xruns (XrunPositions&, bool abs = false) const; 343 344 /** merges _onsets OR _transients with _user_transients into given list 345 * if _onsets and _transients are unset, run analysis. 346 * list is not thinned, duplicates remain in place. 347 * 348 * intended for: Playlist::find_next_transient () 349 */ get_transients(AnalysisFeatureList &)350 virtual void get_transients (AnalysisFeatureList&) { 351 // no transients, but its OK 352 } 353 354 /* wrapper to the above for easy access throug Lua */ transients()355 AnalysisFeatureList transients () { 356 AnalysisFeatureList rv; 357 get_transients (rv); 358 return rv; 359 } 360 361 bool has_transients () const; 362 separate_by_channel(std::vector<boost::shared_ptr<Region>> &)363 virtual int separate_by_channel (std::vector< boost::shared_ptr<Region> >&) const { 364 return -1; 365 } 366 367 void maybe_invalidate_transients (); 368 369 void drop_sources (); 370 371 /* Allow to collect RegionsPropertyChanged signal emissions */ set_changemap(ChangeMap * changemap)372 void set_changemap (ChangeMap* changemap) { 373 _changemap = changemap; 374 } 375 376 void get_cue_markers (CueMarkers&, bool abs = false) const; 377 void move_cue_marker (CueMarker const &, samplepos_t region_relative_position); 378 void rename_cue_marker (CueMarker&, std::string const &); 379 380 protected: 381 virtual XMLNode& state (); 382 383 friend class RegionFactory; 384 385 /** Construct a region from multiple sources*/ 386 Region (const SourceList& srcs); 387 388 /** Construct a region from another region */ 389 Region (boost::shared_ptr<const Region>); 390 391 /** Construct a region from another region, at an offset within that region */ 392 Region (boost::shared_ptr<const Region>, ARDOUR::MusicSample start_offset); 393 394 /** Construct a region as a copy of another region, but with different sources */ 395 Region (boost::shared_ptr<const Region>, const SourceList&); 396 397 /** Constructor for derived types only */ 398 Region (Session& s, samplepos_t start, samplecnt_t length, const std::string& name, DataType); 399 can_trim_start_before_source_start()400 virtual bool can_trim_start_before_source_start () const { 401 return false; 402 } 403 404 protected: 405 406 void send_change (const PBD::PropertyChange&); 407 virtual int _set_state (const XMLNode&, int version, PBD::PropertyChange& what_changed, bool send_signal); 408 void post_set (const PBD::PropertyChange&); 409 virtual void set_position_internal (samplepos_t pos, bool allow_bbt_recompute, const int32_t sub_num); 410 virtual void set_position_music_internal (double qn); 411 virtual void set_length_internal (samplecnt_t, const int32_t sub_num); 412 virtual void set_start_internal (samplecnt_t, const int32_t sub_num = 0); 413 bool verify_start_and_length (samplepos_t, samplecnt_t&); 414 void first_edit (); 415 416 DataType _type; 417 418 PBD::Property<bool> _sync_marked; 419 PBD::Property<bool> _left_of_split; 420 PBD::Property<bool> _right_of_split; 421 PBD::Property<bool> _valid_transients; 422 PBD::Property<samplepos_t> _start; 423 PBD::Property<samplecnt_t> _length; 424 PBD::Property<samplepos_t> _position; 425 PBD::Property<double> _beat; 426 /** Sync position relative to the start of our file */ 427 PBD::Property<samplepos_t> _sync_position; 428 429 double _quarter_note; 430 431 SourceList _sources; 432 /** Used when timefx are applied, so we can always use the original source */ 433 SourceList _master_sources; 434 435 boost::weak_ptr<ARDOUR::Playlist> _playlist; 436 437 void merge_features (AnalysisFeatureList&, const AnalysisFeatureList&, const sampleoffset_t) const; 438 439 AnalysisFeatureList _onsets; // used by the Ferret (Aubio OnsetDetector) 440 441 // _transient_user_start is covered by _valid_transients 442 AnalysisFeatureList _user_transients; // user added 443 samplepos_t _transient_user_start; // region's _start relative to user_transients 444 445 // these are used by Playlist::find_next_transient() in absence of onsets 446 AnalysisFeatureList _transients; // Source Analysis (QM Transient), user read-only 447 samplepos_t _transient_analysis_start; 448 samplepos_t _transient_analysis_end; 449 450 bool _soloSelected; 451 452 private: 453 void mid_thaw (const PBD::PropertyChange&); 454 455 virtual void trim_to_internal (samplepos_t position, samplecnt_t length, const int32_t sub_num); 456 void modify_front (samplepos_t new_position, bool reset_fade, const int32_t sub_num); 457 void modify_end (samplepos_t new_position, bool reset_fade, const int32_t sub_num); 458 459 void maybe_uncopy (); 460 461 bool verify_start (samplepos_t); 462 bool verify_start_mutable (samplepos_t&_start); 463 bool verify_length (samplecnt_t&); 464 465 virtual void recompute_at_start () = 0; 466 virtual void recompute_at_end () = 0; 467 468 PBD::Property<bool> _muted; 469 PBD::Property<bool> _opaque; 470 PBD::Property<bool> _locked; 471 PBD::Property<bool> _video_locked; 472 PBD::Property<bool> _automatic; 473 PBD::Property<bool> _whole_file; 474 PBD::Property<bool> _import; 475 PBD::Property<bool> _external; 476 PBD::Property<bool> _hidden; 477 PBD::Property<bool> _position_locked; 478 PBD::Property<samplepos_t> _ancestral_start; 479 PBD::Property<samplecnt_t> _ancestral_length; 480 PBD::Property<float> _stretch; 481 PBD::Property<float> _shift; 482 PBD::EnumProperty<PositionLockStyle> _position_lock_style; 483 PBD::Property<uint64_t> _layering_index; 484 PBD::Property<std::string> _tags; 485 PBD::Property<bool> _contents; // type is irrelevant 486 487 samplecnt_t _last_length; 488 samplepos_t _last_position; 489 mutable RegionEditState _first_edit; 490 layer_t _layer; 491 492 ChangeMap* _changemap; 493 494 void register_properties (); 495 496 void use_sources (SourceList const &); 497 }; 498 499 } /* namespace ARDOUR */ 500 501 #endif /* __ardour_region_h__ */ 502