"Run plugins while recording" -> "Do not run plugins while recording"
[ardour.git] / libs / ardour / playlist.cc
1 /*
2     Copyright (C) 2000-2003 Paul Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #include <set>
22 #include <fstream>
23 #include <algorithm>
24 #include <unistd.h>
25 #include <cerrno>
26 #include <string>
27 #include <climits>
28
29 #include <sigc++/bind.h>
30
31 #include <pbd/failed_constructor.h>
32 #include <pbd/stl_delete.h>
33 #include <pbd/xml++.h>
34
35 #include <ardour/playlist.h>
36 #include <ardour/session.h>
37 #include <ardour/region.h>
38 #include <ardour/region_factory.h>
39
40 #include "i18n.h"
41
42 using namespace std;
43 using namespace ARDOUR;
44 //using namespace sigc;
45
46 sigc::signal<void,Playlist*> Playlist::PlaylistCreated;
47
48 struct ShowMeTheList {
49     ShowMeTheList (Playlist *pl, const string& n) : playlist (pl), name (n) {}
50     ~ShowMeTheList () { 
51             cerr << ">>>>" << name << endl; playlist->dump(); cerr << "<<<<" << name << endl << endl; 
52     };
53     Playlist *playlist;
54     string name;
55 };
56
57 struct RegionSortByLayer {
58     bool operator() (Region *a, Region *b) {
59             return a->layer() < b->layer();
60     }
61 };
62
63 struct RegionSortByPosition {
64     bool operator() (Region *a, Region *b) {
65             return a->position() < b->position();
66     }
67 };
68
69 struct RegionSortByLastLayerOp {
70     bool operator() (Region *a, Region *b) {
71             return a->last_layer_op() < b->last_layer_op();
72     }
73 };
74
75 Playlist::Playlist (Session& sess, string nom, bool hide)
76         : _session (sess)
77 {
78         init (hide);
79         _name = nom;
80         _orig_diskstream_id = 0;
81         
82 }
83
84 Playlist::Playlist (Session& sess, const XMLNode& node, bool hide)
85         : _session (sess)
86 {
87         init (hide);
88         _name = "unnamed"; /* reset by set_state */
89         _orig_diskstream_id = 0;
90         
91         if (set_state (node)) {
92                 throw failed_constructor();
93         }
94 }
95
96 Playlist::Playlist (const Playlist& other, string namestr, bool hide)
97         : _name (namestr), _session (other._session), _orig_diskstream_id(other._orig_diskstream_id)
98 {
99         init (hide);
100
101         other.copy_regions (regions);
102
103         for (list<Region*>::iterator x = regions.begin(); x != regions.end(); ++x) {
104                 (*x)->set_playlist (this);
105         }
106 }
107
108 Playlist::Playlist (const Playlist& other, jack_nframes_t start, jack_nframes_t cnt, string str, bool hide)
109         : _name (str), _session (other._session), _orig_diskstream_id(other._orig_diskstream_id)
110 {
111         RegionLock rlock2 (&((Playlist&)other));
112         
113         jack_nframes_t end = start + cnt - 1;
114
115         init (hide);
116
117         for (RegionList::const_iterator i = other.regions.begin(); i != other.regions.end(); i++) {
118
119                 Region   *region;
120                 Region   *new_region;
121                 jack_nframes_t offset = 0;
122                 jack_nframes_t position = 0;
123                 jack_nframes_t len = 0;
124                 string    new_name;
125                 OverlapType overlap;
126
127                 region = *i;
128
129                 overlap = region->coverage (start, end);
130
131                 switch (overlap) {
132                 case OverlapNone:
133                         continue;
134
135                 case OverlapInternal:
136                         offset = start - region->position();
137                         position = 0;
138                         len = cnt;
139                         break;
140
141                 case OverlapStart:
142                         offset = 0;
143                         position = region->position() - start;
144                         len = end - region->position();
145                         break;
146
147                 case OverlapEnd:
148                         offset = start - region->position();
149                         position = 0;
150                         len = region->length() - offset;
151                         break;
152
153                 case OverlapExternal:
154                         offset = 0;
155                         position = region->position() - start;
156                         len = region->length();
157                         break;
158                 }
159
160                 _session.region_name (new_name, region->name(), false);
161
162                 new_region = createRegion (*region, offset, len, new_name, region->layer(), region->flags());
163
164                 add_region_internal (new_region, position, true);
165         }
166         
167         /* this constructor does NOT notify others (session) */
168 }
169
170 void
171 Playlist::ref ()
172 {
173         ++_refcnt;
174         InUse (this, true); /* EMIT SIGNAL */
175 }
176
177 void
178 Playlist::unref ()
179 {
180         if (_refcnt > 0) {
181                 _refcnt--; 
182         }
183         if (_refcnt == 0) {
184                 InUse (this, false); /* EMIT SIGNAL */
185                 
186                 if (_hidden) {
187                         /* nobody knows we exist */
188                         delete this;
189                 }
190         }
191 }
192
193
194 void
195 Playlist::copy_regions (RegionList& newlist) const
196 {
197         RegionLock rlock (const_cast<Playlist *> (this));
198
199         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
200                 newlist.push_back (createRegion (**i));
201         }
202 }
203
204 void
205 Playlist::init (bool hide)
206 {
207         atomic_set (&block_notifications, 0);
208         atomic_set (&ignore_state_changes, 0);
209         pending_modified = false;
210         pending_length = false;
211         _refcnt = 0;
212         _hidden = hide;
213         _splicing = false;
214         _nudging = false;
215         in_set_state = false;
216         _edit_mode = _session.get_edit_mode();
217         in_flush = false;
218         in_partition = false;
219         subcnt = 0;
220         _read_data_count = 0;
221         _frozen = false;
222         save_on_thaw = false;
223         layer_op_counter = 0;
224         freeze_length = 0;
225
226         Modified.connect (mem_fun (*this, &Playlist::mark_session_dirty));
227 }
228
229 Playlist::Playlist (const Playlist& pl)
230         : _session (pl._session)
231 {
232         fatal << _("playlist const copy constructor called") << endmsg;
233 }
234
235 Playlist::Playlist (Playlist& pl)
236         : _session (pl._session)
237 {
238         fatal << _("playlist non-const copy constructor called") << endmsg;
239 }
240
241 Playlist::~Playlist ()
242 {
243 }
244
245 void
246 Playlist::set_name (const string& str)
247 {
248         /* in a typical situation, a playlist is being used
249            by one diskstream and also is referenced by the
250            Session. if there are more references than that,
251            then don't change the name.
252         */
253
254         if (_refcnt > 2) {
255                 return;
256         }
257
258         _name = str; 
259         NameChanged(); /* EMIT SIGNAL */
260 }
261
262 /***********************************************************************
263  CHANGE NOTIFICATION HANDLING
264  
265  Notifications must be delayed till the region_lock is released. This
266  is necessary because handlers for the signals may need to acquire
267  the lock (e.g. to read from the playlist).
268  ***********************************************************************/
269
270 void
271 Playlist::freeze ()
272 {
273         delay_notifications ();
274         atomic_inc (&ignore_state_changes);
275 }
276
277 void
278 Playlist::thaw ()
279 {
280         atomic_dec (&ignore_state_changes);
281         release_notifications ();
282 }
283
284
285 void
286 Playlist::delay_notifications ()
287 {
288         atomic_inc (&block_notifications);
289         freeze_length = _get_maximum_extent();
290 }
291
292 void
293 Playlist::release_notifications ()
294 {
295         if (atomic_dec_and_test(&block_notifications)) { 
296                 flush_notifications ();
297         } 
298 }
299
300
301 void
302 Playlist::notify_modified ()
303 {
304         if (holding_state ()) {
305                 pending_modified = true;
306         } else {
307                 pending_modified = false;
308                 Modified(); /* EMIT SIGNAL */
309         }
310 }
311
312 void
313 Playlist::notify_region_removed (Region *r)
314 {
315         if (holding_state ()) {
316                 pending_removals.insert (pending_removals.end(), r);
317         } else {
318                 RegionRemoved (r); /* EMIT SIGNAL */
319                 /* this might not be true, but we have to act
320                    as though it could be.
321                 */
322                 LengthChanged (); /* EMIT SIGNAL */
323                 Modified (); /* EMIT SIGNAL */
324         }
325 }
326
327 void
328 Playlist::notify_region_added (Region *r)
329 {
330         if (holding_state()) {
331                 pending_adds.insert (pending_adds.end(), r);
332         } else {
333                 RegionAdded (r); /* EMIT SIGNAL */
334                 /* this might not be true, but we have to act
335                    as though it could be.
336                 */
337                 LengthChanged (); /* EMIT SIGNAL */
338                 Modified (); /* EMIT SIGNAL */
339         }
340 }
341
342 void
343 Playlist::notify_length_changed ()
344 {
345         if (holding_state ()) {
346                 pending_length = true;
347         } else {
348                 LengthChanged(); /* EMIT SIGNAL */
349                 Modified (); /* EMIT SIGNAL */
350         }
351 }
352
353 void
354 Playlist::flush_notifications ()
355 {
356         RegionList::iterator r;
357         RegionList::iterator a;
358         set<Region*> dependent_checks_needed;
359         uint32_t n = 0;
360
361         if (in_flush) {
362                 return;
363         }
364
365         in_flush = true;
366
367         /* we have no idea what order the regions ended up in pending
368            bounds (it could be based on selection order, for example).
369            so, to preserve layering in the "most recently moved is higher" 
370            model, sort them by existing layer, then timestamp them.
371         */
372
373         // RegionSortByLayer cmp;
374         // pending_bounds.sort (cmp);
375
376         for (RegionList::iterator r = pending_bounds.begin(); r != pending_bounds.end(); ++r) {
377                 if (_session.get_layer_model() == Session::MoveAddHigher) {
378                         timestamp_layer_op (**r);
379                 }
380                 pending_length = true;
381                 n++;
382         }
383
384         for (RegionList::iterator r = pending_bounds.begin(); r != pending_bounds.end(); ++r) {
385                 dependent_checks_needed.insert (*r);
386                 /* don't increment n again - its the same list */
387         }
388
389         for (a = pending_adds.begin(); a != pending_adds.end(); ++a) {
390                 dependent_checks_needed.insert (*a);
391                 RegionAdded (*a); /* EMIT SIGNAL */
392                 n++;
393         }
394
395         for (set<Region*>::iterator x = dependent_checks_needed.begin(); x != dependent_checks_needed.end(); ++x) {
396                 check_dependents (**x, false);
397         }
398
399         for (r = pending_removals.begin(); r != pending_removals.end(); ++r) {
400                 remove_dependents (**r);
401                 RegionRemoved (*r); /* EMIT SIGNAL */
402                 n++;
403         }
404
405         if ((freeze_length != _get_maximum_extent()) || pending_length) {
406                 pending_length = 0;
407                 LengthChanged(); /* EMIT SIGNAL */
408                 n++;
409         }
410
411         if (n || pending_modified) {
412                 possibly_splice ();
413                 relayer ();
414                 pending_modified = false;
415                 Modified (); /* EMIT SIGNAL */
416         }
417
418         pending_adds.clear ();
419         pending_removals.clear ();
420         pending_bounds.clear ();
421
422         if (save_on_thaw) {
423                 save_on_thaw = false;
424                 save_state (last_save_reason);
425         }
426         
427         in_flush = false;
428 }
429
430 /*************************************************************
431   PLAYLIST OPERATIONS
432  *************************************************************/
433
434 void
435 Playlist::add_region (const Region& region, jack_nframes_t position, float times, bool with_save) 
436
437         RegionLock rlock (this);
438         
439         times = fabs (times);
440         
441         int itimes = (int) floor (times);
442
443         jack_nframes_t pos = position;
444         
445         if (itimes >= 1) {
446                 add_region_internal (const_cast<Region*>(&region), pos, true);
447                 pos += region.length();
448                 --itimes;
449         }
450         
451         /* later regions will all be spliced anyway */
452         
453         if (!holding_state ()) {
454                 possibly_splice_unlocked ();
455         }
456
457         /* note that itimes can be zero if we being asked to just
458            insert a single fraction of the region.
459         */
460
461         for (int i = 0; i < itimes; ++i) {
462                 Region *copy = createRegion (region);
463                 add_region_internal (copy, pos, true);
464                 pos += region.length();
465         }
466         
467         if (floor (times) != times) {
468                 jack_nframes_t length = (jack_nframes_t) floor (region.length() * (times - floor (times)));
469                 string name;
470                 _session.region_name (name, region.name(), false);
471                 Region *sub = createRegion (region, 0, length, name, region.layer(), region.flags());
472                 add_region_internal (sub, pos, true);
473         }
474         
475         if (with_save) {
476                 maybe_save_state (_("add region"));
477         }
478 }
479
480 void
481 Playlist::add_region_internal (Region *region, jack_nframes_t position, bool delay_sort)
482 {
483         RegionSortByPosition cmp;
484         jack_nframes_t old_length = 0;
485
486         // cerr << "adding region " << region->name() << " at " << position << endl;
487
488         if (!holding_state()) {
489                  old_length = _get_maximum_extent();
490         }
491
492         region->set_playlist (this);
493         region->set_position (position, this);
494         region->lock_sources ();
495
496         timestamp_layer_op (*region);
497
498         regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
499
500         if (!holding_state () && !in_set_state) {
501                 /* layers get assigned from XML state */
502                 relayer ();
503         }
504
505         /* we need to notify the existence of new region before checking dependents. Ick. */
506
507         notify_region_added (region);
508         
509         if (!holding_state ()) {
510                 check_dependents (*region, false);
511                 if (old_length != _get_maximum_extent()) {
512                         notify_length_changed ();
513                 }
514         }
515
516         region->StateChanged.connect (sigc::bind (mem_fun (this, &Playlist::region_changed_proxy), region));
517 }
518
519 void
520 Playlist::replace_region (Region& old, Region& newr, jack_nframes_t pos)
521 {
522         RegionLock rlock (this);
523
524         remove_region_internal (&old);
525         add_region_internal (&newr, pos);
526
527         if (!holding_state ()) {
528                 possibly_splice_unlocked ();
529         }
530
531         maybe_save_state (_("replace region"));
532 }
533
534 void
535 Playlist::remove_region (Region *region)
536 {
537         RegionLock rlock (this);
538         remove_region_internal (region);
539
540         if (!holding_state ()) {
541                 possibly_splice_unlocked ();
542         }
543
544         maybe_save_state (_("remove region"));
545 }
546
547 int
548 Playlist::remove_region_internal (Region *region, bool delay_sort)
549 {
550         RegionList::iterator i;
551         jack_nframes_t old_length = 0;
552
553         // cerr << "removing region " << region->name() << endl;
554
555         if (!holding_state()) {
556                 old_length = _get_maximum_extent();
557         }
558
559         for (i = regions.begin(); i != regions.end(); ++i) {
560                 if (*i == region) {
561
562                         regions.erase (i);
563
564                         if (!holding_state ()) {
565                                 relayer ();
566                                 remove_dependents (*region);
567                                 
568                                 if (old_length != _get_maximum_extent()) {
569                                         notify_length_changed ();
570                                 }
571                         }
572
573                         notify_region_removed (region);
574                         return 0;
575                 }
576         }
577         return -1;
578 }
579
580 void
581 Playlist::partition (jack_nframes_t start, jack_nframes_t end, bool just_top_level)
582 {
583         RegionList thawlist;
584
585         partition_internal (start, end, false, thawlist);
586
587         for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
588                 (*i)->thaw ("separation");
589         }
590
591         maybe_save_state (_("separate"));
592 }
593
594 void
595 Playlist::partition_internal (jack_nframes_t start, jack_nframes_t end, bool cutting, RegionList& thawlist)
596 {
597         RegionLock rlock (this);
598         Region *region;
599         Region *current;
600         string new_name;
601         RegionList::iterator tmp;
602         OverlapType overlap;
603         jack_nframes_t pos1, pos2, pos3, pos4;
604         RegionList new_regions;
605
606         in_partition = true;
607
608         /* need to work from a copy, because otherwise the regions we add during the process
609            get operated on as well.
610         */
611
612         RegionList copy = regions;
613
614         for (RegionList::iterator i = copy.begin(); i != copy.end(); i = tmp) {
615                 
616                 tmp = i;
617                 ++tmp;
618
619                 current = *i;
620                 
621                 if (current->first_frame() == start && current->last_frame() == end) {
622                         if (cutting) {
623                                 remove_region_internal (current);
624                         }
625                         continue;
626                 }
627                 
628                 if ((overlap = current->coverage (start, end)) == OverlapNone) {
629                         continue;
630                 }
631                 
632                 pos1 = current->position();
633                 pos2 = start;
634                 pos3 = end;
635                 pos4 = current->last_frame();
636
637                 if (overlap == OverlapInternal) {
638                         
639                         /* split: we need 3 new regions, the front, middle and end.
640                            cut:   we need 2 regions, the front and end.
641                         */
642                         
643                         /*
644                                          start                 end
645                           ---------------*************************------------
646                                          P1  P2              P3  P4
647                           SPLIT:
648                           ---------------*****++++++++++++++++====------------
649                           CUT
650                           ---------------*****----------------====------------
651                           
652                         */
653
654                         if (!cutting) {
655                                 
656                                 /* "middle" ++++++ */
657                                 
658                                 _session.region_name (new_name, current->name(), false);
659                                 region = createRegion (*current, pos2 - pos1, pos3 - pos2, new_name,
660                                                        regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit|Region::RightOfSplit));
661                                 add_region_internal (region, start, true);
662                                 new_regions.push_back (region);
663                         }
664                         
665                         /* "end" ====== */
666                         
667                         _session.region_name (new_name, current->name(), false);
668                         region = createRegion (*current, pos3 - pos1, pos4 - pos3, new_name, 
669                                                regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
670
671                         add_region_internal (region, end, true);
672                         new_regions.push_back (region);
673
674                         /* "front" ***** */
675                                 
676                         current->freeze ();
677                         thawlist.push_back (current);
678                         current->trim_end (pos2, this);
679
680                 } else if (overlap == OverlapEnd) {
681
682                         /*
683                                                               start           end
684                                     ---------------*************************------------
685                                                    P1           P2         P4   P3
686                                     SPLIT:                                                 
687                                     ---------------**************+++++++++++------------
688                                     CUT:                                                   
689                                     ---------------**************-----------------------
690
691                         */
692
693                         if (!cutting) {
694                                 
695                                 /* end +++++ */
696                                 
697                                 _session.region_name (new_name, current->name(), false);
698                                 region = createRegion (*current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(),
699                                                        Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit));
700                                 add_region_internal (region, start, true);
701                                 new_regions.push_back (region);
702                         }
703
704                         /* front ****** */
705
706                         current->freeze ();
707                         thawlist.push_back (current);
708                         current->trim_end (pos2, this);
709
710                 } else if (overlap == OverlapStart) {
711
712                         /* split: we need 2 regions: the front and the end.
713                            cut: just trim current to skip the cut area
714                         */
715                                 
716                         /*
717                                                         start           end
718                                     ---------------*************************------------
719                                        P2          P1 P3                   P4          
720
721                                     SPLIT:
722                                     ---------------****+++++++++++++++++++++------------
723                                     CUT:
724                                     -------------------*********************------------
725                                     
726                         */
727
728                         if (!cutting) {
729                                 
730                                 /* front **** */
731                                  _session.region_name (new_name, current->name(), false);
732                                  region = createRegion (*current, 0, pos3 - pos1, new_name,
733                                                         regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
734                                  add_region_internal (region, pos1, true);
735                                  new_regions.push_back (region);
736                         } 
737                         
738                         /* end */
739                         
740                         current->freeze ();
741                         thawlist.push_back (current);
742                         current->trim_front (pos3, this);
743
744                 } else if (overlap == OverlapExternal) {
745
746                         /* split: no split required.
747                            cut: remove the region.
748                         */
749                                 
750                         /*
751                                        start                                      end
752                                     ---------------*************************------------
753                                        P2          P1 P3                   P4          
754
755                                     SPLIT:
756                                     ---------------*************************------------
757                                     CUT:
758                                     ----------------------------------------------------
759                                     
760                         */
761
762                         if (cutting) {
763                                 remove_region_internal (current);
764                         }
765                         new_regions.push_back (current);
766                 }
767         }
768
769         in_partition = false;
770
771         for (RegionList::iterator i = new_regions.begin(); i != new_regions.end(); ++i) {
772                 check_dependents (**i, false);
773         }
774 }
775
776 Playlist*
777 Playlist::cut_copy (Playlist* (Playlist::*pmf)(jack_nframes_t, jack_nframes_t,bool), list<AudioRange>& ranges, bool result_is_hidden)
778 {
779         Playlist* ret;
780         Playlist* pl;
781         jack_nframes_t start;
782
783         if (ranges.empty()) {
784                 return 0;
785         }
786
787         start = ranges.front().start;
788
789
790         for (list<AudioRange>::iterator i = ranges.begin(); i != ranges.end(); ++i) {
791
792                 pl = (this->*pmf)((*i).start, (*i).length(), result_is_hidden);
793                 
794                 if (i == ranges.begin()) {
795                         ret = pl;
796                 } else {
797                         
798                         /* paste the next section into the nascent playlist,
799                            offset to reflect the start of the first range we
800                            chopped.
801                         */
802
803                         ret->paste (*pl, (*i).start - start, 1.0f);
804                         delete pl;
805                 }
806         }
807
808         if (ret) {
809                 /* manually notify session of new playlist here
810                    because the playlists were constructed without notifying 
811                 */
812                 PlaylistCreated (ret);
813         }
814         
815         return ret;
816 }
817
818 Playlist*
819 Playlist::cut (list<AudioRange>& ranges, bool result_is_hidden)
820 {
821         Playlist* (Playlist::*pmf)(jack_nframes_t,jack_nframes_t,bool) = &Playlist::cut;
822         return cut_copy (pmf, ranges, result_is_hidden);
823 }
824
825 Playlist*
826 Playlist::copy (list<AudioRange>& ranges, bool result_is_hidden)
827 {
828         Playlist* (Playlist::*pmf)(jack_nframes_t,jack_nframes_t,bool) = &Playlist::copy;
829         return cut_copy (pmf, ranges, result_is_hidden);
830 }
831
832 Playlist *
833 Playlist::cut (jack_nframes_t start, jack_nframes_t cnt, bool result_is_hidden)
834 {
835         Playlist *the_copy;
836         RegionList thawlist;
837         char buf[32];
838
839         snprintf (buf, sizeof (buf), "%" PRIu32, ++subcnt);
840         string new_name = _name;
841         new_name += '.';
842         new_name += buf;
843
844         if ((the_copy = copyPlaylist (*this, start, cnt, new_name, result_is_hidden)) == 0) {
845                 return 0;
846         }
847
848         partition_internal (start, start+cnt-1, true, thawlist);
849         possibly_splice ();
850
851         for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
852                 (*i)->thaw ("playlist cut");
853         }
854
855         maybe_save_state (_("cut"));
856
857         return the_copy;
858 }
859
860 Playlist *
861 Playlist::copy (jack_nframes_t start, jack_nframes_t cnt, bool result_is_hidden)
862 {
863         char buf[32];
864         
865         snprintf (buf, sizeof (buf), "%" PRIu32, ++subcnt);
866         string new_name = _name;
867         new_name += '.';
868         new_name += buf;
869
870         cnt = min (_get_maximum_extent() - start, cnt);
871         return copyPlaylist (*this, start, cnt, new_name, result_is_hidden);
872 }
873
874 int
875 Playlist::paste (Playlist& other, jack_nframes_t position, float times)
876 {
877         times = fabs (times);
878         jack_nframes_t old_length;
879
880         {
881                 RegionLock rl1 (this);
882                 RegionLock rl2 (&other);
883
884                 old_length = _get_maximum_extent();
885         
886                 int itimes = (int) floor (times);
887                 jack_nframes_t pos = position;
888                 jack_nframes_t shift = other._get_maximum_extent();
889                 layer_t top_layer = regions.size();
890
891                 while (itimes--) {
892                         for (RegionList::iterator i = other.regions.begin(); i != other.regions.end(); ++i) {
893                                 Region *copy_of_region = createRegion (**i);
894
895                                 /* put these new regions on top of all existing ones, but preserve
896                                    the ordering they had in the original playlist.
897                                 */
898                                 
899                                 copy_of_region->set_layer (copy_of_region->layer() + top_layer);
900                                 add_region_internal (copy_of_region, copy_of_region->position() + pos);
901                         }
902                         pos += shift;
903                 }
904
905                 possibly_splice_unlocked ();
906
907                 /* XXX shall we handle fractional cases at some point? */
908
909                 if (old_length != _get_maximum_extent()) {
910                         notify_length_changed ();
911                 }
912
913                 
914         }
915
916         maybe_save_state (_("paste"));
917
918         return 0;
919 }
920
921
922 void
923 Playlist::duplicate (Region& region, jack_nframes_t position, float times)
924 {
925         times = fabs (times);
926
927         RegionLock rl (this);
928         int itimes = (int) floor (times);
929         jack_nframes_t pos = position;
930
931         while (itimes--) {
932                 Region *copy = createRegion (region);
933                 add_region_internal (copy, pos, true);
934                 pos += region.length();
935         }
936
937         if (floor (times) != times) {
938                 jack_nframes_t length = (jack_nframes_t) floor (region.length() * (times - floor (times)));
939                 string name;
940                 _session.region_name (name, region.name(), false);
941                 Region *sub = createRegion (region, 0, length, name, region.layer(), region.flags());
942                 add_region_internal (sub, pos, true);
943         }
944
945         maybe_save_state (_("duplicate"));
946 }
947
948 void
949 Playlist::split_region (Region& region, jack_nframes_t playlist_position)
950 {
951         RegionLock rl (this);
952
953         if (!region.covers (playlist_position)) {
954                 return;
955         }
956
957         if (region.position() == playlist_position ||
958             region.last_frame() == playlist_position) {
959                 return;
960         }
961
962         if (remove_region_internal (&region, true)) {
963                 return;
964         }
965
966         Region *left;
967         Region *right;
968         jack_nframes_t before;
969         jack_nframes_t after;
970         string before_name;
971         string after_name;
972
973         before = playlist_position - region.position();
974         after = region.length() - before;
975         
976         _session.region_name (before_name, region.name(), false);
977         left = createRegion (region, 0, before, before_name, region.layer(), Region::Flag (region.flags()|Region::LeftOfSplit));
978
979         _session.region_name (after_name, region.name(), false);
980         right = createRegion (region, before, after, after_name, region.layer(), Region::Flag (region.flags()|Region::RightOfSplit));
981         
982         add_region_internal (left, region.position(), true);
983         add_region_internal (right, region.position() + before);
984
985         maybe_save_state (_("split"));
986 }
987
988 void
989 Playlist::possibly_splice ()
990 {
991         if (_edit_mode == Splice) {
992                 splice_locked ();
993         }
994 }
995
996 void
997 Playlist::possibly_splice_unlocked ()
998 {
999         if (_edit_mode == Splice) {
1000                 splice_unlocked ();
1001         }
1002 }
1003
1004 void
1005 Playlist::splice_locked ()
1006 {
1007         {
1008                 RegionLock rl (this);
1009                 core_splice ();
1010         }
1011
1012         notify_length_changed ();
1013 }
1014
1015 void
1016 Playlist::splice_unlocked ()
1017 {
1018         core_splice ();
1019         notify_length_changed ();
1020 }
1021
1022 void
1023 Playlist::core_splice ()
1024 {
1025         _splicing = true;
1026         
1027         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1028                 
1029                 RegionList::iterator next;
1030                 
1031                 next = i;
1032                 ++next;
1033                 
1034                 if (next == regions.end()) {
1035                         break;
1036                 }
1037                 
1038                 (*next)->set_position ((*i)->last_frame() + 1, this);
1039         }
1040         
1041         _splicing = false;
1042 }
1043
1044 void
1045 Playlist::region_bounds_changed (Change what_changed, Region *region)
1046 {
1047         if (in_set_state || _splicing || _nudging) {
1048                 return;
1049         }
1050
1051         if (what_changed & ARDOUR::PositionChanged) {
1052
1053                 /* remove it from the list then add it back in
1054                    the right place again.
1055                 */
1056                 
1057                 RegionSortByPosition cmp;
1058
1059                 RegionList::iterator i = find (regions.begin(), regions.end(), region);
1060                 
1061                 if (i == regions.end()) {
1062                         warning << string_compose (_("%1: bounds changed received for region (%2)not in playlist"),
1063                                             _name, region->name())
1064                                 << endmsg;
1065                         return;
1066                 }
1067
1068                 regions.erase (i);
1069                 regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp),
1070                                 region);
1071
1072         }
1073
1074         if (what_changed & Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged)) {
1075         
1076                 if (holding_state ()) {
1077                         pending_bounds.push_back (region);
1078                 } else {
1079                         if (_session.get_layer_model() == Session::MoveAddHigher) {
1080                                 /* it moved or changed length, so change the timestamp */
1081                                 timestamp_layer_op (*region);
1082                         }
1083                         
1084                         possibly_splice ();
1085                         check_dependents (*region, false);
1086                         notify_length_changed ();
1087                         relayer ();
1088                 }
1089         }
1090 }
1091
1092 void
1093 Playlist::region_changed_proxy (Change what_changed, Region* region)
1094 {
1095         /* this makes a virtual call to the right kind of playlist ... */
1096
1097         region_changed (what_changed, region);
1098 }
1099
1100 bool
1101 Playlist::region_changed (Change what_changed, Region* region)
1102 {
1103         Change our_interests = Change (Region::MuteChanged|Region::LayerChanged|Region::OpacityChanged);
1104         bool save = false;
1105
1106         if (in_set_state || in_flush) {
1107                 return false;
1108         }
1109
1110         {
1111                 if (what_changed & BoundsChanged) {
1112                         region_bounds_changed (what_changed, region);
1113                         save = !(_splicing || _nudging);
1114                 }
1115                 
1116                 if ((what_changed & Region::MuteChanged) && 
1117                     !(what_changed &  Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged))) {
1118                         check_dependents (*region, false);
1119                 }
1120                 
1121                 if (what_changed & our_interests) {
1122                         save = true;
1123                 }
1124         }
1125
1126         return save;
1127 }
1128
1129 void
1130 Playlist::clear (bool with_delete, bool with_save)
1131 {
1132         RegionList::iterator i;
1133         RegionList tmp;
1134
1135         { 
1136                 RegionLock rl (this);
1137                 tmp = regions;
1138                 regions.clear ();
1139         }
1140         
1141         for (i = tmp.begin(); i != tmp.end(); ++i) {
1142                 notify_region_removed (*i);
1143                 if (with_delete) {
1144                         delete *i;
1145                 }
1146         }
1147
1148         if (with_save) {
1149                 maybe_save_state (_("clear"));
1150         }
1151 }
1152
1153 /***********************************************************************
1154  FINDING THINGS
1155  **********************************************************************/
1156
1157 Playlist::RegionList *
1158 Playlist::regions_at (jack_nframes_t frame)
1159
1160 {
1161         RegionLock rlock (this);
1162         return find_regions_at (frame);
1163 }       
1164
1165 Region *
1166 Playlist::top_region_at (jack_nframes_t frame)
1167
1168 {
1169         RegionLock rlock (this);
1170         RegionList *rlist = find_regions_at (frame);
1171         Region *region = 0;
1172
1173         if (rlist->size()) {
1174                 RegionSortByLayer cmp;
1175                 rlist->sort (cmp);
1176                 region = rlist->back();
1177         } 
1178
1179         delete rlist;
1180         return region;
1181 }       
1182
1183 Playlist::RegionList *
1184 Playlist::find_regions_at (jack_nframes_t frame)
1185 {
1186         RegionList *rlist = new RegionList;
1187
1188         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1189                 if ((*i)->covers (frame)) {
1190                         rlist->push_back (*i);
1191                 }
1192         }
1193
1194         return rlist;
1195 }
1196
1197 Playlist::RegionList *
1198 Playlist::regions_touched (jack_nframes_t start, jack_nframes_t end)
1199 {
1200         RegionLock rlock (this);
1201         RegionList *rlist = new RegionList;
1202
1203         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1204                 if ((*i)->coverage (start, end) != OverlapNone) {
1205                         rlist->push_back (*i);
1206                 }
1207         }
1208
1209         return rlist;
1210 }
1211
1212
1213 Region*
1214
1215 Playlist::find_next_region (jack_nframes_t frame, RegionPoint point, int dir)
1216 {
1217         RegionLock rlock (this);
1218         Region* ret = 0;
1219         jack_nframes_t closest = max_frames;
1220
1221         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1222
1223                 jack_nframes_t distance;
1224                 Region* r = (*i);
1225                 jack_nframes_t pos = 0;
1226
1227                 switch (point) {
1228                 case Start:
1229                         pos = r->first_frame ();
1230                         break;
1231                 case End:
1232                         pos = r->last_frame ();
1233                         break;
1234                 case SyncPoint:
1235                         pos = r->adjust_to_sync (r->first_frame());
1236                         break;
1237                 }
1238
1239                 switch (dir) {
1240                 case 1: /* forwards */
1241
1242                         if (pos > frame) {
1243                                 if ((distance = pos - frame) < closest) {
1244                                         closest = distance;
1245                                         ret = r;
1246                                 }
1247                         }
1248
1249                         break;
1250
1251                 default: /* backwards */
1252
1253                         if (pos < frame) {
1254                                 if ((distance = frame - pos) < closest) {
1255                                         closest = distance;
1256                                         ret = r;
1257                                 }
1258                         }
1259                         break;
1260                 }
1261         }
1262
1263         return ret;
1264 }
1265
1266 /***********************************************************************/
1267
1268
1269
1270 void
1271 Playlist::mark_session_dirty ()
1272 {
1273         if (!in_set_state && !holding_state ()) {
1274                 _session.set_dirty();
1275         }
1276 }
1277
1278 int
1279 Playlist::set_state (const XMLNode& node)
1280 {
1281         in_set_state = true;
1282
1283         XMLNode *child;
1284         XMLNodeList nlist;
1285         XMLNodeConstIterator niter;
1286         XMLPropertyList plist;
1287         XMLPropertyConstIterator piter;
1288         XMLProperty *prop;
1289         Region *region;
1290         string region_name;
1291
1292         clear (false, false);
1293
1294         if (node.name() != "Playlist") {
1295                 in_set_state = false;
1296                 return -1;
1297         }
1298
1299         plist = node.properties();
1300
1301         for (piter = plist.begin(); piter != plist.end(); ++piter) {
1302
1303                 prop = *piter;
1304                 
1305                 if (prop->name() == X_("name")) {
1306                         _name = prop->value();
1307                 } else if (prop->name() == X_("orig_diskstream_id")) {
1308                         sscanf (prop->value().c_str(), "%" PRIu64, &_orig_diskstream_id);
1309                 } else if (prop->name() == X_("frozen")) {
1310                         _frozen = (prop->value() == X_("yes"));
1311                 }
1312         }
1313
1314         nlist = node.children();
1315
1316         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1317
1318                 child = *niter;
1319                 
1320                 if (child->name() == "Region") {
1321
1322                         if ((region = createRegion (_session, *child, true)) == 0) {
1323                                 error << _("Playlist: cannot create region from state file") << endmsg;
1324                                 continue;
1325                         }
1326
1327                         add_region (*region, region->position(), 1.0, false);
1328
1329                 }                       
1330         }
1331
1332         /* update dependents, which was not done during add_region_internal 
1333            due to in_set_state being true 
1334         */
1335
1336         for (RegionList::iterator r = regions.begin(); r != regions.end(); ++r) {
1337                 check_dependents (**r, false);
1338         }
1339
1340         in_set_state = false;
1341
1342         return 0;
1343 }
1344
1345 XMLNode&
1346 Playlist::get_state()
1347 {
1348         return state(true);
1349 }
1350
1351 XMLNode&
1352 Playlist::get_template()
1353 {
1354         return state(false);
1355 }
1356
1357 XMLNode&
1358 Playlist::state (bool full_state)
1359 {
1360         XMLNode *node = new XMLNode (X_("Playlist"));
1361         char buf[64];
1362         
1363         node->add_property (X_("name"), _name);
1364
1365         snprintf (buf, sizeof(buf), "%" PRIu64, _orig_diskstream_id);
1366         node->add_property (X_("orig_diskstream_id"), buf);
1367         node->add_property (X_("frozen"), _frozen ? "yes" : "no");
1368
1369         if (full_state) {
1370                 RegionLock rlock (this, false);
1371
1372                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1373                         node->add_child_nocopy ((*i)->get_state());
1374                 }
1375         }
1376
1377         if (_extra_xml) {
1378                 node->add_child_copy (*_extra_xml);
1379         }
1380
1381         return *node;
1382 }
1383
1384 bool
1385 Playlist::empty() const
1386 {
1387         return regions.empty();
1388 }
1389
1390 jack_nframes_t
1391 Playlist::get_maximum_extent () const
1392 {
1393         RegionLock rlock (const_cast<Playlist *>(this));
1394         return _get_maximum_extent ();
1395 }
1396
1397 jack_nframes_t
1398 Playlist::_get_maximum_extent () const
1399 {
1400         RegionList::const_iterator i;
1401         jack_nframes_t max_extent = 0;
1402         jack_nframes_t end = 0;
1403
1404         for (i = regions.begin(); i != regions.end(); ++i) {
1405                 if ((end = (*i)->position() + (*i)->length()) > max_extent) {
1406                         max_extent = end;
1407                 }
1408         }
1409
1410         return max_extent;
1411 }
1412
1413 string 
1414 Playlist::bump_name (string name, Session &session)
1415 {
1416         string newname = name;
1417
1418         do {
1419                 newname = Playlist::bump_name_once (newname);
1420         } while (session.playlist_by_name(newname)!=NULL);
1421
1422         return newname;
1423 }
1424
1425 string
1426 Playlist::bump_name_once (string name)
1427 {
1428         string::size_type period;
1429         string newname;
1430
1431         if ((period = name.find_last_of ('.')) == string::npos) {
1432                 newname = name;
1433                 newname += ".1";
1434         } else {
1435                 char buf[32];
1436                 int version;
1437                 
1438                 sscanf (name.substr (period+1).c_str(), "%d", &version);
1439                 snprintf (buf, sizeof(buf), "%d", version+1);
1440                 
1441                 newname = name.substr (0, period+1);
1442                 newname += buf;
1443         }
1444
1445         return newname;
1446 }
1447
1448 layer_t
1449 Playlist::top_layer() const
1450 {
1451         RegionLock rlock (const_cast<Playlist *> (this));
1452         layer_t top = 0;
1453
1454         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1455                 top = max (top, (*i)->layer());
1456         }
1457         return top;
1458 }
1459
1460 void
1461 Playlist::set_edit_mode (EditMode mode)
1462 {
1463         _edit_mode = mode;
1464 }
1465
1466 /********************
1467  * Region Layering
1468  ********************/
1469
1470 void
1471 Playlist::relayer ()
1472 {
1473         RegionList::iterator i;
1474         uint32_t layer = 0;
1475
1476         /* don't send multiple Modified notifications
1477            when multiple regions are relayered.
1478         */
1479
1480         freeze ();
1481
1482         if (_session.get_layer_model() == Session::MoveAddHigher || 
1483             _session.get_layer_model() == Session::AddHigher) {
1484
1485                 RegionSortByLastLayerOp cmp;
1486                 RegionList copy = regions;
1487
1488                 copy.sort (cmp);
1489
1490                 for (i = copy.begin(); i != copy.end(); ++i) {
1491                         (*i)->set_layer (layer++);
1492                 }
1493
1494         } else {
1495                 
1496                 /* Session::LaterHigher model */
1497
1498                 for (i = regions.begin(); i != regions.end(); ++i) {
1499                         (*i)->set_layer (layer++);
1500                 }
1501         }
1502
1503         /* sending Modified means that various kinds of layering
1504            models operate correctly at the GUI
1505            level. slightly inefficient, but only slightly.
1506
1507            We force a Modified signal here in case no layers actually
1508            changed.
1509         */
1510
1511         notify_modified ();
1512
1513         thaw ();
1514 }
1515
1516 /* XXX these layer functions are all deprecated */
1517
1518 void
1519 Playlist::raise_region (Region& region)
1520 {
1521         uint32_t rsz = regions.size();
1522         layer_t target = region.layer() + 1U;
1523
1524         if (target >= rsz) {
1525                 /* its already at the effective top */
1526                 return;
1527         }
1528
1529         move_region_to_layer (target, region, 1);
1530 }
1531
1532 void
1533 Playlist::lower_region (Region& region)
1534 {
1535         if (region.layer() == 0) {
1536                 /* its already at the bottom */
1537                 return;
1538         }
1539
1540         layer_t target = region.layer() - 1U;
1541
1542         move_region_to_layer (target, region, -1);
1543 }
1544
1545 void
1546 Playlist::raise_region_to_top (Region& region)
1547 {
1548         /* does nothing useful if layering mode is later=higher */
1549         if ((_session.get_layer_model() == Session::MoveAddHigher) ||
1550             (_session.get_layer_model() == Session::AddHigher)) {
1551                 timestamp_layer_op (region);
1552                 relayer ();
1553         }
1554 }
1555
1556 void
1557 Playlist::lower_region_to_bottom (Region& region)
1558 {
1559         /* does nothing useful if layering mode is later=higher */
1560         if ((_session.get_layer_model() == Session::MoveAddHigher) ||
1561             (_session.get_layer_model() == Session::AddHigher)) {
1562                 region.set_last_layer_op (0);
1563                 relayer ();
1564         }
1565 }
1566
1567 int
1568 Playlist::move_region_to_layer (layer_t target_layer, Region& region, int dir)
1569 {
1570         RegionList::iterator i;
1571         typedef pair<Region*,layer_t> LayerInfo;
1572         list<LayerInfo> layerinfo;
1573         layer_t dest;
1574
1575         {
1576                 RegionLock rlock (const_cast<Playlist *> (this));
1577                 
1578                 for (i = regions.begin(); i != regions.end(); ++i) {
1579                         
1580                         if (&region == *i) {
1581                                 continue;
1582                         }
1583
1584                         if (dir > 0) {
1585
1586                                 /* region is moving up, move all regions on intermediate layers
1587                                    down 1
1588                                 */
1589                                 
1590                                 if ((*i)->layer() > region.layer() && (*i)->layer() <= target_layer) {
1591                                         dest = (*i)->layer() - 1;
1592                                 } else {
1593                                         /* not affected */
1594                                         continue;
1595                                 }
1596                         } else {
1597
1598                                 /* region is moving down, move all regions on intermediate layers
1599                                    up 1
1600                                 */
1601
1602                                 if ((*i)->layer() < region.layer() && (*i)->layer() >= target_layer) {
1603                                         dest = (*i)->layer() + 1;
1604                                 } else {
1605                                         /* not affected */
1606                                         continue;
1607                                 }
1608                         }
1609
1610                         LayerInfo newpair;
1611                         
1612                         newpair.first = *i;
1613                         newpair.second = dest;
1614                         
1615                         layerinfo.push_back (newpair);
1616                 } 
1617         }
1618
1619         /* now reset the layers without holding the region lock */
1620
1621         for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
1622                 x->first->set_layer (x->second);
1623         }
1624
1625         region.set_layer (target_layer);
1626
1627         /* now check all dependents */
1628
1629         for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
1630                 check_dependents (*(x->first), false);
1631         }
1632         
1633         check_dependents (region, false);
1634         
1635         return 0;
1636 }
1637
1638 void
1639 Playlist::nudge_after (jack_nframes_t start, jack_nframes_t distance, bool forwards)
1640 {
1641         RegionList::iterator i;
1642         jack_nframes_t new_pos;
1643         bool moved = false;
1644
1645         _nudging = true;
1646
1647         {
1648                 RegionLock rlock (const_cast<Playlist *> (this));
1649                 
1650                 for (i = regions.begin(); i != regions.end(); ++i) {
1651
1652                         if ((*i)->position() >= start) {
1653
1654                                 if (forwards) {
1655
1656                                         if ((*i)->last_frame() > max_frames - distance) {
1657                                                 new_pos = max_frames - (*i)->length();
1658                                         } else {
1659                                                 new_pos = (*i)->position() + distance;
1660                                         }
1661                                         
1662                                 } else {
1663                                         
1664                                         if ((*i)->position() > distance) {
1665                                                 new_pos = (*i)->position() - distance;
1666                                         } else {
1667                                                 new_pos = 0;
1668                                         }
1669                                 }
1670
1671                                 (*i)->set_position (new_pos, this);
1672                                 moved = true;
1673                         }
1674                 }
1675         }
1676
1677         if (moved) {
1678                 _nudging = false;
1679                 maybe_save_state (_("nudged"));
1680                 notify_length_changed ();
1681         }
1682
1683 }
1684
1685 Region*
1686 Playlist::find_region (id_t id) const
1687 {
1688         RegionLock rlock (const_cast<Playlist*> (this));
1689         RegionList::const_iterator i;
1690         
1691         for (i = regions.begin(); i != regions.end(); ++i) {
1692                 if ((*i)->id() == id) {
1693                         return (*i);
1694                 }
1695         }
1696
1697         return 0;
1698 }
1699         
1700 void
1701 Playlist::save_state (std::string why)
1702 {
1703         if (!in_set_state) {
1704                 StateManager::save_state (why);
1705         }
1706 }
1707
1708 void
1709 Playlist::dump () const
1710 {
1711         Region *r;
1712
1713         cerr << "Playlist \"" << _name << "\" " << endl
1714              << regions.size() << " regions "
1715              << endl;
1716
1717         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1718                 r = *i;
1719                 cerr << "  " << r->name() << " [" 
1720                      << r->start() << "+" << r->length() 
1721                      << "] at " 
1722                      << r->position()
1723                      << " on layer "
1724                      << r->layer ()
1725                      << endl;
1726         }
1727 }
1728
1729 void
1730 Playlist::set_frozen (bool yn)
1731 {
1732         _frozen = yn;
1733 }
1734
1735 void
1736 Playlist::timestamp_layer_op (Region& region)
1737 {
1738 //      struct timeval tv;
1739 //      gettimeofday (&tv, 0);
1740         region.set_last_layer_op (++layer_op_counter);
1741 }
1742
1743 void
1744 Playlist::maybe_save_state (string why)
1745 {
1746         if (holding_state ()) {
1747                 save_on_thaw = true;
1748                 last_save_reason = why;
1749         } else {
1750                 save_state (why);
1751         }
1752 }