fix up meter thread management when JACK client starts/stops/is halted ; put focus...
[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 */
19
20 #include <set>
21 #include <fstream>
22 #include <algorithm>
23 #include <unistd.h>
24 #include <cerrno>
25 #include <string>
26 #include <climits>
27
28 #include <sigc++/bind.h>
29
30 #include <pbd/failed_constructor.h>
31 #include <pbd/stl_delete.h>
32 #include <pbd/xml++.h>
33 #include <pbd/stacktrace.h>
34
35 #include <ardour/playlist.h>
36 #include <ardour/session.h>
37 #include <ardour/region.h>
38 #include <ardour/region_factory.h>
39 #include <ardour/playlist_factory.h>
40 #include <ardour/transient_detector.h>
41
42 #include "i18n.h"
43
44 using namespace std;
45 using namespace ARDOUR;
46 using namespace PBD;
47
48 struct ShowMeTheList {
49     ShowMeTheList (boost::shared_ptr<Playlist> pl, const string& n) : playlist (pl), name (n) {}
50     ~ShowMeTheList () { 
51             cerr << ">>>>" << name << endl; playlist->dump(); cerr << "<<<<" << name << endl << endl; 
52     };
53     boost::shared_ptr<Playlist> playlist;
54     string name;
55 };
56
57 struct RegionSortByLayer {
58     bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
59             return a->layer() < b->layer();
60     }
61 };
62
63 struct RegionSortByPosition {
64     bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<Region> b) {
65             return a->position() < b->position();
66     }
67 };
68
69 struct RegionSortByLastLayerOp {
70     bool operator() (boost::shared_ptr<Region> a, boost::shared_ptr<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         first_set_state = false;
80         _name = nom;
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
90         /* set state called by derived class */
91 }
92
93 Playlist::Playlist (boost::shared_ptr<const Playlist> other, string namestr, bool hide)
94         : _name (namestr), _session (other->_session), _orig_diskstream_id(other->_orig_diskstream_id)
95 {
96         init (hide);
97
98         RegionList tmp;
99         other->copy_regions (tmp);
100         
101         in_set_state++;
102
103         for (list<boost::shared_ptr<Region> >::iterator x = tmp.begin(); x != tmp.end(); ++x) {
104                 add_region_internal( (*x), (*x)->position());
105         }
106
107         in_set_state--;
108
109         _splicing  = other->_splicing;
110         _nudging   = other->_nudging;
111         _edit_mode = other->_edit_mode;
112
113         in_set_state = 0;
114         first_set_state = false;
115         in_flush = false;
116         in_partition = false;
117         subcnt = 0;
118         _read_data_count = 0;
119         _frozen = other->_frozen;
120         
121         layer_op_counter = other->layer_op_counter;
122         freeze_length = other->freeze_length;
123 }
124
125 Playlist::Playlist (boost::shared_ptr<const Playlist> other, nframes_t start, nframes_t cnt, string str, bool hide)
126         : _name (str), _session (other->_session), _orig_diskstream_id(other->_orig_diskstream_id)
127 {
128         RegionLock rlock2 (const_cast<Playlist*> (other.get()));
129
130         nframes_t end = start + cnt - 1;
131
132         init (hide);
133
134         in_set_state++;
135
136         for (RegionList::const_iterator i = other->regions.begin(); i != other->regions.end(); i++) {
137
138                 boost::shared_ptr<Region> region;
139                 boost::shared_ptr<Region> new_region;
140                 nframes_t offset = 0;
141                 nframes_t position = 0;
142                 nframes_t len = 0;
143                 string    new_name;
144                 OverlapType overlap;
145
146                 region = *i;
147
148                 overlap = region->coverage (start, end);
149
150                 switch (overlap) {
151                 case OverlapNone:
152                         continue;
153
154                 case OverlapInternal:
155                         offset = start - region->position();
156                         position = 0;
157                         len = cnt;
158                         break;
159
160                 case OverlapStart:
161                         offset = 0;
162                         position = region->position() - start;
163                         len = end - region->position();
164                         break;
165
166                 case OverlapEnd:
167                         offset = start - region->position();
168                         position = 0;
169                         len = region->length() - offset;
170                         break;
171
172                 case OverlapExternal:
173                         offset = 0;
174                         position = region->position() - start;
175                         len = region->length();
176                         break;
177                 }
178
179                 _session.region_name (new_name, region->name(), false);
180
181                 new_region = RegionFactory::RegionFactory::create (region, offset, len, new_name, region->layer(), region->flags());
182
183                 add_region_internal (new_region, position);
184         }
185         
186         in_set_state--;
187         first_set_state = false;
188
189         /* this constructor does NOT notify others (session) */
190 }
191
192 void
193 Playlist::use ()
194 {
195         ++_refcnt;
196         InUse (true); /* EMIT SIGNAL */
197 }
198
199 void
200 Playlist::release ()
201 {
202         if (_refcnt > 0) {
203                 _refcnt--; 
204         }
205
206         if (_refcnt == 0) {
207                 InUse (false); /* EMIT SIGNAL */
208         }
209 }
210
211 void
212 Playlist::copy_regions (RegionList& newlist) const
213 {
214         RegionLock rlock (const_cast<Playlist *> (this));
215
216         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
217                 newlist.push_back (RegionFactory::RegionFactory::create (*i));
218         }
219 }
220
221 void
222 Playlist::init (bool hide)
223 {
224         g_atomic_int_set (&block_notifications, 0);
225         g_atomic_int_set (&ignore_state_changes, 0);
226         pending_modified = false;
227         pending_length = false;
228         first_set_state = true;
229         _refcnt = 0;
230         _hidden = hide;
231         _splicing = false;
232         _shuffling = false;
233         _nudging = false;
234         in_set_state = 0;
235         _edit_mode = Config->get_edit_mode();
236         in_flush = false;
237         in_partition = false;
238         subcnt = 0;
239         _read_data_count = 0;
240         _frozen = false;
241         layer_op_counter = 0;
242         freeze_length = 0;
243
244         Modified.connect (mem_fun (*this, &Playlist::mark_session_dirty));
245 }
246
247 Playlist::Playlist (const Playlist& pl)
248         : _session (pl._session)
249 {
250         fatal << _("playlist const copy constructor called") << endmsg;
251 }
252
253 Playlist::Playlist (Playlist& pl)
254         : _session (pl._session)
255 {
256         fatal << _("playlist non-const copy constructor called") << endmsg;
257 }
258
259 Playlist::~Playlist ()
260 {
261         { 
262                 RegionLock rl (this);
263
264                 for (set<boost::shared_ptr<Region> >::iterator i = all_regions.begin(); i != all_regions.end(); ++i) {
265                         (*i)->set_playlist (boost::shared_ptr<Playlist>());
266                 }
267         }
268
269         /* GoingAway must be emitted by derived classes */
270 }
271
272 void
273 Playlist::set_name (string str)
274 {
275         /* in a typical situation, a playlist is being used
276            by one diskstream and also is referenced by the
277            Session. if there are more references than that,
278            then don't change the name.
279         */
280
281         if (_refcnt > 2) {
282                 return;
283         }
284
285         if (str == _name) {
286                 return;
287         }
288
289         string name = str;
290
291         while (_session.playlist_by_name(name) != 0) {
292                 name = bump_name_once(name);
293         }
294
295         _name = name; 
296         NameChanged(); /* EMIT SIGNAL */
297 }
298
299 /***********************************************************************
300  CHANGE NOTIFICATION HANDLING
301  
302  Notifications must be delayed till the region_lock is released. This
303  is necessary because handlers for the signals may need to acquire
304  the lock (e.g. to read from the playlist).
305  ***********************************************************************/
306
307 void
308 Playlist::freeze ()
309 {
310         delay_notifications ();
311         g_atomic_int_inc (&ignore_state_changes);
312 }
313
314 void
315 Playlist::thaw ()
316 {
317         g_atomic_int_dec_and_test (&ignore_state_changes);
318         release_notifications ();
319 }
320
321
322 void
323 Playlist::delay_notifications ()
324 {
325         g_atomic_int_inc (&block_notifications);
326         freeze_length = _get_maximum_extent();
327 }
328
329 void
330 Playlist::release_notifications ()
331 {
332         if (g_atomic_int_dec_and_test (&block_notifications)) { 
333                 flush_notifications ();
334         } 
335 }
336
337
338 void
339 Playlist::notify_modified ()
340 {
341         if (holding_state ()) {
342                 pending_modified = true;
343         } else {
344                 pending_modified = false;
345                 Modified(); /* EMIT SIGNAL */
346         }
347 }
348
349 void
350 Playlist::notify_region_removed (boost::shared_ptr<Region> r)
351 {
352         if (holding_state ()) {
353                 pending_removes.insert (r);
354                 pending_modified = true;
355                 pending_length = true;
356         } else {
357                 /* this might not be true, but we have to act
358                    as though it could be.
359                 */
360                 LengthChanged (); /* EMIT SIGNAL */
361                 Modified (); /* EMIT SIGNAL */
362         }
363 }
364
365 void
366 Playlist::notify_region_added (boost::shared_ptr<Region> r)
367 {
368         /* the length change might not be true, but we have to act
369            as though it could be.
370         */
371
372         if (holding_state()) {
373                 pending_adds.insert (r);
374                 pending_modified = true;
375                 pending_length = true;
376         } else {
377                 LengthChanged (); /* EMIT SIGNAL */
378                 Modified (); /* EMIT SIGNAL */
379         }
380 }
381
382 void
383 Playlist::notify_length_changed ()
384 {
385         if (holding_state ()) {
386                 pending_length = true;
387         } else {
388                 LengthChanged(); /* EMIT SIGNAL */
389                 Modified (); /* EMIT SIGNAL */
390         }
391 }
392
393 void
394 Playlist::flush_notifications ()
395 {
396         set<boost::shared_ptr<Region> > dependent_checks_needed;
397         set<boost::shared_ptr<Region> >::iterator s;
398         uint32_t n = 0;
399
400         if (in_flush) {
401                 return;
402         }
403
404         in_flush = true;
405
406         /* we have no idea what order the regions ended up in pending
407            bounds (it could be based on selection order, for example).
408            so, to preserve layering in the "most recently moved is higher" 
409            model, sort them by existing layer, then timestamp them.
410         */
411
412         // RegionSortByLayer cmp;
413         // pending_bounds.sort (cmp);
414
415         for (RegionList::iterator r = pending_bounds.begin(); r != pending_bounds.end(); ++r) {
416                 if (Config->get_layer_model() == MoveAddHigher) {
417                         timestamp_layer_op (*r);
418                 }
419                 pending_length = true;
420                 dependent_checks_needed.insert (*r);
421                 n++;
422         }
423
424         for (s = pending_adds.begin(); s != pending_adds.end(); ++s) {
425                 dependent_checks_needed.insert (*s);
426                 n++;
427         }
428
429         for (s = pending_removes.begin(); s != pending_removes.end(); ++s) {
430                 remove_dependents (*s);
431                 n++;
432         }
433
434         if ((freeze_length != _get_maximum_extent()) || pending_length) {
435                 pending_length = 0;
436                 LengthChanged(); /* EMIT SIGNAL */
437                 n++;
438         }
439
440         if (n || pending_modified) {
441                 if (!in_set_state) {
442                         relayer ();
443                 }
444                 pending_modified = false;
445                 Modified (); /* EMIT SIGNAL */
446         }
447
448         for (s = dependent_checks_needed.begin(); s != dependent_checks_needed.end(); ++s) {
449                 check_dependents (*s, false);
450         }
451
452         pending_adds.clear ();
453         pending_removes.clear ();
454         pending_bounds.clear ();
455
456         in_flush = false;
457 }
458
459 /*************************************************************
460   PLAYLIST OPERATIONS
461  *************************************************************/
462
463 void
464 Playlist::add_region (boost::shared_ptr<Region> region, nframes_t position, float times) 
465
466         RegionLock rlock (this);
467         
468         times = fabs (times);
469         
470         int itimes = (int) floor (times);
471
472         nframes_t pos = position;
473         
474         if (itimes >= 1) {
475                 add_region_internal (region, pos);
476                 pos += region->length();
477                 --itimes;
478         }
479
480         
481         /* note that itimes can be zero if we being asked to just
482            insert a single fraction of the region.
483         */
484
485         for (int i = 0; i < itimes; ++i) {
486                 boost::shared_ptr<Region> copy = RegionFactory::create (region);
487                 add_region_internal (copy, pos);
488                 pos += region->length();
489         }
490         
491         nframes_t length = 0;
492
493         if (floor (times) != times) {
494                 length = (nframes_t) floor (region->length() * (times - floor (times)));
495                 string name;
496                 _session.region_name (name, region->name(), false);
497                 boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags());
498                 add_region_internal (sub, pos);
499         }
500
501
502         possibly_splice_unlocked (position, (pos + length) - position, boost::shared_ptr<Region>());
503 }
504
505 void
506 Playlist::set_region_ownership ()
507 {
508         RegionLock rl (this);
509         RegionList::iterator i;
510         boost::weak_ptr<Playlist> pl (shared_from_this());
511
512         for (i = regions.begin(); i != regions.end(); ++i) {
513                 (*i)->set_playlist (pl);
514         }
515 }
516
517 void
518 Playlist::add_region_internal (boost::shared_ptr<Region> region, nframes_t position)
519 {
520         RegionSortByPosition cmp;
521         nframes_t old_length = 0;
522
523         if (!holding_state()) {
524                  old_length = _get_maximum_extent();
525         }
526
527         if (!first_set_state) {
528                 boost::shared_ptr<Playlist> foo (shared_from_this());
529                 region->set_playlist (boost::weak_ptr<Playlist>(foo));
530         } 
531
532         region->set_position (position, this);
533
534         timestamp_layer_op (region);
535
536         regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
537         all_regions.insert (region);
538
539         possibly_splice_unlocked (position, region->length(), region);
540
541         if (!holding_state () && !in_set_state) {
542                 /* layers get assigned from XML state */
543                 relayer ();
544         }
545
546         /* we need to notify the existence of new region before checking dependents. Ick. */
547
548         notify_region_added (region);
549         
550         if (!holding_state ()) {
551                 check_dependents (region, false);
552                 if (old_length != _get_maximum_extent()) {
553                         notify_length_changed ();
554                 }
555         }
556
557         region->StateChanged.connect (sigc::bind (mem_fun (this, &Playlist::region_changed_proxy), 
558                                                   boost::weak_ptr<Region> (region)));
559 }
560
561 void
562 Playlist::replace_region (boost::shared_ptr<Region> old, boost::shared_ptr<Region> newr, nframes_t pos)
563 {
564         RegionLock rlock (this);
565
566         bool old_sp = _splicing;
567         _splicing = true;
568
569         remove_region_internal (old);
570         add_region_internal (newr, pos);
571
572         _splicing = old_sp;
573
574         possibly_splice_unlocked (pos, (nframes64_t) old->length() - (nframes64_t) newr->length());
575 }
576
577 void
578 Playlist::remove_region (boost::shared_ptr<Region> region)
579 {
580         RegionLock rlock (this);
581         remove_region_internal (region);
582 }
583
584 int
585 Playlist::remove_region_internal (boost::shared_ptr<Region> region)
586 {
587         RegionList::iterator i;
588         nframes_t old_length = 0;
589
590         if (!holding_state()) {
591                 old_length = _get_maximum_extent();
592         }
593
594         if (!in_set_state) {
595                 /* unset playlist */
596                 region->set_playlist (boost::weak_ptr<Playlist>());
597         }
598
599         for (i = regions.begin(); i != regions.end(); ++i) {
600                 if (*i == region) {
601
602                         nframes_t pos = (*i)->position();
603                         nframes64_t distance = (*i)->length();
604
605                         regions.erase (i);
606
607                         possibly_splice_unlocked (pos, -distance);
608
609                         if (!holding_state ()) {
610                                 relayer ();
611                                 remove_dependents (region);
612                                 
613                                 if (old_length != _get_maximum_extent()) {
614                                         notify_length_changed ();
615                                 }
616                         }
617
618                         notify_region_removed (region);
619                         return 0;
620                 }
621         }
622
623
624
625         return -1;
626 }
627
628 void
629 Playlist::get_equivalent_regions (boost::shared_ptr<Region> other, vector<boost::shared_ptr<Region> >& results)
630 {
631         if (Config->get_use_overlap_equivalency()) {
632                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
633                         if ((*i)->overlap_equivalent (other)) {
634                                 results.push_back ((*i));
635                         }
636                 }
637         } else {
638                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
639                         if ((*i)->equivalent (other)) {
640                                 results.push_back ((*i));
641                         }
642                 }
643         }
644 }
645
646 void
647 Playlist::get_region_list_equivalent_regions (boost::shared_ptr<Region> other, vector<boost::shared_ptr<Region> >& results)
648 {
649         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
650
651                 if ((*i) && (*i)->region_list_equivalent (other)) {
652                         results.push_back (*i);
653                 }
654         }
655 }
656
657 void
658 Playlist::partition (nframes_t start, nframes_t end, bool just_top_level)
659 {
660         RegionList thawlist;
661
662         partition_internal (start, end, false, thawlist);
663
664         for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
665                 (*i)->thaw ("separation");
666         }
667 }
668
669 void
670 Playlist::partition_internal (nframes_t start, nframes_t end, bool cutting, RegionList& thawlist)
671 {
672         RegionList new_regions;
673
674         {
675                 RegionLock rlock (this);
676                 boost::shared_ptr<Region> region;
677                 boost::shared_ptr<Region> current;
678                 string new_name;
679                 RegionList::iterator tmp;
680                 OverlapType overlap;
681                 nframes_t pos1, pos2, pos3, pos4;
682                 
683                 in_partition = true;
684                 
685                 /* need to work from a copy, because otherwise the regions we add during the process
686                    get operated on as well.
687                 */
688                 
689                 RegionList copy = regions;
690                 
691                 for (RegionList::iterator i = copy.begin(); i != copy.end(); i = tmp) {
692                         
693                         tmp = i;
694                         ++tmp;
695                         
696                         current = *i;
697
698                         if (current->first_frame() >= start && current->last_frame() < end) {
699                                 if (cutting) {
700                                         remove_region_internal (current);
701                                 }
702                                 continue;
703                         }
704                         
705                         /* coverage will return OverlapStart if the start coincides
706                            with the end point. we do not partition such a region,
707                            so catch this special case.
708                         */
709
710                         if (current->first_frame() >= end) {
711                                 continue;
712                         }
713
714                         if ((overlap = current->coverage (start, end)) == OverlapNone) {
715                                 continue;
716                         }
717
718                         pos1 = current->position();
719                         pos2 = start;
720                         pos3 = end;
721                         pos4 = current->last_frame();
722                         
723                         if (overlap == OverlapInternal) {
724                         
725                                 /* split: we need 3 new regions, the front, middle and end.
726                                    cut:   we need 2 regions, the front and end.
727                                 */
728                                 
729                                 /*
730                                          start                 end
731                           ---------------*************************------------
732                                          P1  P2              P3  P4
733                           SPLIT:
734                           ---------------*****++++++++++++++++====------------
735                           CUT
736                           ---------------*****----------------====------------
737                           
738                                 */
739
740                                 if (!cutting) {
741                                 
742                                         /* "middle" ++++++ */
743                                         
744                                         _session.region_name (new_name, current->name(), false);
745                                         region = RegionFactory::create (current, pos2 - pos1, pos3 - pos2, new_name,
746                                                                         regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit|Region::RightOfSplit));
747                                         add_region_internal (region, start);
748                                         new_regions.push_back (region);
749                                 }
750                                 
751                                 /* "end" ====== */
752                         
753                                 _session.region_name (new_name, current->name(), false);
754                                 region = RegionFactory::create (current, pos3 - pos1, pos4 - pos3, new_name, 
755                                                                 regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
756                                 
757                                 add_region_internal (region, end);
758                                 new_regions.push_back (region);
759                                 
760                                 /* "front" ***** */
761                                 
762                                 current->freeze ();
763                                 thawlist.push_back (current);
764                                 current->trim_end (pos2, this);
765                                 
766                         } else if (overlap == OverlapEnd) {
767                                 
768                                 /*
769                                                               start           end
770                                     ---------------*************************------------
771                                                    P1           P2         P4   P3
772                                     SPLIT:                                                 
773                                     ---------------**************+++++++++++------------
774                                     CUT:                                                   
775                                     ---------------**************-----------------------
776                                 */
777                                 
778                                 if (!cutting) {
779                                         
780                                         /* end +++++ */
781                                         
782                                         _session.region_name (new_name, current->name(), false);
783                                         region = RegionFactory::create (current, pos2 - pos1, pos4 - pos2, new_name, (layer_t) regions.size(),
784                                                                         Region::Flag(current->flags()|Region::Automatic|Region::LeftOfSplit));
785                                         add_region_internal (region, start);
786                                         new_regions.push_back (region);
787                                 }
788                                 
789                                 /* front ****** */
790                                 
791                                 current->freeze ();
792                                 thawlist.push_back (current);
793                                 current->trim_end (pos2, this);
794                                 
795                         } else if (overlap == OverlapStart) {
796                                 
797                                 /* split: we need 2 regions: the front and the end.
798                                    cut: just trim current to skip the cut area
799                                 */
800                                 
801                                 /*
802                                                         start           end
803                                     ---------------*************************------------
804                                        P2          P1 P3                   P4          
805
806                                     SPLIT:
807                                     ---------------****+++++++++++++++++++++------------
808                                     CUT:
809                                     -------------------*********************------------
810                                     
811                                 */
812
813                                 if (!cutting) {
814                                 
815                                         /* front **** */
816                                         _session.region_name (new_name, current->name(), false);
817                                         region = RegionFactory::create (current, 0, pos3 - pos1, new_name,
818                                                                         regions.size(), Region::Flag(current->flags()|Region::Automatic|Region::RightOfSplit));
819                                         add_region_internal (region, pos1);
820                                         new_regions.push_back (region);
821                                 } 
822                                 
823                                 /* end */
824                                 
825                                 current->freeze ();
826                                 thawlist.push_back (current);
827                                 current->trim_front (pos3, this);
828                                 
829                         } else if (overlap == OverlapExternal) {
830                                 
831                                 /* split: no split required.
832                                    cut: remove the region.
833                                 */
834                                 
835                                 /*
836                                        start                                      end
837                                     ---------------*************************------------
838                                        P2          P1 P3                   P4          
839
840                                     SPLIT:
841                                     ---------------*************************------------
842                                     CUT:
843                                     ----------------------------------------------------
844                                     
845                                 */
846                                 
847                                 if (cutting) {
848                                         remove_region_internal (current);
849                                 }
850                                 new_regions.push_back (current);
851                         }
852                 }
853                 
854                 if (current->first_frame() >= current->last_frame()) {
855                         PBD::stacktrace (cerr);
856                 }
857
858                 in_partition = false;
859         }
860
861         for (RegionList::iterator i = new_regions.begin(); i != new_regions.end(); ++i) {
862                 check_dependents (*i, false);
863         }
864 }
865
866 boost::shared_ptr<Playlist>
867 Playlist::cut_copy (boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t, nframes_t,bool), list<AudioRange>& ranges, bool result_is_hidden)
868 {
869         boost::shared_ptr<Playlist> ret;
870         boost::shared_ptr<Playlist> pl;
871         nframes_t start;
872
873         if (ranges.empty()) {
874                 return boost::shared_ptr<Playlist>();
875         }
876
877         start = ranges.front().start;
878
879         for (list<AudioRange>::iterator i = ranges.begin(); i != ranges.end(); ++i) {
880
881                 pl = (this->*pmf)((*i).start, (*i).length(), result_is_hidden);
882                 
883                 if (i == ranges.begin()) {
884                         ret = pl;
885                 } else {
886                         
887                         /* paste the next section into the nascent playlist,
888                            offset to reflect the start of the first range we
889                            chopped.
890                         */
891
892                         ret->paste (pl, (*i).start - start, 1.0f);
893                 }
894         }
895
896         return ret;
897 }
898
899 boost::shared_ptr<Playlist>
900 Playlist::cut (list<AudioRange>& ranges, bool result_is_hidden)
901 {
902         boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t,nframes_t,bool) = &Playlist::cut;
903         return cut_copy (pmf, ranges, result_is_hidden);
904 }
905
906 boost::shared_ptr<Playlist>
907 Playlist::copy (list<AudioRange>& ranges, bool result_is_hidden)
908 {
909         boost::shared_ptr<Playlist> (Playlist::*pmf)(nframes_t,nframes_t,bool) = &Playlist::copy;
910         return cut_copy (pmf, ranges, result_is_hidden);
911 }
912
913 boost::shared_ptr<Playlist>
914 Playlist::cut (nframes_t start, nframes_t cnt, bool result_is_hidden)
915 {
916         boost::shared_ptr<Playlist> the_copy;
917         RegionList thawlist;
918         char buf[32];
919
920         snprintf (buf, sizeof (buf), "%" PRIu32, ++subcnt);
921         string new_name = _name;
922         new_name += '.';
923         new_name += buf;
924
925         if ((the_copy = PlaylistFactory::create (shared_from_this(), start, cnt, new_name, result_is_hidden)) == 0) {
926                 return boost::shared_ptr<Playlist>();
927         }
928
929         partition_internal (start, start+cnt-1, true, thawlist);
930
931         for (RegionList::iterator i = thawlist.begin(); i != thawlist.end(); ++i) {
932                 (*i)->thaw ("playlist cut");
933         }
934
935         return the_copy;
936 }
937
938 boost::shared_ptr<Playlist>
939 Playlist::copy (nframes_t start, nframes_t cnt, bool result_is_hidden)
940 {
941         char buf[32];
942         
943         snprintf (buf, sizeof (buf), "%" PRIu32, ++subcnt);
944         string new_name = _name;
945         new_name += '.';
946         new_name += buf;
947
948         cnt = min (_get_maximum_extent() - start, cnt);
949         return PlaylistFactory::create (shared_from_this(), start, cnt, new_name, result_is_hidden);
950 }
951
952 int
953 Playlist::paste (boost::shared_ptr<Playlist> other, nframes_t position, float times)
954 {
955         times = fabs (times);
956         nframes_t old_length;
957
958         {
959                 RegionLock rl1 (this);
960                 RegionLock rl2 (other.get());
961
962                 old_length = _get_maximum_extent();
963         
964                 int itimes = (int) floor (times);
965                 nframes_t pos = position;
966                 nframes_t shift = other->_get_maximum_extent();
967                 layer_t top_layer = regions.size();
968
969                 while (itimes--) {
970                         for (RegionList::iterator i = other->regions.begin(); i != other->regions.end(); ++i) {
971                                 boost::shared_ptr<Region> copy_of_region = RegionFactory::create (*i);
972
973                                 /* put these new regions on top of all existing ones, but preserve
974                                    the ordering they had in the original playlist.
975                                 */
976                                 
977                                 copy_of_region->set_layer (copy_of_region->layer() + top_layer);
978                                 add_region_internal (copy_of_region, copy_of_region->position() + pos);
979                         }
980                         pos += shift;
981                 }
982
983
984                 /* XXX shall we handle fractional cases at some point? */
985
986                 if (old_length != _get_maximum_extent()) {
987                         notify_length_changed ();
988                 }
989
990                 
991         }
992
993         return 0;
994 }
995
996
997 void
998 Playlist::duplicate (boost::shared_ptr<Region> region, nframes_t position, float times)
999 {
1000         times = fabs (times);
1001
1002         RegionLock rl (this);
1003         int itimes = (int) floor (times);
1004         nframes_t pos = position;
1005
1006         while (itimes--) {
1007                 boost::shared_ptr<Region> copy = RegionFactory::create (region);
1008                 add_region_internal (copy, pos);
1009                 pos += region->length();
1010         }
1011
1012         if (floor (times) != times) {
1013                 nframes_t length = (nframes_t) floor (region->length() * (times - floor (times)));
1014                 string name;
1015                 _session.region_name (name, region->name(), false);
1016                 boost::shared_ptr<Region> sub = RegionFactory::create (region, 0, length, name, region->layer(), region->flags());
1017                 add_region_internal (sub, pos);
1018         }
1019 }
1020
1021 void
1022 Playlist::split_region (boost::shared_ptr<Region> region, nframes_t playlist_position)
1023 {
1024         RegionLock rl (this);
1025
1026         if (!region->covers (playlist_position)) {
1027                 return;
1028         }
1029
1030         if (region->position() == playlist_position ||
1031             region->last_frame() == playlist_position) {
1032                 return;
1033         }
1034
1035         boost::shared_ptr<Region> left;
1036         boost::shared_ptr<Region> right;
1037         nframes_t before;
1038         nframes_t after;
1039         string before_name;
1040         string after_name;
1041
1042         /* split doesn't change anything about length, so don't try to splice */
1043         
1044         bool old_sp = _splicing;
1045         _splicing = true;
1046
1047         before = playlist_position - region->position();
1048         after = region->length() - before;
1049         
1050         _session.region_name (before_name, region->name(), false);
1051         left = RegionFactory::create (region, 0, before, before_name, region->layer(), Region::Flag (region->flags()|Region::LeftOfSplit));
1052
1053         _session.region_name (after_name, region->name(), false);
1054         right = RegionFactory::create (region, before, after, after_name, region->layer(), Region::Flag (region->flags()|Region::RightOfSplit));
1055
1056         add_region_internal (left, region->position());
1057         add_region_internal (right, region->position() + before);
1058
1059         uint64_t orig_layer_op = region->last_layer_op();
1060         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1061                 if ((*i)->last_layer_op() > orig_layer_op) {
1062                         (*i)->set_last_layer_op( (*i)->last_layer_op() + 1 );
1063                 }
1064         }
1065         
1066         left->set_last_layer_op ( orig_layer_op );
1067         right->set_last_layer_op ( orig_layer_op + 1);
1068
1069         layer_op_counter++;
1070
1071         finalize_split_region (region, left, right);
1072         
1073         remove_region_internal (region);
1074
1075         _splicing = old_sp;
1076 }
1077
1078 void
1079 Playlist::possibly_splice (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
1080 {
1081         if (_splicing || in_set_state) {
1082                 /* don't respond to splicing moves or state setting */
1083                 return;
1084         }
1085
1086         if (_edit_mode == Splice) {
1087                 splice_locked (at, distance, exclude);
1088         }
1089 }
1090
1091 void
1092 Playlist::possibly_splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
1093 {
1094         if (_splicing || in_set_state) {
1095                 /* don't respond to splicing moves or state setting */
1096                 return;
1097         }
1098
1099         if (_edit_mode == Splice) {
1100                 splice_unlocked (at, distance, exclude);
1101         }
1102 }
1103
1104 void
1105 Playlist::splice_locked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
1106 {
1107         {
1108                 RegionLock rl (this);
1109                 core_splice (at, distance, exclude);
1110         }
1111 }
1112
1113 void
1114 Playlist::splice_unlocked (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
1115 {
1116         core_splice (at, distance, exclude);
1117 }
1118
1119 void
1120 Playlist::core_splice (nframes_t at, nframes64_t distance, boost::shared_ptr<Region> exclude)
1121 {
1122         _splicing = true;
1123
1124         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1125
1126                 if (exclude && (*i) == exclude) {
1127                         continue;
1128                 }
1129
1130                 if ((*i)->position() >= at) {
1131                         nframes64_t new_pos = (*i)->position() + distance;
1132                         if (new_pos < 0) {
1133                                 new_pos = 0;
1134                         } else if (new_pos >= max_frames - (*i)->length()) {
1135                                 new_pos = max_frames - (*i)->length();
1136                         } 
1137                                 
1138                         (*i)->set_position (new_pos, this);
1139                 }
1140         }
1141
1142         _splicing = false;
1143
1144         notify_length_changed ();
1145 }
1146
1147 void
1148 Playlist::region_bounds_changed (Change what_changed, boost::shared_ptr<Region> region)
1149 {
1150         if (in_set_state || _splicing || _nudging || _shuffling) {
1151                 return;
1152         }
1153
1154         if (what_changed & ARDOUR::PositionChanged) {
1155
1156                 /* remove it from the list then add it back in
1157                    the right place again.
1158                 */
1159                 
1160                 RegionSortByPosition cmp;
1161
1162                 RegionList::iterator i = find (regions.begin(), regions.end(), region);
1163                 
1164                 if (i == regions.end()) {
1165                         warning << string_compose (_("%1: bounds changed received for region (%2)not in playlist"),
1166                                             _name, region->name())
1167                                 << endmsg;
1168                         return;
1169                 }
1170
1171                 regions.erase (i);
1172                 regions.insert (upper_bound (regions.begin(), regions.end(), region, cmp), region);
1173         }
1174
1175         if (what_changed & Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged)) {
1176                 
1177                 nframes64_t delta = 0;
1178                 
1179                 if (what_changed & ARDOUR::PositionChanged) {
1180                         delta = (nframes64_t) region->position() - (nframes64_t) region->last_position();
1181                 } 
1182                 
1183                 if (what_changed & ARDOUR::LengthChanged) {
1184                         delta += (nframes64_t) region->length() - (nframes64_t) region->last_length();
1185                 } 
1186
1187                 if (delta) {
1188                         possibly_splice (region->last_position() + region->last_length(), delta, region);
1189                 }
1190
1191                 if (holding_state ()) {
1192                         pending_bounds.push_back (region);
1193                 } else {
1194                         if (Config->get_layer_model() == MoveAddHigher) {
1195                                 /* it moved or changed length, so change the timestamp */
1196                                 timestamp_layer_op (region);
1197                         }
1198                         
1199                         notify_length_changed ();
1200                         relayer ();
1201                         check_dependents (region, false);
1202                 }
1203         }
1204 }
1205
1206 void
1207 Playlist::region_changed_proxy (Change what_changed, boost::weak_ptr<Region> weak_region)
1208 {
1209         boost::shared_ptr<Region> region (weak_region.lock());
1210
1211         if (!region) {
1212                 return;
1213         }
1214
1215
1216         /* this makes a virtual call to the right kind of playlist ... */
1217
1218         region_changed (what_changed, region);
1219 }
1220
1221 bool
1222 Playlist::region_changed (Change what_changed, boost::shared_ptr<Region> region)
1223 {
1224         Change our_interests = Change (Region::MuteChanged|Region::LayerChanged|Region::OpacityChanged);
1225         bool save = false;
1226
1227         if (in_set_state || in_flush) {
1228                 return false;
1229         }
1230
1231         {
1232                 if (what_changed & BoundsChanged) {
1233                         region_bounds_changed (what_changed, region);
1234                         save = !(_splicing || _nudging);
1235                 }
1236                 
1237                 if ((what_changed & our_interests) && 
1238                     !(what_changed &  Change (ARDOUR::PositionChanged|ARDOUR::LengthChanged))) {
1239                         check_dependents (region, false);
1240                 }
1241                 
1242                 if (what_changed & our_interests) {
1243                         save = true;
1244                 }
1245         }
1246
1247         return save;
1248 }
1249
1250 void
1251 Playlist::drop_regions ()
1252 {
1253         RegionLock rl (this);
1254         regions.clear ();
1255         all_regions.clear ();
1256 }
1257
1258 void
1259 Playlist::clear (bool with_signals)
1260 {
1261         { 
1262                 RegionLock rl (this);
1263                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1264                         pending_removes.insert (*i);
1265                 }
1266                 regions.clear ();
1267         }
1268
1269         if (with_signals) {
1270                 LengthChanged ();
1271                 Modified ();
1272         }
1273
1274 }
1275
1276 /***********************************************************************
1277  FINDING THINGS
1278  **********************************************************************/
1279
1280 Playlist::RegionList *
1281 Playlist::regions_at (nframes_t frame)
1282
1283 {
1284         RegionLock rlock (this);
1285         return find_regions_at (frame);
1286 }       
1287
1288 boost::shared_ptr<Region>
1289 Playlist::top_region_at (nframes_t frame)
1290
1291 {
1292         RegionLock rlock (this);
1293         RegionList *rlist = find_regions_at (frame);
1294         boost::shared_ptr<Region> region;
1295         
1296         if (rlist->size()) {
1297                 RegionSortByLayer cmp;
1298                 rlist->sort (cmp);
1299                 region = rlist->back();
1300         } 
1301
1302         delete rlist;
1303         return region;
1304 }       
1305
1306 Playlist::RegionList*
1307 Playlist::regions_to_read (nframes_t start, nframes_t end)
1308 {
1309         /* Caller must hold lock */
1310
1311         RegionList covering;
1312         set<nframes_t> to_check;
1313         set<boost::shared_ptr<Region> > unique;
1314         RegionList here;
1315
1316         to_check.insert (start);
1317         to_check.insert (end);
1318
1319         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1320
1321                 /* find all/any regions that span start+end */
1322
1323                 switch ((*i)->coverage (start, end)) {
1324                 case OverlapNone:
1325                         break;
1326
1327                 case OverlapInternal:
1328                         covering.push_back (*i);
1329                         break;
1330
1331                 case OverlapStart:
1332                         to_check.insert ((*i)->position());
1333                         covering.push_back (*i);
1334                         break;
1335
1336                 case OverlapEnd:
1337                         to_check.insert ((*i)->last_frame());
1338                         covering.push_back (*i);
1339                         break;
1340
1341                 case OverlapExternal:
1342                         covering.push_back (*i);
1343                         to_check.insert ((*i)->position());
1344                         to_check.insert ((*i)->last_frame());
1345                         break;
1346                 }
1347
1348                 /* don't go too far */
1349
1350                 if ((*i)->position() > end) {
1351                         break;
1352                 }
1353         }
1354
1355         RegionList* rlist = new RegionList;
1356
1357         /* find all the regions that cover each position .... */
1358
1359         if (covering.size() == 1) {
1360
1361                 rlist->push_back (covering.front());
1362                 
1363         } else {
1364         
1365                 for (set<nframes_t>::iterator t = to_check.begin(); t != to_check.end(); ++t) {
1366                         
1367                         here.clear ();
1368                         
1369                         for (RegionList::iterator x = covering.begin(); x != covering.end(); ++x) {
1370                         
1371                                 if ((*x)->covers (*t)) {
1372                                         here.push_back (*x);
1373                                 }
1374                         }
1375                         
1376                         RegionSortByLayer cmp;
1377                         here.sort (cmp);
1378                         
1379                         /* ... and get the top/transparent regions at "here" */
1380                         
1381                         for (RegionList::reverse_iterator c = here.rbegin(); c != here.rend(); ++c) {
1382                                 
1383                                 unique.insert (*c);
1384                                 
1385                                 if ((*c)->opaque()) {
1386                                         
1387                                         /* the other regions at this position are hidden by this one */
1388                                         
1389                                         break;
1390                                 }
1391                         }
1392                 }
1393                 
1394                 for (set<boost::shared_ptr<Region> >::iterator s = unique.begin(); s != unique.end(); ++s) {
1395                         rlist->push_back (*s);
1396                 }
1397
1398                 if (rlist->size() > 1) {
1399                         /* now sort by time order */
1400                         
1401                         RegionSortByPosition cmp;
1402                         rlist->sort (cmp);
1403                 }
1404         }
1405
1406         return rlist;
1407 }
1408
1409 Playlist::RegionList *
1410 Playlist::find_regions_at (nframes_t frame)
1411 {
1412         /* Caller must hold lock */
1413
1414         RegionList *rlist = new RegionList;
1415
1416         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1417                 if ((*i)->covers (frame)) {
1418                         rlist->push_back (*i);
1419                 }
1420         }
1421
1422         return rlist;
1423 }
1424
1425 Playlist::RegionList *
1426 Playlist::regions_touched (nframes_t start, nframes_t end)
1427 {
1428         RegionLock rlock (this);
1429         RegionList *rlist = new RegionList;
1430
1431         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1432                 if ((*i)->coverage (start, end) != OverlapNone) {
1433                         rlist->push_back (*i);
1434                 }
1435         }
1436
1437         return rlist;
1438 }
1439
1440 nframes64_t
1441 Playlist::find_next_transient (nframes64_t from, int dir)
1442 {
1443         RegionLock rlock (this);
1444         AnalysisFeatureList points;
1445         AnalysisFeatureList these_points;
1446
1447         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1448                 if (dir > 0) {
1449                         if ((*i)->last_frame() < from) {
1450                                 continue;
1451                         }
1452                 } else {
1453                         if ((*i)->first_frame() > from) {
1454                                 continue;
1455                         }
1456                 }
1457
1458                 (*i)->get_transients (these_points);
1459
1460                 /* add first frame, just, err, because */
1461                 
1462                 these_points.push_back ((*i)->first_frame());
1463                 
1464                 points.insert (points.end(), these_points.begin(), these_points.end());
1465                 these_points.clear ();
1466         }
1467         
1468         if (points.empty()) {
1469                 return -1;
1470         }
1471
1472         TransientDetector::cleanup_transients (points, _session.frame_rate(), 3.0);
1473         bool reached = false;
1474         
1475         if (dir > 0) {
1476                 for (AnalysisFeatureList::iterator x = points.begin(); x != points.end(); ++x) {
1477                         if ((*x) >= from) {
1478                                 reached = true;
1479                         }
1480                         
1481                         if (reached && (*x) > from) {
1482                                 return *x;
1483                         }
1484                 }
1485         } else {
1486                 for (AnalysisFeatureList::reverse_iterator x = points.rbegin(); x != points.rend(); ++x) {
1487                         if ((*x) <= from) {
1488                                 reached = true;
1489                         }
1490                         
1491                         if (reached && (*x) < from) {
1492                                 return *x;
1493                         }
1494                 }
1495         }
1496
1497         return -1;
1498 }
1499
1500 boost::shared_ptr<Region>
1501 Playlist::find_next_region (nframes_t frame, RegionPoint point, int dir)
1502 {
1503         RegionLock rlock (this);
1504         boost::shared_ptr<Region> ret;
1505         nframes_t closest = max_frames;
1506
1507
1508         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1509
1510                 nframes_t distance;
1511                 boost::shared_ptr<Region> r = (*i);
1512                 nframes_t pos = 0;
1513
1514                 switch (point) {
1515                 case Start:
1516                         pos = r->first_frame ();
1517                         break;
1518                 case End:
1519                         pos = r->last_frame ();
1520                         break;
1521                 case SyncPoint:
1522                         pos = r->adjust_to_sync (r->first_frame());
1523                         break;
1524                 }
1525
1526                 switch (dir) {
1527                 case 1: /* forwards */
1528
1529                         if (pos >= frame) {
1530                                 if ((distance = pos - frame) < closest) {
1531                                         closest = distance;
1532                                         ret = r;
1533                                 }
1534                         }
1535
1536                         break;
1537
1538                 default: /* backwards */
1539
1540                         if (pos <= frame) {
1541                                 if ((distance = frame - pos) < closest) {
1542                                         closest = distance;
1543                                         ret = r;
1544                                 }
1545                         }
1546                         break;
1547                 }
1548         }
1549
1550         return ret;
1551 }
1552
1553 nframes64_t
1554 Playlist::find_next_region_boundary (nframes64_t frame, int dir)
1555 {
1556         RegionLock rlock (this);
1557
1558         nframes64_t closest = max_frames;
1559         nframes64_t ret = -1;
1560
1561         if (dir > 0) {
1562
1563                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1564                         
1565                         boost::shared_ptr<Region> r = (*i);
1566                         nframes64_t distance;
1567                         nframes64_t end = r->position() + r->length();
1568                         bool reset;
1569
1570                         reset = false;
1571
1572                         if (r->first_frame() > frame) {
1573
1574                                 distance = r->first_frame() - frame;
1575                                 
1576                                 if (distance < closest) {
1577                                         ret = r->first_frame();
1578                                         closest = distance;
1579                                         reset = true;
1580                                 }
1581                         }
1582
1583                         if (end > frame) {
1584                                 
1585                                 distance = end - frame;
1586                                 
1587                                 if (distance < closest) {
1588                                         ret = end;
1589                                         closest = distance;
1590                                         reset = true;
1591                                 }
1592                         }
1593
1594                         if (reset) {
1595                                 break;
1596                         }
1597                 }
1598
1599         } else {
1600
1601                 for (RegionList::reverse_iterator i = regions.rbegin(); i != regions.rend(); ++i) {
1602                         
1603                         boost::shared_ptr<Region> r = (*i);
1604                         nframes64_t distance;
1605                         bool reset;
1606
1607                         reset = false;
1608
1609                         if (r->last_frame() < frame) {
1610
1611                                 distance = frame - r->last_frame();
1612                                 
1613                                 if (distance < closest) {
1614                                         ret = r->last_frame();
1615                                         closest = distance;
1616                                         reset = true;
1617                                 }
1618                         }
1619
1620                         if (r->first_frame() < frame) {
1621                                 distance = frame - r->last_frame();
1622                                 
1623                                 if (distance < closest) {
1624                                         ret = r->first_frame();
1625                                         closest = distance;
1626                                         reset = true;
1627                                 }
1628                         }
1629
1630                         if (reset) {
1631                                 break;
1632                         }
1633                 }
1634         }
1635
1636         return ret;
1637 }
1638
1639 /***********************************************************************/
1640
1641
1642
1643 void
1644 Playlist::mark_session_dirty ()
1645 {
1646         if (!in_set_state && !holding_state ()) {
1647                 _session.set_dirty();
1648         }
1649 }
1650
1651 int
1652 Playlist::set_state (const XMLNode& node)
1653 {
1654         XMLNode *child;
1655         XMLNodeList nlist;
1656         XMLNodeConstIterator niter;
1657         XMLPropertyList plist;
1658         XMLPropertyConstIterator piter;
1659         XMLProperty *prop;
1660         boost::shared_ptr<Region> region;
1661         string region_name;
1662
1663         in_set_state++;
1664
1665         if (node.name() != "Playlist") {
1666                 in_set_state--;
1667                 return -1;
1668         }
1669
1670         freeze ();
1671
1672         plist = node.properties();
1673
1674         for (piter = plist.begin(); piter != plist.end(); ++piter) {
1675
1676                 prop = *piter;
1677                 
1678                 if (prop->name() == X_("name")) {
1679                         _name = prop->value();
1680                 } else if (prop->name() == X_("orig_diskstream_id")) {
1681                         _orig_diskstream_id = prop->value ();
1682                 } else if (prop->name() == X_("frozen")) {
1683                         _frozen = (prop->value() == X_("yes"));
1684                 }
1685         }
1686
1687         clear (false);
1688         
1689         nlist = node.children();
1690
1691         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1692
1693                 child = *niter;
1694                 
1695                 if (child->name() == "Region") {
1696
1697                         if ((prop = child->property ("id")) == 0) {
1698                                 error << _("region state node has no ID, ignored") << endmsg;
1699                                 continue;
1700                         }
1701                         
1702                         ID id = prop->value ();
1703                         
1704                         if ((region = region_by_id (id))) {
1705
1706                                 Change what_changed = Change (0);
1707
1708                                 if (region->set_live_state (*child, what_changed, true)) {
1709                                         error << _("Playlist: cannot reset region state from XML") << endmsg;
1710                                         continue;
1711                                 }
1712
1713                         } else if ((region = RegionFactory::create (_session, *child, true)) == 0) {
1714                                 error << _("Playlist: cannot create region from XML") << endmsg;
1715                                 continue;
1716                         }
1717
1718                         add_region (region, region->position(), 1.0);
1719
1720                         // So that layer_op ordering doesn't get screwed up
1721                         region->set_last_layer_op( region->layer());
1722
1723                 }                       
1724         }
1725         
1726         notify_modified ();
1727
1728         thaw ();
1729
1730         /* update dependents, which was not done during add_region_internal 
1731            due to in_set_state being true 
1732         */
1733
1734         for (RegionList::iterator r = regions.begin(); r != regions.end(); ++r) {
1735                 check_dependents (*r, false);
1736         }
1737
1738         in_set_state--;
1739         first_set_state = false;
1740         return 0;
1741 }
1742
1743 XMLNode&
1744 Playlist::get_state()
1745 {
1746         return state(true);
1747 }
1748
1749 XMLNode&
1750 Playlist::get_template()
1751 {
1752         return state(false);
1753 }
1754
1755 XMLNode&
1756 Playlist::state (bool full_state)
1757 {
1758         XMLNode *node = new XMLNode (X_("Playlist"));
1759         char buf[64];
1760         
1761         node->add_property (X_("name"), _name);
1762
1763         _orig_diskstream_id.print (buf, sizeof (buf));
1764         node->add_property (X_("orig_diskstream_id"), buf);
1765         node->add_property (X_("frozen"), _frozen ? "yes" : "no");
1766
1767         if (full_state) {
1768                 RegionLock rlock (this, false);
1769                 for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
1770                         node->add_child_nocopy ((*i)->get_state());
1771                 }
1772         }
1773
1774         if (_extra_xml) {
1775                 node->add_child_copy (*_extra_xml);
1776         }
1777
1778         return *node;
1779 }
1780
1781 bool
1782 Playlist::empty() const
1783 {
1784         RegionLock rlock (const_cast<Playlist *>(this), false);
1785         return regions.empty();
1786 }
1787
1788 uint32_t
1789 Playlist::n_regions() const
1790 {
1791         RegionLock rlock (const_cast<Playlist *>(this), false);
1792         return regions.size();
1793 }
1794
1795 nframes_t
1796 Playlist::get_maximum_extent () const
1797 {
1798         RegionLock rlock (const_cast<Playlist *>(this), false);
1799         return _get_maximum_extent ();
1800 }
1801
1802 nframes_t
1803 Playlist::_get_maximum_extent () const
1804 {
1805         RegionList::const_iterator i;
1806         nframes_t max_extent = 0;
1807         nframes_t end = 0;
1808
1809         for (i = regions.begin(); i != regions.end(); ++i) {
1810                 if ((end = (*i)->position() + (*i)->length()) > max_extent) {
1811                         max_extent = end;
1812                 }
1813         }
1814
1815         return max_extent;
1816 }
1817
1818 string 
1819 Playlist::bump_name (string name, Session &session)
1820 {
1821         string newname = name;
1822
1823         do {
1824                 newname = bump_name_once (newname);
1825         } while (session.playlist_by_name (newname)!=NULL);
1826
1827         return newname;
1828 }
1829
1830
1831 layer_t
1832 Playlist::top_layer() const
1833 {
1834         RegionLock rlock (const_cast<Playlist *> (this));
1835         layer_t top = 0;
1836
1837         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1838                 top = max (top, (*i)->layer());
1839         }
1840         return top;
1841 }
1842
1843 void
1844 Playlist::set_edit_mode (EditMode mode)
1845 {
1846         _edit_mode = mode;
1847 }
1848
1849 /********************
1850  * Region Layering
1851  ********************/
1852
1853 void
1854 Playlist::relayer ()
1855 {
1856         RegionList::iterator i;
1857         uint32_t layer = 0;
1858
1859         /* don't send multiple Modified notifications
1860            when multiple regions are relayered.
1861         */
1862
1863         freeze ();
1864
1865         if (Config->get_layer_model() == MoveAddHigher || 
1866             Config->get_layer_model() == AddHigher) {
1867
1868                 RegionSortByLastLayerOp cmp;
1869                 RegionList copy = regions;
1870
1871                 copy.sort (cmp);
1872
1873                 for (i = copy.begin(); i != copy.end(); ++i) {
1874                         (*i)->set_layer (layer++);
1875                 }
1876
1877         } else {
1878                 
1879                 /* Session::LaterHigher model */
1880
1881                 for (i = regions.begin(); i != regions.end(); ++i) {
1882                         (*i)->set_layer (layer++);
1883                 }
1884         }
1885
1886         /* sending Modified means that various kinds of layering
1887            models operate correctly at the GUI
1888            level. slightly inefficient, but only slightly.
1889
1890            We force a Modified signal here in case no layers actually
1891            changed.
1892         */
1893
1894         notify_modified ();
1895
1896         thaw ();
1897 }
1898
1899 /* XXX these layer functions are all deprecated */
1900
1901 void
1902 Playlist::raise_region (boost::shared_ptr<Region> region)
1903 {
1904         uint32_t rsz = regions.size();
1905         layer_t target = region->layer() + 1U;
1906
1907         if (target >= rsz) {
1908                 /* its already at the effective top */
1909                 return;
1910         }
1911
1912         move_region_to_layer (target, region, 1);
1913 }
1914
1915 void
1916 Playlist::lower_region (boost::shared_ptr<Region> region)
1917 {
1918         if (region->layer() == 0) {
1919                 /* its already at the bottom */
1920                 return;
1921         }
1922
1923         layer_t target = region->layer() - 1U;
1924
1925         move_region_to_layer (target, region, -1);
1926 }
1927
1928 void
1929 Playlist::raise_region_to_top (boost::shared_ptr<Region> region)
1930 {
1931         /* does nothing useful if layering mode is later=higher */
1932         if ((Config->get_layer_model() == MoveAddHigher) ||
1933             (Config->get_layer_model() == AddHigher)) {
1934                 timestamp_layer_op (region);
1935                 relayer ();
1936         }
1937 }
1938
1939 void
1940 Playlist::lower_region_to_bottom (boost::shared_ptr<Region> region)
1941 {
1942         /* does nothing useful if layering mode is later=higher */
1943         if ((Config->get_layer_model() == MoveAddHigher) ||
1944             (Config->get_layer_model() == AddHigher)) {
1945                 region->set_last_layer_op (0);
1946                 relayer ();
1947         }
1948 }
1949
1950 int
1951 Playlist::move_region_to_layer (layer_t target_layer, boost::shared_ptr<Region> region, int dir)
1952 {
1953         RegionList::iterator i;
1954         typedef pair<boost::shared_ptr<Region>,layer_t> LayerInfo;
1955         list<LayerInfo> layerinfo;
1956         layer_t dest;
1957
1958         {
1959                 RegionLock rlock (const_cast<Playlist *> (this));
1960                 
1961                 for (i = regions.begin(); i != regions.end(); ++i) {
1962                         
1963                         if (region == *i) {
1964                                 continue;
1965                         }
1966
1967                         if (dir > 0) {
1968
1969                                 /* region is moving up, move all regions on intermediate layers
1970                                    down 1
1971                                 */
1972                                 
1973                                 if ((*i)->layer() > region->layer() && (*i)->layer() <= target_layer) {
1974                                         dest = (*i)->layer() - 1;
1975                                 } else {
1976                                         /* not affected */
1977                                         continue;
1978                                 }
1979                         } else {
1980
1981                                 /* region is moving down, move all regions on intermediate layers
1982                                    up 1
1983                                 */
1984
1985                                 if ((*i)->layer() < region->layer() && (*i)->layer() >= target_layer) {
1986                                         dest = (*i)->layer() + 1;
1987                                 } else {
1988                                         /* not affected */
1989                                         continue;
1990                                 }
1991                         }
1992
1993                         LayerInfo newpair;
1994                         
1995                         newpair.first = *i;
1996                         newpair.second = dest;
1997                         
1998                         layerinfo.push_back (newpair);
1999                 } 
2000         }
2001
2002         /* now reset the layers without holding the region lock */
2003
2004         for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
2005                 x->first->set_layer (x->second);
2006         }
2007
2008         region->set_layer (target_layer);
2009
2010 #if 0
2011         /* now check all dependents */
2012
2013         for (list<LayerInfo>::iterator x = layerinfo.begin(); x != layerinfo.end(); ++x) {
2014                 check_dependents (x->first, false);
2015         }
2016         
2017         check_dependents (region, false);
2018 #endif
2019         
2020         return 0;
2021 }
2022
2023 void
2024 Playlist::nudge_after (nframes_t start, nframes_t distance, bool forwards)
2025 {
2026         RegionList::iterator i;
2027         nframes_t new_pos;
2028         bool moved = false;
2029
2030         _nudging = true;
2031
2032         {
2033                 RegionLock rlock (const_cast<Playlist *> (this));
2034                 
2035                 for (i = regions.begin(); i != regions.end(); ++i) {
2036
2037                         if ((*i)->position() >= start) {
2038
2039                                 if (forwards) {
2040
2041                                         if ((*i)->last_frame() > max_frames - distance) {
2042                                                 new_pos = max_frames - (*i)->length();
2043                                         } else {
2044                                                 new_pos = (*i)->position() + distance;
2045                                         }
2046                                         
2047                                 } else {
2048                                         
2049                                         if ((*i)->position() > distance) {
2050                                                 new_pos = (*i)->position() - distance;
2051                                         } else {
2052                                                 new_pos = 0;
2053                                         }
2054                                 }
2055
2056                                 (*i)->set_position (new_pos, this);
2057                                 moved = true;
2058                         }
2059                 }
2060         }
2061
2062         if (moved) {
2063                 _nudging = false;
2064                 notify_length_changed ();
2065         }
2066
2067 }
2068
2069 boost::shared_ptr<Region>
2070 Playlist::find_region (const ID& id) const
2071 {
2072         RegionLock rlock (const_cast<Playlist*> (this));
2073
2074         /* searches all regions currently in use by the playlist */
2075
2076         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2077                 if ((*i)->id() == id) {
2078                         return *i;
2079                 }
2080         }
2081
2082         return boost::shared_ptr<Region> ();
2083 }
2084
2085 boost::shared_ptr<Region>
2086 Playlist::region_by_id (ID id)
2087 {
2088         /* searches all regions ever added to this playlist */
2089
2090         for (set<boost::shared_ptr<Region> >::iterator i = all_regions.begin(); i != all_regions.end(); ++i) {
2091                 if ((*i)->id() == id) {
2092                         return *i;
2093                 }
2094         }
2095         return boost::shared_ptr<Region> ();
2096 }
2097         
2098 void
2099 Playlist::dump () const
2100 {
2101         boost::shared_ptr<Region> r;
2102
2103         cerr << "Playlist \"" << _name << "\" " << endl
2104              << regions.size() << " regions "
2105              << endl;
2106
2107         for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2108                 r = *i;
2109                 cerr << "  " << r->name() << " [" 
2110                      << r->start() << "+" << r->length() 
2111                      << "] at " 
2112                      << r->position()
2113                      << " on layer "
2114                      << r->layer ()
2115                      << endl;
2116         }
2117 }
2118
2119 void
2120 Playlist::set_frozen (bool yn)
2121 {
2122         _frozen = yn;
2123 }
2124
2125 void
2126 Playlist::timestamp_layer_op (boost::shared_ptr<Region> region)
2127 {
2128 //      struct timeval tv;
2129 //      gettimeofday (&tv, 0);
2130         region->set_last_layer_op (++layer_op_counter);
2131 }
2132
2133
2134 void
2135 Playlist::shuffle (boost::shared_ptr<Region> region, int dir)
2136 {
2137         bool moved = false;
2138         nframes_t new_pos;
2139
2140         if (region->locked()) {
2141                 return;
2142         }
2143
2144         _shuffling = true;
2145
2146         {
2147                 RegionLock rlock (const_cast<Playlist*> (this));
2148                 
2149                 
2150                 if (dir > 0) {
2151                         
2152                         RegionList::iterator next;
2153
2154                         for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {       
2155                                 if ((*i) == region) {
2156                                         next = i;
2157                                         ++next;
2158
2159                                         if (next != regions.end()) {
2160
2161                                                 if ((*next)->locked()) {
2162                                                         break;
2163                                                 }
2164
2165                                                 if ((*next)->position() != region->last_frame() + 1) {
2166                                                         /* they didn't used to touch, so after shuffle,
2167                                                            just have them swap positions.
2168                                                         */
2169                                                         new_pos = (*next)->position();
2170                                                 } else {
2171                                                         /* they used to touch, so after shuffle,
2172                                                            make sure they still do. put the earlier
2173                                                            region where the later one will end after
2174                                                            it is moved.
2175                                                         */
2176                                                         new_pos = region->position() + (*next)->length();
2177                                                 }
2178
2179                                                 (*next)->set_position (region->position(), this);
2180                                                 region->set_position (new_pos, this);
2181
2182                                                 /* avoid a full sort */
2183
2184                                                 regions.erase (i); // removes the region from the list */
2185                                                 next++;
2186                                                 regions.insert (next, region); // adds it back after next
2187
2188                                                 moved = true;
2189                                         }
2190                                         break;
2191                                 }
2192                         }
2193                 } else {
2194                         
2195                         RegionList::iterator prev = regions.end();
2196                         
2197                         for (RegionList::iterator i = regions.begin(); i != regions.end(); prev = i, ++i) {     
2198                                 if ((*i) == region) {
2199
2200                                         if (prev != regions.end()) {
2201
2202                                                 if ((*prev)->locked()) {
2203                                                         break;
2204                                                 }
2205
2206                                                 if (region->position() != (*prev)->last_frame() + 1) {
2207                                                         /* they didn't used to touch, so after shuffle,
2208                                                            just have them swap positions.
2209                                                         */
2210                                                         new_pos = region->position();
2211                                                 } else {
2212                                                         /* they used to touch, so after shuffle,
2213                                                            make sure they still do. put the earlier
2214                                                            one where the later one will end after
2215                                                         */
2216                                                         new_pos = (*prev)->position() + region->length();
2217                                                 }
2218
2219                                                 region->set_position ((*prev)->position(), this);
2220                                                 (*prev)->set_position (new_pos, this);
2221                                                 
2222                                                 /* avoid a full sort */
2223
2224                                                 regions.erase (i); // remove region
2225                                                 regions.insert (prev, region); // insert region before prev
2226
2227                                                 moved = true;
2228                                         }
2229
2230                                         break;
2231                                 }
2232                         }
2233                 }
2234         }
2235
2236         _shuffling = false;
2237
2238         if (moved) {
2239
2240                 relayer ();
2241                 check_dependents (region, false);
2242                 
2243                 notify_modified();
2244         }
2245
2246 }
2247
2248 bool
2249 Playlist::region_is_shuffle_constrained (boost::shared_ptr<Region>) 
2250 {
2251         RegionLock rlock (const_cast<Playlist*> (this));
2252         
2253         if (regions.size() > 1) {
2254                 return true;
2255         }
2256
2257         return false;
2258 }
2259
2260 void
2261 Playlist::update_after_tempo_map_change ()
2262 {
2263         RegionLock rlock (const_cast<Playlist*> (this));
2264         RegionList copy (regions);
2265
2266         freeze ();
2267         
2268         for (RegionList::iterator i = copy.begin(); i != copy.end(); ++i) {     
2269                 (*i)->update_position_after_tempo_map_change ();
2270         }
2271
2272         thaw ();
2273 }