interpolation: fix some warnings
[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 #include "pbd/error.h"
22 #include "pbd/convert.h"
23 #include "pbd/pthread_utils.h"
24 #include "pbd/stacktrace.h"
25
26 #include "ardour/source_factory.h"
27 #include "ardour/sndfilesource.h"
28 #include "ardour/silentfilesource.h"
29 #include "ardour/rc_configuration.h"
30 #include "ardour/smf_source.h"
31 #include "ardour/session.h"
32
33 #ifdef  HAVE_COREAUDIO
34 #define USE_COREAUDIO_FOR_FILES
35 #endif
36
37 #ifdef USE_COREAUDIO_FOR_FILES
38 #include "ardour/coreaudiosource.h"
39 #endif
40
41
42 #include "i18n.h"
43
44 using namespace ARDOUR;
45 using namespace std;
46 using namespace PBD;
47
48 sigc::signal<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
49 Glib::Cond* SourceFactory::PeaksToBuild;
50 Glib::StaticMutex SourceFactory::peak_building_lock = GLIBMM_STATIC_MUTEX_INIT;
51 std::list<boost::weak_ptr<AudioSource> > SourceFactory::files_with_peaks;
52
53 static void 
54 peak_thread_work ()
55 {
56         PBD::notify_gui_about_thread_creation (pthread_self(), string ("peakbuilder-") + to_string (pthread_self(), std::dec));
57
58         while (true) {
59
60                 SourceFactory::peak_building_lock.lock ();
61                 
62           wait:
63                 if (SourceFactory::files_with_peaks.empty()) {
64                         SourceFactory::PeaksToBuild->wait (SourceFactory::peak_building_lock);
65                 }
66
67                 if (SourceFactory::files_with_peaks.empty()) {
68                         goto wait;
69                 }
70
71                 boost::shared_ptr<AudioSource> as (SourceFactory::files_with_peaks.front().lock());
72                 SourceFactory::files_with_peaks.pop_front ();
73                 SourceFactory::peak_building_lock.unlock ();
74                 
75                 if (!as) {
76                         continue;
77                 }
78
79                 as->setup_peakfile ();
80         }
81 }
82
83 void
84 SourceFactory::init ()
85 {
86         PeaksToBuild = new Glib::Cond();
87
88         for (int n = 0; n < 2; ++n) {
89                 Glib::Thread::create (sigc::ptr_fun (::peak_thread_work), false);
90         }
91 }
92
93 int
94 SourceFactory::setup_peakfile (boost::shared_ptr<Source> s, bool async)
95 {
96         boost::shared_ptr<AudioSource> as (boost::dynamic_pointer_cast<AudioSource> (s));
97
98         if (as) {
99
100                 if (async) {
101
102                         Glib::Mutex::Lock lm (peak_building_lock);
103                         files_with_peaks.push_back (boost::weak_ptr<AudioSource> (as));
104                         PeaksToBuild->broadcast ();
105
106                 } else {
107
108                         if (as->setup_peakfile ()) {
109                                 error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg;
110                                 return -1;
111                         }
112                 }
113         }
114
115         return 0;
116 }
117
118 boost::shared_ptr<Source>
119 SourceFactory::createSilent (Session& s, const XMLNode& node, nframes_t nframes, float sr)
120 {
121         boost::shared_ptr<Source> ret (new SilentFileSource (s, node, nframes, sr));
122         // no analysis data - the file is non-existent
123         SourceCreated (ret);
124         return ret;
125 }
126
127 boost::shared_ptr<Source>
128 SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
129 {
130         DataType type = DataType::AUDIO;
131         const XMLProperty* prop = node.property("type");
132
133         if (!prop) {
134                 return boost::shared_ptr<Source>();
135         }
136
137         type = DataType (prop->value());
138
139         if (type == DataType::AUDIO) {
140
141                 try {
142                         
143                         boost::shared_ptr<Source> ret (new SndFileSource (s, node));
144                         if (setup_peakfile (ret, defer_peaks)) {
145                                 return boost::shared_ptr<Source>();
146                         }
147                         ret->check_for_analysis_data_on_disk ();
148                         SourceCreated (ret);
149                         return ret;
150                 } 
151                 
152                 catch (failed_constructor& err) {
153
154 #ifdef USE_COREAUDIO_FOR_FILES
155                 
156                         /* this is allowed to throw */
157                         
158                         boost::shared_ptr<Source> ret (new CoreAudioSource (s, node));
159                         
160                         if (setup_peakfile (ret, defer_peaks)) {
161                                 return boost::shared_ptr<Source>();
162                         }
163                         
164                         ret->check_for_analysis_data_on_disk ();
165                         SourceCreated (ret);
166                         return ret;
167 #else
168                         throw; // rethrow 
169 #endif
170                 }
171
172         } else if (type == DataType::MIDI) {
173                 boost::shared_ptr<Source> ret (new SMFSource (s, node));
174                 ret->check_for_analysis_data_on_disk ();
175                 SourceCreated (ret);
176                 return ret;
177         }
178
179         return boost::shared_ptr<Source>();
180 }
181
182 boost::shared_ptr<Source>
183 SourceFactory::createReadable (DataType type, Session& s, const string& path, bool embedded,
184                 int chn, Source::Flag flags, bool announce, bool defer_peaks)
185 {
186         if (type == DataType::AUDIO) {
187
188                 if (!(flags & Destructive)) {
189                         
190                         try {
191                                 
192                                 boost::shared_ptr<Source> ret (new SndFileSource (s, path, embedded, chn, flags));
193                                 
194                                 if (setup_peakfile (ret, defer_peaks)) {
195                                         return boost::shared_ptr<Source>();
196                                 }
197                                 
198                                 ret->check_for_analysis_data_on_disk ();
199                                 if (announce) {
200                                         SourceCreated (ret);
201                                 }
202                                 return ret;
203                         }
204                         
205                         catch (failed_constructor& err) {
206 #ifdef USE_COREAUDIO_FOR_FILES
207                                 
208                                 boost::shared_ptr<Source> ret (new CoreAudioSource (s, path, embedded, chn, flags));
209                                 if (setup_peakfile (ret, defer_peaks)) {
210                                         return boost::shared_ptr<Source>();
211                                 }
212                                 ret->check_for_analysis_data_on_disk ();
213                                 if (announce) {
214                                         SourceCreated (ret);
215                                 }
216                                 return ret;
217                                 
218 #else
219                                 throw; // rethrow
220 #endif
221                         }
222
223                 } else {
224                         // eh?
225                 }
226         
227         } else if (type == DataType::MIDI) {
228                 
229                 boost::shared_ptr<Source> ret (new SMFSource (s, path, embedded, SMFSource::Flag(0)));
230                 
231                 if (announce) {
232                         SourceCreated (ret);
233                 }
234
235                 return ret;
236
237         }
238
239         return boost::shared_ptr<Source>();
240 }
241
242 boost::shared_ptr<Source>
243 SourceFactory::createWritable (DataType type, Session& s, const std::string& path, bool embedded,
244                 bool destructive, nframes_t rate, bool announce, bool defer_peaks)
245 {
246         /* this might throw failed_constructor(), which is OK */
247         
248         if (type == DataType::AUDIO) {
249                 boost::shared_ptr<Source> ret (new SndFileSource (s, path, embedded,
250                                 s.config.get_native_file_data_format(),
251                                 s.config.get_native_file_header_format(),
252                                 rate,
253                                 (destructive
254                                         ? Source::Flag (SndFileSource::default_writable_flags | Source::Destructive)
255                                         : SndFileSource::default_writable_flags)));     
256
257                 if (setup_peakfile (ret, defer_peaks)) {
258                         return boost::shared_ptr<Source>();
259                 }
260                 
261                 // no analysis data - this is a new file
262
263                 if (announce) {
264                         SourceCreated (ret);
265                 }
266                 return ret;
267
268         } else if (type == DataType::MIDI) {
269
270                 boost::shared_ptr<Source> ret (new SMFSource (s, path, embedded, Source::Flag(0)));
271         
272                 // no analysis data - this is a new file
273                 
274                 if (announce) {
275                         SourceCreated (ret);
276                 }
277                 return ret;
278
279         }
280
281         return boost::shared_ptr<Source> ();
282 }
283