more changes to try to improve MTC handling even in slightly pathological cases
[ardour.git] / libs / ardour / region_factory.cc
1 /*
2     Copyright (C) 2000-2006 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 "pbd/error.h"
21 #include "pbd/boost_debug.h"
22
23 #include "ardour/session.h"
24
25 #include "ardour/region_factory.h"
26 #include "ardour/region.h"
27 #include "ardour/audioregion.h"
28 #include "ardour/audiosource.h"
29 #include "ardour/midi_source.h"
30 #include "ardour/midi_region.h"
31
32 #include "i18n.h"
33
34 using namespace ARDOUR;
35 using namespace PBD;
36
37 sigc::signal<void,boost::shared_ptr<Region> > RegionFactory::CheckNewRegion;
38
39 boost::shared_ptr<Region>
40 RegionFactory::create (boost::shared_ptr<Region> region, nframes_t start,
41                        nframes_t length, const std::string& name,
42                        layer_t layer, Region::Flag flags, bool announce)
43 {
44         boost::shared_ptr<const AudioRegion> other_a;
45         boost::shared_ptr<const MidiRegion> other_m;
46
47         if ((other_a = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
48                 AudioRegion* ar = new AudioRegion (other_a, start, length, name, layer, flags);
49                 boost_debug_shared_ptr_mark_interesting (ar, typeid (ar).name());
50                 boost::shared_ptr<AudioRegion> arp (ar);
51                 boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
52                 ret->unlock_property_changes ();
53                 if (announce) {
54                         CheckNewRegion (ret);
55                 }
56                 return ret;
57         } else if ((other_m = boost::dynamic_pointer_cast<MidiRegion>(region)) != 0) {
58                 MidiRegion* ar = new MidiRegion (other_m, start, length, name, layer, flags);
59                 boost::shared_ptr<MidiRegion> arp (ar);
60                 boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
61                 ret->unlock_property_changes ();
62                 if (announce) {
63                         CheckNewRegion (ret);
64                 }
65                 return ret;
66         } else {
67                 fatal << _("programming error: RegionFactory::create() called with unknown Region type")
68                       << endmsg;
69                 /*NOTREACHED*/
70                 return boost::shared_ptr<Region>();
71         }
72 }
73
74 boost::shared_ptr<Region>
75 RegionFactory::create (boost::shared_ptr<const Region> region)
76 {
77         boost::shared_ptr<const AudioRegion> ar;
78         boost::shared_ptr<const MidiRegion> mr;
79
80         if ((ar = boost::dynamic_pointer_cast<const AudioRegion>(region)) != 0) {
81                 AudioRegion* arn = new AudioRegion (ar);
82                 boost_debug_shared_ptr_mark_interesting (arn, typeid (arn).name());
83                 boost::shared_ptr<Region> ret (arn);
84                 ret->unlock_property_changes ();
85                 /* pure copy constructor - no CheckNewRegion emitted */
86                 return ret;
87         } else if ((mr = boost::dynamic_pointer_cast<const MidiRegion>(region)) != 0) {
88                 boost::shared_ptr<Region> ret (new MidiRegion (mr));
89                 ret->unlock_property_changes ();
90                 /* pure copy constructor - no CheckNewRegion emitted */
91                 return ret;
92         } else {
93                 fatal << _("programming error: RegionFactory::create() called with unknown Region type")
94                       << endmsg;
95                 /*NOTREACHED*/
96                 return boost::shared_ptr<Region>();
97         }
98 }
99
100 boost::shared_ptr<Region>
101 RegionFactory::create (boost::shared_ptr<AudioRegion> region, nframes_t start,
102                        nframes_t length, const std::string& name,
103                        layer_t layer, Region::Flag flags, bool announce)
104 {
105         return create (boost::static_pointer_cast<Region> (region), start, length, name, layer, flags, announce);
106 }
107
108 boost::shared_ptr<Region>
109 RegionFactory::create (boost::shared_ptr<Region> region, const SourceList& srcs,
110                        const std::string& name, layer_t layer, Region::Flag flags, bool announce)
111
112 {
113         boost::shared_ptr<const AudioRegion> other;
114
115         /* used by AudioFilter when constructing a new region that is intended to have nearly
116            identical settings to an original, but using different sources.
117         */
118
119         if ((other = boost::dynamic_pointer_cast<AudioRegion>(region)) != 0) {
120                 AudioRegion* ar = new AudioRegion (other, srcs, srcs.front()->length(srcs.front()->timeline_position()), name, layer, flags);
121                 boost_debug_shared_ptr_mark_interesting (ar, typeid (ar).name());
122                 boost::shared_ptr<AudioRegion> arp (ar);
123                 boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
124                 ret->unlock_property_changes ();
125                 if (announce) {
126                         CheckNewRegion (ret);
127                 }
128                 return ret;
129         } else {
130                 fatal << _("programming error: RegionFactory::create() called with unknown Region type")
131                       << endmsg;
132                 /*NOTREACHED*/
133                 return boost::shared_ptr<Region>();
134         }
135 }
136
137 boost::shared_ptr<Region>
138 RegionFactory::create (Session& session, XMLNode& node, bool yn)
139 {
140         boost::shared_ptr<Region> r = session.XMLRegionFactory (node, yn);
141
142         if (r) {
143                 r->unlock_property_changes ();
144                 CheckNewRegion (r);
145         }
146
147         return r;
148 }
149
150 boost::shared_ptr<Region>
151 RegionFactory::create (const SourceList& srcs, nframes_t start, nframes_t length, const string& name, layer_t layer, Region::Flag flags, bool announce)
152 {
153         if (srcs.empty()) {
154                 return boost::shared_ptr<Region>();
155         }
156
157         if (srcs[0]->type() == DataType::AUDIO) {
158
159                 AudioRegion* ar = new AudioRegion (srcs, start, length, name, layer, flags);
160                 boost_debug_shared_ptr_mark_interesting (ar, typeid (ar).name());
161                 boost::shared_ptr<AudioRegion> arp (ar);
162                 boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (arp));
163                 ret->unlock_property_changes ();
164                 if (announce) {
165                         CheckNewRegion (ret);
166                 }
167                 return ret;
168
169         } else if (srcs[0]->type() == DataType::MIDI) {
170
171                 MidiRegion* ar = new MidiRegion (srcs, start, length, name, layer, flags);
172                 boost::shared_ptr<MidiRegion> mrp (ar);
173                 boost::shared_ptr<Region> ret (boost::static_pointer_cast<Region> (mrp));
174                 ret->unlock_property_changes ();
175                 if (announce) {
176                         CheckNewRegion (ret);
177                 }
178                 return ret;
179
180         }
181
182         return boost::shared_ptr<Region> ();
183 }
184
185 boost::shared_ptr<Region>
186 RegionFactory::create (SourceList& srcs, const XMLNode& node)
187 {
188         if (srcs.empty()) {
189                 return boost::shared_ptr<Region>();
190         }
191
192         if (srcs[0]->type() == DataType::AUDIO) {
193                 AudioRegion* ar = new AudioRegion (srcs, node);
194                 boost_debug_shared_ptr_mark_interesting (ar, typeid (ar).name());
195                 boost::shared_ptr<Region> ret (ar);
196                 ret->unlock_property_changes ();
197                 CheckNewRegion (ret);
198                 return ret;
199         } else if (srcs[0]->type() == DataType::MIDI) {
200                 boost::shared_ptr<Region> ret (new MidiRegion (srcs, node));
201                 ret->unlock_property_changes ();
202                 CheckNewRegion (ret);
203                 return ret;
204         }
205
206         return boost::shared_ptr<Region> ();
207 }
208
209 boost::shared_ptr<Region>
210 RegionFactory::create (boost::shared_ptr<Source> src, nframes_t start, nframes_t length, const string& name, layer_t layer, Region::Flag flags, bool announce)
211 {
212         boost::shared_ptr<AudioSource> as;
213         boost::shared_ptr<MidiSource> ms;
214
215         if ((as = boost::dynamic_pointer_cast<AudioSource>(src)) != 0) {
216                 AudioRegion* ar = new AudioRegion (as, start, length, name, layer, flags);
217                 boost_debug_shared_ptr_mark_interesting (ar, typeid (ar).name());
218                 boost::shared_ptr<Region> ret (ar);
219                 ret->unlock_property_changes ();
220                 if (announce) {
221                         CheckNewRegion (ret);
222                 }
223                 return ret;
224         } else if ((ms = boost::dynamic_pointer_cast<MidiSource>(src)) != 0) {
225                 boost::shared_ptr<Region> ret (new MidiRegion (ms, start, length, name, layer, flags));
226                 ret->unlock_property_changes ();
227                 if (announce) {
228                         CheckNewRegion (ret);
229                 }
230                 return ret;
231         }
232
233         return boost::shared_ptr<Region>();
234 }