fixes for 98% of all the warnings/errors reported by OS X gcc on tiger
[ardour.git] / libs / ardour / source_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     $Id$
19 */
20
21 #ifdef WAF_BUILD
22 #include "libardour-config.h"
23 #endif
24
25 #include "pbd/boost_debug.h"
26 #include "pbd/error.h"
27 #include "pbd/convert.h"
28 #include "pbd/pthread_utils.h"
29 #include "pbd/stacktrace.h"
30
31 #include "ardour/audioplaylist.h"
32 #include "ardour/audio_playlist_source.h"
33 #include "ardour/midi_playlist.h"
34 #include "ardour/midi_playlist_source.h"
35 #include "ardour/source_factory.h"
36 #include "ardour/sndfilesource.h"
37 #include "ardour/silentfilesource.h"
38 #include "ardour/rc_configuration.h"
39 #include "ardour/smf_source.h"
40 #include "ardour/session.h"
41
42 #ifdef  HAVE_COREAUDIO
43 #define USE_COREAUDIO_FOR_FILES
44 #endif
45
46 #ifdef USE_COREAUDIO_FOR_FILES
47 #include "ardour/coreaudiosource.h"
48 #endif
49
50
51 #include "i18n.h"
52
53 using namespace ARDOUR;
54 using namespace std;
55 using namespace PBD;
56
57 PBD::Signal1<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
58 Glib::Cond* SourceFactory::PeaksToBuild;
59 Glib::StaticMutex SourceFactory::peak_building_lock = GLIBMM_STATIC_MUTEX_INIT;
60 std::list<boost::weak_ptr<AudioSource> > SourceFactory::files_with_peaks;
61
62 static void
63 peak_thread_work ()
64 {
65         SessionEvent::create_per_thread_pool (X_("PeakFile Builder "), 64);
66
67         while (true) {
68
69                 SourceFactory::peak_building_lock.lock ();
70
71           wait:
72                 if (SourceFactory::files_with_peaks.empty()) {
73                         SourceFactory::PeaksToBuild->wait (SourceFactory::peak_building_lock);
74                 }
75
76                 if (SourceFactory::files_with_peaks.empty()) {
77                         goto wait;
78                 }
79
80                 boost::shared_ptr<AudioSource> as (SourceFactory::files_with_peaks.front().lock());
81                 SourceFactory::files_with_peaks.pop_front ();
82                 SourceFactory::peak_building_lock.unlock ();
83
84                 if (!as) {
85                         continue;
86                 }
87
88                 as->setup_peakfile ();
89         }
90 }
91
92 void
93 SourceFactory::init ()
94 {
95         PeaksToBuild = new Glib::Cond();
96
97         for (int n = 0; n < 2; ++n) {
98                 Glib::Thread::create (sigc::ptr_fun (::peak_thread_work), false);
99         }
100 }
101
102 int
103 SourceFactory::setup_peakfile (boost::shared_ptr<Source> s, bool async)
104 {
105         boost::shared_ptr<AudioSource> as (boost::dynamic_pointer_cast<AudioSource> (s));
106
107         if (as) {
108
109                 if (async) {
110
111                         Glib::Mutex::Lock lm (peak_building_lock);
112                         files_with_peaks.push_back (boost::weak_ptr<AudioSource> (as));
113                         PeaksToBuild->broadcast ();
114
115                 } else {
116
117                         if (as->setup_peakfile ()) {
118                                 error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg;
119                                 return -1;
120                         }
121                 }
122         }
123
124         return 0;
125 }
126
127 boost::shared_ptr<Source>
128 SourceFactory::createSilent (Session& s, const XMLNode& node, framecnt_t nframes, float sr)
129 {
130         Source* src = new SilentFileSource (s, node, nframes, sr);
131 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
132         // boost_debug_shared_ptr_mark_interesting (src, "Source");
133 #endif
134         boost::shared_ptr<Source> ret (src);
135         // no analysis data - the file is non-existent
136         SourceCreated (ret);
137         return ret;
138 }
139
140 boost::shared_ptr<Source>
141 SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
142 {
143         DataType type = DataType::AUDIO;
144         const XMLProperty* prop = node.property("type");
145
146         if (prop) {
147                 type = DataType (prop->value());
148         }
149
150         if (type == DataType::AUDIO) {
151
152                 /* it could be nested */
153
154                 if (node.property ("playlist") != 0) {
155
156                         try {
157                                 boost::shared_ptr<AudioPlaylistSource> ap (new AudioPlaylistSource (s, node));
158                                 
159                                 if (setup_peakfile (ap, true)) {
160                                         return boost::shared_ptr<Source>();
161                                 }
162
163                                 ap->check_for_analysis_data_on_disk ();
164
165                                 SourceCreated (ap);
166                                 return ap;
167
168                         } catch (failed_constructor&) {
169                                 /* oh well, so much for that then ... */
170                         }
171
172                 } else {
173
174
175                         try {
176                                 Source* src = new SndFileSource (s, node);
177 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
178                                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
179 #endif
180                                 boost::shared_ptr<Source> ret (src);
181                                 if (setup_peakfile (ret, defer_peaks)) {
182                                         return boost::shared_ptr<Source>();
183                                 }
184                                 ret->check_for_analysis_data_on_disk ();
185                                 SourceCreated (ret);
186                                 return ret;
187                         }
188
189                         catch (failed_constructor& err) {
190
191 #ifdef USE_COREAUDIO_FOR_FILES
192
193                                 /* this is allowed to throw */
194
195                                 Source *src = new CoreAudioSource (s, node);
196 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
197                                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
198 #endif
199                                 boost::shared_ptr<Source> ret (src);
200
201                                 if (setup_peakfile (ret, defer_peaks)) {
202                                         return boost::shared_ptr<Source>();
203                                 }
204
205                                 ret->check_for_analysis_data_on_disk ();
206                                 SourceCreated (ret);
207                                 return ret;
208 #else
209                                 throw; // rethrow
210 #endif
211                         }
212                 }
213         } else if (type == DataType::MIDI) {
214                 boost::shared_ptr<SMFSource> src (new SMFSource (s, node));
215                 src->load_model (true, true);
216 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
217                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
218 #endif
219                 src->check_for_analysis_data_on_disk ();
220                 SourceCreated (src);
221                 return src;
222         }
223
224         return boost::shared_ptr<Source>();
225 }
226
227 boost::shared_ptr<Source>
228 SourceFactory::createReadable (DataType type, Session& s, const string& path,
229                                int chn, Source::Flag flags, bool announce, bool defer_peaks)
230 {
231         if (type == DataType::AUDIO) {
232
233                 if (!(flags & Destructive)) {
234
235                         try {
236
237                                 Source* src = new SndFileSource (s, path, chn, flags);
238 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
239                                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
240 #endif
241                                 boost::shared_ptr<Source> ret (src);
242
243                                 if (setup_peakfile (ret, defer_peaks)) {
244                                         return boost::shared_ptr<Source>();
245                                 }
246
247                                 ret->check_for_analysis_data_on_disk ();
248                                 if (announce) {
249                                         SourceCreated (ret);
250                                 }
251                                 return ret;
252                         }
253
254                         catch (failed_constructor& err) {
255 #ifdef USE_COREAUDIO_FOR_FILES
256
257                                 Source* src = new CoreAudioSource (s, path, chn, flags);
258 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
259                                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
260 #endif
261                                 boost::shared_ptr<Source> ret (src);
262                                 if (setup_peakfile (ret, defer_peaks)) {
263                                         return boost::shared_ptr<Source>();
264                                 }
265                                 ret->check_for_analysis_data_on_disk ();
266                                 if (announce) {
267                                         SourceCreated (ret);
268                                 }
269                                 return ret;
270
271 #else
272                                 throw; // rethrow
273 #endif
274                         }
275
276                 } else {
277                         // eh?
278                 }
279
280         } else if (type == DataType::MIDI) {
281
282                 SMFSource* src = new SMFSource (s, path, SMFSource::Flag(0));
283                 src->load_model (true, true);
284 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
285                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
286 #endif
287                 boost::shared_ptr<Source> ret (src);
288
289                 if (announce) {
290                         SourceCreated (ret);
291                 }
292
293                 return ret;
294
295         }
296
297         return boost::shared_ptr<Source>();
298 }
299
300 boost::shared_ptr<Source>
301 SourceFactory::createWritable (DataType type, Session& s, const std::string& path, const std::string& origin,
302                                bool destructive, framecnt_t rate, bool announce, bool defer_peaks)
303 {
304         /* this might throw failed_constructor(), which is OK */
305
306         if (type == DataType::AUDIO) {
307                 Source* src = new SndFileSource (s, path, origin,
308                                 s.config.get_native_file_data_format(),
309                                 s.config.get_native_file_header_format(),
310                                 rate,
311                                 (destructive
312                                         ? Source::Flag (SndFileSource::default_writable_flags | Source::Destructive)
313                                  : SndFileSource::default_writable_flags));
314 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
315                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
316 #endif
317                 boost::shared_ptr<Source> ret (src);
318
319                 if (setup_peakfile (ret, defer_peaks)) {
320                         return boost::shared_ptr<Source>();
321                 }
322
323                 // no analysis data - this is a new file
324
325                 if (announce) {
326                         SourceCreated (ret);
327                 }
328                 return ret;
329
330         } else if (type == DataType::MIDI) {
331                 // XXX writable flags should belong to MidiSource too
332                 boost::shared_ptr<SMFSource> src (new SMFSource (s, path, SndFileSource::default_writable_flags));
333                 assert (src->writable ());
334
335                 src->load_model (true, true);
336 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
337                 // boost_debug_shared_ptr_mark_interesting (src, "Source");
338 #endif
339
340                 // no analysis data - this is a new file
341
342                 if (announce) {
343                         SourceCreated (src);
344                 }
345                 return src;
346
347         }
348
349         return boost::shared_ptr<Source> ();
350 }
351
352 boost::shared_ptr<Source>
353 SourceFactory::createFromPlaylist (DataType type, Session& s, boost::shared_ptr<Playlist> p, const ID& orig, const std::string& name,
354                                    uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks)
355 {
356         if (type == DataType::AUDIO) {
357                 try {
358
359                         boost::shared_ptr<AudioPlaylist> ap = boost::dynamic_pointer_cast<AudioPlaylist>(p);
360
361                         if (ap) {
362
363                                 if (copy) {
364                                         ap.reset (new AudioPlaylist (ap, start, len, name, true));
365                                         start = 0;
366                                 }
367
368                                 Source* src = new AudioPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
369                                 boost::shared_ptr<Source> ret (src);
370
371                                 if (setup_peakfile (ret, defer_peaks)) {
372                                         return boost::shared_ptr<Source>();
373                                 }
374
375                                 ret->check_for_analysis_data_on_disk ();
376                                 SourceCreated (ret);
377                                 return ret;
378                         }
379                 }
380
381                 catch (failed_constructor& err) {
382                         /* relax - return at function scope */
383                 }
384
385         } else if (type == DataType::MIDI) {
386
387                 try {
388
389                         boost::shared_ptr<MidiPlaylist> ap = boost::dynamic_pointer_cast<MidiPlaylist>(p);
390
391                         if (ap) {
392
393                                 if (copy) {
394                                         ap.reset (new MidiPlaylist (ap, start, len, name, true));
395                                         start = 0;
396                                 }
397
398                                 Source* src = new MidiPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
399                                 boost::shared_ptr<Source> ret (src);
400
401                                 SourceCreated (ret);
402                                 return ret;
403                         }
404                 }
405
406                 catch (failed_constructor& err) {
407                         /* relax - return at function scope */
408                 }
409
410         }
411
412         return boost::shared_ptr<Source>();
413 }
414