ardour
source_factory.cc
Go to the documentation of this file.
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"
33 #include "ardour/midi_playlist.h"
35 #include "ardour/source_factory.h"
36 #include "ardour/sndfilesource.h"
38 #include "ardour/smf_source.h"
39 #include "ardour/session.h"
40 
41 #ifdef HAVE_COREAUDIO
42 #include "ardour/coreaudiosource.h"
43 #endif
44 
45 
46 #include "i18n.h"
47 
48 using namespace ARDOUR;
49 using namespace std;
50 using namespace PBD;
51 
52 PBD::Signal1<void,boost::shared_ptr<Source> > SourceFactory::SourceCreated;
53 Glib::Threads::Cond SourceFactory::PeaksToBuild;
54 Glib::Threads::Mutex SourceFactory::peak_building_lock;
55 std::list<boost::weak_ptr<AudioSource> > SourceFactory::files_with_peaks;
56 
57 static void
59 {
60  SessionEvent::create_per_thread_pool (X_("PeakFile Builder "), 64);
61 
62  while (true) {
63 
65 
66  wait:
67  if (SourceFactory::files_with_peaks.empty()) {
69  }
70 
71  if (SourceFactory::files_with_peaks.empty()) {
72  goto wait;
73  }
74 
78 
79  if (!as) {
80  continue;
81  }
82 
83  as->setup_peakfile ();
84  }
85 }
86 
87 void
89 {
90  for (int n = 0; n < 2; ++n) {
91  Glib::Threads::Thread::create (sigc::ptr_fun (::peak_thread_work));
92  }
93 }
94 
95 int
97 {
98  boost::shared_ptr<AudioSource> as (boost::dynamic_pointer_cast<AudioSource> (s));
99 
100  if (as) {
101 
102  if (async) {
103 
104  Glib::Threads::Mutex::Lock lm (peak_building_lock);
105  files_with_peaks.push_back (boost::weak_ptr<AudioSource> (as));
106  PeaksToBuild.broadcast ();
107 
108  } else {
109 
110  if (as->setup_peakfile ()) {
111  error << string_compose("SourceFactory: could not set up peakfile for %1", as->name()) << endmsg;
112  return -1;
113  }
114  }
115  }
116 
117  return 0;
118 }
119 
121 SourceFactory::createSilent (Session& s, const XMLNode& node, framecnt_t nframes, float sr)
122 {
123  Source* src = new SilentFileSource (s, node, nframes, sr);
124 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
125  // boost_debug_shared_ptr_mark_interesting (src, "Source");
126 #endif
127  boost::shared_ptr<Source> ret (src);
128  // no analysis data - the file is non-existent
129  SourceCreated (ret);
130  return ret;
131 }
132 
134 SourceFactory::create (Session& s, const XMLNode& node, bool defer_peaks)
135 {
136  DataType type = DataType::AUDIO;
137  const XMLProperty* prop = node.property("type");
138 
139  if (prop) {
140  type = DataType (prop->value());
141  }
142 
143  if (type == DataType::AUDIO) {
144 
145  /* it could be nested */
146 
147  if (node.property ("playlist") != 0) {
148 
149  try {
151 
152  if (setup_peakfile (ap, true)) {
153  return boost::shared_ptr<Source>();
154  }
155 
157 
158  SourceCreated (ap);
159  return ap;
160 
161  } catch (failed_constructor&) {
162  /* oh well, so much for that then ... */
163  }
164 
165  } else {
166 
167 
168  try {
169  Source* src = new SndFileSource (s, node);
170 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
171  // boost_debug_shared_ptr_mark_interesting (src, "Source");
172 #endif
173  boost::shared_ptr<Source> ret (src);
174  if (setup_peakfile (ret, defer_peaks)) {
175  return boost::shared_ptr<Source>();
176  }
178  SourceCreated (ret);
179  return ret;
180  }
181 
182  catch (failed_constructor& err) {
183 
184 #ifdef HAVE_COREAUDIO
185 
186  /* this is allowed to throw */
187 
188  Source *src = new CoreAudioSource (s, node);
189 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
190  // boost_debug_shared_ptr_mark_interesting (src, "Source");
191 #endif
192  boost::shared_ptr<Source> ret (src);
193 
194  if (setup_peakfile (ret, defer_peaks)) {
195  return boost::shared_ptr<Source>();
196  }
197 
199  SourceCreated (ret);
200  return ret;
201 #else
202  throw; // rethrow
203 #endif
204  }
205  }
206  } else if (type == DataType::MIDI) {
207  boost::shared_ptr<SMFSource> src (new SMFSource (s, node));
208  Source::Lock lock(src->mutex());
209  src->load_model (lock, true);
210 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
211  // boost_debug_shared_ptr_mark_interesting (src, "Source");
212 #endif
214  SourceCreated (src);
215  return src;
216  }
217 
218  return boost::shared_ptr<Source>();
219 }
220 
222 SourceFactory::createExternal (DataType type, Session& s, const string& path,
223  int chn, Source::Flag flags, bool announce, bool defer_peaks)
224 {
225  if (type == DataType::AUDIO) {
226 
227  if (!(flags & Destructive)) {
228 
229  try {
230 
231  Source* src = new SndFileSource (s, path, chn, flags);
232 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
233  // boost_debug_shared_ptr_mark_interesting (src, "Source");
234 #endif
235  boost::shared_ptr<Source> ret (src);
236 
237  if (setup_peakfile (ret, defer_peaks)) {
238  return boost::shared_ptr<Source>();
239  }
240 
242  if (announce) {
243  SourceCreated (ret);
244  }
245  return ret;
246  }
247 
248  catch (failed_constructor& err) {
249 #ifdef HAVE_COREAUDIO
250 
251  Source* src = new CoreAudioSource (s, path, chn, flags);
252 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
253  // boost_debug_shared_ptr_mark_interesting (src, "Source");
254 #endif
255  boost::shared_ptr<Source> ret (src);
256  if (setup_peakfile (ret, defer_peaks)) {
257  return boost::shared_ptr<Source>();
258  }
260  if (announce) {
261  SourceCreated (ret);
262  }
263  return ret;
264 
265 #else
266  throw; // rethrow
267 #endif
268  }
269 
270  } else {
271  // eh?
272  }
273 
274  } else if (type == DataType::MIDI) {
275 
276  boost::shared_ptr<SMFSource> src (new SMFSource (s, path));
277  Source::Lock lock(src->mutex());
278  src->load_model (lock, true);
279 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
280  // boost_debug_shared_ptr_mark_interesting (src, "Source");
281 #endif
282 
283  if (announce) {
284  SourceCreated (src);
285  }
286 
287  return src;
288 
289  }
290 
291  return boost::shared_ptr<Source>();
292 }
293 
295 SourceFactory::createWritable (DataType type, Session& s, const std::string& path,
296  bool destructive, framecnt_t rate, bool announce, bool defer_peaks)
297 {
298  /* this might throw failed_constructor(), which is OK */
299 
300  if (type == DataType::AUDIO) {
301  Source* src = new SndFileSource (s, path, string(),
302  s.config.get_native_file_data_format(),
303  s.config.get_native_file_header_format(),
304  rate,
305  (destructive
308 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
309  // boost_debug_shared_ptr_mark_interesting (src, "Source");
310 #endif
311  boost::shared_ptr<Source> ret (src);
312 
313  if (setup_peakfile (ret, defer_peaks)) {
314  return boost::shared_ptr<Source>();
315  }
316 
317  // no analysis data - this is a new file
318 
319  if (announce) {
320  SourceCreated (ret);
321  }
322  return ret;
323 
324  } else if (type == DataType::MIDI) {
325  // XXX writable flags should belong to MidiSource too
327  assert (src->writable ());
328 
329  Source::Lock lock(src->mutex());
330  src->load_model (lock, true);
331 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
332  // boost_debug_shared_ptr_mark_interesting (src, "Source");
333 #endif
334 
335  // no analysis data - this is a new file
336 
337  if (announce) {
338  SourceCreated (src);
339  }
340  return src;
341 
342  }
343 
344  return boost::shared_ptr<Source> ();
345 }
346 
348 SourceFactory::createForRecovery (DataType type, Session& s, const std::string& path, int chn)
349 {
350  /* this might throw failed_constructor(), which is OK */
351 
352  if (type == DataType::AUDIO) {
353  Source* src = new SndFileSource (s, path, chn);
354 
355 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
356  // boost_debug_shared_ptr_mark_interesting (src, "Source");
357 #endif
358  boost::shared_ptr<Source> ret (src);
359 
360  if (setup_peakfile (ret, false)) {
361  return boost::shared_ptr<Source>();
362  }
363 
364  // no analysis data - this is still basically a new file (we
365  // crashed while recording.
366 
367  // always announce these files
368 
369  SourceCreated (ret);
370 
371  return ret;
372 
373  } else if (type == DataType::MIDI) {
374  error << _("Recovery attempted on a MIDI file - not implemented") << endmsg;
375  }
376 
377  return boost::shared_ptr<Source> ();
378 }
379 
382  uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks)
383 {
384  if (type == DataType::AUDIO) {
385  try {
386 
388 
389  if (ap) {
390 
391  if (copy) {
392  ap.reset (new AudioPlaylist (ap, start, len, name, true));
393  start = 0;
394  }
395 
396  Source* src = new AudioPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
397  boost::shared_ptr<Source> ret (src);
398 
399  if (setup_peakfile (ret, defer_peaks)) {
400  return boost::shared_ptr<Source>();
401  }
402 
404  SourceCreated (ret);
405  return ret;
406  }
407  }
408 
409  catch (failed_constructor& err) {
410  /* relax - return at function scope */
411  }
412 
413  } else if (type == DataType::MIDI) {
414 
415  try {
416 
418 
419  if (ap) {
420 
421  if (copy) {
422  ap.reset (new MidiPlaylist (ap, start, len, name, true));
423  start = 0;
424  }
425 
426  Source* src = new MidiPlaylistSource (s, orig, name, ap, chn, start, len, Source::Flag (0));
427  boost::shared_ptr<Source> ret (src);
428 
429  SourceCreated (ret);
430  return ret;
431  }
432  }
433 
434  catch (failed_constructor& err) {
435  /* relax - return at function scope */
436  }
437 
438  }
439 
440  return boost::shared_ptr<Source>();
441 }
442 
static Glib::Threads::Mutex peak_building_lock
virtual int setup_peakfile()
Definition: audiosource.h:98
const std::string & value() const
Definition: xml++.h:159
Glib::Threads::Mutex::Lock Lock
Definition: source.h:54
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
Definition: shared_ptr.hpp:396
static void create_per_thread_pool(const std::string &n, uint32_t nitems)
Definition: Beats.hpp:239
LIBPBD_API Transmitter error
std::ostream & endmsg(std::ostream &ostr)
Definition: transmitter.h:71
static boost::shared_ptr< Source > createExternal(DataType type, Session &, const std::string &path, int chn, Source::Flag flags, bool announce=true, bool async=false)
SessionConfiguration config
Definition: session.h:866
LIBARDOUR_API PBD::PropertyDescriptor< framepos_t > start
Definition: region.cc:63
static boost::shared_ptr< Source > createFromPlaylist(DataType type, Session &s, boost::shared_ptr< Playlist > p, const PBD::ID &orig, const std::string &name, uint32_t chn, frameoffset_t start, framecnt_t len, bool copy, bool defer_peaks)
Definition: id.h:32
static boost::shared_ptr< Source > createSilent(Session &, const XMLNode &node, framecnt_t nframes, float sample_rate)
static std::list< boost::weak_ptr< AudioSource > > files_with_peaks
#define _(Text)
Definition: i18n.h:11
#define X_(Text)
Definition: i18n.h:13
int64_t framecnt_t
Definition: types.h:76
XMLProperty * property(const char *)
Definition: xml++.cc:413
static const Source::Flag default_writable_flags
Definition: sndfilesource.h:73
Definition: amp.h:29
static void peak_thread_work()
static boost::shared_ptr< Source > create(Session &, const XMLNode &node, bool async=false)
int64_t frameoffset_t
Definition: types.h:71
Glib::Threads::Mutex & mutex()
Definition: source.h:105
const char * name
void load_model(const Glib::Threads::Mutex::Lock &lock, bool force_reload=false)
Definition: smf_source.cc:606
Definition: xml++.h:95
std::string name() const
virtual bool check_for_analysis_data_on_disk()
Definition: source.cc:229
static PBD::Signal1< void, boost::shared_ptr< Source > > SourceCreated
static Glib::Threads::Cond PeaksToBuild
Definition: debug.h:30
static boost::shared_ptr< Source > createForRecovery(DataType type, Session &, const std::string &path, int chn)
bool writable() const
Definition: source.cc:305
static int setup_peakfile(boost::shared_ptr< Source >, bool async)
static boost::shared_ptr< Source > createWritable(DataType type, Session &, const std::string &path, bool destructive, framecnt_t rate, bool announce=true, bool async=false)
std::string string_compose(const std::string &fmt, const T1 &o1)
Definition: compose.h:208