fixes for 98% of all the warnings/errors reported by OS X gcc on tiger
[ardour.git] / libs / ardour / audio_playlist_source.cc
1 /*
2     Copyright (C) 2011 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 #ifdef WAF_BUILD
20 #include "libardour-config.h"
21 #endif
22
23 #include <vector>
24 #include <cstdio>
25
26 #include <glibmm/fileutils.h>
27 #include <glibmm/miscutils.h>
28
29 #include "pbd/error.h"
30 #include "pbd/convert.h"
31 #include "pbd/enumwriter.h"
32
33 #include "ardour/audioplaylist.h"
34 #include "ardour/audio_playlist_source.h"
35 #include "ardour/audioregion.h"
36 #include "ardour/debug.h"
37 #include "ardour/filename_extensions.h"
38 #include "ardour/session.h"
39 #include "ardour/session_directory.h"
40 #include "ardour/session_playlists.h"
41 #include "ardour/source_factory.h"
42
43 #include "i18n.h"
44
45 using namespace std;
46 using namespace ARDOUR;
47 using namespace PBD;
48
49 AudioPlaylistSource::AudioPlaylistSource (Session& s, const ID& orig, const std::string& name, boost::shared_ptr<AudioPlaylist> p,
50                                           uint32_t chn, frameoffset_t begin, framecnt_t len, Source::Flag flags)
51         : Source (s, DataType::AUDIO, name)
52         , PlaylistSource (s, orig, name, p, DataType::AUDIO, begin, len, flags)
53         , AudioSource (s, name)
54         , _playlist_channel (chn)
55 {
56         AudioSource::_length = len;
57         ensure_buffers_for_level (_level, _session.frame_rate());
58 }
59
60 AudioPlaylistSource::AudioPlaylistSource (Session& s, const XMLNode& node)
61         : Source (s, node)
62         , PlaylistSource (s, node)
63         , AudioSource (s, node)
64 {
65         /* PlaylistSources are never writable, renameable, removable or destructive */
66         _flags = Flag (_flags & ~(Writable|CanRename|Removable|RemovableIfEmpty|RemoveAtDestroy|Destructive));
67
68         /* ancestors have already called ::set_state() in their XML-based
69            constructors.
70         */
71
72         if (set_state (node, Stateful::loading_state_version, false)) {
73                 throw failed_constructor ();
74         }
75
76         AudioSource::_length = _playlist_length;
77 }
78
79 AudioPlaylistSource::~AudioPlaylistSource ()
80 {
81 }
82
83 XMLNode&
84 AudioPlaylistSource::get_state ()
85 {
86         XMLNode& node (AudioSource::get_state ());
87         char buf[64];
88
89         /* merge PlaylistSource state */
90
91         PlaylistSource::add_state (node);
92
93         snprintf (buf, sizeof (buf), "%" PRIu32, _playlist_channel);
94         node.add_property ("channel", buf);
95
96         return node;
97 }
98
99 int
100 AudioPlaylistSource::set_state (const XMLNode& node, int version)
101 {
102         return set_state (node, version, true);
103 }
104
105 int
106 AudioPlaylistSource::set_state (const XMLNode& node, int version, bool with_descendants)
107 {
108         if (with_descendants) {
109                 if (Source::set_state (node, version) ||
110                     PlaylistSource::set_state (node, version) ||
111                     AudioSource::set_state (node, version)) {
112                         return -1;
113                 }
114         }
115
116         const XMLProperty* prop;
117         pair<framepos_t,framepos_t> extent = _playlist->get_extent();
118
119         AudioSource::_length = extent.second - extent.first;
120
121         if ((prop = node.property (X_("channel"))) == 0) {
122                 throw failed_constructor ();
123         }
124
125         sscanf (prop->value().c_str(), "%" PRIu32, &_playlist_channel);
126
127         ensure_buffers_for_level (_level, _session.frame_rate());
128
129         return 0;
130 }
131
132 framecnt_t
133 AudioPlaylistSource::read_unlocked (Sample* dst, framepos_t start, framecnt_t cnt) const
134 {
135         boost::shared_ptr<Sample> sbuf;
136         boost::shared_ptr<gain_t> gbuf;
137         framecnt_t to_read;
138         framecnt_t to_zero;
139
140         /* we must be careful not to read beyond the end of our "section" of
141          * the playlist, because otherwise we may read data that exists, but
142          * is not supposed be part of our data.
143          */
144
145         if (cnt > _playlist_length - start) {
146                 to_read = _playlist_length - start;
147                 to_zero = cnt - to_read;
148         } else {
149                 to_read = cnt;
150                 to_zero = 0;
151         }
152
153         {
154                 /* Don't need to hold the lock for the actual read, and
155                    actually, we cannot, but we do want to interlock
156                    with any changes to the list of buffers caused
157                    by creating new nested playlists/sources
158                 */
159                 Glib::Mutex::Lock lm (_level_buffer_lock);
160                 sbuf = _mixdown_buffers[_level-1];
161                 gbuf = _gain_buffers[_level-1];
162         }
163
164         boost::dynamic_pointer_cast<AudioPlaylist>(_playlist)->read (dst, sbuf.get(), gbuf.get(), start+_playlist_offset, to_read, _playlist_channel);
165
166         if (to_zero) {
167                 memset (dst+to_read, 0, sizeof (Sample) * to_zero);
168         }
169
170         return cnt;
171 }
172
173 framecnt_t
174 AudioPlaylistSource::write_unlocked (Sample *, framecnt_t)
175 {
176         fatal << string_compose (_("programming error: %1"), "AudioPlaylistSource::write() called - should be impossible") << endmsg;
177         /*NOTREACHED*/
178         return 0;
179 }
180
181 bool
182 AudioPlaylistSource::empty () const
183 {
184         return !_playlist || _playlist->empty();
185 }
186
187 uint32_t
188 AudioPlaylistSource::n_channels () const
189 {
190         /* use just the first region to decide */
191
192         if (empty()) {
193                 return 1;
194         }
195
196         boost::shared_ptr<Region> r = _playlist->region_list().front ();
197         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
198
199         return ar->audio_source()->n_channels ();
200 }
201
202 float
203 AudioPlaylistSource::sample_rate () const
204 {
205         /* use just the first region to decide */
206
207         if (empty()) {
208                 _session.frame_rate ();
209         }
210
211         boost::shared_ptr<Region> r = _playlist->region_list().front ();
212         boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (r);
213
214         return ar->audio_source()->sample_rate ();
215 }
216
217 int
218 AudioPlaylistSource::setup_peakfile ()
219 {
220         _peak_path = Glib::build_filename (_session.session_directory().peak_path().to_string(), name() + ARDOUR::peakfile_suffix);
221         return initialize_peakfile (false, string());
222 }
223
224 string
225 AudioPlaylistSource::peak_path (string /*audio_path_IGNORED*/)
226 {
227         return _peak_path;
228 }
229
230