2 Copyright (C) 2000-2006 Paul Davis
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.
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.
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.
22 #include "libardour-config.h"
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"
31 #include "ardour/source_factory.h"
32 #include "ardour/sndfilesource.h"
33 #include "ardour/silentfilesource.h"
34 #include "ardour/rc_configuration.h"
35 #include "ardour/smf_source.h"
36 #include "ardour/session.h"
39 #define USE_COREAUDIO_FOR_FILES
42 #ifdef USE_COREAUDIO_FOR_FILES
43 #include "ardour/coreaudiosource.h"
49 using namespace ARDOUR
;
53 PBD::Signal1
<void,boost::shared_ptr
<Source
> > SourceFactory::SourceCreated
;
54 Glib::Cond
* SourceFactory::PeaksToBuild
;
55 Glib::StaticMutex
SourceFactory::peak_building_lock
= GLIBMM_STATIC_MUTEX_INIT
;
56 std::list
<boost::weak_ptr
<AudioSource
> > SourceFactory::files_with_peaks
;
61 SessionEvent::create_per_thread_pool (X_("PeakFile Builder "), 64);
65 SourceFactory::peak_building_lock
.lock ();
68 if (SourceFactory::files_with_peaks
.empty()) {
69 SourceFactory::PeaksToBuild
->wait (SourceFactory::peak_building_lock
);
72 if (SourceFactory::files_with_peaks
.empty()) {
76 boost::shared_ptr
<AudioSource
> as (SourceFactory::files_with_peaks
.front().lock());
77 SourceFactory::files_with_peaks
.pop_front ();
78 SourceFactory::peak_building_lock
.unlock ();
84 as
->setup_peakfile ();
89 SourceFactory::init ()
91 PeaksToBuild
= new Glib::Cond();
93 for (int n
= 0; n
< 2; ++n
) {
94 Glib::Thread::create (sigc::ptr_fun (::peak_thread_work
), false);
99 SourceFactory::setup_peakfile (boost::shared_ptr
<Source
> s
, bool async
)
101 boost::shared_ptr
<AudioSource
> as (boost::dynamic_pointer_cast
<AudioSource
> (s
));
107 Glib::Mutex::Lock
lm (peak_building_lock
);
108 files_with_peaks
.push_back (boost::weak_ptr
<AudioSource
> (as
));
109 PeaksToBuild
->broadcast ();
113 if (as
->setup_peakfile ()) {
114 error
<< string_compose("SourceFactory: could not set up peakfile for %1", as
->name()) << endmsg
;
123 boost::shared_ptr
<Source
>
124 SourceFactory::createSilent (Session
& s
, const XMLNode
& node
, nframes_t nframes
, float sr
)
126 Source
* src
= new SilentFileSource (s
, node
, nframes
, sr
);
127 // boost_debug_shared_ptr_mark_interesting (src, "Source");
128 boost::shared_ptr
<Source
> ret (src
);
129 // no analysis data - the file is non-existent
134 boost::shared_ptr
<Source
>
135 SourceFactory::create (Session
& s
, const XMLNode
& node
, bool defer_peaks
)
137 DataType type
= DataType::AUDIO
;
138 const XMLProperty
* prop
= node
.property("type");
141 type
= DataType (prop
->value());
144 if (type
== DataType::AUDIO
) {
148 Source
* src
= new SndFileSource (s
, node
);
149 // boost_debug_shared_ptr_mark_interesting (src, "Source");
150 boost::shared_ptr
<Source
> ret (src
);
151 if (setup_peakfile (ret
, defer_peaks
)) {
152 return boost::shared_ptr
<Source
>();
154 ret
->check_for_analysis_data_on_disk ();
159 catch (failed_constructor
& err
) {
161 #ifdef USE_COREAUDIO_FOR_FILES
163 /* this is allowed to throw */
165 Source
*src
= new CoreAudioSource (s
, node
);
166 // boost_debug_shared_ptr_mark_interesting (src, "Source");
167 boost::shared_ptr
<Source
> ret (src
);
169 if (setup_peakfile (ret
, defer_peaks
)) {
170 return boost::shared_ptr
<Source
>();
173 ret
->check_for_analysis_data_on_disk ();
181 } else if (type
== DataType::MIDI
) {
182 Source
* src
= new SMFSource (s
, node
);
183 // boost_debug_shared_ptr_mark_interesting (src, "Source");
184 boost::shared_ptr
<Source
> ret (src
);
185 ret
->check_for_analysis_data_on_disk ();
190 return boost::shared_ptr
<Source
>();
193 boost::shared_ptr
<Source
>
194 SourceFactory::createReadable (DataType type
, Session
& s
, const string
& path
,
195 int chn
, Source::Flag flags
, bool announce
, bool defer_peaks
)
197 if (type
== DataType::AUDIO
) {
199 if (!(flags
& Destructive
)) {
203 Source
* src
= new SndFileSource (s
, path
, chn
, flags
);
204 // boost_debug_shared_ptr_mark_interesting (src, "Source");
205 boost::shared_ptr
<Source
> ret (src
);
207 if (setup_peakfile (ret
, defer_peaks
)) {
208 return boost::shared_ptr
<Source
>();
211 ret
->check_for_analysis_data_on_disk ();
218 catch (failed_constructor
& err
) {
219 #ifdef USE_COREAUDIO_FOR_FILES
221 Source
* src
= new CoreAudioSource (s
, path
, chn
, flags
);
222 // boost_debug_shared_ptr_mark_interesting (src, "Source");
223 boost::shared_ptr
<Source
> ret (src
);
224 if (setup_peakfile (ret
, defer_peaks
)) {
225 return boost::shared_ptr
<Source
>();
227 ret
->check_for_analysis_data_on_disk ();
242 } else if (type
== DataType::MIDI
) {
244 Source
* src
= new SMFSource (s
, path
, SMFSource::Flag(0));
245 // boost_debug_shared_ptr_mark_interesting (src, "Source");
246 boost::shared_ptr
<Source
> ret (src
);
256 return boost::shared_ptr
<Source
>();
259 boost::shared_ptr
<Source
>
260 SourceFactory::createWritable (DataType type
, Session
& s
, const std::string
& path
,
261 bool destructive
, nframes_t rate
, bool announce
, bool defer_peaks
)
263 /* this might throw failed_constructor(), which is OK */
265 if (type
== DataType::AUDIO
) {
266 Source
* src
= new SndFileSource (s
, path
,
267 s
.config
.get_native_file_data_format(),
268 s
.config
.get_native_file_header_format(),
271 ? Source::Flag (SndFileSource::default_writable_flags
| Source::Destructive
)
272 : SndFileSource::default_writable_flags
));
273 // boost_debug_shared_ptr_mark_interesting (src, "Source");
274 boost::shared_ptr
<Source
> ret (src
);
276 if (setup_peakfile (ret
, defer_peaks
)) {
277 return boost::shared_ptr
<Source
>();
280 // no analysis data - this is a new file
287 } else if (type
== DataType::MIDI
) {
288 // XXX writable flags should belong to MidiSource too
289 Source
* src
= new SMFSource (s
, path
, SndFileSource::default_writable_flags
);
290 // boost_debug_shared_ptr_mark_interesting (src, "Source");
291 boost::shared_ptr
<Source
> ret (src
);
293 // no analysis data - this is a new file
302 return boost::shared_ptr
<Source
> ();